Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping <esc> in vimrc causes bizarre arrow behaviour

Tags:

vim

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.

like image 971
Tomek Kaftal Avatar asked Aug 13 '12 19:08

Tomek Kaftal


3 Answers

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

like image 72
xaizek Avatar answered Nov 12 '22 15:11

xaizek


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

like image 29
Dmitry Alexandrov Avatar answered Nov 12 '22 15:11

Dmitry Alexandrov


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
like image 14
Eric Hu Avatar answered Nov 12 '22 13:11

Eric Hu