Search code examples
vimvim-syntax-highlighting

VIM: How to turn off search highlight after timeout (X seconds)


I know about :nohl and use it all the time, I also use easy motion so the highlight is not in my way when just moving to the search location. It gets in my way after pressing n or N.

I am looking for a way to disable the search highlight after 3 seconds of pressing n or N, also for completeness sake I would like a way to also disable it after searching e.g. /search_word<CR>.

Finally, it has to be a non-blocking command.

Thanks, I am slowly getting into vimscript but this one is out of my league since I haven't seen many examples of commands with timeouts out there.

EDIT:

After some of the comments and online research there are lots of indications there isn't a good way to do this with vimscript.

I am looking for a way to do this in a stable way with any language, e.g. Perl, Python, Ruby.

EDIT 2:

This is my solution based on @dhruva-sagar's response: (I marked his answer as correct because he gave me the skeleton for it).

augroup NoHLSearch
  au!
  autocmd CursorHold,CursorMoved * call <SID>NoHLAfter(4)
augroup END

function! s:NoHLAfter(n)
  if !exists('g:nohl_starttime')
    let g:nohl_starttime = localtime()
  else
    if v:hlsearch && (localtime() - g:nohl_starttime) >= a:n
      :nohlsearch
      redraw
      unlet g:nohl_starttime
    endif
  endif
endfunction

Solution

  • If you check :h :nohl, you will see that the command :nohl does not work within an autocmd, the reason being that vim saves & restores the search & search highlighting state after executing an autocmd. Hence technically it is not feasable to do so. The best way is to create a mapping like nnoremap <C-l> :nohlsearch<CR> and use it when you want to temporarily disable the search highlighting.

    However there is a slight hack that i'd like to demonstrate that does work in a way like you expect by using set nohlsearch instead of nohlsearch, the downside of course is that it turns off search highlighting completely and you need to re-enable it using set hlsearch, so it isn't really a solution but it makes for a good example to demonstrate how one could perform time based operations within vim.

    NOTE: This is more for educational purposes to demonstrate how you could do time based non-blocking tasks in vim. The performance of these could vary depending on what you do within the event triggered function.

    augroup NoHLSearch
      au!
    
      autocmd CursorHold,CursorMoved * call <SID>NoHLAfter(3)
    augroup END
    
    function! s:NoHLAfter(n)
      if !exists('g:nohl_starttime')
        let g:nohl_starttime = localtime()
      else
        if v:hlsearch && (localtime() - g:nohl_starttime) >= a:n
          set nohlsearch
          unlet g:nohl_starttime
        endif
      endif
    endfunction