Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alt key shortcuts not working on gnome terminal with Vim

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.

like image 532
Jesse Avatar asked Jul 21 '11 15:07

Jesse


People also ask

What does ALT do in Vim?

When in insert mode using alt + key sends escape first so that you can then use all movement commands. Also, when you for example use Alt+o/O, you can insert multiple lines fast, switch from insert mode straight to visual, etc.

What is the shortcut to open GNOME Terminal?

CTRL+ALT+T is the shortcut key to start or open the GNOME Terminal on Linux.


2 Answers

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 
like image 102
jpnp Avatar answered Sep 20 '22 07:09

jpnp


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 
like image 44
ying17zi Avatar answered Sep 20 '22 07:09

ying17zi