Files
lz.n/lua/lz/n/handler/state.lua
T
2024-08-28 21:36:04 +02:00

105 lines
3.4 KiB
Lua

---@mod lz.n.handler.state Safe state management for handlers
---
---@brief [[
---This module is to be used by |lz.n.Handler| implementations.
---It provides an API for safely managing handler state,
---ensuring that `trigger_load` can be called in plugin hooks.
---@brief ]]
local state = {}
---@return lz.n.handler.State
function state.new()
---@type table<string, table<string, lz.n.Plugin>>
local pending = {}
local DEFAULT_KEY = "lz.n.handler.State.DEFAULT_KEY"
return {
---@overload fun(key: string, plugin: lz.n.Plugin)
---@overload fun(plugin: lz.n.Plugin)
insert = function(key, plugin)
if type(key) ~= "string" then
plugin = key
key = DEFAULT_KEY
end
pending[key] = pending[key] or {}
pending[key][plugin.name] = plugin
end,
del = function(plugin_name, callback)
vim.iter(pending)
:filter(function(_, plugins)
return plugins[plugin_name] ~= nil
end)
:each(
---@param key string
---@param plugins lz.n.Plugin[]
function(key, plugins)
if callback then
callback(key)
end
plugins[plugin_name] = nil
end
)
end,
has_pending_plugins = function(key)
key = key or DEFAULT_KEY
return pending[key] ~= nil and not vim.tbl_isempty(pending[key])
end,
lookup_plugin = function(plugin_name)
return vim
.iter(pending)
---@param plugins table<string, lz.n.Plugin>
:map(function(_, plugins)
return plugins[plugin_name]
end)
---@param plugin lz.n.Plugin?
:find(function(plugin)
return plugin ~= nil
end)
end,
---@overload fun(key: string, callback: fun(plugin: lz.n.Plugin)): string[]
---@overload fun(callback: fun(plugin: lz.n.Plugin)): string[]
each_pending = function(key, callback)
if type(key) ~= "string" then
callback = key
key = DEFAULT_KEY
end
local plugins = pending[key] or {}
vim
.iter(vim.deepcopy(plugins))
---@param plugin lz.n.Plugin
:each(function(_, plugin)
if pending[key][plugin.name] then
callback(plugin)
end
end)
return vim.tbl_keys(plugins)
end,
}
end
---@class lz.n.handler.State
---
---Insert a plugin (optionally, by key).
---@field insert fun(key: string, plugin: lz.n.Plugin) | fun(plugin: lz.n.Plugin)
---
---Remove a plugin by its name.
---@field del fun(plugin_name: string, callback?: fun(key: string))
---
---Check if there are pending plugins (optionally, by key)
---@field has_pending_plugins fun(key?: string):boolean
---
---Lookup a plugin by its name.
---@field lookup_plugin fun(plugin_name: string):(lz.n.Plugin | nil)
---
---Safely apply a callback to all pending plugins
---(optionally, by key).
---@field each_pending fun(key: string, callback: fun(plugin: lz.n.Plugin)): string[] | fun(callback: fun(plugin: lz.n.Plugin)): string[]
return state