diff --git a/README.md b/README.md index 0a54f7d..4dfe095 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,9 @@ My Neovim config. ## System Requirements + Only supports Linux, macOS and other BSD variants. Requires neovim v0.12. -Below is a list of dependencies and the respective plugins that require it. - -| Dependency | Plugins | -| ------------ | ----------------------------------------- | -| git | lazy, mason | -| C compiler | treesitter, LuaSnip, telescope-fzf-native | -| make | LuaSnip, telescope-fzf-native | -| curl or wget | mason | -| unzip | mason | -| GNU tar | mason | -| gzip | mason | - ## License + BSD-3-Clause, see [LICENSE](LICENSE) for more information. diff --git a/after/lsp/lua_ls.lua b/after/lsp/lua_ls.lua index c36d3f4..aa472b6 100644 --- a/after/lsp/lua_ls.lua +++ b/after/lsp/lua_ls.lua @@ -1,7 +1,7 @@ local lsp = require("lsp") -local lua_library_paths = require("plugin").get_paths() -table.insert(lua_library_paths, vim.env.VIMRUNTIME) +local lua_library_paths = { vim.env.VIMRUNTIME } +vim.list_extend(lua_library_paths, require("pack").paths) ---@type vim.lsp.Config return { diff --git a/init.lua b/init.lua index 6bba3ec..62098f4 100644 --- a/init.lua +++ b/init.lua @@ -21,7 +21,7 @@ for _, file in ipairs(files) do end end -require("plugin").setup({ +require("pack").setup({ "https://github.com/navarasu/onedark.nvim", "https://github.com/nvim-lua/plenary.nvim", "https://github.com/rcarriga/nvim-notify", diff --git a/lua/core/commands.lua b/lua/core/commands.lua index a95ac52..83fd5c5 100644 --- a/lua/core/commands.lua +++ b/lua/core/commands.lua @@ -3,21 +3,21 @@ vim.api.nvim_create_user_command("Q", "q", { desc = "Alias to :q" }) vim.api.nvim_create_user_command("Qa", "q", { desc = "Alias to :qa" }) vim.api.nvim_create_user_command("PluginWatch", function() - require("plugin").watch() + require("pack").watch() end, { desc = "Watch plugin configs for changes and hot-reload" }) vim.api.nvim_create_user_command("PluginUnwatch", function() - require("plugin").unwatch() + require("pack").unwatch() end, { desc = "Stop watching plugin configs" }) vim.api.nvim_create_user_command("PluginReload", function(opts) - require("plugin").reload(opts.args) + require("pack").reload(opts.args) end, { nargs = 1, complete = function(lead) return vim.tbl_filter(function(name) return name:find(lead, 1, true) == 1 - end, require("plugin").get_names()) + end, require("pack").names) end, desc = "Reload a plugin config by name", }) diff --git a/lua/plugin.lua b/lua/pack.lua similarity index 65% rename from lua/plugin.lua rename to lua/pack.lua index cee1a43..df102d8 100644 --- a/lua/plugin.lua +++ b/lua/pack.lua @@ -1,17 +1,6 @@ local log = require("log") ----@class ow.Plugin.Spec ----@field [1] string ----@field name? string ----@field version? string | vim.VersionRange ----@field lazy? boolean ----@field build? string[] | fun(self: ow.Plugin): boolean - ----@class ow.Plugin : ow.Plugin.Spec ----@field path string - ----@type ow.Plugin[] -local plugins = {} +local config_dir = vim.fn.stdpath("config") ---@param path string ---@return boolean success @@ -30,16 +19,20 @@ local function exec(path) return true end ----@param plugin ow.Plugin -local function load(plugin) - vim.cmd.packadd(plugin.name) +---@class ow.Pack.PluginSpec +---@field [1] string +---@field name? string +---@field version? string | vim.VersionRange +---@field build? string[] | fun(self: ow.Pack.Plugin) +---@class ow.Pack.Plugin : ow.Pack.PluginSpec +---@field name string +---@field path string + +---@param plugin ow.Pack.Plugin +local function load(plugin) local name = plugin.name:match("[^.]+"):lower() - local path = string.format( - "%s/lua/plugins/%s.lua", - vim.fn.stdpath("config"), - name - ) + local path = string.format("%s/lua/plugins/%s.lua", config_dir, name) if vim.uv.fs_stat(path) then local ok, err = exec(path) @@ -49,7 +42,7 @@ local function load(plugin) end end ----@param spec string | ow.Plugin.Spec +---@param spec string | ow.Pack.PluginSpec ---@return vim.pack.Spec local function to_pack_spec(spec) if type(spec) == "string" then @@ -61,44 +54,44 @@ local function to_pack_spec(spec) name = spec.name, version = spec.version, data = { - lazy = spec.lazy, build = spec.build, }, } end ----@param plugin ow.Plugin ----@return boolean success +---@param plugin ow.Pack.Plugin local function run_build(plugin) if type(plugin.build) == "function" then - return plugin.build(plugin) + plugin.build(plugin) + return elseif type(plugin.build) == "table" then local ret = vim.system( plugin.build --[[@as table]], { cwd = plugin.path } ):wait() - return ret.code == 0 and ret.signal == 0 + if ret.code ~= 0 then + log.error("Build failed for %s: %s", plugin.name, ret.stderr or "") + end + return end log.error("invalid build parameter for %s", plugin.name) - return false end ----@class ow.Plugin.PackEvent.Data +---@class ow.Pack.Event.Data ---@field active boolean ---@field kind "install" | "update" | "delete" ---@field spec vim.pack.Spec ---@field path string ----@class ow.Plugin.PackEvent : vim.api.keyset.create_autocmd.callback_args ----@field data ow.Plugin.PackEvent.Data +---@class ow.Pack.Event : vim.api.keyset.create_autocmd.callback_args +---@field data ow.Pack.Event.Data ----@param plugin ow.Plugin ----@param events ow.Plugin.PackEvent[] ----@return boolean success -local function handle_pack_events(plugin, events) +---@param plugin ow.Pack.Plugin +---@param events ow.Pack.Event[] +local function process_events(plugin, events) if not plugin.build then - return true + return end for _, ev in ipairs(events) do @@ -106,47 +99,30 @@ local function handle_pack_events(plugin, events) and ev.event == "PackChanged" and (ev.data.kind == "install" or ev.data.kind == "update") then - vim.cmd.packadd(plugin.name) - return run_build(plugin) + run_build(plugin) end end - - return true end ---@type uv.uv_fs_event_t? local watcher = nil -local M = {} +---@type table +local timers = {} -function M.get_paths() - local paths = {} - - for _, plugin in ipairs(plugins) do - table.insert(paths, plugin.path) - end - - return paths -end - ----@return string[] -function M.get_names() - local names = {} - - for _, plugin in ipairs(plugins) do - table.insert(names, plugin.name:match("[^.]+"):lower()) - end - - return names -end +---@class ow.Pack +---@field names string[] +---@field paths string[] +---@field plugins ow.Pack.Plugin[] +local M = { + names = {}, + paths = {}, + plugins = {}, +} ---@param name string function M.reload(name) - local path = string.format( - "%s/lua/plugins/%s.lua", - vim.fn.stdpath("config"), - name - ) + local path = string.format("%s/lua/plugins/%s.lua", config_dir, name) if not vim.uv.fs_stat(path) then log.error("No config file found for %s", name) @@ -166,10 +142,7 @@ function M.watch() return end - local plugins_dir = string.format( - "%s/lua/plugins", - vim.fn.stdpath("config") - ) + local plugins_dir = config_dir .. "/lua/plugins" watcher = vim.uv.new_fs_event() if not watcher then @@ -177,9 +150,6 @@ function M.watch() return end - ---@type table - local timers = {} - watcher:start( plugins_dir, {}, @@ -233,62 +203,67 @@ function M.unwatch() return end + for key, timer in pairs(timers) do + timer:stop() + timer:close() + timers[key] = nil + end + watcher:stop() watcher:close() watcher = nil end ----@param specs (string | ow.Plugin.Spec)[] +---@param specs (string | ow.Pack.PluginSpec)[] function M.setup(specs) - ---@type ow.Plugin.PackEvent[] + ---@type table local events = {} + local group = vim.api.nvim_create_augroup("ow.Pack", { clear = true }) local id = vim.api.nvim_create_autocmd( { "PackChangedPre", "PackChanged" }, { - ---@param ev ow.Plugin.PackEvent + group = group, + ---@param ev ow.Pack.Event callback = function(ev) - table.insert(events, ev) + local name = ev.data.spec.name + if not name then return end + if not events[name] then + events[name] = {} + end + table.insert(events[name], ev) end } ) vim.pack.add(vim.tbl_map(to_pack_spec, specs), { load = function(data) + if not data.spec.name then + log.error("Missing name for plugin: %s", data.spec.src) + return + end local d = data.spec.data or {} - ---@type ow.Plugin + ---@type ow.Pack.Plugin local plugin = { [1] = data.spec.src, name = data.spec.name, version = data.spec.version, - lazy = d.lazy or false, build = d.build, path = data.path, } - table.insert(plugins, plugin) + table.insert(M.plugins, plugin) + table.insert(M.names, plugin.name) + table.insert(M.paths, plugin.path) + vim.cmd.packadd(plugin.name) end }) vim.api.nvim_del_autocmd(id) - local lazy_plugins = {} - for _, plugin in ipairs(plugins) do - if not handle_pack_events(plugin, events) then - return - end - - if plugin.lazy then - table.insert(lazy_plugins, plugin) - else - load(plugin) + for _, plugin in ipairs(M.plugins) do + local ev = events[plugin.name] + if ev then + process_events(plugin, ev) end + load(plugin) end - - vim.api.nvim_create_autocmd("UIEnter", { - once = true, - callback = vim.schedule_wrap(function() - for _, plugin in ipairs(lazy_plugins) do - load(plugin) - end - end) - }) end return M