folke / which-key.nvim

πŸ’₯ Create key bindings that stick. WhichKey helps you remember your Neovim keymaps, by showing available keybindings in a popup as you type.
Apache License 2.0
5.12k stars 163 forks source link

bug: which-key getting into a deadlock state and not setting up trigger #787

Closed mehalter closed 1 month ago

mehalter commented 1 month ago

Did you check docs and existing issues?

Neovim version (nvim -v)

NVIM v0.10.0 (github release)

Operating system/version

Arch Linux

Describe the bug

I have found a fascinatingly specific situation where which-key seems to not set up it's trigger for some reason when entering a buffer. I'm not sure what could be causing it. It seems to be the combination of fzf-lua, rustaceanvim, and the manual re-triggering of filetypedetect autocommand group

If I remove any of the other 2 plugins it works, if I remove the triggering of the filetype it works, if I just run :e foo/src/main.rs it also works

Steps To Reproduce

  1. Have the repro.lua in your current path
  2. cargo new --bin foo, create a new rust project
  3. nvim -u repro.lua, run the configuration
  4. \, press the leader key and see that it triggers the menu
  5. <Esc>, close the menu
  6. :FzfLua files, open the file picker and select src/main.rs
  7. \, press the leader key and see that it doesn't trigger the pop up
  8. :messages, do basically anything else
  9. \ see that the menu triggers now in the buffer just fine

Expected Behavior

which-key should trigger and not get stuck in a deadlock state where it doesn't set up it's trigger.

Health

which-key: require("which-key.health").check()

- OK Most of these checks are for informational purposes only.
  WARNINGS should be treated as a warning, and don't necessarily indicate a problem with your config.
  Please |DON't| report these warnings as an issue.

Checking your config ~
- WARNING |mini.icons| is not installed
- WARNING |nvim-web-devicons| is not installed
- WARNING Keymap icon support will be limited.

Checking for issues with your mappings ~
- OK No issues reported

checking for overlapping keymaps ~
- WARNING In mode `n`, <gc> overlaps with <gcc>:
  - <gc>: Toggle comment
  - <gcc>: Toggle comment line
- OK Overlapping keymaps are only reported for informational purposes.
  This doesn't necessarily mean there is a problem with your config.

Checking for duplicate mappings ~
- OK No duplicate mappings found

Log

Debug Started for v3.12.0
new Mode(n:1)
Trigger(add) Mode(n:1) " ' ` z= g' g` [ <C-W> \ z g ]
on_key: \
State(start): Mode(n:0) Node(\) { keys = "\\" }
  update Mode(n:1)
  continue: \ Mode(n:1)
  getchar
  on_key: <Esc>
  got: <Esc>
on_key: :
ModeChanged(n:c)
  new Mode(c:1)
  Safe(true)
Trigger(add) Mode(c:1) <C-R>
on_key: F
on_key: z
on_key: f
on_key: L
on_key: u
on_key: a
on_key: <Space>
on_key: f
on_key: i
on_key: l
on_key: <Tab>
on_key: <CR>
ModeChanged(c:n)
  Unsafe(command-mode)
  suspend: Mode(n:1)
  Trigger(del) Mode(n:1) g' g` [ <C-W> \ z " ] ' ` z= g
BufNew(6)
BufNew(7)
BufNew(8)
BufNew(9)
ModeChanged(n:nt)
  new Mode(n:7)
  cooldown
ModeChanged(nt:t)
  new Mode(t:7)
  cooldown
Trigger(add) Mode(n:7) " ' ` z= g' g` [ <C-W> \ z g ]
Trigger(add) Mode(n:1) " ' ` z= g' g` [ <C-W> \ z g ]
BufNew(10)
ModeChanged(t:n)
  new Mode(n:10)
  Unsafe(pending "z")
  suspend: Mode(n:10)
ModeChanged(n:t)
  new Mode(t:10)
  cooldown
ModeChanged(t:n)
  cooldown
ModeChanged(n:t)
  cooldown
ModeChanged(t:n)
  cooldown
Trigger(add) Mode(n:10) " ' ` z= g' g` [ <C-W> \ z g ]
on_key: m
on_key: a
on_key: i
BufNew(11)
ModeChanged(n:t)
  new Mode(t:11)
  Unsafe(pending "z")
  suspend: Mode(t:11)
