Util = require("lazy.util") Config = require("lazy.config") local M = {} ---@alias LoaderType "event"|"ft"|"module"|"keys"|"cmd" ---@type LoaderType[] M.types = { "event", "ft", "module", "keys", "cmd", } ---@type table> M.loaders = {} for _, type in ipairs(M.types) do M.loaders[type] = {} end ---@type LazyPlugin[] M.need_setup = {} ---@param plugin LazyPlugin function M.add(plugin) if plugin.init or plugin.opt == false and plugin.config then table.insert(M.need_setup, plugin) end for _, loader_type in ipairs(M.types) do ---@type string[]|string local loaders = plugin[loader_type] if loaders then loaders = type(loaders) == "table" and loaders or { loaders } ---@cast loaders string[] for _, loader in ipairs(loaders) do if not M.loaders[loader_type][loader] then M.loaders[loader_type][loader] = {} end table.insert(M.loaders[loader_type][loader], plugin.name) end end end end function M.setup() local group = vim.api.nvim_create_augroup("lazy_loader", { clear = true, }) -- modules table.insert(package.loaders, 2, M.module) -- events Util.track("loader_events") for event, plugins in pairs(M.loaders.event) do if event == "VimEnter" and vim.v.vim_did_enter == 1 then M.load(plugins) else local user_event = event:match("User (.*)") vim.api.nvim_create_autocmd(user_event and "User" or event, { once = true, group = group, pattern = user_event, callback = function() Util.track("event: " .. (user_event or event)) M.load(plugins) Util.track() end, }) end end Util.track() -- filetypes Util.track("loader_filetypes") for ft, plugins in pairs(M.loaders.ft) do vim.api.nvim_create_autocmd("FileType", { once = true, pattern = ft, group = group, callback = function() Util.track("filetype: " .. ft) M.load(plugins) Util.track() end, }) end Util.track() -- keys Util.track("loader_keys") for keys, plugins in pairs(M.loaders.keys or {}) do vim.keymap.set("n", keys, function() vim.keymap.del("n", keys) Util.track("keys: " .. keys) M.load(plugins) vim.api.nvim_input(keys) Util.track() end) end Util.track() -- commands Util.track("loader_commands") for cmd, plugins in pairs(M.loaders.cmd or {}) do vim.api.nvim_create_user_command(cmd, function(event) vim.api.nvim_del_user_command(cmd) Util.track("cmd: " .. cmd) M.load(plugins) 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 ) ) Util.track() end, { bang = true, nargs = "*", }) end Util.track() end function M.init_plugins() Util.track("loader_plugin_init") for _, plugin in ipairs(M.need_setup) do if plugin.init then Util.track(plugin.name) plugin.init() Util.track() end if plugin.opt == false then M.load(plugin) end end Util.track() end ---@param modname string function M.module(modname) local idx = modname:find(".", 1, true) or #modname + 1 while idx do local name = modname:sub(1, idx - 1) local plugins = M.loaders.module[name] if plugins then M.load(plugins) M.loaders.module[name] = nil end idx = modname:find(".", idx + 1, true) end ---@diagnostic disable-next-line: no-unknown local mod = package.loaded[modname] if type(mod) == "table" then return function() return mod end end end ---@param plugins string|LazyPlugin|string[]|LazyPlugin[] function M.load(plugins) if type(plugins) == "string" or plugins.name then plugins = { plugins } end for _, plugin in ipairs(plugins) do if type(plugin) == "string" then plugin = Config.plugins[plugin] end ---@cast plugin LazyPlugin if not plugin.loaded then plugin.loaded = true Util.track(plugin.name) M.packadd(plugin) if plugin.requires then M.load(plugin.requires) end if plugin.config then plugin.config() end Util.track() end end end ---@param plugin LazyPlugin function M.packadd(plugin) if plugin.opt then vim.cmd.packadd(plugin.pack) M.source_plugin_files(plugin, true) else vim.opt.runtimepath:append(plugin.dir) M.source_plugin_files(plugin) M.source_plugin_files(plugin, true) end end ---@param plugin LazyPlugin ---@param after? boolean function M.source_plugin_files(plugin, after) local pattern = (after and "/after" or "") .. ("/plugin/" .. "**/*.\\(vim\\|lua\\)") local _, entries = pcall(vim.fn.glob, plugin.dir .. "/" .. pattern, false, true) if entries then ---@cast entries string[] for _, file in ipairs(entries) do vim.cmd("silent source " .. file) end end end return M