summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-05-06 16:22:04 +0100
committerBram Moolenaar <Bram@vim.org>2023-05-06 16:22:04 +0100
commit3ab3a864814f903da8a158c01820e4fbe1013c08 (patch)
treebcbd4d89d2496377bf29c708306b4c45807dbe58
parent03ff1c2dde7f15eca5c9baa6dafbda9b49bedc3b (diff)
downloadvim-git-3ab3a864814f903da8a158c01820e4fbe1013c08.tar.gz
patch 9.0.1516: cannot use special keys in <Cmd> mappingv9.0.1516
Problem: Cannot use special keys in <Cmd> mapping. Solution: Do allow for special keys in <Cmd> and <ScriptCmd> mappings. (closes #12326)
-rw-r--r--runtime/doc/map.txt4
-rw-r--r--src/errors.h3
-rw-r--r--src/getchar.c54
-rw-r--r--src/ops.c2
-rw-r--r--src/proto/getchar.pro1
-rw-r--r--src/testdir/test_mapping.vim27
-rw-r--r--src/version.c2
7 files changed, 60 insertions, 33 deletions
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index fb92ea34c..8f2fe7573 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -408,10 +408,6 @@ Note:
by <CR> in the {rhs} of the mapping definition. |Command-line| mode is never
entered.
- *E1137*
-<Cmd> and <ScriptCmd> commands can have only normal characters and cannot
-contain special characters like function keys.
-
1.3 MAPPING AND MODES *:map-modes*
*mapmode-nvo* *mapmode-n* *mapmode-v* *mapmode-o*
diff --git a/src/errors.h b/src/errors.h
index bbfe6bb87..12f187afb 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -2894,8 +2894,7 @@ EXTERN char e_using_string_as_bool_str[]
#endif
EXTERN char e_cmd_mapping_must_end_with_cr_before_second_cmd[]
INIT(= N_("E1136: <Cmd> mapping must end with <CR> before second <Cmd>"));
-EXTERN char e_cmd_mapping_must_not_include_str_key[]
- INIT(= N_("E1137: <Cmd> mapping must not include %s key"));
+// E1137 unused
#ifdef FEAT_EVAL
EXTERN char e_using_bool_as_number[]
INIT(= N_("E1138: Using a Bool as a Number"));
diff --git a/src/getchar.c b/src/getchar.c
index 6817fa5b8..d510e45d9 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -603,6 +603,26 @@ AppendToRedobuffLit(
}
/*
+ * Append "s" to the redo buffer, leaving 3-byte special key codes unmodified
+ * and escaping other K_SPECIAL and CSI bytes.
+ */
+ void
+AppendToRedobuffSpec(char_u *s)
+{
+ while (*s != NUL)
+ {
+ if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL)
+ {
+ // insert special key literally
+ add_buff(&redobuff, s, 3L);
+ s += 3;
+ }
+ else
+ add_char_buff(&redobuff, mb_cptr2char_adv(&s));
+ }
+}
+
+/*
* Append a character to the redo buffer.
* Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
*/
@@ -3941,14 +3961,6 @@ getcmdkeycmd(
if (c1 == K_ESC)
c1 = ESC;
}
- if (c1 == Ctrl_V)
- {
- // CTRL-V is followed by octal, hex or other characters, reverses
- // what AppendToRedobuffLit() does.
- ++no_reduce_keys; // don't merge modifyOtherKeys
- c1 = get_literal(TRUE);
- --no_reduce_keys;
- }
if (got_int)
aborted = TRUE;
@@ -3962,19 +3974,27 @@ getcmdkeycmd(
emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
aborted = TRUE;
}
- else if (IS_SPECIAL(c1))
+ else if (c1 == K_SNR)
{
- if (c1 == K_SNR)
- ga_concat(&line_ga, (char_u *)"<SNR>");
- else
+ ga_concat(&line_ga, (char_u *)"<SNR>");
+ }
+ else
+ {
+ if (cmod != 0)
+ {
+ ga_append(&line_ga, K_SPECIAL);
+ ga_append(&line_ga, KS_MODIFIER);
+ ga_append(&line_ga, cmod);
+ }
+ if (IS_SPECIAL(c1))
{
- semsg(e_cmd_mapping_must_not_include_str_key,
- get_special_key_name(c1, cmod));
- aborted = TRUE;
+ ga_append(&line_ga, K_SPECIAL);
+ ga_append(&line_ga, K_SECOND(c1));
+ ga_append(&line_ga, K_THIRD(c1));
}
+ else
+ ga_append(&line_ga, c1);
}
- else
- ga_append(&line_ga, c1);
cmod = 0;
}
diff --git a/src/ops.c b/src/ops.c
index 33fedba05..4c64e05b2 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -3701,7 +3701,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
ResetRedobuff();
else
{
- AppendToRedobuffLit(repeat_cmdline, -1);
+ AppendToRedobuffSpec(repeat_cmdline);
AppendToRedobuff(NL_STR);
VIM_CLEAR(repeat_cmdline);
}
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
index 66c1e9b72..01746cf70 100644
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -11,6 +11,7 @@ void saveRedobuff(save_redo_T *save_redo);
void restoreRedobuff(save_redo_T *save_redo);
void AppendToRedobuff(char_u *s);
void AppendToRedobuffLit(char_u *str, int len);
+void AppendToRedobuffSpec(char_u *s);
void AppendCharToRedobuff(int c);
void AppendNumberToRedobuff(long n);
void stuffReadbuff(char_u *s);
diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim
index b1dd4446a..f9c21bb07 100644
--- a/src/testdir/test_mapping.vim
+++ b/src/testdir/test_mapping.vim
@@ -1001,10 +1001,6 @@ func Test_map_cmdkey()
call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
call assert_equal(0, x)
- noremap <F3> <Cmd><F3>let x = 2<CR>
- call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
- call assert_equal(0, x)
-
noremap <F3> <Cmd>let x = 3
call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
call assert_equal(0, x)
@@ -1104,11 +1100,6 @@ func Test_map_cmdkey()
unmap <F3>
unmap! <F3>
%bw!
-
- " command line ending in "0" is handled without errors
- onoremap ix <cmd>eval 0<cr>
- call feedkeys('dix.', 'xt')
- ounmap ix
endfunc
" text object enters visual mode
@@ -1495,6 +1486,24 @@ func Test_map_cmdkey_redo()
call delete('Xcmdtext')
delfunc SelectDash
ounmap i-
+
+ new
+ call setline(1, 'aaa bbb ccc ddd')
+
+ " command can contain special keys
+ onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
+ let g:foo = ''
+ call feedkeys('0dix.', 'xt')
+ call assert_equal('……', g:foo)
+ call assert_equal('ccc ddd', getline(1))
+ unlet g:foo
+
+ " command line ending in "0" is handled without errors
+ onoremap ix <Cmd>eval 0<CR>
+ call feedkeys('dix.', 'xt')
+
+ ounmap ix
+ bwipe!
endfunc
func Test_map_script_cmd_restore()
diff --git a/src/version.c b/src/version.c
index 8ec68dec7..260afa8ec 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1516,
+/**/
1515,
/**/
1514,