5

I would like Vim to stop highlighting matches when entering Insert mode. And not to highlight them again until a new search is performed.

A first thought would be to add the following line to my .vimrc.

autocmd InsertEnter * nohlsearch

But from :help :nohlsearch we know that nohlsearch does not work in automatic commands.

One alternative would be this line, which clears the last search pattern. Having nothing to match, Vim will have nothing to highlight.

autocmd InsertEnter * let @/ = ""

This stops the highlighting as intended. Nonetheless, it has side effects: because the last search pattern is cleared, commands such as n or /<CR> will not behave as intended.

So my question is: how can one stop highlighting when entering Insert mode in an efficient way and with no major side effects or no side effects at all?

5 Answers 5

5

You can use feedkeys() to execute :nohlsearch. A small challenge is to avoid the recursion, as the :call temporarily leaves (and then re-enters) insert mode. I've used a simple boolean flag for that here:

let didit = 0
autocmd! InsertEnter * if ! didit | call feedkeys("\<C-\>\<C-o>:nohlsearch|let didit = 1\<CR>", 'n') | endif
autocmd! InsertLeave * let didit = 0
1
  • I just noticed this breaks Visual Block mode. Typing C-v I inserts :nohlsearch|let didit = 1 into the buffer, on the line above '<. Dec 2, 2016 at 0:25
5

You could remap i to run :nohlsearch first and then i:

nnoremap i :nohlsearch<CR>i

You'll probably want to remap more than just i. For all insert mode commands (from :help inserting):

for s:c in ['a', 'A', '<Insert>', 'i', 'I', 'gI', 'gi', 'o', 'O']
    exe 'nnoremap ' . s:c . ' :nohlsearch<CR>' . s:c
endfor

This won't cover :startinsert though, but that isn't used a lot so that's probably okay.

3

Here is how to do it:

autocmd InsertEnter * call EndHighlight()

map n :call RepeatLastSearch()<CR>

function EndHighlight()
    match
    let s:lastsearch = @/
    nohlsearch
    redraw
endfunction

function RepeatLastSearch()
    exe "match Search /".s:lastsearch."/"
    call search(s:lastsearch, "W")
endfunction

You will find that this solution removes search highlighting, even after leaving insert mode, and yet the n command still behaves as expected, with highlighting returning if it is executed again.

What this does is totally disable search highlighting, which is somewhat automated and can be difficult to work with. Match highlighting is far more customizable, and in this case, we've asked it to act just like search highlighting, except as it applies to insert mode.

Because hlsearch is turned off, /<CR> navigates to the next match, but it doesn't highlight anymore. I don't know of a way to piggyback an autocommand when executing /<CR> so that it calls RepeatLastSearch() and executes the match highlight instead. If there was a way to monitor the @/ register for changes, that would be one way to do it, but as far as I know, that isn't possible. Any direct mapping of / would of course screw up your normal search functionality, assuming Vim allows the mapping (I haven't tried it).

Also, I tried to think of a way to call RepeatLastSearch silently, but I don't know of one. That would make it a little nicer when using the mapping for n (the user doesn't have to see the plumbing command underneath the mapping show up on the screen).

1
  • I like your answer. I think you could add that swapping the nohlsearch and let @/ lines and removing redraw does not work because the let command re-highlights the pattern, which I did not expect. As you wrote n and /<CR> do not re-highlight with this solution. Only a new search does. Could you complete your answer with your suggested way to work around this? Nov 27, 2016 at 19:09
1

You can try:

autocmd InsertEnter * setlocal nohlsearch
autocmd InsertLeave * setlocal hlsearch lz
inoremap <silent><Esc> <Esc>:nohl<bar>set nolz<CR>
inoremap <silent><C-c> <C-c>:nohl<bar>set nolz<CR>

I added lazyredraw, because I did not like the short blink of the highlighted areas, when leaving the Insert mode.

Also you could be probably interested in incsearch.vim, especially in this part.

2
  • This re-highlights matches when exiting Insert mode. The desired behaviour is not to highlight again until a new search is performed. Nov 26, 2016 at 21:43
  • I corrected my answer. I hope this is a little bit more helpful than before. I am sorry I missed that the desired behaviour was not to highlight again until a new search.
    – ryuichiro
    Nov 28, 2016 at 7:40
0

I figured a solution that disables highlight search when you enter insert mode and only turns it on again the next time you press n.

autocmd InsertEnter * set nohlsearch                                            
autocmd InsertEnter * nnoremap <silent> n :nunmap n<cr>:set hlsearch<cr>n

Your Answer

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

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