mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 04:42:03 +00:00
feat(terminal): surface exit code via virttext + nvim_get_chan_info #37987
Problem: When a terminal process exits, "[Process Exited]" text is added to the buffer contents. Solution: - Return `exitcode` field from `nvim_get_chan_info`. - Show it in the default 'statusline'. - Show exitcode as virtual text in the terminal buffer.
This commit is contained in:
@@ -841,6 +841,7 @@ nvim_get_chan_info({chan}) *nvim_get_chan_info()*
|
||||
• "buffer" (optional) Buffer connected to |terminal| instance.
|
||||
• "client" (optional) Info about the peer (client on the other end of
|
||||
the channel), as set by |nvim_set_client_info()|.
|
||||
• "exitcode" (optional) Exit code of the |terminal| process.
|
||||
|
||||
nvim_get_color_by_name({name}) *nvim_get_color_by_name()*
|
||||
Returns the 24-bit RGB value of a |nvim_get_color_map()| color name or
|
||||
|
||||
@@ -165,6 +165,7 @@ API
|
||||
• Added experimental |nvim__exec_lua_fast()| to allow remote API clients to
|
||||
execute code while nvim is blocking for input.
|
||||
• |vim.secure.trust()| accepts `path` for the `allow` action.
|
||||
• |nvim_get_chan_info()| includes `exitcode` field for terminal buffers
|
||||
|
||||
BUILD
|
||||
|
||||
@@ -192,6 +193,7 @@ DEFAULTS
|
||||
• |grt| in Normal mode maps to |vim.lsp.buf.type_definition()|
|
||||
• 'shada' default now excludes "/tmp/" and "/private/" paths to reduce clutter in |:oldfiles|.
|
||||
• Enabled treesitter highlighting for Markdown files
|
||||
• 'statusline' shows exit code of finished terminal buffers
|
||||
|
||||
DIAGNOSTICS
|
||||
|
||||
@@ -472,6 +474,8 @@ These existing features changed their behavior.
|
||||
for input and output. This matters mostly for Linux where some command lines
|
||||
using "/dev/stdin" and similiar would break as these special files can be
|
||||
reopened when backed by pipes but not when backed by socket pairs.
|
||||
• On terminal exit, "[Process exited]" is not added to the buffer contents,
|
||||
instead it is shown as virtual text and exit code is shown in statusline.
|
||||
|
||||
==============================================================================
|
||||
REMOVED FEATURES *news-removed*
|
||||
|
||||
@@ -81,4 +81,22 @@ function M.source_is_lua(bufnr, line1, line2)
|
||||
return lang_tree:lang() == 'lua'
|
||||
end
|
||||
|
||||
--- Returns the exit code string for the current buffer, given:
|
||||
--- - Channel is attached to the current buffer
|
||||
--- - Current buffer is a terminal buffer
|
||||
---
|
||||
--- @return string
|
||||
function M.term_exitcode()
|
||||
local chan_id = vim.bo.channel
|
||||
if chan_id == 0 or vim.bo.buftype ~= 'terminal' then
|
||||
return ''
|
||||
end
|
||||
|
||||
local info = vim.api.nvim_get_chan_info(chan_id)
|
||||
if info.exitcode and info.exitcode >= 0 then
|
||||
return string.format('[Exit: %d]', info.exitcode)
|
||||
end
|
||||
return ''
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
1
runtime/lua/vim/_meta/api.lua
generated
1
runtime/lua/vim/_meta/api.lua
generated
@@ -1309,6 +1309,7 @@ function vim.api.nvim_get_autocmds(opts) end
|
||||
--- - "buffer" (optional) Buffer connected to |terminal| instance.
|
||||
--- - "client" (optional) Info about the peer (client on the other end of the channel), as set
|
||||
--- by |nvim_set_client_info()|.
|
||||
--- - "exitcode" (optional) Exit code of the |terminal| process.
|
||||
---
|
||||
function vim.api.nvim_get_chan_info(chan) end
|
||||
|
||||
|
||||
2
runtime/lua/vim/_meta/options.lua
generated
2
runtime/lua/vim/_meta/options.lua
generated
@@ -6964,7 +6964,7 @@ vim.wo.stc = vim.wo.statuscolumn
|
||||
---
|
||||
---
|
||||
--- @type string
|
||||
vim.o.statusline = "%<%f %h%w%m%r %=%{% &showcmdloc == 'statusline' ? '%-10.S ' : '' %}%{% exists('b:keymap_name') ? '<'..b:keymap_name..'> ' : '' %}%{% &busy > 0 ? '◐ ' : '' %}%{% luaeval('(package.loaded[''vim.diagnostic''] and #vim.diagnostic.count() ~= 0 and vim.diagnostic.status() .. '' '') or '''' ') %}%{% &ruler ? ( &rulerformat == '' ? '%-14.(%l,%c%V%) %P' : &rulerformat ) : '' %}"
|
||||
vim.o.statusline = "%<%f %h%w%m%r %{% v:lua.require('vim._core.util').term_exitcode() %}%=%{% &showcmdloc == 'statusline' ? '%-10.S ' : '' %}%{% exists('b:keymap_name') ? '<'..b:keymap_name..'> ' : '' %}%{% &busy > 0 ? '◐ ' : '' %}%{% luaeval('(package.loaded[''vim.diagnostic''] and #vim.diagnostic.count() ~= 0 and vim.diagnostic.status() .. '' '') or '''' ') %}%{% &ruler ? ( &rulerformat == '' ? '%-14.(%l,%c%V%) %P' : &rulerformat ) : '' %}"
|
||||
vim.o.stl = vim.o.statusline
|
||||
vim.wo.statusline = vim.o.statusline
|
||||
vim.wo.stl = vim.wo.statusline
|
||||
|
||||
@@ -1719,6 +1719,7 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dict version, String
|
||||
/// - "buffer" (optional) Buffer connected to |terminal| instance.
|
||||
/// - "client" (optional) Info about the peer (client on the other end of the channel), as set
|
||||
/// by |nvim_set_client_info()|.
|
||||
/// - "exitcode" (optional) Exit code of the |terminal| process.
|
||||
///
|
||||
Dict nvim_get_chan_info(uint64_t channel_id, Integer chan, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(4)
|
||||
|
||||
@@ -182,6 +182,7 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error)
|
||||
chan->stream.internal.cb = LUA_NOREF;
|
||||
chan->stream.internal.closed = true;
|
||||
terminal_close(&chan->term, 0);
|
||||
chan->exit_status = 0;
|
||||
} else {
|
||||
channel_decref(chan);
|
||||
}
|
||||
@@ -784,8 +785,8 @@ static void channel_proc_exit_cb(Proc *proc, int status, void *data)
|
||||
bool exited = (status >= 0);
|
||||
if (exited && chan->on_exit.type != kCallbackNone) {
|
||||
schedule_channel_event(chan);
|
||||
chan->exit_status = status;
|
||||
}
|
||||
chan->exit_status = exited ? status : chan->exit_status;
|
||||
|
||||
channel_decref(chan);
|
||||
}
|
||||
@@ -1001,6 +1002,7 @@ Dict channel_info(uint64_t id, Arena *arena)
|
||||
} else if (chan->term) {
|
||||
mode_desc = "terminal";
|
||||
PUT_C(info, "buffer", BUFFER_OBJ(terminal_buf(chan->term)));
|
||||
PUT_C(info, "exitcode", INTEGER_OBJ(chan->exit_status));
|
||||
} else {
|
||||
mode_desc = "bytes";
|
||||
}
|
||||
|
||||
@@ -8774,6 +8774,7 @@ local options = {
|
||||
if_true = table.concat({
|
||||
'%<',
|
||||
'%f %h%w%m%r ',
|
||||
"%{% v:lua.require('vim._core.util').term_exitcode() %}",
|
||||
'%=',
|
||||
"%{% &showcmdloc == 'statusline' ? '%-10.S ' : '' %}",
|
||||
"%{% exists('b:keymap_name') ? '<'..b:keymap_name..'> ' : '' %}",
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/time.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/extmark.h"
|
||||
#include "nvim/getchar.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/grid.h"
|
||||
@@ -706,13 +707,37 @@ void terminal_close(Terminal **termpp, int status)
|
||||
} else if (!only_destroy) {
|
||||
// Associated channel has been closed and the editor is not exiting.
|
||||
// Do not call the close callback now. Wait for the user to press a key.
|
||||
char msg[sizeof("\r\n[Process exited ]") + NUMBUFLEN];
|
||||
char msg[sizeof("[Process exited ]") + NUMBUFLEN];
|
||||
if (((Channel *)term->opts.data)->streamtype == kChannelStreamInternal) {
|
||||
snprintf(msg, sizeof msg, "\r\n[Terminal closed]");
|
||||
snprintf(msg, sizeof msg, "[Terminal closed]");
|
||||
} else {
|
||||
snprintf(msg, sizeof msg, "\r\n[Process exited %d]", status);
|
||||
snprintf(msg, sizeof msg, "[Process exited %d]", status);
|
||||
}
|
||||
|
||||
// Show the msg as virtual text instead of adding it to buffer
|
||||
VirtTextChunk *chunk = xmalloc(sizeof(VirtTextChunk));
|
||||
*chunk = (VirtTextChunk) { .text = xstrdup(msg), .hl_id = -1 };
|
||||
DecorVirtText *virt_text = xmalloc(sizeof(DecorVirtText));
|
||||
*virt_text = (DecorVirtText) {
|
||||
.priority = DECOR_PRIORITY_BASE,
|
||||
.pos = kVPosWinCol,
|
||||
.data.virt_text = { .items = chunk, .size = 1 }
|
||||
};
|
||||
DecorInline decor = {
|
||||
.ext = true, .data.ext = { .sh_idx = DECOR_ID_INVALID, .vt = virt_text }
|
||||
};
|
||||
|
||||
int pos = MIN(row_to_linenr(term, term->cursor.row),
|
||||
buf->b_ml.ml_line_count - 1);
|
||||
extmark_set(buf, (uint32_t)-1, NULL, pos, 0, -1, 0,
|
||||
decor, 0, true, false, true, false, NULL);
|
||||
|
||||
// Redraw statusline to show the exit code.
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_buffer == buf) {
|
||||
wp->w_redr_status = true;
|
||||
}
|
||||
}
|
||||
terminal_receive(term, msg, strlen(msg));
|
||||
}
|
||||
|
||||
if (only_destroy) {
|
||||
|
||||
@@ -2834,6 +2834,7 @@ describe('API', function()
|
||||
mode = 'terminal',
|
||||
buffer = 1,
|
||||
pty = '?',
|
||||
exitcode = -1,
|
||||
}
|
||||
local event = api.nvim_get_var('opened_event')
|
||||
if not is_os('win') then
|
||||
@@ -2869,6 +2870,7 @@ describe('API', function()
|
||||
mode = 'terminal',
|
||||
buffer = 2,
|
||||
pty = '?',
|
||||
exitcode = -1,
|
||||
}
|
||||
local actual2 = eval('nvim_get_chan_info(&channel)')
|
||||
expected2.pty = actual2.pty
|
||||
@@ -2878,6 +2880,7 @@ describe('API', function()
|
||||
eq(1, eval('jobstop(&channel)'))
|
||||
eval('jobwait([&channel], 1000)') -- Wait.
|
||||
expected2.pty = (is_os('win') and '?' or '') -- pty stream was closed.
|
||||
expected2.exitcode = (is_os('win') and 143 or 129)
|
||||
eq(expected2, eval('nvim_get_chan_info(&channel)'))
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -1370,8 +1370,8 @@ describe('jobs', function()
|
||||
|
||||
feed(':q<CR>')
|
||||
screen:expect([[
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
^ |
|
||||
[Process exited 0] |
|
||||
|*4
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
|
||||
@@ -117,8 +117,8 @@ describe('command-line option', function()
|
||||
)
|
||||
feed('i:cq<CR>')
|
||||
screen:expect([[
|
||||
|
|
||||
[Process exited 1]^ |
|
||||
^ |
|
||||
[Process exited 1] |
|
||||
|*5
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
|
||||
@@ -60,7 +60,8 @@ describe('startup', function()
|
||||
)
|
||||
screen:expect([[
|
||||
^Cannot attach UI of :terminal child to its parent. (Unset $NVIM to skip this check) |
|
||||
|*2
|
||||
[Process exited 1] |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local t = require('test.testutil')
|
||||
local n = require('test.functional.testnvim')()
|
||||
local tt = require('test.functional.testterm')
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local uv = vim.uv
|
||||
@@ -24,6 +25,7 @@ local poke_eventloop = n.poke_eventloop
|
||||
local api = n.api
|
||||
local retry = t.retry
|
||||
local write_file = t.write_file
|
||||
local expect_exitcode = tt.expect_exitcode
|
||||
|
||||
describe(':recover', function()
|
||||
before_each(clear)
|
||||
@@ -552,12 +554,7 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
|
||||
)
|
||||
end)
|
||||
api.nvim_chan_send(chan, 'q')
|
||||
retry(nil, nil, function()
|
||||
eq(
|
||||
{ '', '[Process exited 1]', '' },
|
||||
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
|
||||
)
|
||||
end)
|
||||
expect_exitcode(1)
|
||||
end)
|
||||
|
||||
it('(A)bort at second file argument with -p', function()
|
||||
@@ -585,12 +582,7 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
|
||||
)
|
||||
end)
|
||||
api.nvim_chan_send(chan, 'a')
|
||||
retry(nil, nil, function()
|
||||
eq(
|
||||
{ '', '[Process exited 1]', '' },
|
||||
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
|
||||
)
|
||||
end)
|
||||
expect_exitcode(1)
|
||||
end)
|
||||
|
||||
it('(Q)uit at file opened by -t', function()
|
||||
@@ -626,13 +618,6 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
|
||||
)
|
||||
end)
|
||||
api.nvim_chan_send(chan, 'q')
|
||||
retry(nil, nil, function()
|
||||
eq(
|
||||
{ '[Process exited 1]' },
|
||||
eval(
|
||||
"[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})->filter({_, s -> !empty(trim(s))})"
|
||||
)
|
||||
)
|
||||
end)
|
||||
expect_exitcode(1)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -986,7 +986,7 @@ describe(':terminal buffer', function()
|
||||
3: å̲│{1:~ }|
|
||||
│{1:~ }|
|
||||
[Pro│{1:~ }|
|
||||
cess│{1:~ }|
|
||||
│{1:~ }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
@@ -1005,10 +1005,10 @@ describe(':terminal buffer', function()
|
||||
%d: TEST{MATCH: +}|
|
||||
%d: TEST{MATCH: +}|
|
||||
%d: TEST{MATCH: +}|
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
%d: TEST{MATCH: +}|
|
||||
^[Process exited 0] |
|
||||
{5:-- TERMINAL --} |
|
||||
]]):format(count - 4, count - 3, count - 2, count - 1))
|
||||
]]):format(count - 5, count - 4, count - 3, count - 2, count - 1))
|
||||
local lines = api.nvim_buf_get_lines(0, 0, -1, true)
|
||||
for i = 1, count do
|
||||
eq(('%d: TEST'):format(i - 1), lines[i])
|
||||
@@ -1313,6 +1313,11 @@ describe(':terminal buffer', function()
|
||||
[Process exited 0] |
|
||||
|*5
|
||||
]])
|
||||
api.nvim_buf_clear_namespace(0, -1, 0, -1)
|
||||
env.screen:expect([[
|
||||
^ready $ |
|
||||
|*6
|
||||
]])
|
||||
env.buf = api.nvim_get_current_buf()
|
||||
api.nvim_set_option_value('modified', false, { buf = env.buf })
|
||||
end)
|
||||
@@ -1329,10 +1334,10 @@ describe(':terminal buffer', function()
|
||||
local chan = api.nvim_open_term(0, {})
|
||||
api.nvim_chan_send(chan, 'TEST')
|
||||
fn.chanclose(chan)
|
||||
api.nvim_buf_clear_namespace(0, -1, 0, -1)
|
||||
env.screen:expect([[
|
||||
^TEST |
|
||||
[Terminal closed] |
|
||||
|*5
|
||||
|*6
|
||||
]])
|
||||
env.buf = api.nvim_get_current_buf()
|
||||
api.nvim_set_option_value('modified', false, { buf = env.buf })
|
||||
|
||||
@@ -185,9 +185,9 @@ local function test_autocmd_no_crash(event, extra_tests)
|
||||
]])
|
||||
feed('i')
|
||||
env.screen:expect([[
|
||||
48: TEST |
|
||||
49: TEST |
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
^[Process exited 0] |
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
feed('<CR>')
|
||||
|
||||
@@ -43,12 +43,11 @@ describe(':edit term://*', function()
|
||||
|
||||
local bufcontents = {}
|
||||
local winheight = api.nvim_win_get_height(0)
|
||||
local buf_cont_start = rep - sb - winheight + 2
|
||||
local buf_cont_start = rep - sb - winheight + 1
|
||||
for i = buf_cont_start, (rep - 1) do
|
||||
bufcontents[#bufcontents + 1] = ('%d: foobar'):format(i)
|
||||
end
|
||||
bufcontents[#bufcontents + 1] = ''
|
||||
bufcontents[#bufcontents + 1] = '[Process exited 0]'
|
||||
|
||||
local exp_screen = '\n'
|
||||
for i = 1, (winheight - 1) do
|
||||
|
||||
@@ -861,12 +861,12 @@ describe(':terminal prints more lines than the screen height and exits', functio
|
||||
("call jobstart(['%s', '10'], {'term':v:true}) | startinsert"):format(testprg('tty-test'))
|
||||
)
|
||||
screen:expect([[
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
line8 |
|
||||
line9 |
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
^[Process exited 0] |
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
feed('<cr>')
|
||||
@@ -1096,9 +1096,8 @@ describe('pending scrollback line handling', function()
|
||||
or { 'printf', ('hi\n'):rep(12) }
|
||||
)
|
||||
screen:expect [[
|
||||
hi |*4
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
hi |*5
|
||||
^[Process exited 0] |
|
||||
{5:-- TERMINAL --} |
|
||||
]]
|
||||
assert_alive()
|
||||
|
||||
@@ -2519,8 +2519,8 @@ describe('TUI', function()
|
||||
exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
|
||||
screen:expect(is_os('win') and { any = '%[Process exited 1%]' } or [[
|
||||
Nvim: Caught deadly signal 'SIGTERM' |
|
||||
|
|
||||
[Process exited 1]^ |
|
||||
^ |
|
||||
[Process exited 1] |
|
||||
|*3
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
@@ -2554,8 +2554,8 @@ describe('TUI', function()
|
||||
]]
|
||||
child_session:notify('nvim_exec_lua', code, {})
|
||||
screen:expect([[
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
^ |
|
||||
[Process exited 0] |
|
||||
|*4
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
@@ -2970,8 +2970,8 @@ describe('TUI', function()
|
||||
:w testF |
|
||||
:q |
|
||||
abc |
|
||||
|
|
||||
[Process exited 0]^ |
|
||||
^ |
|
||||
[Process exited 0] |
|
||||
|
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
@@ -4237,8 +4237,8 @@ describe('TUI client', function()
|
||||
exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
|
||||
screen_client:expect(is_os('win') and { any = '%[Process exited 1%]' } or [[
|
||||
Nvim: Caught deadly signal 'SIGTERM' |
|
||||
|
|
||||
[Process exited 1]^ |
|
||||
^ |
|
||||
[Process exited 1] |
|
||||
|*3
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
@@ -4362,8 +4362,8 @@ describe('TUI client', function()
|
||||
|
||||
screen:expect([[
|
||||
Remote ui failed to start: {MATCH:.*}|
|
||||
|
|
||||
[Process exited 1]^ |
|
||||
^ |
|
||||
[Process exited 1] |
|
||||
|*3
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
|
||||
@@ -16,6 +16,8 @@ local testprg = n.testprg
|
||||
local exec_lua = n.exec_lua
|
||||
local api = n.api
|
||||
local nvim_prog = n.nvim_prog
|
||||
local retry = t.retry
|
||||
local eq = t.eq
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -221,4 +223,18 @@ function M.screen_expect(screen, s)
|
||||
screen:expect(s)
|
||||
end
|
||||
|
||||
--- Asserts that the exit code of chan eventually matches the expected exit code
|
||||
---
|
||||
--- @param code integer expected exit code
|
||||
--- @param chan? integer channel id, defaults to current buffer's channel
|
||||
function M.expect_exitcode(code, chan)
|
||||
chan = chan or api.nvim_get_option_value('channel', { buf = 0 }) or 0
|
||||
eq(true, chan > 0, 'Expected a valid channel ID, but got: ' .. chan)
|
||||
|
||||
retry(nil, nil, function()
|
||||
local info = api.nvim_get_chan_info(chan)
|
||||
eq(code, info.exitcode)
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -2479,7 +2479,7 @@ describe('ui/msg_puts_printf', function()
|
||||
^Exモードに入ります。ノー |
|
||||
マルモードに戻るには "vis|
|
||||
ual" と入力してください。|
|
||||
: |
|
||||
[Process exited 0] |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local t = require('test.testutil')
|
||||
local n = require('test.functional.testnvim')()
|
||||
local tt = require('test.functional.testterm')
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local assert_alive = n.assert_alive
|
||||
@@ -14,6 +15,8 @@ local exec_lua = n.exec_lua
|
||||
local eval = n.eval
|
||||
local sleep = vim.uv.sleep
|
||||
local pcall_err = t.pcall_err
|
||||
local testprg = n.testprg
|
||||
local expect_exitcode = tt.expect_exitcode
|
||||
|
||||
local mousemodels = { 'extend', 'popup', 'popup_setpos' }
|
||||
|
||||
@@ -959,6 +962,7 @@ describe('default statusline', function()
|
||||
local default_statusline = table.concat({
|
||||
'%<',
|
||||
'%f %h%w%m%r ',
|
||||
"%{% v:lua.require('vim._core.util').term_exitcode() %}",
|
||||
'%=',
|
||||
"%{% &showcmdloc == 'statusline' ? '%-10.S ' : '' %}",
|
||||
"%{% exists('b:keymap_name') ? '<'..b:keymap_name..'> ' : '' %}",
|
||||
@@ -1026,6 +1030,16 @@ describe('default statusline', function()
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('shows exit code when terminal exits #14986', function()
|
||||
exec_lua("vim.o.statusline = ''")
|
||||
api.nvim_set_option_value('shell', testprg('shell-test'), {})
|
||||
api.nvim_set_option_value('shellcmdflag', 'EXIT', {})
|
||||
api.nvim_set_option_value('shellxquote', '', {}) -- win: avoid extra quotes
|
||||
command('terminal 9')
|
||||
screen:expect({ any = '%[Exit: 9%]' })
|
||||
expect_exitcode(9)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("'statusline' in floatwin", function()
|
||||
|
||||
Reference in New Issue
Block a user