2

Background

I would like to disable arrow keys in all modes. This is what I tried:

"EDIT: added remap for <esc> as per the comments
inoremap <esc> <nop>

inoremap <up> <nop>
inoremap <down> <nop>
inoremap <left> <nop>
inoremap <right> <nop>
"inoremap <ESC>oA <nop>
"inoremap <ESC>oB <nop>
"inoremap <ESC>oC <nop>
"inoremap <ESC>oD <nop>
nnoremap <up> <nop>
nnoremap <down> <nop>
nnoremap <left> <nop>
nnoremap <right> <nop>
vnoremap <up> <nop>
vnoremap <down> <nop>
vnoremap <left> <nop>
vnoremap <right> <nop>

This works fine for normal and visual modes, but in insert mode it starts writing funny characters if I press the arrow keys, like OCOCOCOCOCODODODODODOAOAOAOBOB.

Question

What is the reason that the arrow keys behave differently in insert mode than normal/visual modes? (Or do they actually behave the same, and OCOAOB has no effect in normal/visual modes?)

Update: It turned out that the cause for the behaviour was the remapping of the esc key (thanks to @filbranden for pointing that out!) However, the question is still open: why do the remapped arrow keys in insert mode behave differently, if the esc key is also remapped?

Remarks

  • I am running Ubuntu and using Vim in a local terminal (i.e. not ssh'ing somewhere remotely)
  • I already found this answer, and tried to change all kinds of terminal settings/nocompatible mode. The only difference I could achieve was this: [C[C[C[C[D[D[D[D[D[C[C[A[B[D[C. (EDIT: this is caused e.g. by :set term=ansi)
  • The issue is reproducible also with a minimal .vimrc containing only the lines above (i.e., it is not due to a plugin interferring).
  • By uncommenting the commented lines, the problem is fixed, but 1. I would really like to understand what is going on; 2. that solution feels a bit hacky to me, although it works.

Answer to comments

:set term? t_ku?


term=screen-256color
t_ku <Up>        ^[OA

Platform, OS: Ubuntu 19.04 on x86_64, terminal vim

Pressing arrows in terminal:

$ cat
^[[A^[[B^[[A^[[C^[[D^[[C^[[B^[[A
vim -u NONE -N

--> problem is not reproducible

Contents of /etc/vim/vimrc (comments removed):

runtime! debian.vim

if has("syntax")
  syntax on
endif

if filereadable("/etc/vim/vimrc.local")
  source /etc/vim/vimrc.local
endif
  • 1
    @filbranden see update – Attilio Mar 8 at 19:03
  • 1
    :set term=ansi is the one that causes [C[C[C[C[D[D[D[D[D[C[C[A[B[D[C – Attilio Mar 8 at 21:47
  • 1
    Is the <Esc> key itself remapped? Does :imap <Esc> return anything? In general output of :imap by itself, does anything else stand out? I got to reproduce your issue after :inoremap <Esc> <nop>. – filbranden Mar 8 at 21:52
  • 1
    Bingo! I had esc remapped too (to get used to jk instead :D). Indeed, if I remove that mapping, than the issue is gone. (It seems that this morning: 1. I left it in the minimal vimrc, but 2. forgot to paste it here somehow, I have no idea why.) Will update the the beginning of the question accordingly. (Still it is an interseting question, why remapping esc breaks the remapping of the arrow keys.) – Attilio Mar 8 at 22:01
  • 2
    @filbranden The up arrow produces a different escape sequence in your cat test, because Vim switches to application, or keypad transmit mode by sending the smkx sequence when it starts up. See :help raw-terminal-mode and invisible-island.net/xterm/xterm.faq.html#xterm_arrows – Rich Mar 8 at 22:12
1

So the issue is that the mapping for <Esc> is interfering with other mappings. Since most special keys generate sequences that start with an ESC character (which typically shows up as ^[), the mapping is causing Vim to take that initial ESC from the first mapping, which is ignoring the <Esc>, then keeping the rest of the characters (OA) as a normal sequence to be inserted.

Vim can usually handle mappings that involve prefixes, by waiting for further characters or until a timeout happens. That's how Vim can usually detect between an unmapped <Esc> and a special key.

It's unclear why it's not doing so when you're remapping <Esc>... It possibly has something to do with Vim converting the sequence for the <Up> key into <80>ku internally (where <80> is ASCII character 0x80), which might make Vim no longer think it's a longer sequence starting with <Esc>...

One thing is that when you create a longer mapping that starts with <Esc>, such as the one for <Esc>oA that you had commented, that will trigger the behavior of waiting for a timeout before triggering the macro, so that fixes your other mappings by not triggering the <Esc> macro right away. Note, in particular, that <Esc>oA isn't even what the Up arrow generates (it generates an uppercase O instead of a lowercase one.) But any sequence starting with <Esc> would be enough to trigger this behavior.

For example, I'd suggest using this as a workaround to remap both <Esc> and special keys:

inoremap <Esc><nop> <nop>

That will never match anything (as you don't have a way to produce <nop> as a keystroke), but it will have the intended side effect of delaying the initial <Esc> mapping enough for sequences starting with <Esc> to translate into special keys and match those mappings instead.

(Make sure you add a nice comment to that mapping, so you'll later recall why it's needed!)

| improve this answer | |
  • 1
    Thanks for the detailed explanation: the suggested work-around fixes the issue indeed! – Attilio Mar 9 at 17:04

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.