aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2025-01-14 12:05:23 +0100
committerLuuk van Baal <luukvbaal@gmail.com>2025-01-15 10:51:52 +0100
commit5bae80899d9d29d80c129ca92cde75a1583b5efe (patch)
treec30d604cf4a84d2e5998297596a6ee4e9b0e62b6
parentc5f93d7ab04f93db1470d58ca1f70e947e716c2b (diff)
downloadrneovim-5bae80899d9d29d80c129ca92cde75a1583b5efe.tar.gz
rneovim-5bae80899d9d29d80c129ca92cde75a1583b5efe.tar.bz2
rneovim-5bae80899d9d29d80c129ca92cde75a1583b5efe.zip
feat(messages): add :!cmd shell message kinds
Also print stderr error messages with ErrorMsg highlight group.
-rw-r--r--runtime/doc/news.txt2
-rw-r--r--runtime/doc/ui.txt3
-rw-r--r--src/nvim/event/proc.h4
-rw-r--r--src/nvim/os/shell.c12
-rw-r--r--test/functional/ui/messages_spec.lua38
5 files changed, 51 insertions, 8 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 89504ae244..e12c307b5f 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -96,7 +96,7 @@ EVENTS
• `msg_show`:
• `history` argument indicating if the message was added to the history.
• new message kinds: "bufwrite", "completion", "list_cmd", "lua_print",
- "search_cmd", "undo", "verbose", wildlist".
+ "search_cmd", "shell_out/err/ret", "undo", "verbose", wildlist".
HIGHLIGHTS
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index 26ea03d2be..4d212e2779 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -805,6 +805,9 @@ must handle.
"quickfix" Quickfix navigation message
"search_cmd" Entered search command
"search_count" Search count message ("S" flag of 'shortmess')
+ "shell_err" |:!cmd| shell stderr output
+ "shell_out" |:!cmd| shell stdout output
+ "shell_ret" |:!cmd| shell return code
"undo" |:undo| and |:redo| message
"verbose" 'verbose' message
"wildlist" 'wildmode' "list" message
diff --git a/src/nvim/event/proc.h b/src/nvim/event/proc.h
index f525d46f87..fb14041049 100644
--- a/src/nvim/event/proc.h
+++ b/src/nvim/event/proc.h
@@ -21,8 +21,8 @@ static inline Proc proc_init(Loop *loop, ProcType type, void *data)
.argv = NULL,
.exepath = NULL,
.in = { .closed = false },
- .out = { .s.closed = false },
- .err = { .s.closed = false },
+ .out = { .s.closed = false, .s.fd = STDOUT_FILENO },
+ .err = { .s.closed = false, .s.fd = STDERR_FILENO },
.cb = NULL,
.closed = false,
.internal_close_cb = NULL,
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 81b75dc4d3..5347c8db9a 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -700,6 +700,7 @@ int os_call_shell(char *cmd, int opts, char *extra_args)
}
if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) {
+ msg_ext_set_kind("shell_ret");
msg_puts(_("\nshell returned "));
msg_outnum(exitcode);
msg_putchar('\n');
@@ -1067,7 +1068,7 @@ static void out_data_ring(const char *output, size_t size)
}
if (output == NULL && size == SIZE_MAX) { // Print mode
- out_data_append_to_screen(last_skipped, &last_skipped_len, true);
+ out_data_append_to_screen(last_skipped, &last_skipped_len, STDOUT_FILENO, true);
return;
}
@@ -1095,14 +1096,15 @@ static void out_data_ring(const char *output, size_t size)
/// @param output Data to append to screen lines.
/// @param count Size of data.
/// @param eof If true, there will be no more data output.
-static void out_data_append_to_screen(const char *output, size_t *count, bool eof)
+static void out_data_append_to_screen(const char *output, size_t *count, int fd, bool eof)
FUNC_ATTR_NONNULL_ALL
{
const char *p = output;
const char *end = output + *count;
+ msg_ext_set_kind(fd == STDERR_FILENO ? "shell_err" : "shell_out");
while (p < end) {
if (*p == '\n' || *p == '\r' || *p == TAB || *p == BELL) {
- msg_putchar_hl((uint8_t)(*p), 0);
+ msg_putchar_hl((uint8_t)(*p), fd == STDERR_FILENO ? HLF_E : 0);
p++;
} else {
// Note: this is not 100% precise:
@@ -1118,7 +1120,7 @@ static void out_data_append_to_screen(const char *output, size_t *count, bool eo
goto end;
}
- msg_outtrans_len(p, i, 0, false);
+ msg_outtrans_len(p, i, fd == STDERR_FILENO ? HLF_E : 0, false);
p += i;
}
}
@@ -1133,7 +1135,7 @@ static size_t out_data_cb(RStream *stream, const char *ptr, size_t count, void *
// Save the skipped output. If it is the final chunk, we display it later.
out_data_ring(ptr, count);
} else if (count > 0) {
- out_data_append_to_screen(ptr, &count, eof);
+ out_data_append_to_screen(ptr, &count, stream->s.fd, eof);
}
return count;
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index ea4edefe8a..4d53daa9d6 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -331,6 +331,7 @@ describe('ui/ext_messages', function()
},
})
+ -- kind=verbose for :verbose messages
feed(':1verbose filter Diff[AC] hi<CR>')
screen:expect({
cmdline = { {
@@ -380,6 +381,43 @@ describe('ui/ext_messages', function()
},
},
})
+
+ -- kind=shell for :!cmd messages
+ local cmd = t.is_os('win') and 'echo stdout& echo stderr>&2& exit 3'
+ or '{ echo stdout; echo stderr >&2; exit 3; }'
+ feed(('<CR>:!%s<CR>'):format(cmd))
+ screen:expect({
+ cmdline = { {
+ abort = false,
+ } },
+ messages = {
+ {
+ content = { { (':!%s\r\n[No write since last change]\n'):format(cmd) } },
+ history = false,
+ kind = '',
+ },
+ {
+ content = { { ('stdout%s\n'):format(t.is_os('win') and '\r' or '') } },
+ history = false,
+ kind = 'shell_out',
+ },
+ {
+ content = { { ('stderr%s\n'):format(t.is_os('win') and '\r' or ''), 9, 6 } },
+ history = false,
+ kind = 'shell_err',
+ },
+ {
+ content = { { '\nshell returned 3\n\n' } },
+ history = false,
+ kind = 'shell_ret',
+ },
+ {
+ content = { { 'Press ENTER or type command to continue', 6, 18 } },
+ history = false,
+ kind = 'return_prompt',
+ },
+ },
+ })
end)
it(':echoerr', function()