neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 63689deb45737925cc0d5f9b09a6466b6e536bcc
parent 921752d3e28547c293128aaf02a7e8ceb6c043fb
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Thu, 24 Apr 2025 07:35:11 +0800

vim-patch:9.1.1337: Undo corrupted with 'completeopt' "preinsert" when switching buffer (#33600)

Problem:  Undo corrupted with 'completeopt' "preinsert" when switching
          buffer or window.
Solution: Do not delete preinsert text when switching buffer or window.
          (zeertzjq)

related: neovim/neovim#33581
closes: vim/vim#17193

https://github.com/vim/vim/commit/1343681aba56d49c16d3070615b8ece7f8b0d1bd
Diffstat:
Msrc/nvim/insexpand.c | 3++-
Mtest/old/testdir/test_ins_complete.vim | 43++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c @@ -2334,9 +2334,10 @@ static bool set_ctrl_x_mode(const int c) static bool ins_compl_stop(const int c, const int prev_mode, bool retval) { // Remove pre-inserted text when present. - if (ins_compl_preinsert_effect()) { + if (ins_compl_preinsert_effect() && ins_compl_win_active(curwin)) { ins_compl_delete(false); } + // Get here when we have finished typing a sequence of ^N and // ^P or other completion characters in CTRL-X mode. Free up // memory that was used, and make sure we can redo the insert. diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim @@ -3223,7 +3223,7 @@ func Test_complete_info_completed() set cot& endfunc -function Test_completeopt_preinsert() +func Test_completeopt_preinsert() func Omni_test(findstart, base) if a:findstart return col(".") @@ -3363,6 +3363,47 @@ function Test_completeopt_preinsert() call assert_equal(4, g:col) call assert_equal("wp.", getline('.')) + %delete _ + let &l:undolevels = &l:undolevels + normal! ifoo + let &l:undolevels = &l:undolevels + normal! obar + let &l:undolevels = &l:undolevels + normal! obaz + let &l:undolevels = &l:undolevels + + func CheckUndo() + let g:errmsg = '' + call assert_equal(['foo', 'bar', 'baz'], getline(1, '$')) + undo + call assert_equal(['foo', 'bar'], getline(1, '$')) + undo + call assert_equal(['foo'], getline(1, '$')) + undo + call assert_equal([''], getline(1, '$')) + later 3 + call assert_equal(['foo', 'bar', 'baz'], getline(1, '$')) + call assert_equal('', v:errmsg) + endfunc + + " Check that switching buffer with "preinsert" doesn't corrupt undo. + new + setlocal bufhidden=wipe + inoremap <buffer> <F2> <Cmd>enew!<CR> + call feedkeys("i\<C-X>\<C-O>\<F2>\<Esc>", 'tx') + bwipe! + call CheckUndo() + + " Check that closing window with "preinsert" doesn't corrupt undo. + new + setlocal bufhidden=wipe + inoremap <buffer> <F2> <Cmd>close!<CR> + call feedkeys("i\<C-X>\<C-O>\<F2>\<Esc>", 'tx') + call CheckUndo() + + %delete _ + delfunc CheckUndo + bw! set cot& set omnifunc&