fix(progress): simplify ui-event, introduce default presentation #35527

Problem:
`msg_show` has "progress" info (title, status, percent) which is not presented
by default.

Solution:
Format TUI messages as `{title}: {msg}...{percent}%`. This also gets sent to UI.

- With specific formatting sent to UI we can remove the `progress` item from
  `msg_show` event. It can be added if needed in the future. Also, having
  a default presentation makes the feature more useful.
- For `vim._extui` we just need to implement the replace-msg-with-same-id
  behavior.
- If any UI/plugin wants to do anything fancier, they can handle the `Progress`
  event.
This commit is contained in:
Shadman
2025-08-28 19:33:41 +06:00
committed by GitHub
parent c10e36fc01
commit bc6737250d
5 changed files with 45 additions and 56 deletions

View File

@@ -825,7 +825,7 @@ will be set to zero, but can be changed and used for the replacing cmdline or
message window. Cmdline state is emitted as |ui-cmdline| events, which the UI
must handle.
["msg_show", kind, content, replace_last, history, append, msg_id, progress] ~
["msg_show", kind, content, replace_last, history, append, msg_id] ~
Display a message to the user.
kind
@@ -886,18 +886,6 @@ must handle.
Unique identifier for the message. It can either be an integer or
string. When message of same id appears it should replace the older message.
progress
Progress-message properties:
• title: Title string of the progress message.
• status: Status of the progress message. Can contain one of
the following values
• success: The progress item completed successfully
• running: The progress is ongoing
• failed: The progress item failed
• cancel: The progressing process should be canceled.
• percent: How much progress is done on the progress
message
["msg_clear"] ~
Clear all messages currently displayed by "msg_show", emitted after
clearing the screen (messages sent by other "msg_" events below should

View File

@@ -39,6 +39,11 @@ TREESITTER
• todo
UI
• `progress` attribute removed form |ui-messages| msg_show event
==============================================================================
BREAKING CHANGES *news-breaking*
@@ -190,7 +195,7 @@ EVENTS
• |CmdlineLeavePre| triggered before preparing to leave the command line.
• New `append` paremeter for |ui-messages| `msg_show` event.
• New `msg_id` and `progress` paremeter for |ui-messages| `msg_show` event.
• New `msg_id` paremeter for |ui-messages| `msg_show` event.
• Creating or updating a progress message with |nvim_echo()| triggers a |Progress| event.
HIGHLIGHTS

View File

@@ -165,7 +165,7 @@ void wildmenu_hide(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void msg_show(String kind, Array content, Boolean replace_last, Boolean history, Boolean append,
Object id, Dict progress)
Object id)
FUNC_API_SINCE(6) FUNC_API_FAST FUNC_API_REMOTE_ONLY;
void msg_clear(void)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;

View File

@@ -152,7 +152,6 @@ bool keep_msg_more = false; // keep_msg was set by msgmore()
// Extended msg state, currently used for external UIs with ext_messages
static const char *msg_ext_kind = NULL;
static MsgID msg_ext_id = { .type = kObjectTypeInteger, .data.integer = 0 };
static DictOf(Object) msg_ext_progress = ARRAY_DICT_INIT;
static Array *msg_ext_chunks = NULL;
static garray_T msg_ext_last_chunk = GA_INIT(sizeof(char), 40);
static sattr_T msg_ext_last_attr = -1;
@@ -312,6 +311,7 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
}
is_multihl = true;
msg_ext_skip_flush = true;
bool is_progress = strequal(kind, "progress");
// provide a new id if not given
if (id.type == kObjectTypeNil) {
@@ -323,6 +323,14 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
}
}
// progress message are special displayed as "title: msg...percent%"
if (is_progress && msg_data && msg_data->title.size != 0) {
// this block draws the "title:" before the progress-message
String title = cstr_as_string(concat_str(msg_data->title.data, ": "));
msg_multiline(title, 0, true, false, &need_clear);
api_free_string(title);
}
for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
HlMessageChunk chunk = kv_A(hl_msg, i);
if (err) {
@@ -332,6 +340,13 @@ MsgID msg_multihl(MsgID id, HlMessage hl_msg, const char *kind, bool history, bo
}
assert(!ui_has(kUIMessages) || kind == NULL || msg_ext_kind == kind);
}
if (is_progress && msg_data && msg_data->percent > 0) {
// this block draws the "...percent%" before the progress-message
char percent_buf[10];
vim_snprintf(percent_buf, sizeof(percent_buf), "...%ld%%", (long)msg_data->percent);
msg_multiline(cstr_as_string(percent_buf), 0, true, false, &need_clear);
}
if (history && kv_size(hl_msg)) {
msg_hist_add_multihl(id, hl_msg, false, msg_data);
}
@@ -1106,18 +1121,6 @@ static void msg_hist_add_multihl(MsgID msg_id, HlMessage msg, bool temp, Message
msg_ext_history = true;
msg_ext_id = msg_id;
if (strequal(msg_ext_kind, "progress") && msg_data != NULL && ui_has(kUIMessages)) {
kv_resize(msg_ext_progress, 3);
if (msg_data->title.size != 0) {
PUT_C(msg_ext_progress, "title", STRING_OBJ(msg_data->title));
}
if (msg_data->status.size != 0) {
PUT_C(msg_ext_progress, "status", STRING_OBJ(msg_data->status));
}
if (msg_data->percent >= 0) {
PUT_C(msg_ext_progress, "percent", INTEGER_OBJ(msg_data->percent));
}
}
msg_hist_clear(msg_hist_max);
}
@@ -2210,8 +2213,7 @@ void msg_puts_len(const char *const str, const ptrdiff_t len, int hl_id, bool hi
if (msg_silent != 0 || *str == NUL) {
if (*str == NUL && ui_has(kUIMessages)) {
ui_call_msg_show(cstr_as_string("empty"), (Array)ARRAY_DICT_INIT, false, false, false,
INTEGER_OBJ(-1),
(Dict)ARRAY_DICT_INIT);
INTEGER_OBJ(-1));
}
return;
}
@@ -3239,7 +3241,7 @@ void msg_ext_ui_flush(void)
Array *tofree = msg_ext_init_chunks();
ui_call_msg_show(cstr_as_string(msg_ext_kind), *tofree, msg_ext_overwrite, msg_ext_history,
msg_ext_append, msg_ext_id, msg_ext_progress);
msg_ext_append, msg_ext_id);
// clear info after emiting message.
if (msg_ext_history) {
api_free_array(*tofree);
@@ -3260,7 +3262,6 @@ void msg_ext_ui_flush(void)
msg_ext_append = false;
msg_ext_kind = NULL;
msg_ext_id = INTEGER_OBJ(0);
kv_destroy(msg_ext_progress);
}
}

