From b072f89d1e6169cd4c1a3fdb145d0e4985e9e2f4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 16 Feb 2026 06:51:03 +0800 Subject: [PATCH] vim-patch:9.2.0004: Changing hidden prompt buffer cancels :startinsert/:stopinsert (#37881) Problem: Changing hidden prompt buffer cancels :startinsert/:stopinsert (after 9.0.1439). Solution: Don't change mode for a prompt buffer in an autocommand window (zeertzjq). closes: vim/vim#19410 https://github.com/vim/vim/commit/8b81a6b6e1d514cf0544e0c6d12412ba813564b0 (cherry picked from commit 7d8653575f2a1170f0c7651f271c45a15a185d5e) --- src/nvim/autocmd.c | 8 ---- src/nvim/autocmd_defs.h | 1 - src/nvim/window.c | 8 +++- test/functional/legacy/prompt_buffer_spec.lua | 21 +++++++++- test/old/testdir/test_prompt_buffer.vim | 42 ++++++++++++++----- 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 0ab608ad31..8eb37b4bf6 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1283,7 +1283,6 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf) aco->save_curwin_handle = curwin->handle; aco->save_prevwin_handle = prevwin == NULL ? 0 : prevwin->handle; - aco->save_State = State; if (bt_prompt(curbuf)) { aco->save_prompt_insert = curbuf->b_prompt_insert; } @@ -1366,13 +1365,6 @@ void aucmd_restbuf(aco_save_T *aco) } win_found: curbuf->b_nwindows--; - const bool save_stop_insert_mode = stop_insert_mode; - // May need to stop Insert mode if we were in a prompt buffer. - leaving_window(curwin); - // Do not stop Insert mode when already in Insert mode before. - if (aco->save_State & MODE_INSERT) { - stop_insert_mode = save_stop_insert_mode; - } // Remove the window. win_remove(curwin, NULL); pmap_del(int)(&window_handles, curwin->handle, NULL); diff --git a/src/nvim/autocmd_defs.h b/src/nvim/autocmd_defs.h index 970aced506..00bf61ac89 100644 --- a/src/nvim/autocmd_defs.h +++ b/src/nvim/autocmd_defs.h @@ -22,7 +22,6 @@ typedef struct { char *tp_localdir; ///< saved value of tp_localdir char *globaldir; ///< saved value of globaldir bool save_VIsual_active; ///< saved VIsual_active - int save_State; ///< saved State int save_prompt_insert; ///< saved b_prompt_insert } aco_save_T; diff --git a/src/nvim/window.c b/src/nvim/window.c index 2b67617478..24c5309dcc 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2422,7 +2422,9 @@ void leaving_window(win_T *const win) FUNC_ATTR_NONNULL_ALL { // Only matters for a prompt window. - if (!bt_prompt(win->w_buffer)) { + // Don't do mode changes for a prompt buffer in an autocommand window, as + // it's only used temporarily during an autocommand. + if (!bt_prompt(win->w_buffer) || is_aucmd_win(win)) { return; } @@ -2449,7 +2451,9 @@ void entering_window(win_T *const win) FUNC_ATTR_NONNULL_ALL { // Only matters for a prompt window. - if (!bt_prompt(win->w_buffer)) { + // Don't do mode changes for a prompt buffer in an autocommand window, as + // it's only used temporarily during an autocommand. + if (!bt_prompt(win->w_buffer) || is_aucmd_win(win)) { return; } diff --git a/test/functional/legacy/prompt_buffer_spec.lua b/test/functional/legacy/prompt_buffer_spec.lua index 6a4d5fe7f7..45d11bc5eb 100644 --- a/test/functional/legacy/prompt_buffer_spec.lua +++ b/test/functional/legacy/prompt_buffer_spec.lua @@ -195,10 +195,18 @@ describe('prompt buffer', function() endfunc call prompt_setcallback(bufnr(), function('s:TextEntered')) - func DoAppend() + func DoAppend(cmd_before = '') + exe a:cmd_before call appendbufline('prompt', '$', 'Test') return '' endfunc + + autocmd User SwitchTabPages tabprevious | tabnext + func DoAutoAll(cmd_before = '') + exe a:cmd_before + doautoall User SwitchTabPages + return '' + endfunc ]]) feed('asomething') eq('something', api.nvim_get_var('entered')) @@ -212,6 +220,17 @@ describe('prompt buffer', function() eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) command('call DoAppend()') eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) + command("call DoAppend('stopinsert')") + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) + command("call DoAppend('startreplace')") + eq({ mode = 'R', blocking = false }, api.nvim_get_mode()) + feed('') + command('tabnew') + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) + command("call DoAutoAll('startinsert')") + eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) + command("call DoAutoAll('stopinsert')") + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) -- oldtest: Test_prompt_leave_modify_hidden() diff --git a/test/old/testdir/test_prompt_buffer.vim b/test/old/testdir/test_prompt_buffer.vim index 41e14ae427..44ae4ebaab 100644 --- a/test/old/testdir/test_prompt_buffer.vim +++ b/test/old/testdir/test_prompt_buffer.vim @@ -269,10 +269,18 @@ func Test_prompt_appending_while_hidden() endfunc call prompt_setcallback(bufnr(), function('s:TextEntered')) - func DoAppend() + func DoAppend(cmd_before = '') + exe a:cmd_before call appendbufline('prompt', '$', 'Test') return '' endfunc + + autocmd User SwitchTabPages tabprevious | tabnext + func DoAutoAll(cmd_before = '') + exe a:cmd_before + doautoall User SwitchTabPages + return '' + endfunc END call writefile(script, 'XpromptBuffer', 'D') @@ -283,18 +291,32 @@ func Test_prompt_appending_while_hidden() call TermWait(buf) call term_sendkeys(buf, "exit\") - call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_notmatch('-- .* --', term_getline(buf, 10))}) call term_sendkeys(buf, ":call DoAppend()\") - call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_notmatch('-- .* --', term_getline(buf, 10))}) call term_sendkeys(buf, "i") - call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) call term_sendkeys(buf, "\=DoAppend()\") - call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + + call term_sendkeys(buf, "\=DoAppend('stopinsert')\") + call WaitForAssert({-> assert_notmatch('-- .* --', term_getline(buf, 10))}) + + call term_sendkeys(buf, ":call DoAppend('startreplace')\") + call WaitForAssert({-> assert_match('^-- REPLACE --', term_getline(buf, 10))}) + + call term_sendkeys(buf, "\:tabnew\") + call WaitForAssert({-> assert_notmatch('-- .* --', term_getline(buf, 10))}) + + call term_sendkeys(buf, ":call DoAutoAll('startinsert')\") + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + + call term_sendkeys(buf, "\=DoAutoAll('stopinsert')\") + call WaitForAssert({-> assert_notmatch('-- .* --', term_getline(buf, 10))}) - call term_sendkeys(buf, "\") call StopVimInTerminal(buf) endfunc @@ -323,16 +345,16 @@ func Test_prompt_leave_modify_hidden() call TermWait(buf) call term_sendkeys(buf, "a") - call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) call term_sendkeys(buf, "w") - call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_notmatch('-- .* --', term_getline(buf, 10))}) call term_sendkeys(buf, "\w") - call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) call term_sendkeys(buf, "q") - call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_notmatch('-- .* --', term_getline(buf, 10))}) call term_sendkeys(buf, ":bwipe!\") call WaitForAssert({-> assert_equal('Leave', term_getline(buf, 2))})