ModeChanged(t:n)
  new Mode(n:11)
  cooldown
ModeChanged(n:t)
  cooldown
ModeChanged(t:n)
  cooldown
ModeChanged(n:t)
  cooldown
ModeChanged(t:n)
  cooldown
ModeChanged(n:t)
  cooldown
ModeChanged(t:n)
  cooldown
on_key: n
Trigger(add) Mode(n:11) " ' ` z= g' g` [ <C-W> \ z g ]
on_key: <CR>
BufEnter(1)
  new Mode(t:1)
ModeChanged(n:t)
  Unsafe(pending "m")
  suspend: Mode(t:1)
ModeChanged(t:n)
  cooldown
BufNew(1)
  Trigger(del) Mode(c:1) <C-R>
  Trigger(del) Mode(n:1) ] " ' ` z= g' g` [ z g \ <C-W>
BufReadPost(1)
BufEnter(1)
  new Mode(t:1)
ModeChanged(n:t)
  cooldown
ModeChanged(t:n)
  new Mode(n:1)
  cooldown
Trigger(add) Mode(n:1) " ' ` z= g' g` [ <C-W> \ z g ]
LspAttach(1)
  Trigger(del) Mode(n:1) g' g` [ <C-W> \ z g ] " ' ` z=
new Mode(t:1)
on_key: \
on_key: <Esc>
on_key: :
ModeChanged(n:c)
  new Mode(c:1)
  Safe(true)
Trigger(add) Mode(c:1) <C-R>
on_key: q
on_key: !
on_key: <CR>
ModeChanged(c:n)
  new Mode(n:1)
  Unsafe(command-mode)
  suspend: Mode(n:1)
Trigger(add) Mode(n:1) " ' ` z= g' g` [ z <C-W> \ ] g

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/which-key.nvim", opts = {} },
    { "ibhagwan/fzf-lua", cmd = "FzfLua" },
    { "mrcjkb/rustaceanvim", version = "^4", ft = "rust" },
    -- add any other plugins here
  },
})

-- create test keymap
vim.keymap.set("n", "<Leader>t", function()
  vim.print("Hello, World!")
end, { desc = "test" })

local done
vim.api.nvim_create_autocmd("BufReadPost", {
  callback = function(args)
    if not done then
      vim.schedule(function()
        vim.api.nvim_exec_autocmds(
          "BufReadPost",
          { group = "filetypedetect", buffer = args.buf, data = args.data }
        )
        done = true
      end)
    end
  end,
})
folke commented 1 month ago

Something seems off looking at your log. Will investigate!

mehalter commented 1 month ago

Thanks so much! I know this is a pretty funky one with some very specific situations, sorry it's not the most concise/straight forward situation πŸ˜“

folke commented 1 month ago

hmm, so I don't seem to be able to reproduce this...

folke commented 1 month ago

Notice that in my log, right after LspAttach, the triggers get added again:

Trigger(add) Mode(n:1) ' " ` g' g` z= g z ] [ <C-W> \
LspAttach(1)
  Trigger(del) Mode(n:1) ' " ` g' g` z= <C-W> g z ] [ \
new Mode(t:1)
new Mode(n:1)
Trigger(add) Mode(n:1) ' " ` g' g` z= g ] \ z [ <C-W>

In your log for some reason, they don't

folke commented 1 month ago

Where do you run nvim -u repro.lua? In the foo directory?

folke commented 1 month ago

It looks like you are still in terminal mode for some reason

mehalter commented 1 month ago

woahhhh I just noticed that I couldn't reproduce it anymore πŸ˜‚ only difference is my computer is plugged in.... I have CPU throttling on battery power which decreases the clock speed to save battery. I unplugged my computer and the issue is happening 100% of the time. It seems like something in which-key must have some sort of race condition that when my CPU is working at it's full power it's totally fine, and when it's running on slower clock speeds it gets into that weird situation

mehalter commented 1 month ago

Here is a recording: https://asciinema.org/a/vgHhjSmdVmrBy4wzCU6OrPASe

folke commented 1 month ago

that's indeed very odd πŸ˜…. Will further look into it

folke commented 1 month ago

Can reproduce when I put my laptop in power saving mode :)

folke commented 1 month ago

This really looks like a Neovim bug.

  buf 1
  new Mode(t:1)
ModeChanged(n:t)
  mode t
  buf 1
  cooldown
ModeChanged(t:n)
  mode n
  buf 1
  new Mode(n:1)
  cooldown
Trigger(add) Mode(n:1) " ` ' z= g` g' z \ g [ ] <C-W>
mode t
buf 1
LspAttach(1)
  Trigger(del) Mode(n:1) [ ] <C-W> " ` ' z= g` g' z \ g
