Patch 9.0.1516
Problem: Cannot use special keys in <Cmd> mapping.
Solution: Do allow for special keys in <Cmd> and <ScriptCmd> mappings.
(closes #12326)
Files: runtime/doc/map.txt, src/errors.h, src/getchar.c,
src/proto/
getchar.pro, src/ops.c, src/testdir/test_mapping.vim
*** ../vim-9.0.1515/runtime/doc/map.txt 2023-02-03 12:28:00.299287568 +0000
--- runtime/doc/map.txt 2023-05-06 16:14:43.522945467 +0100
***************
*** 406,415 ****
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*
--- 408,413 ----
*** ../vim-9.0.1515/src/errors.h 2023-05-05 22:58:30.805061562 +0100
--- src/errors.h 2023-05-06 16:14:43.522945467 +0100
***************
*** 2894,2901 ****
#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"));
#ifdef FEAT_EVAL
EXTERN char e_using_bool_as_number[]
INIT(= N_("E1138: Using a Bool as a Number"));
--- 2894,2900 ----
#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>"));
! // E1137 unused
#ifdef FEAT_EVAL
EXTERN char e_using_bool_as_number[]
INIT(= N_("E1138: Using a Bool as a Number"));
*** ../vim-9.0.1515/src/getchar.c 2023-04-22 22:54:28.049802336 +0100
--- src/getchar.c 2023-05-06 16:20:06.574629402 +0100
***************
*** 603,608 ****
--- 603,628 ----
}
/*
+ * 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,3954 ****
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;
--- 3961,3966 ----
***************
*** 3962,3980 ****
emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
aborted = TRUE;
}
! else if (IS_SPECIAL(c1))
{
! if (c1 == K_SNR)
! ga_concat(&line_ga, (char_u *)"<SNR>");
! else
{
! semsg(e_cmd_mapping_must_not_include_str_key,
! get_special_key_name(c1, cmod));
! aborted = TRUE;
}
}
- else
- ga_append(&line_ga, c1);
cmod = 0;
}
--- 3974,4000 ----
emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
aborted = TRUE;
}
! else if (c1 == K_SNR)
{
! 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))
{
! 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);
}
cmod = 0;
}
*** ../vim-9.0.1515/src/proto/
getchar.pro 2022-09-05 16:53:17.115566769 +0100
--- src/proto/
getchar.pro 2023-05-06 16:17:49.110752774 +0100
***************
*** 11,16 ****
--- 11,17 ----
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);
*** ../vim-9.0.1515/src/ops.c 2023-03-04 20:47:32.304617857 +0000
--- src/ops.c 2023-05-06 16:14:43.522945467 +0100
***************
*** 3701,3707 ****
ResetRedobuff();
else
{
! AppendToRedobuffLit(repeat_cmdline, -1);
AppendToRedobuff(NL_STR);
VIM_CLEAR(repeat_cmdline);
}
--- 3701,3707 ----
ResetRedobuff();
else
{
! AppendToRedobuffSpec(repeat_cmdline);
AppendToRedobuff(NL_STR);
VIM_CLEAR(repeat_cmdline);
}
*** ../vim-9.0.1515/src/testdir/test_mapping.vim 2023-04-16 17:17:33.052497158 +0100
--- src/testdir/test_mapping.vim 2023-05-06 16:14:43.526945461 +0100
***************
*** 1001,1010 ****
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)
--- 1001,1006 ----
***************
*** 1104,1114 ****
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
--- 1100,1105 ----
***************
*** 1495,1500 ****
--- 1486,1509 ----
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()
*** ../vim-9.0.1515/src/version.c 2023-05-06 14:08:10.143045044 +0100
--- src/version.c 2023-05-06 16:16:10.290851058 +0100
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1516,
/**/
--
A)bort, R)etry, D)o it right this time
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///