Alt key shortcuts not working on gnome terminal with Vim

The problem

There are two ways for a terminal emulator to send an Alt key (usually called a Meta key as actual terminals didn’t have Alt). It can either send 8 bit characters and set the high bit when Alt is used, or it can use escape sequences, sending Alt-a as <Esc>a. Vim expects to see the 8 bit encoding rather than the escape sequence.

Some terminal emulators such as xterm can be set to use either mode, but Gnome terminal doesn’t offer any such setting. To be honest in these days of Unicode editing, the 8-bit encoding is not such a good idea anyway. But escape sequences are not problem free either; they offer no way of distinguishing between <Esc>j meaning Alt-j vs pressing Esc followed by j.

In earlier terminal use, typing Escj was another way to send a Meta on a keyboard without a Meta key, but this doesn’t fit well with vi’s use of Esc to leave insert mode.

The solution

It is possible to work around this by configuring vim to map the escape sequences to their Alt combinations.

Add this to your .vimrc:

let c="a"
while c <= 'z'
  exec "set <A-".c.">=\e".c
  exec "imap \e".c." <A-".c.">"
  let c = nr2char(1+char2nr(c))
endw

set timeout ttimeoutlen=50

Alt-letter will now be recognised by vi in a terminal as well as by gvim. The timeout settings are used to work around the ambiguity with escape sequences. Esc and j sent within 50ms will be mapped to <A-j>, greater than 50ms will count as separate keys. That should be enough time to distinguish between Meta encoding and hitting two keys.

If you don’t like having timout set, which times out for other mapped key sequences (after a second by default), then you can use ttimeout instead. ttimeout applies only to key codes and not other mappings.

set ttimeout ttimeoutlen=50

Leave a Comment

tech