13

I'm experiencing a weird problem with a normal mode mapping of Esc.

If you create the file escmapvimrc with the contents:

set nocompatible
set showcmd " Doesn't affect the problem: just makes it easier to see
nnoremap <Esc> :noh<CR><esc>

And then start vim using this vimrc:

vim --noplugin -u escmapvimrc

Then vim will start in operator-pending mode with a c command waiting for further input, displaying an empty file, and with the command-line displaying :noh.

If you remove the nnoremap line, then the problem goes away.

If you debug and step through everything you get the following output:

Entering Debug mode.  Type "cont" to continue.
/[...]/escmapvimrc
line 1: set nocompatible
>s
/[...]/escmapvimrc
line 2: set showcmd " Doesn't affect the problem: just makes it easier to see
>s
/[...]/escmapvimrc
line 3: nnoremap <Esc> :noh<CR><esc>
>s
/[...]/escmapvimrc
line 4: End of sourced file
>s
Press ENTER or type command to continue

After you press enter, the Vim startup screen is displayed, and underneath:

Entering Debug mode.  Type "cont" to continue.
cmd: noh
>s

The Vim startup screen then disappears, and you're in operator-pending mode, as described above.

What's going on?

EDIT: Behaviour is as described in Vim 7.3. In Vim 7.4.52, the nmap causes Vim to start up in Replace mode when starting Vim without a file. (If Vim 7.4.52 is started with a file, however, it also starts up with a c-command underway.) Either way, the problem goes away when the nmap is removed.

  • I did reproduce this with vim, but the command line did not show :noh for me. Doing the same with gvim did not show this behavior. – PhilippFrank Mar 18 '15 at 12:04
  • 1
    A common mapping for clearing the search highlight is: nnoremap <c-l> :noh<cr><c-l> – Peter Rincker Mar 18 '15 at 14:43
  • As a side note, you can use /alksdjflaskj to clear up search highlight which is quite fast as well. – Shahbaz Mar 15 '18 at 19:52
10

Vim sends during startup some special terminal codes (that usually contain the <esc> key) to determine several things (colors, bs,...) If you mapped <esc> this will most likely confuse the parser of the return codes and weird things can happen.

Therefore, use your above map only after everything has been setup correctly (e.g. via a VimEnter autocommand).

  • 1
    Well, they're sent whenever the 'term' option is set. That's usually only during startup, but there may be scenarios where it is set at runtime. – jamessan Mar 18 '15 at 20:25
  • In this particular case, this seems to be caused by may_req_ambiguous_char_width() which is only called on startup – Christian Brabandt Mar 18 '15 at 21:48
  • I was planning to try exactly this (which is why I didn't accept the other answer). Good to have confirmation it should work, though. – Rich Mar 19 '15 at 10:01
  • This has done the trick, although VimEnter specifically didn't work. – Rich Mar 20 '15 at 15:57
  • You're kidding right? The escape used to communicate should be separate from the Escape key mapping. – shawnhcorey Feb 5 '17 at 21:30
10

The Linux terminal uses ANSI escape sequences (i.e. strings of characters starting with <Esc>) to send special keys to Vim, and as part of the communication protocol with which the application queries for its capabilities. Your mapping interferes with that, and thereby leads to these "strange" behaviors.

Therefore, don't map <Esc>. Use another key. The problem is less pronounced in GVIM, but I wouldn't recommend it there, neither.

  • Unfortunately, I've had this mapping almost since I started using Vim, so it's pretty well burned in to my muscle memory by now. Thanks for the explanation, though. – Rich Mar 18 '15 at 14:22
  • I should probably add, for posterity's sake, the problem described is the only problem that I know is definitely caused by this mapping, and the only weird unresolved problem I can recollect having with Vim. – Rich Mar 18 '15 at 14:53
  • 1
    @Rich how hard would it be to get used to using something like <Esc><Esc>? – Random832 Mar 19 '15 at 15:28
  • @Random832 That's an intriguing idea. – Rich Mar 20 '15 at 10:18
  • 1
    All xterm programs will do this because they emulate VT-100 terminals. It has nothing to do with Linux. iOS, which is based on BSD not Linux, will also have xterms that emulate VT-100s. – shawnhcorey Feb 5 '17 at 21:28
1

Try this:

augroup escape_mapping
  autocmd TermResponse * nnoremap <Esc> :noh<CR><esc>
augroup end

cf https://stackoverflow.com/a/16027716/400545

1

I tried setting up an autocommand to set the mapping later on in startup, but the problem still occurred.*

I eventually created an autocommand to occur the first time I enter Insert mode. This is obviously not a perfect solution, but for me it'll work most of the time, and it seems to be the best I can do:

UPDATE: After using the longer version below without issue for a few years, I decided it was possibly slightly over-engineered, and since then I've used this much simpler version, which instead just resets the mapping every time you enter insert mode:

augroup escape_mapping
  autocmd!
  autocmd InsertEnter * call s:setupEscapeMap()
augroup END

function! s:setupEscapeMap()
  nnoremap <Esc> :noh<CR><Esc>
endfunction

The mapping doesn't need to be reset every time you enter insert mode, but it also doesn't do any harm for Vim to do so.

ORIGINAL VERSION:

if !exists('g:escape_mapped')  " Only need to set the mapping up once.
  augroup escape_mapping
    autocmd!
    " Create the autocommand, to fire when Insert mode is entered
    autocmd InsertEnter * call s:setupEscapeMap()
  augroup END
endif

function! s:setupEscapeMap()
  " Actually create the mapping
  nnoremap <Esc> :noh<CR><Esc> 

  " Now the map exists, so we won't ever need the autocommand again.
  let g:escape_mapped = 1

  " Tidy up the autocommand and group
  autocmd! escape_mapping InsertEnter *
  augroup! escape_mapping
endfunction

* I tried attaching it to various events: VimEnter, BufReadPost, BufWinEnter, and even CursorMoved(!), but these all seem to fire too early.

  • Have you ever tried the TermResponse autocommand? – Christian Brabandt Jul 30 '18 at 16:12
  • @ChristianBrabandt It's on my todo list! – Rich Jul 30 '18 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.