# HG changeset patch # User Bram Moolenaar # Date 1683477905 -7200 # Node ID 89679a3f2e0918051264fd6848c695b454eb27c1 # Parent a40f038ce8b59c6e132b341b9748a28671004d7f patch 9.0.1521: failing redo of command with control characters Commit: https://github.com/vim/vim/commit/30b6d6104c3d541c41c868989c020b743e01af08 Author: zeertzjq Date: Sun May 7 17:39:23 2023 +0100 patch 9.0.1521: failing redo of command with control characters Problem: Failing redo of command with control characters. Solution: Use AppendToRedobuffLit() for colon commands. (closes https://github.com/vim/vim/issues/12354) diff --git a/src/getchar.c b/src/getchar.c --- a/src/getchar.c +++ b/src/getchar.c @@ -43,8 +43,8 @@ static buffheader_T recordbuff = {{NULL, static int typeahead_char = 0; // typeahead char that's not flushed /* - * when block_redo is TRUE redo buffer will not be changed - * used by edit() to repeat insertions and 'V' command for redoing + * When block_redo is TRUE the redo buffer will not be changed. + * Used by edit() to repeat insertions. */ static int block_redo = FALSE; @@ -609,11 +609,14 @@ AppendToRedobuffLit( void AppendToRedobuffSpec(char_u *s) { + if (block_redo) + return; + while (*s != NUL) { if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) { - // insert special key literally + // Insert special key literally. add_buff(&redobuff, s, 3L); s += 3; } diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -3701,7 +3701,10 @@ do_pending_operator(cmdarg_T *cap, int o ResetRedobuff(); else { - AppendToRedobuffSpec(repeat_cmdline); + if (cap->cmdchar == ':') + AppendToRedobuffLit(repeat_cmdline, -1); + else + AppendToRedobuffSpec(repeat_cmdline); AppendToRedobuff(NL_STR); VIM_CLEAR(repeat_cmdline); } diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -3635,11 +3635,32 @@ func Test_horiz_motion() bwipe! endfunc -" Test for using a : command in operator pending mode +" Test for using a ":" command in operator pending mode func Test_normal_colon_op() new call setline(1, ['one', 'two']) call assert_beeps("normal! Gc:d\") + call assert_equal(['one'], getline(1, '$')) + + call setline(1, ['one…two…three!']) + normal! $ + " Using ":" as a movement is characterwise exclusive + call feedkeys("d:normal! F…\", 'xt') + call assert_equal(['one…two!'], getline(1, '$')) + " Check that redoing a command with 0x80 bytes works + call feedkeys('.', 'xt') + call assert_equal(['one!'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three', 'four', 'five']) + " Add this to the command history + call feedkeys(":normal! G0\", 'xt') + " Use :normal! with control characters in operator pending mode + call feedkeys("d:normal! \\\\\", 'xt') + call assert_equal(['one', 'two', 'five'], getline(1, '$')) + " Check that redoing a command with control characters works + call feedkeys('.', 'xt') + call assert_equal(['five'], getline(1, '$')) + bwipe! endfunc diff --git a/src/version.c b/src/version.c --- 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 */ /**/ + 1521, +/**/ 1520, /**/ 1519,