23

What I'd like is to map one key, e.g. F4, so that pressing F4 will toggle the visibility of search highlights, and so that starting a new search enables visibility no matter the current visibility.

What I've tried:

  1. Mapping F4 to :nohlsearch temporarily disables highlight visibility without turning the hlsearch setting off, but it does not toggle visibility back again.
  2. Mapping F4 to :set hlsearch! does toggle on/off, but I don't want to toggle the hlsearch setting off, just the visibility setting. If hlsearch is off then it doesn't come back automatically with a new search.

There doesn't seem to be an opposite form of :nohlsearch and the command itself has problems being called from a function.

I've found similiar questions, but they don't provide an answer.

Update:
The first comment provides exactly what I was asking for, reproduced below:

let hlstate=0
nnoremap <F4> :if (hlstate == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=1-hlstate<cr>

(N.B. for anyone using this --- cramming the map onto one line instead of using a function is necessary since you can't effect a change on highlighting from inside a function.)

Related question for slightly different functionality: https://stackoverflow.com/a/16750393/1176650

5
  • 1
    Here's the answer: Line 1: " ctrl+c to toggle highlight., Line 2: let hlstate=0. Line 3: nnoremap <c-c> :if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1<cr>. Now just press ctrl+c to toggle highlight.
    – trusktr
    Commented Apr 12, 2013 at 8:46
  • Excellent! If you repost the comment as an answer I'll accept it. As far as I can tell, the question isn't marked as a duplicate anymore.
    – Ein
    Commented May 21, 2013 at 2:23
  • Okay, there it is. :)
    – trusktr
    Commented May 24, 2013 at 8:42
  • Thanks for the inspiration. You might want to add <silent> between nnoremap and <F4>, to prevent littering of the statusline.
    – jollyroger
    Commented Nov 4, 2013 at 13:11
  • It took me a while to note that hlsearch doesn't work in function. Any idea why? Commented Apr 4, 2016 at 19:14

13 Answers 13

27

Note, recent Vims (7.4.79) have the v:hlsearch variable available. This means you can improve your mapping to:

:nnoremap <silent><expr> <Leader>h (&hls && v:hlsearch ? ':nohls' : ':set hls')."\n"
8
  • 2
    This is the best option because any search operation like /, ?, n, N, etc. re-enables highlighting, and it doesn't require remapping any of them.
    – Walf
    Commented Oct 24, 2017 at 23:13
  • How to map ctrl-l without losing its original function? Commented Feb 5, 2021 at 20:00
  • 1
    @SergioAraujo Use the :redraw command and append the hls command. Commented Feb 8, 2021 at 16:53
  • How your command differ from this one? nmap <F4> :let &hls=(&hls == 1 ? 0 : 1)<cr> Because this one does not uses ` v:hlsearch` and does not uses <expr>. And if possible I would like to include a redraw because I want to use <ctrl-l>, it is faster pressing it instead of <leader>h. Commented Feb 8, 2021 at 17:44
  • @SergioAraujo v:hlsearch gives the correct state, whether matches are highlighted or not, hls does not, it just enables this option, but it could still be disabled because of :nohls. Commented Feb 11, 2021 at 10:25
13
" ctrl+c to toggle highlight.
let hlstate=0
nnoremap <c-c> :if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1<cr>

Now just press ctrl+c to toggle highlight. Only quirk is you gotta press it twice after a search to toggle off highlight because searching doesn't increment the counter.

2
  • I've linked to another SO question which shows how to make a better toggle. However it requires accepting a different functionality for when highlights are automatically enabled: in it, only searches will automatically enable highlights, and not substitutes (and this is a limitation of the method). But I think I actually like that a bit better.
    – Ein
    Commented May 25, 2013 at 14:20
  • Cool, thanks for sharing! With some effort, maybe a third solution can be made. :D
    – trusktr
    Commented May 25, 2013 at 22:54
12

What I'd like is to map one key, e.g. F4, so that pressing F4 will toggle the visibility of search highlights, and so that starting a new search enables visibility no matter the current visibility.

Just tried this and seems to do the trick:

" switch higlight no matter the previous state
nmap <F4> :set hls! <cr>
" hit '/' highlights then enter search mode
nnoremap / :set hlsearch<cr>/
5

From Highlight all search pattern matches, we can map a key to toggle the highlighting states. Unlike trusktr's answer, here we do use a variable to store the state.

"If you want to be able to enable/disable highlighting quickly, you can map a key to toggle the hlsearch option":

" Press F4 to toggle highlighting on/off, and show current value.
:noremap <F4> :set hlsearch! hlsearch?<CR>

"Or, press return to temporarily get out of the highlighted search":

:nnoremap <CR> :nohlsearch<CR><CR>
5

You can toggle with :set invhlsearch

0
2

Other answer need to toggle highlight search, this is not so good.

Actually you only need to

let @/ = ''

I write a little function to implement this feature, and highlight current word (just like * star key), but not jump to next matched word, and not touch jumplist.

function! HLtoggle()
    if (@/ == '')
        let @/ = expand("<cword>")
    else
        let @/ = ''
    endif
endfunc

it's simple, but i'm not find it in google.

Have fun with vim! :)

1

Okay, try this:

:map <F12> :set nohls<CR>:let @/ = ""<CR>:set hls<CR>

Then if you hit F12, it turns of the higlighting, then sets the last search string to an empty one (that is: clears it), and turns back on the highlighting.

Or if you want to save the search string, then you can do something like:

