mirror of https://github.com/folke/lazy.nvim.git
feat(plugin): dont include plugin spec fragments for disabled or optional plugins (#1058)
* feat(plugin): dont include plugin spec fragments for disabled or optional plugins * test: fixed tests * fix(plugin): calculate handlers after disabling plugins * fix(plugin): clear Plugin._.super when rebuilding * fix(ui): dont process handlers for disabled plugins * test: added tests for disabling fragments * fix(plugin): ignore any installed deps of a disabled conditional plugin. Fixes #1053
This commit is contained in:
parent
6b55e4695a
commit
f3c7169dd6
|
@ -8,22 +8,30 @@ M.loading = false
|
||||||
|
|
||||||
---@class LazySpecLoader
|
---@class LazySpecLoader
|
||||||
---@field plugins table<string, LazyPlugin>
|
---@field plugins table<string, LazyPlugin>
|
||||||
|
---@field fragments table<number, LazyPlugin>
|
||||||
---@field disabled table<string, LazyPlugin>
|
---@field disabled table<string, LazyPlugin>
|
||||||
|
---@field dirty table<string, true>
|
||||||
|
---@field ignore_installed table<string, true>
|
||||||
---@field modules string[]
|
---@field modules string[]
|
||||||
---@field notifs {msg:string, level:number, file?:string}[]
|
---@field notifs {msg:string, level:number, file?:string}[]
|
||||||
---@field importing? string
|
---@field importing? string
|
||||||
---@field optional? boolean
|
---@field optional? boolean
|
||||||
local Spec = {}
|
local Spec = {}
|
||||||
M.Spec = Spec
|
M.Spec = Spec
|
||||||
|
M.last_fid = 0
|
||||||
|
M.fid_stack = {} ---@type number[]
|
||||||
|
|
||||||
---@param spec? LazySpec
|
---@param spec? LazySpec
|
||||||
---@param opts? {optional?:boolean}
|
---@param opts? {optional?:boolean}
|
||||||
function Spec.new(spec, opts)
|
function Spec.new(spec, opts)
|
||||||
local self = setmetatable({}, { __index = Spec })
|
local self = setmetatable({}, { __index = Spec })
|
||||||
self.plugins = {}
|
self.plugins = {}
|
||||||
|
self.fragments = {}
|
||||||
self.disabled = {}
|
self.disabled = {}
|
||||||
self.modules = {}
|
self.modules = {}
|
||||||
|
self.dirty = {}
|
||||||
self.notifs = {}
|
self.notifs = {}
|
||||||
|
self.ignore_installed = {}
|
||||||
self.optional = opts and opts.optional
|
self.optional = opts and opts.optional
|
||||||
if spec then
|
if spec then
|
||||||
self:parse(spec)
|
self:parse(spec)
|
||||||
|
@ -33,6 +41,7 @@ end
|
||||||
|
|
||||||
function Spec:parse(spec)
|
function Spec:parse(spec)
|
||||||
self:normalize(spec)
|
self:normalize(spec)
|
||||||
|
self:fix_disabled()
|
||||||
|
|
||||||
-- calculate handlers
|
-- calculate handlers
|
||||||
for _, plugin in pairs(self.plugins) do
|
for _, plugin in pairs(self.plugins) do
|
||||||
|
@ -42,8 +51,6 @@ function Spec:parse(spec)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:fix_disabled()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- PERF: optimized code to get package name without using lua patterns
|
-- PERF: optimized code to get package name without using lua patterns
|
||||||
|
@ -56,8 +63,7 @@ end
|
||||||
|
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
---@param results? string[]
|
---@param results? string[]
|
||||||
---@param is_dep? boolean
|
function Spec:add(plugin, results)
|
||||||
function Spec:add(plugin, results, is_dep)
|
|
||||||
-- check if we already processed this spec. Can happen when a user uses the same instance of a spec in multiple specs
|
-- check if we already processed this spec. Can happen when a user uses the same instance of a spec in multiple specs
|
||||||
-- see https://github.com/folke/lazy.nvim/issues/45
|
-- see https://github.com/folke/lazy.nvim/issues/45
|
||||||
if rawget(plugin, "_") then
|
if rawget(plugin, "_") then
|
||||||
|
@ -124,10 +130,28 @@ function Spec:add(plugin, results, is_dep)
|
||||||
plugin.config = nil
|
plugin.config = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
plugin._ = {}
|
local fpid = M.fid_stack[#M.fid_stack]
|
||||||
plugin._.dep = is_dep
|
|
||||||
|
M.last_fid = M.last_fid + 1
|
||||||
|
plugin._ = {
|
||||||
|
fid = M.last_fid,
|
||||||
|
fpid = fpid,
|
||||||
|
dep = fpid ~= nil,
|
||||||
|
}
|
||||||
|
self.fragments[plugin._.fid] = plugin
|
||||||
|
|
||||||
|
if fpid then
|
||||||
|
local parent = self.fragments[fpid]
|
||||||
|
parent._.fdeps = parent._.fdeps or {}
|
||||||
|
table.insert(parent._.fdeps, plugin._.fid)
|
||||||
|
end
|
||||||
|
|
||||||
|
if plugin.dependencies then
|
||||||
|
table.insert(M.fid_stack, plugin._.fid)
|
||||||
|
plugin.dependencies = self:normalize(plugin.dependencies, {})
|
||||||
|
table.remove(M.fid_stack)
|
||||||
|
end
|
||||||
|
|
||||||
plugin.dependencies = plugin.dependencies and self:normalize(plugin.dependencies, {}, true) or nil
|
|
||||||
if self.plugins[plugin.name] then
|
if self.plugins[plugin.name] then
|
||||||
plugin = self:merge(self.plugins[plugin.name], plugin)
|
plugin = self:merge(self.plugins[plugin.name], plugin)
|
||||||
end
|
end
|
||||||
|
@ -146,27 +170,73 @@ function Spec:warn(msg)
|
||||||
self:log(msg, vim.log.levels.WARN)
|
self:log(msg, vim.log.levels.WARN)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param gathered_deps string[]
|
--- Rebuilds a plugin spec excluding any removed fragments
|
||||||
---@param dep_of table<string,string[]>
|
---@param name string
|
||||||
---@param on_disable fun(string):nil
|
function Spec:rebuild(name)
|
||||||
function Spec:fix_dependencies(gathered_deps, dep_of, on_disable)
|
local plugin = self.plugins[name]
|
||||||
local function should_disable(dep_name)
|
if not plugin then
|
||||||
for _, parent in ipairs(dep_of[dep_name] or {}) do
|
return
|
||||||
if self.plugins[parent] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, dep_name in ipairs(gathered_deps) do
|
local fragments = {} ---@type LazyPlugin[]
|
||||||
-- only check if the plugin is still enabled and it is a dep
|
|
||||||
if self.plugins[dep_name] and self.plugins[dep_name]._.dep then
|
repeat
|
||||||
-- check if the dep is still used by another plugin
|
local super = plugin._.super
|
||||||
if should_disable(dep_name) then
|
if self.fragments[plugin._.fid] then
|
||||||
-- disable the dep when no longer needed
|
plugin._.dep = plugin._.fpid ~= nil
|
||||||
on_disable(dep_name)
|
plugin._.super = nil
|
||||||
|
if plugin._.fdeps then
|
||||||
|
plugin.dependencies = {}
|
||||||
|
for _, cid in ipairs(plugin._.fdeps) do
|
||||||
|
if self.fragments[cid] then
|
||||||
|
table.insert(plugin.dependencies, self.fragments[cid].name)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
setmetatable(plugin, nil)
|
||||||
|
table.insert(fragments, 1, plugin)
|
||||||
|
end
|
||||||
|
plugin = super
|
||||||
|
until not plugin
|
||||||
|
|
||||||
|
if #fragments == 0 then
|
||||||
|
self.plugins[name] = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
plugin = fragments[1]
|
||||||
|
for i = 2, #fragments do
|
||||||
|
plugin = self:merge(plugin, fragments[i])
|
||||||
|
end
|
||||||
|
self.plugins[name] = plugin
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Recursively removes all fragments from a plugin spec or a given fragment
|
||||||
|
---@param id string|number Plugin name or fragment id
|
||||||
|
---@param opts {self: boolean}
|
||||||
|
function Spec:remove_fragments(id, opts)
|
||||||
|
local fids = {} ---@type number[]
|
||||||
|
|
||||||
|
if type(id) == "number" then
|
||||||
|
fids[1] = id
|
||||||
|
else
|
||||||
|
local plugin = self.plugins[id]
|
||||||
|
repeat
|
||||||
|
fids[#fids + 1] = plugin._.fid
|
||||||
|
plugin = plugin._.super
|
||||||
|
until not plugin
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, fid in ipairs(fids) do
|
||||||
|
local fragment = self.fragments[fid]
|
||||||
|
if fragment then
|
||||||
|
for _, cid in ipairs(fragment._.fdeps or {}) do
|
||||||
|
self:remove_fragments(cid, { self = true })
|
||||||
|
end
|
||||||
|
if opts.self then
|
||||||
|
self.fragments[fid] = nil
|
||||||
|
end
|
||||||
|
self.dirty[fragment.name] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -179,14 +249,20 @@ function Spec:fix_cond()
|
||||||
end
|
end
|
||||||
if cond == false or (type(cond) == "function" and not cond(plugin)) then
|
if cond == false or (type(cond) == "function" and not cond(plugin)) then
|
||||||
plugin._.cond = false
|
plugin._.cond = false
|
||||||
|
local stack = { plugin }
|
||||||
|
while #stack > 0 do
|
||||||
|
local p = table.remove(stack)
|
||||||
|
for _, dep in ipairs(p.dependencies or {}) do
|
||||||
|
table.insert(stack, self.plugins[dep])
|
||||||
|
end
|
||||||
|
self.ignore_installed[p.name] = true
|
||||||
|
end
|
||||||
plugin.enabled = false
|
plugin.enabled = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string[]
|
|
||||||
function Spec:fix_optional()
|
function Spec:fix_optional()
|
||||||
local all_optional_deps = {}
|
|
||||||
if not self.optional then
|
if not self.optional then
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
local function all_optional(plugin)
|
local function all_optional(plugin)
|
||||||
|
@ -196,14 +272,12 @@ function Spec:fix_optional()
|
||||||
-- handle optional plugins
|
-- handle optional plugins
|
||||||
for _, plugin in pairs(self.plugins) do
|
for _, plugin in pairs(self.plugins) do
|
||||||
if plugin.optional and all_optional(plugin) then
|
if plugin.optional and all_optional(plugin) then
|
||||||
|
-- remove all optional fragments
|
||||||
|
self:remove_fragments(plugin.name, { self = true })
|
||||||
self.plugins[plugin.name] = nil
|
self.plugins[plugin.name] = nil
|
||||||
if plugin.dependencies then
|
|
||||||
vim.list_extend(all_optional_deps, plugin.dependencies)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return all_optional_deps
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Spec:fix_disabled()
|
function Spec:fix_disabled()
|
||||||
|
@ -214,44 +288,24 @@ function Spec:fix_disabled()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type table<string,string[]> plugin to parent plugin
|
self:fix_optional()
|
||||||
local dep_of = {}
|
|
||||||
|
|
||||||
---@type string[] dependencies of disabled plugins
|
|
||||||
local disabled_deps = {}
|
|
||||||
|
|
||||||
---@type string[] dependencies of plugins that are completely optional
|
|
||||||
local all_optional_deps = self:fix_optional()
|
|
||||||
self:fix_cond()
|
self:fix_cond()
|
||||||
|
|
||||||
for _, plugin in pairs(self.plugins) do
|
for _, plugin in pairs(self.plugins) do
|
||||||
local enabled = not (plugin.enabled == false or (type(plugin.enabled) == "function" and not plugin.enabled()))
|
local disabled = plugin.enabled == false or (type(plugin.enabled) == "function" and not plugin.enabled())
|
||||||
if enabled then
|
if disabled then
|
||||||
for _, dep in ipairs(plugin.dependencies or {}) do
|
|
||||||
dep_of[dep] = dep_of[dep] or {}
|
|
||||||
table.insert(dep_of[dep], plugin.name)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
plugin._.kind = "disabled"
|
plugin._.kind = "disabled"
|
||||||
|
-- remove all child fragments
|
||||||
|
self:remove_fragments(plugin.name, { self = false })
|
||||||
self.plugins[plugin.name] = nil
|
self.plugins[plugin.name] = nil
|
||||||
self.disabled[plugin.name] = plugin
|
self.disabled[plugin.name] = plugin
|
||||||
if plugin.dependencies then
|
|
||||||
vim.list_extend(disabled_deps, plugin.dependencies)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- fix deps of plugins that are completely optional
|
-- rebuild any plugin specs that were modified
|
||||||
self:fix_dependencies(all_optional_deps, dep_of, function(dep_name)
|
for name, _ in pairs(self.dirty) do
|
||||||
self.plugins[dep_name] = nil
|
self:rebuild(name)
|
||||||
end)
|
end
|
||||||
-- fix deps of disabled plugins
|
|
||||||
self:fix_dependencies(disabled_deps, dep_of, function(dep_name)
|
|
||||||
local plugin = self.plugins[dep_name]
|
|
||||||
plugin._.kind = "disabled"
|
|
||||||
self.plugins[plugin.name] = nil
|
|
||||||
self.disabled[plugin.name] = plugin
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param msg string
|
---@param msg string
|
||||||
|
@ -272,24 +326,24 @@ end
|
||||||
---@param spec LazySpec|LazySpecImport
|
---@param spec LazySpec|LazySpecImport
|
||||||
---@param results? string[]
|
---@param results? string[]
|
||||||
---@param is_dep? boolean
|
---@param is_dep? boolean
|
||||||
function Spec:normalize(spec, results, is_dep)
|
function Spec:normalize(spec, results)
|
||||||
if type(spec) == "string" then
|
if type(spec) == "string" then
|
||||||
if is_dep and not spec:find("/", 1, true) then
|
if not spec:find("/", 1, true) then
|
||||||
-- spec is a plugin name
|
-- spec is a plugin name
|
||||||
if results then
|
if results then
|
||||||
table.insert(results, spec)
|
table.insert(results, spec)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:add({ spec }, results, is_dep)
|
self:add({ spec }, results)
|
||||||
end
|
end
|
||||||
elseif #spec > 1 or Util.is_list(spec) then
|
elseif #spec > 1 or Util.is_list(spec) then
|
||||||
---@cast spec LazySpec[]
|
---@cast spec LazySpec[]
|
||||||
for _, s in ipairs(spec) do
|
for _, s in ipairs(spec) do
|
||||||
self:normalize(s, results, is_dep)
|
self:normalize(s, results)
|
||||||
end
|
end
|
||||||
elseif spec[1] or spec.dir or spec.url then
|
elseif spec[1] or spec.dir or spec.url then
|
||||||
---@cast spec LazyPlugin
|
---@cast spec LazyPlugin
|
||||||
local plugin = self:add(spec, results, is_dep)
|
local plugin = self:add(spec, results)
|
||||||
---@diagnostic disable-next-line: cast-type-mismatch
|
---@diagnostic disable-next-line: cast-type-mismatch
|
||||||
---@cast plugin LazySpecImport
|
---@cast plugin LazySpecImport
|
||||||
if plugin and plugin.import then
|
if plugin and plugin.import then
|
||||||
|
@ -425,10 +479,8 @@ function M.update_state()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, plugin in pairs(Config.spec.disabled) do
|
for name in pairs(Config.spec.ignore_installed) do
|
||||||
if plugin._.cond == false then
|
installed[name] = nil
|
||||||
installed[plugin.name] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Config.to_clean = {}
|
Config.to_clean = {}
|
||||||
|
|
|
@ -2,12 +2,15 @@
|
||||||
---@alias LazyPluginKind "normal"|"clean"|"disabled"
|
---@alias LazyPluginKind "normal"|"clean"|"disabled"
|
||||||
|
|
||||||
---@class LazyPluginState
|
---@class LazyPluginState
|
||||||
|
---@field fid number id of the plugin spec fragment
|
||||||
|
---@field fpid? number parent id of the plugin spec fragment
|
||||||
|
---@field fdeps? number[] children ids of the fragment
|
||||||
---@field loaded? {[string]:string}|{time:number}
|
---@field loaded? {[string]:string}|{time:number}
|
||||||
---@field installed boolean
|
---@field installed? boolean
|
||||||
---@field tasks? LazyTask[]
|
---@field tasks? LazyTask[]
|
||||||
---@field dirty? boolean
|
---@field dirty? boolean
|
||||||
---@field updated? {from:string, to:string}
|
---@field updated? {from:string, to:string}
|
||||||
---@field is_local boolean
|
---@field is_local? boolean
|
||||||
---@field updates? {from:GitInfo, to:GitInfo}
|
---@field updates? {from:GitInfo, to:GitInfo}
|
||||||
---@field cloned? boolean
|
---@field cloned? boolean
|
||||||
---@field kind? LazyPluginKind
|
---@field kind? LazyPluginKind
|
||||||
|
|
|
@ -411,13 +411,15 @@ function M:plugin(plugin)
|
||||||
else
|
else
|
||||||
self:append(" ")
|
self:append(" ")
|
||||||
local reason = {}
|
local reason = {}
|
||||||
for handler in pairs(Handler.types) do
|
if plugin._.kind ~= "disabled" then
|
||||||
if plugin[handler] then
|
for handler in pairs(Handler.types) do
|
||||||
local trigger = {}
|
if plugin[handler] then
|
||||||
for _, value in ipairs(plugin[handler]) do
|
local trigger = {}
|
||||||
table.insert(trigger, type(value) == "table" and value[1] or value)
|
for _, value in ipairs(plugin[handler]) do
|
||||||
|
table.insert(trigger, type(value) == "table" and value[1] or value)
|
||||||
|
end
|
||||||
|
reason[handler] = table.concat(trigger, " ")
|
||||||
end
|
end
|
||||||
reason[handler] = table.concat(trigger, " ")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for _, other in pairs(Config.plugins) do
|
for _, other in pairs(Config.plugins) do
|
||||||
|
|
|
@ -1,11 +1,25 @@
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
local Plugin = require("lazy.core.plugin")
|
local Plugin = require("lazy.core.plugin")
|
||||||
local Loader = require("lazy.core.loader")
|
|
||||||
|
|
||||||
local assert = require("luassert")
|
local assert = require("luassert")
|
||||||
|
|
||||||
Config.setup()
|
Config.setup()
|
||||||
|
|
||||||
|
---@param plugins LazyPlugin[]|LazyPlugin
|
||||||
|
local function clean(plugins)
|
||||||
|
local p = plugins
|
||||||
|
plugins = type(plugins) == "table" and plugins or { plugins }
|
||||||
|
for _, plugin in pairs(plugins) do
|
||||||
|
plugin._.fid = nil
|
||||||
|
plugin._.fpid = nil
|
||||||
|
plugin._.fdeps = nil
|
||||||
|
if plugin._.dep == false then
|
||||||
|
plugin._.dep = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
|
||||||
describe("plugin spec url/name", function()
|
describe("plugin spec url/name", function()
|
||||||
local tests = {
|
local tests = {
|
||||||
{ { dir = "~/foo" }, { name = "foo", dir = vim.fn.fnamemodify("~/foo", ":p") } },
|
{ { dir = "~/foo" }, { name = "foo", dir = vim.fn.fnamemodify("~/foo", ":p") } },
|
||||||
|
@ -28,6 +42,7 @@ describe("plugin spec url/name", function()
|
||||||
end
|
end
|
||||||
local spec = Plugin.Spec.new(test[1])
|
local spec = Plugin.Spec.new(test[1])
|
||||||
local plugins = vim.tbl_values(spec.plugins)
|
local plugins = vim.tbl_values(spec.plugins)
|
||||||
|
plugins[1]._ = {}
|
||||||
assert(#spec.notifs == 0)
|
assert(#spec.notifs == 0)
|
||||||
assert.equal(1, #plugins)
|
assert.equal(1, #plugins)
|
||||||
assert.same(test[2], plugins[1])
|
assert.same(test[2], plugins[1])
|
||||||
|
@ -61,7 +76,7 @@ describe("plugin spec opt", function()
|
||||||
for _, plugin in pairs(spec.plugins) do
|
for _, plugin in pairs(spec.plugins) do
|
||||||
plugin.dir = nil
|
plugin.dir = nil
|
||||||
end
|
end
|
||||||
assert.same(spec.plugins, {
|
assert.same(clean(spec.plugins), {
|
||||||
bar = {
|
bar = {
|
||||||
"foo/bar",
|
"foo/bar",
|
||||||
_ = {},
|
_ = {},
|
||||||
|
@ -105,7 +120,7 @@ describe("plugin spec opt", function()
|
||||||
for _, plugin in pairs(spec.plugins) do
|
for _, plugin in pairs(spec.plugins) do
|
||||||
plugin.dir = nil
|
plugin.dir = nil
|
||||||
end
|
end
|
||||||
assert.same(spec.plugins, {
|
assert.same(clean(spec.plugins), {
|
||||||
bar = {
|
bar = {
|
||||||
"foo/bar",
|
"foo/bar",
|
||||||
_ = {},
|
_ = {},
|
||||||
|
@ -335,3 +350,32 @@ describe("plugin opts", function()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe("plugin spec", function()
|
||||||
|
it("only includes fragments from enabled plugins", function()
|
||||||
|
local tests = {
|
||||||
|
{
|
||||||
|
spec = {
|
||||||
|
{ "foo/disabled", enabled = false, dependencies = { "foo/bar", opts = { key_disabled = true } } },
|
||||||
|
{ "foo/disabled", dependencies = { "foo/bar", opts = { key_disabled_two = true } } },
|
||||||
|
{ "foo/conditional", cond = false, dependencies = { "foo/bar", opts = { key_cond = true } } },
|
||||||
|
{ "foo/optional", optional = true, dependencies = { "foo/bar", opts = { key_optional = true } } },
|
||||||
|
{ "foo/active", dependencies = { "foo/bar", opts = { key_active = true } } },
|
||||||
|
{
|
||||||
|
"foo/bar",
|
||||||
|
opts = { key = true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected_opts = { key = true, key_active = true },
|
||||||
|
}, -- for now, one test...
|
||||||
|
}
|
||||||
|
for _, test in ipairs(tests) do
|
||||||
|
local spec = Plugin.Spec.new(test.spec)
|
||||||
|
assert(#spec.notifs == 0)
|
||||||
|
assert(vim.tbl_count(spec.plugins) == 2)
|
||||||
|
assert(spec.plugins.active)
|
||||||
|
assert(spec.plugins.bar)
|
||||||
|
assert.same(test.expected_opts, Plugin.values(spec.plugins.bar, "opts"))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
Loading…
Reference in New Issue