I'm trying to write a function that will highlight searches performed with the f and F keys.

I currently have a solution here thanks to @filbranden, but would like to further improve it to only activate highlighting upon using either the f or F keys, and disable it upon moving to a new line.

A solution using CursorMoved was proposed, but I'm pretty confused on how to use it and didn't see too much documentation at :h CursorMoved (though I'm probably just not looking at the right spot)

Seems pretty difficult to me, but I figured I'd ask anyway. Thanks for the help!

1 Answer 1


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

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 CursorMoved * call ClearHighlightOnMove()
  augroup END

  " ...

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!

  • 1
    Thanks for all the help! It works great and makes perfect sense. Yeah that's actually not bad at all haha. I didn't think about using a variable to hold that state of where the line cursor was and I didn't know you cuold delete the autocmd afterwards too. I've also moved everything into ~/.vim/plugin like you suggested. I've learned a lot from this endeavor so thanks again!
    – J-Win
    Aug 27, 2019 at 17:49
  • 1
    Really glad to help @J-Win! Answering questions here has helped me learn so much about Vim and I'm really happy about that too!
    – filbranden
    Aug 27, 2019 at 19:48

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.