mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 10:45:16 -07:00
feat(lua): vim.autocmd
and vim.augroup
test(lua): `vim.autocmd` and `vim.augroup` test: add describe blocks Organize tests with `describe` blocks. style: indentation
This commit is contained in:
parent
2f1fd15554
commit
e04acb1459
243
runtime/lua/vim/_auto.lua
Normal file
243
runtime/lua/vim/_auto.lua
Normal file
@ -0,0 +1,243 @@
|
||||
---@class EventContext
|
||||
---@field _group string|boolean
|
||||
---@field _buffer integer|boolean
|
||||
local EventContext = {}
|
||||
|
||||
---@class Event
|
||||
---@field _ctx EventContext
|
||||
---@field _event string|string[]
|
||||
---@field _pattern? string|string[]
|
||||
local Event = {}
|
||||
|
||||
---@class Augroup
|
||||
---@field _ctx EventContext
|
||||
---@field _group string
|
||||
local Augroup = {}
|
||||
|
||||
local a, validate = vim.api, vim.validate
|
||||
|
||||
---@param group? string|boolean
|
||||
---@param buffer? integer|boolean
|
||||
---@return EventContext
|
||||
---@private
|
||||
function EventContext._new(group, buffer)
|
||||
-- use non-nil values to avoid triggering the `__index` metamethod when we access fields on self.
|
||||
local self = {
|
||||
_group = group or false,
|
||||
_buffer = buffer or false,
|
||||
}
|
||||
return setmetatable(self, EventContext)
|
||||
end
|
||||
|
||||
---@param opts? table API options
|
||||
---@return table opts
|
||||
function EventContext:_apply(opts)
|
||||
opts = opts or {}
|
||||
local g, b = self._group, self._buffer
|
||||
b = b == true and 0 or b
|
||||
opts.buffer = b or opts.buffer
|
||||
opts.group = g or opts.group
|
||||
return opts
|
||||
end
|
||||
|
||||
---@param self EventContext
|
||||
---@param opts? table
|
||||
---@return table
|
||||
---@see |nvim_get_autocmds()|
|
||||
function EventContext:get(opts)
|
||||
return a.nvim_get_autocmds(self:_apply(opts))
|
||||
end
|
||||
|
||||
---@param self EventContext
|
||||
---@param opts? table
|
||||
---@see |nvim_clear_autocmds()|
|
||||
function EventContext:clear(opts)
|
||||
a.nvim_clear_autocmds(self:_apply(opts))
|
||||
end
|
||||
|
||||
---@param self EventContext
|
||||
---@private
|
||||
function EventContext:__index(k)
|
||||
-- first, check methods
|
||||
if EventContext[k] then
|
||||
return EventContext[k]
|
||||
end
|
||||
-- then, check if we're trying to specify a buffer
|
||||
if k == "buf" then
|
||||
return self._buffer == false and EventContext._new(self._group, true) or nil
|
||||
elseif type(k) == "number" then
|
||||
return self._buffer == true and EventContext._new(self._group, k) or nil
|
||||
end
|
||||
-- nothing else to check; use k as event name
|
||||
return Event._new(self, k)
|
||||
end
|
||||
|
||||
---@param ctx EventContext
|
||||
---@param event string|string[]
|
||||
---@param pattern? string|string[]
|
||||
---@return Event
|
||||
---@private
|
||||
function Event._new(ctx, event, pattern)
|
||||
local self = {
|
||||
_ctx = ctx,
|
||||
_event = event,
|
||||
_pattern = pattern or false,
|
||||
}
|
||||
return setmetatable(self, Event)
|
||||
end
|
||||
|
||||
---@param self Event
|
||||
---@param opts? table
|
||||
---@return table[]
|
||||
function Event:get(opts)
|
||||
opts = self._ctx:_apply(opts)
|
||||
opts.event = self._event
|
||||
opts.pattern = self._pattern or opts.pattern
|
||||
return a.nvim_get_autocmds(opts)
|
||||
end
|
||||
|
||||
---@param self Event
|
||||
---@param opts? table
|
||||
function Event:exec(opts)
|
||||
opts = self._ctx:_apply(opts)
|
||||
opts.pattern = self._pattern or opts.pattern
|
||||
a.nvim_exec_autocmds(self._event, opts)
|
||||
end
|
||||
|
||||
---@param self Event
|
||||
---@param opts? table
|
||||
function Event:clear(opts)
|
||||
opts = self._ctx:_apply(opts)
|
||||
opts.event = self._event
|
||||
opts.pattern = self._pattern or opts.pattern
|
||||
a.nvim_clear_autocmds(opts)
|
||||
end
|
||||
|
||||
--- Create an autocommand for this event
|
||||
---@param self Event
|
||||
---@param handler string|function
|
||||
---@param opts? table
|
||||
---@return integer
|
||||
function Event:__call(handler, opts)
|
||||
validate {
|
||||
handler = { handler, {"s", "f"} },
|
||||
opts = { opts, "t", true },
|
||||
}
|
||||
opts = self._ctx:_apply(opts)
|
||||
opts.pattern = self._pattern or opts.pattern
|
||||
if type(handler) == "string" and handler:sub(1, 1) == ":" then
|
||||
opts.command = handler:sub(2)
|
||||
else
|
||||
opts.callback = handler
|
||||
end
|
||||
return a.nvim_create_autocmd(self._event, opts)
|
||||
end
|
||||
|
||||
---@param self Event
|
||||
---@return function|Event|nil
|
||||
function Event:__index(k)
|
||||
if Event[k] then
|
||||
return Event[k]
|
||||
elseif not self._pattern and not self._ctx._buffer then
|
||||
return Event._new(self._ctx, self._event, k)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
Augroup.__index = Augroup
|
||||
|
||||
---@param name string
|
||||
---@return Augroup
|
||||
function Augroup._new(name)
|
||||
local self = {
|
||||
_ctx = EventContext._new(name, nil),
|
||||
_group = name,
|
||||
}
|
||||
return setmetatable(self, Augroup)
|
||||
end
|
||||
|
||||
---@param self Augroup
|
||||
---@return integer id
|
||||
function Augroup:create()
|
||||
return a.nvim_create_augroup(self._group, { clear = false })
|
||||
end
|
||||
|
||||
---@param self Augroup
|
||||
---@param opts? table
|
||||
---@return integer? id
|
||||
function Augroup:clear(opts)
|
||||
if not opts then
|
||||
return a.nvim_create_augroup(self._group, { clear = true })
|
||||
else
|
||||
self._ctx:clear(opts)
|
||||
end
|
||||
end
|
||||
|
||||
---@param self Augroup
|
||||
function Augroup:del()
|
||||
return a.nvim_del_augroup_by_name(self._group)
|
||||
end
|
||||
|
||||
---@param self Augroup
|
||||
---@param opts? table
|
||||
---@return table[]?
|
||||
function Augroup:get(opts)
|
||||
if not opts then
|
||||
local exists, cmds = pcall(a.nvim_get_autocmds, { group = self._group })
|
||||
return exists and cmds or nil
|
||||
else
|
||||
return self._ctx:get(opts)
|
||||
end
|
||||
end
|
||||
|
||||
---@param self Augroup
|
||||
---@param spec fun(au:EventContext):any
|
||||
---@return integer id
|
||||
---@return any
|
||||
function Augroup:__call(spec)
|
||||
local id = self:create()
|
||||
local res = spec(self._ctx)
|
||||
return id, res
|
||||
end
|
||||
|
||||
--- Use `vim.autocmd` to manage autocommands. Index it by event names to create and execute them.
|
||||
---
|
||||
--- To create an autocommand, index `vim.autocmd` with an event name to return a callable table.
|
||||
--- Then call it with a handler (a Lua function, a Vimscript function name, or Ex command) and
|
||||
--- and optional table of options to pass to |nvim_create_autocmd()|.
|
||||
---
|
||||
--- <pre>lua
|
||||
--- -- prefix Ex commands with ":" to use as an event handler
|
||||
--- vim.autocmd.UIEnter(":echo 'Hello!'")
|
||||
--- -- a Lua callback as an event handler
|
||||
--- vim.autocmd.UIEnter(function()
|
||||
--- vim.cmd.echo 'Hello!'
|
||||
--- end)
|
||||
--- -- passing in additional options
|
||||
--- vim.autocmd.UIEnter(":echo 'Hello!'", {
|
||||
--- desc = "greeting",
|
||||
--- once = true,
|
||||
--- })
|
||||
--- -- specify multiple events
|
||||
--- vim.autocmd[{ "UIEnter", "TabEnter", "TermEnter" }](":echo 'Hello!'")
|
||||
--- </pre>
|
||||
---
|
||||
--- You may also specify a pattern by indexing the event.
|
||||
---
|
||||
--- <pre>lua
|
||||
--- vim.autocmd.FileType[{ "qf", "help", "man", }](function()
|
||||
--- vim.opt_local.number = false
|
||||
--- vim.opt_local.relativenumber = false
|
||||
--- end)
|
||||
--- </pre>
|
||||
---
|
||||
vim.autocmd = EventContext._new(nil, nil)
|
||||
|
||||
vim.autocmd.buf = EventContext._new(nil, 0)
|
||||
|
||||
--- Create, delete, and clear autocommand groups with `vim.augroup`.
|
||||
---
|
||||
vim.augroup = setmetatable({}, {
|
||||
__index = function(_, k) return Augroup._new(k) end,
|
||||
})
|
@ -59,6 +59,9 @@ setmetatable(vim, {
|
||||
elseif key == 'inspect_pos' or key == 'show_pos' then
|
||||
require('vim._inspector')
|
||||
return t[key]
|
||||
elseif key == 'autocmd' or key == 'augroup' then
|
||||
require('vim._auto')
|
||||
return t[key]
|
||||
elseif vim.startswith(key, 'uri_') then
|
||||
local val = require('vim.uri')[key]
|
||||
if val ~= nil then
|
||||
|
230
test/functional/lua/auto_spec.lua
Normal file
230
test/functional/lua/auto_spec.lua
Normal file
@ -0,0 +1,230 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local exec_lua = helpers.exec_lua
|
||||
local meths = helpers.meths
|
||||
local clear = helpers.clear
|
||||
local eq = helpers.eq
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('vim.autocmd', function()
|
||||
describe('vim.autocmd:get()', function()
|
||||
pending('behaves like nvim_get_autocmds')
|
||||
end)
|
||||
|
||||
describe('vim.autocmd:clear()', function()
|
||||
pending('behaves like nvim_clear_autocmds')
|
||||
end)
|
||||
|
||||
describe('vim.autocmd.buf', function()
|
||||
pending('manages buflocal autocommands')
|
||||
|
||||
it('can create an autocommand for the current buffer', function()
|
||||
exec_lua [[ vim.autocmd.buf.InsertEnter(':echo "Coding!"') ]]
|
||||
eq(1, #meths.get_autocmds({ buffer = 0 }))
|
||||
end)
|
||||
|
||||
it('can get all autocommands attached to the current buffer', function()
|
||||
meths.create_autocmd('InsertEnter', {
|
||||
buffer = 0,
|
||||
command = 'echo "Coding!"'
|
||||
})
|
||||
meths.create_autocmd('InsertLeave', {
|
||||
buffer = 0,
|
||||
command = 'echo "Done!"'
|
||||
})
|
||||
local aus = exec_lua [[ return vim.autocmd.buf:get() ]]
|
||||
eq(2, #aus)
|
||||
end)
|
||||
|
||||
it('can clear all autocommands attached to the current buffer', function()
|
||||
meths.create_autocmd('InsertEnter', {
|
||||
buffer = 0,
|
||||
command = 'echo "Coding!"'
|
||||
})
|
||||
meths.create_autocmd('InsertLeave', {
|
||||
buffer = 0,
|
||||
command = 'echo "Done!"'
|
||||
})
|
||||
eq(2, #meths.get_autocmds({ buffer = 0 }))
|
||||
exec_lua [[ vim.autocmd.buf:clear() ]]
|
||||
eq(0, #meths.get_autocmds({ buffer = 0 }))
|
||||
end)
|
||||
|
||||
pending('can be indexed with a bufnr')
|
||||
end)
|
||||
|
||||
it('can create an autocommand', function()
|
||||
local id = exec_lua([[
|
||||
return vim.autocmd.UIEnter(':echo "Hello!"')
|
||||
]])
|
||||
assert.number(id)
|
||||
local cmds = meths.get_autocmds({ event = 'UIEnter' })
|
||||
eq(1, #cmds)
|
||||
eq(id, cmds[1].id)
|
||||
eq('echo "Hello!"', cmds[1].command)
|
||||
end)
|
||||
|
||||
it('can create an autocommand with options', function()
|
||||
local id = exec_lua([[
|
||||
return vim.autocmd.UIEnter(':echo "Hello!"', {
|
||||
desc = 'greeting',
|
||||
once = true,
|
||||
})
|
||||
]])
|
||||
assert.number(id)
|
||||
local cmds = meths.get_autocmds({ event = 'UIEnter' })
|
||||
eq(id, cmds[1].id)
|
||||
eq('greeting', cmds[1].desc)
|
||||
end)
|
||||
|
||||
it('can create an autocommand for multiple events', function()
|
||||
local id = exec_lua([[
|
||||
return vim.autocmd[{ 'UIEnter', 'VimEnter', 'WinEnter' }](':echo "Hello!"')
|
||||
]])
|
||||
assert.number(id)
|
||||
eq(id, meths.get_autocmds({ event = 'UIEnter' })[1].id)
|
||||
eq(id, meths.get_autocmds({ event = 'VimEnter' })[1].id)
|
||||
eq(id, meths.get_autocmds({ event = 'WinEnter' })[1].id)
|
||||
end)
|
||||
|
||||
it('can create an autocommand for an event and pattern', function()
|
||||
local id = exec_lua([[
|
||||
return vim.autocmd.User.CustomEvent(':echo "Hello!"')
|
||||
]])
|
||||
assert.number(id)
|
||||
eq(id, meths.get_autocmds({ event = 'User', pattern = 'CustomEvent' })[1].id)
|
||||
end)
|
||||
|
||||
it('can create an autocommand and specify multiple patterns', function()
|
||||
local id = exec_lua([[
|
||||
return vim.autocmd.Filetype[{ 'lua', 'vim', 'sh' }](':echo "Hello!"')
|
||||
]])
|
||||
assert.number(id)
|
||||
eq(3, #meths.get_autocmds({ event = 'Filetype' }))
|
||||
end)
|
||||
|
||||
it('can get autocommands for an event', function()
|
||||
meths.create_autocmd('UIEnter', {
|
||||
command = 'echo "Hello!"',
|
||||
})
|
||||
local cmds = exec_lua([[
|
||||
return vim.autocmd.UIEnter:get()
|
||||
]])
|
||||
eq(1, #cmds)
|
||||
end)
|
||||
|
||||
it('can get autocommands for an event and pattern', function()
|
||||
meths.create_autocmd('User', {
|
||||
pattern = 'foo',
|
||||
command = 'echo "Hello!"',
|
||||
})
|
||||
meths.create_autocmd('User', {
|
||||
pattern = 'bar',
|
||||
command = 'echo "Hello!"',
|
||||
})
|
||||
local cmds = exec_lua([[
|
||||
return vim.autocmd.User.foo:get()
|
||||
]])
|
||||
eq(1, #cmds)
|
||||
end)
|
||||
|
||||
it('can clear autocommands for an event', function()
|
||||
meths.create_autocmd('UIEnter', {
|
||||
command = 'echo "Hello!"',
|
||||
})
|
||||
exec_lua([[
|
||||
vim.autocmd.UIEnter:clear()
|
||||
]])
|
||||
eq(0, #meths.get_autocmds({ event = 'UIEnter' }))
|
||||
end)
|
||||
|
||||
it('can execute autocommands', function()
|
||||
meths.set_var("some_condition", false)
|
||||
|
||||
exec_lua [[
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = "Test",
|
||||
desc = "A test autocommand",
|
||||
callback = function()
|
||||
return vim.g.some_condition
|
||||
end,
|
||||
})
|
||||
]]
|
||||
|
||||
exec_lua [[ vim.autocmd.User.Test:exec() ]]
|
||||
|
||||
local aus = meths.get_autocmds({ event = 'User', pattern = 'Test' })
|
||||
local first = aus[1]
|
||||
eq(first.id, 1)
|
||||
|
||||
meths.set_var("some_condition", true)
|
||||
exec_lua [[ vim.autocmd.User.Test:exec() ]]
|
||||
eq({}, meths.get_autocmds({event = "User", pattern = "Test"}))
|
||||
end)
|
||||
|
||||
end)
|
||||
|
||||
describe('vim.augroup', function()
|
||||
it('can delete an existing group', function()
|
||||
local id = meths.create_augroup('nvim_test_augroup', { clear = true })
|
||||
meths.create_autocmd('User', {
|
||||
group = id,
|
||||
pattern = "Test",
|
||||
desc = "A test autocommand",
|
||||
command = 'echo "Test!"',
|
||||
})
|
||||
local aus = meths.get_autocmds({ group = 'nvim_test_augroup' })
|
||||
eq(1, #aus)
|
||||
exec_lua [[ vim.augroup.nvim_test_augroup:del() ]]
|
||||
local success = exec_lua [[
|
||||
return pcall(vim.api.nvim_get_autocmds, { group = 'nvim_test_augroup' })
|
||||
]]
|
||||
eq(false, success)
|
||||
end)
|
||||
|
||||
describe('Augroup:create()', function()
|
||||
it('can create a group and return its id', function()
|
||||
local id = exec_lua [[ return vim.augroup.nvim_test_augroup:create() ]]
|
||||
meths.create_autocmd('User', {
|
||||
group = id,
|
||||
pattern = "Test",
|
||||
desc = "A test autocommand",
|
||||
command = 'echo "Test!"',
|
||||
})
|
||||
local aus = meths.get_autocmds({ group = id })
|
||||
eq(1, #aus)
|
||||
end)
|
||||
|
||||
pending('can return the id of an existing group')
|
||||
pending('does not clear an existing group')
|
||||
end)
|
||||
|
||||
describe('Augroup:clear()', function()
|
||||
pending('clears autocommands in the group')
|
||||
pending('can be called with a dictionary of autocommand options')
|
||||
pending('can create the group when called without arguments')
|
||||
end)
|
||||
|
||||
describe('Augroup:get()', function()
|
||||
pending('can return a list of autocommands in the group')
|
||||
pending('can be called with a dictionary of autocommand options')
|
||||
pending('returns nil when called without arguments on a nonexistant group')
|
||||
end)
|
||||
|
||||
describe('Augroup:__call()', function()
|
||||
it('can create a group and define its autocommands', function()
|
||||
exec_lua [[
|
||||
vim.augroup.nvim_test_augroup(function(au)
|
||||
au.UIEnter(":echo 'Hello!'")
|
||||
au.User.Test(":echo 'Test!'")
|
||||
au.InsertEnter['*'](":echo 'Test!'")
|
||||
end)
|
||||
]]
|
||||
local aus = meths.get_autocmds({ group = 'nvim_test_augroup' })
|
||||
eq(3, #aus)
|
||||
end)
|
||||
|
||||
pending('can add autocommands to an existing group')
|
||||
pending('returns the group id and any values returned from the function')
|
||||
end)
|
||||
end)
|
Loading…
Reference in New Issue
Block a user