Skip to content

Commit 388bd3f

Browse files
committed
fix(state): deal with the fact that ModeChanged doesn't always seems to trigger. Fixes #787
1 parent c5e7993 commit 388bd3f

File tree

4 files changed

+23
-23
lines changed

4 files changed

+23
-23
lines changed

lua/which-key/buf.lua

-7
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,6 @@ function M.clear(opts)
242242
M.bufs[b]:clear(opts)
243243
end
244244
end
245-
if opts.check ~= false then
246-
M.check()
247-
end
248245
end
249246

250-
M.check = Util.debounce(50, function()
251-
M.get()
252-
end)
253-
254247
return M

lua/which-key/mappings.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ function M.add(mapping, ret, opts)
276276
local modes = mapping.mode or { "n" } --[[@as string|string[] ]]
277277
modes = type(modes) == "string" and vim.split(modes, "") or modes --[[@as string[] ]]
278278
for _, mode in ipairs(modes) do
279-
if mode ~= "v" and mode ~= Util.mapmode({ mode = mode }) then
279+
if mode ~= "v" and mode ~= Util.mapmode(mode) then
280280
M.warn("Invalid mode `" .. mode .. "`", mapping)
281281
end
282282
local m = vim.deepcopy(mapping)

lua/which-key/state.lua

+19-10
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,8 @@ function M.setup()
5757
callback = function(ev)
5858
Util.debug(ev.event)
5959
if ev.event == "RecordingEnter" then
60-
Buf.clear({ buf = ev.buf, check = false })
60+
Buf.clear({ buf = ev.buf })
6161
M.stop()
62-
else
63-
Buf.check()
6462
end
6563
end,
6664
})
@@ -89,16 +87,11 @@ function M.setup()
8987
return Config.defer(ctx)
9088
end
9189

92-
-- this prevents restarting which-key in the same tick
9390
local cooldown = Util.cooldown()
94-
95-
-- cache the mode, since it can change outside of ModeChanged events
96-
Util.mode = vim.api.nvim_get_mode().mode
97-
91+
-- this prevents restarting which-key in the same tick
9892
vim.api.nvim_create_autocmd("ModeChanged", {
9993
group = group,
10094
callback = function(ev)
101-
Util.mode = vim.api.nvim_get_mode().mode
10295
Util.trace("ModeChanged(" .. ev.match .. ")")
10396
local mode = Buf.get()
10497

@@ -147,16 +140,32 @@ function M.setup()
147140
end,
148141
})
149142

143+
local current_buf = vim.api.nvim_get_current_buf()
150144
vim.api.nvim_create_autocmd({ "BufEnter" }, {
151145
group = group,
152146
callback = function(ev)
147+
current_buf = ev.buf ---@type number
153148
Util.trace(ev.event .. "(" .. ev.buf .. ")")
154149
Buf.get()
155150
Util.trace()
156151
end,
157152
})
158153

159-
Buf.check()
154+
-- HACK: ModeChanged does not always trigger, so we need to manually
155+
-- check for mode changes. This seems to be due to the usage of `:norm` in autocmds.
156+
-- See https://github.com/folke/which-key.nvim/issues/787
157+
local last_mode = nil ---@type string?
158+
local last_buf = nil ---@type number?
159+
local timer = uv.new_timer()
160+
timer:start(0, 50, function()
161+
local mode = vim.api.nvim_get_mode().mode
162+
if mode == last_mode and last_buf == current_buf then
163+
return
164+
end
165+
last_mode = mode
166+
last_buf = current_buf
167+
vim.schedule(Buf.get)
168+
end)
160169
end
161170

162171
function M.stop()

lua/which-key/util.lua

+3-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ M.BS = M.t("<bs>")
1717
M.EXIT = M.t("<C-\\><C-n>")
1818
M.LUA_CALLBACK = "\x80\253g"
1919
M.CMD = "\x80\253h"
20-
M.mode = "n"
2120

2221
function M.exit()
2322
vim.api.nvim_feedkeys(M.EXIT, "n", false)
@@ -77,10 +76,9 @@ function M.keys(lhs, opts)
7776
return ret
7877
end
7978

80-
---@param opts? {mode?: string, cached?: boolean}
81-
function M.mapmode(opts)
82-
opts = opts or {}
83-
local mode = opts.mode or (opts.cached ~= false and M.mode) or vim.api.nvim_get_mode().mode
79+
---@param mode? string
80+
function M.mapmode(mode)
81+
mode = mode or vim.api.nvim_get_mode().mode
8482
mode = mode:gsub(M.t("<C-V>"), "v"):gsub(M.t("<C-S>"), "s"):lower()
8583
if mode:sub(1, 2) == "no" then
8684
return "o"

0 commit comments

Comments
 (0)