Skip to content

Commit 8a12a01

Browse files
authored
feat(progress): better default format + history sync neovim#35533
Problem: The default progress message doesn't account for message-status. Also, the title and percent sections don't get written to history. And progress percent is hard to find with variable length messages. Solution: Apply highlighting on Title based on status. And sync the formated msg in history too. Also updates the default progress message format to {title}: {percent}% msg
1 parent 4cda52a commit 8a12a01

File tree

10 files changed

+211
-34
lines changed

10 files changed

+211
-34
lines changed

runtime/doc/news.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ HIGHLIGHTS
204204
|hl-DiffTextAdd| highlights added text within a changed line.
205205
|hl-StderrMsg| |hl-StdoutMsg|
206206
|hl-SnippetTabstopActive| highlights the currently active tabstop.
207+
|hl-OkMsg| highlights success messages.
207208

208209
LSP
209210

runtime/doc/syntax.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5263,6 +5263,8 @@ EndOfBuffer Filler lines (~) after the last line in the buffer.
52635263
By default, this is highlighted like |hl-NonText|.
52645264
*hl-TermCursor*
52655265
TermCursor Cursor in a focused terminal.
5266+
*hl-OkMsg*
5267+
OkMsg Success messages on the command line.
52665268
*hl-ErrorMsg*
52675269
ErrorMsg Error messages on the command line.
52685270
*hl-StderrMsg*

src/nvim/api/vim.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ Union(Integer, String) nvim_echo(ArrayOf(Tuple(String, *HLGroupID)) chunks, Bool
796796
}
797797

798798
bool is_progress = strequal(kind, "progress");
799+
bool needs_clear = !history;
799800

