mirror of
https://github.com/zoriya/lz.n.git
synced 2026-06-04 11:25:18 +00:00
feat: extend lz.n with custom handlers (#17)
added require('lz.n').register_handler(lz.n.HandlerSpec)
added lz.n.Plugin.extras for extra spec items from custom handlers.
feat: extend lz.n with custom handlers
feat: extend lz.n with custom handlers
added tests
Update spec/register_handler_spec.lua
Update spec/register_handler_spec.lua
feat: extend lz.n with custom handlers
Update README.md
Update lua/lz/n/handler/init.lua
Co-authored-by: Marc Jakobi <mrcjkb89@outlook.com>
This commit is contained in:
@@ -315,6 +315,42 @@ Or
|
||||
├── init.lua
|
||||
```
|
||||
|
||||
### Custom Handlers
|
||||
|
||||
You may register your own handlers to lazy-load plugins via
|
||||
other triggers not already covered by the plugin spec.
|
||||
|
||||
You should register all handlers before calling `require('lz.n').load`,
|
||||
because they will not be retroactively applied to
|
||||
the `load` calls that occur before they are registered.
|
||||
|
||||
The `register_handler` function returns a boolean that indicates success.
|
||||
|
||||
`require("lz.n").register_handler(handler: lz.n.Handler): boolean`
|
||||
|
||||
#### lz.n.Handler
|
||||
|
||||
<!-- markdownlint-disable MD013 -->
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| spec_field | `string` | the `lz.n.PluginSpec` field defined by 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 |
|
||||
<!-- markdownlint-enable MD013 -->
|
||||
|
||||
When writing custom handlers,
|
||||
you can load the plugin and run the hooks from
|
||||
the spec with the following function:
|
||||
|
||||
```lua
|
||||
---@type fun(plugins: string | lz.n.Plugin | string[] | lz.n.Plugin[])
|
||||
require('lz.n').trigger_load
|
||||
```
|
||||
|
||||
The function accepts plugin names or parsed plugin specs.
|
||||
It will call the handler's `del` function (if it exists) after the `before` hooks,
|
||||
and before `load` of the plugin's spec.
|
||||
|
||||
## :green_heart: Contributing
|
||||
|
||||
All contributions are welcome!
|
||||
|
||||
@@ -5,7 +5,7 @@ local loader = require("lz.n.loader")
|
||||
---@type lz.n.CmdHandler
|
||||
local M = {
|
||||
pending = {},
|
||||
type = "cmd",
|
||||
spec_field = "cmd",
|
||||
}
|
||||
|
||||
---@param cmd string
|
||||
|
||||
@@ -6,8 +6,8 @@ local loader = require("lz.n.loader")
|
||||
---@type lz.n.ColorschemeHandler
|
||||
local M = {
|
||||
pending = {},
|
||||
type = "colorscheme",
|
||||
augroup = nil,
|
||||
spec_field = "colorscheme",
|
||||
}
|
||||
|
||||
---@param plugin lz.n.Plugin
|
||||
|
||||
@@ -23,7 +23,7 @@ local M = {
|
||||
pending = {},
|
||||
events = {},
|
||||
group = vim.api.nvim_create_augroup("lz_n_handler_event", { clear = true }),
|
||||
type = "event",
|
||||
spec_field = "event",
|
||||
---@param spec lz.n.EventSpec
|
||||
parse = function(spec)
|
||||
local ret = lz_n_events[spec]
|
||||
|
||||
@@ -6,7 +6,7 @@ local event = require("lz.n.handler.event")
|
||||
---@type lz.n.FtHandler
|
||||
local M = {
|
||||
pending = {},
|
||||
type = "ft",
|
||||
spec_field = "ft",
|
||||
---@param value string
|
||||
---@return lz.n.Event
|
||||
parse = function(value)
|
||||
|
||||
+26
-16
@@ -1,20 +1,5 @@
|
||||
---@class lz.n.Handler
|
||||
---@field type lz.n.HandlerTypes
|
||||
---@field pending table<string, table<string, string>> -- key: plugin_name: plugin_name
|
||||
---@field add fun(plugin: lz.n.Plugin)
|
||||
---@field del? fun(plugin: lz.n.Plugin)
|
||||
|
||||
local M = {}
|
||||
|
||||
---@enum lz.n.HandlerTypes
|
||||
M.types = {
|
||||
cmd = "cmd",
|
||||
event = "event",
|
||||
ft = "ft",
|
||||
keys = "keys",
|
||||
colorscheme = "colorscheme",
|
||||
}
|
||||
|
||||
local handlers = {
|
||||
cmd = require("lz.n.handler.cmd"),
|
||||
event = require("lz.n.handler.event"),
|
||||
@@ -23,6 +8,31 @@ local handlers = {
|
||||
colorscheme = require("lz.n.handler.colorscheme"),
|
||||
}
|
||||
|
||||
---@param spec lz.n.PluginSpec
|
||||
---@return boolean
|
||||
function M.is_lazy(spec)
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
return spec.lazy or vim.iter(handlers):any(function(spec_field, _)
|
||||
return spec[spec_field] ~= nil
|
||||
end)
|
||||
end
|
||||
|
||||
---@param handler lz.n.Handler
|
||||
---@return boolean success
|
||||
function M.register_handler(handler)
|
||||
if handlers[handler.spec_field] == nil then
|
||||
handlers[handler.spec_field] = handler
|
||||
return true
|
||||
else
|
||||
vim.notify(
|
||||
"Handler already exists for " .. handler.spec_field .. ". Refusing to register new handler.",
|
||||
vim.log.levels.ERROR,
|
||||
{ title = "lz.n" }
|
||||
)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
---@param plugin lz.n.Plugin
|
||||
local function enable(plugin)
|
||||
for _, handler in pairs(handlers) do
|
||||
@@ -32,7 +42,7 @@ end
|
||||
|
||||
function M.disable(plugin)
|
||||
for _, handler in pairs(handlers) do
|
||||
if type(handler.del) == "function" then
|
||||
if handler.del then
|
||||
handler.del(plugin)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ local loader = require("lz.n.loader")
|
||||
---@type lz.n.KeysHandler
|
||||
local M = {
|
||||
pending = {},
|
||||
type = "keys",
|
||||
spec_field = "keys",
|
||||
---@param value string|lz.n.KeysSpec
|
||||
---@param mode? string
|
||||
---@return lz.n.Keys
|
||||
|
||||
@@ -14,6 +14,12 @@ local deferred_ui_enter = vim.schedule_wrap(function()
|
||||
vim.api.nvim_exec_autocmds("User", { pattern = "DeferredUIEnter", modeline = false })
|
||||
end)
|
||||
|
||||
---@type fun(handler: lz.n.Handler): boolean
|
||||
M.register_handler = require("lz.n.handler").register_handler
|
||||
|
||||
---@type fun(plugins: string | lz.n.Plugin | string[] | lz.n.Plugin[])
|
||||
M.trigger_load = require("lz.n.loader").load
|
||||
|
||||
---@overload fun(spec: lz.n.Spec)
|
||||
---@overload fun(import: string)
|
||||
function M.load(spec)
|
||||
|
||||
@@ -88,5 +88,10 @@ error("Cannot import a meta module")
|
||||
--- Takes the plugin name (not the module name). Defaults to |packadd| if not set.
|
||||
--- @field load? fun(name: string)
|
||||
|
||||
--- @class lz.n.Handler
|
||||
--- @field spec_field string
|
||||
--- @field add fun(plugin: lz.n.Plugin)
|
||||
--- @field del? fun(plugin: lz.n.Plugin)
|
||||
|
||||
--- @type lz.n.Config
|
||||
vim.g.lz_n = vim.g.lz_n
|
||||
|
||||
+1
-5
@@ -144,11 +144,7 @@ local function parse(spec)
|
||||
table.insert(result.colorscheme, _colorscheme_spec)
|
||||
end
|
||||
end
|
||||
result.lazy = result.lazy
|
||||
or result.event ~= nil
|
||||
or result.keys ~= nil
|
||||
or result.cmd ~= nil
|
||||
or result.colorscheme ~= nil
|
||||
result.lazy = require("lz.n.handler").is_lazy(spec)
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
---@diagnostic disable: invisible
|
||||
vim.g.lz_n = {
|
||||
load = function() end,
|
||||
}
|
||||
local lz_n = require("lz.n")
|
||||
local spy = require("luassert.spy")
|
||||
|
||||
describe("handlers.custom", function()
|
||||
---@class TestHandler: lz.n.Handler
|
||||
---@type TestHandler
|
||||
local hndl = {
|
||||
spec_field = "testfield",
|
||||
add = function(_) end,
|
||||
del = function(_) end,
|
||||
}
|
||||
local addspy = spy.on(hndl, "add")
|
||||
local delspy = spy.on(hndl, "del")
|
||||
it("Duplicate handlers fail to register", function()
|
||||
local notispy = spy.new(function() end)
|
||||
-- NOTE: teardown fails if you don't temporarily replace vim.notify
|
||||
local og_notify = vim.notify
|
||||
vim.notify = notispy
|
||||
assert.False(lz_n.register_handler(require("lz.n.handler.ft")))
|
||||
assert.spy(notispy).called(1)
|
||||
vim.notify = og_notify
|
||||
end)
|
||||
it("can add plugins to the handler", function()
|
||||
assert.True(lz_n.register_handler(hndl))
|
||||
lz_n.load({
|
||||
"testplugin",
|
||||
testfield = { "a", "b" },
|
||||
})
|
||||
assert.spy(addspy).called_with({
|
||||
name = "testplugin",
|
||||
testfield = { "a", "b" },
|
||||
lazy = true,
|
||||
})
|
||||
end)
|
||||
it("loading a plugin removes it from the handler", function()
|
||||
lz_n.trigger_load("testplugin")
|
||||
assert.spy(delspy).called_with({
|
||||
name = "testplugin",
|
||||
testfield = { "a", "b" },
|
||||
lazy = true,
|
||||
})
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user