neovim

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

commit 681d00654998baf2a743602e513062cf876f107b
parent e002e4d7fceeac91adb57bf00bb23e383447c99f
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Fri,  9 Jan 2026 07:36:47 +0800

vim-patch:9.1.2066: :wqall! doesn't close a terminal like :qall! does (#37314)

Problem:  :wqall! doesn't close a terminal buffer like :qall! does
          (after 8.0.1525).
Solution: Check eap->forceit (zeertzjq).

Ref: https://github.com/vim/vim/issues/2654#issuecomment-366803932

related: vim/vim#2654
related: neovim/neovim#14061
closes:  vim/vim#19129

https://github.com/vim/vim/commit/d8558fdf4f2758163218289637e82c3ae2d617ec
Diffstat:
Msrc/nvim/buffer.c | 21++++++++++++++++-----
Msrc/nvim/errors.h | 5+++++
Msrc/nvim/ex_cmds.c | 4++--
Mtest/functional/terminal/buffer_spec.lua | 6+++++-
4 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c @@ -1363,7 +1363,7 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags) return FAIL; } } else { - semsg(_("E89: No write since last change for buffer %d (add ! to override)"), + semsg(_(e_no_write_since_last_change_for_buffer_nr_add_bang_to_override), buf->b_fnum); return FAIL; } @@ -1819,13 +1819,24 @@ void do_autochdir(void) } } +void no_write_message_buf(buf_T *buf) +{ + if (buf->terminal + && channel_job_running((uint64_t)buf->b_p_channel)) { + emsg(_(e_job_still_running_add_bang_to_end_the_job)); + } else { + semsg(_(e_no_write_since_last_change_for_buffer_nr_add_bang_to_override), + buf->b_fnum); + } +} + void no_write_message(void) { if (curbuf->terminal && channel_job_running((uint64_t)curbuf->b_p_channel)) { - emsg(_("E948: Job still running (add ! to end the job)")); + emsg(_(e_job_still_running_add_bang_to_end_the_job)); } else { - emsg(_("E37: No write since last change (add ! to override)")); + emsg(_(e_no_write_since_last_change_add_bang_to_override)); } } @@ -1834,9 +1845,9 @@ void no_write_message_nobang(const buf_T *const buf) { if (buf->terminal && channel_job_running((uint64_t)buf->b_p_channel)) { - emsg(_("E948: Job still running")); + emsg(_(e_job_still_running)); } else { - emsg(_("E37: No write since last change")); + emsg(_(e_no_write_since_last_change)); } } diff --git a/src/nvim/errors.h b/src/nvim/errors.h @@ -131,9 +131,14 @@ EXTERN const char e_missingparen[] INIT(= N_("E107: Missing parentheses: %s")); EXTERN const char e_empty_buffer[] INIT(= N_("E749: Empty buffer")); EXTERN const char e_nobufnr[] INIT(= N_("E86: Buffer %" PRId64 " does not exist")); +EXTERN const char e_no_write_since_last_change[] INIT(= N_("E37: No write since last change")); +EXTERN const char e_no_write_since_last_change_add_bang_to_override[] INIT(= N_("E37: No write since last change (add ! to override)")); +EXTERN const char e_no_write_since_last_change_for_buffer_nr_add_bang_to_override[] INIT(= N_("E89: No write since last change for buffer %d (add ! to override)")); EXTERN const char e_buffer_nr_not_found[] INIT(= N_("E92: Buffer %d not found")); EXTERN const char e_unknown_function_str[] INIT(= N_("E117: Unknown function: %s")); EXTERN const char e_str_not_inside_function[] INIT(= N_("E193: %s not inside a function")); +EXTERN const char e_job_still_running[] INIT(= N_("E948: Job still running")); +EXTERN const char e_job_still_running_add_bang_to_end_the_job[] INIT(= N_("E948: Job still running (add ! to end the job)")); EXTERN const char e_invalpat[] INIT(= N_("E682: Invalid search pattern or delimiter")); EXTERN const char e_bufloaded[] INIT(= N_("E139: File is loaded in another buffer")); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c @@ -2104,10 +2104,10 @@ void do_wqall(exarg_T *eap) } FOR_ALL_BUFFERS(buf) { - if (exiting + if (exiting && !eap->forceit && buf->terminal && channel_job_running((uint64_t)buf->b_p_channel)) { - no_write_message_nobang(buf); + no_write_message_buf(buf); error++; } else if (!bufIsChanged(buf) || bt_dontwrite(buf)) { continue; diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua @@ -243,7 +243,7 @@ describe(':terminal buffer', function() it('requires bang (!) to close a running job #15402', function() skip(is_os('win'), 'Test freezes the CI and makes it time out') - eq('Vim(wqall):E948: Job still running', exc_exec('wqall')) + eq('Vim(wqall):E948: Job still running (add ! to end the job)', exc_exec('wqall')) for _, cmd in ipairs({ 'bdelete', '%bdelete', 'bwipeout', 'bunload' }) do matches( '^Vim%(' @@ -257,6 +257,10 @@ describe(':terminal buffer', function() command('bdelete') end) + it(':wqall! closes a running job', function() + n.expect_exit(command, 'wqall!') + end) + it('stops running jobs with :quit', function() -- Open in a new window to avoid terminating the nvim instance command('split')