feat(pack): support user-defined data in plugin spec #35360

Problem:
The load function in opts was difficult to use if you wished to
customize based on the plugin being loaded.

You could get the name, but without some way to mark a spec, that was of
limited usefulness unless you wanted to hardcode a list of names in the
function, or write a wrapper around the whole thing

Solution:
Allow users to provide an arbitrary data field in plugin specs so that
they may receive info as to how to handle that plugin in load, get() and
events, and act upon it

Co-authored-by: BirdeeHub <birdee@localhost>
Co-authored-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com>
This commit is contained in:
Birdee
2025-08-21 10:08:29 -07:00
committed by GitHub
parent 9467731865
commit c522cb0e96
3 changed files with 50 additions and 2 deletions

View File

@@ -309,6 +309,7 @@ Each event populates the following |event-data| fields:
• String to use specific branch, tag, or commit hash.
• Output of |vim.version.range()| to install the
greatest/last semver tag inside the version constraint.
• {data}? (`any`) Arbitrary data associated with a plugin.
add({specs}, {opts}) *vim.pack.add()*

View File

@@ -234,8 +234,10 @@ end
--- - Output of |vim.version.range()| to install the greatest/last semver tag
--- inside the version constraint.
--- @field version? string|vim.VersionRange
---
--- @field data? any Arbitrary data associated with a plugin.
--- @alias vim.pack.SpecResolved { src: string, name: string, version: nil|string|vim.VersionRange }
--- @alias vim.pack.SpecResolved { src: string, name: string, version: nil|string|vim.VersionRange, data: any|nil }
--- @param spec string|vim.pack.Spec
--- @return vim.pack.SpecResolved
@@ -247,7 +249,7 @@ local function normalize_spec(spec)
name = (type(name) == 'string' and name or ''):match('[^/]+$') or ''
vim.validate('spec.name', name, is_nonempty_string, true, 'non-empty string')
vim.validate('spec.version', spec.version, is_version, true, 'string or vim.VersionRange')
return { src = spec.src, name = name, version = spec.version }
return { src = spec.src, name = name, version = spec.version, data = spec.data }
end
--- @class (private) vim.pack.PlugInfo

View File

@@ -311,6 +311,34 @@ describe('vim.pack', function()
eq(exec_lua('return #_G.event_log'), 0)
end)
it('passes data field through to opts.load', function()
eq(
2,
exec_lua(function()
local successes = 0
vim.pack.add({
{ name = 'tabletest', src = repos_src.basic, data = { test = 'value' } },
{ name = 'stringtest', src = repos_src.basic, data = 'value' },
}, {
confirm = false,
load = function(p)
if p.spec.name == 'tabletest' then
if p.spec.data.test == 'value' then
successes = successes + 1
end
end
if p.spec.name == 'stringtest' then
if p.spec.data == 'value' then
successes = successes + 1
end
end
end,
})
return successes
end)
)
end)
it('asks for installation confirmation', function()
exec_lua(function()
---@diagnostic disable-next-line: duplicate-set-field
@@ -1179,6 +1207,23 @@ describe('vim.pack', function()
}, exec_lua('return vim.pack.get()'))
end)
it('respects data field', function()
eq(
true,
exec_lua(function()
vim.pack.add {
{ src = repos_src.basic, data = { test = 'value' } },
}
for _, p in ipairs(vim.pack.get()) do
if p.spec.name == 'basic' and p.spec.data.test == 'value' then
return true
end
end
return false
end)
)
end)
it('works with `del()`', function()
exec_lua(function()
vim.pack.add({ repos_src.defbranch, repos_src.basic })