123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- local t = require('test.testutil')
- local n = require('test.functional.testnvim')()
- local call = n.call
- local clear = n.clear
- local command = n.command
- local eq = t.eq
- local eval = n.eval
- local feed = n.feed
- local map = vim.tbl_map
- local api = n.api
- local parse_context = n.parse_context
- local exec_capture = n.exec_capture
- local source = n.source
- local trim = vim.trim
- local write_file = t.write_file
- local pcall_err = t.pcall_err
- describe('context functions', function()
- local fname1 = 'Xtest-functional-eval-ctx1'
- local fname2 = 'Xtest-functional-eval-ctx2'
- local outofbounds = 'Vim:E475: Invalid value for argument index: out of bounds'
- before_each(function()
- clear()
- write_file(fname1, '1\n2\n3')
- write_file(fname2, 'a\nb\nc')
- end)
- after_each(function()
- os.remove(fname1)
- os.remove(fname2)
- end)
- describe('ctxpush/ctxpop', function()
- it('saves and restores registers properly', function()
- local regs = { '1', '2', '3', 'a' }
- local vals = { '1', '2', '3', 'hjkl' }
- feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
- eq(
- vals,
- map(function(r)
- return trim(call('getreg', r))
- end, regs)
- )
- call('ctxpush')
- call('ctxpush', { 'regs' })
- map(function(r)
- call('setreg', r, {})
- end, regs)
- eq(
- { '', '', '', '' },
- map(function(r)
- return trim(call('getreg', r))
- end, regs)
- )
- call('ctxpop')
- eq(
- vals,
- map(function(r)
- return trim(call('getreg', r))
- end, regs)
- )
- map(function(r)
- call('setreg', r, {})
- end, regs)
- eq(
- { '', '', '', '' },
- map(function(r)
- return trim(call('getreg', r))
- end, regs)
- )
- call('ctxpop')
- eq(
- vals,
- map(function(r)
- return trim(call('getreg', r))
- end, regs)
- )
- end)
- it('saves and restores jumplist properly', function()
- command('edit ' .. fname1)
- feed('G')
- feed('gg')
- command('edit ' .. fname2)
- local jumplist = call('getjumplist')
- call('ctxpush')
- call('ctxpush', { 'jumps' })
- command('clearjumps')
- eq({ {}, 0 }, call('getjumplist'))
- call('ctxpop')
- eq(jumplist, call('getjumplist'))
- command('clearjumps')
- eq({ {}, 0 }, call('getjumplist'))
- call('ctxpop')
- eq(jumplist, call('getjumplist'))
- end)
- it('saves and restores buffer list properly', function()
- command('edit ' .. fname1)
- command('edit ' .. fname2)
- command('edit TEST')
- local bufs = call('map', call('getbufinfo'), 'v:val.name')
- call('ctxpush')
- call('ctxpush', { 'bufs' })
- command('%bwipeout')
- eq({ '' }, call('map', call('getbufinfo'), 'v:val.name'))
- call('ctxpop')
- eq({ '', unpack(bufs) }, call('map', call('getbufinfo'), 'v:val.name'))
- command('%bwipeout')
- eq({ '' }, call('map', call('getbufinfo'), 'v:val.name'))
- call('ctxpop')
- eq({ '', unpack(bufs) }, call('map', call('getbufinfo'), 'v:val.name'))
- end)
- it('saves and restores global variables properly', function()
- api.nvim_set_var('one', 1)
- api.nvim_set_var('Two', 2)
- api.nvim_set_var('THREE', 3)
- eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
- call('ctxpush')
- call('ctxpush', { 'gvars' })
- api.nvim_del_var('one')
- api.nvim_del_var('Two')
- api.nvim_del_var('THREE')
- eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
- eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
- eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
- call('ctxpop')
- eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
- api.nvim_del_var('one')
- api.nvim_del_var('Two')
- api.nvim_del_var('THREE')
- eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
- eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
- eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
- call('ctxpop')
- eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
- end)
- it('saves and restores script functions properly', function()
- source([[
- function s:greet(name)
- echom 'Hello, '.a:name.'!'
- endfunction
- function s:greet_all(name, ...)
- echom 'Hello, '.a:name.'!'
- for more in a:000
- echom 'Hello, '.more.'!'
- endfor
- endfunction
- function Greet(name)
- call call('s:greet', [a:name])
- endfunction
- function GreetAll(name, ...)
- call call('s:greet_all', extend([a:name], a:000))
- endfunction
- function SaveSFuncs()
- call ctxpush(['sfuncs'])
- endfunction
- function DeleteSFuncs()
- delfunction s:greet
- delfunction s:greet_all
- endfunction
- function RestoreFuncs()
- call ctxpop()
- endfunction
- ]])
- eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq(
- 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
- )
- call('SaveSFuncs')
- call('DeleteSFuncs')
- eq(
- 'function Greet, line 1: Vim(call):E117: Unknown function: s:greet',
- pcall_err(command, [[call Greet('World')]])
- )
- eq(
- 'function GreetAll, line 1: Vim(call):E117: Unknown function: s:greet_all',
- pcall_err(command, [[call GreetAll('World', 'One', 'Two', 'Three')]])
- )
- call('RestoreFuncs')
- eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq(
- 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
- )
- end)
- it('saves and restores functions properly', function()
- source([[
- function Greet(name)
- echom 'Hello, '.a:name.'!'
- endfunction
- function GreetAll(name, ...)
- echom 'Hello, '.a:name.'!'
- for more in a:000
- echom 'Hello, '.more.'!'
- endfor
- endfunction
- ]])
- eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq(
- 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
- )
- call('ctxpush', { 'funcs' })
- command('delfunction Greet')
- command('delfunction GreetAll')
- eq('Vim:E117: Unknown function: Greet', pcall_err(call, 'Greet', 'World'))
- eq(
- 'Vim:E117: Unknown function: GreetAll',
- pcall_err(call, 'GreetAll', 'World', 'One', 'Two', 'Three')
- )
- call('ctxpop')
- eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq(
- 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
- )
- end)
- it('errors out when context stack is empty', function()
- local err = 'Vim:Context stack is empty'
- eq(err, pcall_err(call, 'ctxpop'))
- eq(err, pcall_err(call, 'ctxpop'))
- call('ctxpush')
- call('ctxpush')
- call('ctxpop')
- call('ctxpop')
- eq(err, pcall_err(call, 'ctxpop'))
- end)
- end)
- describe('ctxsize()', function()
- it('returns context stack size', function()
- eq(0, call('ctxsize'))
- call('ctxpush')
- eq(1, call('ctxsize'))
- call('ctxpush')
- eq(2, call('ctxsize'))
- call('ctxpush')
- eq(3, call('ctxsize'))
- call('ctxpop')
- eq(2, call('ctxsize'))
- call('ctxpop')
- eq(1, call('ctxsize'))
- call('ctxpop')
- eq(0, call('ctxsize'))
- end)
- end)
- describe('ctxget()', function()
- it('errors out when index is out of bounds', function()
- eq(outofbounds, pcall_err(call, 'ctxget'))
- call('ctxpush')
- eq(outofbounds, pcall_err(call, 'ctxget', 1))
- call('ctxpop')
- eq(outofbounds, pcall_err(call, 'ctxget', 0))
- end)
- it('returns context dict at index in context stack', function()
- feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
- command('edit! ' .. fname1)
- feed('G')
- feed('gg')
- command('edit ' .. fname2)
- api.nvim_set_var('one', 1)
- api.nvim_set_var('Two', 2)
- api.nvim_set_var('THREE', 3)
- local with_regs = {
- ['regs'] = {
- { ['rt'] = 1, ['rc'] = { '1' }, ['n'] = 49, ['ru'] = true },
- { ['rt'] = 1, ['rc'] = { '2' }, ['n'] = 50 },
- { ['rt'] = 1, ['rc'] = { '3' }, ['n'] = 51 },
- { ['rc'] = { 'hjkl' }, ['n'] = 97 },
- },
- }
- local with_jumps = {
- ['jumps'] = eval((([[
- filter(map(add(
- getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
- 'filter(
- { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
- { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
- ]]):gsub('\n', ''))),
- }
- local with_bufs = {
- ['bufs'] = eval([[
- filter(map(getbufinfo(), '{ "f": v:val.name }'), '!empty(v:val.f)')
- ]]),
- }
- local with_gvars = {
- ['gvars'] = { { 'one', 1 }, { 'Two', 2 }, { 'THREE', 3 } },
- }
- local with_all = {
- ['regs'] = with_regs['regs'],
- ['jumps'] = with_jumps['jumps'],
- ['bufs'] = with_bufs['bufs'],
- ['gvars'] = with_gvars['gvars'],
- }
- call('ctxpush')
- eq(with_all, parse_context(call('ctxget')))
- eq(with_all, parse_context(call('ctxget', 0)))
- call('ctxpush', { 'gvars' })
- eq(with_gvars, parse_context(call('ctxget')))
- eq(with_gvars, parse_context(call('ctxget', 0)))
- eq(with_all, parse_context(call('ctxget', 1)))
- call('ctxpush', { 'bufs' })
- eq(with_bufs, parse_context(call('ctxget')))
- eq(with_bufs, parse_context(call('ctxget', 0)))
- eq(with_gvars, parse_context(call('ctxget', 1)))
- eq(with_all, parse_context(call('ctxget', 2)))
- call('ctxpush', { 'jumps' })
- eq(with_jumps, parse_context(call('ctxget')))
- eq(with_jumps, parse_context(call('ctxget', 0)))
- eq(with_bufs, parse_context(call('ctxget', 1)))
- eq(with_gvars, parse_context(call('ctxget', 2)))
- eq(with_all, parse_context(call('ctxget', 3)))
- call('ctxpush', { 'regs' })
- eq(with_regs, parse_context(call('ctxget')))
- eq(with_regs, parse_context(call('ctxget', 0)))
- eq(with_jumps, parse_context(call('ctxget', 1)))
- eq(with_bufs, parse_context(call('ctxget', 2)))
- eq(with_gvars, parse_context(call('ctxget', 3)))
- eq(with_all, parse_context(call('ctxget', 4)))
- call('ctxpop')
- eq(with_jumps, parse_context(call('ctxget')))
- eq(with_jumps, parse_context(call('ctxget', 0)))
- eq(with_bufs, parse_context(call('ctxget', 1)))
- eq(with_gvars, parse_context(call('ctxget', 2)))
- eq(with_all, parse_context(call('ctxget', 3)))
- call('ctxpop')
- eq(with_bufs, parse_context(call('ctxget')))
- eq(with_bufs, parse_context(call('ctxget', 0)))
- eq(with_gvars, parse_context(call('ctxget', 1)))
- eq(with_all, parse_context(call('ctxget', 2)))
- call('ctxpop')
- eq(with_gvars, parse_context(call('ctxget')))
- eq(with_gvars, parse_context(call('ctxget', 0)))
- eq(with_all, parse_context(call('ctxget', 1)))
- call('ctxpop')
- eq(with_all, parse_context(call('ctxget')))
- eq(with_all, parse_context(call('ctxget', 0)))
- end)
- end)
- describe('ctxset()', function()
- it('errors out when index is out of bounds', function()
- eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }))
- call('ctxpush')
- eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }, 1))
- call('ctxpop')
- eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }, 0))
- end)
- it('errors when context dict is invalid', function()
- call('ctxpush')
- eq(
- 'Vim:E474: Failed to convert list to msgpack string buffer',
- pcall_err(call, 'ctxset', { regs = { {} }, jumps = { {} } })
- )
- end)
- it('sets context dict at index in context stack', function()
- api.nvim_set_var('one', 1)
- api.nvim_set_var('Two', 2)
- api.nvim_set_var('THREE', 3)
- call('ctxpush')
- local ctx1 = call('ctxget')
- api.nvim_set_var('one', 'a')
- api.nvim_set_var('Two', 'b')
- api.nvim_set_var('THREE', 'c')
- call('ctxpush')
- call('ctxpush')
- local ctx2 = call('ctxget')
- eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
- call('ctxset', ctx1)
- call('ctxset', ctx2, 2)
- call('ctxpop')
- eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
- call('ctxpop')
- eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
- api.nvim_set_var('one', 1.5)
- eq({ 1.5, 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
- call('ctxpop')
- eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
- end)
- end)
- end)
|