feat: dependencies are opt=true by default if they only appear as a dep

This commit is contained in:
Folke Lemaitre 2022-11-29 19:51:37 +01:00
parent 5810635a26
commit 908b9adf9c
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
6 changed files with 128 additions and 26 deletions

View File

@ -42,8 +42,9 @@
- [x] move tasks etc to Plugin.state - [x] move tasks etc to Plugin.state
- [ ] allow setting up plugins through config - [ ] allow setting up plugins through config
- [ ] handlers imply opt - [ ] handlers imply opt
- [ ] dependencies imply opt for deps - [x] dependencies imply opt for deps
- [x] fix local plugin spec - [x] fix local plugin spec
- [ ] investigate all opt=true. Simplifies logic (easily switch between opt/start afterwards)
## 📦 Differences with Packer ## 📦 Differences with Packer

View File

@ -38,6 +38,7 @@ M.dirty = false
---@field name string display name and name used for plugin config files ---@field name string display name and name used for plugin config files
---@field uri string ---@field uri string
---@field dir string ---@field dir string
---@field dep? boolean True if this plugin is only in the spec as a dependency
---@field enabled? boolean|(fun():boolean) ---@field enabled? boolean|(fun():boolean)
---@field opt? boolean ---@field opt? boolean
---@field dependencies? string[] ---@field dependencies? string[]
@ -82,7 +83,8 @@ function Spec.load(modname, modpath)
end end
---@param plugin LazyPlugin ---@param plugin LazyPlugin
function Spec:add(plugin) ---@param is_dep? boolean
function Spec:add(plugin, is_dep)
local pkg = plugin[1] local pkg = plugin[1]
if type(pkg) ~= "string" then if type(pkg) ~= "string" then
Util.error("Invalid plugin spec " .. vim.inspect(plugin)) Util.error("Invalid plugin spec " .. vim.inspect(plugin))
@ -108,27 +110,30 @@ function Spec:add(plugin)
plugin.name = slash and name:sub(#name - slash + 2) or pkg:gsub("%W+", "_") plugin.name = slash and name:sub(#name - slash + 2) or pkg:gsub("%W+", "_")
end end
plugin.dep = is_dep
M.process_local(plugin) M.process_local(plugin)
local other = self.plugins[plugin.name] local other = self.plugins[plugin.name]
self.plugins[plugin.name] = other and vim.tbl_extend("force", self.plugins[plugin.name], plugin) or plugin self.plugins[plugin.name] = other and M.merge(other, plugin) or plugin
return self.plugins[plugin.name] return self.plugins[plugin.name]
end end
---@param spec LazySpec ---@param spec LazySpec
---@param results? string[] ---@param results? string[]
function Spec:normalize(spec, results) ---@param is_dep? boolean
function Spec:normalize(spec, results, is_dep)
results = results or {} results = results or {}
if type(spec) == "string" then if type(spec) == "string" then
table.insert(results, self:add({ spec }).name) table.insert(results, self:add({ spec }, is_dep).name)
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) self:normalize(s, results, is_dep)
end end
elseif spec.enabled == nil or spec.enabled == true or (type(spec.enabled) == "function" and spec.enabled()) then elseif spec.enabled == nil or spec.enabled == true or (type(spec.enabled) == "function" and spec.enabled()) then
---@cast spec LazyPlugin ---@cast spec LazyPlugin
local plugin = self:add(spec) local plugin = self:add(spec, is_dep)
plugin.dependencies = plugin.dependencies and self:normalize(plugin.dependencies, {}) or nil plugin.dependencies = plugin.dependencies and self:normalize(plugin.dependencies, {}, true) or nil
table.insert(results, plugin.name) table.insert(results, plugin.name)
end end
return results return results
@ -152,9 +157,41 @@ function Spec.revive(spec)
return spec return spec
end end
function M.update_state(check_clean) ---@param old LazyPlugin
---@param new LazyPlugin
---@return LazyPlugin
function M.merge(old, new)
local is_dep = old.dep and new.dep
local Handler = require("lazy.core.handler")
---@diagnostic disable-next-line: no-unknown
for k, v in pairs(new) do
if k == "dep" then
elseif old[k] ~= nil and old[k] ~= v then
if Handler.handlers[k] then
local values = type(v) == "string" and { v } or v
vim.list_extend(values, type(old[k]) == "string" and { old[k] } or old[k])
---@diagnostic disable-next-line: no-unknown
old[k] = values
else
error("Merging plugins is not supported for key `" .. k .. "`")
end
else
---@diagnostic disable-next-line: no-unknown
old[k] = v
end
end
old.dep = is_dep
return old
end
---@param opts? {clean:boolean, installed:boolean, plugins?: LazyPlugin[]}
function M.update_state(opts)
opts = opts or {}
---@type table<"opt"|"start", table<string,FileType>> ---@type table<"opt"|"start", table<string,FileType>>
local installed = { opt = {}, start = {} } local installed = { opt = {}, start = {} }
if opts.installed ~= false then
for opt, packs in pairs(installed) do for opt, packs in pairs(installed) do
Util.ls(Config.options.packpath .. "/" .. opt, function(_, name, type) Util.ls(Config.options.packpath .. "/" .. opt, function(_, name, type)
if type == "directory" or type == "link" then if type == "directory" or type == "link" then
@ -162,12 +199,13 @@ function M.update_state(check_clean)
end end
end) end)
end end
end
for _, plugin in pairs(Config.plugins) do for _, plugin in pairs(opts.plugins or Config.plugins) do
plugin._ = plugin._ or {} plugin._ = plugin._ or {}
plugin[1] = plugin["1"] or plugin[1] plugin[1] = plugin["1"] or plugin[1]
if plugin.opt == nil then if plugin.opt == nil then
plugin.opt = Config.options.opt plugin.opt = plugin.dep or Config.options.opt
end end
local opt = plugin.opt and "opt" or "start" local opt = plugin.opt and "opt" or "start"
plugin.dir = Config.options.packpath .. "/" .. opt .. "/" .. plugin.name plugin.dir = Config.options.packpath .. "/" .. opt .. "/" .. plugin.name
@ -179,7 +217,7 @@ function M.update_state(check_clean)
end end
end end
if check_clean then if opts.clean then
Config.to_clean = {} Config.to_clean = {}
for opt, packs in pairs(installed) do for opt, packs in pairs(installed) do
for pack in pairs(packs) do for pack in pairs(packs) do
@ -244,7 +282,7 @@ function M.load()
for _, spec in ipairs(specs) do for _, spec in ipairs(specs) do
for _, plugin in pairs(spec.plugins) do for _, plugin in pairs(spec.plugins) do
local other = Config.plugins[plugin.name] local other = Config.plugins[plugin.name]
Config.plugins[plugin.name] = other and vim.tbl_extend("force", other, plugin) or plugin Config.plugins[plugin.name] = other and M.merge(other, plugin) or plugin
end end
end end

