neovim

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

option_and_var_spec.lua (42539B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 local Screen = require('test.functional.ui.screen')
      4 
      5 local NIL = vim.NIL
      6 local feed = n.feed
      7 local command = n.command
      8 local clear = n.clear
      9 local api = n.api
     10 local eq = t.eq
     11 local eval = n.eval
     12 local exec = n.exec
     13 local exec_lua = n.exec_lua
     14 local fn = n.fn
     15 local matches = t.matches
     16 local mkdir_p = n.mkdir_p
     17 local pcall_err = t.pcall_err
     18 local rmdir = n.rmdir
     19 local write_file = t.write_file
     20 
     21 local function eq_exec_lua(expected, f)
     22  eq(expected, exec_lua(f))
     23 end
     24 
     25 describe('lua stdlib', function()
     26  before_each(clear)
     27 
     28  describe('variables', function()
     29    it('vim.g', function()
     30      exec_lua(function()
     31        vim.api.nvim_set_var('testing', 'hi')
     32        vim.api.nvim_set_var('other', 123)
     33        vim.api.nvim_set_var('floaty', 5120.1)
     34        vim.api.nvim_set_var('nullvar', vim.NIL)
     35        vim.api.nvim_set_var('to_delete', { hello = 'world' })
     36      end)
     37 
     38      eq('hi', fn.luaeval 'vim.g.testing')
     39      eq(123, fn.luaeval 'vim.g.other')
     40      eq(5120.1, fn.luaeval 'vim.g.floaty')
     41      eq(NIL, fn.luaeval 'vim.g.nonexistent')
     42      eq(NIL, fn.luaeval 'vim.g.nullvar')
     43      -- lost over RPC, so test locally:
     44      eq_exec_lua({ false, true }, function()
     45        return { vim.g.nonexistent == vim.NIL, vim.g.nullvar == vim.NIL }
     46      end)
     47 
     48      eq({ hello = 'world' }, fn.luaeval 'vim.g.to_delete')
     49      exec_lua [[
     50      vim.g.to_delete = nil
     51      ]]
     52      eq(NIL, fn.luaeval 'vim.g.to_delete')
     53 
     54      matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.g[0].testing'))
     55 
     56      exec_lua(function()
     57        local counter = 0
     58        local function add_counter()
     59          counter = counter + 1
     60        end
     61        local function get_counter()
     62          return counter
     63        end
     64        vim.g.AddCounter = add_counter
     65        vim.g.GetCounter = get_counter
     66        vim.g.fn = { add = add_counter, get = get_counter }
     67        vim.g.AddParens = function(s)
     68          return '(' .. s .. ')'
     69        end
     70      end)
     71 
     72      eq(0, eval('g:GetCounter()'))
     73      eval('g:AddCounter()')
     74      eq(1, eval('g:GetCounter()'))
     75      eval('g:AddCounter()')
     76      eq(2, eval('g:GetCounter()'))
     77      exec_lua([[vim.g.AddCounter()]])
     78      eq(3, exec_lua([[return vim.g.GetCounter()]]))
     79      exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
     80      eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
     81      exec_lua([[vim.g.fn.add()]])
     82      eq(5, exec_lua([[return vim.g.fn.get()]]))
     83      exec_lua([[vim.api.nvim_get_var('fn').add()]])
     84      eq(6, exec_lua([[return vim.api.nvim_get_var('fn').get()]]))
     85      eq('((foo))', eval([['foo'->AddParens()->AddParens()]]))
     86 
     87      exec_lua(function()
     88        local counter = 0
     89        local function add_counter()
     90          counter = counter + 1
     91        end
     92        local function get_counter()
     93          return counter
     94        end
     95        vim.api.nvim_set_var('AddCounter', add_counter)
     96        vim.api.nvim_set_var('GetCounter', get_counter)
     97        vim.api.nvim_set_var('fn', { add = add_counter, get = get_counter })
     98        vim.api.nvim_set_var('AddParens', function(s)
     99          return '(' .. s .. ')'
    100        end)
    101      end)
    102 
    103      eq(0, eval('g:GetCounter()'))
    104      eval('g:AddCounter()')
    105      eq(1, eval('g:GetCounter()'))
    106      eval('g:AddCounter()')
    107      eq(2, eval('g:GetCounter()'))
    108      exec_lua([[vim.g.AddCounter()]])
    109      eq(3, exec_lua([[return vim.g.GetCounter()]]))
    110      exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
    111      eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
    112      exec_lua([[vim.g.fn.add()]])
    113      eq(5, exec_lua([[return vim.g.fn.get()]]))
    114      exec_lua([[vim.api.nvim_get_var('fn').add()]])
    115      eq(6, exec_lua([[return vim.api.nvim_get_var('fn').get()]]))
    116      eq('((foo))', eval([['foo'->AddParens()->AddParens()]]))
    117 
    118      exec([[
    119        function Test()
    120        endfunction
    121        function s:Test()
    122        endfunction
    123        let g:Unknown_func = function('Test')
    124        let g:Unknown_script_func = function('s:Test')
    125      ]])
    126      eq(NIL, exec_lua([[return vim.g.Unknown_func]]))
    127      eq(NIL, exec_lua([[return vim.g.Unknown_script_func]]))
    128 
    129      -- Check if autoload works properly
    130      local pathsep = n.get_pathsep()
    131      local xhome = 'Xhome_lua'
    132      local xconfig = xhome .. pathsep .. 'Xconfig'
    133      local xdata = xhome .. pathsep .. 'Xdata'
    134      local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep)
    135      local autoload_file = table.concat({ autoload_folder, 'testload.vim' }, pathsep)
    136      mkdir_p(autoload_folder)
    137      write_file(autoload_file, [[let testload#value = 2]])
    138 
    139      clear { args_rm = { '-u' }, env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata } }
    140 
    141      eq(2, exec_lua("return vim.g['testload#value']"))
    142      rmdir(xhome)
    143    end)
    144 
    145    it('vim.b', function()
    146      exec_lua(function()
    147        vim.api.nvim_buf_set_var(0, 'testing', 'hi')
    148        vim.api.nvim_buf_set_var(0, 'other', 123)
    149        vim.api.nvim_buf_set_var(0, 'floaty', 5120.1)
    150        vim.api.nvim_buf_set_var(0, 'nullvar', vim.NIL)
    151        vim.api.nvim_buf_set_var(0, 'to_delete', { hello = 'world' })
    152        _G.BUF = vim.api.nvim_create_buf(false, true)
    153        vim.api.nvim_buf_set_var(_G.BUF, 'testing', 'bye')
    154      end)
    155 
    156      eq('hi', fn.luaeval 'vim.b.testing')
    157      eq('bye', fn.luaeval 'vim.b[BUF].testing')
    158      eq(123, fn.luaeval 'vim.b.other')
    159      eq(5120.1, fn.luaeval 'vim.b.floaty')
    160      eq(NIL, fn.luaeval 'vim.b.nonexistent')
    161      eq(NIL, fn.luaeval 'vim.b[BUF].nonexistent')
    162      eq(NIL, fn.luaeval 'vim.b.nullvar')
    163      -- lost over RPC, so test locally:
    164      eq_exec_lua({ false, true }, function()
    165        return { vim.b.nonexistent == vim.NIL, vim.b.nullvar == vim.NIL }
    166      end)
    167 
    168      matches(
    169        [[attempt to index .* nil value]],
    170        pcall_err(exec_lua, 'return vim.b[BUF][0].testing')
    171      )
    172 
    173      eq({ hello = 'world' }, fn.luaeval 'vim.b.to_delete')
    174      exec_lua [[
    175      vim.b.to_delete = nil
    176      ]]
    177      eq(NIL, fn.luaeval 'vim.b.to_delete')
    178 
    179      exec_lua(function()
    180        local counter = 0
    181        local function add_counter()
    182          counter = counter + 1
    183        end
    184        local function get_counter()
    185          return counter
    186        end
    187        vim.b.AddCounter = add_counter
    188        vim.b.GetCounter = get_counter
    189        vim.b.fn = { add = add_counter, get = get_counter }
    190        vim.b.AddParens = function(s)
    191          return '(' .. s .. ')'
    192        end
    193      end)
    194 
    195      eq(0, eval('b:GetCounter()'))
    196      eval('b:AddCounter()')
    197      eq(1, eval('b:GetCounter()'))
    198      eval('b:AddCounter()')
    199      eq(2, eval('b:GetCounter()'))
    200      exec_lua([[vim.b.AddCounter()]])
    201      eq(3, exec_lua([[return vim.b.GetCounter()]]))
    202      exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
    203      eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
    204      exec_lua([[vim.b.fn.add()]])
    205      eq(5, exec_lua([[return vim.b.fn.get()]]))
    206      exec_lua([[vim.api.nvim_buf_get_var(0, 'fn').add()]])
    207      eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'fn').get()]]))
    208      eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]]))
    209 
    210      exec_lua(function()
    211        local counter = 0
    212        local function add_counter()
    213          counter = counter + 1
    214        end
    215        local function get_counter()
    216          return counter
    217        end
    218        vim.api.nvim_buf_set_var(0, 'AddCounter', add_counter)
    219        vim.api.nvim_buf_set_var(0, 'GetCounter', get_counter)
    220        vim.api.nvim_buf_set_var(0, 'fn', { add = add_counter, get = get_counter })
    221        vim.api.nvim_buf_set_var(0, 'AddParens', function(s)
    222          return '(' .. s .. ')'
    223        end)
    224      end)
    225 
    226      eq(0, eval('b:GetCounter()'))
    227      eval('b:AddCounter()')
    228      eq(1, eval('b:GetCounter()'))
    229      eval('b:AddCounter()')
    230      eq(2, eval('b:GetCounter()'))
    231      exec_lua([[vim.b.AddCounter()]])
    232      eq(3, exec_lua([[return vim.b.GetCounter()]]))
    233      exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
    234      eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
    235      exec_lua([[vim.b.fn.add()]])
    236      eq(5, exec_lua([[return vim.b.fn.get()]]))
    237      exec_lua([[vim.api.nvim_buf_get_var(0, 'fn').add()]])
    238      eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'fn').get()]]))
    239      eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]]))
    240 
    241      exec([[
    242        function Test()
    243        endfunction
    244        function s:Test()
    245        endfunction
    246        let b:Unknown_func = function('Test')
    247        let b:Unknown_script_func = function('s:Test')
    248      ]])
    249      eq(NIL, exec_lua([[return vim.b.Unknown_func]]))
    250      eq(NIL, exec_lua([[return vim.b.Unknown_script_func]]))
    251 
    252      exec_lua [[
    253      vim.cmd "vnew"
    254      ]]
    255 
    256      eq(NIL, fn.luaeval 'vim.b.testing')
    257      eq(NIL, fn.luaeval 'vim.b.other')
    258      eq(NIL, fn.luaeval 'vim.b.nonexistent')
    259    end)
    260 
    261    it('vim.w', function()
    262      exec_lua [[
    263      vim.api.nvim_win_set_var(0, "testing", "hi")
    264      vim.api.nvim_win_set_var(0, "other", 123)
    265      vim.api.nvim_win_set_var(0, "to_delete", {hello="world"})
    266      BUF = vim.api.nvim_create_buf(false, true)
    267      WIN = vim.api.nvim_open_win(BUF, false, {
    268        width=10, height=10,
    269        relative='win', row=0, col=0
    270      })
    271      vim.api.nvim_win_set_var(WIN, "testing", "bye")
    272      ]]
    273 
    274      eq('hi', fn.luaeval 'vim.w.testing')
    275      eq('bye', fn.luaeval 'vim.w[WIN].testing')
    276      eq(123, fn.luaeval 'vim.w.other')
    277      eq(NIL, fn.luaeval 'vim.w.nonexistent')
    278      eq(NIL, fn.luaeval 'vim.w[WIN].nonexistent')
    279 
    280      matches(
    281        [[attempt to index .* nil value]],
    282        pcall_err(exec_lua, 'return vim.w[WIN][0].testing')
    283      )
    284 
    285      eq({ hello = 'world' }, fn.luaeval 'vim.w.to_delete')
    286      exec_lua [[
    287      vim.w.to_delete = nil
    288      ]]
    289      eq(NIL, fn.luaeval 'vim.w.to_delete')
    290 
    291      exec_lua [[
    292        local counter = 0
    293        local function add_counter() counter = counter + 1 end
    294        local function get_counter() return counter end
    295        vim.w.AddCounter = add_counter
    296        vim.w.GetCounter = get_counter
    297        vim.w.fn = {add = add_counter, get = get_counter}
    298        vim.w.AddParens = function(s) return '(' .. s .. ')' end
    299      ]]
    300 
    301      eq(0, eval('w:GetCounter()'))
    302      eval('w:AddCounter()')
    303      eq(1, eval('w:GetCounter()'))
    304      eval('w:AddCounter()')
    305      eq(2, eval('w:GetCounter()'))
    306      exec_lua([[vim.w.AddCounter()]])
    307      eq(3, exec_lua([[return vim.w.GetCounter()]]))
    308      exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
    309      eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
    310      exec_lua([[vim.w.fn.add()]])
    311      eq(5, exec_lua([[return vim.w.fn.get()]]))
    312      exec_lua([[vim.api.nvim_win_get_var(0, 'fn').add()]])
    313      eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'fn').get()]]))
    314      eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]]))
    315 
    316      exec_lua [[
    317        local counter = 0
    318        local function add_counter() counter = counter + 1 end
    319        local function get_counter() return counter end
    320        vim.api.nvim_win_set_var(0, 'AddCounter', add_counter)
    321        vim.api.nvim_win_set_var(0, 'GetCounter', get_counter)
    322        vim.api.nvim_win_set_var(0, 'fn', {add = add_counter, get = get_counter})
    323        vim.api.nvim_win_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end)
    324      ]]
    325 
    326      eq(0, eval('w:GetCounter()'))
    327      eval('w:AddCounter()')
    328      eq(1, eval('w:GetCounter()'))
    329      eval('w:AddCounter()')
    330      eq(2, eval('w:GetCounter()'))
    331      exec_lua([[vim.w.AddCounter()]])
    332      eq(3, exec_lua([[return vim.w.GetCounter()]]))
    333      exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
    334      eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
    335      exec_lua([[vim.w.fn.add()]])
    336      eq(5, exec_lua([[return vim.w.fn.get()]]))
    337      exec_lua([[vim.api.nvim_win_get_var(0, 'fn').add()]])
    338      eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'fn').get()]]))
    339      eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]]))
    340 
    341      exec([[
    342        function Test()
    343        endfunction
    344        function s:Test()
    345        endfunction
    346        let w:Unknown_func = function('Test')
    347        let w:Unknown_script_func = function('s:Test')
    348      ]])
    349      eq(NIL, exec_lua([[return vim.w.Unknown_func]]))
    350      eq(NIL, exec_lua([[return vim.w.Unknown_script_func]]))
    351 
    352      exec_lua [[
    353      vim.cmd "vnew"
    354      ]]
    355 
    356      eq(NIL, fn.luaeval 'vim.w.testing')
    357      eq(NIL, fn.luaeval 'vim.w.other')
    358      eq(NIL, fn.luaeval 'vim.w.nonexistent')
    359    end)
    360 
    361    it('vim.t', function()
    362      exec_lua [[
    363      vim.api.nvim_tabpage_set_var(0, "testing", "hi")
    364      vim.api.nvim_tabpage_set_var(0, "other", 123)
    365      vim.api.nvim_tabpage_set_var(0, "to_delete", {hello="world"})
    366      ]]
    367 
    368      eq('hi', fn.luaeval 'vim.t.testing')
    369      eq(123, fn.luaeval 'vim.t.other')
    370      eq(NIL, fn.luaeval 'vim.t.nonexistent')
    371      eq('hi', fn.luaeval 'vim.t[0].testing')
    372      eq(123, fn.luaeval 'vim.t[0].other')
    373      eq(NIL, fn.luaeval 'vim.t[0].nonexistent')
    374 
    375      matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.t[0][0].testing'))
    376 
    377      eq({ hello = 'world' }, fn.luaeval 'vim.t.to_delete')
    378      exec_lua [[
    379      vim.t.to_delete = nil
    380      ]]
    381      eq(NIL, fn.luaeval 'vim.t.to_delete')
    382 
    383      exec_lua [[
    384        local counter = 0
    385        local function add_counter() counter = counter + 1 end
    386        local function get_counter() return counter end
    387        vim.t.AddCounter = add_counter
    388        vim.t.GetCounter = get_counter
    389        vim.t.fn = {add = add_counter, get = get_counter}
    390        vim.t.AddParens = function(s) return '(' .. s .. ')' end
    391      ]]
    392 
    393      eq(0, eval('t:GetCounter()'))
    394      eval('t:AddCounter()')
    395      eq(1, eval('t:GetCounter()'))
    396      eval('t:AddCounter()')
    397      eq(2, eval('t:GetCounter()'))
    398      exec_lua([[vim.t.AddCounter()]])
    399      eq(3, exec_lua([[return vim.t.GetCounter()]]))
    400      exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
    401      eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
    402      exec_lua([[vim.t.fn.add()]])
    403      eq(5, exec_lua([[return vim.t.fn.get()]]))
    404      exec_lua([[vim.api.nvim_tabpage_get_var(0, 'fn').add()]])
    405      eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'fn').get()]]))
    406      eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]]))
    407 
    408      exec_lua [[
    409        local counter = 0
    410        local function add_counter() counter = counter + 1 end
    411        local function get_counter() return counter end
    412        vim.api.nvim_tabpage_set_var(0, 'AddCounter', add_counter)
    413        vim.api.nvim_tabpage_set_var(0, 'GetCounter', get_counter)
    414        vim.api.nvim_tabpage_set_var(0, 'fn', {add = add_counter, get = get_counter})
    415        vim.api.nvim_tabpage_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end)
    416      ]]
    417 
    418      eq(0, eval('t:GetCounter()'))
    419      eval('t:AddCounter()')
    420      eq(1, eval('t:GetCounter()'))
    421      eval('t:AddCounter()')
    422      eq(2, eval('t:GetCounter()'))
    423      exec_lua([[vim.t.AddCounter()]])
    424      eq(3, exec_lua([[return vim.t.GetCounter()]]))
    425      exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
    426      eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
    427      exec_lua([[vim.t.fn.add()]])
    428      eq(5, exec_lua([[return vim.t.fn.get()]]))
    429      exec_lua([[vim.api.nvim_tabpage_get_var(0, 'fn').add()]])
    430      eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'fn').get()]]))
    431      eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]]))
    432 
    433      exec_lua [[
    434      vim.cmd "tabnew"
    435      ]]
    436 
    437      eq(NIL, fn.luaeval 'vim.t.testing')
    438      eq(NIL, fn.luaeval 'vim.t.other')
    439      eq(NIL, fn.luaeval 'vim.t.nonexistent')
    440    end)
    441 
    442    it('vim.env', function()
    443      exec_lua([[vim.fn.setenv('A', 123)]])
    444      eq('123', fn.luaeval('vim.env.A'))
    445      exec_lua([[vim.env.A = 456]])
    446      eq('456', fn.luaeval('vim.env.A'))
    447      exec_lua([[vim.env.A = nil]])
    448      eq(NIL, fn.luaeval('vim.env.A'))
    449 
    450      eq(true, fn.luaeval('vim.env.B == nil'))
    451 
    452      command([[let $HOME = 'foo']])
    453      eq('foo', fn.expand('~'))
    454      eq('foo', fn.luaeval('vim.env.HOME'))
    455      exec_lua([[vim.env.HOME = nil]])
    456      eq('foo', fn.expand('~'))
    457      exec_lua([[vim.env.HOME = 'bar']])
    458      eq('bar', fn.expand('~'))
    459      eq('bar', fn.luaeval('vim.env.HOME'))
    460    end)
    461 
    462    it('vim.v', function()
    463      eq(fn.luaeval "vim.api.nvim_get_vvar('progpath')", fn.luaeval 'vim.v.progpath')
    464      eq(false, fn.luaeval "vim.v['false']")
    465      eq(NIL, fn.luaeval 'vim.v.null')
    466      matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.v[0].progpath'))
    467      matches('Key is read%-only: count$', pcall_err(exec_lua, [[vim.v.count = 42]]))
    468      matches('Dict is locked$', pcall_err(exec_lua, [[vim.v.nosuchvar = 42]]))
    469      matches('Key is fixed: errmsg$', pcall_err(exec_lua, [[vim.v.errmsg = nil]]))
    470      exec_lua([[vim.v.errmsg = 'set by Lua']])
    471      eq('set by Lua', eval('v:errmsg'))
    472      exec_lua([[vim.v.errmsg = 42]])
    473      eq('42', eval('v:errmsg'))
    474      exec_lua([[vim.v.oldfiles = { 'one', 'two' }]])
    475      eq({ 'one', 'two' }, eval('v:oldfiles'))
    476      exec_lua([[vim.v.oldfiles = {}]])
    477      eq({}, eval('v:oldfiles'))
    478      matches(
    479        'Setting v:oldfiles to value with wrong type$',
    480        pcall_err(exec_lua, [[vim.v.oldfiles = 'a']])
    481      )
    482      eq({}, eval('v:oldfiles'))
    483 
    484      feed('i foo foo foo<Esc>0/foo<CR>')
    485      eq({ 1, 1 }, api.nvim_win_get_cursor(0))
    486      eq(1, eval('v:searchforward'))
    487      feed('n')
    488      eq({ 1, 5 }, api.nvim_win_get_cursor(0))
    489      exec_lua([[vim.v.searchforward = 0]])
    490      eq(0, eval('v:searchforward'))
    491      feed('n')
    492      eq({ 1, 1 }, api.nvim_win_get_cursor(0))
    493      exec_lua([[vim.v.searchforward = 1]])
    494      eq(1, eval('v:searchforward'))
    495      feed('n')
    496      eq({ 1, 5 }, api.nvim_win_get_cursor(0))
    497 
    498      local screen = Screen.new(60, 3)
    499      eq(1, eval('v:hlsearch'))
    500      screen:expect {
    501        grid = [[
    502         {10:foo} {10:^foo} {10:foo}                                                |
    503        {1:~                                                           }|
    504                                                                    |
    505      ]],
    506      }
    507      exec_lua([[vim.v.hlsearch = 0]])
    508      eq(0, eval('v:hlsearch'))
    509      screen:expect {
    510        grid = [[
    511         foo ^foo foo                                                |
    512        {1:~                                                           }|
    513                                                                    |
    514      ]],
    515      }
    516      exec_lua([[vim.v.hlsearch = 1]])
    517      eq(1, eval('v:hlsearch'))
    518      screen:expect {
    519        grid = [[
    520         {10:foo} {10:^foo} {10:foo}                                                |
    521        {1:~                                                           }|
    522                                                                    |
    523      ]],
    524      }
    525    end)
    526  end)
    527 
    528  describe('options', function()
    529    describe('vim.bo', function()
    530      it('can get and set options', function()
    531        eq('', fn.luaeval 'vim.bo.filetype')
    532        exec_lua(function()
    533          _G.BUF = vim.api.nvim_create_buf(false, true)
    534          vim.api.nvim_set_option_value('filetype', 'markdown', {})
    535          vim.api.nvim_set_option_value('modifiable', false, { buf = _G.BUF })
    536        end)
    537        eq(false, fn.luaeval 'vim.bo.modified')
    538        eq('markdown', fn.luaeval 'vim.bo.filetype')
    539        eq(false, fn.luaeval 'vim.bo[BUF].modifiable')
    540        exec_lua(function()
    541          vim.bo.filetype = ''
    542          vim.bo[_G.BUF].modifiable = true
    543        end)
    544        eq('', fn.luaeval 'vim.bo.filetype')
    545        eq(true, fn.luaeval 'vim.bo[BUF].modifiable')
    546      end)
    547 
    548      it('errors', function()
    549        matches("Unknown option 'nosuchopt'$", pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
    550        matches('Expected Lua string$', pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
    551        matches('Invalid buffer id: %-1$', pcall_err(exec_lua, 'return vim.bo[-1].filetype'))
    552      end)
    553    end)
    554 
    555    describe('vim.wo', function()
    556      it('can get and set options', function()
    557        exec_lua(function()
    558          vim.api.nvim_set_option_value('cole', 2, {})
    559          vim.cmd 'split'
    560          vim.api.nvim_set_option_value('cole', 2, {})
    561        end)
    562        eq(2, fn.luaeval 'vim.wo.cole')
    563        exec_lua(function()
    564          vim.wo.conceallevel = 0
    565        end)
    566        eq(0, fn.luaeval 'vim.wo.cole')
    567        eq(0, fn.luaeval 'vim.wo[0].cole')
    568        eq(0, fn.luaeval 'vim.wo[1001].cole')
    569        matches("Unknown option 'notanopt'$", pcall_err(exec_lua, 'return vim.wo.notanopt'))
    570        matches('Invalid window id: %-1$', pcall_err(exec_lua, 'return vim.wo[-1].list'))
    571        eq(2, fn.luaeval 'vim.wo[1000].cole')
    572        exec_lua(function()
    573          vim.wo[1000].cole = 0
    574        end)
    575        eq(0, fn.luaeval 'vim.wo[1000].cole')
    576 
    577        -- Can handle global-local values
    578        exec_lua [[vim.o.scrolloff = 100]]
    579        exec_lua [[vim.wo.scrolloff = 200]]
    580        eq(200, fn.luaeval 'vim.wo.scrolloff')
    581        exec_lua [[vim.wo.scrolloff = -1]]
    582        eq(100, fn.luaeval 'vim.wo.scrolloff')
    583        exec_lua(function()
    584          vim.wo[0][0].scrolloff = 200
    585          vim.cmd 'enew'
    586        end)
    587        eq(100, fn.luaeval 'vim.wo.scrolloff')
    588      end)
    589 
    590      it('errors', function()
    591        matches('only bufnr=0 is supported', pcall_err(exec_lua, 'vim.wo[0][10].signcolumn = "no"'))
    592        matches(
    593          'only bufnr=0 is supported',
    594          pcall_err(exec_lua, 'local a = vim.wo[0][10].signcolumn')
    595        )
    596      end)
    597    end)
    598 
    599    describe('vim.opt', function()
    600      -- TODO: We still need to write some tests for optlocal, opt and then getting the options
    601      --  Probably could also do some stuff with getting things from viml side as well to confirm behavior is the same.
    602 
    603      it('allows setting number values', function()
    604        local scrolloff = exec_lua [[
    605          vim.opt.scrolloff = 10
    606          return vim.o.scrolloff
    607        ]]
    608        eq(10, scrolloff)
    609      end)
    610 
    611      pending('handles STUPID window things', function()
    612        eq_exec_lua({}, function()
    613          return {
    614            vim.api.nvim_get_option_value('scrolloff', { scope = 'global' }),
    615            vim.api.nvim_get_option_value('scrolloff', { win = 0 }),
    616          }
    617        end)
    618      end)
    619 
    620      it('allows setting tables', function()
    621        eq_exec_lua('hello,world', function()
    622          vim.opt.wildignore = { 'hello', 'world' }
    623          return vim.o.wildignore
    624        end)
    625      end)
    626 
    627      it('allows setting tables with shortnames', function()
    628        eq_exec_lua('hello,world', function()
    629          vim.opt.wig = { 'hello', 'world' }
    630          return vim.o.wildignore
    631        end)
    632      end)
    633 
    634      it('errors when you attempt to set string values to numeric options', function()
    635        eq_exec_lua(false, function()
    636          return ({
    637            pcall(function()
    638              vim.opt.textwidth = 'hello world'
    639            end),
    640          })[1]
    641        end)
    642      end)
    643 
    644      it('errors when you attempt to setlocal a global value', function()
    645        eq_exec_lua(false, function()
    646          return pcall(function()
    647            vim.opt_local.clipboard = 'hello'
    648          end)
    649        end)
    650      end)
    651 
    652      it('allows you to set boolean values', function()
    653        eq_exec_lua({ true, false, true }, function()
    654          local results = {}
    655 
    656          vim.opt.autoindent = true
    657          table.insert(results, vim.bo.autoindent)
    658 
    659          vim.opt.autoindent = false
    660          table.insert(results, vim.bo.autoindent)
    661 
    662          vim.opt.autoindent = not vim.opt.autoindent:get()
    663          table.insert(results, vim.bo.autoindent)
    664 
    665          return results
    666        end)
    667      end)
    668 
    669      it('changes current buffer values and defaults for global local values', function()
    670        local result = exec_lua(function()
    671          local result = {}
    672 
    673          vim.opt.makeprg = 'global-local'
    674          table.insert(result, vim.go.makeprg)
    675          table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
    676 
    677          vim.opt_local.mp = 'only-local'
    678          table.insert(result, vim.go.makeprg)
    679          table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
    680 
    681          vim.opt_global.makeprg = 'only-global'
    682          table.insert(result, vim.go.makeprg)
    683          table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
    684 
    685          vim.opt.makeprg = 'global-local'
    686          table.insert(result, vim.go.makeprg)
    687          table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
    688          return result
    689        end)
    690 
    691        -- Set -> global & local
    692        eq('global-local', result[1])
    693        eq('', result[2])
    694 
    695        -- Setlocal -> only local
    696        eq('global-local', result[3])
    697        eq('only-local', result[4])
    698 
    699        -- Setglobal -> only global
    700        eq('only-global', result[5])
    701        eq('only-local', result[6])
    702 
    703        -- Set -> sets global value and resets local value
    704        eq('global-local', result[7])
    705        eq('', result[8])
    706      end)
    707 
    708      it('allows you to retrieve window opts even if they have not been set', function()
    709        eq_exec_lua({ false, false, true, true }, function()
    710          local result = {}
    711          table.insert(result, vim.opt.number:get())
    712          table.insert(result, vim.opt_local.number:get())
    713 
    714          vim.opt_local.number = true
    715          table.insert(result, vim.opt.number:get())
    716          table.insert(result, vim.opt_local.number:get())
    717 
    718          return result
    719        end)
    720      end)
    721 
    722      it('allows all sorts of string manipulation', function()
    723        eq_exec_lua({ 'hello', 'hello world', 'start hello world' }, function()
    724          local results = {}
    725 
    726          vim.opt.makeprg = 'hello'
    727          table.insert(results, vim.o.makeprg)
    728 
    729          vim.opt.makeprg = vim.opt.makeprg + ' world'
    730          table.insert(results, vim.o.makeprg)
    731 
    732          vim.opt.makeprg = vim.opt.makeprg ^ 'start '
    733          table.insert(results, vim.o.makeprg)
    734 
    735          return results
    736        end)
    737      end)
    738 
    739      describe('option:get()', function()
    740        it('works for boolean values', function()
    741          eq_exec_lua(false, function()
    742            vim.opt.number = false
    743            return vim.opt.number:get()
    744          end)
    745        end)
    746 
    747        it('works for number values', function()
    748          eq_exec_lua(10, function()
    749            vim.opt.tabstop = 10
    750            return vim.opt.tabstop:get()
    751          end)
    752        end)
    753 
    754        it('works for string values', function()
    755          eq_exec_lua('hello world', function()
    756            vim.opt.makeprg = 'hello world'
    757            return vim.opt.makeprg:get()
    758          end)
    759        end)
    760 
    761        it('works for set type flaglists', function()
    762          local formatoptions = exec_lua(function()
    763            vim.opt.formatoptions = 'tcro'
    764            return vim.opt.formatoptions:get()
    765          end)
    766 
    767          eq(true, formatoptions.t)
    768          eq(true, not formatoptions.q)
    769        end)
    770 
    771        it('works for set type flaglists', function()
    772          local formatoptions = exec_lua(function()
    773            vim.opt.formatoptions = { t = true, c = true, r = true, o = true }
    774            return vim.opt.formatoptions:get()
    775          end)
    776 
    777          eq(true, formatoptions.t)
    778          eq(true, not formatoptions.q)
    779        end)
    780 
    781        it('works for array list type options', function()
    782          local wildignore = exec_lua(function()
    783            vim.opt.wildignore = '*.c,*.o,__pycache__'
    784            return vim.opt.wildignore:get()
    785          end)
    786 
    787          eq(3, #wildignore)
    788          eq('*.c', wildignore[1])
    789        end)
    790 
    791        it('works for options that are both commalist and flaglist', function()
    792          eq_exec_lua({ b = true, s = true }, function()
    793            vim.opt.whichwrap = 'b,s'
    794            return vim.opt.whichwrap:get()
    795          end)
    796 
    797          eq_exec_lua({ b = true, h = true }, function()
    798            vim.opt.whichwrap = { b = true, s = false, h = true }
    799            return vim.opt.whichwrap:get()
    800          end)
    801        end)
    802 
    803        it('works for key-value pair options', function()
    804          eq_exec_lua({ tab = '> ', space = '_' }, function()
    805            vim.opt.listchars = 'tab:> ,space:_'
    806            return vim.opt.listchars:get()
    807          end)
    808        end)
    809 
    810        it('allows you to add numeric options', function()
    811          eq_exec_lua(16, function()
    812            vim.opt.tabstop = 12
    813            vim.opt.tabstop = vim.opt.tabstop + 4
    814            return vim.bo.tabstop
    815          end)
    816        end)
    817 
    818        it('allows you to subtract numeric options', function()
    819          eq_exec_lua(2, function()
    820            vim.opt.tabstop = 4
    821            vim.opt.tabstop = vim.opt.tabstop - 2
    822            return vim.bo.tabstop
    823          end)
    824        end)
    825      end)
    826 
    827      describe('key:value style options', function()
    828        it('handles dict style', function()
    829          eq_exec_lua('eol:~,space:.', function()
    830            vim.opt.listchars = { eol = '~', space = '.' }
    831            return vim.o.listchars
    832          end)
    833        end)
    834 
    835        it('allows adding dict style', function()
    836          eq_exec_lua('eol:~,space:-', function()
    837            vim.opt.listchars = { eol = '~', space = '.' }
    838            vim.opt.listchars = vim.opt.listchars + { space = '-' }
    839            return vim.o.listchars
    840          end)
    841        end)
    842 
    843        it('allows adding dict style', function()
    844          eq_exec_lua('eol:~,space:_', function()
    845            vim.opt.listchars = { eol = '~', space = '.' }
    846            vim.opt.listchars = vim.opt.listchars + { space = '-' } + { space = '_' }
    847            return vim.o.listchars
    848          end)
    849        end)
    850 
    851        it('allows completely new keys', function()
    852          eq_exec_lua('eol:~,space:.,tab:>>>', function()
    853            vim.opt.listchars = { eol = '~', space = '.' }
    854            vim.opt.listchars = vim.opt.listchars + { tab = '>>>' }
    855            return vim.o.listchars
    856          end)
    857        end)
    858 
    859        it('allows subtracting dict style', function()
    860          eq_exec_lua('eol:~', function()
    861            vim.opt.listchars = { eol = '~', space = '.' }
    862            vim.opt.listchars = vim.opt.listchars - 'space'
    863            return vim.o.listchars
    864          end)
    865        end)
    866 
    867        it('allows subtracting dict style', function()
    868          eq_exec_lua('', function()
    869            vim.opt.listchars = { eol = '~', space = '.' }
    870            vim.opt.listchars = vim.opt.listchars - 'space' - 'eol'
    871            return vim.o.listchars
    872          end)
    873        end)
    874 
    875        it('allows subtracting dict style multiple times', function()
    876          eq_exec_lua('eol:~', function()
    877            vim.opt.listchars = { eol = '~', space = '.' }
    878            vim.opt.listchars = vim.opt.listchars - 'space' - 'space'
    879            return vim.o.listchars
    880          end)
    881        end)
    882 
    883        it('allows adding a key:value string to a listchars', function()
    884          eq_exec_lua('eol:~,space:.,tab:>~', function()
    885            vim.opt.listchars = { eol = '~', space = '.' }
    886            vim.opt.listchars = vim.opt.listchars + 'tab:>~'
    887            return vim.o.listchars
    888          end)
    889        end)
    890 
    891        it('allows prepending a key:value string to a listchars', function()
    892          eq_exec_lua('eol:~,space:.,tab:>~', function()
    893            vim.opt.listchars = { eol = '~', space = '.' }
    894            vim.opt.listchars = vim.opt.listchars ^ 'tab:>~'
    895            return vim.o.listchars
    896          end)
    897        end)
    898      end)
    899 
    900      it('automatically sets when calling remove', function()
    901        eq_exec_lua('foo,baz', function()
    902          vim.opt.wildignore = 'foo,bar,baz'
    903          vim.opt.wildignore:remove('bar')
    904          return vim.o.wildignore
    905        end)
    906      end)
    907 
    908      it('automatically sets when calling remove with a table', function()
    909        eq_exec_lua('foo', function()
    910          vim.opt.wildignore = 'foo,bar,baz'
    911          vim.opt.wildignore:remove { 'bar', 'baz' }
    912          return vim.o.wildignore
    913        end)
    914      end)
    915 
    916      it('automatically sets when calling append', function()
    917        eq_exec_lua('foo,bar,baz,bing', function()
    918          vim.opt.wildignore = 'foo,bar,baz'
    919          vim.opt.wildignore:append('bing')
    920          return vim.o.wildignore
    921        end)
    922      end)
    923 
    924      it('automatically sets when calling append with a table', function()
    925        eq_exec_lua('foo,bar,baz,bing,zap', function()
    926          vim.opt.wildignore = 'foo,bar,baz'
    927          vim.opt.wildignore:append { 'bing', 'zap' }
    928          return vim.o.wildignore
    929        end)
    930      end)
    931 
    932      it('allows adding tables', function()
    933        eq_exec_lua('foo', function()
    934          vim.opt.wildignore = 'foo'
    935          return vim.o.wildignore
    936        end)
    937 
    938        eq_exec_lua('foo,bar,baz', function()
    939          vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
    940          return vim.o.wildignore
    941        end)
    942      end)
    943 
    944      it('handles adding duplicates', function()
    945        eq_exec_lua('foo', function()
    946          vim.opt.wildignore = 'foo'
    947          return vim.o.wildignore
    948        end)
    949 
    950        eq_exec_lua('foo,bar,baz', function()
    951          vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
    952          return vim.o.wildignore
    953        end)
    954 
    955        eq_exec_lua('foo,bar,baz', function()
    956          vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
    957          return vim.o.wildignore
    958        end)
    959      end)
    960 
    961      it('allows adding multiple times', function()
    962        eq_exec_lua('foo,bar,baz', function()
    963          vim.opt.wildignore = 'foo'
    964          vim.opt.wildignore = vim.opt.wildignore + 'bar' + 'baz'
    965          return vim.o.wildignore
    966        end)
    967      end)
    968 
    969      it('removes values when you use minus', function()
    970        eq_exec_lua('foo', function()
    971          vim.opt.wildignore = 'foo'
    972          return vim.o.wildignore
    973        end)
    974 
    975        eq_exec_lua('foo,bar,baz', function()
    976          vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
    977          return vim.o.wildignore
    978        end)
    979 
    980        eq_exec_lua('foo,baz', function()
    981          vim.opt.wildignore = vim.opt.wildignore - 'bar'
    982          return vim.o.wildignore
    983        end)
    984      end)
    985 
    986      it('prepends values when using ^', function()
    987        eq_exec_lua('first,foo', function()
    988          vim.opt.wildignore = 'foo'
    989          vim.opt.wildignore = vim.opt.wildignore ^ 'first'
    990          return vim.o.wildignore
    991        end)
    992 
    993        eq_exec_lua('super_first,first,foo', function()
    994          vim.opt.wildignore = vim.opt.wildignore ^ 'super_first'
    995          return vim.o.wildignore
    996        end)
    997      end)
    998 
    999      it('does not remove duplicates from wildmode: #14708', function()
   1000        eq_exec_lua('full,list,full', function()
   1001          vim.opt.wildmode = { 'full', 'list', 'full' }
   1002          return vim.o.wildmode
   1003        end)
   1004      end)
   1005 
   1006      describe('option types', function()
   1007        it('allows to set option with numeric value', function()
   1008          eq_exec_lua(4, function()
   1009            vim.opt.tabstop = 4
   1010            return vim.bo.tabstop
   1011          end)
   1012 
   1013          matches(
   1014            "Invalid option type 'string' for 'tabstop'",
   1015            pcall_err(exec_lua, [[vim.opt.tabstop = '4']])
   1016          )
   1017          matches(
   1018            "Invalid option type 'boolean' for 'tabstop'",
   1019            pcall_err(exec_lua, [[vim.opt.tabstop = true]])
   1020          )
   1021          matches(
   1022            "Invalid option type 'table' for 'tabstop'",
   1023            pcall_err(exec_lua, [[vim.opt.tabstop = {4, 2}]])
   1024          )
   1025          matches(
   1026            "Invalid option type 'function' for 'tabstop'",
   1027            pcall_err(exec_lua, [[vim.opt.tabstop = function() return 4 end]])
   1028          )
   1029        end)
   1030 
   1031        it('allows to set option with boolean value', function()
   1032          eq_exec_lua(true, function()
   1033            vim.opt.undofile = true
   1034            return vim.bo.undofile
   1035          end)
   1036 
   1037          matches(
   1038            "Invalid option type 'number' for 'undofile'",
   1039            pcall_err(exec_lua, [[vim.opt.undofile = 0]])
   1040          )
   1041          matches(
   1042            "Invalid option type 'table' for 'undofile'",
   1043            pcall_err(exec_lua, [[vim.opt.undofile = {true}]])
   1044          )
   1045          matches(
   1046            "Invalid option type 'string' for 'undofile'",
   1047            pcall_err(exec_lua, [[vim.opt.undofile = 'true']])
   1048          )
   1049          matches(
   1050            "Invalid option type 'function' for 'undofile'",
   1051            pcall_err(exec_lua, [[vim.opt.undofile = function() return true end]])
   1052          )
   1053        end)
   1054 
   1055        it('allows to set option with array or string value', function()
   1056          eq_exec_lua('indent,eol,start', function()
   1057            vim.opt.backspace = { 'indent', 'eol', 'start' }
   1058            return vim.go.backspace
   1059          end)
   1060 
   1061          eq_exec_lua('indent,eol,start', function()
   1062            vim.opt.backspace = 'indent,eol,start'
   1063            return vim.go.backspace
   1064          end)
   1065 
   1066          matches(
   1067            "Invalid option type 'boolean' for 'backspace'",
   1068            pcall_err(exec_lua, [[vim.opt.backspace = true]])
   1069          )
   1070          matches(
   1071            "Invalid option type 'number' for 'backspace'",
   1072            pcall_err(exec_lua, [[vim.opt.backspace = 2]])
   1073          )
   1074          matches(
   1075            "Invalid option type 'function' for 'backspace'",
   1076            pcall_err(exec_lua, [[vim.opt.backspace = function() return 'indent,eol,start' end]])
   1077          )
   1078        end)
   1079 
   1080        it('allows set option with map or string value', function()
   1081          eq_exec_lua('eol:~,space:.', function()
   1082            vim.opt.listchars = { eol = '~', space = '.' }
   1083            return vim.o.listchars
   1084          end)
   1085 
   1086          eq_exec_lua('eol:~,space:.,tab:>~', function()
   1087            vim.opt.listchars = 'eol:~,space:.,tab:>~'
   1088            return vim.o.listchars
   1089          end)
   1090 
   1091          matches(
   1092            "Invalid option type 'boolean' for 'listchars'",
   1093            pcall_err(exec_lua, [[vim.opt.listchars = true]])
   1094          )
   1095          matches(
   1096            "Invalid option type 'number' for 'listchars'",
   1097            pcall_err(exec_lua, [[vim.opt.listchars = 2]])
   1098          )
   1099          matches(
   1100            "Invalid option type 'function' for 'listchars'",
   1101            pcall_err(
   1102              exec_lua,
   1103              [[vim.opt.listchars = function() return "eol:~,space:.,tab:>~" end]]
   1104            )
   1105          )
   1106        end)
   1107 
   1108        it('allows set option with set or string value', function()
   1109          eq_exec_lua('b,s', function()
   1110            vim.opt.whichwrap = { b = true, s = 1 }
   1111            return vim.go.whichwrap
   1112          end)
   1113 
   1114          eq_exec_lua('b,s,<,>,[,]', function()
   1115            vim.opt.whichwrap = 'b,s,<,>,[,]'
   1116            return vim.go.whichwrap
   1117          end)
   1118 
   1119          matches(
   1120            "Invalid option type 'boolean' for 'whichwrap'",
   1121            pcall_err(exec_lua, [[vim.opt.whichwrap = true]])
   1122          )
   1123          matches(
   1124            "Invalid option type 'number' for 'whichwrap'",
   1125            pcall_err(exec_lua, [[vim.opt.whichwrap = 2]])
   1126          )
   1127          matches(
   1128            "Invalid option type 'function' for 'whichwrap'",
   1129            pcall_err(exec_lua, [[vim.opt.whichwrap = function() return "b,s,<,>,[,]" end]])
   1130          )
   1131        end)
   1132      end)
   1133 
   1134      -- isfname=a,b,c,,,d,e,f
   1135      it('can handle isfname ,,,', function()
   1136        eq_exec_lua({ { ',', 'a', 'b', 'c' }, 'a,b,,,c' }, function()
   1137          vim.opt.isfname = 'a,b,,,c'
   1138          return { vim.opt.isfname:get(), vim.go.isfname }
   1139        end)
   1140      end)
   1141 
   1142      -- isfname=a,b,c,^,,def
   1143      it('can handle isfname ,^,,', function()
   1144        eq_exec_lua({ { '^,', 'a', 'b', 'c' }, 'a,b,^,,c' }, function()
   1145          vim.opt.isfname = 'a,b,^,,c'
   1146          return { vim.opt.isfname:get(), vim.go.isfname }
   1147        end)
   1148      end)
   1149 
   1150      describe('https://github.com/neovim/neovim/issues/14828', function()
   1151        it('gives empty list when item is empty:array', function()
   1152          eq_exec_lua({}, function()
   1153            vim.cmd('set wildignore=')
   1154            return vim.opt.wildignore:get()
   1155          end)
   1156 
   1157          eq_exec_lua({}, function()
   1158            vim.opt.wildignore = {}
   1159            return vim.opt.wildignore:get()
   1160          end)
   1161        end)
   1162 
   1163        it('gives empty list when item is empty:set', function()
   1164          eq_exec_lua({}, function()
   1165            vim.cmd('set formatoptions=')
   1166            return vim.opt.formatoptions:get()
   1167          end)
   1168 
   1169          eq_exec_lua({}, function()
   1170            vim.opt.formatoptions = {}
   1171            return vim.opt.formatoptions:get()
   1172          end)
   1173        end)
   1174 
   1175        it('does not append to empty item', function()
   1176          eq_exec_lua({ '*.foo', '*.bar' }, function()
   1177            vim.opt.wildignore = {}
   1178            vim.opt.wildignore:append { '*.foo', '*.bar' }
   1179            return vim.opt.wildignore:get()
   1180          end)
   1181        end)
   1182 
   1183        it('does not prepend to empty item', function()
   1184          eq_exec_lua({ '*.foo', '*.bar' }, function()
   1185            vim.opt.wildignore = {}
   1186            vim.opt.wildignore:prepend { '*.foo', '*.bar' }
   1187            return vim.opt.wildignore:get()
   1188          end)
   1189        end)
   1190 
   1191        it('append to empty set', function()
   1192          eq_exec_lua({ t = true }, function()
   1193            vim.opt.formatoptions = {}
   1194            vim.opt.formatoptions:append('t')
   1195            return vim.opt.formatoptions:get()
   1196          end)
   1197        end)
   1198 
   1199        it('prepend to empty set', function()
   1200          eq_exec_lua({ t = true }, function()
   1201            vim.opt.formatoptions = {}
   1202            vim.opt.formatoptions:prepend('t')
   1203            return vim.opt.formatoptions:get()
   1204          end)
   1205        end)
   1206      end)
   1207    end) -- vim.opt
   1208 
   1209    describe('vim.opt_local', function()
   1210      it('appends into global value when changing local option value', function()
   1211        eq_exec_lua('foo,bar,baz,qux', function()
   1212          vim.opt.tags = 'foo,bar'
   1213          vim.opt_local.tags:append('baz')
   1214          vim.opt_local.tags:append('qux')
   1215          return vim.bo.tags
   1216        end)
   1217      end)
   1218    end)
   1219 
   1220    describe('vim.opt_global', function()
   1221      it('gets current global option value', function()
   1222        eq_exec_lua({ 'yes' }, function()
   1223          vim.cmd 'setglobal signcolumn=yes'
   1224          return { vim.opt_global.signcolumn:get() }
   1225        end)
   1226      end)
   1227    end)
   1228  end)
   1229 end)