If you use the GUI, you don't need anything special, but you need at least the patch 8.2.0851. Remove all of your code, except the mappings:
inoremap <M-h> <left>
inoremap <M-j> <down>
inoremap <M-k> <up>
inoremap <M-l> <right>
If you use Vim in a terminal which supports the modifyOtherKeys feature (typically xterm and maybe iterm), again, you don't need anything special, but you need at least the patch 8.1.2134. The feature should be enabled by default, but if that's not the case, you can enable it by setting the terminal options 't_TI'
and 't_TE'
:
┌ 1 = enables this feature for keys excluding keys with well-known behavior
│ 2 = enables this feature for all keys (see `man xterm /^\s*modifyOtherKeys`)
│
let &t_TI = "\e[>4;2m"
let &t_TE = "\e[>4;m"
You can check whether the modifyOtherKeys feature is enabled by pressing in insert mode C-S-v
followed by C-v
.
If Vim inserts this key code:
^[[27;5;118~
Then it's enabled; otherwise, if you just get:
^V
Then it's disabled.
Note that for the test to succeed, you need to make sure that you don't have any terminal key binding on C-S-v
.
If you have one, try to disable it temporarily.
If you use Vim in a terminal which does not support the modifyOtherKeys feature, the issue is that <M-h>
is encoded as è
internally which can cause the unexpected behavior you reported in your question:
:echo "\<M-h>"
è
See this answer for more info.
But there exists a workaround; try this:
exe "set <F31>=\eh"
exe "set <F32>=\ej"
exe "set <F33>=\ek"
exe "set <F34>=\el"
inoremap <F31> <left>
inoremap <F32> <down>
inoremap <F33> <up>
inoremap <F34> <right>
The function keys used here are somewhat arbitrary. Although, you can't go beyond <F37>
:
:set <F38>
E846: Key code not set: <F38>
And you probably don't want to use <F1>
to <F12>
, as those are usually present on a keyboard and could be easily typed interactively. You can also use the shift modifier:
vv
:set <S-F37>
but not the other ones:
vv
:set <C-F37>
E518: Unknown option: <C-F37>
It works by telling Vim a lie:
exe "set <F31>=\eh"
This tells Vim that whenever it sees the sequence Esc
+ h
in the typeahead buffer, it must translate it into <F31>
; which is wrong, but bear with me.
From then, whenever you need to refer to <M-h>
in a mapping, you write <F31>
. As an example, you don't write this:
inoremap <M-h> <left>
^---^
✘
But this:
inoremap <F31> <left>
^---^
✔
Now, when you try to insert è
, here's what happens:
typeahead | executed
--------------------
è |
| è
è
is not remapped in the typeahead buffer because you don't have any mapping whose lhs is <M-h>
nor è
.
You may wonder how it's possible for a mapping triggered by <M-h>
to still work even if you no longer write the latter explicitly. It turns out you don't need the Vim key code <M-h>
to make Vim execute something when you press M-h
in the terminal.
Consider the previous code:
exe "set <F31>=\eh"
inoremap <F31> <left>
And suppose you press <M-h>
; here's what happens:
typeahead | executed
--------------------
<esc>h |
<F31> |
<left> |
| <left>
If you don't like this <F31>
hack, visit your terminal's bug tracker, and check whether someone opened a ticket to ask for the modifyOtherKeys feature. If no one did, consider opening one. When your terminal supports the feature, get rid of the hack.
Since you mentioned using sometimes gnome-terminal, I had a look at the gnome bug tracker and found this ticket.
If the developers need some technical documentation, they can find one here. If you need some short user documentation, see here.
For more info, see: