local function parse_mode(mode)
local function startswith(prefix)
return mode:find(prefix, 1, true) == 1
end
if startswith 'no' then
return { 'o', '' }
elseif startswith 'n' then
return { 'n', '' }
end
if startswith 'v' or startswith 'V' or startswith '' then
return { 'x', 'v', '' }
end
if startswith 's' or startswith 'S' or startswith '' then
return { 's', 'v' }
end
if startswith 'i' or startswith 'R' then
return { 'i' }
end
if startswith 'c' then
return { 'c' }
end
if startswith 't' then
return { 't' }
end
return {}
end
local setup_done = {}
local function add_unique(list, value)
for _, existing in ipairs(list) do
if existing == value then
return
end
end
table.insert(list, value)
end
local function all_loaded(ids)
for _, id in ipairs(ids) do
if not require '_rsplug'.loaded[id] then
return false
end
end
return true
end
local pattern_modes = {}
local pattern_ids = {}
local id_patterns = {}
return {
setup = function(mode)
for _, mode_char in ipairs(parse_mode(mode)) do
if not setup_done[mode_char] then
setup_done[mode_char] = true
local exists, mod = pcall(require, '_rsplug/on_map/mode_' .. mode_char)
for pattern, ids in pairs(exists and mod or {}) do
if all_loaded(ids) then
goto continue
end
if not pattern_modes[pattern] then
pattern_modes[pattern] = {}
pattern_ids[pattern] = {}
end
table.insert(pattern_modes[pattern], mode_char)
for _, id in ipairs(ids) do
add_unique(pattern_ids[pattern], id)
if not id_patterns[id] then
id_patterns[id] = {}
end
add_unique(id_patterns[id], pattern)
end
vim.keymap.set(mode_char, pattern, function()
local all_ids = pattern_ids[pattern] or ids
if all_loaded(all_ids) then
pcall(vim.keymap.del, mode_char, pattern, {})
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(pattern, true, false, true), 'imt', true)
return ''
end
local patterns_to_delete = {}
for _, id in ipairs(all_ids) do
local related_patterns = id_patterns[id] or {}
for _, related_pattern in ipairs(related_patterns) do
patterns_to_delete[related_pattern] = true
end
end
for pattern_to_delete, _ in pairs(patterns_to_delete) do
local modes = pattern_modes[pattern_to_delete] or {}
for _, m in ipairs(modes) do
pcall(vim.keymap.del, m, pattern_to_delete, {})
end
pattern_modes[pattern_to_delete] = nil
pattern_ids[pattern_to_delete] = nil
end
for _, id in ipairs(all_ids) do
require '_rsplug'.packadd(id)
id_patterns[id] = nil
end
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(pattern, true, false, true), 'imt', true)
return ''
end, { expr = true, silent = true })
::continue::
end
end
end
end,
}