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

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:
Mapping F4 to :nohlsearch temporarily disables highlight visibility without turning the hlsearch setting off, but it does not toggle visibility back again.
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

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"

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

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

You can toggle with :set invhlsearch

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>

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

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.

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.

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

In order to accomplish this, I added this unsophisticated line in my .vimrc:
nmap <LEADER>h /xxxxx<CR>

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.

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

Related

How to prevent search highlight during when executing a mapping

When writing mappings in nvim, I'm sometimes using a search/replace, for instance in this mapping to creating headings that are the same length as the current line (for markdown etc):
nnoremap <leader>= 0Vyp0v$:s/./=/g<cr>:nohls<cr>
While this clears the search highlighting with :nohls, it still creates the "flash" of the search/replace.
General solution
I would make use of :help function-search-undo and extract the commands into a :function. This won't clobber the current search pattern, and therefore also doesn't affect search highlighting. To be fully neutral, you just have to remove the used substitution pattern from the search history (via histdel()):
function! MakeHeading()
normal! Vyp
s/./=/g
call histdel('search', -1)
endfunction
nnoremap <leader>= :call MakeHeading()<CR>
Note that I've also simplified the visual selection handling: As V always selects the entire line, you don't need to go to the first column (^), neither is the reselection necessary; we can just let :substitute work on the current (pasted) line.
Alternative implementation
That reminds me that the canonical implementation of this functionality uses the :help v_r command, and this indeed requires a re-selection:
nnoremap <leader>= Vyp0v$r=
As there's no pattern involved here, search highlighting is totally unaffected by it :-)
Based on your own answer, I would propose the following:
nnoremap <leader>= :set nohlsearch<cr>0Vyp0v$:s/./=/g<cr>:let #/=''<cr>:set hlsearch<cr>
This just sets the search register to an empty string. So no highlighting. You could even reset it to the previous search string:
nnoremap <leader>= :let olds=#/<cr>0Vyp0v$:s/./=/g<cr>:let #/=olds<cr>
And BTW: Wouldn't yyp:s/./=/g be easier.
I personally have hlsearch off by default and only switch it on, when I need it. To toggle it I have the following mapping in my vimrc:
" Switch on/off higlighting of search string
noremap <F8> :set invhlsearch hlsearch?<CR>
While researching :h :s and :h s_flags`, and doing more looking around here, part of #Ein's answer stuck out to me:
whenever you run the command :set hlsearch there are two effects: It sets the option AND it makes vim forget if you've ever typed :nohlsearch. In other words, changing 'hlsearch' (either on or off) will force the current "highlight visibility" to logically match.
With a combination of using :set nohls and the e flag (:h s_e), I ended up with:
nnoremap <leader>= :set nohlsearch<cr>0Vyp0v$:s/./=/g<cr>:s/thanks#Ein//e<cr>:set hlsearch<cr>
" Broken out
" Turn off highlighting
:set nohlsearch
" Yank the whole line, duplicate it, and replace `.` with `=`
0Vyp0v$:s/./=/g
" Do a replace with something I'll never find in a document (probably), with `/e` to suppress errors.
:s/thanks#Ein//e
" Finally, reenable highlighting
:set hlsearch
Any more elegant solutions are welcome. I think I'll be refactoring some of this into a function soon at least, to allow for using other characters like - for subheadings.

Highlight searches in Vim but not substitutions?

I know it's possible to stop Vim from highlighting on any search, but is there a way to make it highlight on regular searches but not, for instance, substitutions?
I will often highlight a block of text then do something like:
:s/^/#/
to comment out the whole block. But then I have an ugly yellow bar running up and down the left side of my screen and I have to :noh every time to clear it.
I want highlighting to remain on regular /searches. Is this possible?
This doesn't answer your question fully but for me having the same problem it helped: I added this command to easily deactivate the highlighting after a search or a search-and-replace
nnoremap <esc> :noh<return><esc>
(from Vim clear last search highlighting)
My solution: put this in your vimrc file
set nohlsearch
noremap * :set hlsearch<CR>:nohlsearch<CR>*
noremap / :set hlsearch<CR>:nohlsearch<CR>/
noremap ? :set hlsearch<CR>:nohlsearch<CR>?
nnoremap <F4> :set invhlsearch<CR>
inoremap <F4> <ESC>:set invhlsearch<CR>gi
nnoremap <CR> :set nohlsearch<CR>
What it does:
Searches always enable highlights.
Use Enter to turn off highlights until the next search, but not the next substitute. Pressing Enter again will not turn them back on though.
Use F4 to turn off highlights until the next search, but not next substitute. Pressing F4 again will toggle the highlights for the last search pattern --- search OR substitute --- if there was one.
Some notes on highlights that are never really explained well:
When the 'hlsearch' option is on, all future searches/substitutes will turn on "highlight visibility". The current "highlight visibility" is not really an option you can directly query or set independently, but you can independently turn OFF highlight visibility with the command :nohlsearch (this is not the same as :set nohlsearch, because the next search will enable visibility again).
In addition, whenever you run the command :set hlsearch there are two effects: It sets the option AND it makes vim forget if you've ever typed :nohlsearch. In other words, changing 'hlsearch' (either on or off) will force the current "highlight visibility" to logically match.

Emacs style highlighting for incremental search in vim

In Vim, is there a way to enable on-the-fly highlighting for all matches when searching?
If I enable incsearch and type "/something" it will highlight the first match only. If I enable hlsearch and type "/something", nothing happens until I press enter (it only highlights the previous search).
In emacs the first match will be highlighted, and (after a slight delay) all other matches on the screen are highlighted in a different color, giving almost instant feedback when scanning for matches in a piece of code.
Doesn't answer your question, but maybe this Wikia post can help?
Quote from that post:
Put the following code in your vimrc, or create file
~/.vim/plugin/autohighlight.vim (Unix) or
$HOME/vimfiles/plugin/autohighlight.vim (Windows) containing the
script below. Then restart Vim.
To automatically highlight the current word, type z/. To turn off,
type z/ again.
" Highlight all instances of word under cursor, when idle.
" Useful when studying strange source code.
" Type z/ to toggle highlighting on/off.
nnoremap z/ :if AutoHighlightToggle()<Bar>set hls<Bar>endif<CR>
function! AutoHighlightToggle()
let #/ = ''
if exists('#auto_highlight')
au! auto_highlight
augroup! auto_highlight
setl updatetime=4000
echo 'Highlight current word: off'
return 0
else
augroup auto_highlight
au!
au CursorHold * let #/ = '\V\<'.escape(expand('<cword>'), '\').'\>'
augroup end
setl updatetime=500
echo 'Highlight current word: ON'
return 1
endif
endfunction
Add this to your .vimrc
hi Search guifg=black guibg=#C6C5FE gui=BOLD ctermfg=black ctermbg=cyan cterm=BOLD
Of course, you might want to change the colors to suit your needs.

How to highlight all occurrences of a selected word in VIM?

How can I highlight all occurrence of a selected word in GVim, like in Notepad++?
In Normal mode:
:set hlsearch
Then search for a pattern with the command / in Normal mode, or <Ctrl>o followed by / in Insert mode. * in Normal mode will search for the next occurrence of the word under the cursor. The hlsearch option will highlight all of them if set. # will search for the previous occurrence of the word.
To remove the highlight of the previous search:
:nohlsearch
You might wish to map :nohlsearch<CR> to some convenient key.
The * key will highlight all occurrences of the word that is under the cursor.
I know than it's a really old question, but if someone is interested in this feature, can check this code
http://vim.wikia.com/wiki/Auto_highlight_current_word_when_idle
" Highlight all instances of word under cursor, when idle.
" Useful when studying strange source code.
" Type z/ to toggle highlighting on/off.
nnoremap z/ :if AutoHighlightToggle()<Bar>set hls<Bar>endif<CR>
function! AutoHighlightToggle()
let #/ = ''
if exists('#auto_highlight')
au! auto_highlight
augroup! auto_highlight
setl updatetime=4000
echo 'Highlight current word: off'
return 0
else
augroup auto_highlight
au!
au CursorHold * let #/ = '\V\<'.escape(expand('<cword>'), '\').'\>'
augroup end
setl updatetime=500
echo 'Highlight current word: ON'
return 1
endif
endfunction
the simplest way, type in normal mode *
I also have these mappings to enable and disable
"highligh search enabled by default
set hlsearch
"now you can toggle it
nnoremap <S-F11> <ESC>:set hls! hls?<cr>
inoremap <S-F11> <C-o>:set hls! hls?<cr>
vnoremap <S-F11> <ESC>:set hls! hls?<cr> <bar> gv
Select word by clickin on it
set mouse=a "Enables mouse click
nnoremap <silent> <2-LeftMouse> :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>
Bonus: CountWordFunction
fun! CountWordFunction()
try
let l:win_view = winsaveview()
let l:old_query = getreg('/')
let var = expand("<cword>")
exec "%s/" . var . "//gn"
finally
call winrestview(l:win_view)
call setreg('/', l:old_query)
endtry
endfun
" Bellow we set a command "CountWord" and a mapping to count word
" change as you like it
command! -nargs=0 CountWord :call CountWordFunction()
nnoremap <f3> :CountWord<CR>
Selecting word with mouse and counting occurrences at once:
OBS: Notice that in this version we have "CountWord" command at the end
nnoremap <silent> <2-LeftMouse> :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>:CountWord<cr>
Search based solutions (*, /...) move cursor, which may be unfortunate.
An alternative is to use enhanced mark.vim plugin, then complete your .vimrc to let double-click trigger highlighting (I don't know how a keyboard selection may trigger a command) :
"Use Mark plugin to highlight selected word
map <2-leftmouse> \m
It allows multiple highlightings, persistence, etc.
To remove highlighting, either :
Double click again
:Mark (switch off until next selection)
:MarkClear
First (or in your .vimrc):
:set hlsearch
Then position your cursor over the word you want highlighted, and hit *.
hlsearch means highlight all occurrences of the current search, and * means search for the word under the cursor.
to highlight word without moving cursor, plop
" highlight reg. ex. in #/ register
set hlsearch
" remap `*`/`#` to search forwards/backwards (resp.)
" w/o moving cursor
nnoremap <silent> * :execute "normal! *N"<cr>
nnoremap <silent> # :execute "normal! #n"<cr>
into your vimrc.
What's nice about this is g* and g# will still work like "normal" * and #.
To set hlsearch off, you can use "short-form" (unless you have another function that starts with "noh" in command mode): :noh. Or you can use long version: :nohlsearch
For extreme convenience (I find myself toggling hlsearch maybe 20 times per day), you can map something to toggle hlsearch like so:
" search highlight toggle
nnoremap <silent> <leader>st :set hlsearch!<cr>
.:. if your <leader> is \ (it is by default), you can press \st (quickly) in normal mode to toggle hlsearch.
Or maybe you just want to have :noh mapped:
" search clear
nnoremap <silent> <leader>sc :nohlsearch<cr>
The above simply runs :nohlsearch so (unlike :set hlsearch!) it will still highlight word next time you press * or # in normal mode.
cheers
For example this plugIns:
https://github.com/rrethy/vim-illuminate
https://github.com/itchyny/vim-cursorword
Just search for under cursor in vimawesome.com
The key, as clagccs mentioned, is that the highlight does NOT conflict with your search: https://vim.fandom.com/wiki/Auto_highlight_current_word_when_idle
Screen-shot of how it does NOT conflict with search:
Notes:
vim-illuminate highlights by default, in my screen-shot I switched to underline
vim-illuminate highlights/underlines word under cursor by default, in my screen-shot I unset it
my colorschemes are very grey-ish. Check yours to customize it too.
First ensure that hlsearch is enabled by issuing the following command
:set hlsearch
You can also add this to your .vimrc file as set
set hlsearch
now when you use the quick search mechanism in command mode or a regular search command, all results will be highlighted. To move forward between results, press 'n' to move backwards press 'N'
In normal mode, to perform a quick search for the word under the cursor and to jump to the next occurrence in one command press '*', you can also search for the word under the cursor and move to the previous occurrence by pressing '#'
In normal mode, quick search can also be invoked with the
/searchterm<Enter>
to remove highlights on ocuurences use, I have bound this to a shortcut in my .vimrc
:nohl
set hlsearch
maybe ?
Enable search highlighting:
:set hlsearch
Then search for the word:
/word<Enter>
My favorite for doing this is the mark.vim plugin.
It allows to highlight several words in different colors simultaneously.
Example Screenshot
Use autocmd CursorMoved * exe printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))
Make sure you have IncSearch set to something. e.g call s:Attr('IncSearch', 'reverse'). Alternatively you can use another highlight group in its place.
This will highlight all occurrences of words under your cursor without a delay. I find that a delay slows me down when I'm wizzing through code. The highlight color will match the color of the word, so it stays consistent with your scheme.
Why not just:
z/
That will highlight the current word under cursor and any other occurrences. And you don't have to give a separate command for each item you're searching for. Perhaps that's not available in the unholy gvim? It's in vim by default.
* is only good if you want the cursor to move to the next occurrence. When comparing two things visually you often don't want the cursor to move, and it's annoying to hit the * key every time.
Add those lines in your ~/.vimrc file
" highlight the searched items
set hlsearch
" F8 search for word under the cursor recursively , :copen , to close -> :ccl
nnoremap <F8> :grep! "\<<cword>\>" . -r<CR>:copen 33<CR>
Reload the settings with :so%
In normal model go over the word.
Press * Press F8 to search recursively bellow your whole project over the word
--> if you want to highlight a text occurrences in gvim
Select the text & copy
then ?paste the selected text (Note: This will not work for insert mode)