View File

@ -115,7 +115,7 @@ end
---@param opts? ManagerOpts ---@param opts? ManagerOpts
function M.clean(opts) function M.clean(opts)
Plugin.update_state(true) Plugin.update_state({ clean = true })
M.run({ M.run({
pipeline = { "fs.clean" }, pipeline = { "fs.clean" },
plugins = Config.to_clean, plugins = Config.to_clean,
@ -123,7 +123,7 @@ function M.clean(opts)
end end
function M.clear() function M.clear()
Plugin.update_state(true) Plugin.update_state({ clean = true })
for _, plugin in pairs(Config.plugins) do for _, plugin in pairs(Config.plugins) do
plugin._.updated = nil plugin._.updated = nil
plugin._.cloned = nil plugin._.cloned = nil

View File

@ -13,7 +13,7 @@ M.modes = {
{ name = "log", key = "L", desc = "Show recent updates for all plugins" }, { name = "log", key = "L", desc = "Show recent updates for all plugins" },
{ name = "restore", key = "R", desc = "Updates all plugins to the state in the lockfile" }, { name = "restore", key = "R", desc = "Updates all plugins to the state in the lockfile" },
{ name = "profile", key = "P", desc = "Show detailed profiling", toggle = true }, { name = "profile", key = "P", desc = "Show detailed profiling", toggle = true },
{ name = "help", key = "g?", hide = true, desc = "Toggle this help page", toggle = true }, { name = "help", key = "?", hide = true, desc = "Toggle this help page", toggle = true },
{ plugin = true, name = "update", key = "u", desc = "Update this plugin. This will also update the lockfile" }, { plugin = true, name = "update", key = "u", desc = "Update this plugin. This will also update the lockfile" },
{ {

View File

@ -2,7 +2,6 @@ local Config = require("lazy.core.config")
local Util = require("lazy.util") local Util = require("lazy.util")
local Sections = require("lazy.view.sections") local Sections = require("lazy.view.sections")
local Handler = require("lazy.core.handler") local Handler = require("lazy.core.handler")
local Plugin = require("lazy.core.plugin")
local Git = require("lazy.manage.git") local Git = require("lazy.manage.git")
local Text = require("lazy.view.text") local Text = require("lazy.view.text")
@ -95,7 +94,7 @@ end
function M:title() function M:title()
self:append(" lazy.nvim ", "LazyH1"):center():nl() self:append(" lazy.nvim ", "LazyH1"):center():nl()
self:append("press "):append("g?", "LazySpecial"):append(" for help"):center():nl() self:append("press "):append("<?>", "LazySpecial"):append(" for help"):center():nl()
self:append("https://github.com/folke/lazy.nvim", "LazyMuted"):center():nl() self:append("https://github.com/folke/lazy.nvim", "LazyMuted"):center():nl()
local View = require("lazy.view") local View = require("lazy.view")

View File

@ -5,7 +5,7 @@ local assert = require("luassert")
Config.setup() Config.setup()
describe("plugin spec", function() describe("plugin spec uri/name", function()
local tests = { local tests = {
{ { "~/foo" }, { [1] = "~/foo", name = "foo", uri = vim.fn.fnamemodify("~/foo", ":p") } }, { { "~/foo" }, { [1] = "~/foo", name = "foo", uri = vim.fn.fnamemodify("~/foo", ":p") } },
{ { "/tmp/foo" }, { [1] = "/tmp/foo", name = "foo", uri = "/tmp/foo" } }, { { "/tmp/foo" }, { [1] = "/tmp/foo", name = "foo", uri = "/tmp/foo" } },
@ -19,7 +19,7 @@ describe("plugin spec", function()
} }
for _, test in ipairs(tests) do for _, test in ipairs(tests) do
it("parses uri " .. vim.inspect(test[1]):gsub("%s+", " "), function() it("parses " .. vim.inspect(test[1]):gsub("%s+", " "), function()
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)
assert.equal(1, #plugins) assert.equal(1, #plugins)
@ -27,3 +27,67 @@ describe("plugin spec", function()
end) end)
end end
end) end)
describe("plugin spec opt", function()
it("handles dependencies", function()
local tests = {
{ "foo/bar", dependencies = { "foo/dep1", "foo/dep2" } },
{ "foo/bar", dependencies = { { "foo/dep1" }, "foo/dep2" } },
{ { { "foo/bar", dependencies = { { "foo/dep1" }, "foo/dep2" } } } },
}
Config.options.opt = false
for _, test in ipairs(tests) do
local spec = Plugin.Spec.new(test)
Plugin.update_state({ plugins = spec.plugins })
assert(vim.tbl_count(spec.plugins) == 3)
assert(#spec.plugins.bar.dependencies == 2)
assert(spec.plugins.bar.dep ~= true)
assert(spec.plugins.bar.opt == false)
assert(spec.plugins.dep1.dep == true)
assert(spec.plugins.dep1.opt == true)
assert(spec.plugins.dep2.dep == true)
assert(spec.plugins.dep2.opt == true)
end
end)
it("handles opt from dep", function()
Config.options.opt = false
local spec = Plugin.Spec.new({ "foo/dep1", { "foo/bar", dependencies = { "foo/dep1", "foo/dep2" } } })
Plugin.update_state({ plugins = spec.plugins })
assert.same(3, vim.tbl_count(spec.plugins))
assert(spec.plugins.bar.dep ~= true)
assert(spec.plugins.bar.opt == false)
assert(spec.plugins.dep2.dep == true)
assert(spec.plugins.dep2.opt == true)
assert(spec.plugins.dep1.dep ~= true)
assert(spec.plugins.dep1.opt == false)
end)
it("merges lazy loaders", function()
local tests = {
{ { "foo/bar", module = "mod1" }, { "foo/bar", module = "mod2" } },
{ { "foo/bar", module = { "mod1" } }, { "foo/bar", module = { "mod2" } } },
{ { "foo/bar", module = "mod1" }, { "foo/bar", module = { "mod2" } } },
}
for _, test in ipairs(tests) do
local spec = Plugin.Spec.new(test)
assert(vim.tbl_count(spec.plugins) == 1)
assert(type(spec.plugins.bar.module) == "table")
assert(#spec.plugins.bar.module == 2)
assert(vim.tbl_contains(spec.plugins.bar.module, "mod1"))
assert(vim.tbl_contains(spec.plugins.bar.module, "mod2"))
end
end)
it("refuses to merge", function()
assert.has.errors(function()
Plugin.Spec.new({
{ "foo/dep1", config = 1 },
{
"foo/bar",
dependencies = { { "foo/dep1", config = 2 }, "foo/dep2" },
},
})
end)
end)
end)