neovim

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

commit 6e4df18b457e9743c34068fd6e0a89fd04d3526c
parent f1748b78e3165a0821a11f5ae1fb9398aa67c535
Author: luukvbaal <luukvbaal@gmail.com>
Date:   Fri, 15 Nov 2024 23:34:42 +0100

fix(ui): no fast context for prompt message kinds #31224

Problem:  No longer able to show prompt messages with vim.ui_attach().
Solution: Do not execute callback in fast context for prompt message
          kinds. These events must be safe to show the incoming message
          so the event itself serves to indicate that the message
          should be shown immediately.
Diffstat:
Mruntime/doc/lua.txt | 4+++-
Mruntime/lua/vim/_meta/builtin.lua | 4+++-
Msrc/nvim/ui.c | 7+++++++
Mtest/functional/lua/ui_event_spec.lua | 22++++++++++++++++++++--
4 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt @@ -1083,7 +1083,9 @@ vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()* |ui-popupmenu| and the sections below for event format for respective events. - Callbacks for `msg_show` events are executed in |api-fast| context. + Callbacks for `msg_show` events are executed in |api-fast| context unless + Nvim will wait for input, in which case messages should be shown + immediately. Excessive errors inside the callback will result in forced detachment. diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua @@ -233,7 +233,9 @@ function vim.wait(time, callback, interval, fast_only) end --- {callback} receives event name plus additional parameters. See |ui-popupmenu| --- and the sections below for event format for respective events. --- ---- Callbacks for `msg_show` events are executed in |api-fast| context. +--- Callbacks for `msg_show` events are executed in |api-fast| context unless +--- Nvim will wait for input, in which case messages should be shown +--- immediately. --- --- Excessive errors inside the callback will result in forced detachment. --- diff --git a/src/nvim/ui.c b/src/nvim/ui.c @@ -717,6 +717,13 @@ void ui_call_event(char *name, bool fast, Array args) { bool handled = false; UIEventCallback *event_cb; + + // Prompt messages should be shown immediately so must be safe + if (strcmp(name, "msg_show") == 0) { + char *kind = args.items[0].data.string.data; + fast = !kind || (strncmp(kind, "confirm", 7) != 0 && strcmp(kind, "return_prompt") != 0); + } + map_foreach(&ui_event_cbs, ui_event_ns_id, event_cb, { Error err = ERROR_INIT; uint32_t ns_id = ui_event_ns_id; diff --git a/test/functional/lua/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua @@ -237,20 +237,21 @@ describe('vim.ui_attach', function() }) end) - it('aborts :function on error with ext_messages', function() + it('msg_show in fast context', function() exec_lua([[ vim.ui_attach(ns, { ext_messages = true }, function(event, _, content) if event == "msg_show" then - -- "fast-api" does not prevent aborting :function vim.api.nvim_get_runtime_file("foo", false) -- non-"fast-api" is not allowed in msg_show callback and should be scheduled local _, err = pcall(vim.api.nvim_buf_set_lines, 0, -2, -1, false, { content[1][2] }) + pcall(vim.api.nvim__redraw, { flush = true }) vim.schedule(function() vim.api.nvim_buf_set_lines(0, -2, -1, false, { content[1][2], err }) end) end end) ]]) + -- "fast-api" does not prevent aborting :function feed(':func Foo()<cr>bar<cr>endf<cr>:func Foo()<cr>') screen:expect({ grid = [[ @@ -267,6 +268,23 @@ describe('vim.ui_attach', function() }, }, }) + -- No fast context for prompt message kinds + feed(':%s/Function/Replacement/c<cr>') + screen:expect({ + grid = [[ + ^E122: {10:Function} Foo already exists, add !| + to replace it | + replace with Replacement (y/n/a/q/l/^E/^| + Y)? | + {1:~ }| + ]], + messages = { + { + content = { { 'replace with Replacement (y/n/a/q/l/^E/^Y)?', 6, 19 } }, + kind = 'confirm_sub', + }, + }, + }) end) it('detaches after excessive errors', function()