mode t
buf 1
new Mode(t:1)

In the log you can see a ModeChanged event happened from t to n, but then further in the code all of the sudden vim.api.nvim_get_mode() returns t again...

folke commented 1 month ago

Would some of the filetypedetect stuff execute shell commands maybe?

mehalter commented 1 month ago

Maybe, the main thing is that when I'm sitting in the buffer I'm definitely in normal mode at some point because I can navigate through the buffer and do other commands. Also I can replicate it in a full AstroNvim installation with a similar setup where the statusline shows the current mode and it shows that I'm in Normal mode. So it seems like which-key isn't picked it up that it's moving back to normal mode if it's in terminal mode for some period of time.

mehalter commented 1 month ago

I looked to see if there was some sort of scheduling issue where things are running out of order basically:

Here is the end of my logs when the error happens. What we have seen before, it being put into terminal mode:

LspAttach(8)
  Trigger(del) Mode(n:8) ' " ` z= g` g' < <Space> z ] [ <C-W> > g
new Mode(t:8)
on_key: <Space>
on_key: <Space>
on_key: Z
on_key: Z

If I go to where the mode change autocommand is and do callback = schedule_wrap(function(ev) ... end), I see this:

LspAttach(7)
ModeChanged(n:t)
  new Mode(t:7)
  Safe(true)
ModeChanged(t:n)
  Safe(true)
on_key: j
on_key: j
on_key: k
on_key: k
on_key: <Space>
on_key: <Space>
on_key: <Esc>
on_key: Z
on_key: Z

which actually captures the mode change back from terminal mode to normal mode, but the triggers are not added back.

mehalter commented 1 month ago

It does seem like the schedule is probably necessary to make sure things are running in order because looking at the log it does look a bit more sensible. I'm now trying to figure out why it is that after the ModeChanged event is triggered with t:n the mode is still reporting as t and not n like the event said. It's supposed to happen after the mode is changed πŸ€”

mehalter commented 1 month ago

Ok @folke I have a small PR put together with changes that make this work. Let me know what you think. Hopefully it can help out at least in some small way. For reals thanks for taking a serious look at this, the herculean effort for maintaining such a huge part of the Neovim ecosystem is so appreciated!

folke commented 1 month ago

I think that should fix it. Would be great if you can confirm.

mehalter commented 1 month ago

Looks great! I just tested it and it seems to work on my end. Thanks again so so much for looking into such a strange error πŸ˜…

mehalter commented 1 month ago

Oh no, I think this commit may have really messed things up now. Now I am getting this behavior all the time even on my full CPU power.

If I revert https://github.com/folke/which-key.nvim/commit/c1b062ae95c3ca3e6eb87c075da991523605d79b then it goes back to working

Here is a log of me opening an init.lua file from Telescope:

Debug Started for v3.13.0
{
  commit = "c5e799388989fe1b87072d6188719b529d7421c5"
}
new Mode(n:1)
Trigger(add) Mode(n:1) ' " ` g` g' z= g <Space> ] [ <C-W> > < z
on_key: <Space>
State(start): Mode(n:0) Node(<Space>) { keys = "<Space>" }
  update Mode(n:1)
  continue: <Space> Mode(n:1)
  getchar
  on_key: f
  got: f
  continue: <Space>f Mode(n:1)
  getchar
  on_key: f
  got: f
  suspend: Mode(n:1)
  Trigger(del) Mode(n:1) ` g` g' z= > < z <C-W> ' [ ] " <Space> g
  feedkeys: Mode(n:1) <Space>ff
on_key: <Space>ff
BufNew(3)
BufNew(4)
BufNew(5)
BufNew(6)
BufNew(7)
BufNew(8)
BufEnter(7)
  new Mode(n:7)
ModeChanged(n:i)
  new Mode(i:7)
  Unsafe(pending "<80>")
  suspend: Mode(i:7)
on_key: i
Trigger(add) Mode(i:7) <C-R>
Trigger(add) Mode(n:7) ' " ` g` g' z= g <Space> ] [ z <C-W> > <
Trigger(add) Mode(n:1) ' " ` g` g' z= g <Space> ] [ <C-W> > < z
BufNew(10)
on_key: n
on_key: i
on_key: t
on_key: .
on_key: l
on_key: u
on_key: a
on_key: <CR>
BufEnter(1)
  new Mode(i:1)
BufNew(1)
  Trigger(del) Mode(n:1) > < z <C-W> z= ' " ` g` g' g <Space> ] [
BufReadPost(1)
BufEnter(1)
  new Mode(i:1)
Trigger(add) Mode(i:1) <C-R>
Trigger(del) Mode(i:1) <C-R>
LspAttach(1)
new Mode(i:1)
Trigger(add) Mode(i:1) <C-R>
on_key: <Space>
on_key: Z
on_key: Z
mehalter commented 1 month ago

It must be a different cause because the very specific case in the original issue is fine, but I'm getting it in my full blown configuration very frequently

mehalter commented 1 month ago

ah @folke I have a new one for you. Apparently that commit breaks the ability to use the built in vim mkview

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/which-key.nvim", event = "VeryLazy", opts = {} },
    { "nvim-telescope/telescope.nvim", tag = "0.1.8", dependencies = { "nvim-lua/plenary.nvim" } },
    -- add any other plugins here
  },
})

