2

vim-help :h search() says it start search at column 0 of cursor position.

Search for regexp pattern {pattern}. The search starts at the cursor position (you can use |cursor()| to set it).
....

'b' search Backward instead of forward
'e' move to the End of the match
'z' start searching at the cursor column instead of zero

.... When the 'z' flag is not given, searching always starts in column zero and then matches before the cursor are skipped. When the 'c' flag is present in 'cpo' the next search starts after the match. Without the 'c' flag the next search starts one column further.

Thus, when below script being sourced,

func! GoParagraphStart(flags) range abort
    echo search('^',a:flags)
endfunc

nnoremap <silent> { :call GoParagraphStart('be')<CR>
nnoremap <silent> } :call GoParagraphStart('e')<CR>

I suppose, be the cursor at the first column or not, pressing { will always move cursor to previous line. But the result is

  • go previous line if cursor at first column
  • go first column of current line if not at first column.

Which make me puzzled.

Question: Is the behavior wrong, or I mis-interpreted the meaning of the help file?

version: vim 8.0 with patch 1-1216 on Cygwin64

== motivation & the true problem ==
previous function definition is for illustrative purpose, original one is

func! GoParagraphStart(flags) range abort
    if v:count < 2
        call search('\(\_^\s*\_$\n\_^.\)', a:flags)
    else
        let cnt = 0
        while cnt < v:count
            call search('\(\_^\s*\_$\n\_^.\)', a:flags) 
            let cnt += 1
        endwhile
    endif
endfunc

The behavior I needed is, when cursor at first line or a paragraph, pressing { will go previous paragraph's first line, no matter cursor at column zero or not. However, currently not working if cursor not at column zero.

== P.S. ==

Answer not answering the question, but instead do fix and achieve the intended behavior is well-appreciated too.

== Edit ==

As @statox stated, the behavior is indeed as documented, the departure is because, depends on found-pos == line('.'), col('.'), the result will be rejected if true, else accept. unless flag c is specified.

Thus, the fix is easy, add call cursor('.',1) or norm! 0 before do search.

(side notes. concerning norm! k$, it fixs backward search, but break forward search.)

2

Why does the search move the cursor to the previous line if you are on the first column?

If you are on the first a of the following line:

abcabc

Using call search('a') will move the cursor to the 4th letter of the line. It is because search() by default doesn't accept a match at the cursor position (you can use the flag c to change that). Thus it is the same when you search backward: the beginning of the line at the current position is not accepted by search. The behavior you are observing is the one which is documented.

How to solve that?

If you want to always go to the previous line you should be able to use norm! k$ before you use search() this way you will always be on the end of the previous line and you should get the behavior go first column of current line if not at first column. each time.

  • So, the reason is: the search is indeed always start at line('.') 1, but since the found position is also line('.') 1, thus depending col('.') eq 1` or not, the result will be rejected/accepted, unless overridden by flag 'c'? – qeatzy Dec 5 '17 at 12:08
  • And the fix is quite easy, just move cursor to column 1 before search, call cursor('.',1). (just verified that) or as suggested, use norm! k$. – qeatzy Dec 5 '17 at 12:10
  • @qeatzy I'm not sure I fully understand your first comment but I think you got it right: if you are on the first column, this first column itself is ignored. About the fix: yes moving to the first column with cursor() or norm! 0 should work just like norm! k$ – statox Dec 5 '17 at 12:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.