diff --git a/README.md b/README.md index 33dafa8..2d91ff2 100644 --- a/README.md +++ b/README.md @@ -380,24 +380,38 @@ Any operation can be started from the UI, with a sub command or an API function: -| Command | Lua | Description | -| ------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------- | -| `:Lazy home` | `require("lazy").home()` | Go back to plugin list | -| `:Lazy install [plugins]` | `require("lazy").install(plugins?)` | Install missing plugins | -| `:Lazy update [plugins]` | `require("lazy").update(plugins?)` | Update all plugins. This will also update the lockfile | -| `:Lazy sync` | `require("lazy").sync()` | Run install, clean and update | -| `:Lazy clean [plugins]` | `require("lazy").clean(plugins?)` | Clean plugins that are no longer needed | -| `:Lazy check [plugins]` | `require("lazy").check(plugins?)` | Check for updates and show the log (git fetch) | -| `:Lazy log [plugins]` | `require("lazy").log(plugins?)` | Show recent updates for all plugins | -| `:Lazy restore [plugins]` | `require("lazy").restore(plugins?)` | Updates all plugins to the state in the lockfile | -| `:Lazy profile` | `require("lazy").profile()` | Show detailed profiling | -| `:Lazy debug` | `require("lazy").debug()` | Show debug information | -| `:Lazy help` | `require("lazy").help()` | Toggle this help page | -| `:Lazy clear` | `require("lazy").clear()` | Clear finished tasks | -| `:Lazy load {plugins}` | `require("lazy").load(plugins)` | Load a plugin that has not been loaded yet. Similar to `:packadd`. Like `:Lazy load foo.nvim` | +| Command | Lua | Description | +| ------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------- | +| `:Lazy check [plugins]` | `require("lazy").check(opts?)` | Check for updates and show the log (git fetch) | +| `:Lazy clean [plugins]` | `require("lazy").clean(opts?)` | Clean plugins that are no longer needed | +| `:Lazy clear` | `require("lazy").clear()` | Clear finished tasks | +| `:Lazy debug` | `require("lazy").debug()` | Show debug information | +| `:Lazy help` | `require("lazy").help()` | Toggle this help page | +| `:Lazy home` | `require("lazy").home()` | Go back to plugin list | +| `:Lazy install [plugins]` | `require("lazy").install(opts?)` | Install missing plugins | +| `:Lazy load {plugins}` | `require("lazy").load(opts)` | Load a plugin that has not been loaded yet. Similar to `:packadd`. Like `:Lazy load foo.nvim` | +| `:Lazy log [plugins]` | `require("lazy").log(opts?)` | Show recent updates for all plugins | +| `:Lazy profile` | `require("lazy").profile()` | Show detailed profiling | +| `:Lazy restore [plugins]` | `require("lazy").restore(opts?)` | Updates all plugins to the state in the lockfile | +| `:Lazy sync [plugins]` | `require("lazy").sync(opts?)` | Run install, clean and update | +| `:Lazy update [plugins]` | `require("lazy").update(opts?)` | Update all plugins. This will also update the lockfile | +Any command can have a **bang** to make the command wait till it finished. For example, +if you want to sync lazy from the cmdline, you can use: + +```shell +$ nvim --headless "+Lazy! sync" +qa +``` + +`opts` is a table with the following key-values: + +- **wait**: when true, then the call will wait till the operation completed +- **show**: when false, the UI will not be shown +- **plugins**: a list of plugin names to run the operation on +- **concurrency**: limit the `number` of concurrently running tasks + If you want to display the number of plugins on your dashboard, you can use this simple API: diff --git a/lua/lazy/docs.lua b/lua/lazy/docs.lua index b8020ae..755892b 100644 --- a/lua/lazy/docs.lua +++ b/lua/lazy/docs.lua @@ -75,41 +75,43 @@ end function M.commands() local commands = require("lazy.view.commands").commands - local modes = require("lazy.view").modes + ---@type table + local modes = {} + for _, mode in ipairs(require("lazy.view").modes) do + modes[mode.name] = modes[mode.name] or {} + modes[mode.name].plugin = modes[mode.name].plugin or mode.plugin + if not modes[mode.name].desc or not mode.plugin then + modes[mode.name].desc = mode.desc + end + end + modes.load.opts = true local lines = { { "Command", "Lua", "Description" }, { "---", "---", "---", "---" }, } - local with_plugins = {} - for _, mode in ipairs(modes) do - if mode.plugin then - with_plugins[mode.name] = true - end - end - local plugins_required = { load = true } - for _, mode in ipairs(modes) do - if not mode.plugin and commands[mode.name] then - if plugins_required[mode.name] then + Util.foreach(modes, function(name, mode) + if commands[name] then + if mode.opts then lines[#lines + 1] = { - ("`:Lazy %s {plugins}`"):format(mode.name), - ([[`require("lazy").%s(plugins)`]]):format(mode.name), + ("`:Lazy %s {plugins}`"):format(name), + ([[`require("lazy").%s(opts)`]]):format(name), mode.desc, } - elseif with_plugins[mode.name] then + elseif mode.plugin then lines[#lines + 1] = { - ("`:Lazy %s [plugins]`"):format(mode.name), - ([[`require("lazy").%s(plugins?)`]]):format(mode.name), + ("`:Lazy %s [plugins]`"):format(name), + ([[`require("lazy").%s(opts?)`]]):format(name), mode.desc, } else lines[#lines + 1] = { - ("`:Lazy %s`"):format(mode.name), - ([[`require("lazy").%s()`]]):format(mode.name), + ("`:Lazy %s`"):format(name), + ([[`require("lazy").%s()`]]):format(name), mode.desc, } end end - end + end) local ret = {} for _, line in ipairs(lines) do ret[#ret + 1] = "| " .. table.concat(line, " | ") .. " |" diff --git a/lua/lazy/manage/init.lua b/lua/lazy/manage/init.lua index 27d8821..cac6efc 100644 --- a/lua/lazy/manage/init.lua +++ b/lua/lazy/manage/init.lua @@ -52,8 +52,17 @@ function M.run(ropts, opts) return runner end +---@generic O: ManagerOpts +---@param opts? O +---@param defaults? ManagerOpts +---@return O +function M.opts(opts, defaults) + return vim.tbl_deep_extend("force", { clear = true }, defaults or {}, opts or {}) +end + ---@param opts? ManagerOpts function M.install(opts) + opts = M.opts(opts, { mode = "install" }) return M.run({ pipeline = { "git.clone", @@ -72,7 +81,7 @@ end ---@param opts? ManagerOpts|{lockfile?:boolean} function M.update(opts) - opts = opts or {} + opts = M.opts(opts, { mode = "update" }) return M.run({ pipeline = { "git.branch", @@ -91,9 +100,16 @@ function M.update(opts) require("lazy.help").update() end) end +-- +---@param opts? ManagerOpts +function M.restore(opts) + opts = M.opts(opts, { mode = "restore", lockfile = true }) + return M.update(opts) +end ---@param opts? ManagerOpts function M.check(opts) + opts = M.opts(opts, { mode = "check" }) opts = opts or {} return M.run({ pipeline = { @@ -109,6 +125,7 @@ end ---@param opts? ManagerOpts function M.log(opts) + opts = M.opts(opts, { mode = "log" }) return M.run({ pipeline = { "git.log" }, plugins = function(plugin) @@ -117,8 +134,21 @@ function M.log(opts) }, opts) end +---@param opts? ManagerOpts +function M.sync(opts) + opts = M.opts(opts, { mode = "sync" }) + if opts.clear then + M.clear() + opts.clear = false + end + M.clean(opts) + M.install(opts) + M.update(opts) +end + ---@param opts? ManagerOpts function M.clean(opts) + opts = M.opts(opts, { mode = "clean" }) return M.run({ pipeline = { "fs.clean" }, plugins = Config.to_clean, diff --git a/lua/lazy/view/commands.lua b/lua/lazy/view/commands.lua index eae1ba7..0005848 100644 --- a/lua/lazy/view/commands.lua +++ b/lua/lazy/view/commands.lua @@ -6,32 +6,23 @@ local Config = require("lazy.core.config") local M = {} ---@param cmd string ----@param plugins? LazyPlugin[] -function M.cmd(cmd, plugins) +---@param opts? ManagerOpts +function M.cmd(cmd, opts) cmd = cmd == "" and "home" or cmd local command = M.commands[cmd] if command == nil then Util.error("Invalid lazy command '" .. cmd .. "'") else - command(plugins) + command(opts) end end ---@class LazyCommands M.commands = { - clean = function(plugins) - Manage.clean({ clear = true, mode = "clean", plugins = plugins }) - end, clear = function() Manage.clear() View.show() end, - install = function(plugins) - Manage.install({ clear = true, mode = "install", plugins = plugins }) - end, - log = function(plugins) - Manage.log({ clear = true, mode = "log", plugins = plugins }) - end, home = function() View.show("home") end, @@ -47,23 +38,20 @@ M.commands = { profile = function() View.show("profile") end, - sync = function() - Manage.clean({ clear = true, wait = true, mode = "sync" }) - Manage.update() - Manage.install() - end, - update = function(plugins) - Manage.update({ clear = true, mode = "update", plugins = plugins }) - end, - check = function(plugins) - Manage.check({ clear = true, mode = "check", plugins = plugins }) - end, - restore = function(plugins) - Manage.update({ clear = true, lockfile = true, mode = "restore", plugins = plugins }) - end, - load = function(plugins) - require("lazy.core.loader").load(plugins, { cmd = "LazyLoad" }) + ---@param opts ManagerOpts + load = function(opts) + if not (opts and opts.plugins and #opts.plugins > 0) then + return Util.error("`Lazy load` requires at least one plugin name to load") + end + require("lazy.core.loader").load(opts.plugins, { cmd = "LazyLoad" }) end, + log = Manage.log, + clean = Manage.clean, + install = Manage.install, + sync = Manage.sync, + update = Manage.update, + check = Manage.check, + restore = Manage.restore, } function M.complete(cmd, prefix) @@ -91,26 +79,23 @@ end function M.setup() vim.api.nvim_create_user_command("Lazy", function(cmd) - local args = vim.split(vim.trim(cmd.args or ""), " ") - local name = args[1] - table.remove(args, 1) - M.cmd(name, #args > 0 and args or nil) + ---@type ManagerOpts + local opts = { wait = cmd.bang == true } + local prefix, args = M.parse(cmd.args) + if #args > 0 then + opts.plugins = args + end + M.cmd(prefix, opts) end, { + bang = true, nargs = "?", desc = "Lazy", complete = function(_, line) - ---@type string? - local cmd, prefix = line:match("^%s*Lazy (%w+) (%w*)") - if prefix then - return M.complete(cmd, prefix) + local prefix, args = M.parse(line) + if #args > 0 then + return M.complete(prefix, args[#args]) end - if line:match("^%s*Lazy %w+ ") then - return {} - end - - prefix = line:match("^%s*Lazy (%w*)") or "" - ---@param key string return vim.tbl_filter(function(key) return key:find(prefix) == 1 @@ -119,4 +104,16 @@ function M.setup() }) end +---@return string, string[] +function M.parse(args) + local parts = vim.split(vim.trim(args), "%s+") + if parts[1]:find("Lazy") then + table.remove(parts, 1) + end + if args:sub(-1) == " " then + parts[#parts + 1] = "" + end + return table.remove(parts, 1) or "", parts +end + return M diff --git a/lua/lazy/view/init.lua b/lua/lazy/view/init.lua index eeac8f6..07d655e 100644 --- a/lua/lazy/view/init.lua +++ b/lua/lazy/view/init.lua @@ -21,7 +21,9 @@ M.modes = { name = "load", desc = "Load a plugin that has not been loaded yet. Similar to `:packadd`. Like `:Lazy load foo.nvim`", hide = true, + plugin = true, }, + { name = "sync", desc = "Run install, clean and update", hide = true, plugin = true }, { plugin = true, name = "update", key = "u", desc = "Update this plugin. This will also update the lockfile" }, { @@ -193,7 +195,7 @@ function M.show(mode) if m.plugin then local plugin = get_plugin() if plugin then - Commands.cmd(m.name, { plugin }) + Commands.cmd(m.name, { plugins = { plugin } }) end else if M.mode == m.name and m.toggle then