feat(event): added support for structured events (see readme on event)

This commit is contained in:
Folke Lemaitre 2023-10-11 14:24:18 +02:00
parent 73fbf5ccab
commit 303a3ed6a8
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
3 changed files with 82 additions and 61 deletions

View File

@ -80,7 +80,7 @@ require("lazy").setup({
## 🔌 Plugin Spec ## 🔌 Plugin Spec
| Property | Type | Description | | Property | Type | Description |
| ---------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **[1]** | `string?` | Short plugin url. Will be expanded using `config.git.url_format` | | **[1]** | `string?` | Short plugin url. Will be expanded using `config.git.url_format` |
| **dir** | `string?` | A directory pointing to a local plugin | | **dir** | `string?` | A directory pointing to a local plugin |
| **url** | `string?` | A custom git url where the plugin is hosted | | **url** | `string?` | A custom git url where the plugin is hosted |
@ -101,7 +101,7 @@ require("lazy").setup({
| **version** | `string?` or `false` to override the default | Version to use from the repository. Full [Semver](https://devhints.io/semver) ranges are supported | | **version** | `string?` or `false` to override the default | Version to use from the repository. Full [Semver](https://devhints.io/semver) ranges are supported |
| **pin** | `boolean?` | When `true`, this plugin will not be included in updates | | **pin** | `boolean?` | When `true`, this plugin will not be included in updates |
| **submodules** | `boolean?` | When false, git submodules will not be fetched. Defaults to `true` | | **submodules** | `boolean?` | When false, git submodules will not be fetched. Defaults to `true` |
| **event** | `string?` or `string[]` or `fun(self:LazyPlugin, event:string[]):string[]` | Lazy-load on event. Events can be specified as `BufEnter` or with a pattern like `BufEnter *.lua` | | **event** | `string?` or `string[]` or `fun(self:LazyPlugin, event:string[]):string[]` or `{event:string[]\|string, pattern?:string[]\|string}` | Lazy-load on event. Events can be specified as `BufEnter` or with a pattern like `BufEnter *.lua` |
| **cmd** | `string?` or `string[]` or `fun(self:LazyPlugin, cmd:string[]):string[]` | Lazy-load on command | | **cmd** | `string?` or `string[]` or `fun(self:LazyPlugin, cmd:string[]):string[]` | Lazy-load on command |
| **ft** | `string?` or `string[]` or `fun(self:LazyPlugin, ft:string[]):string[]` | Lazy-load on filetype | | **ft** | `string?` or `string[]` or `fun(self:LazyPlugin, ft:string[]):string[]` | Lazy-load on filetype |
| **keys** | `string?` or `string[]` or `LazyKeys[]` or `fun(self:LazyPlugin, keys:string[]):(string \| LazyKeys)[]` | Lazy-load on key mapping | | **keys** | `string?` or `string[]` or `LazyKeys[]` or `fun(self:LazyPlugin, keys:string[]):(string \| LazyKeys)[]` | Lazy-load on key mapping |

View File

@ -4,12 +4,14 @@ local Util = require("lazy.core.util")
---@class LazyEventOpts ---@class LazyEventOpts
---@field event string ---@field event string
---@field pattern? string
---@field group? string ---@field group? string
---@field exclude? string[] ---@field exclude? string[]
---@field data? any ---@field data? any
---@field buffer? number ---@field buffer? number
---@alias LazyEvent {id:string, event:string[]|string, pattern?:string[]|string}
---@alias LazyEventSpec string|{event?:string|string[], pattern?:string|string[]}|string[]
---@class LazyEventHandler:LazyHandler ---@class LazyEventHandler:LazyHandler
---@field events table<string,true> ---@field events table<string,true>
---@field group number ---@field group number
@ -23,28 +25,64 @@ M.triggers = {
M.group = vim.api.nvim_create_augroup("lazy_handler_event", { clear = true }) M.group = vim.api.nvim_create_augroup("lazy_handler_event", { clear = true })
---@param value string ---@param spec LazyEventSpec
function M:_add(value) ---@return LazyEvent
local event_spec = self:_event(value) function M:parse(spec)
---@type string?, string? local ret = M.mappings[spec] --[[@as LazyEvent?]]
local event, pattern = event_spec:match("^(%w+)%s+(.*)$") if ret then
event = event or event_spec return ret
end
if type(spec) == "string" then
local event, pattern = spec:match("^(%w+)%s+(.*)$")
event = event or spec
return { id = spec, event = event, pattern = pattern }
elseif Util.is_list(spec) then
ret = { id = table.concat(spec, "|"), event = spec }
else
ret = spec --[[@as LazyEvent]]
if not ret.id then
---@diagnostic disable-next-line: assign-type-mismatch, param-type-mismatch
ret.id = type(ret.event) == "string" and ret.event or table.concat(ret.event, "|")
if ret.pattern then
---@diagnostic disable-next-line: assign-type-mismatch, param-type-mismatch
ret.id = ret.id .. " " .. (type(ret.pattern) == "string" and ret.pattern or table.concat(ret.pattern, ", "))
end
end
end
return ret
end
---@param plugin LazyPlugin
function M:values(plugin)
---@type table<string,any>
local values = {}
---@diagnostic disable-next-line: no-unknown
for _, value in ipairs(plugin[self.type] or {}) do
local event = self:parse(value)
values[event.id] = event
end
return values
end
---@param event LazyEvent
function M:_add(event)
local done = false local done = false
vim.api.nvim_create_autocmd(event, { vim.api.nvim_create_autocmd(event.event, {
group = self.group, group = self.group,
once = true, once = true,
pattern = pattern, pattern = event.pattern,
callback = function(ev) callback = function(ev)
if done or not self.active[value] then if done or not self.active[event.id] then
return return
end end
-- HACK: work-around for https://github.com/neovim/neovim/issues/25526
done = true done = true
Util.track({ [self.type] = value }) Util.track({ [self.type] = event.id })
local state = M.get_state(ev.event, pattern, ev.buf, ev.data) local state = M.get_state(ev.event, ev.buf, ev.data)
-- load the plugins -- load the plugins
Loader.load(self.active[value], { [self.type] = value }) Loader.load(self.active[event.id], { [self.type] = event.id })
-- check if any plugin created an event handler for this event and fire the group -- check if any plugin created an event handler for this event and fire the group
for _, s in ipairs(state) do for _, s in ipairs(state) do
@ -57,38 +95,23 @@ end
-- Get the current state of the event and all the events that will be fired -- Get the current state of the event and all the events that will be fired
---@param event string ---@param event string
---@param pattern? string
---@param buf number ---@param buf number
---@param data any ---@param data any
function M.get_state(event, pattern, buf, data) function M.get_state(event, buf, data)
local state = {} ---@type LazyEventOpts[] local state = {} ---@type LazyEventOpts[]
while event do while event do
table.insert(state, 1, { table.insert(state, 1, {
event = event, event = event,
pattern = pattern,
exclude = event ~= "FileType" and M.get_augroups(event) or nil, exclude = event ~= "FileType" and M.get_augroups(event) or nil,
buffer = buf, buffer = buf,
data = data, data = data,
}) })
data = nil -- only pass the data to the first event data = nil -- only pass the data to the first event
if event == "FileType" then
pattern = nil -- only use the pattern for the first event
end
event = M.triggers[event] event = M.triggers[event]
end end
return state return state
end end
---@param value string
function M:_event(value)
if value == "VeryLazy" then
return "User VeryLazy"
elseif value == "BufRead" then
return "BufReadPost"
end
return value
end
-- Get all augroups for the events -- Get all augroups for the events
---@param event string ---@param event string
function M.get_augroups(event) function M.get_augroups(event)
@ -127,7 +150,6 @@ function M._trigger(opts)
Util.info({ Util.info({
"# Firing Events", "# Firing Events",
" - **event:** " .. opts.event, " - **event:** " .. opts.event,
opts.pattern and (" - **pattern:** " .. opts.pattern),
opts.group and (" - **group:** " .. opts.group), opts.group and (" - **group:** " .. opts.group),
opts.buffer and (" - **buffer:** " .. opts.buffer), opts.buffer and (" - **buffer:** " .. opts.buffer),
}) })
@ -135,7 +157,6 @@ function M._trigger(opts)
Util.track({ event = opts.group or opts.event }) Util.track({ event = opts.group or opts.event })
Util.try(function() Util.try(function()
vim.api.nvim_exec_autocmds(opts.event, { vim.api.nvim_exec_autocmds(opts.event, {
-- pattern = opts.pattern,
buffer = opts.buffer, buffer = opts.buffer,
group = opts.group, group = opts.group,
modeline = false, modeline = false,

View File

@ -29,7 +29,7 @@
---@field opts? PluginOpts ---@field opts? PluginOpts
---@class LazyPluginHandlers ---@class LazyPluginHandlers
---@field event? string[] ---@field event? LazyEventSpec[]
---@field cmd? string[] ---@field cmd? string[]
---@field ft? string[] ---@field ft? string[]
---@field keys? (string|LazyKeysSpec)[] ---@field keys? (string|LazyKeysSpec)[]