Allow users to lazy load on another package

This commit is contained in:
2025-07-03 16:13:01 -04:00
parent 542298c1fe
commit 8e46eddecd
4 changed files with 106 additions and 11 deletions

View File

@ -15,6 +15,7 @@ Table of Contents *dep-table-of-contents*
6. Examples |dep-examples|
- Declaring Dependencies |dep-examples-declaring-dependencies|
- Modules |dep-examples-modules|
- Lazy Loading |dep-examples-lazy-loading|
7. Credits & License |dep-credits|
==============================================================================
@ -293,6 +294,27 @@ into the options table to re-run the binding after loading the package. You
may choose to include your own logic by passing a function to the `rerun`
field or disable the built-in logic by passing false.
------------------------------------------------------------------------------
LOAD:PLUGIN *dep-lazy-loading-api-plugin*
`load:plugin` is a function which allows you to specify another plugin for the
package to load after. It takes two arguments: `plugin` which is the name of
the plugin you want to follow like: 'user/package'. The second argument is
`opts` which is a table with one option: `callback` which is a function. The
following is an example:
>lua
load:plugin("user/package", {})
<
Which is the same as:
>lua
load:plugin("user/package", {
callback = function()
self:cleanup()
end
})
<
When 'user/package' is already loaded the `callback` is called immediately.
LAZY LOADING API SHORTHANDS *dep-lazy-loading-api-shorthands*
On occasion you may wish to only define one condition for the package to load.
@ -589,6 +611,50 @@ declared in that module.
}
}
<
LAZY LOADING *dep-examples-lazy-loading*
Lazy loading is a very complicated topic, and therefore this part of the
documentation assumes you have experience with regular package managment.
Let's go over loading order, and how the lazy loader determines what needs to
be loaded.
Let's say we have the following spec:
>lua
{ "user/package",
lazy = true,
deps = "user/dependent"
}
<
This is the same as the following:
>lua
{ "user/package",
lazy = true
},
{ "user/dependent",
reqs = "user/package",
lazy = require("dep.lazy.loader.short").plugin("user/package")
}
<
What you're seeing is implicit lazy loading. By default dep will lazy load
dependents who are explicitly defined in the spec. Now if we we're to modify
'user/dependent' like so:
>lua
{ "user/package",
lazy = true
},
{ "user/dependent",
reqs = "user/package",
lazy = function(load)
load:plugin("user/package")
load:cmd("LoadDependent")
end
}
<
If we were to call the command `:LoadDependent` it would first load
'user/package', and then load 'user/dependent'.
==============================================================================
7. Credits & License *dep-credits*

View File

@ -1,10 +1,12 @@
local logger = require('dep.log')
local packager = require('dep.package')
---@class lazy_loader
---@field load function the function to load the plugin
---@field command_ids table the commands that have been registered
---@field auto_ids table the auto commands that have been registered
---@field keybind_ids table the keybinds that have been registered
---@field plugin_ids table the plugins that have been registered
local lazy_loader = {}
--- create a new instance of lazy
@ -16,6 +18,7 @@ function lazy_loader:new()
o.command_ids = {}
o.auto_ids = {}
o.keybind_ids = {}
o.plugin_ids = {}
self.__index = self
@ -107,9 +110,29 @@ function lazy_loader:keymap(mode, bind, opts)
table.insert(self.keybind_ids, { ['mode'] = mode, ['bind'] = bind })
end
--- load a plugin when another plugin loads
---@param plugin string plugin name
---@param opts table? options
function lazy_loader:plugin(plugin, opts)
opts = opts or {}
opts["callback"] = opts["callback"] or function()
self:cleanup()
end
if packager.get_packages()[plugin].loaded then
opts["callback"]()
else
local on_load = packager.get_packages()[plugin].on_load
local on_load_idx = #on_load + 1
on_load[on_load_idx] = opts["callback"]
table.insert(self.plugin_ids, { plugin, on_load_idx })
end
end
--- cleanup all the callbacks, and load the plugin
function lazy_loader:cleanup()
-- cleanup user commands
-- cleanup user commands
for _, command_id in pairs(self.command_ids) do
local ok, err = pcall(vim.api.nvim_del_user_command, command_id)
if not ok then
@ -130,6 +153,10 @@ function lazy_loader:cleanup()
logger:log("lazy", err or "failed to delete keymap")
end
end
-- cleanup plugins
for _, plugin_id in pairs(self.plugin_ids) do
table.remove(packager.get_packages()[plugin_id[0]], plugin_id[1])
end
-- load the plugin
self:load()
end

View File

@ -59,4 +59,14 @@ function short.keymap(mode, bind, opts)
end
end
--- create a single plugin load event for when another plugin loads
---@param plugin string plugin name
---@param opts table? options
---@return function callback
function short.plugin(plugin, opts)
return function(load)
load:plugin(plugin, opts)
end
end
return short

View File

@ -165,18 +165,10 @@ function package:new(spec, overrides)
-- if the child package is lazy loaded make sure the child package
-- is only loaded when the parent package has finished loading
if o.lazy then
table.insert(o.on_load, function()
local ok = o:loadtree(true)
if not ok then
logger:log("lazy",
"failed to run loadtree for %s, some packages may not be loaded",
o.id)
end
end)
-- tell the dep that it's gonna be lazy
pkg.lazy = true
table.insert(pkg.lazy_load, function(_) end)
table.insert(pkg.lazy_load,
require("dep.lazy.loader.short").plugin(id))
end
end
end