18

When I hit the arrow keys in insert mode I get characters instead of navigation:

Pressing arrow keys types characters

I'd like to be able to use the arrow keys to navigate.


Things I've tried

I have set nocompatible in my ~/.vimrc (vimrc pastebin), I am using pathogen and here is my ~/.vim/bundle directory:

YouCompleteMe/
emmet-vim/
nerdtree/
node/
vim-airline/
vim-markdown/

The problem only started recently, can't remember the cause.

Some recommend :set term=builtin_ansi, and this fixes the problem but removes all my colors.


$ vim --version
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Aug 29 2016 12:51:13)
MacOS X (unix) version
Included patches: 1-2290
Compiled by Homebrew
Huge version without GUI.  Features included (+) or not (-):
...

See http://pastebin.com/5z1HbpqW for the whole output.

$ echo $TERM
xterm-256color

and in vim:

:set compatible?
nocompatible

:set term?
term=xterm-256color
13
  • 5
    Maybe not a duplicate (I'm not sure) but at least pretty related vi.stackexchange.com/q/5123/1841 – statox Sep 30 '16 at 12:45
  • @statox this is not a duplicate as I am using vim, not vi. – theonlygusti Sep 30 '16 at 18:43
  • 1
    How did you record your screen like that? – Anthony Sep 30 '16 at 19:36
  • Have you tried tips from this site: vim.wikia.com/wiki/… ? – grodzik Oct 3 '16 at 8:02
  • 1
    Get rid of the insert mode mapping with escape. Line 133 – FDinoff Oct 4 '16 at 23:23
13

What's causing the behaviour

When you press the left arrow, your terminal is sending the following escape sequence:

ESC O D

This can also be notated as ^[OD, where ^[ is notation for Ctrl-[, which is another way of notating or entering the ESC character. (Try it in insert mode!)

Vim is not recognising this as an escape sequence, and therefore it is treating those keystrokes as if you had typed them out yourself:

  • Esc: Leave insert mode,
  • O: Begin a new line above the cursor and enter insert mode,
  • D: Enter a 'D' character.

You can confirm that this is what your terminal is sending by entering insert mode and then pressing Ctrl-V followed by the Left arrow.

What's going wrong

The escape sequence might be timing out

The only way that Vim can distinguish the escape sequence from the same three characters manually typed in is by the time that occurs between the receipt of each character. It's possible therefore on slow terminals or very busy systems that there is sufficient delay between each character that Vim is deciding it's not an escape sequence and just interpreting the keystrokes as described above.

This is described in :help vt100-cursor-keys and further in :help timeout — the suggested solution is to set a sufficiently large ttimeoutlen, but disabling timeouts entirely by setting both notimeout and nottimeout would also work.

However, given your setup, this is pretty unlikely to be the issue.

Vim doesn't recognise the sequence

It's more likely that the problem is that Vim doesn't recognise the escape sequence sent, and so is interpreting it as keystrokes. You can check this with the following command:

:set <left>?

In a working setup with your current terminal configuration, this should give either of the following outputs:

t_kl <Left>      ^[O*D
t_kl <Left>      ^[OD

If you see anything else1, then Vim and your terminal are not quite speaking the same language.

The correct way to fix this would be to fix your terminal configuration so that your terminfo database reports the sequences that are actually sent when you press the arrow keys, but doing so can be complicated. A slightly hacky fix is to change what your terminal sends to match what Vim is expecting. I infer from your comments that you are using the default Mac Terminal.app: You can change what escape sequences are sent for each keystroke in Preferences → Profiles → Your profile → Keyboard.

However, the easiest fix is probably to inform Vim directly what escape sequences to expect. You can do this by setting its terminal options thus:

set <up>=^[OA
set <down>=^[OB
set <right>=^[OC
set <left>=^[OD

Note that the ^[ in the above is a literal ESC character. You cannot just type ^ followed by [! The easiest way to enter the mappings is to enter e.g.

set <left>=

and then, still in insert mode, press Ctrl-V followed by the left arrow. Note that you are then setting the escape sequence directly to what Vim receives when you press the arrow key... by sending it that sequence!

1: One likely possibility is the CSI sequence: ^[[D

3
  • Finally, thanks to your answer I have been able to fix the cursor keys under Windows Subsystem for Linux! – David Ferenczy Rogožan Mar 6 '20 at 20:39
  • In my case, I did the mistake of remapping <esc> without a GUI check. Mainly intended for gvim use, but completely broke terminal vim. Checking :verbose imap <esc> might be a good idea as well – Zoe Feb 14 at 12:12
  • 1
    @Zoe I didn't include that possibility in my answer because the OP had already mentioned in the comments that they experienced their issue without any such mapping. It should probably be mentioned on this page, for future readers, though. You should add it as an answer: I'll upvote it! – Rich Feb 23 at 15:56
7

This answer solved the exact same problem for me.

In ~/.vimrc add the following line:

set nocompatible

After restarting vim the problem has gone

1
  • 3
    From :h 'nocompatible' default on, off when a vimrc or gvimrc file is found so if you have a .vimrc putting set nocompatible in it should be redundant. – statox Dec 14 '18 at 9:26
4

Updating the vim package fixed the broken arrows issue for me.

If you are on Ubuntu, run apt upgrade vim. Interestingly, apt install vim also helps. And even more interestingly, after update vim version stays the same:

VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Nov 24 2016 16:44:48)
Included patches: 1-1689
Extra patches: 8.0.0056

But it helps.

3
  • 1
    The version might stay the same but maybe the included patches were updated? Otherwise, I don't see how apt upgrade could solve the problem. – statox Dec 6 '17 at 15:28
  • This worked perfectly for me on elementary OS 5.1 Hera. – praneetloke Feb 10 '20 at 0:16
  • What is happening here is that vim is a different "improved" version of vi. When you install vim it updates the symbolic link in /usr/bin/vi to point to the same executable as vim. – rockettc Nov 30 '20 at 20:23
2

Adding my comment as an answer on Rich's advice; while mappings don't apply in this case specifically, it's still a possible cause of the problem

Remapping <esc> can also trigger the problem.

In my case, I had a map like this:

inoremap <expr> <esc> pumvisible() ? "<C-o>:pclose<CR>" : "\<esc>"

Largely intended for gvim use, but for some reason I don't entirely understand, terminal Vim didn't like this. Some local testing even makes vim trip on inoremap <esc> <esc>. I'm assuming it's related to how terminals in general handle input, and by extension, how vim is required to handle it. Heavy dependency on escape characters seem to be the possible cause, though I'm not sure how that accounts for <esc> remapped to itself non-recursively breaks arrows, but exiting into normal mode still works fine.

TL;DR: a possible reason for this issue is an <esc> remap. Check whether you have one with :verbose imap <esc>, and consider unsetting it to test whether it helps with the issue. :verbose imap <esc> does also give you an indicator of where the map is being set, which is particularly useful if you didn't set it in your vimrc. See also this answer for general advice on keybind debugging and fixing them (fixing keybinds is largely useful if they're set by a plugin without config options; you can remap your own keybinds, but you only ever need unmap for code out of your control -- at least in cases like this).

2
  • Yea, it’s something to do with escape characters, special keys, and drawing codes *waves hands * – D. Ben Knoble Feb 24 at 14:30
  • Just from some random testing, I've found that several keys are interpreted with escape characters. I.e. the right arrow (can be tested with <C-v><right> in insert mode) produces <Right> in gvim, and ^[0C in terminal vim. ^[ being the escape character is why I'm not sure why remapping <esc> to itself causes the problem. I personally expected the escape character to be interpreted as itself sanely. I don't really have much else to say other than "terminal input handling is weird" :') The definition of <right> in a terminal is at least why it's triggered – Zoe Feb 24 at 14:45
1

Check if you have set noescapekeys somewhere in your config.

'esckeys':

Function keys that start with an <Esc> are recognized in Insert mode. When this option is off, the cursor and function keys cannot be used in Insert mode if they start with an <Esc>. The advantage of this is that the single <Esc> is recognized immediately, instead of after one second. Instead of resetting this option, you might want to try changing the values for 'timeoutlen' and 'ttimeoutlen'. Note that when 'esckeys' is off, you can still map anything, but the cursor keys won't work by default.

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.