vim.g.mapleader = " "

-- create test keymap
vim.keymap.set("n", "<Leader>ff", function()
  require("telescope.builtin").find_files()
end, { desc = "find files" })

vim.api.nvim_create_autocmd("BufWinEnter", {
  desc = "Try to load file view if available and enable view saving for real files",
  callback = function(event)
    if not vim.b[event.buf].view_activated then
      local filetype = vim.bo[event.buf].filetype
      local buftype = vim.bo[event.buf].buftype
      local ignore_filetypes = { "gitcommit", "gitrebase", "svg", "hgcommit" }
      if buftype == "" and filetype and filetype ~= "" and not vim.tbl_contains(ignore_filetypes, filetype) then
        vim.b[event.buf].view_activated = true
        vim.cmd.loadview({ mods = { emsg_silent = true } })
      end
    end
  end,
})
vim.api.nvim_create_autocmd({ "BufWinLeave", "BufWritePost", "WinLeave" }, {
  desc = "Save view with mkview for real files",
  callback = function(event)
    if vim.b[event.buf].view_activated then
      vim.cmd.mkview({ mods = { emsg_silent = true } })
    end
  end,
})

Steps:

  1. rm -rf .repro, make sure to have a clean environment
  2. nvim -u repro.lua, load up the above configuration
  3. <Space>ff, use Telescope and select a file, repro.lua is a good once since we know it's there
  4. <Space>, see that which-key is not triggering

EDIT: adding wk.log from the above

