aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
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 {