local helpers = require('test.functional.helpers')(after_each) local call = helpers.call local clear = helpers.clear local command = helpers.command local eq = helpers.eq local eval = helpers.eval local expect_err = helpers.expect_err local feed = helpers.feed local map = helpers.map local nvim = helpers.nvim local parse_context = helpers.parse_context local trim = helpers.trim local write_file = helpers.write_file 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('i123ddddddqahjklq') 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 buflist = call('map', call('getbufinfo'), 'v:val.name') call('ctxpush') call('ctxpush', {'buflist'}) command('%bwipeout') eq({''}, call('map', call('getbufinfo'), 'v:val.name')) call('ctxpop') eq({'', unpack(buflist)}, call('map', call('getbufinfo'), 'v:val.name')) command('%bwipeout') eq({''}, call('map', call('getbufinfo'), 'v:val.name')) call('ctxpop') eq({'', unpack(buflist)}, call('map', call('getbufinfo'), 'v:val.name')) end) it('saves and restores global variables properly', function() nvim('set_var', 'one', 1) nvim('set_var', 'Two', 2) nvim('set_var', 'THREE', 3) eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]')) call('ctxpush') call('ctxpush', {'gvars'}) nvim('del_var', 'one') nvim('del_var', 'Two') nvim('del_var', 'THREE') expect_err('E121: Undefined variable: g:one', eval, 'g:one') expect_err('E121: Undefined variable: g:Two', eval, 'g:Two') expect_err('E121: Undefined variable: g:THREE', eval, 'g:THREE') call('ctxpop') eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]')) nvim('del_var', 'one') nvim('del_var', 'Two') nvim('del_var', 'THREE') expect_err('E121: Undefined variable: g:one', eval, 'g:one') expect_err('E121: Undefined variable: g:Two', eval, 'g:Two') expect_err('E121: Undefined variable: g:THREE', eval, 'g:THREE') call('ctxpop') eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]')) end) it('errors out when context stack is empty', function() local err = 'Vim:Context stack is empty' expect_err(err, call, 'ctxpop') expect_err(err, call, 'ctxpop') call('ctxpush') call('ctxpush') call('ctxpop') call('ctxpop') expect_err(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() expect_err(outofbounds, call, 'ctxget') call('ctxpush') expect_err(outofbounds, call, 'ctxget', 1) call('ctxpop') expect_err(outofbounds, call, 'ctxget', 0) end) it('returns context dictionary at index in context stack', function() feed('i123ddddddqahjklq') command('edit! '..fname1) feed('G') feed('gg') command('edit '..fname2) nvim('set_var', 'one', 1) nvim('set_var', 'Two', 2) 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_buflist = { ['buflist'] = 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'], ['buflist'] = with_buflist['buflist'], ['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', {'buflist'}) eq(with_buflist, parse_context(call('ctxget'))) eq(with_buflist, 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_buflist, 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_buflist, 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_buflist, 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_buflist, parse_context(call('ctxget'))) eq(with_buflist, 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() expect_err(outofbounds, call, 'ctxset', {dummy = 1}) call('ctxpush') expect_err(outofbounds, call, 'ctxset', {dummy = 1}, 1) call('ctxpop') expect_err(outofbounds, call, 'ctxset', {dummy = 1}, 0) end) it('sets context dictionary at index in context stack', function() nvim('set_var', 'one', 1) nvim('set_var', 'Two', 2) nvim('set_var', 'THREE', 3) call('ctxpush') local ctx1 = call('ctxget') nvim('set_var', 'one', 'a') nvim('set_var', 'Two', 'b') 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]')) 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)