2022-12-05 21:45:50 +08:00
|
|
|
local Loader = require("lazy.core.loader")
|
2023-10-09 17:25:42 +08:00
|
|
|
local Util = require("lazy.core.util")
|
2022-12-05 21:45:50 +08:00
|
|
|
|
2023-10-08 16:11:25 +08:00
|
|
|
---@class LazyKeysBase
|
2022-12-22 17:32:21 +08:00
|
|
|
---@field desc? string
|
|
|
|
---@field noremap? boolean
|
|
|
|
---@field remap? boolean
|
|
|
|
---@field expr? boolean
|
2023-10-08 16:11:25 +08:00
|
|
|
---@field nowait? boolean
|
2023-10-05 20:00:08 +08:00
|
|
|
---@field ft? string|string[]
|
2023-10-08 16:11:25 +08:00
|
|
|
|
|
|
|
---@class LazyKeysSpec: LazyKeysBase
|
|
|
|
---@field [1] string lhs
|
|
|
|
---@field [2]? string|fun()|false rhs
|
|
|
|
---@field mode? string|string[]
|
|
|
|
|
|
|
|
---@class LazyKeys: LazyKeysBase
|
|
|
|
---@field lhs string lhs
|
|
|
|
---@field rhs? string|fun() rhs
|
|
|
|
---@field mode? string
|
2023-01-16 17:16:35 +08:00
|
|
|
---@field id string
|
2023-10-17 04:34:44 +08:00
|
|
|
---@field name string
|
2022-12-22 17:32:21 +08:00
|
|
|
|
2022-12-05 21:45:50 +08:00
|
|
|
---@class LazyKeysHandler:LazyHandler
|
|
|
|
local M = {}
|
|
|
|
|
2023-10-17 04:34:44 +08:00
|
|
|
local skip = { mode = true, id = true, ft = true, rhs = true, lhs = true }
|
|
|
|
|
2023-10-08 16:11:25 +08:00
|
|
|
---@param value string|LazyKeysSpec
|
|
|
|
---@param mode? string
|
|
|
|
---@return LazyKeys
|
|
|
|
function M.parse(value, mode)
|
|
|
|
value = type(value) == "string" and { value } or value --[[@as LazyKeysSpec]]
|
|
|
|
local ret = vim.deepcopy(value) --[[@as LazyKeys]]
|
|
|
|
ret.lhs = ret[1] or ""
|
|
|
|
ret.rhs = ret[2]
|
|
|
|
---@diagnostic disable-next-line: no-unknown
|
|
|
|
ret[1] = nil
|
|
|
|
---@diagnostic disable-next-line: no-unknown
|
|
|
|
ret[2] = nil
|
|
|
|
ret.mode = mode or "n"
|
|
|
|
ret.id = vim.api.nvim_replace_termcodes(ret.lhs, true, true, true)
|
2023-10-17 04:34:44 +08:00
|
|
|
|
2024-01-20 21:11:32 +08:00
|
|
|
if ret.ft then
|
|
|
|
local ft = type(ret.ft) == "string" and { ret.ft } or ret.ft --[[@as string[] ]]
|
|
|
|
ret.id = ret.id .. " (" .. table.concat(ft, ", ") .. ")"
|
|
|
|
end
|
|
|
|
|
2023-10-08 16:11:25 +08:00
|
|
|
if ret.mode ~= "n" then
|
|
|
|
ret.id = ret.id .. " (" .. ret.mode .. ")"
|
2023-01-16 17:16:35 +08:00
|
|
|
end
|
2022-12-23 00:49:32 +08:00
|
|
|
return ret
|
2022-12-22 17:32:21 +08:00
|
|
|
end
|
|
|
|
|
2023-10-17 04:34:44 +08:00
|
|
|
---@param keys LazyKeys
|
|
|
|
function M.to_string(keys)
|
|
|
|
return keys.lhs .. (keys.mode == "n" and "" or " (" .. keys.mode .. ")")
|
|
|
|
end
|
|
|
|
|
2023-10-08 16:11:25 +08:00
|
|
|
---@param lhs string
|
|
|
|
---@param mode? string
|
|
|
|
function M:have(lhs, mode)
|
|
|
|
local keys = M.parse(lhs, mode)
|
2023-10-09 01:14:33 +08:00
|
|
|
return self.managed[keys.id] ~= nil
|
2023-10-08 16:11:25 +08:00
|
|
|
end
|
|
|
|
|
2023-10-17 04:34:44 +08:00
|
|
|
function M:_values(values)
|
|
|
|
return M.resolve(values)
|
2023-10-08 16:11:25 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
---@param spec? (string|LazyKeysSpec)[]
|
|
|
|
function M.resolve(spec)
|
|
|
|
---@type LazyKeys[]
|
2023-01-16 17:16:35 +08:00
|
|
|
local values = {}
|
|
|
|
---@diagnostic disable-next-line: no-unknown
|
2023-10-08 16:11:25 +08:00
|
|
|
for _, value in ipairs(spec or {}) do
|
|
|
|
value = type(value) == "string" and { value } or value --[[@as LazyKeysSpec]]
|
|
|
|
value.mode = value.mode or "n"
|
|
|
|
local modes = (type(value.mode) == "table" and value.mode or { value.mode }) --[=[@as string[]]=]
|
|
|
|
for _, mode in ipairs(modes) do
|
|
|
|
local keys = M.parse(value, mode)
|
|
|
|
if keys.rhs == vim.NIL or keys.rhs == false then
|
|
|
|
values[keys.id] = nil
|
|
|
|
else
|
|
|
|
values[keys.id] = keys
|
|
|
|
end
|
2023-01-16 17:16:35 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
return values
|
|
|
|
end
|
|
|
|
|
2023-10-08 16:11:25 +08:00
|
|
|
---@param keys LazyKeys
|
2022-12-22 17:32:21 +08:00
|
|
|
function M.opts(keys)
|
2023-10-08 16:11:25 +08:00
|
|
|
local opts = {} ---@type LazyKeysBase
|
|
|
|
---@diagnostic disable-next-line: no-unknown
|
2022-12-22 17:32:21 +08:00
|
|
|
for k, v in pairs(keys) do
|
2023-10-08 16:11:25 +08:00
|
|
|
if type(k) ~= "number" and not skip[k] then
|
|
|
|
---@diagnostic disable-next-line: no-unknown
|
2022-12-22 17:32:21 +08:00
|
|
|
opts[k] = v
|
2022-12-22 02:01:58 +08:00
|
|
|
end
|
2022-12-22 17:32:21 +08:00
|
|
|
end
|
|
|
|
return opts
|
|
|
|
end
|
|
|
|
|
2024-06-06 16:15:33 +08:00
|
|
|
---@param keys LazyKeys
|
|
|
|
function M.is_nop(keys)
|
|
|
|
return type(keys.rhs) == "string" and (keys.rhs == "" or keys.rhs:lower() == "<nop>")
|
|
|
|
end
|
|
|
|
|
2023-01-16 17:16:35 +08:00
|
|
|
---@param keys LazyKeys
|
|
|
|
function M:_add(keys)
|
2023-10-08 16:11:25 +08:00
|
|
|
local lhs = keys.lhs
|
2022-12-23 00:49:32 +08:00
|
|
|
local opts = M.opts(keys)
|
2022-12-25 23:17:36 +08:00
|
|
|
|
2023-10-05 20:00:08 +08:00
|
|
|
---@param buf? number
|
|
|
|
local function add(buf)
|
2024-06-06 16:15:33 +08:00
|
|
|
if M.is_nop(keys) then
|
2024-06-06 15:28:35 +08:00
|
|
|
return self:_set(keys, buf)
|
|
|
|
end
|
|
|
|
|
2023-10-05 20:00:08 +08:00
|
|
|
vim.keymap.set(keys.mode, lhs, function()
|
|
|
|
local plugins = self.active[keys.id]
|
2022-12-25 23:17:36 +08:00
|
|
|
|
2023-10-05 20:00:08 +08:00
|
|
|
-- always delete the mapping immediately to prevent recursive mappings
|
2023-10-08 02:41:06 +08:00
|
|
|
self:_del(keys)
|
2023-10-05 20:00:08 +08:00
|
|
|
self.active[keys.id] = nil
|
2023-02-08 23:00:56 +08:00
|
|
|
|
2023-10-05 20:00:08 +08:00
|
|
|
if plugins then
|
2023-10-17 04:34:44 +08:00
|
|
|
local name = M.to_string(keys)
|
|
|
|
Util.track({ keys = name })
|
|
|
|
Loader.load(plugins, { keys = name })
|
2023-10-05 20:00:08 +08:00
|
|
|
Util.track()
|
|
|
|
end
|
|
|
|
|
2024-03-08 00:30:37 +08:00
|
|
|
if keys.mode:sub(-1) == "a" then
|
|
|
|
lhs = lhs .. "<C-]>"
|
2024-01-21 18:40:46 +08:00
|
|
|
end
|
2023-10-05 20:00:08 +08:00
|
|
|
local feed = vim.api.nvim_replace_termcodes("<Ignore>" .. lhs, true, true, true)
|
|
|
|
-- insert instead of append the lhs
|
|
|
|
vim.api.nvim_feedkeys(feed, "i", false)
|
|
|
|
end, {
|
|
|
|
desc = opts.desc,
|
|
|
|
nowait = opts.nowait,
|
|
|
|
-- we do not return anything, but this is still needed to make operator pending mappings work
|
|
|
|
expr = true,
|
|
|
|
buffer = buf,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2023-10-08 02:41:06 +08:00
|
|
|
-- buffer-local mappings
|
2023-10-05 20:00:08 +08:00
|
|
|
if keys.ft then
|
|
|
|
vim.api.nvim_create_autocmd("FileType", {
|
|
|
|
pattern = keys.ft,
|
|
|
|
callback = function(event)
|
2024-06-06 16:15:33 +08:00
|
|
|
if self.active[keys.id] and not M.is_nop(keys) then
|
2023-10-05 20:00:08 +08:00
|
|
|
add(event.buf)
|
|
|
|
else
|
|
|
|
-- Only create the mapping if its managed by lazy
|
|
|
|
-- otherwise the plugin is supposed to manage it
|
2023-10-08 02:41:06 +08:00
|
|
|
self:_set(keys, event.buf)
|
2023-10-05 20:00:08 +08:00
|
|
|
end
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
else
|
|
|
|
add()
|
|
|
|
end
|
2022-12-05 21:45:50 +08:00
|
|
|
end
|
|
|
|
|
2024-05-21 03:15:03 +08:00
|
|
|
-- Delete a mapping and create the real global/buffer-local
|
2023-10-08 02:41:06 +08:00
|
|
|
-- mapping when needed
|
|
|
|
---@param keys LazyKeys
|
|
|
|
function M:_del(keys)
|
2024-05-21 03:15:03 +08:00
|
|
|
-- bufs will be all buffers of the filetype for a buffer-local mapping
|
|
|
|
-- OR `false` for a global mapping
|
2024-05-22 04:10:49 +08:00
|
|
|
local bufs = { false }
|
|
|
|
|
|
|
|
if keys.ft then
|
|
|
|
local ft = type(keys.ft) == "string" and { keys.ft } or keys.ft --[[@as string[] ]]
|
|
|
|
bufs = vim.tbl_filter(function(buf)
|
|
|
|
return vim.tbl_contains(ft, vim.bo[buf].filetype)
|
|
|
|
end, vim.api.nvim_list_bufs())
|
|
|
|
end
|
2024-05-21 03:15:03 +08:00
|
|
|
|
|
|
|
for _, buf in ipairs(bufs) do
|
|
|
|
pcall(vim.keymap.del, keys.mode, keys.lhs, { buffer = buf or nil })
|
|
|
|
self:_set(keys, buf or nil)
|
2023-10-08 02:41:06 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Create a mapping if it is managed by lazy
|
2023-01-16 17:16:35 +08:00
|
|
|
---@param keys LazyKeys
|
2023-10-05 20:00:08 +08:00
|
|
|
---@param buf number?
|
2023-10-08 02:41:06 +08:00
|
|
|
function M:_set(keys, buf)
|
2023-10-08 16:11:25 +08:00
|
|
|
if keys.rhs then
|
2023-10-05 20:00:08 +08:00
|
|
|
local opts = M.opts(keys)
|
2023-10-08 16:11:25 +08:00
|
|
|
---@diagnostic disable-next-line: inject-field
|
2023-10-05 20:00:08 +08:00
|
|
|
opts.buffer = buf
|
2023-10-08 16:11:25 +08:00
|
|
|
vim.keymap.set(keys.mode, keys.lhs, keys.rhs, opts)
|
2022-12-22 17:32:21 +08:00
|
|
|
end
|
2022-12-05 21:45:50 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
return M
|