Alt key shortcuts not working on gnome terminal with Vim

VimTerminalGnomeAlt Key

Vim Problem Overview


I'm running Vim on a gnome terminal. But the alt key mappings are not working.
For example (this is just an example):

:imap <A-i> <Esc>

It works fine in GVim. But when I run the same command with Vim in the gnome terminal it just doesn't work.
So I think the problem is with the terminal, right?
How can I fix it?

Thanks

EDIT: I have Windows 7 installed on the same machine, and with Windows terminal it works just fine too.

Vim Solutions


Solution 1 - 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

Solution 2 - Vim

For Gnome-terminal, use the following instead:

imap ^[i <Esc>

^[i should be typed by pressing Ctrl-v Alt-i

Attention: You need to yank and put in Vim when you want to copy it elsewhere. If you just copy the mapping in an editor like gedit, the mapping will probably be broken.

EDIT here is an example which makes Alt-k add an empty line above the cursor, and Alt-j add an empty line after the current line.

" Alt-j/k to add a blank line
if has('gui_running')
    " the following two lines do not work in vim, but work in Gvim
    nnoremap <silent><A-j> :set paste<CR>m`o<Esc>``:set nopaste<CR>
    nnoremap <silent><A-k> :set paste<CR>m`O<Esc>``:set nopaste<CR>
else
    " these two work in vim
    " shrtcut with alt key: press Ctrl-v then Alt-k
    " ATTENTION: the following two lines should not be 
    " edited under other editors like gedit. ^[k and ^[j will be broken!
    nnoremap ^[k :set paste<CR>m`O<Esc>``:set nopaste<CR>
    nnoremap ^[j :set paste<CR>m`o<Esc>``:set nopaste<CR>
endif

Solution 3 - Vim

Try

<m-i>

Or, if typing alti inserts a character (like in my case, it inserts a carret: ˆ) just map to that character:

:inoremap ˆ <esc>

Be careful, because this one wouldn't work (at least in my system, MacOS 10.6). The caret waits for a letter, because it's not exactly a caret, it is a circumflex.

Solution 4 - Vim

The same thing happens to me. I searched on Google with "gnome terminal alt key", and found that someone asked almost the same question: "How to disable the alt-hotkey behavior on gnome terminal?" in the first link found. (The second link is just this question)

So, maybe you can try that:

Edit > Keyboard Shortcuts, and uncheck "Enable menu access keys"

Solution 5 - Vim

It may be that the shortcuts are actually from the Gnome Desktop. Try looking at the Gnome Keyboard Shortcuts tool (System menu, Preferences, Keyboard Shortcuts), which lets you view and modify the shortcuts defined on Gnome Desktop. If the key combination is assigned to a function on Gnome Desktop, then remove it and then that key combo should filter down to Vim properly.

Or you may be right that it is a problem of the terminal. Not all terminals support all key combos. Your problem may be the one described in the Vim help docs at :h map-alt-keys. The docs provide a workaround, but not a very good one.

Solution 6 - Vim

Take a look at section 1.10 of http://vimdoc.sourceforge.net/htmldoc/map.html. It seems to indicate that gnome-terminal automatically escapes the Alt modifier, so that it doesn't switch the byte sent in the way that Vim is expecting. The document seems to indicate that there isn't really a way around this except for using a different terminal (such as xterm).

This is certainly frustrating because so far as I can tell Linux machines are also incapable of using the D (Mac's Command or Linux's Super) bindings, so at least as far as the terminal goes, we are limited to Shift and Ctrl modifiers, which is frustrating if we want to ensure that we can use all the commands we use in Gvim on terminal Vim (at least without switching terminals, towards which I'm perhaps overly stubborn - gnome-terminal is just so much prettier). I've been looking for a way around this but have been unable to find anything.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJesseView Question on Stackoverflow
Solution 1 - VimjpnpView Answer on Stackoverflow
Solution 2 - Vimying17ziView Answer on Stackoverflow
Solution 3 - VimsidyllView Answer on Stackoverflow
Solution 4 - Vimaptx4869View Answer on Stackoverflow
Solution 5 - VimHerbert SitzView Answer on Stackoverflow
Solution 6 - VimmetasoarousView Answer on Stackoverflow