refactor(pack,ts): switch specs to src field and decentralize update hooks
This commit is contained in:
+69
-70
@@ -24,13 +24,11 @@ local function exec(path)
|
||||
return true
|
||||
end
|
||||
|
||||
---@class ow.Pack.PluginSpec
|
||||
---@field [1] string
|
||||
---@field name? string
|
||||
---@field version? string | vim.VersionRange
|
||||
---@class ow.Pack.Spec : vim.pack.Spec
|
||||
---@field src string
|
||||
---@field build? string[] | fun(self: ow.Pack.Plugin)
|
||||
|
||||
---@class ow.Pack.Plugin : ow.Pack.PluginSpec
|
||||
---@class ow.Pack.Plugin : ow.Pack.Spec
|
||||
---@field name string
|
||||
---@field path string
|
||||
|
||||
@@ -81,7 +79,7 @@ local function is_url(src)
|
||||
return src:find("://") ~= nil
|
||||
end
|
||||
|
||||
---@param spec string | ow.Pack.PluginSpec
|
||||
---@param spec string | ow.Pack.Spec
|
||||
---@return vim.pack.Spec
|
||||
local function to_pack_spec(spec)
|
||||
if type(spec) == "string" then
|
||||
@@ -89,7 +87,7 @@ local function to_pack_spec(spec)
|
||||
end
|
||||
|
||||
return {
|
||||
src = spec[1],
|
||||
src = spec.src,
|
||||
name = spec.name,
|
||||
version = spec.version,
|
||||
data = {
|
||||
@@ -130,62 +128,49 @@ local watcher = nil
|
||||
---@type ow.Util.KeyedDebounceHandle<string>?
|
||||
local on_change_handle = nil
|
||||
|
||||
---@alias ow.Pack.Hook fun(ev: ow.Pack.Event.Data)
|
||||
|
||||
---@type table<string, ow.Pack.Hook>
|
||||
local hooks = {}
|
||||
---@alias ow.Pack.Hook fun(data: ow.Pack.Event.Data)
|
||||
|
||||
---@class ow.Pack
|
||||
---@field plugins ow.Pack.Plugin[]
|
||||
---@field plugins table<string, ow.Pack.Plugin> keyed by src
|
||||
local M = {
|
||||
plugins = {},
|
||||
}
|
||||
|
||||
---@param name string
|
||||
---@param fn ow.Pack.Hook
|
||||
function M.register_hook(name, fn)
|
||||
hooks[name] = fn
|
||||
end
|
||||
|
||||
local function setup_event_listener()
|
||||
local group =
|
||||
vim.api.nvim_create_augroup("ow.Pack.events", { clear = true })
|
||||
vim.api.nvim_create_autocmd("PackChanged", {
|
||||
group = group,
|
||||
---@param ev ow.Pack.Event
|
||||
callback = function(ev)
|
||||
local name = ev.data.spec.name
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
if ev.data.kind ~= "install" and ev.data.kind ~= "update" then
|
||||
return
|
||||
end
|
||||
local hook = hooks[name]
|
||||
if hook then
|
||||
hook(ev.data)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
function M.get_names()
|
||||
return vim.tbl_map(function(p)
|
||||
return vim.tbl_values(vim.tbl_map(function(p)
|
||||
return p.name
|
||||
end, M.plugins)
|
||||
end, M.plugins))
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
function M.get_paths()
|
||||
return vim.tbl_map(function(p)
|
||||
return vim.tbl_values(vim.tbl_map(function(p)
|
||||
return p.path
|
||||
end, M.plugins)
|
||||
end, M.plugins))
|
||||
end
|
||||
|
||||
---@param plugin_path string
|
||||
function M.unload(plugin_path)
|
||||
local lua_dir = vim.fs.joinpath(plugin_path, "lua")
|
||||
local search = lua_dir .. "/?.lua;" .. lua_dir .. "/?/init.lua"
|
||||
for name in pairs(package.loaded) do
|
||||
if package.searchpath(name, search) then
|
||||
package.loaded[name] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param name string
|
||||
function M.reload_plugin(name)
|
||||
load(name, true)
|
||||
---@param required boolean
|
||||
function M.reload_plugin(name, required)
|
||||
for _, plugin in pairs(M.plugins) do
|
||||
if plugin.name == name then
|
||||
M.unload(plugin.path)
|
||||
break
|
||||
end
|
||||
end
|
||||
load(name, required)
|
||||
end
|
||||
|
||||
function M.watch()
|
||||
@@ -195,7 +180,7 @@ function M.watch()
|
||||
|
||||
local w, err = vim.uv.new_fs_event()
|
||||
if not w then
|
||||
util.error("pack: failed to create fs_event: %s", err)
|
||||
log.error("pack: failed to create fs_event: %s", err)
|
||||
return
|
||||
end
|
||||
local on_change, handle = util.keyed_debounce(
|
||||
@@ -232,7 +217,7 @@ function M.watch()
|
||||
end
|
||||
)
|
||||
if not ok then
|
||||
util.error("pack: failed to watch %s: %s", plugins_dir, err)
|
||||
log.error("pack: failed to watch %s: %s", plugins_dir, err)
|
||||
w:close()
|
||||
handle:close()
|
||||
return
|
||||
@@ -256,10 +241,10 @@ function M.unwatch()
|
||||
end
|
||||
|
||||
---@param specs vim.pack.Spec[]
|
||||
---@param on_load fun(data: { spec: vim.pack.Spec, path: string })
|
||||
---@return table<string, true> changed names installed or updated during this call
|
||||
---@param on_load boolean|fun(plug_data: {spec: vim.pack.Spec, path: string})
|
||||
---@return table<string, ow.Pack.Event.Data>
|
||||
function M.install(specs, on_load)
|
||||
---@type table<string, true>
|
||||
---@type table<string, ow.Pack.Event.Data>
|
||||
local changed = {}
|
||||
local group =
|
||||
vim.api.nvim_create_augroup("ow.Pack.install", { clear = true })
|
||||
@@ -267,12 +252,9 @@ function M.install(specs, on_load)
|
||||
group = group,
|
||||
---@param ev ow.Pack.Event
|
||||
callback = function(ev)
|
||||
local name = ev.data.spec.name
|
||||
if
|
||||
name
|
||||
and (ev.data.kind == "install" or ev.data.kind == "update")
|
||||
then
|
||||
changed[name] = true
|
||||
local src = ev.data.spec.src
|
||||
if ev.data.kind == "install" or ev.data.kind == "update" then
|
||||
changed[src] = ev.data
|
||||
end
|
||||
end,
|
||||
})
|
||||
@@ -281,11 +263,11 @@ function M.install(specs, on_load)
|
||||
return changed
|
||||
end
|
||||
|
||||
---@param specs (string | ow.Pack.PluginSpec)[]
|
||||
---@param specs (string | ow.Pack.Spec)[]
|
||||
function M.setup(specs)
|
||||
local pack_specs = {}
|
||||
for _, spec in ipairs(specs) do
|
||||
local src = type(spec) == "string" and spec or spec[1]
|
||||
local src = type(spec) == "string" and spec or spec.src
|
||||
if is_url(src) then
|
||||
table.insert(pack_specs, to_pack_spec(spec))
|
||||
else
|
||||
@@ -294,11 +276,11 @@ function M.setup(specs)
|
||||
vim.api.nvim_get_runtime_file("pack/*/opt/" .. src, false)
|
||||
---@type ow.Pack.Plugin
|
||||
local plugin = {
|
||||
[1] = src,
|
||||
src = src,
|
||||
name = src,
|
||||
path = runtime[1] or "",
|
||||
}
|
||||
table.insert(M.plugins, plugin)
|
||||
M.plugins[plugin.src] = plugin
|
||||
end
|
||||
end
|
||||
|
||||
@@ -310,30 +292,47 @@ function M.setup(specs)
|
||||
local d = data.spec.data or {}
|
||||
---@type ow.Pack.Plugin
|
||||
local plugin = {
|
||||
[1] = data.spec.src,
|
||||
src = data.spec.src,
|
||||
name = data.spec.name,
|
||||
version = data.spec.version,
|
||||
build = d.build,
|
||||
path = data.path,
|
||||
}
|
||||
table.insert(M.plugins, plugin)
|
||||
M.plugins[plugin.src] = plugin
|
||||
vim.cmd.packadd(plugin.name)
|
||||
end)
|
||||
|
||||
for _, plugin in ipairs(M.plugins) do
|
||||
for _, plugin in pairs(M.plugins) do
|
||||
if plugin.build then
|
||||
if changed[plugin.name] then
|
||||
local data = changed[plugin.src]
|
||||
if data then
|
||||
plugin.path = data.path
|
||||
run_build(plugin)
|
||||
end
|
||||
M.register_hook(plugin.name, function(ev)
|
||||
plugin.path = ev.path
|
||||
run_build(plugin)
|
||||
end)
|
||||
end
|
||||
load(plugin.name, false)
|
||||
end
|
||||
|
||||
setup_event_listener()
|
||||
vim.api.nvim_create_autocmd("PackChanged", {
|
||||
group = vim.api.nvim_create_augroup(
|
||||
"ow.Pack.updates",
|
||||
{ clear = true }
|
||||
),
|
||||
callback = function(ev)
|
||||
if ev.data.kind ~= "update" then
|
||||
return
|
||||
end
|
||||
local plugin = M.plugins[ev.data.spec.src]
|
||||
if not plugin then
|
||||
return
|
||||
end
|
||||
plugin.path = ev.data.path
|
||||
if plugin.build then
|
||||
run_build(plugin)
|
||||
end
|
||||
M.reload_plugin(plugin.name, false)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
---@param names? string[]
|
||||
|
||||
Reference in New Issue
Block a user