autocmd_spec.lua 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local assert_visible = n.assert_visible
  5. local assert_alive = n.assert_alive
  6. local dedent = t.dedent
  7. local eq = t.eq
  8. local neq = t.neq
  9. local eval = n.eval
  10. local feed = n.feed
  11. local clear = n.clear
  12. local matches = t.matches
  13. local api = n.api
  14. local pcall_err = t.pcall_err
  15. local fn = n.fn
  16. local expect = n.expect
  17. local command = n.command
  18. local exc_exec = n.exc_exec
  19. local exec_lua = n.exec_lua
  20. local retry = t.retry
  21. local source = n.source
  22. describe('autocmd', function()
  23. before_each(clear)
  24. it(':tabnew, :split, :close events order, <afile>', function()
  25. local expected = {
  26. { 'WinLeave', '' },
  27. { 'TabLeave', '' },
  28. { 'WinEnter', '' },
  29. { 'TabNew', 'testfile1' }, -- :tabnew
  30. { 'TabEnter', '' },
  31. { 'BufLeave', '' },
  32. { 'BufEnter', 'testfile1' }, -- :split
  33. { 'WinLeave', 'testfile1' },
  34. { 'WinEnter', 'testfile1' },
  35. { 'WinLeave', 'testfile1' },
  36. { 'WinClosed', '1002' }, -- :close, WinClosed <afile> = window-id
  37. { 'WinEnter', 'testfile1' },
  38. { 'WinLeave', 'testfile1' }, -- :bdelete
  39. { 'WinEnter', 'testfile1' },
  40. { 'BufLeave', 'testfile1' },
  41. { 'BufEnter', 'testfile2' },
  42. { 'WinClosed', '1000' },
  43. }
  44. command('let g:evs = []')
  45. command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])')
  46. command('autocmd BufLeave * :call add(g:evs, ["BufLeave", expand("<afile>")])')
  47. command('autocmd TabEnter * :call add(g:evs, ["TabEnter", expand("<afile>")])')
  48. command('autocmd TabLeave * :call add(g:evs, ["TabLeave", expand("<afile>")])')
  49. command('autocmd TabNew * :call add(g:evs, ["TabNew", expand("<afile>")])')
  50. command('autocmd WinEnter * :call add(g:evs, ["WinEnter", expand("<afile>")])')
  51. command('autocmd WinLeave * :call add(g:evs, ["WinLeave", expand("<afile>")])')
  52. command('autocmd WinClosed * :call add(g:evs, ["WinClosed", expand("<afile>")])')
  53. command('tabnew testfile1')
  54. command('split')
  55. command('close')
  56. command('new testfile2')
  57. command('bdelete 1')
  58. eq(expected, eval('g:evs'))
  59. end)
  60. it('first edit causes BufUnload on NoName', function()
  61. local expected = {
  62. { 'BufUnload', '' },
  63. { 'BufDelete', '' },
  64. { 'BufWipeout', '' },
  65. { 'BufEnter', 'testfile1' },
  66. }
  67. command('let g:evs = []')
  68. command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])')
  69. command('autocmd BufDelete * :call add(g:evs, ["BufDelete", expand("<afile>")])')
  70. command('autocmd BufLeave * :call add(g:evs, ["BufLeave", expand("<afile>")])')
  71. command('autocmd BufUnload * :call add(g:evs, ["BufUnload", expand("<afile>")])')
  72. command('autocmd BufWipeout * :call add(g:evs, ["BufWipeout", expand("<afile>")])')
  73. command('edit testfile1')
  74. eq(expected, eval('g:evs'))
  75. end)
  76. it('WinClosed is non-recursive', function()
  77. command('let g:triggered = 0')
  78. command('autocmd WinClosed * :let g:triggered+=1 | :bdelete 2')
  79. command('new testfile2')
  80. command('new testfile3')
  81. -- All 3 buffers are visible.
  82. assert_visible(1, true)
  83. assert_visible(2, true)
  84. assert_visible(3, true)
  85. -- Trigger WinClosed, which also deletes buffer/window 2.
  86. command('bdelete 1')
  87. -- Buffers 1 and 2 were closed but WinClosed was triggered only once.
  88. eq(1, eval('g:triggered'))
  89. assert_visible(1, false)
  90. assert_visible(2, false)
  91. assert_visible(3, true)
  92. end)
  93. it('WinClosed from a different tabpage', function()
  94. command('let g:evs = []')
  95. command('edit tesfile1')
  96. command('autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])')
  97. local buf1 = eval("bufnr('%')")
  98. command('new')
  99. local buf2 = eval("bufnr('%')")
  100. command(
  101. 'autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])'
  102. -- Attempt recursion.
  103. .. ' | bdelete '
  104. .. buf2
  105. )
  106. command('tabedit testfile2')
  107. command('tabedit testfile3')
  108. command('bdelete ' .. buf2)
  109. -- Non-recursive: only triggered once.
  110. eq({
  111. { 'WinClosed', '2' },
  112. }, eval('g:evs'))
  113. command('bdelete ' .. buf1)
  114. eq({
  115. { 'WinClosed', '2' },
  116. { 'WinClosed', '1' },
  117. }, eval('g:evs'))
  118. end)
  119. it('WinClosed from root directory', function()
  120. command('cd /')
  121. command('let g:evs = []')
  122. command('autocmd WinClosed * :call add(g:evs, ["WinClosed", expand("<afile>")])')
  123. command('new')
  124. command('close')
  125. eq({
  126. { 'WinClosed', '1001' },
  127. }, eval('g:evs'))
  128. end)
  129. it('v:vim_did_enter is 1 after VimEnter', function()
  130. eq(1, eval('v:vim_did_enter'))
  131. end)
  132. describe('BufLeave autocommand', function()
  133. it('can wipe out the buffer created by :edit which triggered autocmd', function()
  134. api.nvim_set_option_value('hidden', true, {})
  135. api.nvim_buf_set_lines(0, 0, 1, false, {
  136. 'start of test file xx',
  137. 'end of test file xx',
  138. })
  139. command('autocmd BufLeave * bwipeout yy')
  140. eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', exc_exec('edit yy'))
  141. expect([[
  142. start of test file xx
  143. end of test file xx]])
  144. end)
  145. end)
  146. it('++once', function() -- :help autocmd-once
  147. --
  148. -- ":autocmd … ++once" executes its handler once, then removes the handler.
  149. --
  150. local expected = {
  151. 'Many1',
  152. 'Once1',
  153. 'Once2',
  154. 'Many2',
  155. 'Once3',
  156. 'Many1',
  157. 'Many2',
  158. 'Many1',
  159. 'Many2',
  160. }
  161. command('let g:foo = []')
  162. command('autocmd TabNew * :call add(g:foo, "Many1")')
  163. command('autocmd TabNew * ++once :call add(g:foo, "Once1")')
  164. command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
  165. command('autocmd TabNew * :call add(g:foo, "Many2")')
  166. command('autocmd TabNew * ++once :call add(g:foo, "Once3")')
  167. eq(
  168. dedent([[
  169. --- Autocommands ---
  170. TabNew
  171. * :call add(g:foo, "Many1")
  172. :call add(g:foo, "Once1")
  173. :call add(g:foo, "Once2")
  174. :call add(g:foo, "Many2")
  175. :call add(g:foo, "Once3")]]),
  176. fn.execute('autocmd Tabnew')
  177. )
  178. command('tabnew')
  179. command('tabnew')
  180. command('tabnew')
  181. eq(expected, eval('g:foo'))
  182. eq(
  183. dedent([[
  184. --- Autocommands ---
  185. TabNew
  186. * :call add(g:foo, "Many1")
  187. :call add(g:foo, "Many2")]]),
  188. fn.execute('autocmd Tabnew')
  189. )
  190. --
  191. -- ":autocmd … ++once" handlers can be deleted.
  192. --
  193. expected = {}
  194. command('let g:foo = []')
  195. command('autocmd TabNew * ++once :call add(g:foo, "Once1")')
  196. command('autocmd! TabNew')
  197. command('tabnew')
  198. eq(expected, eval('g:foo'))
  199. --
  200. -- ":autocmd … <buffer> ++once ++nested"
  201. --
  202. expected = {
  203. 'OptionSet-Once',
  204. 'CursorMoved-Once',
  205. }
  206. command('let g:foo = []')
  207. command('autocmd OptionSet binary ++nested ++once :call add(g:foo, "OptionSet-Once")')
  208. command(
  209. 'autocmd CursorMoved <buffer> ++once ++nested setlocal binary|:call add(g:foo, "CursorMoved-Once")'
  210. )
  211. command("put ='foo bar baz'")
  212. feed('0llhlh')
  213. eq(expected, eval('g:foo'))
  214. --
  215. -- :autocmd should not show empty section after ++once handlers expire.
  216. --
  217. expected = {
  218. 'Once1',
  219. 'Once2',
  220. }
  221. command('let g:foo = []')
  222. command('autocmd! TabNew') -- Clear all TabNew handlers.
  223. command('autocmd TabNew * ++once :call add(g:foo, "Once1")')
  224. command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
  225. command('tabnew')
  226. eq(expected, eval('g:foo'))
  227. eq(
  228. dedent([[
  229. --- Autocommands ---]]),
  230. fn.execute('autocmd Tabnew')
  231. )
  232. --
  233. -- :autocmd does not recursively call ++once Lua handlers.
  234. --
  235. exec_lua [[vim.g.count = 0]]
  236. eq(0, eval('g:count'))
  237. exec_lua [[
  238. vim.api.nvim_create_autocmd('User', {
  239. once = true,
  240. pattern = nil,
  241. callback = function()
  242. vim.g.count = vim.g.count + 1
  243. vim.api.nvim_exec_autocmds('User', { pattern = nil })
  244. end,
  245. })
  246. vim.api.nvim_exec_autocmds('User', { pattern = nil })
  247. ]]
  248. eq(1, eval('g:count'))
  249. end)
  250. it('internal `aucmd_win` window', function()
  251. -- Nvim uses a special internal window `aucmd_win` to execute certain
  252. -- actions for an invisible buffer (:help E813).
  253. -- Check redrawing and API accesses to this window.
  254. local screen = Screen.new(50, 10)
  255. source([[
  256. function! Doit()
  257. let g:winid = nvim_get_current_win()
  258. redraw!
  259. echo getchar()
  260. " API functions work when aucmd_win is in scope
  261. let g:had_value = has_key(w:, "testvar")
  262. call nvim_win_set_var(g:winid, "testvar", 7)
  263. let g:test = w:testvar
  264. endfunction
  265. set hidden
  266. " add dummy text to not discard the buffer
  267. call setline(1,"bb")
  268. autocmd User <buffer> call Doit()
  269. ]])
  270. screen:expect([[
  271. ^bb |
  272. {1:~ }|*8
  273. |
  274. ]])
  275. feed(':enew | doautoall User<cr>')
  276. screen:expect([[
  277. {4:bb }|
  278. {11:~ }|*4
  279. {1:~ }|*4
  280. ^:enew | doautoall User |
  281. ]])
  282. feed('<cr>')
  283. screen:expect([[
  284. ^ |
  285. {1:~ }|*8
  286. 13 |
  287. ]])
  288. eq(7, eval('g:test'))
  289. -- API calls are blocked when aucmd_win is not in scope
  290. eq(
  291. 'Vim(call):E5555: API call: Invalid window id: 1001',
  292. pcall_err(command, 'call nvim_set_current_win(g:winid)')
  293. )
  294. -- second time aucmd_win is needed, a different code path is invoked
  295. -- to reuse the same window, so check again
  296. command('let g:test = v:null')
  297. command('let g:had_value = v:null')
  298. feed(':doautoall User<cr>')
  299. screen:expect([[
  300. {4:bb }|
  301. {11:~ }|*4
  302. {1:~ }|*4
  303. ^:doautoall User |
  304. ]])
  305. feed('<cr>')
  306. screen:expect([[
  307. ^ |
  308. {1:~ }|*8
  309. 13 |
  310. ]])
  311. -- win vars in aucmd_win should have been reset
  312. eq(0, eval('g:had_value'))
  313. eq(7, eval('g:test'))
  314. eq(
  315. 'Vim(call):E5555: API call: Invalid window id: 1001',
  316. pcall_err(command, 'call nvim_set_current_win(g:winid)')
  317. )
  318. end)
  319. it('`aucmd_win` cannot be changed into a normal window #13699', function()
  320. local screen = Screen.new(50, 10)
  321. -- Create specific layout and ensure it's left unchanged.
  322. -- Use vim._with on a hidden buffer so aucmd_win is used.
  323. exec_lua [[
  324. vim.cmd "wincmd s | wincmd _"
  325. _G.buf = vim.api.nvim_create_buf(true, true)
  326. vim._with({buf = _G.buf}, function() vim.cmd "wincmd J" end)
  327. ]]
  328. screen:expect [[
  329. ^ |
  330. {1:~ }|*5
  331. {3:[No Name] }|
  332. |
  333. {2:[No Name] }|
  334. |
  335. ]]
  336. -- This used to crash after making aucmd_win a normal window via the above.
  337. exec_lua [[
  338. vim.cmd "tabnew | tabclose # | wincmd s | wincmd _"
  339. vim._with({buf = _G.buf}, function() vim.cmd "wincmd K" end)
  340. ]]
  341. assert_alive()
  342. screen:expect_unchanged()
  343. -- Also check with win_splitmove().
  344. exec_lua [[
  345. vim._with({buf = _G.buf}, function()
  346. vim.fn.win_splitmove(vim.fn.winnr(), vim.fn.win_getid(1))
  347. end)
  348. ]]
  349. screen:expect_unchanged()
  350. -- Also check with nvim_win_set_config().
  351. matches(
  352. '^Failed to move window %d+ into split$',
  353. pcall_err(
  354. exec_lua,
  355. [[
  356. vim._with({buf = _G.buf}, function()
  357. vim.api.nvim_win_set_config(0, {
  358. vertical = true,
  359. win = vim.fn.win_getid(1)
  360. })
  361. end)
  362. ]]
  363. )
  364. )
  365. screen:expect_unchanged()
  366. -- Ensure splitting still works from inside the aucmd_win.
  367. exec_lua [[vim._with({buf = _G.buf}, function() vim.cmd "split" end)]]
  368. screen:expect [[
  369. ^ |
  370. {1:~ }|
  371. {3:[No Name] }|
  372. |
  373. {1:~ }|
  374. {2:[Scratch] }|
  375. |
  376. {1:~ }|
  377. {2:[No Name] }|
  378. |
  379. ]]
  380. -- After all of our messing around, aucmd_win should still be floating.
  381. -- Use :only to ensure _G.buf is hidden again (so the aucmd_win is used).
  382. eq(
  383. 'editor',
  384. exec_lua [[
  385. vim.cmd "only"
  386. vim._with({buf = _G.buf}, function()
  387. _G.config = vim.api.nvim_win_get_config(0)
  388. end)
  389. return _G.config.relative
  390. ]]
  391. )
  392. end)
  393. describe('closing last non-floating window in tab from `aucmd_win`', function()
  394. before_each(function()
  395. command('edit Xa.txt')
  396. command('tabnew Xb.txt')
  397. command('autocmd BufAdd Xa.txt 1close')
  398. end)
  399. it('gives E814 when there are no other floating windows', function()
  400. eq(
  401. 'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
  402. pcall_err(command, 'doautoall BufAdd')
  403. )
  404. end)
  405. it('gives E814 when there are other floating windows', function()
  406. api.nvim_open_win(
  407. 0,
  408. true,
  409. { width = 10, height = 10, relative = 'editor', row = 10, col = 10 }
  410. )
  411. eq(
  412. 'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
  413. pcall_err(command, 'doautoall BufAdd')
  414. )
  415. end)
  416. end)
  417. it('closing `aucmd_win` using API gives E813', function()
  418. exec_lua([[
  419. vim.cmd('tabnew')
  420. _G.buf = vim.api.nvim_create_buf(true, true)
  421. ]])
  422. matches(
  423. 'Vim:E813: Cannot close autocmd window$',
  424. pcall_err(
  425. exec_lua,
  426. [[
  427. vim._with({buf = _G.buf}, function()
  428. local win = vim.api.nvim_get_current_win()
  429. vim.api.nvim_win_close(win, true)
  430. end)
  431. ]]
  432. )
  433. )
  434. matches(
  435. 'Vim:E813: Cannot close autocmd window$',
  436. pcall_err(
  437. exec_lua,
  438. [[
  439. vim._with({buf = _G.buf}, function()
  440. local win = vim.api.nvim_get_current_win()
  441. vim.cmd('tabnext')
  442. vim.api.nvim_win_close(win, true)
  443. end)
  444. ]]
  445. )
  446. )
  447. matches(
  448. 'Vim:E813: Cannot close autocmd window$',
  449. pcall_err(
  450. exec_lua,
  451. [[
  452. vim._with({buf = _G.buf}, function()
  453. local win = vim.api.nvim_get_current_win()
  454. vim.api.nvim_win_hide(win)
  455. end)
  456. ]]
  457. )
  458. )
  459. matches(
  460. 'Vim:E813: Cannot close autocmd window$',
  461. pcall_err(
  462. exec_lua,
  463. [[
  464. vim._with({buf = _G.buf}, function()
  465. local win = vim.api.nvim_get_current_win()
  466. vim.cmd('tabnext')
  467. vim.api.nvim_win_hide(win)
  468. end)
  469. ]]
  470. )
  471. )
  472. end)
  473. it(':doautocmd does not warn "No matching autocommands" #10689', function()
  474. local screen = Screen.new(32, 3)
  475. feed(':doautocmd User Foo<cr>')
  476. screen:expect {
  477. grid = [[
  478. ^ |
  479. {1:~ }|
  480. :doautocmd User Foo |
  481. ]],
  482. }
  483. feed(':autocmd! SessionLoadPost<cr>')
  484. feed(':doautocmd SessionLoadPost<cr>')
  485. screen:expect {
  486. grid = [[
  487. ^ |
  488. {1:~ }|
  489. :doautocmd SessionLoadPost |
  490. ]],
  491. }
  492. end)
  493. describe('v:event is readonly #18063', function()
  494. it('during ChanOpen event', function()
  495. command('autocmd ChanOpen * let v:event.info.id = 0')
  496. fn.jobstart({ 'cat' })
  497. retry(nil, nil, function()
  498. eq('E46: Cannot change read-only variable "v:event.info"', api.nvim_get_vvar('errmsg'))
  499. end)
  500. end)
  501. it('during ChanOpen event', function()
  502. command('autocmd ChanInfo * let v:event.info.id = 0')
  503. api.nvim_set_client_info('foo', {}, 'remote', {}, {})
  504. retry(nil, nil, function()
  505. eq('E46: Cannot change read-only variable "v:event.info"', api.nvim_get_vvar('errmsg'))
  506. end)
  507. end)
  508. it('during RecordingLeave event', function()
  509. command([[autocmd RecordingLeave * let v:event.regname = '']])
  510. eq(
  511. 'RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"',
  512. pcall_err(command, 'normal! qqq')
  513. )
  514. end)
  515. it('during TermClose event', function()
  516. command('autocmd TermClose * let v:event.status = 0')
  517. command('terminal')
  518. eq(
  519. 'TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"',
  520. pcall_err(command, 'bdelete!')
  521. )
  522. end)
  523. end)
  524. describe('old_tests', function()
  525. it('vimscript: WinNew ++once', function()
  526. source [[
  527. " Without ++once WinNew triggers twice
  528. let g:did_split = 0
  529. augroup Testing
  530. au!
  531. au WinNew * let g:did_split += 1
  532. augroup END
  533. split
  534. split
  535. call assert_equal(2, g:did_split)
  536. call assert_true(exists('#WinNew'))
  537. close
  538. close
  539. " With ++once WinNew triggers once
  540. let g:did_split = 0
  541. augroup Testing
  542. au!
  543. au WinNew * ++once let g:did_split += 1
  544. augroup END
  545. split
  546. split
  547. call assert_equal(1, g:did_split)
  548. call assert_false(exists('#WinNew'))
  549. close
  550. close
  551. call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
  552. ]]
  553. api.nvim_set_var('did_split', 0)
  554. source [[
  555. augroup Testing
  556. au!
  557. au WinNew * let g:did_split += 1
  558. augroup END
  559. split
  560. split
  561. ]]
  562. eq(2, api.nvim_get_var('did_split'))
  563. eq(1, fn.exists('#WinNew'))
  564. -- Now with once
  565. api.nvim_set_var('did_split', 0)
  566. source [[
  567. augroup Testing
  568. au!
  569. au WinNew * ++once let g:did_split += 1
  570. augroup END
  571. split
  572. split
  573. ]]
  574. eq(1, api.nvim_get_var('did_split'))
  575. eq(0, fn.exists('#WinNew'))
  576. -- call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
  577. local ok, msg = pcall(
  578. source,
  579. [[
  580. au WinNew * ++once ++once echo bad
  581. ]]
  582. )
  583. eq(false, ok)
  584. eq(true, not not string.find(msg, 'E983:'))
  585. end)
  586. it('should have autocmds in filetypedetect group', function()
  587. source [[filetype on]]
  588. neq({}, api.nvim_get_autocmds { group = 'filetypedetect' })
  589. end)
  590. it('should allow comma-separated patterns', function()
  591. source [[
  592. augroup TestingPatterns
  593. au!
  594. autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello'
  595. autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello'
  596. augroup END
  597. ]]
  598. eq(4, #api.nvim_get_autocmds { event = 'BufReadCmd', group = 'TestingPatterns' })
  599. end)
  600. end)
  601. it('no use-after-free when adding autocommands from a callback', function()
  602. exec_lua [[
  603. vim.cmd "autocmd! TabNew"
  604. vim.g.count = 0
  605. vim.api.nvim_create_autocmd('TabNew', {
  606. callback = function()
  607. vim.g.count = vim.g.count + 1
  608. for _ = 1, 100 do
  609. vim.cmd "autocmd TabNew * let g:count += 1"
  610. end
  611. return true
  612. end,
  613. })
  614. vim.cmd "tabnew"
  615. ]]
  616. eq(1, eval('g:count')) -- Added autocommands should not be executed
  617. end)
  618. it('no crash when clearing a group inside a callback #23355', function()
  619. exec_lua [[
  620. vim.cmd "autocmd! TabNew"
  621. local group = vim.api.nvim_create_augroup('Test', {})
  622. local id
  623. id = vim.api.nvim_create_autocmd('TabNew', {
  624. group = group,
  625. callback = function()
  626. vim.api.nvim_del_autocmd(id)
  627. vim.api.nvim_create_augroup('Test', { clear = true })
  628. end,
  629. })
  630. vim.cmd "tabnew"
  631. ]]
  632. end)
  633. end)