commit 49d7f694a8509e3134a2b9e38e692099e48cf51f
parent 885426f1bfe72b29287e385ccc57f7823d16f53e
Author: zeertzjq <zeertzjq@outlook.com>
Date: Fri, 9 Jan 2026 09:31:00 +0800
fix(:ls): check for finished terminal properly (#37303)
Use terminal_running() instead of channel_job_running().
Diffstat:
4 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
@@ -2924,7 +2924,7 @@ void buflist_list(exarg_T *eap)
: (bufIsChanged(buf) ? '+' : ' ');
int ro_char = !MODIFIABLE(buf) ? '-' : (buf->b_p_ro ? '=' : ' ');
if (buf->terminal) {
- ro_char = channel_job_running((uint64_t)buf->b_p_channel) ? 'R' : 'F';
+ ro_char = terminal_running(buf->terminal) ? 'R' : 'F';
}
msg_putchar('\n');
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
@@ -900,6 +900,8 @@ static void set_info_event(void **argv)
channel_decref(chan);
}
+/// Unlike terminal_running(), this returns false immediately after stopping a job.
+/// However, this always returns false for nvim_open_term() terminals.
bool channel_job_running(uint64_t id)
{
Channel *chan = find_channel(id);
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
@@ -2106,6 +2106,8 @@ void do_wqall(exarg_T *eap)
FOR_ALL_BUFFERS(buf) {
if (exiting && !eap->forceit
&& buf->terminal
+ // TODO(zeertzjq): this always returns false for nvim_open_term() terminals.
+ // Use terminal_running() instead?
&& channel_job_running((uint64_t)buf->b_p_channel)) {
no_write_message_buf(buf);
error++;
diff --git a/test/functional/ex_cmds/ls_spec.lua b/test/functional/ex_cmds/ls_spec.lua
@@ -15,15 +15,15 @@ describe(':ls', function()
clear()
end)
- it('R, F for :terminal buffers', function()
- api.nvim_set_option_value('shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
-
+ --- @param start_running_term fun()
+ --- @param start_finished_term fun()
+ local function test_ls_terminal_buffer(start_running_term, start_finished_term)
command('edit foo')
command('set hidden')
- command('terminal')
+ start_running_term()
command('vsplit')
- command('terminal')
- feed('iexit<cr>')
+ start_finished_term()
+
retry(nil, 5000, function()
local ls_output = eval('execute("ls")')
-- Normal buffer.
@@ -45,5 +45,25 @@ describe(':ls', function()
-- Just the [F]inished terminal buffer.
eq('\n 3 %aF ', string.match(ls_output, '^\n *3 ... '))
end)
+ end
+
+ describe('R, F for', function()
+ it('terminal buffers', function()
+ api.nvim_set_option_value('shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
+ test_ls_terminal_buffer(function()
+ command('terminal')
+ end, function()
+ command('terminal')
+ feed('iexit<cr>')
+ end)
+ end)
+
+ it('nvim_open_term() buffers', function()
+ test_ls_terminal_buffer(function()
+ command('enew | call nvim_open_term(0, {})')
+ end, function()
+ command('enew | call chanclose(nvim_open_term(0, {}))')
+ end)
+ end)
end)
end)