diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-04-26 15:05:56 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2022-04-29 15:51:04 +0800 |
commit | abe91e1efec84c47c03a69ab8a998bb16f628084 (patch) | |
tree | 59814a0125ad7ece7476d9473e25e867e8099339 | |
parent | 6832b626ea1b3413c445dfc23f4d921335dfeaf3 (diff) | |
download | rneovim-abe91e1efec84c47c03a69ab8a998bb16f628084.tar.gz rneovim-abe91e1efec84c47c03a69ab8a998bb16f628084.tar.bz2 rneovim-abe91e1efec84c47c03a69ab8a998bb16f628084.zip |
vim-patch:8.2.0855: GUI tests fail because the test doesn't use a modifier
Problem: GUI tests fail because the test doesn't use a modifier.
Solution: Add "\{xxx}" to be able to encode a modifier.
https://github.com/vim/vim/commit/ebe9d34aa07037cff2188a8dd424ee1f59cbb0bf
Change macros to enums to use them in unit tests.
-rw-r--r-- | runtime/doc/eval.txt | 3 | ||||
-rw-r--r-- | src/nvim/eval.c | 13 | ||||
-rw-r--r-- | src/nvim/keymap.c | 47 | ||||
-rw-r--r-- | src/nvim/keymap.h | 17 | ||||
-rw-r--r-- | src/nvim/option.c | 3 | ||||
-rw-r--r-- | src/nvim/os/input.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_backspace_opt.vim | 4 | ||||
-rw-r--r-- | src/nvim/testdir/test_mapping.vim | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_messages.vim | 2 | ||||
-rw-r--r-- | src/nvim/vim.h | 6 | ||||
-rw-r--r-- | src/nvim/viml/parser/expressions.c | 14 | ||||
-rw-r--r-- | test/unit/keymap_spec.lua | 22 |
12 files changed, 83 insertions, 56 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 2f3602caa1..7f62b7621a 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1325,6 +1325,9 @@ A string constant accepts these special characters: To use the double quote character it must be escaped: "<M-\">". Don't use <Char-xxxx> to get a UTF-8 character, use \uxxxx as mentioned above. +\{xxx} like \<xxx> but prepends a modifier instead of including it in the + character. E.g. "\<C-w>" is one character 0x17 while "\{C-w}" is four + bytes: 3 for the CTRL modifier and then character "W". Note that "\xff" is stored as the byte 255, which may be invalid in some encodings. Use "\u00ff" to store character 255 correctly as UTF-8. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index af6e7e470d..4427179633 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -4963,9 +4963,17 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) ++name; break; - // Special key, e.g.: "\<C-W>" + // Special key, e.g.: "\<C-W>" or "\{C-W}" case '<': - extra = trans_special((const char_u **)&p, STRLEN(p), name, true, true, true, NULL); + case '{': { + int flags = FSK_KEYCODE | FSK_IN_STRING; + + if (*p == '<') { + flags |= FSK_SIMPLIFY; + } else { + flags |= FSK_CURLY; + } + extra = trans_special((const char_u **)&p, STRLEN(p), name, flags, NULL); if (extra != 0) { name += extra; if (name >= rettv->vval.v_string + len) { @@ -4973,6 +4981,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) } break; } + } FALLTHROUGH; default: diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index 07975545be..11abe25255 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -568,25 +568,21 @@ char_u *get_special_key_name(int c, int modifiers) /// @param[in] src_len Length of the srcp. /// @param[out] dst Location where translation result will be kept. It must // be at least 19 bytes per "<x>" form. -/// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL. -/// @param[in] in_string Inside a double quoted string -/// @param[in] simplify simplify <C-H>, etc. +/// @param[in] flags FSK_ values /// @param[out] did_simplify found <C-H>, etc. /// /// @return Number of characters added to dst, zero for no match. unsigned int trans_special(const char_u **const srcp, const size_t src_len, char_u *const dst, - const bool keycode, const bool in_string, const bool simplify, - bool *const did_simplify) + const int flags, bool *const did_simplify) FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT { int modifiers = 0; - int key = find_special_key(srcp, src_len, &modifiers, keycode, false, in_string, simplify, - did_simplify); + int key = find_special_key(srcp, src_len, &modifiers, flags, did_simplify); if (key == 0) { return 0; } - return special_to_buf(key, modifiers, keycode, dst); + return special_to_buf(key, modifiers, flags & FSK_KEYCODE, dst); } /// Put the character sequence for "key" with "modifiers" into "dst" and return @@ -625,16 +621,12 @@ unsigned int special_to_buf(int key, int modifiers, bool keycode, char_u *dst) /// @param[in,out] srcp Translated <> name. Is advanced to after the <> name. /// @param[in] src_len srcp length. /// @param[out] modp Location where information about modifiers is saved. -/// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL. -/// @param[in] keep_x_key Don’t translate xHome to Home key. -/// @param[in] in_string In string, double quote is escaped -/// @param[in] simplify simplify <C-H>, etc. -/// @param[out] did_simplify found <C-H>, etc. +/// @param[in] flags FSK_ values +/// @param[out] did_simplify FSK_SIMPLIFY and found <C-H>, etc. /// /// @return Key and modifiers or 0 if there is no match. int find_special_key(const char_u **const srcp, const size_t src_len, int *const modp, - const bool keycode, const bool keep_x_key, const bool in_string, - const bool simplify, bool *const did_simplify) + const int flags, bool *const did_simplify) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3) { const char_u *last_dash; @@ -642,9 +634,11 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const const char_u *src; const char_u *bp; const char_u *const end = *srcp + src_len - 1; + const bool in_string = flags & FSK_IN_STRING; int modifiers; int bit; int key; + const int endchar = (flags & FSK_CURLY) ? '}' : '>'; uvarnumber_T n; int l; @@ -653,7 +647,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const } src = *srcp; - if (src[0] != '<') { + if (src[0] != ((flags & FSK_CURLY) ? '{' : '<')) { return 0; } @@ -667,16 +661,16 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const // Anything accepted, like <C-?>. // <C-"> or <M-"> are not special in strings as " is // the string delimiter. With a backslash it works: <M-\"> - if (end - bp > l && !(in_string && bp[1] == '"') && bp[l+1] == '>') { + if (end - bp > l && !(in_string && bp[1] == '"') && bp[l + 1] == endchar) { bp += l; } else if (end - bp > 2 && in_string && bp[1] == '\\' - && bp[2] == '"' && bp[3] == '>') { + && bp[2] == '"' && bp[3] == endchar) { bp += 2; } } } if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') { - bp += 3; // skip t_xx, xx may be '-' or '>' + bp += 3; // skip t_xx, xx may be '-' or '>'/'}' } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) { vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true); if (l == 0) { @@ -688,7 +682,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const } } - if (bp <= end && *bp == '>') { // found matching '>' + if (bp <= end && *bp == endchar) { // found matching '>' or '}' end_of_name = bp + 1; // Which modifiers are given? @@ -724,11 +718,11 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const } else { l = utfc_ptr2len(last_dash + 1); } - if (modifiers != 0 && last_dash[l + 1] == '>') { + if (modifiers != 0 && last_dash[l + 1] == endchar) { key = utf_ptr2char(last_dash + off); } else { key = get_special_key_code(last_dash + off); - if (!keep_x_key) { + if (!(flags & FSK_KEEP_X_KEY)) { key = handle_x_keys(key); } } @@ -741,7 +735,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const // includes the modifier. key = simplify_key(key, &modifiers); - if (!keycode) { + if (!(flags & FSK_KEYCODE)) { // don't want keycode, use single byte code if (key == K_BS) { key = BS; @@ -753,7 +747,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const // Normal Key with modifier: // Try to make a single byte code (except for Alt/Meta modifiers). if (!IS_SPECIAL(key)) { - key = extract_modifiers(key, &modifiers, simplify, did_simplify); + key = extract_modifiers(key, &modifiers, flags & FSK_SIMPLIFY, did_simplify); } *modp = modifiers; @@ -945,8 +939,9 @@ char_u *replace_termcodes(const char_u *const from, const size_t from_len, char_ } } - slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, true, false, - (flags & REPTERM_NO_SIMPLIFY) == 0, did_simplify); + slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, + FSK_KEYCODE | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY), + did_simplify); if (slen) { dlen += slen; continue; diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h index 9dff8ba333..5259bf3d52 100644 --- a/src/nvim/keymap.h +++ b/src/nvim/keymap.h @@ -507,6 +507,23 @@ enum key_extra { ? 0 \ : FLAG_CPO_BSLASH) +// Flags for replace_termcodes() +enum { + REPTERM_FROM_PART = 1, + REPTERM_DO_LT = 2, + REPTERM_NO_SPECIAL = 4, + REPTERM_NO_SIMPLIFY = 8, +}; + +// Flags for find_special_key() +enum { + FSK_KEYCODE = 0x01, ///< prefer key code, e.g. K_DEL in place of DEL + FSK_KEEP_X_KEY = 0x02, ///< don’t translate xHome to Home key + FSK_IN_STRING = 0x04, ///< in string, double quote is escaped + FSK_SIMPLIFY = 0x08, ///< simplify <C-H>, etc. + FSK_CURLY = 0x10, ///< {C-x} instead of <C-x> +}; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "keymap.h.generated.h" #endif diff --git a/src/nvim/option.c b/src/nvim/option.c index 79231385ad..068b779eb6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5222,7 +5222,8 @@ int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt) } else if (has_lt) { arg--; // put arg at the '<' modifiers = 0; - key = find_special_key(&arg, len + 1, &modifiers, true, true, false, true, NULL); + key = find_special_key(&arg, len + 1, &modifiers, + FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY, NULL); if (modifiers) { // can't handle modifiers here key = 0; } diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index a4b8735b9e..f68a1c08c8 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -240,7 +240,7 @@ size_t input_enqueue(String keys) uint8_t buf[19] = { 0 }; // Do not simplify the keys here. Simplification will be done later. unsigned int new_size - = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true, false, false, NULL); + = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, FSK_KEYCODE, NULL); if (new_size) { new_size = handle_mouse_event(&ptr, buf, new_size); diff --git a/src/nvim/testdir/test_backspace_opt.vim b/src/nvim/testdir/test_backspace_opt.vim index 11459991ea..64342fbdf8 100644 --- a/src/nvim/testdir/test_backspace_opt.vim +++ b/src/nvim/testdir/test_backspace_opt.vim @@ -76,7 +76,7 @@ func Test_backspace_ctrl_u() set cpo-=< inoremap <c-u> <left><c-u> - exe "normal Avim3\<C-U>\<Esc>\<CR>" + exe "normal Avim3\{C-U}\<Esc>\<CR>" iunmap <c-u> exe "normal Avim4\<C-U>\<C-U>\<Esc>\<CR>" @@ -86,7 +86,7 @@ func Test_backspace_ctrl_u() exe "normal A vim6\<Esc>Azwei\<C-G>u\<C-U>\<Esc>\<CR>" inoremap <c-u> <left><c-u> - exe "normal A vim7\<C-U>\<C-U>\<Esc>\<CR>" + exe "normal A vim7\{C-U}\{C-U}\<Esc>\<CR>" call assert_equal([ \ "1 this shouldn't be deleted", diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index b1c2429511..c6f052ab44 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -62,7 +62,7 @@ func Test_map_ctrl_c_insert() inoremap <c-c> <ctrl-c> cnoremap <c-c> dummy cunmap <c-c> - call feedkeys("GoTEST2: CTRL-C |\<C-C>A|\<Esc>", "xt") + call feedkeys("GoTEST2: CTRL-C |\{C-C}A|\<Esc>", "xt") call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$')) unmap! <c-c> set nomodified @@ -71,7 +71,7 @@ endfunc func Test_map_ctrl_c_visual() " mapping of ctrl-c in Visual mode vnoremap <c-c> :<C-u>$put ='vmap works' - call feedkeys("GV\<C-C>\<CR>", "xt") + call feedkeys("GV\{C-C}\<CR>", "xt") call assert_equal('vmap works', getline('$')) vunmap <c-c> set nomodified @@ -221,7 +221,7 @@ endfunc func Test_map_meta_quotes() imap <M-"> foo - call feedkeys("Go-\<M-\">-\<Esc>", "xt") + call feedkeys("Go-\{M-\"}-\<Esc>", "xt") call assert_equal("-foo-", getline('$')) set nomodified iunmap <M-"> diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index 2e9b0a8531..7cb2a2f1fa 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -115,7 +115,7 @@ endfunc func Test_mapping_at_hit_return_prompt() nnoremap <C-B> :echo "hit ctrl-b"<CR> call feedkeys(":ls\<CR>", "xt") - call feedkeys("\<C-B>", "xt") + call feedkeys("\{C-B}", "xt") call assert_match('hit ctrl-b', Screenline(&lines - 1)) nunmap <C-B> endfunc diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 2672d0b2bc..3c8a865fb1 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -318,10 +318,4 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() #define REPLACE_CR_NCHAR (-1) #define REPLACE_NL_NCHAR (-2) -// Flags for replace_termcodes() -#define REPTERM_FROM_PART 1 -#define REPTERM_DO_LT 2 -#define REPTERM_NO_SPECIAL 4 -#define REPTERM_NO_SIMPLIFY 8 - #endif // NVIM_VIM_H diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index ec747d56d4..1beae0d003 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -1815,10 +1815,18 @@ static void parse_quoted_string(ParserState *const pstate, ExprASTNode *const no *v_p++ = (char)ch; break; } - // Special key, e.g.: "\<C-W>" - case '<': { + // Special key, e.g.: "\<C-W>" or "\{C-W}" + case '<': + case '{': { + int flags = FSK_KEYCODE | FSK_IN_STRING; + + if (*p == '<') { + flags |= FSK_SIMPLIFY; + } else { + flags |= FSK_CURLY; + } const size_t special_len = trans_special((const char_u **)&p, (size_t)(e - p), - (char_u *)v_p, true, true, true, NULL); + (char_u *)v_p, flags, NULL); if (special_len != 0) { v_p += special_len; } else { diff --git a/test/unit/keymap_spec.lua b/test/unit/keymap_spec.lua index 1255774f11..1f1f32bb9e 100644 --- a/test/unit/keymap_spec.lua +++ b/test/unit/keymap_spec.lua @@ -5,7 +5,7 @@ local ffi = helpers.ffi local eq = helpers.eq local neq = helpers.neq -local keymap = helpers.cimport("./src/nvim/keymap.h") +local keymap = helpers.cimport('./src/nvim/keymap.h') local NULL = helpers.NULL describe('keymap.c', function() @@ -16,12 +16,12 @@ describe('keymap.c', function() itp('no keycode', function() srcp[0] = 'abc' - eq(0, keymap.find_special_key(srcp, 3, modp, false, false, false, false, NULL)) + eq(0, keymap.find_special_key(srcp, 3, modp, 0, NULL)) end) itp('keycode with multiple modifiers', function() srcp[0] = '<C-M-S-A>' - neq(0, keymap.find_special_key(srcp, 9, modp, false, false, false, false, NULL)) + neq(0, keymap.find_special_key(srcp, 9, modp, 0, NULL)) neq(0, modp[0]) end) @@ -29,22 +29,22 @@ describe('keymap.c', function() -- Compare other capitalizations to this. srcp[0] = '<C-A>' local all_caps_key = - keymap.find_special_key(srcp, 5, modp, false, false, false, false, NULL) + keymap.find_special_key(srcp, 5, modp, 0, NULL) local all_caps_mod = modp[0] srcp[0] = '<C-a>' eq(all_caps_key, - keymap.find_special_key(srcp, 5, modp, false, false, false, false, NULL)) + keymap.find_special_key(srcp, 5, modp, 0, NULL)) eq(all_caps_mod, modp[0]) srcp[0] = '<c-A>' eq(all_caps_key, - keymap.find_special_key(srcp, 5, modp, false, false, false, false, NULL)) + keymap.find_special_key(srcp, 5, modp, 0, NULL)) eq(all_caps_mod, modp[0]) srcp[0] = '<c-a>' eq(all_caps_key, - keymap.find_special_key(srcp, 5, modp, false, false, false, false, NULL)) + keymap.find_special_key(srcp, 5, modp, 0, NULL)) eq(all_caps_mod, modp[0]) end) @@ -52,20 +52,20 @@ describe('keymap.c', function() -- Unescaped with in_string=false srcp[0] = '<C-">' eq(string.byte('"'), - keymap.find_special_key(srcp, 5, modp, false, false, false, false, NULL)) + keymap.find_special_key(srcp, 5, modp, 0, NULL)) -- Unescaped with in_string=true - eq(0, keymap.find_special_key(srcp, 5, modp, false, false, true, false, NULL)) + eq(0, keymap.find_special_key(srcp, 5, modp, keymap.FSK_IN_STRING, NULL)) -- Escaped with in_string=false srcp[0] = '<C-\\">' -- Should fail because the key is invalid -- (more than 1 non-modifier character). - eq(0, keymap.find_special_key(srcp, 6, modp, false, false, false, false, NULL)) + eq(0, keymap.find_special_key(srcp, 6, modp, 0, NULL)) -- Escaped with in_string=true eq(string.byte('"'), - keymap.find_special_key(srcp, 6, modp, false, false, true, false, NULL)) + keymap.find_special_key(srcp, 6, modp, keymap.FSK_IN_STRING, NULL)) end) end) |