aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/pack.lua
diff options
context:
space:
mode:
authorEvgeni Chasnovski <evgeni.chasnovski@gmail.com>2026-07-31 11:28:11 +0300
committerEvgeni Chasnovski <evgeni.chasnovski@gmail.com>2026-07-31 18:04:58 +0300
commit4cdd6d76c5ad2714aa5c056c8b16fca408120e61 (patch)
tree6462dc4cbdd0325abab655a54431a939382b8ae4 /runtime/lua/vim/pack.lua
parent02a25caa1b5211e349c41ac2e0642de905ae7be9 (diff)
downloadrneovim-4cdd6d76c5ad2714aa5c056c8b16fca408120e61.tar.gz
rneovim-4cdd6d76c5ad2714aa5c056c8b16fca408120e61.tar.bz2
rneovim-4cdd6d76c5ad2714aa5c056c8b16fca408120e61.zip
feat(pack): introduce plugin manifest support
Problem: There is no agreed way for plugins to provide extra information about themselves. Like required Neovim version, install/update/delete hooks, and dependencies. Solution: Introduce basic concept of plugin manifest file `pkg.json` based on https://packspec.org/.
Diffstat (limited to 'runtime/lua/vim/pack.lua')
-rw-r--r--runtime/lua/vim/pack.lua53
1 files changed, 53 insertions, 0 deletions
diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua
index 2b456a6dbb..a69684de75 100644
--- a/runtime/lua/vim/pack.lua
+++ b/runtime/lua/vim/pack.lua
@@ -232,6 +232,25 @@
----- To act on install from lockfile, run before very first `vim.pack.add()`
---vim.api.nvim_create_autocmd('PackChanged', { callback = hooks })
---```
+---[vim.pack-manifest]()
+---
+---Plugins can come with a special top level `pkg.json` manifest file with extra
+---information. If present, `vim.pack` uses it for improved user experience:
+---- Running |:checkhealth| for `vim.pack` will perform extra checks to ensure
+--- healthy plugin installation.
+---
+---Full specification see at https://packspec.org/. See also |vim.pack.Manifest|.
+---A simple example:
+---```json
+---{
+--- "name": "best-plugin.nvim",
+--- "description": "The best plugin for Neovim",
+--- "engines": {
+--- "nvim": ">=0.13.0",
+--- "vim": ">=9.1.0"
+--- }
+---}
+---```
local api = vim.api
local uv = vim.uv
@@ -516,6 +535,37 @@ end
local active_plugins = {}
local n_active_plugins = 0
+--- @class vim.pack.ManifestEngines
+--- @inlinedoc
+--- @field nvim? string Version range for Nvim.
+--- @field vim? string Version range for Vim.
+
+--- @class vim.pack.Manifest
+--- @field name? string Plugin name
+--- @field description? string Plugin description
+--- Supported engine versions. Values should be |vim.version.range()| compatible specs.
+--- @field engines? vim.pack.ManifestEngines
+
+--- @param path string
+--- @return vim.pack.Manifest?
+local function manifest_read(path)
+ local manifest_path = vim.fs.joinpath(path, 'pkg.json')
+ local stat = uv.fs_stat(manifest_path)
+ if not stat then
+ return nil
+ end
+
+ local fd = uv.fs_open(manifest_path, 'r', 438)
+ if not fd then
+ return {}
+ end
+
+ local data = assert(uv.fs_read(fd, stat.size, 0))
+ assert(uv.fs_close(fd))
+ local ok, res = pcall(vim.json.decode, data)
+ return (ok and type(res) == 'table') and res or {}
+end
+
--- @param plugs vim.pack.Plug[]
--- @param event_name 'PackChangedPre'|'PackChanged'
--- @param kind 'install'|'update'|'delete'
@@ -1468,6 +1518,8 @@ end
--- @class vim.pack.PlugData
--- @field active boolean Whether plugin was added via |vim.pack.add()| to current session.
--- @field branches? string[] Available Git branches (first is default). Missing if `info=false`.
+--- Data from the |vim.pack-manifest|. Empty in case of reading error. Missing if `info=false`.
+--- @field manifest? vim.pack.Manifest
--- @field path string Plugin's path on disk.
--- @field rev string Current Git revision. Taken from |vim.pack-lockfile| if `info=false`.
--- Git revision of a pending update. The same as used during |vim.pack.update()| and which
@@ -1494,6 +1546,7 @@ local function add_p_data_info(p_data_list, offline)
funs[i] = function()
p_data.branches = git_get_branches(path)
p_data.tags = git_get_tags(path)
+ p_data.manifest = manifest_read(path)
if not offline then
git_fetch(path)