Is there anyway to dynamically enable / disable the highlighting in Vim? - vim

Ok so basically the way Vim highlights searches displeases me. Basically you do a search, then you have to type /asdf or have a shortcut like this in your vimrc:
nn <silent> <leader><space> :noh<CR>
Which is what I have. But it's still too much mental work. Basically, when I do a search, I want highlighting to enable (like it does now) but if I do anything other than cycle through the searches (with n/N) then I want highlighting to turn off. That's basically my workflow, so I'm wondering if I can automate it. Also if I search, do something other than n/N (which should turn highlighting off) and then press n/N again, it should re-enable.
Any ideas?

That's difficult. One idea is
:autocmd CursorHold * call feedkeys(":noh\<CR>")
(One needs to use feedkeys() because :nohlsearch is ineffective in functions and autocmds.) This clears the highlighting whenever you pause the cursor for some seconds. You can add other triggers like InsertEnter or CursorHoldI.
What does not work is CursorMoved, because the searches and n / N jump as well. You would need to overload those commands, store the cursor position after the jump, and modify the autocmd to only clear the highlighting when the position is different.
What I do: I have Enter mapped to :nohlsearch; it's quick and easy to reach.

you can turn it on or off with:
:set hls
or
:set nohls
I have F7 mapped to set hls!:
noremap <F7> :set hls!<CR>

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.

Setting mouse=a and mapping <esc> to :noh breaks mouse working on vim? [duplicate]

