diff options
-rw-r--r-- | runtime/doc/lua.txt | 4 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/builtin.lua | 4 | ||||
-rw-r--r-- | src/nvim/ui.c | 7 | ||||
-rw-r--r-- | test/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 index e6f7e62e02..243c907180 100644 --- 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 index dd6ef69eb8..b8779b66fe 100644 --- 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 index d50747e63f..7c81110ae9 100644 --- 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 index f78fced14e..0580442d0a 100644 --- 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() |