aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-04-26 15:05:56 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-04-29 15:51:04 +0800
commitabe91e1efec84c47c03a69ab8a998bb16f628084 (patch)
tree59814a0125ad7ece7476d9473e25e867e8099339
parent6832b626ea1b3413c445dfc23f4d921335dfeaf3 (diff)
downloadrneovim-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.txt3
-rw-r--r--src/nvim/eval.c13
-rw-r--r--src/nvim/keymap.c47
-rw-r--r--src/nvim/keymap.h17
-rw-r--r--src/nvim/option.c3
-rw-r--r--src/nvim/os/input.c2
-rw-r--r--src/nvim/testdir/test_backspace_opt.vim4
-rw-r--r--src/nvim/testdir/test_mapping.vim6
-rw-r--r--src/nvim/testdir/test_messages.vim2
-rw-r--r--src/nvim/vim.h6
-rw-r--r--src/nvim/viml/parser/expressions.c14
-rw-r--r--test/unit/keymap_spec.lua22
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)