From 913e81c35f162c1e2647565397608f63f38d7043 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 9 Jan 2025 14:05:40 +0100 Subject: fix(getchar): do not simplify keycodes in terminal mode The code represents a useful pattern in normal mode where remapping `` will implicitly also remap `` unless you remap that explicitly. This relies on the _unmapped_ behavior being identical which is not true in terminal mode, as vterm can distinguish these keys. Vim seems to entangle this with kitty keyboard mode detection which is irrelevant for us. Conditional fallbacks depending on keyboard mode could be done completely inside `vterm/` without getchar.c getting involved, I would think. --- src/nvim/getchar.c | 8 +++++--- src/nvim/terminal.c | 16 ++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 60aa1055c3..6cf4556a9f 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1518,9 +1518,11 @@ int merge_modifiers(int c_arg, int *modifiers) if (*modifiers & MOD_MASK_CTRL) { if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) { - c &= 0x1f; - if (c == NUL) { - c = K_ZERO; + if (!(State & MODE_TERMINAL) || !(c == 'I' || c == 'J' || c == 'M' || c == '[')) { + c &= 0x1f; + if (c == NUL) { + c = K_ZERO; + } } } else if (c == '6') { // CTRL-6 is equivalent to CTRL-^ diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index d7ed709906..ad343bad67 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1011,7 +1011,7 @@ static void terminal_send_key(Terminal *term, int c) c = Ctrl_AT; } - VTermKey key = convert_key(c, &mod); + VTermKey key = convert_key(&c, &mod); if (key) { vterm_keyboard_key(term->vt, key, mod); @@ -1415,19 +1415,23 @@ static int term_selection_set(VTermSelectionMask mask, VTermStringFragment frag, // }}} // input handling {{{ -static void convert_modifiers(int key, VTermModifier *statep) +static void convert_modifiers(int *key, VTermModifier *statep) { if (mod_mask & MOD_MASK_SHIFT) { *statep |= VTERM_MOD_SHIFT; } if (mod_mask & MOD_MASK_CTRL) { *statep |= VTERM_MOD_CTRL; + if (!(mod_mask & MOD_MASK_SHIFT) && *key >= 'A' && *key <= 'Z') { + // vterm interprets CTRL+A as SHIFT+CTRL, change to CTRL+a + *key += ('a' - 'A'); + } } if (mod_mask & MOD_MASK_ALT) { *statep |= VTERM_MOD_ALT; } - switch (key) { + switch (*key) { case K_S_TAB: case K_S_UP: case K_S_DOWN: @@ -1459,11 +1463,11 @@ static void convert_modifiers(int key, VTermModifier *statep) } } -static VTermKey convert_key(int key, VTermModifier *statep) +static VTermKey convert_key(int *key, VTermModifier *statep) { convert_modifiers(key, statep); - switch (key) { + switch (*key) { case K_BS: return VTERM_KEY_BACKSPACE; case K_S_TAB: @@ -1791,7 +1795,7 @@ static bool send_mouse_event(Terminal *term, int c) } VTermModifier mod = VTERM_MOD_NONE; - convert_modifiers(c, &mod); + convert_modifiers(&c, &mod); mouse_action(term, button, row, col - offset, pressed, mod); return false; } -- cgit