wk.log ``` Debug Started for v3.13.0 { commit = "c5e799388989fe1b87072d6188719b529d7421c5" } new Mode(n:1) Trigger(add) Mode(n:1) ' ` " z= g' g` z g ] [ on_key: State(start): Mode(n:0) Node() { keys = "" } update Mode(n:1) continue: Mode(n:1) getchar on_key: f got: f continue: f Mode(n:1) getchar on_key: f got: f suspend: Mode(n:1) Trigger(del) Mode(n:1) z g ] ' ` " z= [ g' g` feedkeys: Mode(n:1) ff on_key: ff BufNew(4) BufNew(5) BufNew(6) BufNew(7) BufNew(8) BufNew(9) BufEnter(8) new Mode(n:8) ModeChanged(n:i) new Mode(i:8) Safe(true) Trigger(add) Mode(n:8) ' ` " z= g' g` z g ] [ Trigger(add) Mode(n:1) ' ` " z= g' g` z g ] [ Trigger(add) Mode(i:8) BufNew(10) on_key: r BufNew(11) on_key: e on_key: p on_key: BufEnter(1) new Mode(i:1) BufNew(1) Trigger(del) Mode(n:1) ' ` " z= g' g` z g ] [ BufReadPost(1) BufEnter(1) new Mode(i:1) Trigger(add) Mode(i:1) on_key: on_key: Z on_key: Z ```
folke commented 1 month ago

That's very weird, as you can see there's no ModeChanged i:n? (your other message)

mehalter commented 1 month ago

Yeah! So strange 😦 Here is the log without the caching commit where it works correctly, there is still no ModeChanged from i:n πŸ€”

Debug Started for v3.12.0
new Mode(n:1)
Trigger(add) Mode(n:1) ` ' " z= g' g` <C-W> z <Space> g ] [
on_key: <Space>
State(start): Mode(n:0) Node(<Space>) { keys = "<Space>" }
  update Mode(n:1)
  continue: <Space> Mode(n:1)
  getchar
  on_key: f
  got: f
  continue: <Space>f Mode(n:1)
  getchar
  on_key: f
  got: f
  suspend: Mode(n:1)
  Trigger(del) Mode(n:1) z= g' g` <C-W> z <Space> g ` [ ' " ]
  feedkeys: Mode(n:1) <Space>ff
on_key: <Space>ff
BufNew(4)
BufNew(5)
BufNew(6)
BufNew(7)
BufNew(8)
BufNew(9)
BufEnter(8)
  new Mode(n:8)
ModeChanged(n:i)
  new Mode(i:8)
  Safe(true)
Trigger(add) Mode(n:1) ` ' " z= g' g` <C-W> z <Space> g ] [
Trigger(add) Mode(n:8) ` ' " z= g' g` <C-W> z <Space> g ] [
Trigger(add) Mode(i:8) <C-R>
BufNew(10)
on_key: r
BufNew(11)
on_key: e
on_key: p
on_key: <CR>
BufEnter(1)
  new Mode(i:1)
BufNew(1)
  Trigger(del) Mode(n:1) [ ` ' " z= g' g` <C-W> z <Space> g ]
BufReadPost(1)
BufEnter(1)
  new Mode(i:1)
Trigger(add) Mode(i:1) <C-R>
new Mode(n:1)
Trigger(add) Mode(n:1) ` ' " z= g' g` <C-W> z <Space> g ] [
on_key: <Space>
State(start): Mode(n:0) Node(<Space>) { keys = "<Space>" }
  update Mode(n:1)
  continue: <Space> Mode(n:1)
  getchar
  on_key: <Esc>
  got: <Esc>
on_key: Z
on_key: Z
folke commented 1 month ago

I do get the ModeChanged for both versions:

BufNew(4)
BufNew(5)
BufEnter(4)
  new Mode(n:4)
ModeChanged(n:i)
  new Mode(i:4)
  Unsafe(pending "<80>")
  suspend: Mode(i:4)
Trigger(add) Mode(n:4) " ` ' g' g` z= <Space> g <C-W> z = [ > ] <
Trigger(add) Mode(n:1) " ` ' g' g` z= <Space> <C-W> z = > ] [ < gr gs
Trigger(add) Mode(i:4) <C-R>
BufNew(7)
on_key: i
on_key: n
on_key: i
on_key: <CR>
BufEnter(1)
  new Mode(i:1)
BufNew(8)
BufReadPost(8)
BufEnter(8)
  new Mode(i:8)
ModeChanged(i:n)
  new Mode(n:8)
  Safe(true)
Trigger(add) Mode(i:8) <C-R>
Trigger(add) Mode(n:8) " ` ' g' g` z= <Space> g <C-W> z = [ > ] <
LspAttach(8)
  Trigger(del) Mode(i:8) <C-R>
  Trigger(del) Mode(n:8) " ` ' g' g` z= <Space> g <C-W> z = [ > ] <
new Mode(n:8)
Trigger(add) Mode(n:8) " ` ' g` g' z= <Space> g <C-W> z = [ > ] <
BufNew(9)
LspAttach(8)
  Trigger(del) Mode(n:8) " ` ' g' g` z= <Space> g <C-W> z = [ > ] <
new Mode(n:8)
Trigger(add) Mode(n:8) " ` ' g` g' z= <Space> g <C-W> z = [ > ] <
BufNew(10)
BufNew(11)
folke commented 1 month ago

What Neovim version are you using?

folke commented 1 month ago

I'm on latest nightly

mehalter commented 1 month ago

I'm on Neovim v0.10 release

mehalter commented 1 month ago

Let me try nightly

mehalter commented 1 month ago

Hm, I just tested on the latest nightly and I get the same behavior. Let me try throttling my CPU

folke commented 1 month ago

Can you try to see what happens with debug disabled?

mehalter commented 1 month ago

I get the same behavior with debug disabled, also with my CPU in powersaver and performance mode, both on latest stable and latest nightly

Are you saying you cannot replicate even given the new repro.lua file and the replication steps?

mehalter commented 1 month ago

I have tested it on Ubuntu, Red Hat, and Arch Linux and can replicate it on all 3, all on different machines πŸ€”

folke commented 1 month ago

I'm still trying to find out why you don't see a ModeChanged event for i:n, while I do

mehalter commented 1 month ago

Yeah, is that while using the exact repro.lua code I sent above with the loadview call in the autocmd? I would definitely expect that you would see the same thing in the logs that I do

folke commented 1 month ago

I'll try the exact repro. just a sec

folke commented 1 month ago

For me it works and I do get the ModeChanged i:n. This is all very very weird....

State(start): Mode(n:0) Node(<Space>) { keys = "<Space>" }
  update Mode(n:1)
  continue: <Space> Mode(n:1)
  getchar
  on_key: f
  got: f
  continue: <Space>f Mode(n:1)
  getchar
  on_key: f
  got: f
  suspend: Mode(n:1)
  Trigger(del) Mode(n:1) z= g` g' z <Space> <C-W> ` g ] [ " '
  feedkeys: Mode(n:1) <Space>ff
on_key: <Space>ff
BufNew(6)
BufNew(7)
BufNew(8)
BufNew(9)
BufEnter(8)
  new Mode(n:8)
ModeChanged(n:i)
  new Mode(i:8)
  Safe(true)
Trigger(add) Mode(i:8) <C-R>
Trigger(add) Mode(n:8) ` " ' z= g` g' <C-W> <Space> z g ] [
Trigger(add) Mode(n:1) ` " ' z= g` g' <C-W> <Space> z g ] [
on_key: i
on_key: n
on_key: i
on_key: <CR>
BufEnter(1)
  new Mode(i:1)
BufNew(1)
  Trigger(del) Mode(c:1) <C-R>
  Trigger(del) Mode(n:1) ` " ' z= g` [ ] g g' <C-W> <Space> z
BufReadPost(1)
BufEnter(1)
  new Mode(i:1)
ModeChanged(i:n)
  new Mode(n:1)
  Safe(true)
Trigger(add) Mode(i:1) <C-R>
Trigger(add) Mode(n:1) ` " ' z= g` g' <C-W> <Space> z g ] [
on_key: <Space>
State(start): Mode(n:0) Node(<Space>) { keys = "<Space>" }
  update Mode(n:1)
  continue: <Space> Mode(n:1)
  getchar
  on_key: <Esc>
  got: <Esc>
on_key: <LeftRelease>
mehalter commented 1 month ago

Hm this is very very strange πŸ€”

Here is a recording of me walking through the whole replication process if that's helpful: https://asciinema.org/a/Dp0vwbYEuXDpRRKGXCW8yIaRY

folke commented 1 month ago

So it seems that doing a normal! command skips ModeChanged.

If you're in insert mode and then an autocmd does normal, there will never be a ModeChanged event back to normal.

folke commented 1 month ago
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/which-key.nvim",
            event = "VeryLazy",
            dev = true,
            opts = { debug = true },
        },
        { "nvim-telescope/telescope.nvim", tag = "0.1.8", dependencies = { "nvim-lua/plenary.nvim" } },
        -- add any other plugins here
    },
})

