patch 9.2.0384: stale Insstart after <Cmd> cursor move breaks undo

Problem:  A <Cmd> command executed from Insert mode can sync undo and
          move the cursor before the next edit. stop_arrow() saved the
          new cursor line for undo, but left Insstart at the previous
          insertion point. A line-start backspace could then delete
          lines above the saved line without saving the joined range,
          leaving a pending undo entry whose bottom resolved above
          its top and raising E340.
Solution: Update Insstart and Insstart_textlen after the pending undo
          save so the next edit starts from the command-updated cursor
          position (Jaehwang Jung).

closes: #20031

AI-assisted: Codex

Signed-off-by: Jaehwang Jung <tomtomjhj@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Jaehwang Jung
2026-04-21 19:21:24 +00:00
committed by Christian Brabandt
parent 405e2fb6d5
commit d4fb31762e
3 changed files with 21 additions and 0 deletions
+5
View File
@@ -2502,7 +2502,12 @@ stop_arrow(void)
else if (ins_need_undo)
{
if (u_save_cursor() == OK)
{
// A command or event may have moved the cursor after syncing undo.
Insstart = curwin->w_cursor;
Insstart_textlen = (colnr_T)linetabsize_str(ml_get_curline());
ins_need_undo = FALSE;
}
}
#ifdef FEAT_FOLDING
+14
View File
@@ -924,5 +924,19 @@ func Test_restore_cursor_position_after_undo()
bw!
endfunc
func Test_undo_line_backspace_after_insert_cmd_cursor_movement()
new
setlocal backspace=eol undolevels=100
call setline(1, ['', '', 'abc', 'def'])
call cursor(4, 1)
let v:errmsg = ''
call feedkeys("i\<Cmd>setlocal undolevels=101 | call cursor(3, 1)\<CR>"
\ .. "\<BS>\<BS>\<Esc>u", 'xt')
call assert_equal('', v:errmsg)
call assert_equal(['', '', 'abc', 'def'], getline(1, '$'))
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+2
View File
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
384,
/**/
383,
/**/