neovim

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

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:
Msrc/nvim/buffer.c | 2+-
Msrc/nvim/channel.c | 2++
Msrc/nvim/ex_cmds.c | 2++
Mtest/functional/ex_cmds/ls_spec.lua | 32++++++++++++++++++++++++++------
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)