vim.g.mapleader = " "

-- create test keymap
vim.keymap.set("n", "<Leader>ff", function()
    require("telescope.builtin").find_files()
end, { desc = "find files" })

vim.api.nvim_create_autocmd("BufWinEnter", {
    callback = function()
        vim.cmd("normal! zE")
    end,
})
folke commented 1 month ago

Without which-key:

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 = {
        { "nvim-telescope/telescope.nvim", tag = "0.1.8", dependencies = { "nvim-lua/plenary.nvim" } },
        -- add any other plugins here
    },
})

vim.g.mapleader = " "

-- create test keymap
vim.keymap.set("n", "<Leader>ff", function()
    require("telescope.builtin").find_files()
end, { desc = "find files" })

vim.api.nvim_create_autocmd("BufWinEnter", {
    callback = function()
        vim.cmd("normal! zE")
    end,
})

vim.api.nvim_create_autocmd("ModeChanged", {
    callback = function(ev)
        print(ev.match)
    end,
})
folke commented 1 month ago

This is really bad. It means that my approach with ModeChanged will never work correctly. I have an idea on how I can possibly fix this.

folke commented 1 month ago

I've reverted that cached mode check and changed it to a timer that does a api-fast check every 50ms to see if the current buf or current mode changed. If so, it will ensure the mode exists for the buffer.