800801
VALIDATE(is_progress
801802
|| (opts->status.size == 0 && opts->title.size == 0 && opts->percent == 0
@@ -822,7 +823,7 @@ Union(Integer, String) nvim_echo(ArrayOf(Tuple(String, *HLGroupID)) chunks, Bool
822823
MessageData msg_data = { .title = opts->title, .status = opts->status,
823824
.percent = opts->percent, .data = opts->data };
824825

825-
id = msg_multihl(opts->id, hl_msg, kind, history, opts->err, &msg_data);
826+
id = msg_multihl(opts->id, hl_msg, kind, history, opts->err, &msg_data, &needs_clear);
826827

827828
if (opts->verbose) {
828829
verbose_leave();
@@ -833,8 +834,8 @@ Union(Integer, String) nvim_echo(ArrayOf(Tuple(String, *HLGroupID)) chunks, Bool
833834
do_autocmd_progress(id, hl_msg, &msg_data);
834835
}
835836

836-
if (history) {
837-
// history takes ownership
837+
if (!needs_clear) {
838+
// history takes ownership of `hl_msg`
838839
return id;
839840
}
840841

src/nvim/highlight.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ EXTERN const char *hlf_names[] INIT( = {
8484
[HLF_BFOOTER] = "FloatFooter",
8585
[HLF_TS] = "StatusLineTerm",
8686
[HLF_TSNC] = "StatusLineTermNC",
87+
[HLF_OK] = "OkMsg",
8788
});
8889

8990
EXTERN int highlight_attr[HLF_COUNT]; // Highl. attr for each context.

src/nvim/highlight_defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ typedef enum {
132132
HLF_TSNC, ///< status line for non-current terminal window
133133
HLF_SE, ///< stderr messages (from shell)
134134
HLF_SO, ///< stdout messages (from shell)
135+
HLF_OK, ///< OK message
135136
HLF_COUNT, ///< MUST be the last one
136137
} hlf_T;
137138

src/nvim/highlight_group.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ static const char *highlight_init_light[] = {
375375
"MoreMsg guifg=NvimDarkCyan ctermfg=6",
376376
"NonText guifg=NvimLightGrey4",
377377
"NormalFloat guibg=NvimLightGrey1",
378+
"OkMsg guifg=NvimDarkGreen ctermfg=2",
378379
"Pmenu guibg=NvimLightGrey3 cterm=reverse",
379380
"PmenuThumb guibg=NvimLightGrey4",
380381
"Question guifg=NvimDarkCyan ctermfg=6",
@@ -459,6 +460,7 @@ static const char *highlight_init_dark[] = {
459460
"MoreMsg guifg=NvimLightCyan ctermfg=14",
460461
"NonText guifg=NvimDarkGrey4",
461462
"NormalFloat guibg=NvimDarkGrey1",
463+
"OkMsg guifg=NvimLightGreen ctermfg=10",
462464
"Pmenu guibg=NvimDarkGrey3 cterm=reverse",
463465
"PmenuThumb guibg=NvimDarkGrey4",
464466
"Question guifg=NvimLightCyan ctermfg=14",

src/nvim/lua/executor.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,8 @@ static void nlua_print_event(void **argv)
994994
HlMessage msg = KV_INITIAL_VALUE;
995995
HlMessageChunk chunk = { { .data = argv[0], .size = (size_t)(intptr_t)argv[1] - 1 }, 0 };
996996
kv_push(msg, chunk);
997-
msg_multihl(INTEGER_OBJ(0), msg, "lua_print", true, false, NULL);
997+
bool needs_clear = false;
998+
msg_multihl(INTEGER_OBJ(0), msg, "lua_print", true, false, NULL, &needs_clear);
998999
}
9991000

10001001
/// Print as a Vim message

src/nvim/message.c

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -292,14 +292,61 @@ void msg_multiline(String str, int hl_id, bool check_int, bool hist, bool *need_
292292
// Avoid starting a new message for each chunk and adding message to history in msg_keep().
293293
static bool is_multihl = false;
294294

295+
/// Format a progress message, adding title and percent if given.
296+
///
297+
/// @param hl_msg Message chunks
298+
/// @param msg_data Additional data for progress messages
299+
static HlMessage format_progress_message(HlMessage hl_msg, MessageData *msg_data)
300+
{
301+
HlMessage updated_msg = KV_INITIAL_VALUE;
302+
// progress messages are special. displayed as "title: percent% msg"
303+
if (msg_data->title.size != 0) {
304+
// this block draws the "title:" before the progress-message
305+
int hl_id = 0;
306+
if (msg_data->status.data == NULL) {
307+
hl_id = 0;
308+
} else if (strequal(msg_data->status.data, "success")) {
309+
hl_id = syn_check_group("OkMsg", STRLEN_LITERAL("OkMsg"));
310+
} else if (strequal(msg_data->status.data, "failed")) {
311+
hl_id = syn_check_group("ErrorMsg", STRLEN_LITERAL("ErrorMsg"));
312+
} else if (strequal(msg_data->status.data, "running")) {
313+
hl_id = syn_check_group("MoreMsg", STRLEN_LITERAL("MoreMsg"));
314+
} else if (strequal(msg_data->status.data, "cancel")) {
315+
hl_id = syn_check_group("WarningMsg", STRLEN_LITERAL("WarningMsg"));
316+
}
317+
kv_push(updated_msg,
318+
((HlMessageChunk){ .text = copy_string(msg_data->title, NULL), .hl_id = hl_id }));
319+
kv_push(updated_msg, ((HlMessageChunk){ .text = cstr_to_string(": "), .hl_id = 0 }));
320+
}
321+
if (msg_data->percent > 0) {
322+
char percent_buf[10];
323+
vim_snprintf(percent_buf, sizeof(percent_buf), "%3ld%% ", (long)msg_data->percent);
324+
String percent = cstr_to_string(percent_buf);
325+
int hl_id = syn_check_group("WarningMsg", STRLEN_LITERAL("WarningMsg"));
326+
kv_push(updated_msg, ((HlMessageChunk){ .text = percent, .hl_id = hl_id }));
327+
}
328+
329+
if (kv_size(updated_msg) != 0) {
330+
for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
331+
kv_push(updated_msg,
332+
((HlMessageChunk){ .text = copy_string(kv_A(hl_msg, i).text, NULL),
333+
.hl_id = kv_A(hl_msg, i).hl_id }));
334+
}
335+
return updated_msg;
336+
} else {
337+
return hl_msg;
338+
}
339+
}
340+
295341
/// Print message chunks, each with their own highlight ID.
296342
///
297343
/// @param hl_msg Message chunks
298344
/// @param kind Message kind (can be NULL to avoid setting kind)
299345
/// @param history Whether to add message to history
300346
/// @param err Whether to print message as an error
347+
/// @param msg_data Additional data for progress messages
301348
MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bool err,
302-
MessageData *msg_data)
349+
MessageData *msg_data, bool *needs_msg_clear)
303350
{
304351
no_wait_return++;
305352
msg_start();
@@ -311,7 +358,6 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
311358
}
312359
is_multihl = true;
313360
msg_ext_skip_flush = true;
314-
bool is_progress = strequal(kind, "progress");
315361

316362
// provide a new id if not given
317363
if (id.type == kObjectTypeNil) {
@@ -323,12 +369,13 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
323369
}
324370
}
325371

326-
// progress message are special displayed as "title: msg...percent%"
327-
if (is_progress && msg_data && msg_data->title.size != 0) {
328-
// this block draws the "title:" before the progress-message
329-
String title = cstr_as_string(concat_str(msg_data->title.data, ": "));
330-
msg_multiline(title, 0, true, false, &need_clear);
331-
api_free_string(title);
372+
// progress message are special displayed as "title: percent% msg"
373+
if (strequal(kind, "progress") && msg_data) {
374+
HlMessage formated_message = format_progress_message(hl_msg, msg_data);
375+
if (formated_message.items != hl_msg.items) {
376+
*needs_msg_clear = true;
377+
hl_msg = formated_message;
378+
}
332379
}
333380

334381
for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
@@ -341,12 +388,6 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
341388
assert(!ui_has(kUIMessages) || kind == NULL || msg_ext_kind == kind);
342389
}
343390

344-
if (is_progress && msg_data && msg_data->percent > 0) {
345-
// this block draws the "...percent%" before the progress-message
346-
char percent_buf[10];
347-
vim_snprintf(percent_buf, sizeof(percent_buf), "...%ld%%", (long)msg_data->percent);
348-
msg_multiline(cstr_as_string(percent_buf), 0, true, false, &need_clear);
349-
}
350391
if (history && kv_size(hl_msg)) {
351392
msg_hist_add_multihl(id, hl_msg, false, msg_data);
352393
}
@@ -1265,7 +1306,8 @@ void ex_messages(exarg_T *eap)
12651306
}
12661307
if (redirecting() || !ui_has(kUIMessages)) {
12671308
msg_silent += ui_has(kUIMessages);
1268-
msg_multihl(INTEGER_OBJ(0), p->msg, p->kind, false, false, NULL);
1309+
bool needs_clear = false;
1310+
msg_multihl(INTEGER_OBJ(0), p->msg, p->kind, false, false, NULL, &needs_clear);
12691311
msg_silent -= ui_has(kUIMessages);
12701312
}
12711313
}

test/functional/ui/cursor_spec.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ describe('ui/cursor', function()
262262
m.attr = { background = Screen.colors.DarkGray }
263263
end
264264
if m.id_lm then
265-
m.id_lm = 75
265+
m.id_lm = 76
266266
m.attr_lm = {}
267267
end
268268
end

0 commit comments

Comments
 (0)