Skip to content

Commit ab2c595

Browse files
committed
(mini.clue) Prototype: enable autocommand triggers on ModeChanged
1 parent 3a3e19d commit ab2c595

File tree

2 files changed

+44
-29
lines changed

2 files changed

+44
-29
lines changed

lua/mini/clue.lua

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ MiniClue.enable_all_triggers = function()
601601
-- Map only inside valid listed buffers
602602
if vim.fn.buflisted(buf_id) == 1 then H.map_buf_triggers(buf_id) end
603603
end
604+
H.state.disable_autocmd_triggers = false
604605
end
605606

606607
--- Enable triggers in buffer
@@ -617,6 +618,7 @@ MiniClue.disable_all_triggers = function()
617618
for _, buf_id in ipairs(vim.api.nvim_list_bufs()) do
618619
H.unmap_buf_triggers(buf_id)
619620
end
621+
H.state.disable_autocmd_triggers = true
620622
end
621623

622624
--- Disable triggers in buffer
@@ -1190,6 +1192,10 @@ H.create_autocommands = function(config)
11901192
au('RecordingLeave', '*', MiniClue.enable_all_triggers, 'Enable all triggers')
11911193

11921194
au('VimResized', '*', H.window_update, 'Update window on resize')
1195+
1196+
if vim.fn.has('nvim-0.10') == 1 then
1197+
au('ModeChanged', 'n:no', function() H.start_query({ mode = "o", keys = "" }) end, 'Trigger on change to operator-pending mode')
1198+
end
11931199
end
11941200

11951201
--stylua: ignore
@@ -1229,6 +1235,31 @@ H.get_buf_var = function(buf_id, name)
12291235
end
12301236

12311237
-- Triggers -------------------------------------------------------------------
1238+
H.start_query = function(trigger)
1239+
if vim.fn.has('nvim-0.10') == 1 and vim.fn.state('m') ~= '' then
1240+
return
1241+
end
1242+
1243+
if H.state.disable_autocmd_triggers then
1244+
return
1245+
end
1246+
1247+
-- Don't act if for some reason entered another trigger is already active
1248+
local is_in_exec = type(H.exec_trigger) == 'table'
1249+
if is_in_exec then
1250+
return
1251+
end
1252+
1253+
-- Start user query
1254+
H.state_set(trigger, { trigger.keys })
1255+
1256+
-- Do not advance if no other clues to query. NOTE: it is `<= 1` and not
1257+
-- `<= 0` because the "init query" mapping should match.
1258+
if vim.tbl_count(H.state.clues) <= 1 then return H.state_exec() end
1259+
1260+
H.state_advance()
1261+
end
1262+
12321263
H.map_buf_triggers = function(buf_id)
12331264
if not H.is_valid_buf(buf_id) or H.is_disabled(buf_id) then return end
12341265

@@ -1252,33 +1283,13 @@ H.map_trigger = function(buf_id, trigger)
12521283
trigger.keys = H.replace_termcodes(trigger.keys)
12531284
local keys_trans = H.keytrans(trigger.keys)
12541285

1255-
local rhs = function()
1256-
-- Don't act if for some reason entered the same trigger during state exec
1257-
local is_in_exec = type(H.exec_trigger) == 'table'
1258-
and H.exec_trigger.mode == trigger.mode
1259-
and H.exec_trigger.keys == trigger.keys
1260-
if is_in_exec then
1261-
H.exec_trigger = nil
1262-
return
1263-
end
1264-
1265-
-- Start user query
1266-
H.state_set(trigger, { trigger.keys })
1267-
1268-
-- Do not advance if no other clues to query. NOTE: it is `<= 1` and not
1269-
-- `<= 0` because the "init query" mapping should match.
1270-
if vim.tbl_count(H.state.clues) <= 1 then return H.state_exec() end
1271-
1272-
H.state_advance()
1273-
end
1274-
12751286
-- Use buffer-local mappings and `nowait` to make it a primary source of
12761287
-- keymap execution
12771288
local desc = string.format('Query keys after "%s"', keys_trans)
12781289
local opts = { buffer = buf_id, nowait = true, desc = desc }
12791290

