fix(message): concatenate multi-chunk nvim_echo({err}) for exception message #38131

Problem:  Exception error message only prints the first chunk of a
          multi-chunk nvim_echo() message.
Solution: Concatenate consecutive message chunks in the exception
          message list.
This commit is contained in:
luukvbaal
2026-03-10 15:35:24 +01:00
committed by GitHub
parent c8693051a8
commit b47b0caba8
3 changed files with 19 additions and 6 deletions

View File

@@ -155,7 +155,7 @@ bool aborted_in_try(void)
/// When several messages appear in the same command, the first is usually the
/// most specific one and used as the exception value. The "severe" flag can be
/// set to true, if a later but severer message should be used instead.
bool cause_errthrow(const char *mesg, bool multiline, bool severe, bool *ignore)
bool cause_errthrow(const char *mesg, bool multiline, bool concat, bool severe, bool *ignore)
FUNC_ATTR_NONNULL_ALL
{
msglist_T *elem;
@@ -241,6 +241,12 @@ bool cause_errthrow(const char *mesg, bool multiline, bool severe, bool *ignore)
if (msg_list != NULL) {
msglist_T **plist = msg_list;
while (*plist != NULL) {
// Concatenate (a multihl message) instead.
if ((*plist)->next == NULL && concat) {
(*plist)->msg = xrealloc((*plist)->msg, strlen((*plist)->msg) + strlen(mesg) + 1);
(*plist)->throw_msg = strcat((*plist)->msg, mesg);
return true;
}
plist = &(*plist)->next;
}

View File

@@ -292,8 +292,8 @@ void msg_multiline(String str, int hl_id, bool check_int, bool hist, bool *need_
}
}
// Avoid starting a new message for each chunk and adding message to history in msg_keep().
static bool is_multihl = false;
// Ensure a single msg_show event, msg_list and history entry for entire multihl message.
static int is_multihl = 0;
/// Format a progress message, adding title and percent if given.
///
@@ -360,7 +360,6 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
if (kind != NULL) {
msg_ext_set_kind(kind);
}
is_multihl = true;
msg_ext_skip_flush = true;
// provide a new id if not given
@@ -384,6 +383,7 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
HlMessageChunk chunk = kv_A(hl_msg, i);
is_multihl++;
if (err) {
emsg_multiline(chunk.text.data, kind, chunk.hl_id, true);
} else {
@@ -397,7 +397,7 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
}
msg_ext_skip_flush = false;
is_multihl = false;
is_multihl = 0;
no_wait_return--;
msg_end();
@@ -776,7 +776,7 @@ bool emsg_multiline(const char *s, const char *kind, int hl_id, bool multiline)
// be found, the message will be displayed later on.) "ignore" is set
// when the message should be ignored completely (used for the
// interrupt message).
if (cause_errthrow(s, multiline, severe, &ignore)) {
if (cause_errthrow(s, multiline, is_multihl > 1, severe, &ignore)) {
if (!ignore) {
did_emsg++;
}

View File

@@ -445,6 +445,13 @@ describe('API', function()
api.nvim_exec2('hi VisualNC', { output = true })
eq('VisualNC xxx cleared', api.nvim_exec2('hi VisualNC', { output = true }).output)
end)
it('captures multi-chunk err nvim_echo() #36883', function()
eq(
'nvim_exec2(), line 1: Vim(call):abc',
pcall_err(request, 'nvim_exec2', 'call nvim_echo([["a"],["b"],["c"] ], 0, #{err:1})', {})
)
end)
end)
describe('nvim_command', function()