Ein
Ein

Reputation: 1603

How to toggle Vim's search highlight visibility without disabling it

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

Upvotes: 23

Views: 17802

Answers (13)

0xfadeef
0xfadeef

Reputation: 25

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.)

Upvotes: 0

andrewmarkle
andrewmarkle

Reputation: 241

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).

Upvotes: 0

110100100
110100100

Reputation: 199

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.

Upvotes: 0

Gene
Gene

Reputation: 143

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

nmap <LEADER>h /xxxxx<CR>

Upvotes: 0

jpm
jpm

Reputation: 184

You can toggle with :set invhlsearch

Upvotes: 8

Christian Brabandt
Christian Brabandt

Reputation: 8258

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"

Upvotes: 27

liuyang1
liuyang1

Reputation: 1725

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! :)

Upvotes: 2

Yixing Lao
Yixing Lao

Reputation: 1438

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>

Upvotes: 5

ypid
ypid

Reputation: 1848

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

Upvotes: 0

trusktr
trusktr

Reputation: 45502

" 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.

Upvotes: 13

Bathz
Bathz

Reputation: 654

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>/

Upvotes: 12

Zsolt Botykai
Zsolt Botykai

Reputation: 51693

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.

Upvotes: 1

romainl
romainl

Reputation: 196886

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.

Upvotes: 0

Related Questions