Alt key shortcuts not working on gnome terminal with Vim
Asked Answered
V

6

58

I'm running Vim on a gnome terminal. But the alt key mappings are not working. For example:

:imap <A-i> <Esc>

It works fine in GVim. But when I run the same command with Vim in the gnome terminal it does nothing.

I'm using Windows 7, The problem is with the terminal, right?

Vender answered 21/7, 2011 at 15:51 Comment(1)
Your Alt-i keystroke was intercepted by the operating system itself or the terminal emulator window's GUI keybindings, it performed an action that had no visible effect, and so vim does not receive the Alt-i keystroke at all. To remedy you have to review your OS system settings -> keybindings. Then review your Terminal Emulator's system->keymaps. There you will find an entry for Alt-i. Delete that entry and now vim can receive your keystroke.Mintz
W
108

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
Willdon answered 18/4, 2012 at 19:23 Comment(12)
Thank you so much for this! You finally fixed a problem that's been bothering me for so long!Fini
How to modify it for <A-L>? I mean - for uppercase keys?Germaun
Change the let to 'A' and the while condition to 'Z' to map upper case keys. Do both if you want.Willdon
I have found with this setup, if I'm in Cmdline-mode or Visual-mode that if I press escape it'll either execute a mapping or insert multibyte characters. I fixed this by allowing myself to leave these modes by pressing escape twice with these settings: vnoremap <Esc> <C-v><Esc> and cnoremap <Esc> <C-c>Fini
Is there a workaround that works with having timeout disabled? I don't like timeout, and vim will wait indefinitely for me to complete (for example) a sequence starting with <leader>.Laugh
@Laugh Yes you can set ttimeout. Will add to answer.Willdon
If you are using vim within tmux and can't figure out why the above isn't working, it's because tmux inserts a wait after ESC and will itself interpret keycodes. Put set -sg escape-time 0 in your .tmux.conf to disable this behavior.Malpighi
I found this solution very helpful. I would had trouble using it because I was interested in the <m-9> keybinding, which isn't affected in your while loop. It was easy enough to add, by repeating the loop from '0' to '9'.Deface
Is it possible to make a similar hack work in tmux (so that you can use the alt key in tmux)?Sitter
Unfortunately, this breaks macros in vim for me.Roxane
For some reason vim return me error: E518: Unknown option: <A-a>=^[a :( Any ideas why?Transmit
This post solves regular key bindings (which is great). But I'm getting the same issue with my language server bindings (e.g. map <C-h> :LspRename<CR> works but <M-h> does nothing. I wish I had more skill to debug this.Irrationality
N
8

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
Naphthalene answered 17/5, 2012 at 9:32 Comment(1)
I prefer the 'imap <esc>i ...' spelling, that way there are no control characters in my .vimrcEmad
S
2

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.

Simplicidentate answered 21/7, 2011 at 16:0 Comment(1)
Thanks for the reply. I already tried that too. But it doesn't work neither.Vender
P
2

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.

Panga answered 21/7, 2011 at 18:0 Comment(2)
Since the alt shortcut works with GVim, I think it is not a keyboard issue. Maybe the problem is really the terminal. Do you know if there are alternative terminals for Ubuntu witch I could try?Vender
Here's list of terminal alternatives for Ubuntu: howtogeek.com/howto/ubuntu/…Panga
S
2

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"
Shirker answered 23/6, 2012 at 0:54 Comment(1)
Dunno if that's one of those weird ubuntu upstream edits on gnome-terminal but debian's version didn't quite have that, simply going to edit->preferences->shortcuts and disabling them all worked for meKaenel
A
1

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.

Akkad answered 23/1, 2012 at 2:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.