neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

autocmd_spec.lua (48383B)


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