feat(pack): add support for sourcing manifest scripts

Problem: No way for plugins to define hooks that would be executed
  during plugin lifecycle. Like after install/update or before
  update/delete.

Solution: Automatically source scripts defined in plugin manifest file
  (if any) after triggering corresponding `PackChanged{,Pre}` events.
  During sourcing make some termporary adjustments:
  - Current directory is set to plugin's root to simplify execution of
    CLI calls like `make build`.
  - Plugin's path is ensured to be inside 'runtimepath' to allow using
    `require('plugin-module')` inside manifest scripts.

  The reason to execute after triggering event is so that there is a
  possibility for users to execute code both before the script (exactly
  on event) and after the script (more-or-less via `vim.schedule` called
  on the event).
This commit is contained in:
Evgeni Chasnovski
2026-07-31 15:17:00 +03:00
parent 4cdd6d76c5
commit 9d12df0398
4 changed files with 242 additions and 2 deletions

View File

@@ -200,7 +200,8 @@ local function check_lockfile()
end
end
local function check_manifest(manifest, plug_name)
--- @param manifest vim.pack.Manifest
local function check_manifest(manifest, plug_name, plug_path)
local name_str = vim.inspect(plug_name)
if vim.tbl_count(manifest) == 0 then
health.warn(('Plugin %s has empty or malformed manifest file'):format(name_str))
@@ -222,6 +223,18 @@ local function check_manifest(manifest, plug_name)
return false
end
local ok_scripts = true
---@diagnostic disable-next-line: no-unknown
for name, script_path in pairs(manifest.scripts or {}) do
if vim.fn.filereadable(vim.fs.joinpath(plug_path, script_path)) == 0 then
health.warn(('Plugin %s has no %s script at %s path'):format(name_str, name, script_path))
ok_scripts = false
end
end
if not ok_scripts then
return false
end
return true
end
@@ -275,7 +288,7 @@ local function check_installed_plugin(plug_name)
-- Manifest
if info[1].manifest then
return check_manifest(info[1].manifest, plug_name)
return check_manifest(info[1].manifest, plug_name, plug_path)
end
return true