commit bc6737250d61703d07d7a95ba83ebf841f5454b9
parent c10e36fc016cb265026a772571ce0a405df2ab71
Author: Shadman <shadmansaleh3@gmail.com>
Date: Thu, 28 Aug 2025 19:33:41 +0600
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.
Diffstat:
5 files changed, 45 insertions(+), 56 deletions(-)
diff --git a/runtime/doc/api-ui-events.txt b/runtime/doc/api-ui-events.txt
@@ -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
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -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
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
@@ -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;
diff --git a/src/nvim/message.c b/src/nvim/message.c
@@ -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);
}
}
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
@@ -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)