diff --git a/lua/lazy/core/config.lua b/lua/lazy/core/config.lua index beafd4c..0ed35ee 100644 --- a/lua/lazy/core/config.lua +++ b/lua/lazy/core/config.lua @@ -55,7 +55,7 @@ M.defaults = { icons = { cmd = " ", config = "", - event = "", + event = " ", ft = " ", init = " ", import = " ", @@ -67,7 +67,7 @@ M.defaults = { runtime = " ", require = "󰢱 ", source = " ", - start = "", + start = " ", task = "✔ ", list = { "●", diff --git a/lua/lazy/core/handler/event.lua b/lua/lazy/core/handler/event.lua index 018d04b..aff4572 100644 --- a/lua/lazy/core/handler/event.lua +++ b/lua/lazy/core/handler/event.lua @@ -37,7 +37,7 @@ M.group = vim.api.nvim_create_augroup("lazy_handler_event", { clear = true }) ---@param spec LazyEventSpec ---@return LazyEvent -function M:parse(spec) +function M:_parse(spec) local ret = M.mappings[spec] --[[@as LazyEvent?]] if ret then return ret @@ -62,19 +62,6 @@ function M:parse(spec) return ret end ----@param plugin LazyPlugin -function M:values(plugin) - local Plugin = require("lazy.core.plugin") - ---@type table - local values = {} - ---@diagnostic disable-next-line: no-unknown - for _, value in ipairs(Plugin.values(plugin, self.type, true)) do - local event = self:parse(value) - values[event.id] = event - end - return values -end - ---@param event LazyEvent function M:_add(event) local done = false diff --git a/lua/lazy/core/handler/ft.lua b/lua/lazy/core/handler/ft.lua index 7af2b9a..9b33d37 100644 --- a/lua/lazy/core/handler/ft.lua +++ b/lua/lazy/core/handler/ft.lua @@ -13,7 +13,8 @@ function M:add(plugin) end end -function M:parse(value) +---@return LazyEvent +function M:_parse(value) return { id = value, event = "FileType", diff --git a/lua/lazy/core/handler/init.lua b/lua/lazy/core/handler/init.lua index 8a5179d..ba45de5 100644 --- a/lua/lazy/core/handler/init.lua +++ b/lua/lazy/core/handler/init.lua @@ -39,29 +39,20 @@ end ---@param plugin LazyPlugin function M.disable(plugin) - if not plugin._.handlers_enabled then - return - end - plugin._.handlers_enabled = false - for type, handler in pairs(M.handlers) do - if plugin[type] then - handler:del(plugin) - end + for type in pairs(plugin._.handlers or {}) do + M.handlers[type]:del(plugin) end end ---@param plugin LazyPlugin function M.enable(plugin) if not plugin._.loaded then - if plugin._.handlers_enabled then - return + if not plugin._.handlers then + M.load(plugin) end - for type, handler in pairs(M.handlers) do - if plugin[type] then - handler:add(plugin) - end + for type in pairs(plugin._.handlers or {}) do + M.handlers[type]:add(plugin) end - plugin._.handlers_enabled = true end end @@ -86,21 +77,40 @@ function M:_add(_value) end ---@protected function M:_del(_value) end +---@param value any +---@param _plugin LazyPlugin +---@return string|{id:string} +function M:_parse(value, _plugin) + assert(type(value) == "string", "Expected string, got " .. vim.inspect(value)) + return value +end + +---@param values any[] ---@param plugin LazyPlugin -function M:values(plugin) - local Plugin = require("lazy.core.plugin") +function M:_values(values, plugin) ---@type table - local values = {} - ---@diagnostic disable-next-line: no-unknown - for _, value in ipairs(Plugin.values(plugin, self.type, true)) do - values[value] = value + local ret = {} + for _, value in ipairs(values) do + local parsed = self:_parse(value, plugin) + ret[type(parsed) == "string" and parsed or parsed.id] = parsed + end + return ret +end + +---@param plugin LazyPlugin +function M.load(plugin) + local Plugin = require("lazy.core.plugin") + plugin._.handlers = {} + for type, handler in pairs(M.handlers) do + if plugin[type] then + plugin._.handlers[type] = handler:_values(Plugin.values(plugin, type, true), plugin) + end end - return values end ---@param plugin LazyPlugin function M:add(plugin) - for key, value in pairs(self:values(plugin)) do + for key, value in pairs(plugin._.handlers[self.type] or {}) do if not self.active[key] then self.active[key] = {} self:_add(value) @@ -112,7 +122,10 @@ end ---@param plugin LazyPlugin function M:del(plugin) - for key, value in pairs(self:values(plugin)) do + if not plugin._.handlers then + return + end + for key, value in pairs(plugin._.handlers[self.type] or {}) do if self.active[key] and self.active[key][plugin.name] then self.active[key][plugin.name] = nil if vim.tbl_isempty(self.active[key]) then diff --git a/lua/lazy/core/handler/keys.lua b/lua/lazy/core/handler/keys.lua index a7f7f68..e19d6e5 100644 --- a/lua/lazy/core/handler/keys.lua +++ b/lua/lazy/core/handler/keys.lua @@ -19,10 +19,13 @@ local Util = require("lazy.core.util") ---@field rhs? string|fun() rhs ---@field mode? string ---@field id string +---@field name string ---@class LazyKeysHandler:LazyHandler local M = {} +local skip = { mode = true, id = true, ft = true, rhs = true, lhs = true } + ---@param value string|LazyKeysSpec ---@param mode? string ---@return LazyKeys @@ -37,12 +40,18 @@ function M.parse(value, mode) ret[2] = nil ret.mode = mode or "n" ret.id = vim.api.nvim_replace_termcodes(ret.lhs, true, true, true) + if ret.mode ~= "n" then ret.id = ret.id .. " (" .. ret.mode .. ")" end return ret end +---@param keys LazyKeys +function M.to_string(keys) + return keys.lhs .. (keys.mode == "n" and "" or " (" .. keys.mode .. ")") +end + ---@param lhs string ---@param mode? string function M:have(lhs, mode) @@ -50,10 +59,8 @@ function M:have(lhs, mode) return self.managed[keys.id] ~= nil end ----@param plugin LazyPlugin -function M:values(plugin) - local Plugin = require("lazy.core.plugin") - return M.resolve(Plugin.values(plugin, "keys", true)) +function M:_values(values) + return M.resolve(values) end ---@param spec? (string|LazyKeysSpec)[] @@ -79,7 +86,6 @@ end ---@param keys LazyKeys function M.opts(keys) - local skip = { mode = true, id = true, ft = true, rhs = true, lhs = true } local opts = {} ---@type LazyKeysBase ---@diagnostic disable-next-line: no-unknown for k, v in pairs(keys) do @@ -106,8 +112,9 @@ function M:_add(keys) self.active[keys.id] = nil if plugins then - Util.track({ keys = lhs }) - Loader.load(plugins, { keys = lhs }) + local name = M.to_string(keys) + Util.track({ keys = name }) + Loader.load(plugins, { keys = name }) Util.track() end diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua index d9ad3ac..229b6bf 100644 --- a/lua/lazy/core/plugin.lua +++ b/lua/lazy/core/plugin.lua @@ -556,10 +556,6 @@ function M.load() Config.plugins[name]._ = plugin._ Config.plugins[name]._.dep = dep Config.plugins[name]._.super = super - -- FIXME: work-around for changes related to Plugin.values - for handler in pairs(Handler) do - Config.plugins[name][handler] = plugin[handler] - end end end Util.track() @@ -607,29 +603,32 @@ function M.values(plugin, prop, is_list) if not plugin[prop] then return {} end - plugin._.values = plugin._.values or {} + plugin._.cache = plugin._.cache or {} local key = prop .. (is_list and "_list" or "") - if plugin._.values[key] == nil then - plugin[prop] = M._values(plugin, prop, is_list) - plugin._.values[key] = true + if plugin._.cache[key] == nil then + plugin._.cache[key] = M._values(plugin, plugin, prop, is_list) end - return plugin[prop] or {} + return plugin._.cache[key] end -- Merges super values or runs the values function to override values or return new ones -- Used for opts, cmd, event, ft and keys +---@param root LazyPlugin ---@param plugin LazyPlugin ---@param prop string ---@param is_list? boolean -function M._values(plugin, prop, is_list) +function M._values(root, plugin, prop, is_list) + if not plugin[prop] then + return {} + end ---@type table - local ret = plugin._.super and M._values(plugin._.super, prop, is_list) or {} + local ret = plugin._.super and M._values(root, plugin._.super, prop, is_list) or {} local values = rawget(plugin, prop) if not values then return ret elseif type(values) == "function" then - ret = values(plugin, ret) or ret + ret = values(root, ret) or ret return type(ret) == "table" and ret or { ret } end diff --git a/lua/lazy/types.lua b/lua/lazy/types.lua index 346d8e4..0525ca0 100644 --- a/lua/lazy/types.lua +++ b/lua/lazy/types.lua @@ -20,8 +20,8 @@ ---@field module? string ---@field dir? string Explicit dir or dev set for this plugin ---@field rtp_loaded? boolean ----@field values? table ----@field handlers_enabled? boolean +---@field handlers? LazyPluginHandlers +---@field cache? table ---@alias PluginOpts table|fun(self:LazyPlugin, opts:table):table? @@ -32,12 +32,11 @@ ---@field build? string|fun(self:LazyPlugin)|(string|fun(self:LazyPlugin))[] ---@field opts? PluginOpts ----@class LazyPluginHandlers ----@field event? LazyEventSpec[] ----@field cmd? string[] ----@field ft? string[] ----@field keys? (string|LazyKeysSpec)[] ----@field module? false +---@class LazyPluginHandlers: {[string]: any} +---@field event? table +---@field ft? table +---@field keys? table +---@field cmd? table ---@class LazyPluginRef ---@field branch? string diff --git a/lua/lazy/view/render.lua b/lua/lazy/view/render.lua index df37b74..770abf8 100644 --- a/lua/lazy/view/render.lua +++ b/lua/lazy/view/render.lua @@ -1,6 +1,7 @@ local Config = require("lazy.core.config") local Git = require("lazy.manage.git") local Handler = require("lazy.core.handler") +local Keys = require("lazy.core.handler.keys") local Plugin = require("lazy.core.plugin") local Sections = require("lazy.view.sections") local Util = require("lazy.util") @@ -334,12 +335,10 @@ function M:reason(reason, opts) else self:append(" ") end - if key == "keys" then - value = type(value) == "string" and value or value.lhs or value[1] - end local hl = "LazyReason" .. key:sub(1, 1):upper() .. key:sub(2) local icon = Config.options.ui.icons[key] if icon then + icon = icon:gsub("%s*$", "") self:append(icon .. " ", hl) self:append(value, hl) else @@ -411,35 +410,18 @@ function M:plugin(plugin) end local plugin_start = self:row() if plugin._.loaded then + -- When the plugin is loaded, only show the loading reason self:reason(plugin._.loaded) else + -- otherwise show all lazy handlers self:append(" ") - local reason = {} - if plugin._.kind ~= "disabled" and plugin._.handlers_enabled then - for handler in pairs(Handler.types) do - if plugin[handler] then - local values = Handler.handlers[handler]:values(plugin) - values = vim.tbl_map(function(value) - if handler == "ft" or handler == "event" then - ---@cast value LazyEvent - return value.id - elseif handler == "keys" then - ---@cast value LazyKeys - return value.lhs .. (value.mode == "n" and "" or " (" .. value.mode .. ")") - end - return value - end, vim.tbl_values(values)) - table.sort(values) - reason[handler] = table.concat(values, " ") - end - end - end + self:handlers(plugin) for _, other in pairs(Config.plugins) do if vim.tbl_contains(other.dependencies or {}, plugin.name) then - reason.plugin = other.name + self:reason({ plugin = other.name }) + self:append(" ") end end - self:reason(reason) end self:diagnostics(plugin) self:nl() @@ -542,26 +524,36 @@ function M:details(plugin) end end) - if plugin._.handlers_enabled then - for handler in pairs(Handler.types) do - if plugin[handler] then - table.insert(props, { - handler, - function() - for _, value in ipairs(Plugin.values(plugin, handler, true)) do - self:reason({ [handler] = value }) - self:append(" ") - end - end, - }) - end - end + for handler in pairs(plugin._.handlers or {}) do + table.insert(props, { + handler, + function() + self:handlers(plugin, handler) + end, + }) end self:props(props, { indent = 6 }) self:nl() end +---@param plugin LazyPlugin +---@param types? LazyHandlerTypes[]|LazyHandlerTypes +function M:handlers(plugin, types) + if not plugin._.handlers then + return + end + types = type(types) == "string" and { types } or types + types = types and types or vim.tbl_keys(Handler.types) + for _, t in ipairs(types) do + for id, value in pairs(plugin._.handlers[t] or {}) do + value = t == "keys" and Keys.to_string(value) or id + self:reason({ [t] = value }) + self:append(" ") + end + end +end + ---@alias LazyProps {[1]:string, [2]:string|fun(), [3]?:string}[] ---@param props LazyProps ---@param opts? {indent: number} @@ -690,16 +682,16 @@ function M:debug() Util.foreach(require("lazy.core.handler").handlers, function(handler_type, handler) Util.foreach(handler.active, function(value, plugins) - value = type(value) == "table" and value[1] or value + assert(type(value) == "string") if not vim.tbl_isempty(plugins) then ---@type string[] plugins = vim.tbl_values(plugins) table.sort(plugins) self:append("● ", "LazySpecial", { indent = 2 }) if handler_type == "keys" then - for k, v in pairs(Handler.handlers.keys:values(Config.plugins[plugins[1]])) do + for k, v in pairs(Config.plugins[plugins[1]]._.handlers.keys) do if k == value then - value = v + value = v.name break end end diff --git a/tests/core/plugin_spec.lua b/tests/core/plugin_spec.lua index 6df2e81..ee5b007 100644 --- a/tests/core/plugin_spec.lua +++ b/tests/core/plugin_spec.lua @@ -1,4 +1,5 @@ local Config = require("lazy.core.config") +local Handler = require("lazy.core.handler") local Plugin = require("lazy.core.plugin") local assert = require("luassert") @@ -142,6 +143,9 @@ describe("plugin spec opt", function() end) describe("deps", function() + before_each(function() + Handler.init() + end) it("handles dep names", function() Config.options.defaults.lazy = false local tests = { @@ -237,11 +241,13 @@ describe("plugin spec opt", function() local spec = Plugin.Spec.new(test) assert(#spec.notifs == 0) assert(vim.tbl_count(spec.plugins) == 1) - Plugin.values(spec.plugins.bar, "event", true) - assert(type(spec.plugins.bar.event) == "table") - assert(#spec.plugins.bar.event == 2) - assert(vim.tbl_contains(spec.plugins.bar.event, "mod1")) - assert(vim.tbl_contains(spec.plugins.bar.event, "mod2")) + Handler.load(spec.plugins.bar) + vim.print(spec.plugins.bar._.handlers) + local events = vim.tbl_keys(spec.plugins.bar._.handlers.event or {}) + assert(type(events) == "table") + assert(#events == 2) + assert(vim.tbl_contains(events, "mod1")) + assert(vim.tbl_contains(events, "mod2")) end end) end) @@ -297,14 +303,16 @@ describe("plugin spec opt", function() { { "foo/bar", event = "mod1" }, { "foo/bar", event = { "mod2" } } }, } for _, test in ipairs(tests) do + Handler.init() local spec = Plugin.Spec.new(test) assert(#spec.notifs == 0) assert(vim.tbl_count(spec.plugins) == 1) - Plugin.values(spec.plugins.bar, "event", true) - assert(type(spec.plugins.bar.event) == "table") - assert(#spec.plugins.bar.event == 2) - assert(vim.tbl_contains(spec.plugins.bar.event, "mod1")) - assert(vim.tbl_contains(spec.plugins.bar.event, "mod2")) + Handler.load(spec.plugins.bar) + local events = spec.plugins.bar._.handlers.event + assert(type(events) == "table") + assert(vim.tbl_count(events) == 2) + assert(events["mod1"]) + assert(events["mod2"]) end end)