Highlight variable under cursor in Vim like in NetBeans

I worked in NetBeans and liked this feature: when you place cursor in a variable name all occurences of the variable are highlighted. This is very useful for quick searching all occurences of the variable. Is it possible to add this behavior to Vim?
This autocommand will do what you want:
:autocmd CursorMoved * exe printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))
Edit: I have used the IncSearch highlight group in my example, but you can find other colours to use by running this command:
:so $VIMRUNTIME/syntax/hitest.vim
If you set
:set hlsearch
to highlight all occurrences of a search pattern, and then use * or # to find occurrences of the word under your cursor, that will get you some way to what you want. However I think a syntax-aware variable highlighting is beyond the scope of VIM.
This statement will allow a variable to enable/disable highlighting all occurences of the word under the cursor:
:autocmd CursorMoved * exe exists("HlUnderCursor")?HlUnderCursor?printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\')):'match none':""
One would activate highlighting with:
:let HlUnderCursor=1
And disable it with:
:let HlUnderCursor=0
One could easily define a shortcut key for enabling/disabling highlighting:
:nnoremap <silent> <F3> :exe "let HlUnderCursor=exists(\"HlUnderCursor\")?HlUnderCursor*-1+1:1"<CR>
Deleting the variable would prevent the match statement from executing, and not clear the current highlight:
:unlet HlUnderCursor
If you do not want to highlight language words (statements / preprocs such as if, #define) when your cursor is on these words, you can put this function in your .vimrc based on the #too_much_php answer :
let g:no_highlight_group_for_current_word=["Statement", "Comment", "Type", "PreProc"]
function s:HighlightWordUnderCursor()
let l:syntaxgroup = synIDattr(synIDtrans(synID(line("."), stridx(getline("."), expand('<cword>')) + 1, 1)), "name")
if (index(g:no_highlight_group_for_current_word, l:syntaxgroup) == -1)
exe printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))
else
exe 'match IncSearch /\V\<\>/'
endif
endfunction
autocmd CursorMoved * call s:HighlightWordUnderCursor()
i think that what you really want is the following plugin by Shuhei Kubota:
http://www.vim.org/scripts/script.php?script_id=4306
According to the description: 'This script highlights words under the cursor like many IDEs.'
Cheers.
vim_current_word works out of the box, is syntax aware, and allows customisable colours.
To map F2 to toggle highlighting:
map <F2> :set hlsearch!<CR> * #
It is certainly not perfect. '* #' jumps around a bit much...
This variant is optimized for speed (uses CursorHold instead of CursorMoved) and compatibility with hlsearch. The current search word highlighting will not be disrupted.
" autosave delay, cursorhold trigger, default: 4000ms
setl updatetime=300
" highlight the word under cursor (CursorMoved is inperformant)
highlight WordUnderCursor cterm=underline gui=underline
autocmd CursorHold * call HighlightCursorWord()
function! HighlightCursorWord()
" if hlsearch is active, don't overwrite it!
let search = getreg('/')
let cword = expand('<cword>')
if match(cword, search) == -1
exe printf('match WordUnderCursor /\V\<%s\>/', escape(cword, '/\'))
endif
endfunction
Similar to the accepted answer, but this way allows you to set a delay time after holding the cursor over a word before the highlighting will appear. The 1000 is in milliseconds and means that it will highlight after 1 second.
set updatetime=1000
autocmd CursorHold * exe
\ printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))
See :h CursorHold for more info.
vim-illuminate does the trick for me.
match-up does the trick for me.
vim match-up: even better % navigate and highlight matching words modern matchit and matchparen
Features
jump between matching words
jump to open & close words
jump inside (z%)
full set of text objects
highlight (), [], & {}
highlight all matching words
display matches off-screen
show where you are (breadcrumbs)
(neovim) tree-sitter integration

Resources