diff options
Diffstat (limited to 'src')
-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 |
10 files changed, 69 insertions, 45 deletions
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 { |