neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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:
Mruntime/doc/api-ui-events.txt | 14+-------------
Mruntime/doc/news.txt | 7++++++-
Msrc/nvim/api/ui_events.in.h | 2+-
Msrc/nvim/message.c | 35++++++++++++++++++-----------------
Mtest/functional/ui/messages_spec.lua | 43+++++++++++++++++++------------------------
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)