Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Noice confirmation prompts are broken on nightly #1036

Open
4 tasks done
PriceHiller opened this issue Jan 14, 2025 · 2 comments
Open
4 tasks done

bug: Noice confirmation prompts are broken on nightly #1036

PriceHiller opened this issue Jan 14, 2025 · 2 comments
Labels
bug Something isn't working

Comments

@PriceHiller
Copy link

PriceHiller commented Jan 14, 2025

Did you check docs and existing issues?

  • I have read all the noice.nvim docs
  • I have updated the plugin to the latest version before submitting this issue
  • I have searched the existing issues of noice.nvim
  • I have searched the existing issues of plugins related to this issue

Neovim version (nvim -v)

0.11.x, commit >= 48e2a73

Operating system/version

NixOS 25.05

Describe the bug

(Sorry for the super long issue, but I got a bit wrapped up into this late last night and figured I'd share my thoughts).

The issue

After Neovim merged neovim/neovim#31525 prompt messages are no longer correctly handled by Noice.

Related: #998

Two Problems:

  1. The button prompting in the popup is now gone for responding to confirmation inputs.
  2. The commandline popup window remains open after a confirmation dialogue is responded to with a valid choice.
Issues upstream from Neovim (?)

Unfortunately, like @folke noticed in the upstream PR for the prompt messages (neovim/neovim#31525 (comment)), the cmdline_show event does not inform us if we have a confirmation event.

A bigger problem is that the cmdline_show event for confirmation prompts fails to send the actual confirmation message along in vim.ui_attach. There's no way to determine what you're actually confirming in the new model when intercepting vim.ui_attach. The cmdline_show event only puts the confirmation prompt into the cmdline_show->prompt, but never the confirmation message. This means external ui providers are boned when it comes to correctly prompting for confirmations :/.

Steps To Reproduce

  1. Ensure you have Neovim installed with a version containing commit neovim/neovim@48e2a73
  2. Attempt to use a confirmation input: :lua vim.fn.confirm("Save changes?", "&Yes\n&No\n&Cancel")

Expected Behavior

One of two behaviors would occur:

1. Most ideally, we get the old behavior with the confirmation popup.

With a bit of nasty hacking what we can do is capture the msg_show event where kind == "confirm" and then hang onto confirmation info in a separate state variable. Then, when the next cmdline_show event hits with the confirmation prompt we can do a bit of magic to shove the prompt back up into the confirmation popup. This also allows us to capture the confirmation message in that state storage avoiding issues around the missing message in cmdline_show.

This hack around is messy, it would be better if upstream Neovim had an additional field informing ui_attach listeners when a confirmation event hits.

Problem with this: It seems the intent from upstream Neovim is to eventually remove the entire msg_show: confirm event at some point and opt for that to be entirely held in the cmdline_show: prompt stuff. So this may be a temporary hack that eventually breaks 🤷.

I actually tried this, but I don't understand enough on how Noice works under the hood with the confirmation popup and the cmdline_show magic to do this the right way.

2. We use the cmdline window popup and ensure we close out the popup when the commandline is left.

A Hack/Patch to do this below:

diff --git a/lua/noice/ui/init.lua b/lua/noice/ui/init.lua
index 4fa98cc..e762e62 100644
--- a/lua/noice/ui/init.lua
+++ b/lua/noice/ui/init.lua
@@ -128,6 +128,20 @@ function M.enable()
       vim.api.nvim_input("<cr>")
       return true
     end
+    -- HACK: handle confirmation event on nvim commit >= 48e2a73610ca5639408f79b3d8eebd3e5f57a327
+    if event == "msg_show" and kind == "confirm" then
+      vim.schedule(function()
+        vim.api.nvim_create_autocmd("CmdlineLeave", {
+          group = vim.api.nvim_create_augroup("noice-cmdline-leave-confirm", { clear = true }),
+          callback = function()
+            vim.wait(50, vim.in_fast_event, 10)
+            Util.try(Router.update)
+            return true
+          end,
+        })
+      end)
+      return
+    end
     local handler = M.get_handler(event, kind, ...)
     if not handler then
       return

What this does:

  • Disables the old prompting for the confirmation menu popup by returning early
  • Correctly cleans up the commandline popup after the cursor exits the commandline on CmdlineLeave

This is slightly sketchy with the way vim.wait works, there is a small chance we don't remove the cmdline popup. I haven't ran into this problem at all, but it is technically possible.

Repro

vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()

require("lazy.minit").repro({
    spec = {
        { "folke/noice.nvim", opts = {} },
        -- add any other plugins here
    },
})

-- Not sure *why* this has to be scheduled when using `lazy.minit`, but it _does_ 🤷
vim.schedule(function()
    vim.fn.confirm("Save changes?", "&Yes\n&No\n&Cancel")
end)
@PriceHiller PriceHiller added the bug Something isn't working label Jan 14, 2025
@luukvbaal
Copy link

  1. The button prompting in the popup is now gone for responding to confirmation inputs.

The way to achieve this has changed, but should still be possible. Scheduled events are now processed during the cmdline prompt, so you can schedule message events, and check whether a cmdline_event event with prompt is currently open to route them to a different "view". That's what I'm doing in neovim/neovim#27855 currently.

  1. The commandline popup window remains open after a confirmation dialogue is responded to with a valid choice.

This was fixed in neovim/neovim#32033.

@PriceHiller
Copy link
Author

The way to achieve this has changed, but should still be possible. Scheduled events are now processed during the cmdline prompt, so you can schedule message events, and check whether a cmdline_event event with prompt is currently open to route them to a different "view". That's what I'm doing in neovim/neovim#27855 currently.

I'll take a look at your implementation later, thanks for providing it -- it'll be a great help.

Just to save me a bit of trouble, do you get the confirmation message as well?

When I looked at vim.ui_attach I was able to get the prompt no problem, but the actual message from vim.fn.confirm("Save changes?", "&Yes\n&No\n&Cancel"), "Save Changes?" didn't appear to get sent in vim.ui_attach, only the prompt ""&Yes\n&No\n&Cancel".

This was fixed in neovim/neovim#32033.

Awesome! Thanks 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants