changeset 31406:627d4f236ac8 v9.0.1036

patch 9.0.1036: undo misbehaves when writing from an insert mode mapping Commit: https://github.com/vim/vim/commit/3f8f82772313af9f2417b06651f30988b63e1c96 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Dec 8 21:49:35 2022 +0000 patch 9.0.1036: undo misbehaves when writing from an insert mode mapping Problem: Undo misbehaves when writing from an insert mode mapping. Solution: Sync undo when writing. (closes https://github.com/vim/vim/issues/11674)
author Bram Moolenaar <Bram@vim.org>
date Thu, 08 Dec 2022 23:00:03 +0100
parents a49b1c42f649
children 9b7fe85ab47f
files src/edit.c src/testdir/dumps/Test_undo_after_write_1.dump src/testdir/dumps/Test_undo_after_write_2.dump src/testdir/dumps/Test_undo_after_write_2.vim src/testdir/test_undo.vim src/version.c
diffstat 6 files changed, 56 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/edit.c
+++ b/src/edit.c
@@ -1049,12 +1049,19 @@ doESCkey:
 
 	case K_COMMAND:		    // <Cmd>command<CR>
 	case K_SCRIPT_COMMAND:	    // <ScriptCmd>command<CR>
-	    do_cmdkey_command(c, 0);
+	    {
+		do_cmdkey_command(c, 0);
+
 #ifdef FEAT_TERMINAL
-	    if (term_use_loop())
-		// Started a terminal that gets the input, exit Insert mode.
-		goto doESCkey;
+		if (term_use_loop())
+		    // Started a terminal that gets the input, exit Insert mode.
+		    goto doESCkey;
 #endif
+		if (curbuf->b_u_synced)
+		    // The command caused undo to be synced.  Need to save the
+		    // line for undo before inserting the next char.
+		    ins_need_undo = TRUE;
+	    }
 	    break;
 
 	case K_CURSORHOLD:	// Didn't type something for a while.
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_undo_after_write_1.dump
@@ -0,0 +1,6 @@
+|t+0&#ffffff0|e|s>t| @70
+@75
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|1+0#0000000&| |l|i|n|e| |l|e|s@1|;| |b|e|f|o|r|e| |#|2| @1|0| |s|e|c|o|n|d|s| |a|g|o| @19|1|,|4| @10|A|l@1| 
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_undo_after_write_2.dump
@@ -0,0 +1,6 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|2+0#0000000&| |f|e|w|e|r| |l|i|n|e|s|;| |b|e|f|o|r|e| |#|1| @1|1| |s|e|c|o|n|d| |a|g|o| @18|0|,|0|-|1| @8|A|l@1| 
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_undo_after_write_2.vim
@@ -0,0 +1,2 @@
+" Filter that changes the "1 second ago" message to "0 seconds ago".
+6s+|1| |s|e|c|o|n|d| |a|g|o| @18|+|0| |s|e|c|o|n|d|s| |a|g|o| @17|+e
--- a/src/testdir/test_undo.vim
+++ b/src/testdir/test_undo.vim
@@ -3,6 +3,9 @@
 " undo-able pieces.  Do that by setting 'undolevels'.
 " Also tests :earlier and :later.
 
+source check.vim
+source screendump.vim
+
 func Test_undotree()
   new
 
@@ -775,4 +778,30 @@ func Test_undo_mark()
   bwipe!
 endfunc
 
+func Test_undo_after_write()
+  " use a terminal to make undo work like when text is typed
+  CheckRunVimInTerminal
+
+  let lines =<< trim END
+      edit Xtestfile.txt
+      set undolevels=100 undofile
+      imap . <Cmd>write<CR>
+      write
+  END
+  call writefile(lines, 'Xtest_undo_after_write', 'D')
+  let buf = RunVimInTerminal('-S Xtest_undo_after_write', #{rows: 6})
+
+  call term_sendkeys(buf, "Otest.\<CR>boo!!!\<Esc>")
+  sleep 100m
+  call term_sendkeys(buf, "u")
+  call VerifyScreenDump(buf, 'Test_undo_after_write_1', {})
+
+  call term_sendkeys(buf, "u")
+  call VerifyScreenDump(buf, 'Test_undo_after_write_2', {})
+
+  call StopVimInTerminal(buf)
+  call delete('Xtestfile.txt')
+endfunc
+
+
 " vim: shiftwidth=2 sts=2 expandtab
--- 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 */
 /**/
+    1036,
+/**/
     1035,
 /**/
     1034,