autocmd_spec.lua 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local clear = n.clear
  4. local command = n.command
  5. local eq = t.eq
  6. local neq = t.neq
  7. local exec_lua = n.exec_lua
  8. local matches = t.matches
  9. local api = n.api
  10. local source = n.source
  11. local pcall_err = t.pcall_err
  12. before_each(clear)
  13. describe('autocmd api', function()
  14. describe('nvim_create_autocmd', function()
  15. it('validation', function()
  16. eq(
  17. "Cannot use both 'callback' and 'command'",
  18. pcall_err(api.nvim_create_autocmd, 'BufReadPost', {
  19. pattern = '*.py,*.pyi',
  20. command = "echo 'Should Have Errored",
  21. callback = 'NotAllowed',
  22. })
  23. )
  24. eq(
  25. "Cannot use both 'pattern' and 'buffer' for the same autocmd",
  26. pcall_err(api.nvim_create_autocmd, 'FileType', {
  27. command = 'let g:called = g:called + 1',
  28. buffer = 0,
  29. pattern = '*.py',
  30. })
  31. )
  32. eq(
  33. "Required: 'event'",
  34. pcall_err(api.nvim_create_autocmd, {}, {
  35. command = 'ls',
  36. })
  37. )
  38. eq("Required: 'command' or 'callback'", pcall_err(api.nvim_create_autocmd, 'FileType', {}))
  39. eq(
  40. "Invalid 'desc': expected String, got Integer",
  41. pcall_err(api.nvim_create_autocmd, 'FileType', {
  42. command = 'ls',
  43. desc = 42,
  44. })
  45. )
  46. eq(
  47. "Invalid 'callback': expected Lua function or Vim function name, got Integer",
  48. pcall_err(api.nvim_create_autocmd, 'FileType', {
  49. callback = 0,
  50. })
  51. )
  52. eq(
  53. "Invalid 'event' item: expected String, got Array",
  54. pcall_err(api.nvim_create_autocmd, { 'FileType', {} }, {})
  55. )
  56. eq(
  57. "Invalid 'group': 0",
  58. pcall_err(api.nvim_create_autocmd, 'FileType', {
  59. group = 0,
  60. command = 'ls',
  61. })
  62. )
  63. eq("Invalid 'event': 'foo'", pcall_err(api.nvim_create_autocmd, 'foo', { command = '' }))
  64. eq(
  65. "Invalid 'event': 'VimEnter '",
  66. pcall_err(api.nvim_create_autocmd, 'VimEnter ', { command = '' })
  67. )
  68. eq(
  69. "Invalid 'event': 'VimEnter foo'",
  70. pcall_err(api.nvim_create_autocmd, 'VimEnter foo', { command = '' })
  71. )
  72. eq(
  73. "Invalid 'event': 'BufAdd,BufDelete'",
  74. pcall_err(api.nvim_create_autocmd, 'BufAdd,BufDelete', { command = '' })
  75. )
  76. end)
  77. it('doesnt leak when you use ++once', function()
  78. eq(
  79. 1,
  80. exec_lua(
  81. [[
  82. local count = 0
  83. vim.api.nvim_create_autocmd("FileType", {
  84. pattern = "*",
  85. callback = function() count = count + 1 end,
  86. once = true
  87. })
  88. vim.cmd "set filetype=txt"
  89. vim.cmd "set filetype=python"
  90. return count
  91. ]],
  92. {}
  93. )
  94. )
  95. end)
  96. it('allows passing buffer by key', function()
  97. api.nvim_set_var('called', 0)
  98. api.nvim_create_autocmd('FileType', {
  99. command = 'let g:called = g:called + 1',
  100. buffer = 0,
  101. })
  102. command 'set filetype=txt'
  103. eq(1, api.nvim_get_var('called'))
  104. -- switch to a new buffer
  105. command 'new'
  106. command 'set filetype=python'
  107. eq(1, api.nvim_get_var('called'))
  108. end)
  109. it('does not allow passing invalid buffers', function()
  110. local ok, msg = pcall(api.nvim_create_autocmd, 'FileType', {
  111. command = 'let g:called = g:called + 1',
  112. buffer = -1,
  113. })
  114. eq(false, ok)
  115. matches('Invalid buffer id', msg)
  116. end)
  117. it('errors on non-functions for cb', function()
  118. eq(
  119. false,
  120. pcall(
  121. exec_lua,
  122. [[
  123. vim.api.nvim_create_autocmd("BufReadPost", {
  124. pattern = "*.py,*.pyi",
  125. callback = 5,
  126. })
  127. ]]
  128. )
  129. )
  130. end)
  131. it('allow passing pattern and <buffer> in same pattern', function()
  132. local ok = pcall(api.nvim_create_autocmd, 'BufReadPost', {
  133. pattern = '*.py,<buffer>',
  134. command = "echo 'Should Not Error'",
  135. })
  136. eq(true, ok)
  137. end)
  138. it('should handle multiple values as comma separated list', function()
  139. api.nvim_create_autocmd('BufReadPost', {
  140. pattern = '*.py,*.pyi',
  141. command = "echo 'Should Not Have Errored'",
  142. })
  143. -- We should have one autocmd for *.py and one for *.pyi
  144. eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' })
  145. end)
  146. it('should handle multiple values as array', function()
  147. api.nvim_create_autocmd('BufReadPost', {
  148. pattern = { '*.py', '*.pyi' },
  149. command = "echo 'Should Not Have Errored'",
  150. })
  151. -- We should have one autocmd for *.py and one for *.pyi
  152. eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' })
  153. end)
  154. describe('desc', function()
  155. it('can add description to one autocmd', function()
  156. local cmd = "echo 'Should Not Have Errored'"
  157. local desc = 'Can show description'
  158. api.nvim_create_autocmd('BufReadPost', {
  159. pattern = '*.py',
  160. command = cmd,
  161. desc = desc,
  162. })
  163. eq(desc, api.nvim_get_autocmds { event = 'BufReadPost' }[1].desc)
  164. eq(cmd, api.nvim_get_autocmds { event = 'BufReadPost' }[1].command)
  165. end)
  166. it('can add description to one autocmd that uses a callback', function()
  167. local desc = 'Can show description'
  168. api.nvim_set_var('desc', desc)
  169. local result = exec_lua([[
  170. local callback = function() print 'Should Not Have Errored' end
  171. vim.api.nvim_create_autocmd("BufReadPost", {
  172. pattern = "*.py",
  173. callback = callback,
  174. desc = vim.g.desc,
  175. })
  176. local aus = vim.api.nvim_get_autocmds({ event = 'BufReadPost' })
  177. local first = aus[1]
  178. return {
  179. desc = first.desc,
  180. cbtype = type(first.callback)
  181. }
  182. ]])
  183. eq({ desc = desc, cbtype = 'function' }, result)
  184. end)
  185. it('will not add a description unless it was provided', function()
  186. exec_lua([[
  187. local callback = function() print 'Should Not Have Errored' end
  188. vim.api.nvim_create_autocmd("BufReadPost", {
  189. pattern = "*.py",
  190. callback = callback,
  191. })
  192. ]])
  193. eq(nil, api.nvim_get_autocmds({ event = 'BufReadPost' })[1].desc)
  194. end)
  195. it('can add description to multiple autocmd', function()
  196. api.nvim_create_autocmd('BufReadPost', {
  197. pattern = { '*.py', '*.pyi' },
  198. command = "echo 'Should Not Have Errored'",
  199. desc = 'Can show description',
  200. })
  201. local aus = api.nvim_get_autocmds { event = 'BufReadPost' }
  202. eq(2, #aus)
  203. eq('Can show description', aus[1].desc)
  204. eq('Can show description', aus[2].desc)
  205. end)
  206. end)
  207. pending('script and verbose settings', function()
  208. it('marks API client', function()
  209. api.nvim_create_autocmd('BufReadPost', {
  210. pattern = '*.py',
  211. command = "echo 'Should Not Have Errored'",
  212. desc = 'Can show description',
  213. })
  214. local aus = api.nvim_get_autocmds { event = 'BufReadPost' }
  215. eq(1, #aus, aus)
  216. end)
  217. end)
  218. it('removes an autocommand if the callback returns true', function()
  219. api.nvim_set_var('some_condition', false)
  220. exec_lua [[
  221. vim.api.nvim_create_autocmd("User", {
  222. pattern = "Test",
  223. desc = "A test autocommand",
  224. callback = function()
  225. return vim.g.some_condition
  226. end,
  227. })
  228. ]]
  229. api.nvim_exec_autocmds('User', { pattern = 'Test' })
  230. local aus = api.nvim_get_autocmds({ event = 'User', pattern = 'Test' })
  231. local first = aus[1]
  232. eq(true, first.id > 0)
  233. api.nvim_set_var('some_condition', true)
  234. api.nvim_exec_autocmds('User', { pattern = 'Test' })
  235. eq({}, api.nvim_get_autocmds({ event = 'User', pattern = 'Test' }))
  236. end)
  237. local function test_autocmd_args(event)
  238. local function get_amatch(pat)
  239. return event == 'User' and pat or vim.fs.normalize(n.fn.fnamemodify(pat, ':p'))
  240. end
  241. local group_id = api.nvim_create_augroup('TestGroup', {})
  242. -- Having an existing autocmd calling expand("<afile>") shouldn't change args #18964
  243. api.nvim_create_autocmd(event, {
  244. group = 'TestGroup',
  245. pattern = 'Te*',
  246. command = 'call expand("<afile>")',
  247. })
  248. local autocmd_id = exec_lua(([[
  249. return vim.api.nvim_create_autocmd(%q, {
  250. group = "TestGroup",
  251. pattern = "Te*",
  252. callback = function(args)
  253. vim.g.autocmd_args = args
  254. end,
  255. })
  256. ]]):format(event))
  257. local exec_pat = 'Test pattern'
  258. local amatch = get_amatch(exec_pat)
  259. api.nvim_exec_autocmds(event, { pattern = exec_pat })
  260. eq({
  261. id = autocmd_id,
  262. group = group_id,
  263. event = event,
  264. match = amatch,
  265. file = exec_pat,
  266. buf = 1,
  267. }, api.nvim_get_var('autocmd_args'))
  268. -- Test without a group
  269. autocmd_id = exec_lua(([[
  270. return vim.api.nvim_create_autocmd(%q, {
  271. pattern = "*",
  272. callback = function(args)
  273. vim.g.autocmd_args = args
  274. end,
  275. })
  276. ]]):format(event))
  277. exec_pat = 'some_pat'
  278. amatch = get_amatch(exec_pat)
  279. api.nvim_exec_autocmds(event, { pattern = exec_pat })
  280. eq({
  281. id = autocmd_id,
  282. group = nil,
  283. event = event,
  284. match = amatch,
  285. file = exec_pat,
  286. buf = 1,
  287. }, api.nvim_get_var('autocmd_args'))
  288. end
  289. describe('receives correct args table', function()
  290. it('for event that takes non-file pattern', function()
  291. test_autocmd_args('User')
  292. end)
  293. it('for event that takes file pattern', function()
  294. test_autocmd_args('BufEnter')
  295. end)
  296. end)
  297. it('can receive arbitrary data', function()
  298. local function test(data)
  299. eq(
  300. data,
  301. exec_lua(
  302. [[
  303. local input = ...
  304. local output
  305. vim.api.nvim_create_autocmd("User", {
  306. pattern = "Test",
  307. callback = function(args)
  308. output = args.data
  309. end,
  310. })
  311. vim.api.nvim_exec_autocmds("User", {
  312. pattern = "Test",
  313. data = input,
  314. })
  315. return output
  316. ]],
  317. data
  318. )
  319. )
  320. end
  321. test('Hello')
  322. test(42)
  323. test(true)
  324. test({ 'list' })
  325. test({ foo = 'bar' })
  326. end)
  327. it('function in arbitrary data is passed to all autocmds #28353', function()
  328. eq(
  329. 1303,
  330. exec_lua([[
  331. local res = 1
  332. local fun = function(m, x)
  333. res = res * m + x
  334. end
  335. local group = vim.api.nvim_create_augroup('MyTest', { clear = false })
  336. vim.api.nvim_create_autocmd('User', {
  337. group = group,
  338. callback = function(payload)
  339. payload.data.fun(10, payload.data.x)
  340. end,
  341. pattern = 'MyEvent',
  342. })
  343. vim.api.nvim_create_autocmd('User', {
  344. group = group,
  345. callback = function(payload)
  346. payload.data.fun(100, payload.data.x)
  347. end,
  348. pattern = 'MyEvent',
  349. })
  350. vim.api.nvim_exec_autocmds('User', {
  351. group = group,
  352. pattern = 'MyEvent',
  353. data = { x = 3, fun = fun },
  354. })
  355. return res
  356. ]])
  357. )
  358. end)
  359. end)
  360. describe('nvim_get_autocmds', function()
  361. it('validation', function()
  362. eq(
  363. "Invalid 'group': 9997999",
  364. pcall_err(api.nvim_get_autocmds, {
  365. group = 9997999,
  366. })
  367. )
  368. eq(
  369. "Invalid 'group': 'bogus'",
  370. pcall_err(api.nvim_get_autocmds, {
  371. group = 'bogus',
  372. })
  373. )
  374. eq(
  375. "Invalid 'group': 0",
  376. pcall_err(api.nvim_get_autocmds, {
  377. group = 0,
  378. })
  379. )
  380. eq(
  381. "Invalid 'group': expected String or Integer, got Array",
  382. pcall_err(api.nvim_get_autocmds, {
  383. group = {},
  384. })
  385. )
  386. eq(
  387. "Invalid 'buffer': expected Integer or Array, got Boolean",
  388. pcall_err(api.nvim_get_autocmds, {
  389. buffer = true,
  390. })
  391. )
  392. eq(
  393. "Invalid 'event': expected String or Array",
  394. pcall_err(api.nvim_get_autocmds, {
  395. event = true,
  396. })
  397. )
  398. eq(
  399. "Invalid 'pattern': expected String or Array, got Boolean",
  400. pcall_err(api.nvim_get_autocmds, {
  401. pattern = true,
  402. })
  403. )
  404. end)
  405. describe('events', function()
  406. it('returns one autocmd when there is only one for an event', function()
  407. command [[au! InsertEnter]]
  408. command [[au InsertEnter * :echo "1"]]
  409. local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
  410. eq(1, #aus)
  411. end)
  412. it('returns two autocmds when there are two for an event', function()
  413. command [[au! InsertEnter]]
  414. command [[au InsertEnter * :echo "1"]]
  415. command [[au InsertEnter * :echo "2"]]
  416. local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
  417. eq(2, #aus)
  418. end)
  419. it('returns the same thing if you use string or list', function()
  420. command [[au! InsertEnter]]
  421. command [[au InsertEnter * :echo "1"]]
  422. command [[au InsertEnter * :echo "2"]]
  423. local string_aus = api.nvim_get_autocmds { event = 'InsertEnter' }
  424. local array_aus = api.nvim_get_autocmds { event = { 'InsertEnter' } }
  425. eq(string_aus, array_aus)
  426. end)
  427. it('returns two autocmds when there are two for an event', function()
  428. command [[au! InsertEnter]]
  429. command [[au! InsertLeave]]
  430. command [[au InsertEnter * :echo "1"]]
  431. command [[au InsertEnter * :echo "2"]]
  432. local aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
  433. eq(2, #aus)
  434. end)
  435. it('returns different IDs for different autocmds', function()
  436. command [[au! InsertEnter]]
  437. command [[au! InsertLeave]]
  438. command [[au InsertEnter * :echo "1"]]
  439. source [[
  440. call nvim_create_autocmd("InsertLeave", #{
  441. \ command: ":echo 2",
  442. \ })
  443. ]]
  444. local aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
  445. local first = aus[1]
  446. eq(first.id, nil)
  447. -- TODO: Maybe don't have this number, just assert it's not nil
  448. local second = aus[2]
  449. neq(second.id, nil)
  450. api.nvim_del_autocmd(second.id)
  451. local new_aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
  452. eq(1, #new_aus)
  453. eq(first, new_aus[1])
  454. end)
  455. it('returns event name', function()
  456. command [[au! InsertEnter]]
  457. command [[au InsertEnter * :echo "1"]]
  458. local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
  459. eq({
  460. {
  461. buflocal = false,
  462. command = ':echo "1"',
  463. event = 'InsertEnter',
  464. once = false,
  465. pattern = '*',
  466. },
  467. }, aus)
  468. end)
  469. it('works with buffer numbers', function()
  470. command [[new]]
  471. command [[au! InsertEnter]]
  472. command [[au InsertEnter <buffer=1> :echo "1"]]
  473. command [[au InsertEnter <buffer=2> :echo "2"]]
  474. local aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = 0 }
  475. eq({
  476. {
  477. buffer = 2,
  478. buflocal = true,
  479. command = ':echo "2"',
  480. event = 'InsertEnter',
  481. once = false,
  482. pattern = '<buffer=2>',
  483. },
  484. }, aus)
  485. aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = 1 }
  486. eq({
  487. {
  488. buffer = 1,
  489. buflocal = true,
  490. command = ':echo "1"',
  491. event = 'InsertEnter',
  492. once = false,
  493. pattern = '<buffer=1>',
  494. },
  495. }, aus)
  496. aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = { 1, 2 } }
  497. eq({
  498. {
  499. buffer = 1,
  500. buflocal = true,
  501. command = ':echo "1"',
  502. event = 'InsertEnter',
  503. once = false,
  504. pattern = '<buffer=1>',
  505. },
  506. {
  507. buffer = 2,
  508. buflocal = true,
  509. command = ':echo "2"',
  510. event = 'InsertEnter',
  511. once = false,
  512. pattern = '<buffer=2>',
  513. },
  514. }, aus)
  515. eq(
  516. "Invalid 'buffer': expected Integer or Array, got String",
  517. pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = 'foo' })
  518. )
  519. eq(
  520. "Invalid 'buffer': expected Integer, got String",
  521. pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = { 'foo', 42 } })
  522. )
  523. eq(
  524. 'Invalid buffer id: 42',
  525. pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = { 42 } })
  526. )
  527. local bufs = {}
  528. for _ = 1, 257 do
  529. table.insert(bufs, api.nvim_create_buf(true, false))
  530. end
  531. eq(
  532. 'Too many buffers (maximum of 256)',
  533. pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = bufs })
  534. )
  535. end)
  536. it('returns autocmds when group is specified by id', function()
  537. local auid = api.nvim_create_augroup('nvim_test_augroup', { clear = true })
  538. api.nvim_create_autocmd('FileType', { group = auid, command = 'echo "1"' })
  539. api.nvim_create_autocmd('FileType', { group = auid, command = 'echo "2"' })
  540. local aus = api.nvim_get_autocmds { group = auid }
  541. eq(2, #aus)
  542. local aus2 = api.nvim_get_autocmds { group = auid, event = 'InsertEnter' }
  543. eq(0, #aus2)
  544. end)
  545. it('returns autocmds when group is specified by name', function()
  546. local auname = 'nvim_test_augroup'
  547. api.nvim_create_augroup(auname, { clear = true })
  548. api.nvim_create_autocmd('FileType', { group = auname, command = 'echo "1"' })
  549. api.nvim_create_autocmd('FileType', { group = auname, command = 'echo "2"' })
  550. local aus = api.nvim_get_autocmds { group = auname }
  551. eq(2, #aus)
  552. local aus2 = api.nvim_get_autocmds { group = auname, event = 'InsertEnter' }
  553. eq(0, #aus2)
  554. end)
  555. it('should respect nested', function()
  556. local bufs = exec_lua [[
  557. local count = 0
  558. vim.api.nvim_create_autocmd("BufNew", {
  559. once = false,
  560. nested = true,
  561. callback = function()
  562. count = count + 1
  563. if count > 5 then
  564. return true
  565. end
  566. vim.cmd(string.format("new README_%s.md", count))
  567. end
  568. })
  569. vim.cmd "new First.md"
  570. return vim.api.nvim_list_bufs()
  571. ]]
  572. -- 1 for the first buffer
  573. -- 2 for First.md
  574. -- 3-7 for the 5 we make in the autocmd
  575. eq({ 1, 2, 3, 4, 5, 6, 7 }, bufs)
  576. end)
  577. it('can retrieve a callback from an autocmd', function()
  578. local content = 'I Am A Callback'
  579. api.nvim_set_var('content', content)
  580. exec_lua([[
  581. local cb = function() return vim.g.content end
  582. vim.api.nvim_create_autocmd("User", {
  583. pattern = "TestTrigger",
  584. desc = "A test autocommand with a callback",
  585. callback = cb,
  586. })
  587. ]])
  588. local result = exec_lua([[
  589. local aus = vim.api.nvim_get_autocmds({ event = 'User', pattern = 'TestTrigger' })
  590. local first = aus[1]
  591. return {
  592. cb = {
  593. type = type(first.callback),
  594. can_retrieve = first.callback() == vim.g.content
  595. }
  596. }
  597. ]])
  598. eq({ cb = { type = 'function', can_retrieve = true } }, result)
  599. -- Also test with Vimscript
  600. source([[
  601. let s:aus = nvim_get_autocmds({'event': 'User', 'pattern': 'TestTrigger'})
  602. let g:result = s:aus[0].callback()
  603. ]])
  604. eq(content, api.nvim_get_var('result'))
  605. end)
  606. it(
  607. 'will return an empty string as the command for an autocmd that uses a callback',
  608. function()
  609. local result = exec_lua([[
  610. local callback = function() print 'I Am A Callback' end
  611. vim.api.nvim_create_autocmd("BufWritePost", {
  612. pattern = "*.py",
  613. callback = callback,
  614. })
  615. local aus = vim.api.nvim_get_autocmds({ event = 'BufWritePost' })
  616. local first = aus[1]
  617. return {
  618. command = first.command,
  619. cbtype = type(first.callback)
  620. }
  621. ]])
  622. eq({ command = '', cbtype = 'function' }, result)
  623. end
  624. )
  625. end)
  626. describe('groups', function()
  627. before_each(function()
  628. command [[au! InsertEnter]]
  629. command [[au InsertEnter * :echo "No Group"]]
  630. command [[augroup GroupOne]]
  631. command [[ au InsertEnter * :echo "GroupOne:1"]]
  632. command [[augroup END]]
  633. command [[augroup GroupTwo]]
  634. command [[ au InsertEnter * :echo "GroupTwo:2"]]
  635. command [[ au InsertEnter * :echo "GroupTwo:3"]]
  636. command [[augroup END]]
  637. end)
  638. it('returns all groups if no group is specified', function()
  639. local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
  640. if #aus ~= 4 then
  641. eq({}, aus)
  642. end
  643. eq(4, #aus)
  644. end)
  645. it('returns only the group specified', function()
  646. local aus = api.nvim_get_autocmds {
  647. event = 'InsertEnter',
  648. group = 'GroupOne',
  649. }
  650. eq(1, #aus)
  651. eq([[:echo "GroupOne:1"]], aus[1].command)
  652. eq('GroupOne', aus[1].group_name)
  653. end)
  654. it('returns only the group specified, multiple values', function()
  655. local aus = api.nvim_get_autocmds {
  656. event = 'InsertEnter',
  657. group = 'GroupTwo',
  658. }
  659. eq(2, #aus)
  660. eq([[:echo "GroupTwo:2"]], aus[1].command)
  661. eq('GroupTwo', aus[1].group_name)
  662. eq([[:echo "GroupTwo:3"]], aus[2].command)
  663. eq('GroupTwo', aus[2].group_name)
  664. end)
  665. end)
  666. describe('groups: 2', function()
  667. it('raises error for undefined augroup name', function()
  668. local success, code = unpack(api.nvim_exec_lua(
  669. [[
  670. return {pcall(function()
  671. vim.api.nvim_create_autocmd("FileType", {
  672. pattern = "*",
  673. group = "NotDefined",
  674. command = "echo 'hello'",
  675. })
  676. end)}
  677. ]],
  678. {}
  679. ))
  680. eq(false, success)
  681. matches("Invalid 'group': 'NotDefined'", code)
  682. end)
  683. it('raises error for undefined augroup id', function()
  684. local success, code = unpack(api.nvim_exec_lua(
  685. [[
  686. return {pcall(function()
  687. -- Make sure the augroup is deleted
  688. vim.api.nvim_del_augroup_by_id(1)
  689. vim.api.nvim_create_autocmd("FileType", {
  690. pattern = "*",
  691. group = 1,
  692. command = "echo 'hello'",
  693. })
  694. end)}
  695. ]],
  696. {}
  697. ))
  698. eq(false, success)
  699. matches("Invalid 'group': 1", code)
  700. end)
  701. it('raises error for invalid group type', function()
  702. local success, code = unpack(api.nvim_exec_lua(
  703. [[
  704. return {pcall(function()
  705. vim.api.nvim_create_autocmd("FileType", {
  706. pattern = "*",
  707. group = true,
  708. command = "echo 'hello'",
  709. })
  710. end)}
  711. ]],
  712. {}
  713. ))
  714. eq(false, success)
  715. matches("Invalid 'group': expected String or Integer, got Boolean", code)
  716. end)
  717. it('raises error for invalid pattern array', function()
  718. local success, code = unpack(api.nvim_exec_lua(
  719. [[
  720. return {pcall(function()
  721. vim.api.nvim_create_autocmd("FileType", {
  722. pattern = {{}},
  723. command = "echo 'hello'",
  724. })
  725. end)}
  726. ]],
  727. {}
  728. ))
  729. eq(false, success)
  730. matches("Invalid 'pattern' item: expected String, got Array", code)
  731. end)
  732. end)
  733. describe('patterns', function()
  734. before_each(function()
  735. command [[au! InsertEnter]]
  736. command [[au InsertEnter * :echo "No Group"]]
  737. command [[au InsertEnter *.one :echo "GroupOne:1"]]
  738. command [[au InsertEnter *.two :echo "GroupTwo:2"]]
  739. command [[au InsertEnter *.two :echo "GroupTwo:3"]]
  740. command [[au InsertEnter <buffer> :echo "Buffer"]]
  741. end)
  742. it('returns for literal match', function()
  743. local aus = api.nvim_get_autocmds {
  744. event = 'InsertEnter',
  745. pattern = '*',
  746. }
  747. eq(1, #aus)
  748. eq([[:echo "No Group"]], aus[1].command)
  749. end)
  750. it('returns for multiple matches', function()
  751. -- vim.api.nvim_get_autocmds
  752. local aus = api.nvim_get_autocmds {
  753. event = 'InsertEnter',
  754. pattern = { '*.one', '*.two' },
  755. }
  756. eq(3, #aus)
  757. eq([[:echo "GroupOne:1"]], aus[1].command)
  758. eq([[:echo "GroupTwo:2"]], aus[2].command)
  759. eq([[:echo "GroupTwo:3"]], aus[3].command)
  760. end)
  761. it('should work for buffer autocmds', function()
  762. local normalized_aus = api.nvim_get_autocmds {
  763. event = 'InsertEnter',
  764. pattern = '<buffer=1>',
  765. }
  766. local raw_aus = api.nvim_get_autocmds {
  767. event = 'InsertEnter',
  768. pattern = '<buffer>',
  769. }
  770. local zero_aus = api.nvim_get_autocmds {
  771. event = 'InsertEnter',
  772. pattern = '<buffer=0>',
  773. }
  774. eq(normalized_aus, raw_aus)
  775. eq(normalized_aus, zero_aus)
  776. eq([[:echo "Buffer"]], normalized_aus[1].command)
  777. end)
  778. end)
  779. describe('id', function()
  780. it('gets events by ID', function()
  781. local id = api.nvim_create_autocmd('BufEnter', {
  782. command = 'echo "hello"',
  783. })
  784. eq({
  785. {
  786. buflocal = false,
  787. command = 'echo "hello"',
  788. event = 'BufEnter',
  789. id = id,
  790. once = false,
  791. pattern = '*',
  792. },
  793. }, api.nvim_get_autocmds({ id = id }))
  794. end)
  795. it('gets events by ID by other filters', function()
  796. local group_name = 'NVIM_GET_AUTOCMDS_ID'
  797. local group = api.nvim_create_augroup(group_name, { clear = true })
  798. local id = api.nvim_create_autocmd('BufEnter', {
  799. command = 'set number',
  800. group = group,
  801. })
  802. api.nvim_create_autocmd('WinEnter', {
  803. group = group,
  804. command = 'set cot&',
  805. })
  806. eq({
  807. {
  808. buflocal = false,
  809. command = 'set number',
  810. event = 'BufEnter',
  811. group = group,
  812. group_name = group_name,
  813. id = id,
  814. once = false,
  815. pattern = '*',
  816. },
  817. }, api.nvim_get_autocmds({ id = id, group = group }))
  818. end)
  819. it('gets events by ID and a specific event', function()
  820. local id = api.nvim_create_autocmd('InsertEnter', { command = 'set number' })
  821. api.nvim_create_autocmd('InsertEnter', { command = 'set wrap' })
  822. eq({
  823. {
  824. buflocal = false,
  825. command = 'set number',
  826. event = 'InsertEnter',
  827. id = id,
  828. once = false,
  829. pattern = '*',
  830. },
  831. }, api.nvim_get_autocmds({ id = id, event = 'InsertEnter' }))
  832. end)
  833. it('gets events by ID and a specific pattern', function()
  834. local id = api.nvim_create_autocmd('InsertEnter', {
  835. pattern = '*.c',
  836. command = 'set number',
  837. })
  838. api.nvim_create_autocmd('InsertEnter', {
  839. pattern = '*.c',
  840. command = 'set wrap',
  841. })
  842. eq({
  843. {
  844. buflocal = false,
  845. command = 'set number',
  846. event = 'InsertEnter',
  847. id = id,
  848. once = false,
  849. pattern = '*.c',
  850. },
  851. }, api.nvim_get_autocmds({ id = id, pattern = '*.c' }))
  852. end)
  853. it('empty result when id does not found', function()
  854. eq({}, api.nvim_get_autocmds({ id = 255 }))
  855. end)
  856. end)
  857. end)
  858. describe('nvim_exec_autocmds', function()
  859. it('validation', function()
  860. eq(
  861. "Invalid 'group': 9997999",
  862. pcall_err(api.nvim_exec_autocmds, 'FileType', {
  863. group = 9997999,
  864. })
  865. )
  866. eq(
  867. "Invalid 'group': 'bogus'",
  868. pcall_err(api.nvim_exec_autocmds, 'FileType', {
  869. group = 'bogus',
  870. })
  871. )
  872. eq(
  873. "Invalid 'group': expected String or Integer, got Array",
  874. pcall_err(api.nvim_exec_autocmds, 'FileType', {
  875. group = {},
  876. })
  877. )
  878. eq(
  879. "Invalid 'group': 0",
  880. pcall_err(api.nvim_exec_autocmds, 'FileType', {
  881. group = 0,
  882. })
  883. )
  884. eq(
  885. "Invalid 'buffer': expected Buffer, got Array",
  886. pcall_err(api.nvim_exec_autocmds, 'FileType', {
  887. buffer = {},
  888. })
  889. )
  890. eq(
  891. "Invalid 'event' item: expected String, got Array",
  892. pcall_err(api.nvim_exec_autocmds, { 'FileType', {} }, {})
  893. )
  894. end)
  895. it('can trigger builtin autocmds', function()
  896. api.nvim_set_var('autocmd_executed', false)
  897. api.nvim_create_autocmd('BufReadPost', {
  898. pattern = '*',
  899. command = 'let g:autocmd_executed = v:true',
  900. })
  901. eq(false, api.nvim_get_var('autocmd_executed'))
  902. api.nvim_exec_autocmds('BufReadPost', {})
  903. eq(true, api.nvim_get_var('autocmd_executed'))
  904. end)
  905. it('can trigger multiple patterns', function()
  906. api.nvim_set_var('autocmd_executed', 0)
  907. api.nvim_create_autocmd('BufReadPost', {
  908. pattern = '*',
  909. command = 'let g:autocmd_executed += 1',
  910. })
  911. api.nvim_exec_autocmds('BufReadPost', { pattern = { '*.lua', '*.vim' } })
  912. eq(2, api.nvim_get_var('autocmd_executed'))
  913. api.nvim_create_autocmd('BufReadPre', {
  914. pattern = { 'bar', 'foo' },
  915. command = 'let g:autocmd_executed += 10',
  916. })
  917. api.nvim_exec_autocmds('BufReadPre', { pattern = { 'foo', 'bar', 'baz', 'frederick' } })
  918. eq(22, api.nvim_get_var('autocmd_executed'))
  919. end)
  920. it('can pass the buffer', function()
  921. api.nvim_set_var('buffer_executed', -1)
  922. eq(-1, api.nvim_get_var('buffer_executed'))
  923. api.nvim_create_autocmd('BufLeave', {
  924. pattern = '*',
  925. command = 'let g:buffer_executed = +expand("<abuf>")',
  926. })
  927. -- Doesn't execute for other non-matching events
  928. api.nvim_exec_autocmds('CursorHold', { buffer = 1 })
  929. eq(-1, api.nvim_get_var('buffer_executed'))
  930. api.nvim_exec_autocmds('BufLeave', { buffer = 1 })
  931. eq(1, api.nvim_get_var('buffer_executed'))
  932. end)
  933. it('can pass the filename, pattern match', function()
  934. api.nvim_set_var('filename_executed', 'none')
  935. eq('none', api.nvim_get_var('filename_executed'))
  936. api.nvim_create_autocmd('BufEnter', {
  937. pattern = '*.py',
  938. command = 'let g:filename_executed = expand("<afile>")',
  939. })
  940. -- Doesn't execute for other non-matching events
  941. api.nvim_exec_autocmds('CursorHold', { buffer = 1 })
  942. eq('none', api.nvim_get_var('filename_executed'))
  943. command('edit __init__.py')
  944. eq('__init__.py', api.nvim_get_var('filename_executed'))
  945. end)
  946. it('cannot pass buf and fname', function()
  947. local ok = pcall(
  948. api.nvim_exec_autocmds,
  949. 'BufReadPre',
  950. { pattern = 'literally_cannot_error.rs', buffer = 1 }
  951. )
  952. eq(false, ok)
  953. end)
  954. it('can pass the filename, exact match', function()
  955. api.nvim_set_var('filename_executed', 'none')
  956. eq('none', api.nvim_get_var('filename_executed'))
  957. command('edit other_file.txt')
  958. command('edit __init__.py')
  959. eq('none', api.nvim_get_var('filename_executed'))
  960. api.nvim_create_autocmd('CursorHoldI', {
  961. pattern = '__init__.py',
  962. command = 'let g:filename_executed = expand("<afile>")',
  963. })
  964. -- Doesn't execute for other non-matching events
  965. api.nvim_exec_autocmds('CursorHoldI', { buffer = 1 })
  966. eq('none', api.nvim_get_var('filename_executed'))
  967. api.nvim_exec_autocmds('CursorHoldI', { buffer = api.nvim_get_current_buf() })
  968. eq('__init__.py', api.nvim_get_var('filename_executed'))
  969. -- Reset filename
  970. api.nvim_set_var('filename_executed', 'none')
  971. api.nvim_exec_autocmds('CursorHoldI', { pattern = '__init__.py' })
  972. eq('__init__.py', api.nvim_get_var('filename_executed'))
  973. end)
  974. it('works with user autocmds', function()
  975. api.nvim_set_var('matched', 'none')
  976. api.nvim_create_autocmd('User', {
  977. pattern = 'TestCommand',
  978. command = 'let g:matched = "matched"',
  979. })
  980. api.nvim_exec_autocmds('User', { pattern = 'OtherCommand' })
  981. eq('none', api.nvim_get_var('matched'))
  982. api.nvim_exec_autocmds('User', { pattern = 'TestCommand' })
  983. eq('matched', api.nvim_get_var('matched'))
  984. end)
  985. it('can pass group by id', function()
  986. api.nvim_set_var('group_executed', false)
  987. local auid = api.nvim_create_augroup('nvim_test_augroup', { clear = true })
  988. api.nvim_create_autocmd('FileType', {
  989. group = auid,
  990. command = 'let g:group_executed = v:true',
  991. })
  992. eq(false, api.nvim_get_var('group_executed'))
  993. api.nvim_exec_autocmds('FileType', { group = auid })
  994. eq(true, api.nvim_get_var('group_executed'))
  995. end)
  996. it('can pass group by name', function()
  997. api.nvim_set_var('group_executed', false)
  998. local auname = 'nvim_test_augroup'
  999. api.nvim_create_augroup(auname, { clear = true })
  1000. api.nvim_create_autocmd('FileType', {
  1001. group = auname,
  1002. command = 'let g:group_executed = v:true',
  1003. })
  1004. eq(false, api.nvim_get_var('group_executed'))
  1005. api.nvim_exec_autocmds('FileType', { group = auname })
  1006. eq(true, api.nvim_get_var('group_executed'))
  1007. end)
  1008. end)
  1009. describe('nvim_create_augroup', function()
  1010. before_each(function()
  1011. clear()
  1012. api.nvim_set_var('executed', 0)
  1013. end)
  1014. local make_counting_autocmd = function(opts)
  1015. opts = opts or {}
  1016. local resulting = {
  1017. pattern = '*',
  1018. command = 'let g:executed = g:executed + 1',
  1019. }
  1020. resulting.group = opts.group
  1021. resulting.once = opts.once
  1022. api.nvim_create_autocmd('FileType', resulting)
  1023. end
  1024. local set_ft = function(ft)
  1025. ft = ft or 'txt'
  1026. source(string.format('set filetype=%s', ft))
  1027. end
  1028. local get_executed_count = function()
  1029. return api.nvim_get_var('executed')
  1030. end
  1031. it('can be added in a group', function()
  1032. local augroup = 'TestGroup'
  1033. api.nvim_create_augroup(augroup, { clear = true })
  1034. make_counting_autocmd { group = augroup }
  1035. set_ft('txt')
  1036. set_ft('python')
  1037. eq(2, get_executed_count())
  1038. end)
  1039. it('works getting called multiple times', function()
  1040. make_counting_autocmd()
  1041. set_ft()
  1042. set_ft()
  1043. set_ft()
  1044. eq(3, get_executed_count())
  1045. end)
  1046. it('handles ++once', function()
  1047. make_counting_autocmd { once = true }
  1048. set_ft('txt')
  1049. set_ft('help')
  1050. set_ft('txt')
  1051. set_ft('help')
  1052. eq(1, get_executed_count())
  1053. end)
  1054. it('errors on unexpected keys', function()
  1055. local success, code = pcall(api.nvim_create_autocmd, 'FileType', {
  1056. pattern = '*',
  1057. not_a_valid_key = 'NotDefined',
  1058. })
  1059. eq(false, success)
  1060. matches('not_a_valid_key', code)
  1061. end)
  1062. it('can execute simple callback', function()
  1063. exec_lua(
  1064. [[
  1065. vim.g.executed = false
  1066. vim.api.nvim_create_autocmd("FileType", {
  1067. pattern = "*",
  1068. callback = function() vim.g.executed = true end,
  1069. })
  1070. ]],
  1071. {}
  1072. )
  1073. eq(
  1074. true,
  1075. exec_lua(
  1076. [[
  1077. vim.cmd "set filetype=txt"
  1078. return vim.g.executed
  1079. ]],
  1080. {}
  1081. )
  1082. )
  1083. end)
  1084. it('calls multiple lua callbacks for the same autocmd execution', function()
  1085. eq(
  1086. 4,
  1087. exec_lua(
  1088. [[
  1089. local count = 0
  1090. local counter = function()
  1091. count = count + 1
  1092. end
  1093. vim.api.nvim_create_autocmd("FileType", {
  1094. pattern = "*",
  1095. callback = counter,
  1096. })
  1097. vim.api.nvim_create_autocmd("FileType", {
  1098. pattern = "*",
  1099. callback = counter,
  1100. })
  1101. vim.cmd "set filetype=txt"
  1102. vim.cmd "set filetype=txt"
  1103. return count
  1104. ]],
  1105. {}
  1106. )
  1107. )
  1108. end)
  1109. it('properly releases functions with ++once', function()
  1110. exec_lua([[
  1111. WeakTable = setmetatable({}, { __mode = "k" })
  1112. OnceCount = 0
  1113. MyVal = {}
  1114. WeakTable[MyVal] = true
  1115. vim.api.nvim_create_autocmd("FileType", {
  1116. pattern = "*",
  1117. callback = function()
  1118. OnceCount = OnceCount + 1
  1119. MyVal = {}
  1120. end,
  1121. once = true
  1122. })
  1123. ]])
  1124. command [[set filetype=txt]]
  1125. eq(1, exec_lua([[return OnceCount]], {}))
  1126. exec_lua([[collectgarbage()]], {})
  1127. command [[set filetype=txt]]
  1128. eq(1, exec_lua([[return OnceCount]], {}))
  1129. eq(
  1130. 0,
  1131. exec_lua([[
  1132. local count = 0
  1133. for _ in pairs(WeakTable) do
  1134. count = count + 1
  1135. end
  1136. return count
  1137. ]]),
  1138. 'Should have no keys remaining'
  1139. )
  1140. end)
  1141. it('groups can be cleared', function()
  1142. local augroup = 'TestGroup'
  1143. api.nvim_create_augroup(augroup, { clear = true })
  1144. api.nvim_create_autocmd('FileType', {
  1145. group = augroup,
  1146. command = 'let g:executed = g:executed + 1',
  1147. })
  1148. set_ft('txt')
  1149. set_ft('txt')
  1150. eq(2, get_executed_count(), 'should only count twice')
  1151. api.nvim_create_augroup(augroup, { clear = true })
  1152. eq({}, api.nvim_get_autocmds { group = augroup })
  1153. set_ft('txt')
  1154. set_ft('txt')
  1155. eq(2, get_executed_count(), 'No additional counts')
  1156. end)
  1157. it('can delete non-existent groups with pcall', function()
  1158. eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_name, 'noexist')]])
  1159. eq('Vim:E367: No such group: "noexist"', pcall_err(api.nvim_del_augroup_by_name, 'noexist'))
  1160. eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, -12342)]])
  1161. eq('Vim:E367: No such group: "--Deleted--"', pcall_err(api.nvim_del_augroup_by_id, -12312))
  1162. eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, 0)]])
  1163. eq('Vim:E367: No such group: "[NULL]"', pcall_err(api.nvim_del_augroup_by_id, 0))
  1164. eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, 12342)]])
  1165. eq('Vim:E367: No such group: "[NULL]"', pcall_err(api.nvim_del_augroup_by_id, 12312))
  1166. end)
  1167. it('groups work with once', function()
  1168. local augroup = 'TestGroup'
  1169. api.nvim_create_augroup(augroup, { clear = true })
  1170. make_counting_autocmd { group = augroup, once = true }
  1171. set_ft('txt')
  1172. set_ft('python')
  1173. eq(1, get_executed_count())
  1174. end)
  1175. it('autocmds can be registered multiple times.', function()
  1176. local augroup = 'TestGroup'
  1177. api.nvim_create_augroup(augroup, { clear = true })
  1178. make_counting_autocmd { group = augroup, once = false }
  1179. make_counting_autocmd { group = augroup, once = false }
  1180. make_counting_autocmd { group = augroup, once = false }
  1181. set_ft('txt')
  1182. set_ft('python')
  1183. eq(3 * 2, get_executed_count())
  1184. end)
  1185. it('can be deleted', function()
  1186. local augroup = 'WillBeDeleted'
  1187. api.nvim_create_augroup(augroup, { clear = true })
  1188. api.nvim_create_autocmd({ 'FileType' }, {
  1189. pattern = '*',
  1190. command = "echo 'does not matter'",
  1191. })
  1192. -- Clears the augroup from before, which erases the autocmd
  1193. api.nvim_create_augroup(augroup, { clear = true })
  1194. local result = #api.nvim_get_autocmds { group = augroup }
  1195. eq(0, result)
  1196. end)
  1197. it('can be used for buffer local autocmds', function()
  1198. local augroup = 'WillBeDeleted'
  1199. api.nvim_set_var('value_set', false)
  1200. api.nvim_create_augroup(augroup, { clear = true })
  1201. api.nvim_create_autocmd('FileType', {
  1202. pattern = '<buffer>',
  1203. command = 'let g:value_set = v:true',
  1204. })
  1205. command 'new'
  1206. command 'set filetype=python'
  1207. eq(false, api.nvim_get_var('value_set'))
  1208. end)
  1209. it('can accept vimscript functions', function()
  1210. source [[
  1211. let g:vimscript_executed = 0
  1212. function! MyVimscriptFunction() abort
  1213. let g:vimscript_executed = g:vimscript_executed + 1
  1214. endfunction
  1215. call nvim_create_autocmd("FileType", #{
  1216. \ pattern: ["python", "javascript"],
  1217. \ callback: "MyVimscriptFunction",
  1218. \ })
  1219. set filetype=txt
  1220. set filetype=python
  1221. set filetype=txt
  1222. set filetype=javascript
  1223. set filetype=txt
  1224. ]]
  1225. eq(2, api.nvim_get_var('vimscript_executed'))
  1226. end)
  1227. end)
  1228. describe('augroup!', function()
  1229. it('legacy: should clear and not return any autocmds for delete groups', function()
  1230. command('augroup TEMP_A')
  1231. command(' autocmd! BufReadPost *.py :echo "Hello"')
  1232. command('augroup END')
  1233. command('augroup! TEMP_A')
  1234. eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_A' }))
  1235. -- For some reason, augroup! doesn't clear the autocmds themselves, which is just wild
  1236. -- but we managed to keep this behavior.
  1237. eq(1, #api.nvim_get_autocmds { event = 'BufReadPost' })
  1238. end)
  1239. it('legacy: remove augroups that have no autocmds', function()
  1240. command('augroup TEMP_AB')
  1241. command('augroup END')
  1242. command('augroup! TEMP_AB')
  1243. eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_AB' }))
  1244. eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' })
  1245. end)
  1246. it('legacy: multiple remove and add augroup', function()
  1247. command('augroup TEMP_ABC')
  1248. command(' au!')
  1249. command(' autocmd BufReadPost *.py echo "Hello"')
  1250. command('augroup END')
  1251. command('augroup! TEMP_ABC')
  1252. -- Should still have one autocmd :'(
  1253. local aus = api.nvim_get_autocmds { event = 'BufReadPost' }
  1254. eq(1, #aus, aus)
  1255. command('augroup TEMP_ABC')
  1256. command(' au!')
  1257. command(' autocmd BufReadPost *.py echo "Hello"')
  1258. command('augroup END')
  1259. -- Should now have two autocmds :'(
  1260. aus = api.nvim_get_autocmds { event = 'BufReadPost' }
  1261. eq(2, #aus, aus)
  1262. command('augroup! TEMP_ABC')
  1263. eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABC' }))
  1264. eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' })
  1265. end)
  1266. it('api: should clear and not return any autocmds for delete groups by id', function()
  1267. command('augroup TEMP_ABCD')
  1268. command('autocmd! BufReadPost *.py :echo "Hello"')
  1269. command('augroup END')
  1270. local augroup_id = api.nvim_create_augroup('TEMP_ABCD', { clear = false })
  1271. api.nvim_del_augroup_by_id(augroup_id)
  1272. -- For good reason, we kill all the autocmds from del_augroup,
  1273. -- so now this works as expected
  1274. eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABCD' }))
  1275. eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' })
  1276. end)
  1277. it('api: should clear and not return any autocmds for delete groups by name', function()
  1278. command('augroup TEMP_ABCDE')
  1279. command('autocmd! BufReadPost *.py :echo "Hello"')
  1280. command('augroup END')
  1281. api.nvim_del_augroup_by_name('TEMP_ABCDE')
  1282. -- For good reason, we kill all the autocmds from del_augroup,
  1283. -- so now this works as expected
  1284. eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABCDE' }))
  1285. eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' })
  1286. end)
  1287. end)
  1288. describe('nvim_clear_autocmds', function()
  1289. it('validation', function()
  1290. eq(
  1291. "Cannot use both 'pattern' and 'buffer'",
  1292. pcall_err(api.nvim_clear_autocmds, {
  1293. pattern = '*',
  1294. buffer = 42,
  1295. })
  1296. )
  1297. eq(
  1298. "Invalid 'event' item: expected String, got Array",
  1299. pcall_err(api.nvim_clear_autocmds, {
  1300. event = { 'FileType', {} },
  1301. })
  1302. )
  1303. eq("Invalid 'group': 0", pcall_err(api.nvim_clear_autocmds, { group = 0 }))
  1304. end)
  1305. it('should clear based on event + pattern', function()
  1306. command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"')
  1307. command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"')
  1308. local search = { event = 'InsertEnter', pattern = '*.txt' }
  1309. local before_delete = api.nvim_get_autocmds(search)
  1310. eq(1, #before_delete)
  1311. local before_delete_all = api.nvim_get_autocmds { event = search.event }
  1312. eq(2, #before_delete_all)
  1313. api.nvim_clear_autocmds(search)
  1314. local after_delete = api.nvim_get_autocmds(search)
  1315. eq(0, #after_delete)
  1316. local after_delete_all = api.nvim_get_autocmds { event = search.event }
  1317. eq(1, #after_delete_all)
  1318. end)
  1319. it('should clear based on event', function()
  1320. command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"')
  1321. command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"')
  1322. local search = { event = 'InsertEnter' }
  1323. local before_delete = api.nvim_get_autocmds(search)
  1324. eq(2, #before_delete)
  1325. api.nvim_clear_autocmds(search)
  1326. local after_delete = api.nvim_get_autocmds(search)
  1327. eq(0, #after_delete)
  1328. end)
  1329. it('should clear based on pattern', function()
  1330. command('autocmd InsertEnter *.TestPat1 :echo "Enter 1"')
  1331. command('autocmd InsertLeave *.TestPat1 :echo "Leave 1"')
  1332. command('autocmd InsertEnter *.TestPat2 :echo "Enter 2"')
  1333. command('autocmd InsertLeave *.TestPat2 :echo "Leave 2"')
  1334. local search = { pattern = '*.TestPat1' }
  1335. local before_delete = api.nvim_get_autocmds(search)
  1336. eq(2, #before_delete)
  1337. local before_delete_events =
  1338. api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
  1339. eq(4, #before_delete_events)
  1340. api.nvim_clear_autocmds(search)
  1341. local after_delete = api.nvim_get_autocmds(search)
  1342. eq(0, #after_delete)
  1343. local after_delete_events = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
  1344. eq(2, #after_delete_events)
  1345. end)
  1346. it('should allow clearing by buffer', function()
  1347. command('autocmd! InsertEnter')
  1348. command('autocmd InsertEnter <buffer> :echo "Enter Buffer"')
  1349. command('autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"')
  1350. local search = { event = 'InsertEnter' }
  1351. local before_delete = api.nvim_get_autocmds(search)
  1352. eq(2, #before_delete)
  1353. api.nvim_clear_autocmds { buffer = 0 }
  1354. local after_delete = api.nvim_get_autocmds(search)
  1355. eq(1, #after_delete)
  1356. eq('*.TestPat1', after_delete[1].pattern)
  1357. end)
  1358. it('should allow clearing by buffer and group', function()
  1359. command('augroup TestNvimClearAutocmds')
  1360. command(' au!')
  1361. command(' autocmd InsertEnter <buffer> :echo "Enter Buffer"')
  1362. command(' autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"')
  1363. command('augroup END')
  1364. local search = { event = 'InsertEnter', group = 'TestNvimClearAutocmds' }
  1365. local before_delete = api.nvim_get_autocmds(search)
  1366. eq(2, #before_delete)
  1367. -- Doesn't clear without passing group.
  1368. api.nvim_clear_autocmds { buffer = 0 }
  1369. local without_group = api.nvim_get_autocmds(search)
  1370. eq(2, #without_group)
  1371. -- Doesn't clear with passing group.
  1372. api.nvim_clear_autocmds { buffer = 0, group = search.group }
  1373. local with_group = api.nvim_get_autocmds(search)
  1374. eq(1, #with_group)
  1375. end)
  1376. end)
  1377. end)