From 989b385b5dd12acd6bc3fc67ef3a951da98420be Mon Sep 17 00:00:00 2001 From: Squibid Date: Thu, 3 Jul 2025 16:13:01 -0400 Subject: [PATCH] Allow users to lazy load on another package --- doc/dep.txt | 66 +++++++++++++++++++++++++++++++++++ lua/dep/lazy/loader/init.lua | 29 ++++++++++++++- lua/dep/lazy/loader/short.lua | 10 ++++++ lua/dep/package.lua | 12 ++----- 4 files changed, 106 insertions(+), 11 deletions(-) diff --git a/doc/dep.txt b/doc/dep.txt index c6f2cd8..0fe154c 100644 --- a/doc/dep.txt +++ b/doc/dep.txt @@ -11,6 +11,7 @@ Table of Contents *dep-table-of-contents* 4. Lazy Loading |dep-lazy-loading| - Lazy Loading API |dep-lazy-loading-api| - Lazy Loading API Shorthands |dep-lazy-loading-api-shorthands| + - Lazy Loading |dep-examples-lazy-loading| 5. Commands |dep-commands| 6. Examples |dep-examples| - Declaring Dependencies |dep-examples-declaring-dependencies| @@ -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* diff --git a/lua/dep/lazy/loader/init.lua b/lua/dep/lazy/loader/init.lua index 1ae3c18..9513f31 100644 --- a/lua/dep/lazy/loader/init.lua +++ b/lua/dep/lazy/loader/init.lua @@ -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 diff --git a/lua/dep/lazy/loader/short.lua b/lua/dep/lazy/loader/short.lua index d6badde..e7c74f2 100644 --- a/lua/dep/lazy/loader/short.lua +++ b/lua/dep/lazy/loader/short.lua @@ -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 diff --git a/lua/dep/package.lua b/lua/dep/package.lua index a8c46e8..183bef2 100644 --- a/lua/dep/package.lua +++ b/lua/dep/package.lua @@ -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