I am a happy VIM user, although I admit I'm quite far from being fluent. I found this nice post:
Vim clear last search highlighting and I thought I'd become a better person if I didn't have to hammer away a random character sequence every time I did a search. Now, I'm also using the vimrc config from here:
http://amix.dk/vim/vimrc.html
and the problem I have is that when I add the line nnoremap <esc> :noh<return><esc> to it (it doesn't seem to make a difference where I put it) I get awkward behaviour when I use arrows in command mode, namely letters from A to D appear in a newline and I get switched to insert mode.
There has to be some mapping conflict but for the life of me I can't figure out where it is.
EDIT: As it follows from the answers it turns out the Ultimate vimrc part is not relevant, the mentioned nnoremap command will cause altered arrow behaviour even if it's the only vimrc entry. Changing title to a more informative one.
PS. I know I shouldn't use arrows, hopefully I'll get there one day.
The mapping
nnoremap <esc> :noh<return><esc>
will conflict with so called "grey keys" and I believe that it should be used either in GVim only or in terminal Vim by someone who does not use special keys like arrows.
From what I know (and guess) how Vim processes keys, I would say that it's impossible to do anything with this. For Vim to recognize special key all its components should go in a row, so when you press Arrow Left Vim gets the following sequence of codes:
<esc> [ D
But after your mapping Arrow Left becomes:
: n o h l <cr> <esc>
[ D
Vim sees two separate sequences and treats <esc> as a single press of Escape key, thus next two codes of Left Arrow key lose their special meaning.
So I suggest you to map :noh to some other key sequence (e.g. to one starting with <leader>, see :help mapleader; I don't recommend you to use F-keys, using them is as bad as using of arrow keys).
The cause had been explained well, but solution was not mentioned. However there is a straight one.
If you’ll tell to Vim explicitly that there are key sequences starting from <esc>[
:nnoremap <silent><esc> :noh<CR>
:nnoremap <esc>[ <esc>[
than when single <esc> will be pressed Vim will wait for a second (or different time, see :h 'timeoutlen') or for a next key (second <esc> for example) and only then replace it with :noh<CR>.
This solution preserves the ESC mapping to :nohlsearch.
The comment on this answer explaining why this is happening tells us that the root cause is the TermResponse behavior of vim. This can be compensated for by wrapping the mapping in an autocommand for the TermResponse event.
This ensures that the binding doesn't happen until after the term response is set, which prevents Esc from also sending a string like ]>1;3201;0c to vim.
Change your line in vimrc to this:
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
The augroup commands are not strictly necessary, but they prevent multiple mappings when you reload your vimrc without quitting vim.
EDIT: If you also use a graphical vim like Gvim or Macvim, the TermResponse event will not fire. Assuming you use a single vimrc, you'll need some additional code like
if has('gui_running')
nnoremap <silent> <esc> :nohlsearch<return><esc>
else
" code from above
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
end
Problem is that when you press an arrow terminal emits something like <Esc>OA. Vim part that supports terminal seems to use the same mapping mechanism to do the job as you are using: while nmap <Esc>OA will tell you nothing, call feedkeys("\eOA") will move one line up and call feedkeys("\eOA", 'n') will add letter A beyond current line. With your mapping being noremappable you forbid vim to use <Esc> as a part of the key. The problem is that you need remappable mapping here, but can have remappable mapping without it being recursive as well only if it starts with {lhs}, but <Esc>:noh<CR>OA is not going to work. I thought the following code will (it uses <expr> and function with side effect to make <Esc> be the first character of the actual {rhs} and still launch :noh), but in fact it does not:
function s:NoHlSearch()
nohlsearch
return "\e"
endfunction
nmap <expr> <Esc> <SID>NoHlSearch()
. I have no other idea how to solve the problem of having non-recursive remappable mapping which includes {lhs} but not at the start.
I have had good luck with this
if $TERM =~ 'xterm'
set noek
endif
nnoremap <silent> <esc> <esc>:noh<cr>
The disadvantage is that function keys can not be used in insert mode.
:h ek

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.

How to prevent <Esc> from waiting for more input in Insert Mode

When I leave insert mode by pressing Esc, there is a half-second pause before Vim actually returns to normal mode.
Normally this wouldn't be an issue, since pressing a normal mode command like j after pressing Esc executes the normal-mode command immediately (without the above-mentioned wait), but I have the mapping inoremap <Esc> <Esc>:w<CR>, so that every time I leave insert mode the file is written. I would like the write to occur immediately when I press Esc, but instead there is that half-second pause.
I'm assuming that the pause is because Vim is waiting for more input before it decides that I just meant to type a single, simple Esc. This must be because there is a mapping somewhere who's first character is <Esc>, but I've looked in my .vimrc and there is no such mapping.
Furthermore, I even ran :map <Esc>, and it returned No such mapping. So, if there is no such mapping, why does Vim appear to be waiting for more input, and how can I avoid that behavior?
Extra Information
It appears that this is not reproduceable, so here is some more information in case anyone really wants to get to the bottom of this:
I am using Steve Francia's spf13 distribution of Vim, with my own .vimrc.local on top of it. I have also installed several additional plugins using Vundle.
Notes: .vimrc.local is sourced last in .vimrc.
UPDATE (3/19/2014)
I found a far better solution than trying to hunt down all the mappings that start with <Esc>, courtesy of Powerline, from the Tips & Tricks section of the docs. Put this somewhere in your .vimrc:
" leave insert mode quickly
if ! has('gui_running')
set ttimeoutlen=10
augroup FastEscape
autocmd!
au InsertEnter * set timeoutlen=0
au InsertLeave * set timeoutlen=1000
augroup END
endif
Note that this will make it impossible to use mappings that start with <Esc> while in insert mode, but there shouldn't be any of those anyway, because of the problem this solves.
I found the lines in spf13's .vimrc that were causing the problem:
" Fix home and end keybindings for screen, particularly on mac
" - for some reason this fixes the arrow keys too. huh.
map ^[F $
imap ^[F $
map ^[H g0
imap ^[H g0
The reason I couldn't find them before is because they weren't mapped using <Esc>, but ^[ instead. Very irritating! Hope this helps some equally disgruntled spf13 user :)
UPDATE:
If removing those mappings doesn't work, then it's probably a mapping from a plugin.
Type :verbose map <Esc> to get a list of all mappings involving Esc. The verbose part instructs Vim to print where the mapping was set. That should help find out what's causing the problem.
Also, the command unmap <Esc> might be useful—it removes any mappings for the Esc key.
Note that unmap does not remove mappings in all modes; type :h unmap for more info.
In my case, it was tmux injecting that delay (this came as a complete surprise for me!).
I fixed it by adding set -g escape-time 0 to my tmux.conf.
This may not strictly help the author, but this question comes up first when searching for this issue with many different keyword combinations, so I hope it helps someone.
Source: first comment from here.
I'm not exactly sure what the problem is with the mapping you describe, in my opinion it should be fine. However, I think that what you want to accomplish can be reached in a better way. Your mapping is basically an attempt at creating a InsertLeave event, which Vim actually already has built in!
Try adding something like this to your .vimrc:
au InsertLeave * if &mod && expand('%')!=''|write|endif
As an added bonus, this one only saves your buffer if it has a filename and was actually modified.
set timeoutlen=1000 ttimeoutlen=0
timeoutlen - mapping delays.
ttimeoutlen - key code delays.
Source

How do you make Vim unhighlight what you searched for? [duplicate]

This question already has answers here:
Vim clear last search highlighting
(32 answers)
Closed 3 years ago.
I search for "nurple" in a file. I found it, great. But now, every occurrence of "nurple" is rendered in sick black on yellow. Forever.
Forever, that is, until I search for something I know won't be found, such as "asdhfalsdflajdflakjdf" simply so it clears the previous search highlighting.
Can't I just hit a magic key to kill the highlights when I'm done searching?
:noh (short for nohighlight) will temporarily clear the search highlight. The next search will still be highlighted.
Just put this in your .vimrc
" <Ctrl-l> redraws the screen and removes any search highlighting.
nnoremap <silent> <C-l> :nohl<CR><C-l>
/lkjasdf has always been faster than :noh for me.
" Make double-<Esc> clear search highlights
nnoremap <silent> <Esc><Esc> <Esc>:nohlsearch<CR><Esc>
Then I prefer this:
map <F12> :set hls!<CR>
imap <F12> <ESC>:set hls!<CR>a
vmap <F12> <ESC>:set hls!<CR>gv
And why? Because it toggles the switch: if highlight is on, then pressing F12 turns it off. And vica versa. HTH.
Append the following line to the end of your .vimrc to prevent highlighting altogether:
set nohlsearch
*:noh* *:nohlsearch*
:noh[lsearch] Stop the highlighting for the 'hlsearch' option. It
is automatically turned back on when using a search
command, or setting the 'hlsearch' option.
This command doesn't work in an autocommand, because
the highlighting state is saved and restored when
executing autocommands |autocmd-searchpat|.
Same thing for when invoking a user function.
I found it just under :help #, which I keep hitting all the time, and which highlights all the words on the current page like the current one.
I think the best answer is to have a leader shortcut:
<leader>c :nohl<CR>
Now whenever you have your document all junked up with highlighted terms, you just hit , + C (I have my leader mapped to a comma). It works perfectly.
I search so often that I've found it useful to map the underscore key to remove the search highlight:
nnoremap <silent> _ :nohl<CR>
I think this answer in "Vim clear last search highlighting" is better:
:let #/ = ""
There is hlsearch and nohlsearch. :help hlsearch will provide more information.
If you want to bind F12 to toggle it on/off you can use this:
map <F12> :nohlsearch<CR>
imap <F12> <ESC>:nohlsearch<CR>i
vmap <F12> <ESC>:nohlsearch<CR>gv
I have this in my .vimrc:
nnoremap ; :set invhlsearch<CR>
This way, ; will toggle search highlighting. Normally, the ; key repeats the latest t/T/f/F command, but I never really used that functionality. I find this setting much more useful, because I can change search highlighting on and off very quickly and can easily get a sense of where my search results are, at a glance.
Also, if you want to have a toogle and be sure that the highlight will be reactivate for the next time you search something, you can use this
nmap <F12> :set hls!<CR>
nnoremap / :set hls<CR>/
I add the following mapping to my ~/.vimrc
map e/ /sdfdskfxxxxy
And in ESC mode, I press e/

Resources