This should fix both repros you provided.

The fact that using :norm inside an autocmd skips ModeChanged events does smell like a Neovim bug. I can't see any reason why that would make sense...

mehalter commented 1 month ago

Hm, I'm getting very bad behavior now. I can replicate on a fresh installation of LazyVim. If I open lazyvim with a fresh install, press f to open the file picker from the dashboard, and select a file, then which-key is not working

mehalter commented 1 month ago

Here is a recording with using a clean installation of LazyVim: https://asciinema.org/a/w8bUi82Uyhz8BcgRb7QDqFQUD

folke commented 1 month ago

Can you show the log for that? I can't reproduce this with a fresh lazyvim install unfortunately.

mehalter commented 1 month ago

Sure, here is a log:

Debug Started for v3.13.0
{
  branch = "main",
  commit = "388bd3f83de06d1a1758ea6a342cf3ae614401f1"
}
new Mode(n:2)
BufNew(4)
Trigger(add) Mode(n:2) ' " ` z= g' g` z ] [ g <C-W> \ <Space>
on_key: q
BufEnter(1)
  new Mode(n:1)
Trigger(add) Mode(n:1) ' " ` g' g` z= <Space> ] [ g <C-W> z
on_key: f
BufNew(5)
BufNew(6)
BufNew(7)
BufNew(8)
BufNew(9)
BufNew(10)
BufEnter(9)
  new Mode(n:9)
ModeChanged(n:i)
  new Mode(i:9)
  Unsafe(pending "<80>")
  suspend: Mode(i:9)
BufNew(12)
Trigger(add) Mode(n:9) ' " ` g' g` z= <Space> ] [ g <C-W> z
Trigger(add) Mode(i:9) <C-R>
BufNew(13)
BufNew(14)
on_key: i
BufNew(15)
on_key: n
on_key: i
on_key: <CR>
BufEnter(1)
  new Mode(i:1)
BufNew(16)
BufReadPost(16)
BufEnter(16)
  new Mode(i:16)
ModeChanged(i:n)
  new Mode(n:16)
  Safe(true)
Trigger(add) Mode(i:16) <C-R>
Trigger(add) Mode(n:16) ' " ` z= g' g` z ] [ g <C-W> <Space>
BufNew(17)
BufNew(18)
LspAttach(16)
  Trigger(del) Mode(n:16) g' g` z ] [ g <C-W> <Space> ' " ` z=
  Trigger(del) Mode(i:16) <C-R>
on_key: <Space>
BufNew(19)
BufNew(20)
on_key: <Space>
on_key: Z
on_key: Z
folke commented 1 month ago

Just pushed another change that hopefully does fix it for you as well now. Can you check?

folke commented 1 month ago

Problem is that I didn't account for mode clear(). So when your pc is slow (or fast) after an LspAttach, it could be that the mode no longe changed, but that the mode was cleared.

mehalter commented 1 month ago

Ah I see, I think things are working as intended now. I'll let you know if anything else pops up regarding this πŸ˜