aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-12-09 06:35:29 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-12-09 06:55:15 +0800
commit70d6c335b17cf166760457e3673aa61098ef0e66 (patch)
tree3d91c89cff300a9f2717e0e0d36f8ef7369fce12
parentea39fc2cadc1d87109216da354a876427eeea31a (diff)
downloadrneovim-70d6c335b17cf166760457e3673aa61098ef0e66.tar.gz
rneovim-70d6c335b17cf166760457e3673aa61098ef0e66.tar.bz2
rneovim-70d6c335b17cf166760457e3673aa61098ef0e66.zip
vim-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 vim/vim#11674) https://github.com/vim/vim/commit/3f8f82772313af9f2417b06651f30988b63e1c96 Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--src/nvim/edit.c6
-rw-r--r--src/nvim/testdir/test_undo.vim29
-rw-r--r--test/functional/editor/undo_spec.lua35
3 files changed, 70 insertions, 0 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index ac2973ba68..09836e747f 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -908,6 +908,12 @@ check_pum:
}
pum_want.active = false;
}
+
+ if (curbuf->b_u_synced) {
+ // The K_EVENT, K_COMMAND, or K_LUA caused undo to be synced.
+ // Need to save the line for undo before inserting the next char.
+ ins_need_undo = true;
+ }
break;
case K_HOME: // <Home>
diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim
index eb47af08d7..ee8b52caaf 100644
--- a/src/nvim/testdir/test_undo.vim
+++ b/src/nvim/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
@@ -773,4 +776,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
diff --git a/test/functional/editor/undo_spec.lua b/test/functional/editor/undo_spec.lua
index a041428cdc..6f9c4506fc 100644
--- a/test/functional/editor/undo_spec.lua
+++ b/test/functional/editor/undo_spec.lua
@@ -9,6 +9,7 @@ local feed = helpers.feed
local feed_command = helpers.feed_command
local insert = helpers.insert
local funcs = helpers.funcs
+local exec = helpers.exec
local function lastmessage()
local messages = funcs.split(funcs.execute('messages'), '\n')
@@ -67,6 +68,40 @@ describe('u CTRL-R g- g+', function()
undo_and_redo(4, 'u', '<C-r>', '1')
undo_and_redo(4, 'g-', 'g+', '1')
end)
+
+ describe('undo works correctly when writing in Insert mode', function()
+ before_each(function()
+ exec([[
+ edit Xtestfile.txt
+ set undolevels=100 undofile
+ write
+ ]])
+ end)
+
+ after_each(function()
+ command('bwipe!')
+ os.remove('Xtestfile.txt')
+ os.remove('Xtestfile.txt.un~')
+ end)
+
+ -- oldtest: Test_undo_after_write()
+ it('using <Cmd> mapping', function()
+ command('imap . <Cmd>write<CR>')
+ feed('Otest.<CR>boo!!!<Esc>')
+ expect([[
+ test
+ boo!!!
+ ]])
+
+ feed('u')
+ expect([[
+ test
+ ]])
+
+ feed('u')
+ expect('')
+ end)
+ end)
end)
describe(':undo! command', function()