29

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, 2016 at 12:45
  • @statox this is not a duplicate as I am using vim, not vi. Sep 30, 2016 at 18:43
  • 2
    How did you record your screen like that?
    – Anthony
    Sep 30, 2016 at 19:36
  • Have you tried tips from this site: vim.wikia.com/wiki/… ?
    – grodzik
    Oct 3, 2016 at 8:02
  • 1
    Get rid of the insert mode mapping with escape. Line 133
    – FDinoff
    Oct 4, 2016 at 23:23

9 Answers 9

20

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

4
  • Finally, thanks to your answer I have been able to fix the cursor keys under Windows Subsystem for Linux! Mar 6, 2020 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 Feb 14, 2021 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, 2021 at 15:56
  • Excellent explanation of how VI and keycodes interact. Might be worth incorporating esckeys as mentioned by vi.stackexchange.com/a/29549/36971 which was missing key step in my case on Debian
    – vmpn
    Mar 5, 2022 at 20:32
13

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, 2018 at 9:26
5

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, 2017 at 15:28
  • This worked perfectly for me on elementary OS 5.1 Hera. Feb 10, 2020 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, 2020 at 20:23
3

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

3
  • Yea, it’s something to do with escape characters, special keys, and drawing codes *waves hands *
    – D. Ben Knoble
    Feb 24, 2021 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 Feb 24, 2021 at 14:45
  • In a configuration I was loading, there was inoremap <expr> <esc> ((pumvisible())?("\<C-e>"):("\<esc>")) so that Escape would close autocomplete; unfortunately, it seemed to cause this behaviour too. The developer of the configuration probably never noticed because they disabled arrow keys. Thanks! Dec 15, 2022 at 22:56
3

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.

1

Before doing any re-mapping or tweaking the vim configs, I would highly recommend you to upgrade your packages first.

sudo apt-get upgrade

The latest vim versions fix the re-mapping and related signal issues, and it should fix the problem that you're facing.

0

I fix it with this in my .vimrc:

First line:

set nocompatible

Next:

noremap <Up> g<Up>
noremap <Down> g<Down>
inoremap <Up> <C-o>g<Up>
inoremap <Down> <C-o>g<Down>
1
  • Welcome to Vi and Vim! Note that it is redundant to put :set nocompatible in your vimrc (see :help 'compatible').
    – D. Ben Knoble
    Feb 15, 2022 at 15:07
0

Here is the command that solved the problem for me:

Run in VIM :!reset

-1

vim/vi doesn't require use of the standard arrow keys for document navigation. The h j k l keys can be used for left down up right respectively, when not in insert mode.

The standard arrow keys stopped working for me on a linux vm I typically work on, randomly, not sure why. But then I had a forehead slap moment where I remembered that h j k l keys are pretty much the way you're supposed to navigate with vim/vi.

The question is more around getting the arrow keys working explicitly, but I thought this was a good reminder that h j k l keys can be used to navigate, like the arrow keys, with vim/vi, as this answer came up a lot when I was searching for a way to navigate in general when the arrow keys broke.

1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Feb 8, 2022 at 16:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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