It's actually not that hard!
To use CursorMoved for this purpose, you write a function that will check if you're still in the same line. If you're not, you can clear highlighting using :match none
. At the same time, you can remove the autocmd
hook that has been calling you, so you don't get called again (until registered again.)
Here's an example of such a function:
function! ClearHighlightOnMove()
" First check if we moved to another line.
if line('.') !=# b:fsearch_line
" If we did, clear highlighting.
match none
" Remove the CursorMoved autocmd.
" We don't need it anymore.
au! fsearch_moved
endif
endfunction
This might look a bit magical, until you see how it's registered...
It depends on having a variable store the line you're highlighting, which we store in a buffer variable b:fsearch_line
.
It also clears an augroup
called fsearch_moved
, which presumably is the one for the autocmd
that triggers this function on CursorMoved.
So you need to set the buffer variable and register the autocmd
, which you should do in HighlightFSearches()
itself:
function! HighlightFSearches(cmd)
" ...
" Save the current line in a buffer variable.
let b:fsearch_line = line('.')
" Install a CursorMoved autocmd to track it.
" Use an augroup so we can easily clear it.
augroup fsearch_moved
au!
au CursorMoved * call ClearHighlightOnMove()
augroup END
" ...
endfunction
This way, the overhead of calling a function (ClearHighlightOnMove()
) on every motion only exists while you're highlighting the matches and will be cleared as soon as you move away from that line!
What's still missing from your implementation?
You should consider adding support for the t
and T
commands, which are pretty similar to f
and F
(in fact, only the :map
commands are missing to handle those.)
You might want to support ;
and ,
as well, which will repeat the last f
, F
, t
or T
command, but this might happen on a different line, so you need to highlight the previously searched character in that case, which you don't have at that time!
You could use another buffer variable to store that character, whenever your hook for the other functions run. Make sure you handle the corner case where ;
or ,
are called before the other functions were ever called (you can maybe check that with exists()
on the buffer variable.) If you translate ;
and ,
back to f
, F
, t
or T
commands, you might want to store those in yet another buffer variable, and switch capitalization in case of ,
which goes in the inverse direction.
Finally, you might want to move this from your .vimrc
to a plug-in, which simply means storing it in a file under ~/.vim/plugin/*.vim
(see :help add-plugin
for more details.) A file in that location will be automatically loaded when Vim starts.
One advantage of moving this from .vimrc
to a plug-in file is that you can use s:
to make your functions local to that file (see :help script-variable
and :help script-local
.)
Good luck!