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.
This commit is contained in:
luukvbaal 2024-11-15 23:34:42 +01:00 committed by GitHub
parent f1748b78e3
commit 6e4df18b45
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 33 additions and 4 deletions

View File

@ -1083,7 +1083,9 @@ vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()*
|ui-popupmenu| and the sections below for event format for respective |ui-popupmenu| and the sections below for event format for respective
events. 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. Excessive errors inside the callback will result in forced detachment.

View File

@ -233,7 +233,9 @@ function vim.wait(time, callback, interval, fast_only) end
--- {callback} receives event name plus additional parameters. See |ui-popupmenu| --- {callback} receives event name plus additional parameters. See |ui-popupmenu|
--- and the sections below for event format for respective events. --- 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. --- Excessive errors inside the callback will result in forced detachment.
--- ---

View File

@ -717,6 +717,13 @@ void ui_call_event(char *name, bool fast, Array args)
{ {
bool handled = false; bool handled = false;
UIEventCallback *event_cb; 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, { map_foreach(&ui_event_cbs, ui_event_ns_id, event_cb, {
Error err = ERROR_INIT; Error err = ERROR_INIT;
uint32_t ns_id = ui_event_ns_id; uint32_t ns_id = ui_event_ns_id;

View File

@ -237,20 +237,21 @@ describe('vim.ui_attach', function()
}) })
end) end)
it('aborts :function on error with ext_messages', function() it('msg_show in fast context', function()
exec_lua([[ exec_lua([[
vim.ui_attach(ns, { ext_messages = true }, function(event, _, content) vim.ui_attach(ns, { ext_messages = true }, function(event, _, content)
if event == "msg_show" then if event == "msg_show" then
-- "fast-api" does not prevent aborting :function
vim.api.nvim_get_runtime_file("foo", false) vim.api.nvim_get_runtime_file("foo", false)
-- non-"fast-api" is not allowed in msg_show callback and should be scheduled -- 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] }) 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.schedule(function()
vim.api.nvim_buf_set_lines(0, -2, -1, false, { content[1][2], err }) vim.api.nvim_buf_set_lines(0, -2, -1, false, { content[1][2], err })
end) end)
end end
end) end)
]]) ]])
-- "fast-api" does not prevent aborting :function
feed(':func Foo()<cr>bar<cr>endf<cr>:func Foo()<cr>') feed(':func Foo()<cr>bar<cr>endf<cr>:func Foo()<cr>')
screen:expect({ screen:expect({
grid = [[ 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) end)
it('detaches after excessive errors', function() it('detaches after excessive errors', function()