View File

@@ -3197,12 +3197,7 @@ describe('progress-message', function()
]],
messages = {
{
content = { { 'test-message' } },
progress = {
percent = 10,
status = 'running',
title = 'testsuit',
},
content = { { 'testsuit: test-message...10%' } },
history = true,
id = 1,
kind = 'progress',
@@ -3232,12 +3227,7 @@ describe('progress-message', function()
]],
messages = {
{
content = { { 'test-message-updated' } },
progress = {
percent = 50,
status = 'running',
title = 'TestSuit',
},
content = { { 'TestSuit: test-message-updated...50%' } },
history = true,
id = 1,
kind = 'progress',
@@ -3294,15 +3284,10 @@ describe('progress-message', function()
]],
messages = {
{
content = { { 'test-message' } },
content = { { 'TestSuit: test-message...10%' } },
history = true,
id = 1,
kind = 'progress',
progress = {
percent = 10,
status = 'running',
title = 'TestSuit',
},
},
},
})
@@ -3491,15 +3476,10 @@ describe('progress-message', function()
]],
messages = {
{
content = { { 'supports str-id' } },
content = { { 'TestSuit: supports str-id...30%' } },
history = true,
id = 'str-id',
kind = 'progress',
progress = {
percent = 30,
status = 'running',
title = 'TestSuit',
},
},
},
})
@@ -3519,4 +3499,19 @@ describe('progress-message', function()
data = {},
})
end)
it('tui displays progress message in proper format', function()
clear()
setup_screen(false)
api.nvim_echo(
{ { 'test-message' } },
true,
{ kind = 'progress', title = 'TestSuit', percent = 10, status = 'running' }
)
screen:expect([[
^ |
{1:~ }|*3
TestSuit: test-message...10% |
]])
end)
end)