From 282ec2602d808556f5632a6b8b9a267121575ace Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Thu, 30 Apr 2026 14:05:55 +0200 Subject: [PATCH] refactor(pack)!: collapse Plugin* commands into :Plugin --- lua/core/commands.lua | 140 +++++++++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 37 deletions(-) diff --git a/lua/core/commands.lua b/lua/core/commands.lua index 6f86676..6d23e9a 100644 --- a/lua/core/commands.lua +++ b/lua/core/commands.lua @@ -1,3 +1,5 @@ +local log = require("log") + vim.api.nvim_create_user_command( "Q", "q", @@ -9,51 +11,115 @@ vim.api.nvim_create_user_command( { bang = true, desc = "Alias to :qa" } ) -vim.api.nvim_create_user_command("PluginWatch", function() - require("pack").watch() -end, { desc = "Watch plugin configs for changes and hot-reload" }) - -vim.api.nvim_create_user_command("PluginUnwatch", function() - require("pack").unwatch() -end, { desc = "Stop watching plugin configs" }) - local function complete_plugin_names(lead) return vim.tbl_filter(function(name) return name:find(lead, 1, true) == 1 end, require("pack").get_names()) end -vim.api.nvim_create_user_command("PluginReload", function(opts) - require("pack").reload_plugin(opts.args) -end, { - nargs = 1, - complete = complete_plugin_names, - desc = "Reload a plugin config by name", -}) +---@class ow.PluginSubcommand +---@field run fun(args: string[]) +---@field min_args? integer +---@field max_args? integer +---@field complete? fun(lead: string): string[] -vim.api.nvim_create_user_command("PluginUpdate", function(opts) - local names = #opts.fargs > 0 and opts.fargs or nil - require("pack").update(names) -end, { - nargs = "*", - complete = complete_plugin_names, - desc = "Update plugins (fetch from remote)", -}) +---@type table +local plugin_cmds = { + watch = { + max_args = 0, + run = function() + require("pack").watch() + end, + }, + unwatch = { + max_args = 0, + run = function() + require("pack").unwatch() + end, + }, + reload = { + min_args = 1, + max_args = 1, + complete = complete_plugin_names, + run = function(args) + require("pack").reload_plugin(args[1] --[[@as -nil]]) + end, + }, + update = { + complete = complete_plugin_names, + run = function(args) + require("pack").update(#args > 0 and args or nil) + end, + }, + ["update-offline"] = { + complete = complete_plugin_names, + run = function(args) + require("pack").update( + #args > 0 and args or nil, + { offline = true } + ) + end, + }, + restore = { + complete = complete_plugin_names, + run = function(args) + require("pack").update( + #args > 0 and args or nil, + { target = "lockfile" } + ) + end, + }, +} -vim.api.nvim_create_user_command("PluginUpdateOffline", function(opts) - local names = #opts.fargs > 0 and opts.fargs or nil - require("pack").update(names, { offline = true }) -end, { - nargs = "*", - complete = complete_plugin_names, - desc = "Show pending plugin updates without fetching from remote", -}) +local plugin_cmd_names = vim.tbl_keys(plugin_cmds) +table.sort(plugin_cmd_names) -vim.api.nvim_create_user_command("PluginRestore", function(opts) - local names = #opts.fargs > 0 and opts.fargs or nil - require("pack").update(names, { target = "lockfile" }) +vim.api.nvim_create_user_command("Plugin", function(opts) + local cmd_name = opts.fargs[1] + local cmd = plugin_cmds[cmd_name] + if not cmd then + log.error( + "Plugin: unknown subcommand %q (expected one of: %s)", + cmd_name or "", + table.concat(plugin_cmd_names, ", ") + ) + return + end + local args = vim.list_slice(opts.fargs, 2) + local bound, n = nil, #args + if cmd.min_args and n < cmd.min_args then + bound = { "least", cmd.min_args } + elseif cmd.max_args and n > cmd.max_args then + bound = { "most", cmd.max_args } + end + if bound then + log.error( + "Plugin %s: expected at %s %d argument(s), got %d", + cmd_name, + bound[1], + bound[2], + n + ) + return + end + cmd.run(args) end, { - nargs = "*", - complete = complete_plugin_names, - desc = "Restore plugins to revisions in the lockfile", + nargs = "+", + complete = function(arg_lead, cmd_line) + local rest = cmd_line:gsub("^%s*%S+%s*", "", 1) + local words = vim.split(rest, "%s+", { trimempty = false }) + if #words <= 1 then + return vim.tbl_filter(function(name) + return name:find(arg_lead, 1, true) == 1 + end, plugin_cmd_names) + end + local cmd = plugin_cmds[words[1]] + if not cmd or not cmd.complete then + return {} + end + return cmd.complete(arg_lead) + end, + desc = "Plugin management (subcommands: " + .. table.concat(plugin_cmd_names, ", ") + .. ")", })