# HG changeset patch # User Bram Moolenaar # Date 1670536803 -3600 # Node ID 627d4f236ac8074cf7c0c76daa69b63352d54234 # Parent a49b1c42f64990856f766d0b78874bb3a8238520 patch 9.0.1036: undo misbehaves when writing from an insert mode mapping Commit: https://github.com/vim/vim/commit/3f8f82772313af9f2417b06651f30988b63e1c96 Author: Bram Moolenaar 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) diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -1049,12 +1049,19 @@ doESCkey: case K_COMMAND: // command case K_SCRIPT_COMMAND: // command - 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. diff --git a/src/testdir/dumps/Test_undo_after_write_1.dump b/src/testdir/dumps/Test_undo_after_write_1.dump 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| diff --git a/src/testdir/dumps/Test_undo_after_write_2.dump b/src/testdir/dumps/Test_undo_after_write_2.dump 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| diff --git a/src/testdir/dumps/Test_undo_after_write_2.vim b/src/testdir/dumps/Test_undo_after_write_2.vim 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 diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim --- 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 . write + 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.\boo!!!\") + 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 diff --git a/src/version.c b/src/version.c --- 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,