Mercurial > vim
changeset 30827:0c30130f8c94 v9.0.0748
patch 9.0.0748: Kitty may send key without modifiers with CSI u code
Commit: https://github.com/vim/vim/commit/b9c09c118e951bc6ea2059941101939dc572b4ce
Author: Trygve Aaberge <trygveaa@gmail.com>
Date: Fri Oct 14 12:08:24 2022 +0100
patch 9.0.0748: Kitty may send key without modifiers with CSI u code
Problem: Kitty may send key without modifiers with CSI u code.
Solution: Handle CSI u code without modifiers. (Trygve Aaberge,
closes #11364)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 14 Oct 2022 13:15:04 +0200 |
parents | ddf4fc8d9c65 |
children | 0f439fcdfa1a |
files | src/term.c src/testdir/test_termcodes.vim src/version.c |
diffstat | 3 files changed, 77 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/term.c +++ b/src/term.c @@ -4807,6 +4807,28 @@ handle_version_response(int first, int * } /* + * Add "key" to "buf" and return the number of bytes used. + * Handles special keys and multi-byte characters. + */ + static int +add_key_to_buf(int key, char_u *buf) +{ + int idx = 0; + + if (IS_SPECIAL(key)) + { + buf[idx++] = K_SPECIAL; + buf[idx++] = KEY2TERMCAP0(key); + buf[idx++] = KEY2TERMCAP1(key); + } + else if (has_mbyte) + idx += (*mb_char2bytes)(key, buf + idx); + else + buf[idx++] = key; + return idx; +} + +/* * Handle a sequence with key and modifier, one of: * {lead}27;{modifier};{key}~ * {lead}{key};{modifier}u @@ -4824,7 +4846,6 @@ handle_key_with_modifier( { int key; int modifiers; - int new_slen; char_u string[MAX_KEY_CODE_LEN + 1]; seenModifyOtherKeys = TRUE; @@ -4842,18 +4863,33 @@ handle_key_with_modifier( modifiers = may_remove_shift_modifier(modifiers, key); // insert modifiers with KS_MODIFIER - new_slen = modifiers2keycode(modifiers, &key, string); - - if (IS_SPECIAL(key)) - { - string[new_slen++] = K_SPECIAL; - string[new_slen++] = KEY2TERMCAP0(key); - string[new_slen++] = KEY2TERMCAP1(key); - } - else if (has_mbyte) - new_slen += (*mb_char2bytes)(key, string + new_slen); - else - string[new_slen++] = key; + int new_slen = modifiers2keycode(modifiers, &key, string); + + // add the bytes for the key + new_slen += add_key_to_buf(key, string + new_slen); + + if (put_string_in_typebuf(offset, csi_len, string, new_slen, + buf, bufsize, buflen) == FAIL) + return -1; + return new_slen - csi_len + offset; +} + +/* + * Handle a sequence with key without a modifier: + * {lead}{key}u + * Returns the difference in length. + */ + static int +handle_key_without_modifier( + int *arg, + int csi_len, + int offset, + char_u *buf, + int bufsize, + int *buflen) +{ + char_u string[MAX_KEY_CODE_LEN + 1]; + int new_slen = add_key_to_buf(arg[0], string); if (put_string_in_typebuf(offset, csi_len, string, new_slen, buf, bufsize, buflen) == FAIL) @@ -5016,6 +5052,14 @@ handle_csi( csi_len, offset, buf, bufsize, buflen); } + // Key without modifier (bad Kitty may send this): + // {lead}{key}u + else if (argc == 1 && trail == 'u') + { + return len + handle_key_without_modifier(arg, + csi_len, offset, buf, bufsize, buflen); + } + // else: Unknown CSI sequence. We could drop it, but then the // user can't create a map for it. return 0;
--- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -1992,6 +1992,11 @@ func GetEscCodeCSIu(key, modifier) return "\<Esc>[" .. key .. ';' .. mod .. 'u' endfunc +func GetEscCodeCSIuWithoutModifier(key) + let key = printf("%d", char2nr(a:key)) + return "\<Esc>[" .. key .. 'u' +endfunc + " This checks the CSI sequences when in modifyOtherKeys mode. " The mode doesn't need to be enabled, the codes are always detected. func RunTest_modifyOtherKeys(func) @@ -2080,6 +2085,19 @@ func Test_modifyOtherKeys_no_mapping() set timeoutlen& endfunc +func Test_CSIu_keys_without_modifiers() + " Escape sent as `CSI 27 u` should act as normal escape and not undo + call setline(1, 'a') + call feedkeys('a' .. GetEscCodeCSIuWithoutModifier("\e"), 'Lx!') + call assert_equal('n', mode()) + call assert_equal('a', getline(1)) + + " Tab sent as `CSI 9 u` should work + call setline(1, '') + call feedkeys('a' .. GetEscCodeCSIuWithoutModifier("\t") .. "\<Esc>", 'Lx!') + call assert_equal("\t", getline(1)) +endfunc + " Check that when DEC mouse codes are recognized a special key is handled. func Test_ignore_dec_mouse() silent !infocmp gnome >/dev/null 2>&1