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

d8558fdf4f
(cherry picked from commit 681d006549)
This commit is contained in:
zeertzjq
2026-01-09 07:36:47 +08:00
committed by github-actions[bot]
parent 781da755e8
commit 9f2b991331
4 changed files with 28 additions and 8 deletions

View File

@@ -1350,7 +1350,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;
}
@@ -1806,13 +1806,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));
}
}
@@ -1821,9 +1832,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));
}
}

View File

@@ -129,9 +129,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"));

View File

@@ -1887,10 +1887,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;

View File

@@ -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')