mirror of
https://github.com/zoriya/lz.n.git
synced 2026-06-09 05:05:13 +00:00
feat!: simplify state management + idempotent trigger_load (#56)
* feat!: simplify state management + idempotent `trigger_load(name)` * feat!: `lz.n.Handler.del` now takes a plugin name (`string`)
This commit is contained in:
@@ -315,7 +315,9 @@ Or
|
|||||||
├── init.lua
|
├── init.lua
|
||||||
```
|
```
|
||||||
|
|
||||||
### Custom Handlers
|
## :electric_plug: API
|
||||||
|
|
||||||
|
### Custom handlers
|
||||||
|
|
||||||
You may register your own handlers to lazy-load plugins via
|
You may register your own handlers to lazy-load plugins via
|
||||||
other triggers not already covered by the plugin spec.
|
other triggers not already covered by the plugin spec.
|
||||||
@@ -335,25 +337,67 @@ require("lz.n").register_handler(handler)
|
|||||||
#### `lz.n.Handler`
|
#### `lz.n.Handler`
|
||||||
|
|
||||||
<!-- markdownlint-disable MD013 -->
|
<!-- markdownlint-disable MD013 -->
|
||||||
| Property | Type | Description |
|
| Property | Type | Description |
|
||||||
|----------|------|-------------|
|
| --- | --- | --- |
|
||||||
| spec_field | `string` | the `lz.n.PluginSpec` field defined by the handler |
|
| spec_field | `string` | the `lz.n.PluginSpec` field used to configure the handler |
|
||||||
| add | `fun(plugin: lz.n.Plugin)` | adds a plugin to the handler |
|
| add | `fun(plugin: lz.n.Plugin)` | adds a plugin to the handler |
|
||||||
| del | `fun(plugin: lz.n.Plugin)?` | removes a plugin from the handler |
|
| del | `fun(name: string)` | removes a plugin from the handler by name |
|
||||||
|
| lookup | `fun(name: string):lz.n.Plugin?` | lookup a plugin managed by this handler by name |
|
||||||
<!-- markdownlint-enable MD013 -->
|
<!-- markdownlint-enable MD013 -->
|
||||||
|
|
||||||
When writing custom handlers,
|
### Lua API
|
||||||
you can load the plugin and run the hooks from
|
|
||||||
the spec with the following function:
|
The following Lua functions are part of the public API.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> If you use internal functions or modules that are not listed here,
|
||||||
|
> things may break without a major version bump.
|
||||||
|
|
||||||
|
#### `trigger_load`
|
||||||
|
|
||||||
|
You can manually load a plugin (and run the hooks from the spec)
|
||||||
|
with the following function:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
---@type fun(plugins: string | lz.n.Plugin | string[] | lz.n.Plugin[])
|
---@type fun(plugins: string | string[] | lz.n.Plugin | lz.n.Plugin[])
|
||||||
require('lz.n').trigger_load
|
require('lz.n').trigger_load
|
||||||
```
|
```
|
||||||
|
|
||||||
The function accepts plugin names or parsed plugin specs.
|
The function accepts plugin names (`string | string[]`, when called in another
|
||||||
It will call the handler's `del` function (if it exists) after the `before` hooks,
|
plugin's hook), or `lz.n.Plugin` items (when called by a `lz.n.Handler`).
|
||||||
and before `load` of the plugin's spec.
|
If called with a plugin name, it will use the registered
|
||||||
|
handlers' `lookup` functions to search for a plugin to load
|
||||||
|
(loading the first one it finds).
|
||||||
|
Once a plugin has been loaded, it will be removed from all handlers (via `del`).
|
||||||
|
As a result, calling `trigger_load` with a plugin name is idempotent.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
>
|
||||||
|
> This can be used to influence the order in which plugins are lazy-loaded,
|
||||||
|
> for example when a plugin depends on another one.
|
||||||
|
>
|
||||||
|
> However, we strongly recommend you consider alternatives before doing so.
|
||||||
|
> lz.n was designed with automatic dependency management in mind and hence
|
||||||
|
> **does not provide an API** to declare dependencies in the `lz.n.PluginSpec`.
|
||||||
|
> Plugin dependencies are usually just Lua libraries, which can be added to the
|
||||||
|
> `package.path` without any noticeable impact on startup time.
|
||||||
|
>
|
||||||
|
> If a plugin relies on another plugin's `plugin/` or `after/plugin/` scripts
|
||||||
|
> having been sourced before it is loaded, we consider this a bug, as this is not
|
||||||
|
> supported by Neovim's built-in loading mechanisms.
|
||||||
|
>
|
||||||
|
> Similarly, requiring users to worry about *the order in which they configure*
|
||||||
|
> plugins is bad design and defeats the purpose of automatic dependency management.
|
||||||
|
|
||||||
|
#### `lookup`
|
||||||
|
|
||||||
|
To lookup a plugin that is pending to be loaded by name, use:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
---@type fun(name: string):lz.n.Plugin?
|
||||||
|
require('lz.n').lookup
|
||||||
|
```
|
||||||
|
|
||||||
### Extensions
|
### Extensions
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,17 @@ local loader = require("lz.n.loader")
|
|||||||
|
|
||||||
---@type lz.n.CmdHandler
|
---@type lz.n.CmdHandler
|
||||||
local M = {
|
local M = {
|
||||||
|
---@type table<string, table<string, lz.n.Plugin[]>>
|
||||||
pending = {},
|
pending = {},
|
||||||
spec_field = "cmd",
|
spec_field = "cmd",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return lz.n.Plugin?
|
||||||
|
function M.lookup(name)
|
||||||
|
return require("lz.n.handler.extra").lookup(M.pending, name)
|
||||||
|
end
|
||||||
|
|
||||||
---@param cmd string
|
---@param cmd string
|
||||||
local function load(cmd)
|
local function load(cmd)
|
||||||
vim.api.nvim_del_user_command(cmd)
|
vim.api.nvim_del_user_command(cmd)
|
||||||
@@ -66,12 +73,16 @@ local function add_cmd(cmd)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param plugin lz.n.Plugin
|
---@param name string
|
||||||
function M.del(plugin)
|
function M.del(name)
|
||||||
pcall(vim.api.nvim_del_user_command, plugin.cmd)
|
vim.iter(M.pending)
|
||||||
vim.iter(M.pending):each(function(_, plugins)
|
:filter(function(_, plugins)
|
||||||
plugins[plugin.name] = nil
|
return plugins[name] ~= nil
|
||||||
end)
|
end)
|
||||||
|
:each(function(cmd, plugins)
|
||||||
|
pcall(vim.api.nvim_del_user_command, cmd)
|
||||||
|
plugins[name] = nil
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param plugin lz.n.Plugin
|
---@param plugin lz.n.Plugin
|
||||||
@@ -82,7 +93,7 @@ function M.add(plugin)
|
|||||||
---@param cmd string
|
---@param cmd string
|
||||||
vim.iter(plugin.cmd):each(function(cmd)
|
vim.iter(plugin.cmd):each(function(cmd)
|
||||||
M.pending[cmd] = M.pending[cmd] or {}
|
M.pending[cmd] = M.pending[cmd] or {}
|
||||||
M.pending[cmd][plugin.name] = plugin.name
|
M.pending[cmd][plugin.name] = plugin
|
||||||
add_cmd(cmd)
|
add_cmd(cmd)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,15 +5,22 @@ local loader = require("lz.n.loader")
|
|||||||
|
|
||||||
---@type lz.n.ColorschemeHandler
|
---@type lz.n.ColorschemeHandler
|
||||||
local M = {
|
local M = {
|
||||||
|
---@type table<string, table<string, lz.n.Plugin[]>>
|
||||||
pending = {},
|
pending = {},
|
||||||
augroup = nil,
|
augroup = nil,
|
||||||
spec_field = "colorscheme",
|
spec_field = "colorscheme",
|
||||||
}
|
}
|
||||||
|
|
||||||
---@param plugin lz.n.Plugin
|
---@param name string
|
||||||
function M.del(plugin)
|
---@return lz.n.Plugin?
|
||||||
|
function M.lookup(name)
|
||||||
|
return require("lz.n.handler.extra").lookup(M.pending, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
function M.del(name)
|
||||||
vim.iter(M.pending):each(function(_, plugins)
|
vim.iter(M.pending):each(function(_, plugins)
|
||||||
plugins[plugin.name] = nil
|
plugins[name] = nil
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -49,7 +56,7 @@ function M.add(plugin)
|
|||||||
---@param colorscheme string
|
---@param colorscheme string
|
||||||
vim.iter(plugin.colorscheme):each(function(colorscheme)
|
vim.iter(plugin.colorscheme):each(function(colorscheme)
|
||||||
M.pending[colorscheme] = M.pending[colorscheme] or {}
|
M.pending[colorscheme] = M.pending[colorscheme] or {}
|
||||||
M.pending[colorscheme][plugin.name] = plugin.name
|
M.pending[colorscheme][plugin.name] = plugin
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ lz_n_events["User DeferredUIEnter"] = lz_n_events.DeferredUIEnter
|
|||||||
|
|
||||||
---@type lz.n.EventHandler
|
---@type lz.n.EventHandler
|
||||||
local M = {
|
local M = {
|
||||||
|
---@type table<string, table<string, lz.n.Plugin[]>>
|
||||||
pending = {},
|
pending = {},
|
||||||
events = {},
|
events = {},
|
||||||
group = vim.api.nvim_create_augroup("lz_n_handler_event", { clear = true }),
|
group = vim.api.nvim_create_augroup("lz_n_handler_event", { clear = true }),
|
||||||
@@ -56,6 +57,12 @@ local M = {
|
|||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return lz.n.Plugin?
|
||||||
|
function M.lookup(name)
|
||||||
|
return require("lz.n.handler.extra").lookup(M.pending, name)
|
||||||
|
end
|
||||||
|
|
||||||
-- Get all augroups for an event
|
-- Get all augroups for an event
|
||||||
---@param event string
|
---@param event string
|
||||||
---@return string[]
|
---@return string[]
|
||||||
@@ -166,15 +173,15 @@ function M.add(plugin)
|
|||||||
---@param event lz.n.Event
|
---@param event lz.n.Event
|
||||||
vim.iter(plugin.event or {}):each(function(event)
|
vim.iter(plugin.event or {}):each(function(event)
|
||||||
M.pending[event.id] = M.pending[event.id] or {}
|
M.pending[event.id] = M.pending[event.id] or {}
|
||||||
M.pending[event.id][plugin.name] = plugin.name
|
M.pending[event.id][plugin.name] = plugin
|
||||||
add_event(event)
|
add_event(event)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param plugin lz.n.Plugin
|
---@param name string
|
||||||
function M.del(plugin)
|
function M.del(name)
|
||||||
vim.iter(M.pending):each(function(_, plugins)
|
vim.iter(M.pending):each(function(_, plugins)
|
||||||
plugins[plugin.name] = nil
|
plugins[name] = nil
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---@mod lz.n.handler.extra Helper functions for use by handlers
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
---Look up a plugin in a plugin table, commonly used by handlers to
|
||||||
|
---keep track of plugins they manage
|
||||||
|
---@param plugin_tbl table<unknown, table<string, lz.n.Plugin>>
|
||||||
|
---@param name string
|
||||||
|
---@return lz.n.Plugin?
|
||||||
|
function M.lookup(plugin_tbl, name)
|
||||||
|
return vim
|
||||||
|
.iter(plugin_tbl)
|
||||||
|
---@param plugins table<string, lz.n.Plugin>
|
||||||
|
:map(function(_, plugins)
|
||||||
|
return plugins[name]
|
||||||
|
end)
|
||||||
|
---@param plugin lz.n.Plugin?
|
||||||
|
:find(function(plugin)
|
||||||
|
return plugin ~= nil
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -5,7 +5,6 @@ local event = require("lz.n.handler.event")
|
|||||||
|
|
||||||
---@type lz.n.FtHandler
|
---@type lz.n.FtHandler
|
||||||
local M = {
|
local M = {
|
||||||
pending = {},
|
|
||||||
spec_field = "ft",
|
spec_field = "ft",
|
||||||
---@param value string
|
---@param value string
|
||||||
---@return lz.n.Event
|
---@return lz.n.Event
|
||||||
@@ -16,6 +15,7 @@ local M = {
|
|||||||
pattern = value,
|
pattern = value,
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
|
lookup = event.lookup,
|
||||||
}
|
}
|
||||||
|
|
||||||
---@param plugin lz.n.Plugin
|
---@param plugin lz.n.Plugin
|
||||||
@@ -23,9 +23,9 @@ function M.add(plugin)
|
|||||||
event.add(plugin)
|
event.add(plugin)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param plugin lz.n.Plugin
|
---@param name string
|
||||||
function M.del(plugin)
|
function M.del(name)
|
||||||
event.del(plugin)
|
event.del(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -8,6 +8,21 @@ local handlers = {
|
|||||||
colorscheme = require("lz.n.handler.colorscheme"),
|
colorscheme = require("lz.n.handler.colorscheme"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return lz.n.Plugin?
|
||||||
|
function M.lookup(name)
|
||||||
|
return vim
|
||||||
|
.iter(handlers)
|
||||||
|
---@param handler lz.n.Handler
|
||||||
|
:map(function(_, handler)
|
||||||
|
return handler.lookup(name)
|
||||||
|
end)
|
||||||
|
---@param result lz.n.Plugin?
|
||||||
|
:find(function(result)
|
||||||
|
return result ~= nil
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
---@param spec lz.n.PluginSpec
|
---@param spec lz.n.PluginSpec
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function M.is_lazy(spec)
|
function M.is_lazy(spec)
|
||||||
@@ -41,12 +56,11 @@ local function enable(plugin)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.disable(plugin)
|
---@param name string
|
||||||
|
function M.disable(name)
|
||||||
---@param handler lz.n.Handler
|
---@param handler lz.n.Handler
|
||||||
vim.iter(handlers):each(function(_, handler)
|
vim.iter(handlers):each(function(_, handler)
|
||||||
if handler.del then
|
handler.del(name)
|
||||||
handler.del(plugin)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ end
|
|||||||
|
|
||||||
---@type lz.n.KeysHandler
|
---@type lz.n.KeysHandler
|
||||||
local M = {
|
local M = {
|
||||||
|
---@type table<string, table<string, lz.n.Plugin[]>>
|
||||||
pending = {},
|
pending = {},
|
||||||
spec_field = "keys",
|
spec_field = "keys",
|
||||||
---@param value string|lz.n.KeysSpec
|
---@param value string|lz.n.KeysSpec
|
||||||
@@ -43,6 +44,12 @@ local M = {
|
|||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return lz.n.Plugin?
|
||||||
|
function M.lookup(name)
|
||||||
|
return require("lz.n.handler.extra").lookup(M.pending, name)
|
||||||
|
end
|
||||||
|
|
||||||
local skip = { mode = true, id = true, ft = true, rhs = true, lhs = true }
|
local skip = { mode = true, id = true, ft = true, rhs = true, lhs = true }
|
||||||
|
|
||||||
---@param keys lz.n.Keys
|
---@param keys lz.n.Keys
|
||||||
@@ -142,15 +149,15 @@ function M.add(plugin)
|
|||||||
---@param key lz.n.Keys
|
---@param key lz.n.Keys
|
||||||
vim.iter(plugin.keys or {}):each(function(key)
|
vim.iter(plugin.keys or {}):each(function(key)
|
||||||
M.pending[key.id] = M.pending[key.id] or {}
|
M.pending[key.id] = M.pending[key.id] or {}
|
||||||
M.pending[key.id][plugin.name] = plugin.name
|
M.pending[key.id][plugin.name] = plugin
|
||||||
add_keys(key)
|
add_keys(key)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param plugin lz.n.Plugin
|
---@param name string
|
||||||
function M.del(plugin)
|
function M.del(name)
|
||||||
vim.iter(M.pending):each(function(_, plugins)
|
vim.iter(M.pending):each(function(_, plugins)
|
||||||
plugins[plugin.name] = nil
|
plugins[name] = nil
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+26
-33
@@ -15,10 +15,21 @@ local deferred_ui_enter = vim.schedule_wrap(function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
---@type fun(handler: lz.n.Handler): boolean
|
---@type fun(handler: lz.n.Handler): boolean
|
||||||
M.register_handler = require("lz.n.handler").register_handler
|
M.register_handler = function(...)
|
||||||
|
return require("lz.n.handler").register_handler(...)
|
||||||
|
end
|
||||||
|
|
||||||
---@type fun(plugins: string | lz.n.Plugin | string[] | lz.n.Plugin[])
|
--- Accepts plugin names (`string | string[]`, when called in another
|
||||||
M.trigger_load = require("lz.n.loader").load
|
--- plugin's hook), or |lz.n.Plugin| items (when called by a |lz.n.Handler|).
|
||||||
|
--- If called with a plugin name, it will use the registered
|
||||||
|
--- handlers' `lookup` functions to search for a plugin to load
|
||||||
|
--- (loading the first one it finds).
|
||||||
|
--- Once a plugin has been loaded, it will be removed from all handlers (via `del`).
|
||||||
|
--- As a result, calling `trigger_load` with a plugin name is idempotent.
|
||||||
|
---@param plugins string | lz.n.Plugin | string[] | lz.n.Plugin[]
|
||||||
|
M.trigger_load = function(plugins)
|
||||||
|
require("lz.n.loader").load(plugins, M.lookup)
|
||||||
|
end
|
||||||
|
|
||||||
---@overload fun(spec: lz.n.Spec)
|
---@overload fun(spec: lz.n.Spec)
|
||||||
---@overload fun(import: string)
|
---@overload fun(import: string)
|
||||||
@@ -28,42 +39,17 @@ function M.load(spec)
|
|||||||
end
|
end
|
||||||
--- @cast spec lz.n.Spec
|
--- @cast spec lz.n.Spec
|
||||||
local spec_mod = require("lz.n.spec")
|
local spec_mod = require("lz.n.spec")
|
||||||
local is_single_plugin_spec = spec_mod.is_single_plugin_spec(spec)
|
|
||||||
local plugins = spec_mod.parse(spec)
|
local plugins = spec_mod.parse(spec)
|
||||||
|
|
||||||
-- add to state before loading anything, to prevent multiple loads being called
|
|
||||||
-- from within other eager plugin specs
|
|
||||||
local state = require("lz.n.state")
|
|
||||||
if is_single_plugin_spec then
|
|
||||||
local ok, updated_plugins = pcall(vim.tbl_deep_extend, "error", state.plugins, plugins)
|
|
||||||
if not ok then
|
|
||||||
return vim.schedule(function()
|
|
||||||
vim.notify("Cannot load the same plugin specs more than once", vim.log.levels.ERROR, { title = "lz.n" })
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
state.plugins = updated_plugins
|
|
||||||
else
|
|
||||||
if state.plugins[spec[1]] then
|
|
||||||
return vim.schedule(function()
|
|
||||||
vim.notify(
|
|
||||||
("Plugin %s has already been registered for lazy loading"):format(spec[1]),
|
|
||||||
vim.log.levels.ERROR,
|
|
||||||
{ title = "lz.n" }
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
state.plugins = plugins
|
|
||||||
end
|
|
||||||
|
|
||||||
-- calls handler add functions
|
-- calls handler add functions
|
||||||
require("lz.n.handler").init(plugins)
|
require("lz.n.handler").init(plugins)
|
||||||
|
|
||||||
-- because this calls the handler's del functions,
|
-- Because this calls the handlers' `del` functions,
|
||||||
-- this should be ran after the handlers are given the plugin.
|
-- this should be ran after the plugins are registered with the handlers.
|
||||||
-- even if the plugin isnt supposed to have been added to any of them
|
-- even if an eager plugin isn't supposed to have been added to any of them
|
||||||
|
-- This allows even startup plugins to call
|
||||||
|
-- `require('lz.n').trigger_load()` safely
|
||||||
require("lz.n.loader").load_startup_plugins(plugins)
|
require("lz.n.loader").load_startup_plugins(plugins)
|
||||||
-- in addition, this allows even startup plugins to call
|
|
||||||
-- require('lz.n').trigger_load('someplugin') safely
|
|
||||||
|
|
||||||
if vim.v.vim_did_enter == 1 then
|
if vim.v.vim_did_enter == 1 then
|
||||||
deferred_ui_enter()
|
deferred_ui_enter()
|
||||||
@@ -76,4 +62,11 @@ function M.load(spec)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Lookup a plugin that is pending to be loaded by name.
|
||||||
|
---@param name string
|
||||||
|
---@return lz.n.Plugin?
|
||||||
|
function M.lookup(name)
|
||||||
|
return require("lz.n.handler").lookup(name)
|
||||||
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
+5
-7
@@ -1,7 +1,5 @@
|
|||||||
---@mod lz.n.loader
|
---@mod lz.n.loader
|
||||||
|
|
||||||
local state = require("lz.n.state")
|
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local DEFAULT_PRIORITY = 50
|
local DEFAULT_PRIORITY = 50
|
||||||
@@ -14,7 +12,7 @@ function M._load(plugin)
|
|||||||
if plugin.enabled == false or (type(plugin.enabled) == "function" and not plugin.enabled()) then
|
if plugin.enabled == false or (type(plugin.enabled) == "function" and not plugin.enabled()) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
require("lz.n.handler").disable(plugin)
|
require("lz.n.handler").disable(plugin.name)
|
||||||
---@type fun(name: string) | nil
|
---@type fun(name: string) | nil
|
||||||
local load_impl = plugin.load or vim.tbl_get(vim.g, "lz_n", "load")
|
local load_impl = plugin.load or vim.tbl_get(vim.g, "lz_n", "load")
|
||||||
if type(load_impl) == "function" then
|
if type(load_impl) == "function" then
|
||||||
@@ -101,7 +99,8 @@ local function hook(hook_key, plugin)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param plugins string | lz.n.Plugin | string[] | lz.n.Plugin[]
|
---@param plugins string | lz.n.Plugin | string[] | lz.n.Plugin[]
|
||||||
function M.load(plugins)
|
---@param lookup? fun(name: string): lz.n.Plugin?
|
||||||
|
function M.load(plugins, lookup)
|
||||||
plugins = (type(plugins) == "string" or plugins.name) and { plugins } or plugins
|
plugins = (type(plugins) == "string" or plugins.name) and { plugins } or plugins
|
||||||
---@cast plugins (string|lz.n.Plugin)[]
|
---@cast plugins (string|lz.n.Plugin)[]
|
||||||
for _, plugin in pairs(plugins) do
|
for _, plugin in pairs(plugins) do
|
||||||
@@ -109,9 +108,8 @@ function M.load(plugins)
|
|||||||
-- https://github.com/nvim-neorocks/lz.n/pull/21
|
-- https://github.com/nvim-neorocks/lz.n/pull/21
|
||||||
local loadable = true
|
local loadable = true
|
||||||
if type(plugin) == "string" then
|
if type(plugin) == "string" then
|
||||||
if state.plugins[plugin] then
|
plugin = lookup and lookup(plugin) or plugin
|
||||||
plugin = state.plugins[plugin]
|
if type(plugin) == "string" then
|
||||||
else
|
|
||||||
vim.notify("Plugin " .. plugin .. " not found", vim.log.levels.ERROR, { title = "lz.n" })
|
vim.notify("Plugin " .. plugin .. " not found", vim.log.levels.ERROR, { title = "lz.n" })
|
||||||
loadable = false
|
loadable = false
|
||||||
end
|
end
|
||||||
|
|||||||
+10
-1
@@ -89,9 +89,18 @@ error("Cannot import a meta module")
|
|||||||
--- @field load? fun(name: string)
|
--- @field load? fun(name: string)
|
||||||
|
|
||||||
--- @class lz.n.Handler
|
--- @class lz.n.Handler
|
||||||
|
---
|
||||||
|
--- The |lz.n.PluginSpec| field used to configure this handler.
|
||||||
--- @field spec_field string
|
--- @field spec_field string
|
||||||
|
---
|
||||||
|
--- Add a plugin to this handler.
|
||||||
--- @field add fun(plugin: lz.n.Plugin)
|
--- @field add fun(plugin: lz.n.Plugin)
|
||||||
--- @field del? fun(plugin: lz.n.Plugin)
|
---
|
||||||
|
--- Remove a plugin from this handler by name.
|
||||||
|
--- @field del fun(name: string)
|
||||||
|
---
|
||||||
|
--- Lookup a plugin by name.
|
||||||
|
--- @field lookup fun(name: string): lz.n.Plugin?
|
||||||
|
|
||||||
--- @type lz.n.Config
|
--- @type lz.n.Config
|
||||||
vim.g.lz_n = vim.g.lz_n
|
vim.g.lz_n = vim.g.lz_n
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
---@mod lz.n.state
|
|
||||||
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
---@type table<string, lz.n.Plugin>
|
|
||||||
M.plugins = {}
|
|
||||||
|
|
||||||
return M
|
|
||||||
@@ -3,7 +3,6 @@ vim.g.lz_n = {
|
|||||||
load = function() end,
|
load = function() end,
|
||||||
}
|
}
|
||||||
local cmd = require("lz.n.handler.cmd")
|
local cmd = require("lz.n.handler.cmd")
|
||||||
local state = require("lz.n.state")
|
|
||||||
local loader = require("lz.n.loader")
|
local loader = require("lz.n.loader")
|
||||||
local spy = require("luassert.spy")
|
local spy = require("luassert.spy")
|
||||||
|
|
||||||
@@ -15,7 +14,6 @@ describe("handlers.cmd", function()
|
|||||||
cmd = { "Foo" },
|
cmd = { "Foo" },
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
cmd.add(plugin)
|
cmd.add(plugin)
|
||||||
assert.is_not_nil(vim.cmd.Foo)
|
assert.is_not_nil(vim.cmd.Foo)
|
||||||
local counter = 0
|
local counter = 0
|
||||||
@@ -49,7 +47,6 @@ describe("handlers.cmd", function()
|
|||||||
cmd = commands,
|
cmd = commands,
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
cmd.add(plugin)
|
cmd.add(plugin)
|
||||||
vim.cmd[commands[1]]()
|
vim.cmd[commands[1]]()
|
||||||
vim.cmd[commands[2]]()
|
vim.cmd[commands[2]]()
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ vim.g.lz_n = {
|
|||||||
load = function() end,
|
load = function() end,
|
||||||
}
|
}
|
||||||
local colorscheme = require("lz.n.handler.colorscheme")
|
local colorscheme = require("lz.n.handler.colorscheme")
|
||||||
local state = require("lz.n.state")
|
|
||||||
local loader = require("lz.n.loader")
|
local loader = require("lz.n.loader")
|
||||||
local spy = require("luassert.spy")
|
local spy = require("luassert.spy")
|
||||||
|
|
||||||
@@ -14,7 +13,6 @@ describe("handlers.colorscheme", function()
|
|||||||
colorscheme = { "sweetie" },
|
colorscheme = { "sweetie" },
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
colorscheme.add(plugin)
|
colorscheme.add(plugin)
|
||||||
pcall(vim.cmd.colorscheme, "sweetie")
|
pcall(vim.cmd.colorscheme, "sweetie")
|
||||||
pcall(vim.cmd.colorscheme, "sweetie")
|
pcall(vim.cmd.colorscheme, "sweetie")
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ vim.g.lz_n = {
|
|||||||
load = function() end,
|
load = function() end,
|
||||||
}
|
}
|
||||||
local event = require("lz.n.handler.event")
|
local event = require("lz.n.handler.event")
|
||||||
local state = require("lz.n.state")
|
|
||||||
local loader = require("lz.n.loader")
|
local loader = require("lz.n.loader")
|
||||||
local spy = require("luassert.spy")
|
local spy = require("luassert.spy")
|
||||||
|
|
||||||
@@ -52,7 +51,6 @@ describe("handlers.event", function()
|
|||||||
event = { event.parse("BufEnter") },
|
event = { event.parse("BufEnter") },
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
event.add(plugin)
|
event.add(plugin)
|
||||||
vim.api.nvim_exec_autocmds("BufEnter", {})
|
vim.api.nvim_exec_autocmds("BufEnter", {})
|
||||||
vim.api.nvim_exec_autocmds("BufEnter", {})
|
vim.api.nvim_exec_autocmds("BufEnter", {})
|
||||||
@@ -67,7 +65,6 @@ describe("handlers.event", function()
|
|||||||
event = events,
|
event = events,
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
event.add(plugin)
|
event.add(plugin)
|
||||||
vim.api.nvim_exec_autocmds(events[1].event, {
|
vim.api.nvim_exec_autocmds(events[1].event, {
|
||||||
pattern = ".lua",
|
pattern = ".lua",
|
||||||
@@ -98,7 +95,6 @@ describe("handlers.event", function()
|
|||||||
group = vim.api.nvim_create_augroup("foo", {}),
|
group = vim.api.nvim_create_augroup("foo", {}),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
event.add(plugin)
|
event.add(plugin)
|
||||||
vim.api.nvim_exec_autocmds("BufEnter", {})
|
vim.api.nvim_exec_autocmds("BufEnter", {})
|
||||||
assert.True(triggered)
|
assert.True(triggered)
|
||||||
@@ -111,7 +107,6 @@ describe("handlers.event", function()
|
|||||||
event = { event.parse("DeferredUIEnter") },
|
event = { event.parse("DeferredUIEnter") },
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
event.add(plugin)
|
event.add(plugin)
|
||||||
vim.api.nvim_exec_autocmds("User", { pattern = "DeferredUIEnter", modeline = false })
|
vim.api.nvim_exec_autocmds("User", { pattern = "DeferredUIEnter", modeline = false })
|
||||||
assert.spy(spy_load).called(1)
|
assert.spy(spy_load).called(1)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ vim.g.lz_n = {
|
|||||||
load = function() end,
|
load = function() end,
|
||||||
}
|
}
|
||||||
local ft = require("lz.n.handler.ft")
|
local ft = require("lz.n.handler.ft")
|
||||||
local state = require("lz.n.state")
|
|
||||||
local loader = require("lz.n.loader")
|
local loader = require("lz.n.loader")
|
||||||
local spy = require("luassert.spy")
|
local spy = require("luassert.spy")
|
||||||
|
|
||||||
@@ -22,7 +21,6 @@ describe("handlers.ft", function()
|
|||||||
event = { ft.parse("rust") },
|
event = { ft.parse("rust") },
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
ft.add(plugin)
|
ft.add(plugin)
|
||||||
vim.api.nvim_exec_autocmds("FileType", { pattern = "rust" })
|
vim.api.nvim_exec_autocmds("FileType", { pattern = "rust" })
|
||||||
vim.api.nvim_exec_autocmds("FileType", { pattern = "rust" })
|
vim.api.nvim_exec_autocmds("FileType", { pattern = "rust" })
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ vim.g.lz_n = {
|
|||||||
load = function() end,
|
load = function() end,
|
||||||
}
|
}
|
||||||
local keys = require("lz.n.handler.keys")
|
local keys = require("lz.n.handler.keys")
|
||||||
local state = require("lz.n.state")
|
|
||||||
local loader = require("lz.n.loader")
|
local loader = require("lz.n.loader")
|
||||||
local spy = require("luassert.spy")
|
local spy = require("luassert.spy")
|
||||||
|
|
||||||
@@ -30,7 +29,6 @@ describe("handlers.keys", function()
|
|||||||
keys = keys.parse(lhs),
|
keys = keys.parse(lhs),
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
keys.add(plugin)
|
keys.add(plugin)
|
||||||
local feed = vim.api.nvim_replace_termcodes("<Ignore>" .. lhs, true, true, true)
|
local feed = vim.api.nvim_replace_termcodes("<Ignore>" .. lhs, true, true, true)
|
||||||
vim.api.nvim_feedkeys(feed, "ix", false)
|
vim.api.nvim_feedkeys(feed, "ix", false)
|
||||||
@@ -47,7 +45,6 @@ describe("handlers.keys", function()
|
|||||||
keys = lzkeys,
|
keys = lzkeys,
|
||||||
}
|
}
|
||||||
local spy_load = spy.on(loader, "_load")
|
local spy_load = spy.on(loader, "_load")
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
keys.add(plugin)
|
keys.add(plugin)
|
||||||
local feed1 = vim.api.nvim_replace_termcodes("<Ignore>" .. lzkeys[1].lhs, true, true, true)
|
local feed1 = vim.api.nvim_replace_termcodes("<Ignore>" .. lzkeys[1].lhs, true, true, true)
|
||||||
vim.api.nvim_feedkeys(feed1, "ix", false)
|
vim.api.nvim_feedkeys(feed1, "ix", false)
|
||||||
@@ -74,7 +71,6 @@ describe("handlers.keys", function()
|
|||||||
end)
|
end)
|
||||||
orig_load(...)
|
orig_load(...)
|
||||||
end
|
end
|
||||||
state.plugins[plugin.name] = plugin
|
|
||||||
keys.add(plugin)
|
keys.add(plugin)
|
||||||
local feed = vim.api.nvim_replace_termcodes("<Ignore>" .. lhs, true, true, true)
|
local feed = vim.api.nvim_replace_termcodes("<Ignore>" .. lhs, true, true, true)
|
||||||
vim.api.nvim_feedkeys(feed, "ix", false)
|
vim.api.nvim_feedkeys(feed, "ix", false)
|
||||||
|
|||||||
@@ -5,16 +5,35 @@ vim.g.lz_n = {
|
|||||||
local lz_n = require("lz.n")
|
local lz_n = require("lz.n")
|
||||||
local spy = require("luassert.spy")
|
local spy = require("luassert.spy")
|
||||||
|
|
||||||
|
---@type lz.n.Plugin
|
||||||
|
local testplugin = {
|
||||||
|
name = "testplugin",
|
||||||
|
testfield = { "a", "b" },
|
||||||
|
lazy = true,
|
||||||
|
}
|
||||||
|
|
||||||
describe("handlers.custom", function()
|
describe("handlers.custom", function()
|
||||||
---@class TestHandler: lz.n.Handler
|
---@class TestHandler: lz.n.Handler
|
||||||
|
local mock_state = {}
|
||||||
---@type TestHandler
|
---@type TestHandler
|
||||||
local hndl = {
|
local mock_hndl = {
|
||||||
spec_field = "testfield",
|
spec_field = "testfield",
|
||||||
add = function(_) end,
|
add = function(plugin)
|
||||||
del = function(_) end,
|
mock_state[plugin.name] = plugin
|
||||||
|
end,
|
||||||
|
---@param name string
|
||||||
|
del = function(name)
|
||||||
|
mock_state[name] = nil
|
||||||
|
end,
|
||||||
|
---@param name string
|
||||||
|
---@return lz.n.Plugin?
|
||||||
|
lookup = function(name)
|
||||||
|
return mock_state[name]
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
local addspy = spy.on(hndl, "add")
|
|
||||||
local delspy = spy.on(hndl, "del")
|
local addspy = spy.on(mock_hndl, "add")
|
||||||
|
local delspy = spy.on(mock_hndl, "del")
|
||||||
it("Duplicate handlers fail to register", function()
|
it("Duplicate handlers fail to register", function()
|
||||||
local notispy = spy.new(function() end)
|
local notispy = spy.new(function() end)
|
||||||
-- NOTE: teardown fails if you don't temporarily replace vim.notify
|
-- NOTE: teardown fails if you don't temporarily replace vim.notify
|
||||||
@@ -25,23 +44,19 @@ describe("handlers.custom", function()
|
|||||||
vim.notify = og_notify
|
vim.notify = og_notify
|
||||||
end)
|
end)
|
||||||
it("can add plugins to the handler", function()
|
it("can add plugins to the handler", function()
|
||||||
assert.True(lz_n.register_handler(hndl))
|
assert.True(lz_n.register_handler(mock_hndl))
|
||||||
lz_n.load({
|
lz_n.load({
|
||||||
"testplugin",
|
"testplugin",
|
||||||
testfield = { "a", "b" },
|
testfield = { "a", "b" },
|
||||||
})
|
})
|
||||||
assert.spy(addspy).called_with({
|
assert.spy(addspy).called_with(testplugin)
|
||||||
name = "testplugin",
|
|
||||||
testfield = { "a", "b" },
|
|
||||||
lazy = true,
|
|
||||||
})
|
|
||||||
end)
|
end)
|
||||||
it("loading a plugin removes it from the handler", function()
|
it("loading a plugin removes it from the handler", function()
|
||||||
lz_n.trigger_load("testplugin")
|
lz_n.trigger_load(testplugin.name)
|
||||||
assert.spy(delspy).called_with({
|
assert.spy(delspy).called_with(testplugin.name)
|
||||||
name = "testplugin",
|
end)
|
||||||
testfield = { "a", "b" },
|
it("trigger_load is idempotent when called with a plugin name", function()
|
||||||
lazy = true,
|
lz_n.trigger_load(testplugin.name)
|
||||||
})
|
assert.spy(delspy).called(1)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|||||||
Reference in New Issue
Block a user