:map <F12> :set nohls<CR>:let @s = @/<CR>:let @/ = ""<CR>:set hls<CR>
:map <SHIFT><F12> :let @/=@s<CR>

Now after pressing SHIFTF12 the original searchstring will be set back and highlighted.

If that still not satisfy you, you can still do it like:

:map <F12> :highlight Search term=None ctermfg=None ctermbg=None guifg=None guibg=None<CR>
:map <SHIFT><F12> :highlight Search term=OV1 ctermfg=OV2 ctermbg=OV3 guifg=OV4 guibg=OV5<CR>

Where OVx are the original values which you can write down when you issue a :highlight Search<CR>. This way it can be turned off then set back on, but with two keyboard shortcuts. If you want it with one, you should create a function for that which toggles it, then create a mapping for that function.

3
  • This is effectively the same as attempt 1) in that it will nicely turn off highlighting and make sure it nicely comes back on my next search. The problem is that if there isn't a next search I want the button to turn off and on the highlighting on whatever my last search is, so we can't go clearing the @/ variable.
    – Ein
    Commented Jan 29, 2012 at 22:15
  • See my updated answer, on setting it back, and/or using the highlight command. Commented Jan 29, 2012 at 22:34
  • @Ein The solution is simple (perhaps it didn't work in vim back in Jan 2012) but to "hide" the highlight, do :nohl, and to "unhide" the highlight, just do :set hls. Your search term will be rememebered the whole time. Just make a mapping that executes either command based on a variable counter modded by 2.
    – trusktr
    Commented Apr 12, 2013 at 7:37
0

Hmm, isn't :set hlsearch the opposite of :nohlsearch?

The first one turns matches highlighting on, the second one turns matches highlighting off temporarilly.

I don't understand what you mean by "I don't want to toggle the 'hlsearch' setting itself, just the visibility setting.": :set hlsearch and its pendant only deal with the visibility ("highlighting") of search matches, nothing else.

If you want to have matches highlighted each time you do a search just add :set hlsearch to your ~/.vimrc.

If you want the ability to turn highlighting off after a search just map F4 to :nohlsearch, highlighting will be back at your next search.

7
  • To answer your question, try this in vim :set hlsearch? to verify it is on, perform a search, perform :nohlsearch (which turns off visibility, if any), then perform :set hlsearch? again. This will reveal that hlsearch is still on. The significance is if you perform a second search then highlight visibility will come back. In contrast if you perform :set nohlsearch then visibility will never come back until you undo the setting.
    – Ein
    Commented Jan 29, 2012 at 21:13
  • With regards to the last sentence, mapping F4 to :nohlsearch only lets me toggle highlights off. I want to be able to toggle the same search on and off and have it always come back on at my next search.
    – Ein
    Commented Jan 29, 2012 at 21:21
  • That's the point of :nohlsearch: it's temporary. Highlighting will be back at your next search, isn't that what you want?
    – romainl
    Commented Jan 29, 2012 at 21:39
  • Yes and no. I want it off temporarily, yes. But I don't want that temporary time to be "until the next time I perform a new search". Rather, I want it to be off temporarily "until the next time I either press F4 or perform a new search"
    – Ein
    Commented Jan 29, 2012 at 21:49
  • I too want to toggle it, without having to do a new search.
    – trusktr
    Commented Apr 12, 2013 at 7:02
0

I use this slightly improved version from trusktr. Note that ctrl+c as used in the example from trusktr is already mapped to Escape by default which is very handy.

" Toggle highlight search
let hlstate=0
nnomap <Leader>b :if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1<CR>:echo "toggled visibility for hlsearch"<CR>
inomap <Leader>b <ESC>:if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1<CR>:echo "toggled visibility for hlsearch"<CR>a
2
  • What does <Leader> mean? Is it a key?
    – Jocer
    Commented Apr 14, 2022 at 17:23
  • Could you provide the link to the source that you mention? (Who is this "trusktr"?) 🤨
    – Jocer
    Commented Apr 14, 2022 at 17:48
0

In order to accomplish this, I added this unsophisticated line in my .vimrc:

nmap <LEADER>h /xxxxx<CR>
1
  • 1
    Made me laugh out loud :)
    – salezica
    Commented May 5 at 2:07
0

I use the following:

augroup onsearch                                                                                                                    
    autocmd!                                                                                                                          
    autocmd VimEnter * set hlsearch                                                                                                   
augroup END

nnoremap <leader>/ :set hlsearch!<CR>

The autogroup ensure's that highlighting is enabled when entering vim, but not switched on when re-sourcing your vimrc file(s). The mapping toggles it on and off.

0

If anyone is looking to do this in neovim (in lua) this is a simple command that I wrote:

HLSTATE = vim.opt.hlsearch
function TOGGLE_SEARCH_HIGHLIGTING()
  if HLSTATE == true then
    vim.opt.hlsearch = false
    HLSTATE = false
  else
    vim.opt.hlsearch = true
    HLSTATE = true
  end
end
vim.api.nvim_create_user_command('HighlightToggle', 'lua TOGGLE_SEARCH_HIGHLIGTING()', {})

You can then run it with the command :HighlightToggle (and assign in a keymap if you want).

0

I use this mapping in my vimrc:

nnoremap <silent> <leader>a :let v:hlsearch=(&hls && !v:hlsearch)<CR>

Basically if hlsearch is off, the mapping is no-op (v:hlsearch is always false). If it's on, then \a toggles search highlight without changing the hlsearch setting. (Not exactly what OP asked, but I really don't like the idea of switching hlsearch on every time new search starts.)

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