GNOME Terminal – Send Correct Numeric Keypad Keycodes to Vim

gnome-shellgnome-terminalvim

I use the vim-mark plugin, which allows me to make multiple highlights of different colours. It has some default key maps that uses the numeric keypad (<k1><k9> and <C-k1><C-k9>), which allows me to jump back and forth among occurrences of highlights.

Currently, the key maps only work in gvim, but gvim comes with its own rendering quirks, which I will not expand on. If I try to use the numeric keypad in plain vim in GNOME Terminal, vim receives keycodes of the digits above the letters on the keyboard and doesn't do the jumps among highlight occurrences.

Is there a way to make GNOME Terminal send the real numeric keypad keycodes to vim?

I really don't want to change the default key maps of the plugin because any other key maps will either be less memorable or pretty much guarantee the need for more key presses.

Best Answer

GNOME Terminal, as every terminal emulator maps the keysyms it receives from X (or whatever display server you are using) into characters or escape sequences. Unfortunately it has a fixed mapping with no space for configuration.

The keypad can work in two modes: when it is in normal mode it sends the same characters as the digits in the upper row. However, if it is in application mode it send escape sequences. GNOME Terminal's mapping for both modes is the same, whereas vim expects to see the following escape sequences (check with :set termcap):

t_KC <k0>        ^[O*p
t_KD <k1>        ^[O*q
t_KE <k2>        ^[O*r
t_KF <k3>        ^[O*s
t_KG <k4>        ^[O*t
t_KH <k5>        ^[O*u
t_KI <k6>        ^[O*v
t_KJ <k7>        ^[O*w
t_KK <k8>        ^[O*x
t_KL <k9>        ^[O*y

In order to use those shortcut keys you need a terminal, which correctly sends escape sequences when in application mode. You might for example use xterm and switch it into VT220-style function keys, by adding:

XTerm.sunKeyboard: true

to your ~/.Xresources.

Edit: If you want to recompile libvte you should probably modify the entries to something like:

static const struct _vte_keymap_entry _vte_keymap_GDK_KP_0[] = {
    {cursor_all, keypad_all, 0, "0", 1},
    {cursor_all, keypad_app, VTE_NUMLOCK_MASK, "0", 1},
    {cursor_all, keypad_app, 0, _VTE_CAP_SS3 "p", -1},
    {cursor_all, keypad_all, 0, X_NULL, 0},
};

and send the patch to GNOME.