mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 04:18:18 +00:00
feat(pack): allow function opts.load
in add()
Problem: No way to have full control over how plugin is loaded. Although `:packadd!` has small side effects (only adds plugin directory to 'runtimepath'; and maybe its 'after/' subdirectory), it still has side effects. For example, 'plugin/' directories are still loaded during startup (as part of `:h load-plugins`). Solution: Allow function `opts.load` that has full control over how plugin is loaded.
This commit is contained in:
@@ -315,11 +315,12 @@ add({specs}, {opts}) *vim.pack.add()*
|
|||||||
Add plugin to current session
|
Add plugin to current session
|
||||||
• For each specification check that plugin exists on disk in
|
• For each specification check that plugin exists on disk in
|
||||||
|vim.pack-directory|:
|
|vim.pack-directory|:
|
||||||
• If exists, do nothin in this step.
|
• If exists, do nothing in this step.
|
||||||
• If doesn't exist, install it by downloading from `src` into `name`
|
• If doesn't exist, install it by downloading from `src` into `name`
|
||||||
subdirectory (via `git clone`) and update state to match `version`
|
subdirectory (via `git clone`) and update state to match `version`
|
||||||
(via `git checkout`).
|
(via `git checkout`).
|
||||||
• For each plugin execute |:packadd| making them reachable by Nvim.
|
• For each plugin execute |:packadd| (or customizable `load` function)
|
||||||
|
making it reachable by Nvim.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
• Installation is done in parallel, but waits for all to finish before
|
• Installation is done in parallel, but waits for all to finish before
|
||||||
@@ -334,8 +335,11 @@ add({specs}, {opts}) *vim.pack.add()*
|
|||||||
• {specs} (`(string|vim.pack.Spec)[]`) List of plugin specifications.
|
• {specs} (`(string|vim.pack.Spec)[]`) List of plugin specifications.
|
||||||
String item is treated as `src`.
|
String item is treated as `src`.
|
||||||
• {opts} (`table?`) A table with the following fields:
|
• {opts} (`table?`) A table with the following fields:
|
||||||
• {load}? (`boolean`) Load `plugin/` files and `ftdetect/`
|
• {load}?
|
||||||
scripts. If `false`, works like `:packadd!`. Default
|
(`boolean|fun(plug_data: {spec: vim.pack.Spec, path: string})`)
|
||||||
|
Load `plugin/` files and `ftdetect/` scripts. If `false`,
|
||||||
|
works like `:packadd!`. If function, called with plugin
|
||||||
|
data and is fully responsible for loading plugin. Default
|
||||||
`false` during startup and `true` afterwards.
|
`false` during startup and `true` afterwards.
|
||||||
|
|
||||||
del({names}) *vim.pack.del()*
|
del({names}) *vim.pack.del()*
|
||||||
|
@@ -352,7 +352,13 @@ end
|
|||||||
--- @param event_name 'PackChangedPre'|'PackChanged'
|
--- @param event_name 'PackChangedPre'|'PackChanged'
|
||||||
--- @param kind 'install'|'update'|'delete'
|
--- @param kind 'install'|'update'|'delete'
|
||||||
local function trigger_event(p, event_name, kind)
|
local function trigger_event(p, event_name, kind)
|
||||||
local data = { kind = kind, spec = vim.deepcopy(p.spec), path = p.path }
|
local spec = vim.deepcopy(p.spec)
|
||||||
|
-- Infer default branch for fuller `event-data` (if possible)
|
||||||
|
-- Doing it only on event trigger level allows keeping `spec` close to what
|
||||||
|
-- user supplied without performance issues during startup.
|
||||||
|
spec.version = spec.version or (uv.fs_stat(p.path) and git_get_default_branch(p.path))
|
||||||
|
|
||||||
|
local data = { kind = kind, spec = spec, path = p.path }
|
||||||
vim.api.nvim_exec_autocmds(event_name, { pattern = p.path, data = data })
|
vim.api.nvim_exec_autocmds(event_name, { pattern = p.path, data = data })
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -574,9 +580,6 @@ local function install_list(plug_list)
|
|||||||
git_clone(p.spec.src, p.path)
|
git_clone(p.spec.src, p.path)
|
||||||
p.info.installed = true
|
p.info.installed = true
|
||||||
|
|
||||||
-- Infer default branch for fuller `event-data`
|
|
||||||
p.spec.version = p.spec.version or git_get_default_branch(p.path)
|
|
||||||
|
|
||||||
-- Do not skip checkout even if HEAD and target have same commit hash to
|
-- Do not skip checkout even if HEAD and target have same commit hash to
|
||||||
-- have new repo in expected detached HEAD state and generated help files.
|
-- have new repo in expected detached HEAD state and generated help files.
|
||||||
checkout(p, timestamp, false)
|
checkout(p, timestamp, false)
|
||||||
@@ -640,7 +643,7 @@ local active_plugins = {}
|
|||||||
local n_active_plugins = 0
|
local n_active_plugins = 0
|
||||||
|
|
||||||
--- @param plug vim.pack.Plug
|
--- @param plug vim.pack.Plug
|
||||||
--- @param load boolean
|
--- @param load boolean|fun(plug_data: {spec: vim.pack.Spec, path: string})
|
||||||
local function pack_add(plug, load)
|
local function pack_add(plug, load)
|
||||||
-- Add plugin only once, i.e. no overriding of spec. This allows users to put
|
-- Add plugin only once, i.e. no overriding of spec. This allows users to put
|
||||||
-- plugin first to fully control its spec.
|
-- plugin first to fully control its spec.
|
||||||
@@ -651,6 +654,11 @@ local function pack_add(plug, load)
|
|||||||
n_active_plugins = n_active_plugins + 1
|
n_active_plugins = n_active_plugins + 1
|
||||||
active_plugins[plug.path] = { plug = plug, id = n_active_plugins }
|
active_plugins[plug.path] = { plug = plug, id = n_active_plugins }
|
||||||
|
|
||||||
|
if vim.is_callable(load) then
|
||||||
|
load({ spec = vim.deepcopy(plug.spec), path = plug.path })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- NOTE: The `:packadd` specifically seems to not handle spaces in dir name
|
-- NOTE: The `:packadd` specifically seems to not handle spaces in dir name
|
||||||
vim.cmd.packadd({ vim.fn.escape(plug.spec.name, ' '), bang = not load, magic = { file = false } })
|
vim.cmd.packadd({ vim.fn.escape(plug.spec.name, ' '), bang = not load, magic = { file = false } })
|
||||||
|
|
||||||
@@ -670,16 +678,18 @@ end
|
|||||||
--- @class vim.pack.keyset.add
|
--- @class vim.pack.keyset.add
|
||||||
--- @inlinedoc
|
--- @inlinedoc
|
||||||
--- Load `plugin/` files and `ftdetect/` scripts. If `false`, works like `:packadd!`.
|
--- Load `plugin/` files and `ftdetect/` scripts. If `false`, works like `:packadd!`.
|
||||||
|
--- If function, called with plugin data and is fully responsible for loading plugin.
|
||||||
--- Default `false` during startup and `true` afterwards.
|
--- Default `false` during startup and `true` afterwards.
|
||||||
--- @field load? boolean
|
--- @field load? boolean|fun(plug_data: {spec: vim.pack.Spec, path: string})
|
||||||
|
|
||||||
--- Add plugin to current session
|
--- Add plugin to current session
|
||||||
---
|
---
|
||||||
--- - For each specification check that plugin exists on disk in |vim.pack-directory|:
|
--- - For each specification check that plugin exists on disk in |vim.pack-directory|:
|
||||||
--- - If exists, do nothin in this step.
|
--- - If exists, do nothing in this step.
|
||||||
--- - If doesn't exist, install it by downloading from `src` into `name`
|
--- - If doesn't exist, install it by downloading from `src` into `name`
|
||||||
--- subdirectory (via `git clone`) and update state to match `version` (via `git checkout`).
|
--- subdirectory (via `git clone`) and update state to match `version` (via `git checkout`).
|
||||||
--- - For each plugin execute |:packadd| making them reachable by Nvim.
|
--- - For each plugin execute |:packadd| (or customizable `load` function) making
|
||||||
|
--- it reachable by Nvim.
|
||||||
---
|
---
|
||||||
--- Notes:
|
--- Notes:
|
||||||
--- - Installation is done in parallel, but waits for all to finish before
|
--- - Installation is done in parallel, but waits for all to finish before
|
||||||
|
@@ -484,6 +484,52 @@ describe('vim.pack', function()
|
|||||||
validate(false, {})
|
validate(false, {})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can use function `opts.load`', function()
|
||||||
|
local validate = function()
|
||||||
|
n.exec_lua(function()
|
||||||
|
_G.load_log = {}
|
||||||
|
local load = function(...)
|
||||||
|
table.insert(_G.load_log, { ... })
|
||||||
|
end
|
||||||
|
vim.pack.add({ repos_src.plugindirs, repos_src.basic }, { load = load })
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Order of execution should be the same as supplied in `add()`
|
||||||
|
local plugindirs_data = {
|
||||||
|
spec = { src = repos_src.plugindirs, name = 'plugindirs' },
|
||||||
|
path = pack_get_plug_path('plugindirs'),
|
||||||
|
}
|
||||||
|
local basic_data = {
|
||||||
|
spec = { src = repos_src.basic, name = 'basic' },
|
||||||
|
path = pack_get_plug_path('basic'),
|
||||||
|
}
|
||||||
|
-- - Only single table argument should be supplied to `load`
|
||||||
|
local ref_log = { { plugindirs_data }, { basic_data } }
|
||||||
|
eq(ref_log, n.exec_lua('return _G.load_log'))
|
||||||
|
|
||||||
|
-- Should not add plugin to the session in any way
|
||||||
|
eq(false, exec_lua('return pcall(require, "plugindirs")'))
|
||||||
|
eq(false, exec_lua('return pcall(require, "basic")'))
|
||||||
|
|
||||||
|
-- Should not source 'plugin/'
|
||||||
|
eq({}, n.exec_lua('return { vim.g._plugin, vim.g._after_plugin }'))
|
||||||
|
|
||||||
|
-- Plugins should still be marked as "active", since they were added
|
||||||
|
plugindirs_data.spec.version = 'main'
|
||||||
|
plugindirs_data.active = true
|
||||||
|
basic_data.spec.version = 'main'
|
||||||
|
basic_data.active = true
|
||||||
|
eq({ plugindirs_data, basic_data }, n.exec_lua('return vim.pack.get()'))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Works on initial install
|
||||||
|
validate()
|
||||||
|
|
||||||
|
-- Works when loading already installed plugin
|
||||||
|
n.clear()
|
||||||
|
validate()
|
||||||
|
end)
|
||||||
|
|
||||||
it('generates help tags', function()
|
it('generates help tags', function()
|
||||||
exec_lua(function()
|
exec_lua(function()
|
||||||
vim.pack.add({ { src = repos_src.helptags, name = 'help tags' } })
|
vim.pack.add({ { src = repos_src.helptags, name = 'help tags' } })
|
||||||
|
Reference in New Issue
Block a user