lazy.nvim/lua/lazy/core/handler.lua

159 lines
4.2 KiB
Lua

local Util = require("lazy.core.util")
local Loader = require("lazy.core.loader")
---@class LazyPluginHandlers
---@field event? string|string[]
---@field cmd? string|string[]
---@field ft? string|string[]
---@field module? string|string[]
---@field keys? string|string[]
local M = {}
---@alias LazyHandler fun(grouped:table<string, string[]>)
---@type table<string, table<string, string[]>>
M._groups = nil
---@param plugins LazyPlugin[]
---@param rebuild? boolean
function M.group(plugins, rebuild)
if M._groups == nil or rebuild then
M._groups = {}
local types = vim.tbl_keys(M.handlers) --[[@as string[] ]]
for _, key in ipairs(types) do
M._groups[key] = {}
for _, plugin in pairs(plugins) do
if plugin[key] then
---@diagnostic disable-next-line: no-unknown
for _, value in pairs(type(plugin[key]) == "table" and plugin[key] or { plugin[key] }) do
M._groups[key][value] = M._groups[key][value] or {}
table.insert(M._groups[key][value], plugin.name)
end
end
end
end
end
return M._groups
end
---@type table<string, LazyHandler>
M.handlers = {}
function M.handlers.event(grouped)
local group = vim.api.nvim_create_augroup("lazy_handler_event", { clear = true })
for event, plugins in pairs(grouped) do
---@cast event string
if event == "VimEnter" and vim.v.vim_did_enter == 1 then
Loader.load(plugins, { event = event })
else
local _event, pattern = event:match("^(%w+)%s+(.*)$")
vim.api.nvim_create_autocmd(_event or event, {
group = group,
once = true,
pattern = pattern,
callback = function()
Util.track({ event = event })
Loader.load(plugins, { event = event })
Util.track()
end,
})
end
end
end
function M.handlers.keys(grouped)
for keys, plugins in pairs(grouped) do
---@cast keys string
vim.keymap.set("n", keys, function()
vim.keymap.del("n", keys)
Util.track({ keys = keys })
Loader.load(plugins, { keys = keys })
vim.api.nvim_input(keys)
Util.track()
end)
end
end
function M.handlers.ft(grouped)
local group = vim.api.nvim_create_augroup("lazy_handler_ft", { clear = true })
for ft, plugins in pairs(grouped) do
---@cast ft string
vim.api.nvim_create_autocmd("FileType", {
once = true,
pattern = ft,
group = group,
callback = function()
Util.track({ ft = ft })
Loader.load(plugins, { ft = ft })
Util.track()
end,
})
end
end
function M.handlers.cmd(grouped)
for cmd, plugins in pairs(grouped) do
---@cast cmd string
local function _load()
vim.api.nvim_del_user_command(cmd)
Util.track({ cmd = cmd })
Loader.load(plugins, { cmd = cmd })
Util.track()
end
vim.api.nvim_create_user_command(cmd, function(event)
_load()
vim.cmd(
("%s %s%s%s %s"):format(
event.mods or "",
event.line1 == event.line2 and "" or event.line1 .. "," .. event.line2,
cmd,
event.bang and "!" or "",
event.args or ""
)
)
end, {
bang = true,
nargs = "*",
complete = function()
_load()
-- HACK: trick Neovim to show the newly loaded command completion
vim.api.nvim_input("<space><bs><tab>")
end,
})
end
end
function M.handlers.module(grouped)
---@param modname string
table.insert(package.loaders, 2, function(modname)
local idx = modname:find(".", 1, true) or #modname + 1
while idx do
local name = modname:sub(1, idx - 1)
---@diagnostic disable-next-line: redefined-local
local plugins = grouped[name]
if plugins then
grouped[name] = nil
local reason = { require = modname }
if #Loader.loading == 0 then
local f = 3
while not reason.source do
local info = debug.getinfo(f, "S")
if not info then
break
end
if info.what ~= "C" then
reason.source = info.source:sub(2)
end
f = f + 1
end
end
Loader.load(plugins, reason)
end
idx = modname:find(".", idx + 1, true)
end
end)
end
return M