vim-patch:8.2.0867: using \{xxx} for encoding a modifier is not nice

Problem:    Using \{xxx} for encoding a modifier is not nice.
Solution:   Use \<*xxx> instead, since it's the same as \<xxx> but producing a
            different code.
fccd93f091

Use this notation in langmap_spec.
This commit is contained in:
zeertzjq
2022-04-26 15:31:29 +08:00
parent abe91e1efe
commit d531ef6813
9 changed files with 27 additions and 32 deletions

View File

@@ -1325,8 +1325,8 @@ A string constant accepts these special characters:
To use the double quote character it must be escaped: "<M-\">". 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 Don't use <Char-xxxx> to get a UTF-8 character, use \uxxxx as
mentioned above. mentioned above.
\{xxx} like \<xxx> but prepends a modifier instead of including it in the \<*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 character. E.g. "\<C-w>" is one character 0x17 while "\<*C-w>" is four
bytes: 3 for the CTRL modifier and then character "W". 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 Note that "\xff" is stored as the byte 255, which may be invalid in some

View File

@@ -4963,15 +4963,12 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
++name; ++name;
break; break;
// Special key, e.g.: "\<C-W>" or "\{C-W}" // Special key, e.g.: "\<C-W>"
case '<': case '<': {
case '{': {
int flags = FSK_KEYCODE | FSK_IN_STRING; int flags = FSK_KEYCODE | FSK_IN_STRING;
if (*p == '<') { if (p[1] != '*') {
flags |= FSK_SIMPLIFY; flags |= FSK_SIMPLIFY;
} else {
flags |= FSK_CURLY;
} }
extra = trans_special((const char_u **)&p, STRLEN(p), name, flags, NULL); extra = trans_special((const char_u **)&p, STRLEN(p), name, flags, NULL);
if (extra != 0) { if (extra != 0) {

View File

@@ -638,7 +638,6 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
int modifiers; int modifiers;
int bit; int bit;
int key; int key;
const int endchar = (flags & FSK_CURLY) ? '}' : '>';
uvarnumber_T n; uvarnumber_T n;
int l; int l;
@@ -647,9 +646,12 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
} }
src = *srcp; src = *srcp;
if (src[0] != ((flags & FSK_CURLY) ? '{' : '<')) { if (src[0] != '<') {
return 0; return 0;
} }
if (src[1] == '*') { // <*xxx>: do not simplify
src++;
}
// Find end of modifier list // Find end of modifier list
last_dash = src; last_dash = src;
@@ -661,16 +663,16 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
// Anything accepted, like <C-?>. // Anything accepted, like <C-?>.
// <C-"> or <M-"> are not special in strings as " is // <C-"> or <M-"> are not special in strings as " is
// the string delimiter. With a backslash it works: <M-\"> // the string delimiter. With a backslash it works: <M-\">
if (end - bp > l && !(in_string && bp[1] == '"') && bp[l + 1] == endchar) { if (end - bp > l && !(in_string && bp[1] == '"') && bp[l + 1] == '>') {
bp += l; bp += l;
} else if (end - bp > 2 && in_string && bp[1] == '\\' } else if (end - bp > 2 && in_string && bp[1] == '\\'
&& bp[2] == '"' && bp[3] == endchar) { && bp[2] == '"' && bp[3] == '>') {
bp += 2; bp += 2;
} }
} }
} }
if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') { 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) { } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) {
vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true); vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
if (l == 0) { if (l == 0) {
@@ -682,7 +684,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
} }
} }
if (bp <= end && *bp == endchar) { // found matching '>' or '}' if (bp <= end && *bp == '>') { // found matching '>'
end_of_name = bp + 1; end_of_name = bp + 1;
// Which modifiers are given? // Which modifiers are given?
@@ -718,7 +720,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
} else { } else {
l = utfc_ptr2len(last_dash + 1); l = utfc_ptr2len(last_dash + 1);
} }
if (modifiers != 0 && last_dash[l + 1] == endchar) { if (modifiers != 0 && last_dash[l + 1] == '>') {
key = utf_ptr2char(last_dash + off); key = utf_ptr2char(last_dash + off);
} else { } else {
key = get_special_key_code(last_dash + off); key = get_special_key_code(last_dash + off);

View File

@@ -521,7 +521,6 @@ enum {
FSK_KEEP_X_KEY = 0x02, ///< dont translate xHome to Home key FSK_KEEP_X_KEY = 0x02, ///< dont translate xHome to Home key
FSK_IN_STRING = 0x04, ///< in string, double quote is escaped FSK_IN_STRING = 0x04, ///< in string, double quote is escaped
FSK_SIMPLIFY = 0x08, ///< simplify <C-H>, etc. FSK_SIMPLIFY = 0x08, ///< simplify <C-H>, etc.
FSK_CURLY = 0x10, ///< {C-x} instead of <C-x>
}; };
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS

View File

@@ -76,7 +76,7 @@ func Test_backspace_ctrl_u()
set cpo-=< set cpo-=<
inoremap <c-u> <left><c-u> inoremap <c-u> <left><c-u>
exe "normal Avim3\{C-U}\<Esc>\<CR>" exe "normal Avim3\<*C-U>\<Esc>\<CR>"
iunmap <c-u> iunmap <c-u>
exe "normal Avim4\<C-U>\<C-U>\<Esc>\<CR>" 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>" exe "normal A vim6\<Esc>Azwei\<C-G>u\<C-U>\<Esc>\<CR>"
inoremap <c-u> <left><c-u> 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([ call assert_equal([
\ "1 this shouldn't be deleted", \ "1 this shouldn't be deleted",

View File

@@ -62,7 +62,7 @@ func Test_map_ctrl_c_insert()
inoremap <c-c> <ctrl-c> inoremap <c-c> <ctrl-c>
cnoremap <c-c> dummy cnoremap <c-c> dummy
cunmap <c-c> 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('$')) call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
unmap! <c-c> unmap! <c-c>
set nomodified set nomodified
@@ -71,7 +71,7 @@ endfunc
func Test_map_ctrl_c_visual() func Test_map_ctrl_c_visual()
" mapping of ctrl-c in Visual mode " mapping of ctrl-c in Visual mode
vnoremap <c-c> :<C-u>$put ='vmap works' 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('$')) call assert_equal('vmap works', getline('$'))
vunmap <c-c> vunmap <c-c>
set nomodified set nomodified
@@ -221,7 +221,7 @@ endfunc
func Test_map_meta_quotes() func Test_map_meta_quotes()
imap <M-"> foo imap <M-"> foo
call feedkeys("Go-\{M-\"}-\<Esc>", "xt") call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
call assert_equal("-foo-", getline('$')) call assert_equal("-foo-", getline('$'))
set nomodified set nomodified
iunmap <M-"> iunmap <M-">

View File

@@ -115,7 +115,7 @@ endfunc
func Test_mapping_at_hit_return_prompt() func Test_mapping_at_hit_return_prompt()
nnoremap <C-B> :echo "hit ctrl-b"<CR> nnoremap <C-B> :echo "hit ctrl-b"<CR>
call feedkeys(":ls\<CR>", "xt") call feedkeys(":ls\<CR>", "xt")
call feedkeys("\{C-B}", "xt") call feedkeys("\<*C-B>", "xt")
call assert_match('hit ctrl-b', Screenline(&lines - 1)) call assert_match('hit ctrl-b', Screenline(&lines - 1))
nunmap <C-B> nunmap <C-B>
endfunc endfunc

View File

@@ -1815,15 +1815,12 @@ static void parse_quoted_string(ParserState *const pstate, ExprASTNode *const no
*v_p++ = (char)ch; *v_p++ = (char)ch;
break; break;
} }
// Special key, e.g.: "\<C-W>" or "\{C-W}" // Special key, e.g.: "\<C-W>"
case '<': case '<': {
case '{': {
int flags = FSK_KEYCODE | FSK_IN_STRING; int flags = FSK_KEYCODE | FSK_IN_STRING;
if (*p == '<') { if (p[1] != '*') {
flags |= FSK_SIMPLIFY; flags |= FSK_SIMPLIFY;
} else {
flags |= FSK_CURLY;
} }
const size_t special_len = trans_special((const char_u **)&p, (size_t)(e - p), const size_t special_len = trans_special((const char_u **)&p, (size_t)(e - p),
(char_u *)v_p, flags, NULL); (char_u *)v_p, flags, NULL);

View File

@@ -213,11 +213,11 @@ describe("'langmap'", function()
iii]]) iii]])
end) end)
local function testrecording(command_string, expect_string, setup_function) local function testrecording(command_string, expect_string, setup_function, expect_macro)
if setup_function then setup_function() end if setup_function then setup_function() end
feed('qa' .. command_string .. 'q') feed('qa' .. command_string .. 'q')
expect(expect_string) expect(expect_string)
eq(helpers.funcs.nvim_replace_termcodes(command_string, true, true, true), eq(expect_macro or helpers.funcs.nvim_replace_termcodes(command_string, true, true, true),
eval('@a')) eval('@a'))
if setup_function then setup_function() end if setup_function then setup_function() end
-- n.b. may need nvim_replace_termcodes() here. -- n.b. may need nvim_replace_termcodes() here.
@@ -273,8 +273,8 @@ describe("'langmap'", function()
it('treats control modified keys as characters', function() it('treats control modified keys as characters', function()
command('nnoremap <C-w> iw<esc>') command('nnoremap <C-w> iw<esc>')
command('nnoremap <C-i> ii<esc>') command('nnoremap <C-i> ii<esc>')
testrecording('<C-w>', 'whello', local_setup) testrecording('<C-w>', 'whello', local_setup, eval([["\<*C-w>"]]))
testrecording('<C-i>', 'ihello', local_setup) testrecording('<C-i>', 'ihello', local_setup, eval([["\<*C-i>"]]))
end) end)
end) end)