local M = {} M.loaded = {} M.waiting = {} ---@alias pluginArray string|(pluginArray[]) ---@class loadOpts ---@field source ?string ---@field packOpts ?vim.pack.keyset.add ---@alias loadFn fun(plugin: pluginArray, opts?: loadOpts): nil ---nice utility wrapper around vim.pack.add ---@type loadFn function M.load(plugin, opts) if plugin == nil then error("value passed to load is nil") end if type(plugin) == "table" then for _, i in ipairs(plugin) do M.load(i, opts) end elseif type(plugin) == "string" then if (opts == nil) then vim.pack.add({ "https://github.com/" .. plugin }) else if opts.source == nil then plugin = "https://github.com/" .. plugin elseif type(opts.source) == "string" then plugin = opts.source .. plugin else error("plugin source must be either string or nil") end if opts.packOpts == nil then vim.pack.add({ plugin }) elseif type(opts.packOpts) == "table" then vim.pack.add({ plugin }, opts.packOpts) else error("packOpts must be table") end end else error("value passed to load must be string or table of tables or strings") end end ---get plugin, expect it to be in @VIMRC/lua/plugins/name.lua ---@param plugin string ---@return Plugin function M.get(plugin) return require("plugins." .. plugin) end ---@param pkg Plugin ---@return boolean local isDoneWaiting = function(pkg) local after = pkg.after ---@cast after table for _, i in pairs(after) do if not M.loaded[i] then return false end end return true end ---@class Plugin ---@field configure fun(load: loadFn): nil ---@field after? string|table ---@field configures? string ---@field onUpdate? fun(ev): nil ---parse a plugin in the util.Plugin format ---@param plugin Plugin function M.parse(plugin) local load = false if plugin.after == nil then load = true elseif type(plugin.after) == "string" then load = M.loaded[plugin.after] else load = isDoneWaiting(plugin) end if load then plugin.configure(M.load) if plugin.configures ~= nil then M.loaded[plugin.configures] = true if M.waiting[plugin.configures] ~= nil then for _, i in pairs(M.waiting[plugin.configures]) do M.parse(i) end end M.waiting[plugin.configures] = nil if plugin.onUpdate ~= nil then vim.api.nvim_create_autocmd("PackChanged", { callback = function(ev) local name, kind = ev.data.spec.name, ev.data.kind print("name: ", name, ", kind: ", kind, ", configures: ", plugin.configures) if name == plugin.configures and kind == "update" then if not ev.data.active then vim.cmd.packadd(plugin.configures) end plugin.onUpdate(ev) end end, }) end end else if type(plugin.after) == "string" then if M.waiting[plugin.after] == nil then M.waiting[plugin.after] = {} end table.insert(M.waiting[plugin.after], plugin) else local after = plugin.after ---@cast after table for _, i in pairs(after) do if M.waiting[i] == nil then M.waiting[i] = {} end table.insert(M.waiting[i], plugin) end end end end return M