From e8e76798bb2e3900878c453cd3034f608336050a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 15 Feb 2026 11:37:13 +0800 Subject: [PATCH] Changing hidden prompt buffer cancels :startinsert/:stopinsert 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. --- src/autocmd.c | 9 ------- src/structs.h | 1 - src/testdir/test_prompt_buffer.vim | 42 +++++++++++++++++++++++------- src/window.c | 8 ++++-- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/autocmd.c b/src/autocmd.c index 7c0cc50a7f7347..acf7bb140ff8a7 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -1627,7 +1627,6 @@ aucmd_prepbuf( aco->save_curwin_id = curwin->w_id; aco->save_prevwin_id = prevwin == NULL ? 0 : prevwin->w_id; - aco->save_State = State; #ifdef FEAT_JOB_CHANNEL if (bt_prompt(curbuf)) aco->save_prompt_insert = curbuf->b_prompt_insert; @@ -1727,14 +1726,6 @@ aucmd_restbuf( } win_found: --curbuf->b_nwindows; -#ifdef FEAT_JOB_CHANNEL - int 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; -#endif // Remove the window and frame from the tree of frames. (void)winframe_remove(curwin, &dummy, NULL, NULL); win_remove(curwin, NULL); diff --git a/src/structs.h b/src/structs.h index 83d35c53f3950f..df296b35d3e1aa 100644 --- a/src/structs.h +++ b/src/structs.h @@ -4575,7 +4575,6 @@ typedef struct char_u *tp_localdir; // saved value of tp_localdir char_u *globaldir; // saved value of globaldir int save_VIsual_active; // saved VIsual_active - int save_State; // saved State #ifdef FEAT_JOB_CHANNEL int save_prompt_insert; // saved b_prompt_insert #endif diff --git a/src/testdir/test_prompt_buffer.vim b/src/testdir/test_prompt_buffer.vim index 72882e29e03984..357492b408dbd6 100644 --- a/src/testdir/test_prompt_buffer.vim +++ b/src/testdir/test_prompt_buffer.vim @@ -266,10 +266,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') @@ -280,18 +288,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 @@ -320,16 +342,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))}) diff --git a/src/window.c b/src/window.c index 4573591261d6b2..62089bdec9c908 100644 --- a/src/window.c +++ b/src/window.c @@ -2436,7 +2436,9 @@ win_equal_rec( leaving_window(win_T *win) { // 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; // When leaving a prompt window stop Insert mode and perhaps restart @@ -2461,7 +2463,9 @@ leaving_window(win_T *win) entering_window(win_T *win) { // 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; // When switching to a prompt buffer that was in Insert mode, don't stop