85

I'm trying to map Alt key in the following way:

:map <A-j> j
:map <A-k> k

but it doesn't work (bell is rang on Alt + j/Alt + k).

What am I missing?

I'm using Terminal on OSX, the same happens on remote Linux.


On Ctrl + v, Alt + j, I've got: ?~H~F ( when encoding=utf-8).

On Ctrl + v, Alt + k, I've got: ?~Z (˚ when encoding=utf-8).

Running vim without plugins (-u NONE) doesn't make any difference.

Kossak
  • 1,658
  • 13
  • 15
kenorb
  • 18,433
  • 18
  • 72
  • 134
  • 1
    Does Alt (press, not hold) and then j work? With xterm at least I need to set metaSendsEscape to true to get these sequences to work... I don't know if you have the same problem, and I don't use OSX so I can't test... – Martin Tournoij Mar 03 '15 at 23:16
  • @Carpetsmoker Pressing Alt, release, then j or any other key works as normal. I've checked and found the option 'Use option as meta key', enabled it and it works now. So setting metaSendsEscape did the trick, thanks. – kenorb Mar 03 '15 at 23:41
  • 5
    This question was previously answered (with a better response) here: http://stackoverflow.com/questions/6778961/alt-key-shortcuts-not-working-on-gnome-terminal-with-vim/10216459#10216459 – user3751385 Oct 05 '16 at 07:55
  • Your Alt-j and Alt-k was intercepted by your operating system or your Terminal emulator or both. The intercepted action (Find?) as defined in your_os->system->settings->keybindings or your_terminal->settings->keymaps will tell you where the keystroke sunk. Delete all entries and vim once again receives your keystroke. – Eric Leschinski Jun 05 '22 at 01:42

8 Answers8

93

That's how I do it on Linux or Cygwin:

First check what chars are sent by your terminal when you press ALT+J:

In order to do this I go to console and run sed -n l (you can also use cat for it). Then I press ALT+J and see that the chars on the screen are ^[j .

I replace ^[ with \e (because that's what is sent by my terminal when I press esc) and the final string for me is \ej.

Then I write it to my .vimrc:

execute "set <M-j>=\ej"
nnoremap <M-j> j

And the mapping works.

guntbert
  • 1,245
  • 1
  • 13
  • 27
Kossak
  • 1,658
  • 13
  • 15
21

With help of Carpetsmoker, it seems that Terminal wasn't configured to 'Use Alt/option as meta key' (this is especially common for GUI Terminals).

For Terminal on OSX, it's in Preferences -> Settings -> Keyboard tab -> 'Use option as meta key'. Check: How can I change Terminal to use option as meta key? (Mavericks).

For XTerm, check: Configuring XTerm to Default to Meta Sends Escape which says:

Add this line anywhere in your personal .Xdefaults file (~/.Xdefaults):

xterm*metaSendsEscape: true

Then reload the config with xrdb. Without this step the changes in .Xdefaults won't take effect until the next X restart:

xrdb -l ~/.Xdefaults

Then standard mappings with Alt key like:

:map <A-j> j
:map <A-k> k

works fine.

For help, see: :h :map-alt-keys.

kenorb
  • 18,433
  • 18
  • 72
  • 134
14

Similar to Kossak's answer but a bit simpler, by mapping literal key presses.

Either in normal mode after pressing :, or inserted into your .vimrc, map the input directly by starting the mapping:

nnoremap 

then hitting Ctrl + V then the keystroke to record, e.g. Alt + . This will show as something like this:

nnoremap ^[[1;3D

but each ^[ is a single, literal escape character and syntax highlighting should show this. Replace the literal escape(s) with the text <Esc>, and append the command you wish to use:

nnoremap <Esc>[1;3D <C-w>h

I know OP was mapping Alt + letters, but I used arrows to show how do it for something that may not be mapped by default.

Walf
  • 294
  • 2
  • 9
4

If Control+V followed by ALT-x shows ^[x (type in terminal) you can fix it with this small script from vim.wikia.com:

for i in range(97,122)
  let c = nr2char(i)
  exec "map \e".c." <M-".c.">"
  exec "map! \e".c." <M-".c.">"
endfor

Add to .vimrc for all alt key mappings.

laktak
  • 2,933
  • 13
  • 27
3

This works for me on Ubuntu 16.04 xfce terminal (and alacritty rust terminal)

Set ultisnip snippet trigger to Meta-/ (just like emacs snippet)

let g:UltiSnipsExpandTrigger="^[/"

Here's now I type ^[/ in vim

In insert mode Ctrl-V Alt-/

(Meta is the Alt key on my PC keyboard)

muru
  • 24,838
  • 8
  • 82
  • 143
user178047
  • 131
  • 1
2

I'm using Terminal on OSX, the same happens on remote Linux.

I don't know about Terminal, but if you are on OSX, your mappings should work out of the box, provided that you use a recent Vim version, and a recent iTerm2 terminal.

You need at least the Vim patch 8.1.2134. Having the patch 8.1.2194 also helps, because it automatically enables the modifyOtherKeys feature on which Vim relies to let the user map various chords.

For iterm2, I think you need at least the version 3.4.0. From the changelog:

  • Modifier keys in vim should work better now. CSI u mode is no longer enabled by a control sequence. Instead, a "modifyOtherKeys" mode has been added which is compatible with xterm.

On Linux, xterm also supports the modifyOtherKeys feature.


You are not limited to meta chords. You can map many other chords, like <C-;> for example:

vim -Nu NONE +'nno <c-;> :echo "c-; was hit"<cr>'

For more info, see :h modifyOtherKeys.

user938271
  • 5,947
  • 1
  • 15
  • 24
  • I'm on 8.2.2300, and I couldn't make nnoremap <A-j> :echo "alt-j"<CR> work on macOS on either Terminal.app or Alacritty :( oh well, I don't tend to use those chords anyway – D. Ben Knoble Mar 07 '21 at 17:53
1

You have another option. NeoVim works with M-x out of the box when you have terminal sending ESC + sequence, which mostly every terminal could.

As a summary for other answers, I think your two options are

  1. Turning using "opt as meta" off, using the actual sent code in mapping
  2. Turning using "opt as meta" on, using <esc>x type of sequence for mapping.

There are some answers stating that just turning on opt as meta would make <A-x>/<M-x> work. That is not true. At least, it will not work on macOS.

D. Ben Knoble
  • 26,070
  • 3
  • 29
  • 65
Haodong Du
  • 11
  • 1
  • 1
    Welcome to [vi.se]! I've edited your post for some formatting, and also edited out the opinion-based parts to focus on the core facts. – D. Ben Knoble Mar 07 '21 at 17:46
1

I couldn't get any of the solutions in this thread to work on macOS because it has special characters mapped to <alt><letter>.

I ended up just mapping to the special characters. So <A-J><M-J> gets mapped to å. It doesn't work in insert mode because the special character will still get inserted, but I spend more time in normal mode anyway.

It's been the simplest working solution for me thus far.

Martin Tournoij
  • 62,054
  • 25
  • 192
  • 271