local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local command = helpers.command local eq = helpers.eq local neq = helpers.neq local exec_lua = helpers.exec_lua local matches = helpers.matches local meths = helpers.meths local source = helpers.source local pcall_err = helpers.pcall_err before_each(clear) describe('autocmd api', function() describe('nvim_create_autocmd', function() it('"command" and "callback" are mutually exclusive', function() local rv = pcall_err(meths.create_autocmd, "BufReadPost", { pattern = "*.py,*.pyi", command = "echo 'Should Have Errored", callback = "NotAllowed", }) eq("specify either 'callback' or 'command', not both", rv) end) it('doesnt leak when you use ++once', function() eq(1, exec_lua([[ local count = 0 vim.api.nvim_create_autocmd("FileType", { pattern = "*", callback = function() count = count + 1 end, once = true }) vim.cmd "set filetype=txt" vim.cmd "set filetype=python" return count ]], {})) end) it('allows passing buffer by key', function() meths.set_var('called', 0) meths.create_autocmd("FileType", { command = "let g:called = g:called + 1", buffer = 0, }) meths.command "set filetype=txt" eq(1, meths.get_var('called')) -- switch to a new buffer meths.command "new" meths.command "set filetype=python" eq(1, meths.get_var('called')) end) it('does not allow passing buffer and patterns', function() local rv = pcall_err(meths.create_autocmd, "Filetype", { command = "let g:called = g:called + 1", buffer = 0, pattern = "*.py", }) eq("cannot pass both: 'pattern' and 'buffer' for the same autocmd", rv) end) it('does not allow passing invalid buffers', function() local ok, msg = pcall(meths.create_autocmd, "Filetype", { command = "let g:called = g:called + 1", buffer = -1, }) eq(false, ok) matches('Invalid buffer id', msg) end) it('errors on non-functions for cb', function() eq(false, pcall(exec_lua, [[ vim.api.nvim_create_autocmd("BufReadPost", { pattern = "*.py,*.pyi", callback = 5, }) ]])) end) it('allow passing pattern and in same pattern', function() local ok = pcall(meths.create_autocmd, "BufReadPost", { pattern = "*.py,", command = "echo 'Should Not Error'" }) eq(true, ok) end) it('should handle multiple values as comma separated list', function() meths.create_autocmd("BufReadPost", { pattern = "*.py,*.pyi", command = "echo 'Should Not Have Errored'" }) -- We should have one autocmd for *.py and one for *.pyi eq(2, #meths.get_autocmds { event = "BufReadPost" }) end) it('should handle multiple values as array', function() meths.create_autocmd("BufReadPost", { pattern = { "*.py", "*.pyi", }, command = "echo 'Should Not Have Errored'" }) -- We should have one autocmd for *.py and one for *.pyi eq(2, #meths.get_autocmds { event = "BufReadPost" }) end) describe('desc', function() it('can add description to one autocmd', function() local cmd = "echo 'Should Not Have Errored'" local desc = "Can show description" meths.create_autocmd("BufReadPost", { pattern = "*.py", command = cmd, desc = desc, }) eq(desc, meths.get_autocmds { event = "BufReadPost" }[1].desc) eq(cmd, meths.get_autocmds { event = "BufReadPost" }[1].command) end) it('can add description to one autocmd that uses a callback', function() local desc = 'Can show description' meths.set_var('desc', desc) local result = exec_lua([[ local callback = function() print 'Should Not Have Errored' end vim.api.nvim_create_autocmd("BufReadPost", { pattern = "*.py", callback = callback, desc = vim.g.desc, }) local aus = vim.api.nvim_get_autocmds({ event = 'BufReadPost' }) local first = aus[1] return { desc = first.desc, cbtype = type(first.callback) } ]]) eq({ desc = desc, cbtype = 'function' }, result) end) it('will not add a description unless it was provided', function() exec_lua([[ local callback = function() print 'Should Not Have Errored' end vim.api.nvim_create_autocmd("BufReadPost", { pattern = "*.py", callback = callback, }) ]]) eq(nil, meths.get_autocmds({ event = 'BufReadPost' })[1].desc) end) it('can add description to multiple autocmd', function() meths.create_autocmd("BufReadPost", { pattern = {"*.py", "*.pyi"}, command = "echo 'Should Not Have Errored'", desc = "Can show description", }) local aus = meths.get_autocmds { event = "BufReadPost" } eq(2, #aus) eq("Can show description", aus[1].desc) eq("Can show description", aus[2].desc) end) end) pending('script and verbose settings', function() it('marks API client', function() meths.create_autocmd("BufReadPost", { pattern = "*.py", command = "echo 'Should Not Have Errored'", desc = "Can show description", }) local aus = meths.get_autocmds { event = "BufReadPost" } eq(1, #aus, aus) end) end) it('removes an autocommand if the callback returns true', 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, }) ]] meths.exec_autocmds("User", {pattern = "Test"}) local aus = meths.get_autocmds({ event = 'User', pattern = 'Test' }) local first = aus[1] eq(first.id, 1) meths.set_var("some_condition", true) meths.exec_autocmds("User", {pattern = "Test"}) eq({}, meths.get_autocmds({event = "User", pattern = "Test"})) end) it('receives an args table', function() local res = exec_lua [[ local group_id = vim.api.nvim_create_augroup("TestGroup", {}) local autocmd_id = vim.api.nvim_create_autocmd("User", { group = "TestGroup", pattern = "Te*", callback = function(args) vim.g.autocmd_args = args end, }) return {group_id, autocmd_id} ]] meths.exec_autocmds("User", {pattern = "Test pattern"}) eq({ id = res[2], group = res[1], event = "User", match = "Test pattern", file = "Test pattern", buf = 1, }, meths.get_var("autocmd_args")) -- Test without a group res = exec_lua [[ local autocmd_id = vim.api.nvim_create_autocmd("User", { pattern = "*", callback = function(args) vim.g.autocmd_args = args end, }) return {autocmd_id} ]] meths.exec_autocmds("User", {pattern = "some_pat"}) eq({ id = res[1], group = nil, event = "User", match = "some_pat", file = "some_pat", buf = 1, }, meths.get_var("autocmd_args")) end) it('can receive arbitrary data', function() local function test(data) eq(data, exec_lua([[ local input = ... local output vim.api.nvim_create_autocmd("User", { pattern = "Test", callback = function(args) output = args.data end, }) vim.api.nvim_exec_autocmds("User", { pattern = "Test", data = input, }) return output ]], data)) end test("Hello") test(42) test(true) test({ "list" }) test({ foo = "bar" }) end) end) describe('nvim_get_autocmds', function() describe('events', function() it('should return one autocmd when there is only one for an event', function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "1"]] local aus = meths.get_autocmds { event = "InsertEnter" } eq(1, #aus) end) it('should return two autocmds when there are two for an event', function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "1"]] command [[au InsertEnter * :echo "2"]] local aus = meths.get_autocmds { event = "InsertEnter" } eq(2, #aus) end) it('should return the same thing if you use string or list', function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "1"]] command [[au InsertEnter * :echo "2"]] local string_aus = meths.get_autocmds { event = "InsertEnter" } local array_aus = meths.get_autocmds { event = { "InsertEnter" } } eq(string_aus, array_aus) end) it('should return two autocmds when there are two for an event', function() command [[au! InsertEnter]] command [[au! InsertLeave]] command [[au InsertEnter * :echo "1"]] command [[au InsertEnter * :echo "2"]] local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } eq(2, #aus) end) it('should return different IDs for different autocmds', function() command [[au! InsertEnter]] command [[au! InsertLeave]] command [[au InsertEnter * :echo "1"]] source [[ call nvim_create_autocmd("InsertLeave", #{ \ command: ":echo 2", \ }) ]] local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } local first = aus[1] eq(first.id, nil) -- TODO: Maybe don't have this number, just assert it's not nil local second = aus[2] neq(second.id, nil) meths.del_autocmd(second.id) local new_aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } eq(1, #new_aus) eq(first, new_aus[1]) end) it('should return event name', function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "1"]] local aus = meths.get_autocmds { event = "InsertEnter" } eq({ { buflocal = false, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "*" } }, aus) end) it('should work with buffer numbers', function() command [[new]] command [[au! InsertEnter]] command [[au InsertEnter :echo "1"]] command [[au InsertEnter :echo "2"]] local aus = meths.get_autocmds { event = "InsertEnter", buffer = 0 } eq({{ buffer = 2, buflocal = true, command = ':echo "2"', event = 'InsertEnter', once = false, pattern = '', }}, aus) aus = meths.get_autocmds { event = "InsertEnter", buffer = 1 } eq({{ buffer = 1, buflocal = true, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "", }}, aus) aus = meths.get_autocmds { event = "InsertEnter", buffer = { 1, 2 } } eq({{ buffer = 1, buflocal = true, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "", }, { buffer = 2, buflocal = true, command = ':echo "2"', event = "InsertEnter", once = false, pattern = "", }}, aus) eq("Invalid value for 'buffer': must be an integer or array of integers", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = "foo" })) eq("Invalid value for 'buffer': must be an integer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { "foo", 42 } })) eq("Invalid buffer id: 42", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { 42 } })) local bufs = {} for _ = 1, 257 do table.insert(bufs, meths.create_buf(true, false)) end eq("Too many buffers. Please limit yourself to 256 or fewer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs })) end) it('should return autocmds when group is specified by id', function() local auid = meths.create_augroup("nvim_test_augroup", { clear = true }) meths.create_autocmd("FileType", { group = auid, command = 'echo "1"' }) meths.create_autocmd("FileType", { group = auid, command = 'echo "2"' }) local aus = meths.get_autocmds { group = auid } eq(2, #aus) local aus2 = meths.get_autocmds { group = auid, event = "InsertEnter" } eq(0, #aus2) end) it('should return autocmds when group is specified by name', function() local auname = "nvim_test_augroup" meths.create_augroup(auname, { clear = true }) meths.create_autocmd("FileType", { group = auname, command = 'echo "1"' }) meths.create_autocmd("FileType", { group = auname, command = 'echo "2"' }) local aus = meths.get_autocmds { group = auname } eq(2, #aus) local aus2 = meths.get_autocmds { group = auname, event = "InsertEnter" } eq(0, #aus2) end) it('should respect nested', function() local bufs = exec_lua [[ local count = 0 vim.api.nvim_create_autocmd("BufNew", { once = false, nested = true, callback = function() count = count + 1 if count > 5 then return true end vim.cmd(string.format("new README_%s.md", count)) end }) vim.cmd "new First.md" return vim.api.nvim_list_bufs() ]] -- 1 for the first buffer -- 2 for First.md -- 3-7 for the 5 we make in the autocmd eq({1, 2, 3, 4, 5, 6, 7}, bufs) end) it('can retrieve a callback from an autocmd', function() local content = 'I Am A Callback' meths.set_var('content', content) local result = exec_lua([[ local cb = function() return vim.g.content end vim.api.nvim_create_autocmd("User", { pattern = "TestTrigger", desc = "A test autocommand with a callback", callback = cb, }) local aus = vim.api.nvim_get_autocmds({ event = 'User', pattern = 'TestTrigger'}) local first = aus[1] return { cb = { type = type(first.callback), can_retrieve = first.callback() == vim.g.content } } ]]) eq("function", result.cb.type) eq(true, result.cb.can_retrieve) end) it('will return an empty string as the command for an autocmd that uses a callback', function() local result = exec_lua([[ local callback = function() print 'I Am A Callback' end vim.api.nvim_create_autocmd("BufWritePost", { pattern = "*.py", callback = callback, }) local aus = vim.api.nvim_get_autocmds({ event = 'BufWritePost' }) local first = aus[1] return { command = first.command, cbtype = type(first.callback) } ]]) eq({ command = "", cbtype = 'function' }, result) end) end) describe('groups', function() before_each(function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "No Group"]] command [[augroup GroupOne]] command [[ au InsertEnter * :echo "GroupOne:1"]] command [[augroup END]] command [[augroup GroupTwo]] command [[ au InsertEnter * :echo "GroupTwo:2"]] command [[ au InsertEnter * :echo "GroupTwo:3"]] command [[augroup END]] end) it('should return all groups if no group is specified', function() local aus = meths.get_autocmds { event = "InsertEnter" } if #aus ~= 4 then eq({}, aus) end eq(4, #aus) end) it('should return only the group specified', function() local aus = meths.get_autocmds { event = "InsertEnter", group = "GroupOne", } eq(1, #aus) eq([[:echo "GroupOne:1"]], aus[1].command) eq("GroupOne", aus[1].group_name) end) it('should return only the group specified, multiple values', function() local aus = meths.get_autocmds { event = "InsertEnter", group = "GroupTwo", } eq(2, #aus) eq([[:echo "GroupTwo:2"]], aus[1].command) eq("GroupTwo", aus[1].group_name) eq([[:echo "GroupTwo:3"]], aus[2].command) eq("GroupTwo", aus[2].group_name) end) end) describe('groups: 2', function() it('raises error for undefined augroup name', function() local success, code = unpack(meths.exec_lua([[ return {pcall(function() vim.api.nvim_create_autocmd("FileType", { pattern = "*", group = "NotDefined", command = "echo 'hello'", }) end)} ]], {})) eq(false, success) matches('invalid augroup: NotDefined', code) end) it('raises error for undefined augroup id', function() local success, code = unpack(meths.exec_lua([[ return {pcall(function() -- Make sure the augroup is deleted vim.api.nvim_del_augroup_by_id(1) vim.api.nvim_create_autocmd("FileType", { pattern = "*", group = 1, command = "echo 'hello'", }) end)} ]], {})) eq(false, success) matches('invalid augroup: 1', code) end) it('raises error for invalid group type', function() local success, code = unpack(meths.exec_lua([[ return {pcall(function() vim.api.nvim_create_autocmd("FileType", { pattern = "*", group = true, command = "echo 'hello'", }) end)} ]], {})) eq(false, success) matches("'group' must be a string or an integer", code) end) it('raises error for invalid pattern array', function() local success, code = unpack(meths.exec_lua([[ return {pcall(function() vim.api.nvim_create_autocmd("FileType", { pattern = {{}}, command = "echo 'hello'", }) end)} ]], {})) eq(false, success) matches("All entries in 'pattern' must be strings", code) end) end) describe('patterns', function() before_each(function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "No Group"]] command [[au InsertEnter *.one :echo "GroupOne:1"]] command [[au InsertEnter *.two :echo "GroupTwo:2"]] command [[au InsertEnter *.two :echo "GroupTwo:3"]] command [[au InsertEnter :echo "Buffer"]] end) it('should should return for literal match', function() local aus = meths.get_autocmds { event = "InsertEnter", pattern = "*" } eq(1, #aus) eq([[:echo "No Group"]], aus[1].command) end) it('should return for multiple matches', function() -- vim.api.nvim_get_autocmds local aus = meths.get_autocmds { event = "InsertEnter", pattern = { "*.one", "*.two" }, } eq(3, #aus) eq([[:echo "GroupOne:1"]], aus[1].command) eq([[:echo "GroupTwo:2"]], aus[2].command) eq([[:echo "GroupTwo:3"]], aus[3].command) end) it('should work for buffer autocmds', function() local normalized_aus = meths.get_autocmds { event = "InsertEnter", pattern = "", } local raw_aus = meths.get_autocmds { event = "InsertEnter", pattern = "", } local zero_aus = meths.get_autocmds { event = "InsertEnter", pattern = "", } eq(normalized_aus, raw_aus) eq(normalized_aus, zero_aus) eq([[:echo "Buffer"]], normalized_aus[1].command) end) end) end) describe('nvim_exec_autocmds', function() it("can trigger builtin autocmds", function() meths.set_var("autocmd_executed", false) meths.create_autocmd("BufReadPost", { pattern = "*", command = "let g:autocmd_executed = v:true", }) eq(false, meths.get_var("autocmd_executed")) meths.exec_autocmds("BufReadPost", {}) eq(true, meths.get_var("autocmd_executed")) end) it("can trigger multiple patterns", function() meths.set_var("autocmd_executed", 0) meths.create_autocmd("BufReadPost", { pattern = "*", command = "let g:autocmd_executed += 1", }) meths.exec_autocmds("BufReadPost", { pattern = { "*.lua", "*.vim" } }) eq(2, meths.get_var("autocmd_executed")) meths.create_autocmd("BufReadPre", { pattern = { "bar", "foo" }, command = "let g:autocmd_executed += 10", }) meths.exec_autocmds("BufReadPre", { pattern = { "foo", "bar", "baz", "frederick" }}) eq(22, meths.get_var("autocmd_executed")) end) it("can pass the buffer", function() meths.set_var("buffer_executed", -1) eq(-1, meths.get_var("buffer_executed")) meths.create_autocmd("BufLeave", { pattern = "*", command = 'let g:buffer_executed = +expand("")', }) -- Doesn't execute for other non-matching events meths.exec_autocmds("CursorHold", { buffer = 1 }) eq(-1, meths.get_var("buffer_executed")) meths.exec_autocmds("BufLeave", { buffer = 1 }) eq(1, meths.get_var("buffer_executed")) end) it("can pass the filename, pattern match", function() meths.set_var("filename_executed", 'none') eq('none', meths.get_var("filename_executed")) meths.create_autocmd("BufEnter", { pattern = "*.py", command = 'let g:filename_executed = expand("")', }) -- Doesn't execute for other non-matching events meths.exec_autocmds("CursorHold", { buffer = 1 }) eq('none', meths.get_var("filename_executed")) meths.command('edit __init__.py') eq('__init__.py', meths.get_var("filename_executed")) end) it('cannot pass buf and fname', function() local ok = pcall(meths.exec_autocmds, "BufReadPre", { pattern = "literally_cannot_error.rs", buffer = 1 }) eq(false, ok) end) it("can pass the filename, exact match", function() meths.set_var("filename_executed", 'none') eq('none', meths.get_var("filename_executed")) meths.command('edit other_file.txt') meths.command('edit __init__.py') eq('none', meths.get_var("filename_executed")) meths.create_autocmd("CursorHoldI", { pattern = "__init__.py", command = 'let g:filename_executed = expand("")', }) -- Doesn't execute for other non-matching events meths.exec_autocmds("CursorHoldI", { buffer = 1 }) eq('none', meths.get_var("filename_executed")) meths.exec_autocmds("CursorHoldI", { buffer = meths.get_current_buf() }) eq('__init__.py', meths.get_var("filename_executed")) -- Reset filename meths.set_var("filename_executed", 'none') meths.exec_autocmds("CursorHoldI", { pattern = '__init__.py' }) eq('__init__.py', meths.get_var("filename_executed")) end) it("works with user autocmds", function() meths.set_var("matched", 'none') meths.create_autocmd("User", { pattern = "TestCommand", command = 'let g:matched = "matched"' }) meths.exec_autocmds("User", { pattern = "OtherCommand" }) eq('none', meths.get_var('matched')) meths.exec_autocmds("User", { pattern = "TestCommand" }) eq('matched', meths.get_var('matched')) end) it('can pass group by id', function() meths.set_var("group_executed", false) local auid = meths.create_augroup("nvim_test_augroup", { clear = true }) meths.create_autocmd("FileType", { group = auid, command = 'let g:group_executed = v:true', }) eq(false, meths.get_var("group_executed")) meths.exec_autocmds("FileType", { group = auid }) eq(true, meths.get_var("group_executed")) end) it('can pass group by name', function() meths.set_var("group_executed", false) local auname = "nvim_test_augroup" meths.create_augroup(auname, { clear = true }) meths.create_autocmd("FileType", { group = auname, command = 'let g:group_executed = v:true', }) eq(false, meths.get_var("group_executed")) meths.exec_autocmds("FileType", { group = auname }) eq(true, meths.get_var("group_executed")) end) end) describe('nvim_create_augroup', function() before_each(function() clear() meths.set_var('executed', 0) end) local make_counting_autocmd = function(opts) opts = opts or {} local resulting = { pattern = "*", command = "let g:executed = g:executed + 1", } resulting.group = opts.group resulting.once = opts.once meths.create_autocmd("FileType", resulting) end local set_ft = function(ft) ft = ft or "txt" source(string.format("set filetype=%s", ft)) end local get_executed_count = function() return meths.get_var('executed') end it('can be added in a group', function() local augroup = "TestGroup" meths.create_augroup(augroup, { clear = true }) make_counting_autocmd { group = augroup } set_ft("txt") set_ft("python") eq(2, get_executed_count()) end) it('works getting called multiple times', function() make_counting_autocmd() set_ft() set_ft() set_ft() eq(3, get_executed_count()) end) it('handles ++once', function() make_counting_autocmd {once = true} set_ft('txt') set_ft('help') set_ft('txt') set_ft('help') eq(1, get_executed_count()) end) it('errors on unexpected keys', function() local success, code = pcall(meths.create_autocmd, "FileType", { pattern = "*", not_a_valid_key = "NotDefined", }) eq(false, success) matches('not_a_valid_key', code) end) it('can execute simple callback', function() exec_lua([[ vim.g.executed = false vim.api.nvim_create_autocmd("FileType", { pattern = "*", callback = function() vim.g.executed = true end, }) ]], {}) eq(true, exec_lua([[ vim.cmd "set filetype=txt" return vim.g.executed ]], {})) end) it('calls multiple lua callbacks for the same autocmd execution', function() eq(4, exec_lua([[ local count = 0 local counter = function() count = count + 1 end vim.api.nvim_create_autocmd("FileType", { pattern = "*", callback = counter, }) vim.api.nvim_create_autocmd("FileType", { pattern = "*", callback = counter, }) vim.cmd "set filetype=txt" vim.cmd "set filetype=txt" return count ]], {})) end) it('properly releases functions with ++once', function() exec_lua([[ WeakTable = setmetatable({}, { __mode = "k" }) OnceCount = 0 MyVal = {} WeakTable[MyVal] = true vim.api.nvim_create_autocmd("FileType", { pattern = "*", callback = function() OnceCount = OnceCount + 1 MyVal = {} end, once = true }) ]]) command [[set filetype=txt]] eq(1, exec_lua([[return OnceCount]], {})) exec_lua([[collectgarbage()]], {}) command [[set filetype=txt]] eq(1, exec_lua([[return OnceCount]], {})) eq(0, exec_lua([[ local count = 0 for _ in pairs(WeakTable) do count = count + 1 end return count ]]), "Should have no keys remaining") end) it('groups can be cleared', function() local augroup = "TestGroup" meths.create_augroup(augroup, { clear = true }) meths.create_autocmd("FileType", { group = augroup, command = "let g:executed = g:executed + 1" }) set_ft("txt") set_ft("txt") eq(2, get_executed_count(), "should only count twice") meths.create_augroup(augroup, { clear = true }) eq({}, meths.get_autocmds { group = augroup }) set_ft("txt") set_ft("txt") eq(2, get_executed_count(), "No additional counts") end) it('can delete non-existent groups with pcall', function() eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_name, 'noexist')]]) eq('Vim:E367: No such group: "noexist"', pcall_err(meths.del_augroup_by_name, 'noexist')) eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_id, -12342)]]) eq('Vim:E367: No such group: "--Deleted--"', pcall_err(meths.del_augroup_by_id, -12312)) end) it('groups work with once', function() local augroup = "TestGroup" meths.create_augroup(augroup, { clear = true }) make_counting_autocmd { group = augroup, once = true } set_ft("txt") set_ft("python") eq(1, get_executed_count()) end) it('autocmds can be registered multiple times.', function() local augroup = "TestGroup" meths.create_augroup(augroup, { clear = true }) make_counting_autocmd { group = augroup, once = false } make_counting_autocmd { group = augroup, once = false } make_counting_autocmd { group = augroup, once = false } set_ft("txt") set_ft("python") eq(3 * 2, get_executed_count()) end) it('can be deleted', function() local augroup = "WillBeDeleted" meths.create_augroup(augroup, { clear = true }) meths.create_autocmd({"Filetype"}, { pattern = "*", command = "echo 'does not matter'", }) -- Clears the augroup from before, which erases the autocmd meths.create_augroup(augroup, { clear = true }) local result = #meths.get_autocmds { group = augroup } eq(0, result) end) it('can be used for buffer local autocmds', function() local augroup = "WillBeDeleted" meths.set_var("value_set", false) meths.create_augroup(augroup, { clear = true }) meths.create_autocmd("Filetype", { pattern = "", command = "let g:value_set = v:true", }) command "new" command "set filetype=python" eq(false, meths.get_var("value_set")) end) it('can accept vimscript functions', function() source [[ let g:vimscript_executed = 0 function! MyVimscriptFunction() abort let g:vimscript_executed = g:vimscript_executed + 1 endfunction call nvim_create_autocmd("FileType", #{ \ pattern: ["python", "javascript"], \ callback: "MyVimscriptFunction", \ }) set filetype=txt set filetype=python set filetype=txt set filetype=javascript set filetype=txt ]] eq(2, meths.get_var("vimscript_executed")) end) end) describe('augroup!', function() it('legacy: should clear and not return any autocmds for delete groups', function() command('augroup TEMP_A') command(' autocmd! BufReadPost *.py :echo "Hello"') command('augroup END') command('augroup! TEMP_A') eq(false, pcall(meths.get_autocmds, { group = 'TEMP_A' })) -- For some reason, augroup! doesn't clear the autocmds themselves, which is just wild -- but we managed to keep this behavior. eq(1, #meths.get_autocmds { event = 'BufReadPost' }) end) it('legacy: remove augroups that have no autocmds', function() command('augroup TEMP_AB') command('augroup END') command('augroup! TEMP_AB') eq(false, pcall(meths.get_autocmds, { group = 'TEMP_AB' })) eq(0, #meths.get_autocmds { event = 'BufReadPost' }) end) it('legacy: multiple remove and add augroup', function() command('augroup TEMP_ABC') command(' au!') command(' autocmd BufReadPost *.py echo "Hello"') command('augroup END') command('augroup! TEMP_ABC') -- Should still have one autocmd :'( local aus = meths.get_autocmds { event = 'BufReadPost' } eq(1, #aus, aus) command('augroup TEMP_ABC') command(' au!') command(' autocmd BufReadPost *.py echo "Hello"') command('augroup END') -- Should now have two autocmds :'( aus = meths.get_autocmds { event = 'BufReadPost' } eq(2, #aus, aus) command('augroup! TEMP_ABC') eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABC' })) eq(2, #meths.get_autocmds { event = 'BufReadPost' }) end) it('api: should clear and not return any autocmds for delete groups by id', function() command('augroup TEMP_ABCD') command('autocmd! BufReadPost *.py :echo "Hello"') command('augroup END') local augroup_id = meths.create_augroup("TEMP_ABCD", { clear = false }) meths.del_augroup_by_id(augroup_id) -- For good reason, we kill all the autocmds from del_augroup, -- so now this works as expected eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCD' })) eq(0, #meths.get_autocmds { event = 'BufReadPost' }) end) it('api: should clear and not return any autocmds for delete groups by name', function() command('augroup TEMP_ABCDE') command('autocmd! BufReadPost *.py :echo "Hello"') command('augroup END') meths.del_augroup_by_name("TEMP_ABCDE") -- For good reason, we kill all the autocmds from del_augroup, -- so now this works as expected eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCDE' })) eq(0, #meths.get_autocmds { event = 'BufReadPost' }) end) end) describe('nvim_clear_autocmds', function() it('should clear based on event + pattern', function() command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"') command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"') local search = { event = "InsertEnter", pattern = "*.txt" } local before_delete = meths.get_autocmds(search) eq(1, #before_delete) local before_delete_all = meths.get_autocmds { event = search.event } eq(2, #before_delete_all) meths.clear_autocmds(search) local after_delete = meths.get_autocmds(search) eq(0, #after_delete) local after_delete_all = meths.get_autocmds { event = search.event } eq(1, #after_delete_all) end) it('should clear based on event', function() command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"') command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"') local search = { event = "InsertEnter"} local before_delete = meths.get_autocmds(search) eq(2, #before_delete) meths.clear_autocmds(search) local after_delete = meths.get_autocmds(search) eq(0, #after_delete) end) it('should clear based on pattern', function() command('autocmd InsertEnter *.TestPat1 :echo "Enter 1"') command('autocmd InsertLeave *.TestPat1 :echo "Leave 1"') command('autocmd InsertEnter *.TestPat2 :echo "Enter 2"') command('autocmd InsertLeave *.TestPat2 :echo "Leave 2"') local search = { pattern = "*.TestPat1"} local before_delete = meths.get_autocmds(search) eq(2, #before_delete) local before_delete_events = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } eq(4, #before_delete_events) meths.clear_autocmds(search) local after_delete = meths.get_autocmds(search) eq(0, #after_delete) local after_delete_events = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } eq(2, #after_delete_events) end) it('should allow clearing by buffer', function() command('autocmd! InsertEnter') command('autocmd InsertEnter :echo "Enter Buffer"') command('autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"') local search = { event = "InsertEnter" } local before_delete = meths.get_autocmds(search) eq(2, #before_delete) meths.clear_autocmds { buffer = 0 } local after_delete = meths.get_autocmds(search) eq(1, #after_delete) eq("*.TestPat1", after_delete[1].pattern) end) it('should allow clearing by buffer and group', function() command('augroup TestNvimClearAutocmds') command(' au!') command(' autocmd InsertEnter :echo "Enter Buffer"') command(' autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"') command('augroup END') local search = { event = "InsertEnter", group = "TestNvimClearAutocmds" } local before_delete = meths.get_autocmds(search) eq(2, #before_delete) -- Doesn't clear without passing group. meths.clear_autocmds { buffer = 0 } local without_group = meths.get_autocmds(search) eq(2, #without_group) -- Doest clear with passing group. meths.clear_autocmds { buffer = 0, group = search.group } local with_group = meths.get_autocmds(search) eq(1, #with_group) end) end) end)