diff --git a/src/nvim/normal.c b/src/nvim/normal.c index fd8c6d9406..3d4eef6f8e 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -544,6 +544,7 @@ static void normal_prepare(NormalState *s) } may_trigger_modechanged(); + s->set_prevcount = false; // When not finishing an operator and no register name typed, reset the count. if (!finish_op && !s->oa.regname) { s->ca.opcount = 0; @@ -964,6 +965,8 @@ static bool normal_get_command_count(NormalState *s) static void normal_finish_command(NormalState *s) { + bool did_visual_op = false; + if (s->command_finished) { goto normal_end; } @@ -983,11 +986,13 @@ static void normal_finish_command(NormalState *s) s->old_mapped_len = typebuf_maplen(); } - const bool prev_VIsual_active = VIsual_active; - // If an operation is pending, handle it. But not for K_IGNORE or // K_MOUSEMOVE. if (s->ca.cmdchar != K_IGNORE && s->ca.cmdchar != K_MOUSEMOVE) { + did_visual_op = VIsual_active && s->oa.op_type != OP_NOP + // For OP_COLON, do_pending_operator() stuffs ':' into + // the read buffer, which isn't executed immediately. + && s->oa.op_type != OP_COLON; do_pending_operator(&s->ca, s->old_col, false); } @@ -1002,7 +1007,7 @@ normal_end: msg_nowait = false; - if (finish_op || prev_VIsual_active) { + if (finish_op || did_visual_op) { set_reg_var(get_default_register_name()); } diff --git a/test/old/testdir/test_registers.vim b/test/old/testdir/test_registers.vim index b5554fec1e..7ecac84d12 100644 --- a/test/old/testdir/test_registers.vim +++ b/test/old/testdir/test_registers.vim @@ -671,7 +671,9 @@ func Test_v_register() exec 'normal! "' .. v:register .. 'P' endfunc nnoremap (test) :call s:Put() + xnoremap (test) :call s:Put() nmap S (test) + xmap S (test) let @z = "testz\n" let @" = "test@\n" @@ -689,15 +691,41 @@ func Test_v_register() let s:register = '' call feedkeys('"zS', 'mx') call assert_equal('z', s:register) + call assert_equal('testz', getline('.')) let s:register = '' call feedkeys('"zSS', 'mx') call assert_equal('"', s:register) + call assert_equal('test@', getline('.')) + + let s:register = '' + call feedkeys("\"z\S", 'mx') + call assert_equal('z', s:register) + call assert_equal('testz', getline('.')) let s:register = '' call feedkeys('"_S', 'mx') call assert_equal('_', s:register) + let s:register = '' + call feedkeys('V"zS', 'mx') + call assert_equal('z', s:register) + call assert_equal('testz', getline('.')) + + let s:register = '' + call feedkeys('V"zSS', 'mx') + call assert_equal('"', s:register) + call assert_equal('test@', getline('.')) + + let s:register = '' + call feedkeys("V\"z\S", 'mx') + call assert_equal('z', s:register) + call assert_equal('testz', getline('.')) + + let s:register = '' + call feedkeys('V"_S', 'mx') + call assert_equal('_', s:register) + let s:register = '' normal "_ddS call assert_equal('"', s:register) " fails before 8.2.0929