12801291
-- Create mapping. Use translated variant to make it work with <F*> keys.
1281-
vim.keymap.set(trigger.mode, keys_trans, rhs, opts)
1292+
vim.keymap.set(trigger.mode, keys_trans, function() H.start_query(trigger) end, opts)
12821293
end
12831294

12841295
H.unmap_trigger = function(buf_id, trigger)
@@ -1372,20 +1383,20 @@ H.state_exec = function()
13721383
local has_postkeys = (clue or {}).postkeys ~= nil
13731384
H.state_reset(has_postkeys)
13741385

1375-
-- Disable trigger !!!VERY IMPORTANT!!!
1386+
-- Disable triggers !!!VERY IMPORTANT!!!
13761387
-- This is a workaround against infinite recursion (like if `g` is trigger
13771388
-- then typing `gg`/`g~` would introduce infinite recursion).
13781389
local buf_id = vim.api.nvim_get_current_buf()
1379-
H.unmap_trigger(buf_id, trigger)
1390+
MiniClue.disable_all_triggers()
13801391

13811392
-- Execute keys. The `i` flag is used to fully support Operator-pending mode.
13821393
-- Flag `t` imitates keys as if user typed, which is reasonable but has small
13831394
-- downside with edge cases of 'langmap' (like ':\;;\;:') as it "inverts" key
13841395
-- meaning second time (at least in Normal mode).
13851396
vim.api.nvim_feedkeys(keys_to_type, 'mit', false)
13861397

1387-
-- Enable trigger back after it can no longer harm
1388-
vim.schedule(function() H.map_trigger(buf_id, trigger) end)
1398+
-- Enable triggers back after it can no longer harm
1399+
vim.schedule(function() MiniClue.enable_all_triggers() end)
13891400

13901401
-- Apply postkeys (in scheduled fashion)
13911402
if has_postkeys then H.state_apply_postkeys(clue.postkeys) end
@@ -1438,8 +1449,11 @@ H.compute_exec_keys = function()
14381449
-- Using `feedkeys()` inside Operator-pending mode leads to its cancel into
14391450
-- Normal/Insert mode so extra work should be done to rebuild all keys
14401451
if vim.startswith(cur_mode, 'no') then
1441-
local operator_tweak = H.operator_tweaks[vim.v.operator] or function(x) return x end
1442-
res = operator_tweak(vim.v.operator .. H.get_forced_submode() .. res)
1452+
res = H.get_forced_submode() .. res
1453+
if H.state.trigger.keys ~= "" then
1454+
local operator_tweak = H.operator_tweaks[vim.v.operator] or function(x) return x end
1455+
res = operator_tweak(vim.v.operator .. res)
1456+
end
14431457
elseif not vim.startswith(cur_mode, 'i') and H.get_default_register() ~= vim.v.register then
14441458
-- Force non-default register but not in Insert mode
14451459
res = '"' .. vim.v.register .. res

tests/test_clue.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,8 +2391,9 @@ T['Reproducing keys']['Operator-pending mode'] = new_set({
23912391

23922392
-- Register trigger. Use zero delay in window to account for possible
23932393
-- clearance of `v:count` and `v:register` inside window update.
2394-
load_module({ triggers = { { mode = 'o', keys = 'i' } }, window = { delay = 0 } })
2395-
validate_trigger_keymap('o', 'i')
2394+
-- load_module({ triggers = { { mode = 'o', keys = 'i' } }, window = { delay = 0 } })
2395+
-- validate_trigger_keymap('o', 'i')
2396+
load_module({ triggers = {}, window = { delay = 0 } })
23962397
end,
23972398
},
23982399
})

0 commit comments

Comments
 (0)