neovim

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

commit b4e602dde544d2b18bc7813415565fbe6ab1041b
parent 933b99a2b1c95c877b67eb4e0d35fd8dd6b0d532
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Tue, 20 Jan 2026 06:24:22 +0800

vim-patch:9.1.2095: :wqall! doesn't quit when using :quit in BufWritePost

Problem:  :wqall! doesn't quit when using :quit in BufWritePost
          (after 8.0.1190).
Solution: Restore old value of "exiting" when calling not_exiting()
          instead of always resetting it to FALSE (zeertzjq).

related: vim/vim#2205
closes:  vim/vim#19212

https://github.com/vim/vim/commit/e803ad1c56f50a4ffdfe8beb478795aa5201475e

Diffstat:
Msrc/nvim/ex_cmds.c | 3++-
Msrc/nvim/ex_docmd.c | 22++++++++++++----------
Mtest/old/testdir/test_exit.vim | 14++++++++++++++
3 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c @@ -2095,6 +2095,7 @@ void do_wqall(exarg_T *eap) { int error = 0; int save_forceit = eap->forceit; + bool save_exiting = exiting; if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall) { if (before_quit_all(eap) == FAIL) { @@ -2147,7 +2148,7 @@ void do_wqall(exarg_T *eap) if (!error) { getout(0); // exit Vim } - not_exiting(); + not_exiting(save_exiting); } } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c @@ -4779,9 +4779,9 @@ static void ex_highlight(exarg_T *eap) /// Call this function if we thought we were going to exit, but we won't /// (because of an error). May need to restore the terminal mode. -void not_exiting(void) +void not_exiting(bool save_exiting) { - exiting = false; + exiting = save_exiting; } /// Call this function if we thought we were going to restart, but we won't @@ -4858,6 +4858,7 @@ static void ex_quit(exarg_T *eap) return; } + bool save_exiting = exiting; // If there is only one relevant window we will exit. if (check_more(false, eap->forceit) == OK && only_one_window()) { exiting = true; @@ -4868,7 +4869,7 @@ static void ex_quit(exarg_T *eap) | CCGD_EXCMD)) || check_more(true, eap->forceit) == FAIL || (only_one_window() && check_changed_any(eap->forceit, true))) { - not_exiting(); + not_exiting(save_exiting); } else { // quit last window // Note: only_one_window() returns true, even so a help window is @@ -4879,7 +4880,7 @@ static void ex_quit(exarg_T *eap) if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0)) { getout(0); } - not_exiting(); + not_exiting(save_exiting); // close window; may free buffer win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit, eap->forceit); } @@ -4925,12 +4926,12 @@ static void ex_quitall(exarg_T *eap) if (before_quit_all(eap) == FAIL) { return; } + bool save_exiting = exiting; exiting = true; - if (!eap->forceit && check_changed_any(false, false)) { - not_exiting(); - return; + if (eap->forceit || !check_changed_any(false, false)) { + getout(0); } - getout(0); + not_exiting(save_exiting); } /// ":restart": restart the Nvim server (using ":qall!"). @@ -5292,6 +5293,7 @@ static void ex_exit(exarg_T *eap) return; } + bool save_exiting = exiting; // we plan to exit if there is only one relevant window if (check_more(false, eap->forceit) == OK && only_one_window()) { exiting = true; @@ -5303,13 +5305,13 @@ static void ex_exit(exarg_T *eap) || before_quit_autocmds(curwin, false, eap->forceit) || check_more(true, eap->forceit) == FAIL || (only_one_window() && check_changed_any(eap->forceit, false))) { - not_exiting(); + not_exiting(save_exiting); } else { if (only_one_window()) { // quit last window, exit Vim getout(0); } - not_exiting(); + not_exiting(save_exiting); // Quit current window, may free the buffer. win_close(curwin, !buf_hide(curwin->w_buffer), eap->forceit); } diff --git a/test/old/testdir/test_exit.vim b/test/old/testdir/test_exit.vim @@ -93,6 +93,20 @@ func Test_exiting() call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout')) endif call delete('Xtestout') + + " Test using :quit in BufWritePost during :wqall + let after =<< trim [CODE] + botright new Xwritebuf + call setline(1, 'SHOULD BE WRITTEN') + autocmd BufWritePost Xwritebuf 1quit + wqall + call setline(1, 'NOT REACHED') | write | qall + [CODE] + + if RunVim([], after, '') + call assert_equal(['SHOULD BE WRITTEN'], readfile('Xwritebuf')) + endif + call delete('Xwritebuf') endfunc " Test for getting the Vim exit code from v:exiting