# HG changeset patch # User Bram Moolenaar # Date 1637591408 -3600 # Node ID 9a8e9383e4cdefe9d6e1cee893a4e8551c37c9c9 # Parent b0c79beaf975e215790881d8c1f4562aa57882bc patch 8.2.3644: count for 'operatorfunc' in Visual mode is not redone Commit: https://github.com/vim/vim/commit/2228cd72cf7c6f326e4e41179e88d37595ca4abc Author: Bram Moolenaar Date: Mon Nov 22 14:16:08 2021 +0000 patch 8.2.3644: count for 'operatorfunc' in Visual mode is not redone Problem: Count for 'operatorfunc' in Visual mode is not redone. Solution: Add the count to the redo buffer. (closes https://github.com/vim/vim/issues/9174) diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -380,8 +380,10 @@ static const struct nv_cmd // Number of commands in nv_cmds[]. #define NV_CMDS_SIZE ARRAY_LENGTH(nv_cmds) +#ifndef PROTO // cproto doesn't like this // Sorted index of commands in nv_cmds[]. static short nv_cmd_idx[NV_CMDS_SIZE]; +#endif // The highest index for which // nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char] @@ -1697,19 +1699,37 @@ prep_redo( int cmd4, int cmd5) { + prep_redo_num2(regname, num, cmd1, cmd2, 0L, cmd3, cmd4, cmd5); +} + +/* + * Prepare for redo of any command with extra count after "cmd2". + */ + void +prep_redo_num2( + int regname, + long num1, + int cmd1, + int cmd2, + long num2, + int cmd3, + int cmd4, + int cmd5) +{ ResetRedobuff(); if (regname != 0) // yank from specified buffer { AppendCharToRedobuff('"'); AppendCharToRedobuff(regname); } - if (num) - AppendNumberToRedobuff(num); - + if (num1 != 0) + AppendNumberToRedobuff(num1); if (cmd1 != NUL) AppendCharToRedobuff(cmd1); if (cmd2 != NUL) AppendCharToRedobuff(cmd2); + if (num2 != 0) + AppendNumberToRedobuff(num2); if (cmd3 != NUL) AppendCharToRedobuff(cmd3); if (cmd4 != NUL) diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -3764,6 +3764,8 @@ do_pending_operator(cmdarg_T *cap, int o oap->motion_force, cap->cmdchar, cap->nchar); else if (cap->cmdchar != ':' && cap->cmdchar != K_COMMAND) { + int opchar = get_op_char(oap->op_type); + int extra_opchar = get_extra_op_char(oap->op_type); int nchar = oap->op_type == OP_REPLACE ? cap->nchar : NUL; // reverse what nv_replace() did @@ -3771,10 +3773,14 @@ do_pending_operator(cmdarg_T *cap, int o nchar = CAR; else if (nchar == REPLACE_NL_NCHAR) nchar = NL; - prep_redo(oap->regname, 0L, NUL, 'v', - get_op_char(oap->op_type), - get_extra_op_char(oap->op_type), - nchar); + + if (opchar == 'g' && extra_opchar == '@') + // also repeat the count for 'operatorfunc' + prep_redo_num2(oap->regname, 0L, NUL, 'v', + cap->count0, opchar, extra_opchar, nchar); + else + prep_redo(oap->regname, 0L, NUL, 'v', + opchar, extra_opchar, nchar); } if (!redo_VIsual_busy) { diff --git a/src/proto/normal.pro b/src/proto/normal.pro --- a/src/proto/normal.pro +++ b/src/proto/normal.pro @@ -10,6 +10,7 @@ void restore_visual_mode(void); int find_ident_under_cursor(char_u **text, int find_type); int find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char_u **text, int *textcol, int find_type); void prep_redo(int regname, long num, int cmd1, int cmd2, int cmd3, int cmd4, int cmd5); +void prep_redo_num2(int regname, long num1, int cmd1, int cmd2, long num2, int cmd3, int cmd4, int cmd5); void clearop(oparg_T *oap); void clearopbeep(oparg_T *oap); void may_clear_cmdline(void); 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 @@ -363,7 +363,7 @@ func Test_normal08_fold() bw! endfunc -func Test_normal09_operatorfunc() +func Test_normal09a_operatorfunc() " Test operatorfunc call Setup_NewWindow() " Add some spaces for counting @@ -457,7 +457,7 @@ func Test_normal09_operatorfunc() bw! endfunc -func Test_normal09a_operatorfunc() +func Test_normal09b_operatorfunc() " Test operatorfunc call Setup_NewWindow() " Add some spaces for counting @@ -484,6 +484,26 @@ func Test_normal09a_operatorfunc() unlet! g:opt endfunc +func OperatorfuncRedo(_) + let g:opfunc_count = v:count +endfunc + +func Test_normal09c_operatorfunc() + " Test redoing operatorfunc + new + call setline(1, 'some text') + set operatorfunc=OperatorfuncRedo + normal v3g@ + call assert_equal(3, g:opfunc_count) + let g:opfunc_count = 0 + normal . + call assert_equal(3, g:opfunc_count) + + bw! + unlet g:opfunc_count + set operatorfunc= +endfunc + func Test_normal10_expand() " Test for expand() 10new diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3644, +/**/ 3643, /**/ 3642,