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

Community
  • 1
  • 1
Ein
  • 1,553
  • 3
  • 15
  • 22
  • 1
    Here's the answer: Line 1: `" ctrl+c to toggle highlight.`, Line 2: `let hlstate=0`. Line 3: `nnoremap :if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1`. Now just press ctrl+c to toggle highlight. – trusktr Apr 12 '13 at 08: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 May 21 '13 at 02:23
  • Okay, there it is. :) – trusktr May 24 '13 at 08:42
  • Thanks for the inspiration. You might want to add between nnoremap and , to prevent littering of the statusline. – jollyroger Nov 04 '13 at 13:11
  • It took me a while to note that hlsearch doesn't work in function. Any idea why? – dragonxlwang Apr 04 '16 at 19:14

13 Answers13

26

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"
Christian Brabandt
  • 8,038
  • 1
  • 28
  • 32
  • 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 Oct 24 '17 at 23:13
  • How to map `ctrl-l` without losing its original function? – SergioAraujo Feb 05 '21 at 20:00
  • 1
    @SergioAraujo Use the `:redraw` command and append the `hls` command. – Christian Brabandt Feb 08 '21 at 16:53
  • How your command differ from this one? `nmap :let &hls=(&hls == 1 ? 0 : 1)` Because this one does not uses ` v:hlsearch` and does not uses ``. And if possible I would like to include a `redraw` because I want to use ``, it is faster pressing it instead of `h`. – SergioAraujo Feb 08 '21 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`. – Christian Brabandt Feb 11 '21 at 10:25
  • @ChristianBrabandt could you expand your answer and provide the actual solution with ``? @Walf and you say is the best solution but it's not clear what to put in ``, `` or ``. – Jocer Apr 14 '22 at 17:36
  • @jocerfranquiz I am not sure what your problem is. If you want to use `` instead of `h`, simply replace `h` by ``. – Christian Brabandt Apr 17 '22 at 14:41
  • @jocerfranquiz If I'm reading you correctly, you've interpreted ``, etc. as placeholders. They aren't, they're literal text with the angle brackets giving the words within them special meaning in vimscript. – Walf May 04 '22 at 06:14
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.

trusktr
  • 44,284
  • 53
  • 191
  • 263
  • 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 May 25 '13 at 14:20
  • Cool, thanks for sharing! With some effort, maybe a third solution can be made. :D – trusktr May 25 '13 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>/
Bathz
  • 654
  • 4
  • 17
6

You can toggle with :set invhlsearch

jpm
  • 156
  • 1
  • 5
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>
Yixing Lao
  • 1,198
  • 17
  • 29
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! :)

liuyang1
  • 1,575
  • 1
  • 15
  • 23
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.

Zsolt Botykai
  • 50,406
  • 14
  • 85
  • 110
  • 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 Jan 29 '12 at 22:15
  • See my updated answer, on setting it back, and/or using the `highlight` command. – Zsolt Botykai Jan 29 '12 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 Apr 12 '13 at 07:37
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
ypid
  • 1,708
  • 14
  • 10
0

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

nmap <LEADER>h /xxxxx<CR>
Gene
  • 143
  • 1
  • 6
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.

110100100
  • 169
  • 4
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).

andrewmarkle
  • 221
  • 3
  • 9
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.)

0xfadeef
  • 25
  • 1
  • 8
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.

romainl
  • 186,200
  • 21
  • 280
  • 313
  • 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 Jan 29 '12 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 Jan 29 '12 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 Jan 29 '12 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 Jan 29 '12 at 21:49
  • I too want to toggle it, without having to do a new search. – trusktr Apr 12 '13 at 07:02
  • Zsolt Botykai points out in his answer that to make the search visible, simply do :set hlsearch, which makes it visible again. The hlsearch setting is already on, so :set hlsearch just does the opposite of :nohlsearch, while the whole time the hlsearch setting is on. Make sense? – trusktr Apr 12 '13 at 07:05
  • Since this question is closed as duplicate and I can't post an answer, I've posted my solution as a comment to the original question. Take a look above. – trusktr Apr 12 '13 at 08:48