0

Regarding this command:

f{char}                 To [count]'th occurrence of {char} to the right.  The
                        cursor is placed on {char} |inclusive|.
                        {char} can be entered as a digraph |digraph-arg|.
                        When 'encoding' is set to Unicode, composing
                        characters may be used, see |utf-8-char-arg|.
                        |:lmap| mappings apply to {char}.  The CTRL-^ command
                        in Insert mode can be used to switch this on/off
                        |i_CTRL-^|.

I would like to change its behaviour as such. Take this sample string, in which ^ indicates the cursor position:

fooBar(); // boat programming SO meme
^

The keystroke: fb would ordinarily jump to:

fooBar(); // boat programming SO meme
             ^

I would rather have it jump to:

fooBar(); // boat programming SO meme
   ^

Make sense? Ideally the solution should continue to work with ';'

2

2 Answers 2

2

A basic version of this is actually in the reference manual as an example of how to use the getchar() function:

This example redefines "f" to ignore case:

:nmap f :call FindChar()<CR>
:function FindChar()
:  let c = nr2char(getchar())
:  while col('.') < col('$') - 1
:    normal l
:    if getline('.')[col('.') - 1] ==? c
:      break
:    endif
:  endwhile
:endfunction

See :help getchar().

Note that this doesn't handle counts or other, related commands (t, F, T, ;, ,), although it could be adapted to do so.

1

Here is a one-liner solution built on top of getchar())

nnoremap <silent> f :silent! exe "normal! ". substitute(matchstr(getline('.')[col('.') :], '\v\c.{-}'.nr2char(getchar())), '.', "l", "g")<cr>

The idea is to extract all the characters from the current position till the character typed, and to convert them in as many <right> as necessary. Note that as this is a one liner mapping definition, I cannot use \<right> easily, hence the more obfuscated l.

Note: I don't use a loop as loops are slow and a PITA to debug.

In order to support a count, it could become:

nnoremap <silent> f :<c-u>silent! exe "normal! ". substitute(matchstr(getline('.')[col('.') :], '\v\c(.{-}'.nr2char(getchar()).'){'.v:count1.'}'), '.', "l", "g")<cr>

What changes here is the use of :<c-u> to clear the count, and the fact that I've surrounded the pattern .{-}Z (by Z I meant the result of nr2char(getchar())) with (...){v:count1} (lose syntax) to count exactly the number of whatever Z I want.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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