mirror of
https://github.com/neovim/neovim
synced 2025-07-27 00:41:52 +00:00
feat(messages): add :!cmd shell message kinds
Also print stderr error messages with ErrorMsg highlight group.
This commit is contained in:
@ -96,7 +96,7 @@ EVENTS
|
|||||||
• `msg_show`:
|
• `msg_show`:
|
||||||
• `history` argument indicating if the message was added to the history.
|
• `history` argument indicating if the message was added to the history.
|
||||||
• new message kinds: "bufwrite", "completion", "list_cmd", "lua_print",
|
• new message kinds: "bufwrite", "completion", "list_cmd", "lua_print",
|
||||||
"search_cmd", "undo", "verbose", wildlist".
|
"search_cmd", "shell_out/err/ret", "undo", "verbose", wildlist".
|
||||||
|
|
||||||
HIGHLIGHTS
|
HIGHLIGHTS
|
||||||
|
|
||||||
|
@ -805,6 +805,9 @@ must handle.
|
|||||||
"quickfix" Quickfix navigation message
|
"quickfix" Quickfix navigation message
|
||||||
"search_cmd" Entered search command
|
"search_cmd" Entered search command
|
||||||
"search_count" Search count message ("S" flag of 'shortmess')
|
"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
|
"undo" |:undo| and |:redo| message
|
||||||
"verbose" 'verbose' message
|
"verbose" 'verbose' message
|
||||||
"wildlist" 'wildmode' "list" message
|
"wildlist" 'wildmode' "list" message
|
||||||
|
@ -21,8 +21,8 @@ static inline Proc proc_init(Loop *loop, ProcType type, void *data)
|
|||||||
.argv = NULL,
|
.argv = NULL,
|
||||||
.exepath = NULL,
|
.exepath = NULL,
|
||||||
.in = { .closed = false },
|
.in = { .closed = false },
|
||||||
.out = { .s.closed = false },
|
.out = { .s.closed = false, .s.fd = STDOUT_FILENO },
|
||||||
.err = { .s.closed = false },
|
.err = { .s.closed = false, .s.fd = STDERR_FILENO },
|
||||||
.cb = NULL,
|
.cb = NULL,
|
||||||
.closed = false,
|
.closed = false,
|
||||||
.internal_close_cb = NULL,
|
.internal_close_cb = NULL,
|
||||||
|
@ -700,6 +700,7 @@ int os_call_shell(char *cmd, int opts, char *extra_args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) {
|
if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) {
|
||||||
|
msg_ext_set_kind("shell_ret");
|
||||||
msg_puts(_("\nshell returned "));
|
msg_puts(_("\nshell returned "));
|
||||||
msg_outnum(exitcode);
|
msg_outnum(exitcode);
|
||||||
msg_putchar('\n');
|
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
|
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;
|
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 output Data to append to screen lines.
|
||||||
/// @param count Size of data.
|
/// @param count Size of data.
|
||||||
/// @param eof If true, there will be no more data output.
|
/// @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
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
const char *p = output;
|
const char *p = output;
|
||||||
const char *end = output + *count;
|
const char *end = output + *count;
|
||||||
|
msg_ext_set_kind(fd == STDERR_FILENO ? "shell_err" : "shell_out");
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
if (*p == '\n' || *p == '\r' || *p == TAB || *p == BELL) {
|
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++;
|
p++;
|
||||||
} else {
|
} else {
|
||||||
// Note: this is not 100% precise:
|
// 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;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_outtrans_len(p, i, 0, false);
|
msg_outtrans_len(p, i, fd == STDERR_FILENO ? HLF_E : 0, false);
|
||||||
p += i;
|
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.
|
// Save the skipped output. If it is the final chunk, we display it later.
|
||||||
out_data_ring(ptr, count);
|
out_data_ring(ptr, count);
|
||||||
} else if (count > 0) {
|
} 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;
|
return count;
|
||||||
|
@ -331,6 +331,7 @@ describe('ui/ext_messages', function()
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- kind=verbose for :verbose messages
|
||||||
feed(':1verbose filter Diff[AC] hi<CR>')
|
feed(':1verbose filter Diff[AC] hi<CR>')
|
||||||
screen:expect({
|
screen:expect({
|
||||||
cmdline = { {
|
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)
|
end)
|
||||||
|
|
||||||
it(':echoerr', function()
|
it(':echoerr', function()
|
||||||
|
Reference in New Issue
Block a user