aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ops.c12
-rw-r--r--src/nvim/testdir/test_normal.vim33
-rw-r--r--test/functional/ui/mode_spec.lua20
3 files changed, 61 insertions, 4 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index f61c978f3c..f1814291b8 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2483,8 +2483,14 @@ int op_change(oparg_T *oap)
fix_indent();
}
+ // Reset finish_op now, don't want it set inside edit().
+ const bool save_finish_op = finish_op;
+ finish_op = false;
+
retval = edit(NUL, false, (linenr_T)1);
+ finish_op = save_finish_op;
+
// In Visual block mode, handle copying the new text to all lines of the
// block.
// Don't repeat the insert when Insert mode ended with CTRL-C.
@@ -5635,8 +5641,6 @@ bool set_ref_in_opfunc(int copyID)
static void op_function(const oparg_T *oap)
FUNC_ATTR_NONNULL_ALL
{
- const TriState save_virtual_op = virtual_op;
- const bool save_finish_op = finish_op;
const pos_T orig_start = curbuf->b_op_start;
const pos_T orig_end = curbuf->b_op_end;
@@ -5663,9 +5667,11 @@ static void op_function(const oparg_T *oap)
// Reset virtual_op so that 'virtualedit' can be changed in the
// function.
+ const TriState save_virtual_op = virtual_op;
virtual_op = kNone;
// Reset finish_op so that mode() returns the right value.
+ const bool save_finish_op = finish_op;
finish_op = false;
typval_T rettv;
@@ -6205,8 +6211,6 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
// Restore linebreak, so that when the user edits it looks as before.
restore_lbr(lbr_saved);
- // Reset finish_op now, don't want it set inside edit().
- finish_op = false;
if (op_change(oap)) { // will call edit()
cap->retval |= CA_COMMAND_BUSY;
}
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 0d75644920..e5756bd505 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -3713,4 +3713,37 @@ func Test_normal_count_out_of_range()
bwipe!
endfunc
+" Test that mouse shape is restored to Normal mode after failed "c" operation.
+func Test_mouse_shape_after_failed_change()
+ CheckFeature mouseshape
+ CheckCanRunGui
+
+ let lines =<< trim END
+ set mouseshape+=o:busy
+ setlocal nomodifiable
+ let g:mouse_shapes = []
+
+ func SaveMouseShape(timer)
+ let g:mouse_shapes += [getmouseshape()]
+ endfunc
+
+ func SaveAndQuit(timer)
+ call writefile(g:mouse_shapes, 'Xmouseshapes')
+ quit
+ endfunc
+
+ call timer_start(50, {_ -> feedkeys('c')})
+ call timer_start(100, 'SaveMouseShape')
+ call timer_start(150, {_ -> feedkeys('c')})
+ call timer_start(200, 'SaveMouseShape')
+ call timer_start(250, 'SaveAndQuit')
+ END
+ call writefile(lines, 'Xmouseshape.vim', 'D')
+ call RunVim([], [], "-g -S Xmouseshape.vim")
+ sleep 300m
+ call assert_equal(['busy', 'arrow'], readfile('Xmouseshapes'))
+
+ call delete('Xmouseshapes')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/functional/ui/mode_spec.lua b/test/functional/ui/mode_spec.lua
index 9390f268b3..cf4eb034e0 100644
--- a/test/functional/ui/mode_spec.lua
+++ b/test/functional/ui/mode_spec.lua
@@ -17,6 +17,7 @@ describe('ui mode_change event', function()
[1] = {bold=true, reverse=true},
[2] = {bold=true},
[3] = {reverse=true},
+ [4] = {background=Screen.colors.Red, foreground=Screen.colors.White}, -- ErrorMsg
})
end)
@@ -43,6 +44,25 @@ describe('ui mode_change event', function()
{0:~ }|
|
]], mode="normal"}
+
+ screen:try_resize(50, 4)
+ command('set nomodifiable')
+
+ feed('c')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]], mode="operator"}
+
+ feed('c')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {4:E21: Cannot make changes, 'modifiable' is off} |
+ ]], mode="normal"}
end)
it('works in insert mode', function()