4

Is is possible to search for a regexp in only the current line.

Here is an example line:

This is some text that I have written. Can you find this word?
                                                    ^

This line contains many t's. I would like to search forward for this so the cursor ends up at the caret (the ^ character).

The problem with using / is that if the pattern does not match in the line the cursor will jump to another part of the buffer. I do not want that behavior. I want the search to stop if there is no match in the line.

I can of course search forward using ft and press ; repeatedly but if I were to record macro that would make the macro inconsistent when executed at different locations.

The most obvious solution would be :./this but that did not work for me (it finds matches at other lines in the buffer). So it appears to me that Vim is lacking this feature.

Do you know of a way to do what I am describing?

4

You can do:

:call search('find', '', line('.'))

... where 'find'is the pattern. The cursor will be moved to the start of the match.

Sample interactive mapping (not perfect):

:nnoremap <leader>/ :call search(input("Pattern: "), '', line('.'))<cr>

Also: with several plugins that enhance Vim grammar (operator-search, textobj-line (*)), you can do:

:map g/ <Plug>(operator-search)

and then:

g/il

... i.e. "go search for pattern (g/) in this line (il)". But also:

g/is

(search in this sentence).

Or, visually select a range, move cursor to the end, hit g/ to search inside the visual selection. Press n for next match, etc.

(*) Note that these plugins depend on their generic counterparts, Kana's textobj-user and operator-user.

3

You can use \%l to mach a specific line, but that means you would have to constantly change your pattern. e.g. /\%42lfoo. With a quick mapping you can start your search with the line number injected into your search:

nnoremap <key> /\%<c-r>=line('.')<cr>l

For more help see:

:h /\%l 
  • Your first example doesn't seem to match foo at the start of the line, or the word foobar, which is sort of what I would expect? In fact, it only seems to match the last occurrence of the match on the current line (rather than all matches on the current line)... I don't know of a better way to do this, though... – Martin Tournoij Aug 17 '15 at 11:46
  • It will match at the start of the line. The problem is multiple matches. That is where things go wrong, so very wrong. To be perfectly honest I think regex has too much going on. It would not be difficult to use the /\%l method if a simple mapping, e.g. nnoremap <key> /\%<c-r>=line('.')<cr>l – Peter Rincker Aug 17 '15 at 12:08
1

How about using :s/this//cI? Substitutes this on the current line by it's own occurrence (an empty replacement string just uses the match), case sensitive (that's the I). Using c for confirmation, so the cursor actually jumps to the match, you'd have to press q afterwards to stop the substitute-command. It has the additional advantage that if you have several matches on a line, you just press y until you are where you want to be.

0

Using the search() tip from VanLaser I created these functions:

" Repeat in the opposite direction if `reverse` is true
function! RepeatLineSearch(reverse)
    if a:reverse == s:search_backward
        call search(s:search_pattern, '', line('.'), '')
    else
        call search(s:search_pattern, 'b', line('.'), '')
    endif
endfunction

" Search backward if `backward` is true
function! LineSearch(pattern, backward)
    let s:search_pattern = a:pattern
    let s:search_backward = a:backward
    call RepeatLineSearch(0)
endfunction

I then put these mappings in my .vimrc:

" Search forward/backward for a pattern in current line
noremap <silent> <leader>f :call LineSearch(input('--> '), 0)<cr>
noremap <silent> <leader>F :call LineSearch(input('<-- '), 1)<cr>
noremap <silent> <leader>; :call RepeatLineSearch(0)<cr>
noremap <silent> <leader>, :call RepeatLineSearch(1)<cr>

This allows me to search for a new pattern using \f and \F and repeat the last pattern using \; and \, where \, repeats the pattern in the opposite direction.

Feel free to copy this code directly into your .vimrc or modify it to fit your needs.

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.