aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/buffer_spec.lua35
-rw-r--r--test/functional/api/keymap_spec.lua505
-rw-r--r--test/functional/api/vim_spec.lua4
-rw-r--r--test/functional/autocmd/autocmd_spec.lua116
-rw-r--r--test/functional/core/channels_spec.lua8
-rw-r--r--test/functional/core/main_spec.lua12
-rw-r--r--test/functional/core/spellfile_spec.lua (renamed from test/functional/spell/spellfile_spec.lua)0
-rw-r--r--test/functional/core/startup_spec.lua24
-rw-r--r--test/functional/eval/api_functions_spec.lua2
-rw-r--r--test/functional/ex_cmds/oldfiles_spec.lua12
-rw-r--r--test/functional/ex_cmds/quickfix_commands_spec.lua10
-rw-r--r--test/functional/ex_cmds/wviminfo_spec.lua16
-rw-r--r--test/functional/helpers.lua72
-rw-r--r--test/functional/legacy/074_global_var_in_viminfo_spec.lua8
-rw-r--r--test/functional/legacy/assert_spec.lua9
-rw-r--r--test/functional/options/defaults_spec.lua58
-rw-r--r--test/functional/provider/clipboard_spec.lua (renamed from test/functional/clipboard/clipboard_provider_spec.lua)18
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua9
-rw-r--r--test/functional/terminal/highlight_spec.lua50
-rw-r--r--test/functional/terminal/tui_spec.lua6
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua2
-rw-r--r--test/functional/ui/cmdline_spec.lua25
-rw-r--r--test/functional/ui/embed_spec.lua2
-rw-r--r--test/functional/ui/messages_spec.lua133
-rw-r--r--test/functional/ui/multigrid_spec.lua2
-rw-r--r--test/functional/ui/options_spec.lua3
-rw-r--r--test/functional/ui/screen.lua28
-rw-r--r--test/functional/viml/errorlist_spec.lua8
28 files changed, 1064 insertions, 113 deletions
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index d26cb0dbb3..9d6cfb99ab 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -39,6 +39,41 @@ describe('api/buf', function()
eq(1, curbuf_depr('line_count'))
end)
+ it('cursor position is maintained after lines are inserted #9961', function()
+ -- replace the buffer contents with these three lines.
+ request('nvim_buf_set_lines', 0, 0, -1, 1, {"line1", "line2", "line3", "line4"})
+ -- Set the current cursor to {3, 2}.
+ curwin('set_cursor', {3, 2})
+
+ -- add 2 lines and delete 1 line above the current cursor position.
+ request('nvim_buf_set_lines', 0, 1, 2, 1, {"line5", "line6"})
+ -- check the current set of lines in the buffer.
+ eq({"line1", "line5", "line6", "line3", "line4"}, buffer('get_lines', 0, 0, -1, 1))
+ -- cursor should be moved below by 1 line.
+ eq({4, 2}, curwin('get_cursor'))
+
+ -- add a line after the current cursor position.
+ request('nvim_buf_set_lines', 0, 5, 5, 1, {"line7"})
+ -- check the current set of lines in the buffer.
+ eq({"line1", "line5", "line6", "line3", "line4", "line7"}, buffer('get_lines', 0, 0, -1, 1))
+ -- cursor position is unchanged.
+ eq({4, 2}, curwin('get_cursor'))
+
+ -- overwrite current cursor line.
+ request('nvim_buf_set_lines', 0, 3, 5, 1, {"line8", "line9"})
+ -- check the current set of lines in the buffer.
+ eq({"line1", "line5", "line6", "line8", "line9", "line7"}, buffer('get_lines', 0, 0, -1, 1))
+ -- cursor position is unchanged.
+ eq({4, 2}, curwin('get_cursor'))
+
+ -- delete current cursor line.
+ request('nvim_buf_set_lines', 0, 3, 5, 1, {})
+ -- check the current set of lines in the buffer.
+ eq({"line1", "line5", "line6", "line7"}, buffer('get_lines', 0, 0, -1, 1))
+ -- cursor position is unchanged.
+ eq({4, 2}, curwin('get_cursor'))
+ end)
+
it('line_count has defined behaviour for unloaded buffers', function()
-- we'll need to know our bufnr for when it gets unloaded
local bufnr = curbuf('get_number')
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index f52372bee3..c150787425 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -1,15 +1,19 @@
local helpers = require('test.functional.helpers')(after_each)
local global_helpers = require('test.helpers')
+local bufmeths = helpers.bufmeths
local clear = helpers.clear
local command = helpers.command
local curbufmeths = helpers.curbufmeths
-local eq = helpers.eq
+local eq, neq = helpers.eq, helpers.neq
+local expect_err = helpers.expect_err
+local feed = helpers.feed
local funcs = helpers.funcs
local meths = helpers.meths
local source = helpers.source
local shallowcopy = global_helpers.shallowcopy
+local sleep = global_helpers.sleep
describe('nvim_get_keymap', function()
before_each(clear)
@@ -308,3 +312,502 @@ describe('nvim_get_keymap', function()
eq({space_table}, meths.get_keymap('n'))
end)
end)
+
+describe('nvim_set_keymap, nvim_del_keymap', function()
+ before_each(clear)
+
+ -- `generate_expected` is truthy: for generating an expected output for
+ -- maparg(), which does not accept "!" (though it returns "!" in its output
+ -- if getting a mapping set with |:map!|).
+ local function normalize_mapmode(mode, generate_expected)
+ if not generate_expected and mode == '!' then
+ -- Cannot retrieve mapmode-ic mappings with "!", but can with "i" or "c".
+ mode = 'i'
+ elseif mode == '' then
+ mode = generate_expected and ' ' or mode
+ end
+ return mode
+ end
+
+ -- Generate a mapargs dict, for comparison against the mapping that was
+ -- actually set
+ local function generate_mapargs(mode, lhs, rhs, opts)
+ if not opts then
+ opts = {}
+ end
+
+ local to_return = {}
+ to_return.mode = normalize_mapmode(mode, true)
+ to_return.noremap = not opts.noremap and 0 or 1
+ to_return.lhs = lhs
+ to_return.rhs = rhs
+ to_return.silent = not opts.silent and 0 or 1
+ to_return.nowait = not opts.nowait and 0 or 1
+ to_return.expr = not opts.expr and 0 or 1
+ to_return.sid = not opts.sid and 0 or opts.sid
+ to_return.buffer = not opts.buffer and 0 or opts.buffer
+
+ -- mode 't' doesn't print when calling maparg
+ if mode == 't' then
+ to_return.mode = ''
+ end
+
+ return to_return
+ end
+
+ -- Gets a maparg() dict from Nvim, if one exists.
+ local function get_mapargs(mode, lhs)
+ return funcs.maparg(lhs, normalize_mapmode(mode), false, true)
+ end
+
+ it('error on empty LHS', function()
+ -- escape parentheses in lua string, else comparison fails erroneously
+ expect_err('Invalid %(empty%) LHS',
+ meths.set_keymap, '', '', 'rhs', {})
+ expect_err('Invalid %(empty%) LHS',
+ meths.set_keymap, '', '', '', {})
+
+ expect_err('Invalid %(empty%) LHS', meths.del_keymap, '', '')
+ end)
+
+ it('error if LHS longer than MAXMAPLEN', function()
+ -- assume MAXMAPLEN of 50 chars, as declared in vim.h
+ local MAXMAPLEN = 50
+ local lhs = ''
+ for i=1,MAXMAPLEN do
+ lhs = lhs..(i % 10)
+ end
+
+ -- exactly 50 chars should be fine
+ meths.set_keymap('', lhs, 'rhs', {})
+
+ -- del_keymap should unmap successfully
+ meths.del_keymap('', lhs)
+ eq({}, get_mapargs('', lhs))
+
+ -- 51 chars should produce an error
+ lhs = lhs..'1'
+ expect_err('LHS exceeds maximum map length: '..lhs,
+ meths.set_keymap, '', lhs, 'rhs', {})
+ expect_err('LHS exceeds maximum map length: '..lhs,
+ meths.del_keymap, '', lhs)
+ end)
+
+ it('does not throw errors when rhs is longer than MAXMAPLEN', function()
+ local MAXMAPLEN = 50
+ local rhs = ''
+ for i=1,MAXMAPLEN do
+ rhs = rhs..(i % 10)
+ end
+ rhs = rhs..'1'
+ meths.set_keymap('', 'lhs', rhs, {})
+ eq(generate_mapargs('', 'lhs', rhs),
+ get_mapargs('', 'lhs'))
+ end)
+
+ it('throws errors when given too-long mode shortnames', function()
+ expect_err('Shortname is too long: map',
+ meths.set_keymap, 'map', 'lhs', 'rhs', {})
+
+ expect_err('Shortname is too long: vmap',
+ meths.set_keymap, 'vmap', 'lhs', 'rhs', {})
+
+ expect_err('Shortname is too long: xnoremap',
+ meths.set_keymap, 'xnoremap', 'lhs', 'rhs', {})
+
+ expect_err('Shortname is too long: map', meths.del_keymap, 'map', 'lhs')
+ expect_err('Shortname is too long: vmap', meths.del_keymap, 'vmap', 'lhs')
+ expect_err('Shortname is too long: xnoremap', meths.del_keymap, 'xnoremap', 'lhs')
+ end)
+
+ it('error on invalid mode shortname', function()
+ expect_err('Invalid mode shortname: " "',
+ meths.set_keymap, ' ', 'lhs', 'rhs', {})
+ expect_err('Invalid mode shortname: "m"',
+ meths.set_keymap, 'm', 'lhs', 'rhs', {})
+ expect_err('Invalid mode shortname: "?"',
+ meths.set_keymap, '?', 'lhs', 'rhs', {})
+ expect_err('Invalid mode shortname: "y"',
+ meths.set_keymap, 'y', 'lhs', 'rhs', {})
+ expect_err('Invalid mode shortname: "p"',
+ meths.set_keymap, 'p', 'lhs', 'rhs', {})
+ expect_err('Invalid mode shortname: "?"', meths.del_keymap, '?', 'lhs')
+ expect_err('Invalid mode shortname: "y"', meths.del_keymap, 'y', 'lhs')
+ expect_err('Invalid mode shortname: "p"', meths.del_keymap, 'p', 'lhs')
+ end)
+
+ it('error on invalid optnames', function()
+ expect_err('Invalid key: silentt',
+ meths.set_keymap, 'n', 'lhs', 'rhs', {silentt = true})
+ expect_err('Invalid key: sidd',
+ meths.set_keymap, 'n', 'lhs', 'rhs', {sidd = false})
+ expect_err('Invalid key: nowaiT',
+ meths.set_keymap, 'n', 'lhs', 'rhs', {nowaiT = false})
+ end)
+
+ it('error on <buffer> option key', function()
+ expect_err('Invalid key: buffer',
+ meths.set_keymap, 'n', 'lhs', 'rhs', {buffer = true})
+ end)
+
+ local optnames = {'nowait', 'silent', 'script', 'expr', 'unique'}
+ for _, opt in ipairs(optnames) do
+ -- note: need '%' to escape hyphens, which have special meaning in lua
+ it('throws an error when given non-boolean value for '..opt, function()
+ local opts = {}
+ opts[opt] = 2
+ expect_err('Gave non%-boolean value for an opt: '..opt,
+ meths.set_keymap, 'n', 'lhs', 'rhs', opts)
+ end)
+ end
+
+ -- Perform tests of basic functionality
+ it('sets ordinary mappings', function()
+ meths.set_keymap('n', 'lhs', 'rhs', {})
+ eq(generate_mapargs('n', 'lhs', 'rhs'), get_mapargs('n', 'lhs'))
+
+ meths.set_keymap('v', 'lhs', 'rhs', {})
+ eq(generate_mapargs('v', 'lhs', 'rhs'), get_mapargs('v', 'lhs'))
+ end)
+
+ it('does not throw when LHS or RHS have leading/trailing whitespace', function()
+ meths.set_keymap('n', ' lhs', 'rhs', {})
+ eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'),
+ get_mapargs('n', ' lhs'))
+
+ meths.set_keymap('n', 'lhs ', 'rhs', {})
+ eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'),
+ get_mapargs('n', 'lhs '))
+
+ meths.set_keymap('v', ' lhs ', '\trhs\t\f', {})
+ eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'),
+ get_mapargs('v', ' lhs '))
+ end)
+
+ it('can set noremap mappings', function()
+ meths.set_keymap('x', 'lhs', 'rhs', {noremap = true})
+ eq(generate_mapargs('x', 'lhs', 'rhs', {noremap = true}),
+ get_mapargs('x', 'lhs'))
+
+ meths.set_keymap('t', 'lhs', 'rhs', {noremap = true})
+ eq(generate_mapargs('t', 'lhs', 'rhs', {noremap = true}),
+ get_mapargs('t', 'lhs'))
+ end)
+
+ it('can unmap mappings', function()
+ meths.set_keymap('v', 'lhs', 'rhs', {})
+ meths.del_keymap('v', 'lhs')
+ eq({}, get_mapargs('v', 'lhs'))
+
+ meths.set_keymap('t', 'lhs', 'rhs', {noremap = true})
+ meths.del_keymap('t', 'lhs')
+ eq({}, get_mapargs('t', 'lhs'))
+ end)
+
+ -- Test some edge cases
+ it('"!" and empty string are synonyms for mapmode-nvo', function()
+ local nvo_shortnames = {'', '!'}
+ for _, name in ipairs(nvo_shortnames) do
+ meths.set_keymap(name, 'lhs', 'rhs', {})
+ meths.del_keymap(name, 'lhs')
+ eq({}, get_mapargs(name, 'lhs'))
+ end
+ end)
+
+ local special_chars = {'<C-U>', '<S-Left>', '<F12><F2><Tab>', '<Space><Tab>'}
+ for _, lhs in ipairs(special_chars) do
+ for _, rhs in ipairs(special_chars) do
+ local mapmode = '!'
+ it('can set mappings with special characters, lhs: '..lhs..', rhs: '..rhs,
+ function()
+ meths.set_keymap(mapmode, lhs, rhs, {})
+ eq(generate_mapargs(mapmode, lhs, rhs), get_mapargs(mapmode, lhs))
+ end)
+ end
+ end
+
+ it('can set mappings containing literal keycodes', function()
+ meths.set_keymap('n', '\n\r\n', 'rhs', {})
+ local expected = generate_mapargs('n', '<NL><CR><NL>', 'rhs')
+ eq(expected, get_mapargs('n', '<C-j><CR><C-j>'))
+ end)
+
+ it('can set mappings whose RHS is a <Nop>', function()
+ meths.set_keymap('i', 'lhs', '<Nop>', {})
+ command('normal ilhs')
+ eq({''}, curbufmeths.get_lines(0, -1, 0)) -- imap to <Nop> does nothing
+ eq(generate_mapargs('i', 'lhs', '<Nop>', {}),
+ get_mapargs('i', 'lhs'))
+
+ -- also test for case insensitivity
+ meths.set_keymap('i', 'lhs', '<nOp>', {})
+ command('normal ilhs')
+ eq({''}, curbufmeths.get_lines(0, -1, 0))
+ -- note: RHS in returned mapargs() dict reflects the original RHS
+ -- provided by the user
+ eq(generate_mapargs('i', 'lhs', '<nOp>', {}),
+ get_mapargs('i', 'lhs'))
+
+ meths.set_keymap('i', 'lhs', '<NOP>', {})
+ command('normal ilhs')
+ eq({''}, curbufmeths.get_lines(0, -1, 0))
+ eq(generate_mapargs('i', 'lhs', '<NOP>', {}),
+ get_mapargs('i', 'lhs'))
+ end)
+
+ it('treats an empty RHS in a mapping like a <Nop>', function()
+ meths.set_keymap('i', 'lhs', '', {})
+ command('normal ilhs')
+ eq({''}, curbufmeths.get_lines(0, -1, 0))
+ eq(generate_mapargs('i', 'lhs', '', {}),
+ get_mapargs('i', 'lhs'))
+ end)
+
+ it('can set and unset <M-">', function()
+ -- Taken from the legacy test: test_mapping.vim. Exposes a bug in which
+ -- replace_termcodes changes the length of the mapping's LHS, but
+ -- do_map continues to use the *old* length of LHS.
+ meths.set_keymap('i', '<M-">', 'foo', {})
+ meths.del_keymap('i', '<M-">')
+ eq({}, get_mapargs('i', '<M-">'))
+ end)
+
+ it('interprets control sequences in expr-quotes correctly when called '
+ ..'inside vim', function()
+ command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]])
+ eq(generate_mapargs('i', '<Space>', '\t', {}),
+ get_mapargs('i', '<Space>'))
+ feed('i ')
+ eq({'\t'}, curbufmeths.get_lines(0, -1, 0))
+ end)
+
+ it('throws appropriate error messages when setting <unique> maps', function()
+ meths.set_keymap('l', 'lhs', 'rhs', {})
+ expect_err('E227: mapping already exists for lhs',
+ meths.set_keymap, 'l', 'lhs', 'rhs', {unique = true})
+ -- different mapmode, no error should be thrown
+ meths.set_keymap('t', 'lhs', 'rhs', {unique = true})
+ end)
+
+ it('can set <expr> mappings whose RHS change dynamically', function()
+ meths.command_output([[
+ function! FlipFlop() abort
+ if !exists('g:flip') | let g:flip = 0 | endif
+ let g:flip = !g:flip
+ return g:flip
+ endfunction
+ ]])
+ eq(1, meths.call_function('FlipFlop', {}))
+ eq(0, meths.call_function('FlipFlop', {}))
+ eq(1, meths.call_function('FlipFlop', {}))
+ eq(0, meths.call_function('FlipFlop', {}))
+
+ meths.set_keymap('i', 'lhs', 'FlipFlop()', {expr = true})
+ command('normal ilhs')
+ eq({'1'}, curbufmeths.get_lines(0, -1, 0))
+
+ command('normal! ggVGd')
+
+ command('normal ilhs')
+ eq({'0'}, curbufmeths.get_lines(0, -1, 0))
+ end)
+
+ it('can set mappings that do trigger other mappings', function()
+ meths.set_keymap('i', 'mhs', 'rhs', {})
+ meths.set_keymap('i', 'lhs', 'mhs', {})
+
+ command('normal imhs')
+ eq({'rhs'}, curbufmeths.get_lines(0, -1, 0))
+
+ command('normal! ggVGd')
+
+ command('normal ilhs')
+ eq({'rhs'}, curbufmeths.get_lines(0, -1, 0))
+ end)
+
+ it("can set noremap mappings that don't trigger other mappings", function()
+ meths.set_keymap('i', 'mhs', 'rhs', {})
+ meths.set_keymap('i', 'lhs', 'mhs', {noremap = true})
+
+ command('normal imhs')
+ eq({'rhs'}, curbufmeths.get_lines(0, -1, 0))
+
+ command('normal! ggVGd')
+
+ command('normal ilhs') -- shouldn't trigger mhs-to-rhs mapping
+ eq({'mhs'}, curbufmeths.get_lines(0, -1, 0))
+ end)
+
+ it("can set nowait mappings that fire without waiting", function()
+ meths.set_keymap('i', '123456', 'longer', {})
+ meths.set_keymap('i', '123', 'shorter', {nowait = true})
+
+ -- feed keys one at a time; if all keys arrive atomically, the longer
+ -- mapping will trigger
+ local keys = 'i123456'
+ for c in string.gmatch(keys, '.') do
+ feed(c)
+ sleep(5)
+ end
+ eq({'shorter456'}, curbufmeths.get_lines(0, -1, 0))
+ end)
+
+ -- Perform exhaustive tests of basic functionality
+ local mapmodes = {'n', 'v', 'x', 's', 'o', '!', 'i', 'l', 'c', 't', ''}
+ for _, mapmode in ipairs(mapmodes) do
+ it('can set/unset normal mappings in mapmode '..mapmode, function()
+ meths.set_keymap(mapmode, 'lhs', 'rhs', {})
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs'),
+ get_mapargs(mapmode, 'lhs'))
+
+ -- some mapmodes (like 'o') will prevent other mapmodes (like '!') from
+ -- taking effect, so unmap after each mapping
+ meths.del_keymap(mapmode, 'lhs')
+ eq({}, get_mapargs(mapmode, 'lhs'))
+ end)
+ end
+
+ for _, mapmode in ipairs(mapmodes) do
+ it('can set/unset noremap mappings using mapmode '..mapmode, function()
+ meths.set_keymap(mapmode, 'lhs', 'rhs', {noremap = true})
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs', {noremap = true}),
+ get_mapargs(mapmode, 'lhs'))
+
+ meths.del_keymap(mapmode, 'lhs')
+ eq({}, get_mapargs(mapmode, 'lhs'))
+ end)
+ end
+
+ -- Test map-arguments, using optnames from above
+ -- remove some map arguments that are harder to test, or were already tested
+ optnames = {'nowait', 'silent', 'expr', 'noremap'}
+ for _, mapmode in ipairs(mapmodes) do
+ local printable_mode = normalize_mapmode(mapmode)
+
+ -- Test with single mappings
+ for _, maparg in ipairs(optnames) do
+ it('can set/unset '..printable_mode..'-mappings with maparg: '..maparg,
+ function()
+ meths.set_keymap(mapmode, 'lhs', 'rhs', {[maparg] = true})
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs', {[maparg] = true}),
+ get_mapargs(mapmode, 'lhs'))
+ meths.del_keymap(mapmode, 'lhs')
+ eq({}, get_mapargs(mapmode, 'lhs'))
+ end)
+ it ('can set/unset '..printable_mode..'-mode mappings with maparg '..
+ maparg..', whose value is false', function()
+ meths.set_keymap(mapmode, 'lhs', 'rhs', {[maparg] = false})
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs'),
+ get_mapargs(mapmode, 'lhs'))
+ meths.del_keymap(mapmode, 'lhs')
+ eq({}, get_mapargs(mapmode, 'lhs'))
+ end)
+ end
+
+ -- Test with triplets of mappings, one of which is false
+ for i = 1, (#optnames - 2) do
+ local opt1, opt2, opt3 = optnames[i], optnames[i + 1], optnames[i + 2]
+ it('can set/unset '..printable_mode..'-mode mappings with mapargs '..
+ opt1..', '..opt2..', '..opt3, function()
+ local opts = {[opt1] = true, [opt2] = false, [opt3] = true}
+ meths.set_keymap(mapmode, 'lhs', 'rhs', opts)
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts),
+ get_mapargs(mapmode, 'lhs'))
+ meths.del_keymap(mapmode, 'lhs')
+ eq({}, get_mapargs(mapmode, 'lhs'))
+ end)
+ end
+ end
+end)
+
+describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
+ before_each(clear)
+
+ -- nvim_set_keymap is implemented as a wrapped call to nvim_buf_set_keymap,
+ -- so its tests also effectively test nvim_buf_set_keymap
+
+ -- here, we mainly test for buffer specificity and other special cases
+
+ -- switch to the given buffer, abandoning any changes in the current buffer
+ local function switch_to_buf(bufnr)
+ command(bufnr..'buffer!')
+ end
+
+ -- `set hidden`, then create two buffers and return their bufnr's
+ -- If start_from_first is truthy, the first buffer will be open when
+ -- the function returns; if falsy, the second buffer will be open.
+ local function make_two_buffers(start_from_first)
+ command('set hidden')
+
+ local first_buf = meths.call_function('bufnr', {'%'})
+ command('new')
+ local second_buf = meths.call_function('bufnr', {'%'})
+ neq(second_buf, first_buf) -- sanity check
+
+ if start_from_first then
+ switch_to_buf(first_buf)
+ end
+
+ return first_buf, second_buf
+ end
+
+ it('rejects negative bufnr values', function()
+ expect_err('Wrong type for argument 1, expecting Buffer',
+ bufmeths.set_keymap, -1, '', 'lhs', 'rhs', {})
+ end)
+
+ it('can set mappings active in the current buffer but not others', function()
+ local first, second = make_two_buffers(true)
+
+ bufmeths.set_keymap(0, '', 'lhs', 'irhs<Esc>', {})
+ command('normal lhs')
+ eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1))
+
+ -- mapping should have no effect in new buffer
+ switch_to_buf(second)
+ command('normal lhs')
+ eq({''}, bufmeths.get_lines(0, 0, 1, 1))
+
+ -- mapping should remain active in old buffer
+ switch_to_buf(first)
+ command('normal ^lhs')
+ eq({'rhsrhs'}, bufmeths.get_lines(0, 0, 1, 1))
+ end)
+
+ it('can set local mappings in buffer other than current', function()
+ local first = make_two_buffers(false)
+ bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
+
+ -- shouldn't do anything
+ command('normal lhs')
+ eq({''}, bufmeths.get_lines(0, 0, 1, 1))
+
+ -- should take effect
+ switch_to_buf(first)
+ command('normal lhs')
+ eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1))
+ end)
+
+ it('can disable mappings made in another buffer, inside that buffer', function()
+ local first = make_two_buffers(false)
+ bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
+ bufmeths.del_keymap(first, '', 'lhs')
+ switch_to_buf(first)
+
+ -- shouldn't do anything
+ command('normal lhs')
+ eq({''}, bufmeths.get_lines(0, 0, 1, 1))
+ end)
+
+ it("can't disable mappings given wrong buffer handle", function()
+ local first, second = make_two_buffers(false)
+ bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
+ expect_err('E31: No such mapping',
+ bufmeths.del_keymap, second, '', 'lhs')
+
+ -- should still work
+ switch_to_buf(first)
+ command('normal lhs')
+ eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1))
+ end)
+end)
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index c508ca37db..2178abab53 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1284,7 +1284,7 @@ describe('API', function()
end)
it('returns attached UIs', function()
local screen = Screen.new(20, 4)
- screen:attach()
+ screen:attach({override=true})
local expected = {
{
chan = 1,
@@ -1299,6 +1299,7 @@ describe('API', function()
ext_messages = false,
height = 4,
rgb = true,
+ override = true,
width = 20,
}
}
@@ -1308,6 +1309,7 @@ describe('API', function()
screen = Screen.new(44, 99)
screen:attach({ rgb = false })
expected[1].rgb = false
+ expected[1].override = false
expected[1].width = 44
expected[1].height = 99
eq(expected, nvim("list_uis"))
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index 814624d8e2..337c5442ef 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local dedent = helpers.dedent
local eq = helpers.eq
@@ -6,11 +7,13 @@ local eval = helpers.eval
local feed = helpers.feed
local clear = helpers.clear
local meths = helpers.meths
+local meth_pcall = helpers.meth_pcall
local funcs = helpers.funcs
local expect = helpers.expect
local command = helpers.command
local exc_exec = helpers.exc_exec
local curbufmeths = helpers.curbufmeths
+local source = helpers.source
describe('autocmd', function()
before_each(clear)
@@ -144,4 +147,117 @@ describe('autocmd', function()
--- Autocommands ---]]),
funcs.execute('autocmd Tabnew'))
end)
+
+ it('window works', function()
+ -- Nvim uses a special window to execute certain actions for an invisible buffer,
+ -- internally called autcmd_win and mentioned in the docs at :help E813
+ -- Do some safety checks for redrawing and api accesses to this window.
+
+ local screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {background = Screen.colors.LightMagenta},
+ [3] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1},
+ })
+
+ source([[
+ function! Doit()
+ let g:winid = nvim_get_current_win()
+ redraw!
+ echo getchar()
+ " API functions work when aucmd_win is in scope
+ let g:had_value = has_key(w:, "testvar")
+ call nvim_win_set_var(g:winid, "testvar", 7)
+ let g:test = w:testvar
+ endfunction
+ set hidden
+ " add dummy text to not discard the buffer
+ call setline(1,"bb")
+ autocmd User <buffer> call Doit()
+ ]])
+ screen:expect([[
+ ^bb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+
+ feed(":enew | doautoall User<cr>")
+ screen:expect([[
+ {2:bb }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^:enew | doautoall User |
+ ]])
+
+ feed('<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ 13 |
+ ]])
+ eq(7, eval('g:test'))
+
+ -- API calls are blocked when aucmd_win is not in scope
+ eq({false, 'Vim(call):Invalid window id'},
+ meth_pcall(command, "call nvim_set_current_win(g:winid)"))
+
+ -- second time aucmd_win is needed, a different code path is invoked
+ -- to reuse the same window, so check again
+ command("let g:test = v:null")
+ command("let g:had_value = v:null")
+ feed(":doautoall User<cr>")
+ screen:expect([[
+ {2:bb }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^:doautoall User |
+ ]])
+
+ feed('<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ 13 |
+ ]])
+ -- win vars in aucmd_win should have been reset
+ eq(0, eval('g:had_value'))
+ eq(7, eval('g:test'))
+
+ eq({false, 'Vim(call):Invalid window id'},
+ meth_pcall(command, "call nvim_set_current_win(g:winid)"))
+ end)
end)
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index 7b89172f92..0137092eb5 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -1,3 +1,5 @@
+local global_helpers = require('test.helpers')
+local uname = global_helpers.uname
local helpers = require('test.functional.helpers')(after_each)
local clear, eq, eval, next_msg, ok, source = helpers.clear, helpers.eq,
@@ -7,6 +9,7 @@ local sleep = helpers.sleep
local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv
local set_session = helpers.set_session
local nvim_prog = helpers.nvim_prog
+local os_name = helpers.os_name
local retry = helpers.retry
local expect_twostreams = helpers.expect_twostreams
@@ -138,9 +141,8 @@ describe('channels', function()
command("call chansend(id, 'incomplet\004')")
- local is_freebsd = eval("system('uname') =~? 'FreeBSD'") == 1
- local bsdlike = is_freebsd or (helpers.os_name() == "osx")
- print("bsdlike:", bsdlike)
+ local is_freebsd = (string.lower(uname()) == 'freebsd')
+ local bsdlike = is_freebsd or (os_name() == "osx")
local extra = bsdlike and "^D\008\008" or ""
expect_twoline(id, "stdout",
"incomplet"..extra, "[1, ['incomplet'], 'stdin']", true)
diff --git a/test/functional/core/main_spec.lua b/test/functional/core/main_spec.lua
index a0981e9207..b793e531c9 100644
--- a/test/functional/core/main_spec.lua
+++ b/test/functional/core/main_spec.lua
@@ -7,19 +7,9 @@ local feed = helpers.feed
local eval = helpers.eval
local clear = helpers.clear
local funcs = helpers.funcs
-local nvim_prog = helpers.nvim_prog
+local nvim_prog_abs = helpers.nvim_prog_abs
local write_file = helpers.write_file
-local function nvim_prog_abs()
- -- system(['build/bin/nvim']) does not work for whatever reason. It needs to
- -- either be executable searched in $PATH or something starting with / or ./.
- if nvim_prog:match('[/\\]') then
- return funcs.fnamemodify(nvim_prog, ':p')
- else
- return nvim_prog
- end
-end
-
describe('Command-line option', function()
describe('-s', function()
local fname = 'Xtest-functional-core-main-s'
diff --git a/test/functional/spell/spellfile_spec.lua b/test/functional/core/spellfile_spec.lua
index afd2c1bce4..afd2c1bce4 100644
--- a/test/functional/spell/spellfile_spec.lua
+++ b/test/functional/core/spellfile_spec.lua
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 76e242b1e2..f77af836a6 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -13,9 +13,7 @@ local nvim_set = helpers.nvim_set
local read_file = helpers.read_file
local retry = helpers.retry
local rmdir = helpers.rmdir
-local set_session = helpers.set_session
local sleep = helpers.sleep
-local spawn = helpers.spawn
local iswin = helpers.iswin
local write_file = helpers.write_file
@@ -228,10 +226,6 @@ describe('sysinit', function()
local vimdir = 'Xvim'
local xhome = 'Xhome'
local pathsep = helpers.get_pathsep()
- local argv = {
- nvim_prog, '--headless', '--embed', '-i', 'NONE', '-n',
- '--cmd', 'set nomore undodir=. directory=. belloff='
- }
before_each(function()
rmdir(xdgdir)
@@ -260,19 +254,21 @@ describe('sysinit', function()
end)
it('prefers XDG_CONFIG_DIRS over VIM', function()
- set_session(spawn(argv, nil,
- { 'HOME='..xhome,
- 'XDG_CONFIG_DIRS='..xdgdir,
- 'VIM='..vimdir }))
+ clear{args={'--cmd', 'set nomore undodir=. directory=. belloff='},
+ args_rm={'-u', '--cmd'},
+ env={ HOME=xhome,
+ XDG_CONFIG_DIRS=xdgdir,
+ VIM=vimdir }}
eq('loaded 1 xdg 1 vim 0',
eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))'))
end)
it('uses VIM if XDG_CONFIG_DIRS unset', function()
- set_session(spawn(argv, nil,
- { 'HOME='..xhome,
- 'XDG_CONFIG_DIRS=',
- 'VIM='..vimdir }))
+ clear{args={'--cmd', 'set nomore undodir=. directory=. belloff='},
+ args_rm={'-u', '--cmd'},
+ env={ HOME=xhome,
+ XDG_CONFIG_DIRS='',
+ VIM=vimdir }}
eq('loaded 1 xdg 0 vim 1',
eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))'))
end)
diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/eval/api_functions_spec.lua
index 6f440c7d82..40d06b599f 100644
--- a/test/functional/eval/api_functions_spec.lua
+++ b/test/functional/eval/api_functions_spec.lua
@@ -6,7 +6,7 @@ local clear, curbufmeths = helpers.clear, helpers.curbufmeths
local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval
local insert = helpers.insert
-describe('api functions', function()
+describe('eval-API', function()
before_each(clear)
it("work", function()
diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua
index e2958c2924..802c3f68c6 100644
--- a/test/functional/ex_cmds/oldfiles_spec.lua
+++ b/test/functional/ex_cmds/oldfiles_spec.lua
@@ -1,18 +1,18 @@
local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
local buf, eq, feed_command = helpers.curbufmeths, helpers.eq, helpers.feed_command
-local feed, nvim_prog, wait = helpers.feed, helpers.nvim_prog, helpers.wait
-local ok, set_session, spawn = helpers.ok, helpers.set_session, helpers.spawn
+local feed, wait = helpers.feed, helpers.wait
+local ok = helpers.ok
local eval = helpers.eval
local shada_file = 'Xtest.shada'
local function _clear()
- set_session(spawn({nvim_prog, '--embed', '--headless', '-u', 'NONE',
- -- Need shada for these tests.
- '-i', shada_file,
- '--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'}))
+ clear{args={'-i', shada_file, -- Need shada for these tests.
+ '--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'},
+ args_rm={'-i', '--cmd'}}
end
describe(':oldfiles', function()
diff --git a/test/functional/ex_cmds/quickfix_commands_spec.lua b/test/functional/ex_cmds/quickfix_commands_spec.lua
index bf10f80401..3392a90270 100644
--- a/test/functional/ex_cmds/quickfix_commands_spec.lua
+++ b/test/functional/ex_cmds/quickfix_commands_spec.lua
@@ -37,9 +37,9 @@ for _, c in ipairs({'l', 'c'}) do
-- Second line of each entry (i.e. `nr=-1, …`) was obtained from actual
-- results. First line (i.e. `{lnum=…`) was obtained from legacy test.
local list = {
- {lnum=700, col=10, text='Line 700',
+ {lnum=700, col=10, text='Line 700', module='',
nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
- {lnum=800, col=15, text='Line 800',
+ {lnum=800, col=15, text='Line 800', module='',
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
}
eq(list, getlist())
@@ -58,7 +58,7 @@ for _, c in ipairs({'l', 'c'}) do
]]):format(file))
command(('%s %s'):format(addfcmd, file))
list[#list + 1] = {
- lnum=900, col=30, text='Line 900',
+ lnum=900, col=30, text='Line 900', module='',
nr=-1, bufnr=5, valid=1, pattern='', vcol=0, ['type']='',
}
eq(list, getlist())
@@ -71,9 +71,9 @@ for _, c in ipairs({'l', 'c'}) do
command('enew!')
command(('%s %s'):format(getfcmd, file))
list = {
- {lnum=222, col=77, text='Line 222',
+ {lnum=222, col=77, text='Line 222', module='',
nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
- {lnum=333, col=88, text='Line 333',
+ {lnum=333, col=88, text='Line 333', module='',
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
}
eq(list, getlist())
diff --git a/test/functional/ex_cmds/wviminfo_spec.lua b/test/functional/ex_cmds/wviminfo_spec.lua
index df0b9df5dd..7c00daf1d7 100644
--- a/test/functional/ex_cmds/wviminfo_spec.lua
+++ b/test/functional/ex_cmds/wviminfo_spec.lua
@@ -1,23 +1,21 @@
local helpers = require('test.functional.helpers')(after_each)
local lfs = require('lfs')
-local command, eq, neq, spawn, nvim_prog, set_session, write_file =
- helpers.command, helpers.eq, helpers.neq, helpers.spawn,
- helpers.nvim_prog, helpers.set_session, helpers.write_file
+local clear = helpers.clear
+local command, eq, neq, write_file =
+ helpers.command, helpers.eq, helpers.neq, helpers.write_file
local iswin = helpers.iswin
local read_file = helpers.read_file
describe(':wshada', function()
local shada_file = 'wshada_test'
- local session
before_each(function()
- -- Override the default session because we need 'swapfile' for these tests.
- session = spawn({nvim_prog, '-u', 'NONE', '-i', iswin() and 'nul' or '/dev/null', '--embed',
- '--cmd', 'set swapfile'})
- set_session(session)
+ clear{args={'-i', iswin() and 'nul' or '/dev/null',
+ -- Need 'swapfile' for these tests.
+ '--cmd', 'set swapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'},
+ args_rm={'-n', '-i', '--cmd'}}
end)
after_each(function ()
- session:close()
os.remove(shada_file)
end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 7f9b5fe5fc..fd10a6afcd 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -38,7 +38,7 @@ local nvim_prog = (
local nvim_set = 'set shortmess+=I background=light noswapfile noautoindent'
..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
..' belloff= noshowcmd noruler nomore'
-local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N',
+local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE',
'--cmd', nvim_set, '--embed'}
-- Directory containing nvim.
local nvim_dir = nvim_prog:gsub("[/\\][^/\\]+$", "")
@@ -238,6 +238,16 @@ local function stop()
session:stop()
end
+local function nvim_prog_abs()
+ -- system(['build/bin/nvim']) does not work for whatever reason. It must
+ -- be executable searched in $PATH or something starting with / or ./.
+ if nvim_prog:match('[/\\]') then
+ return request('nvim_call_function', 'fnamemodify', {nvim_prog, ':p'})
+ else
+ return nvim_prog
+ end
+end
+
-- Executes an ex-command. VimL errors manifest as client (lua) errors, but
-- v:errmsg will not be updated.
local function nvim_command(cmd)
@@ -312,6 +322,43 @@ local function merge_args(...)
return argv
end
+-- Removes Nvim startup args from `args` matching items in `args_rm`.
+--
+-- "-u", "-i", "--cmd" are treated specially: their "values" are also removed.
+-- Example:
+-- args={'--headless', '-u', 'NONE'}
+-- args_rm={'--cmd', '-u'}
+-- Result:
+-- {'--headless'}
+--
+-- All cases are removed.
+-- Example:
+-- args={'--cmd', 'foo', '-N', '--cmd', 'bar'}
+-- args_rm={'--cmd', '-u'}
+-- Result:
+-- {'-N'}
+local function remove_args(args, args_rm)
+ local new_args = {}
+ local skip_following = {'-u', '-i', '-c', '--cmd', '-s', '--listen'}
+ if not args_rm or #args_rm == 0 then
+ return {unpack(args)}
+ end
+ for _, v in ipairs(args_rm) do
+ assert(type(v) == 'string')
+ end
+ local last = ''
+ for _, arg in ipairs(args) do
+ if table_contains(skip_following, last) then
+ last = ''
+ elseif table_contains(args_rm, arg) then
+ last = arg
+ else
+ table.insert(new_args, arg)
+ end
+ end
+ return new_args
+end
+
local function spawn(argv, merge, env)
local child_stream = ChildProcessStream.spawn(
merge and merge_args(prepend_argv, argv) or argv,
@@ -350,20 +397,25 @@ local function retry(max, max_ms, fn)
end
-- Starts a new global Nvim session.
+--
-- Parameters are interpreted as startup args, OR a map with these keys:
--- args: Merged with the default `nvim_argv` set.
--- env : Defines the environment of the new session.
+-- args: List: Args appended to the default `nvim_argv` set.
+-- args_rm: List: Args removed from the default set. All cases are
+-- removed, e.g. args_rm={'--cmd'} removes all cases of "--cmd"
+-- (and its value) from the default set.
+-- env: Map: Defines the environment of the new session.
--
-- Example:
-- clear('-e')
--- clear({args={'-e'}, env={TERM=term}})
+-- clear{args={'-e'}, args_rm={'-i'}, env={TERM=term}}
local function clear(...)
local args = {unpack(nvim_argv)}
+ table.insert(args, '--headless')
local new_args
local env = nil
local opts = select(1, ...)
- local headless = true
if type(opts) == 'table' then
+ args = remove_args(args, opts.args_rm)
if opts.env then
local env_tbl = {}
for k, v in pairs(opts.env) do
@@ -374,7 +426,8 @@ local function clear(...)
for _, k in ipairs({
'HOME',
'ASAN_OPTIONS',
- 'LD_LIBRARY_PATH', 'PATH',
+ 'LD_LIBRARY_PATH',
+ 'PATH',
'NVIM_LOG_FILE',
'NVIM_RPLUGIN_MANIFEST',
}) do
@@ -388,15 +441,9 @@ local function clear(...)
end
end
new_args = opts.args or {}
- if opts.headless == false then
- headless = false
- end
else
new_args = {...}
end
- if headless then
- table.insert(args, '--headless')
- end
for _, arg in ipairs(new_args) do
table.insert(args, arg)
end
@@ -789,6 +836,7 @@ local module = {
nvim_async = nvim_async,
nvim_dir = nvim_dir,
nvim_prog = nvim_prog,
+ nvim_prog_abs = nvim_prog_abs,
nvim_set = nvim_set,
ok = ok,
os_name = os_name,
diff --git a/test/functional/legacy/074_global_var_in_viminfo_spec.lua b/test/functional/legacy/074_global_var_in_viminfo_spec.lua
index e17b463e30..f7f074c61a 100644
--- a/test/functional/legacy/074_global_var_in_viminfo_spec.lua
+++ b/test/functional/legacy/074_global_var_in_viminfo_spec.lua
@@ -2,9 +2,9 @@
local helpers = require('test.functional.helpers')(after_each)
local lfs = require('lfs')
-local clear, command, eq, neq, eval, wait, spawn =
+local clear, command, eq, neq, eval, wait =
helpers.clear, helpers.command, helpers.eq, helpers.neq, helpers.eval,
- helpers.wait, helpers.spawn
+ helpers.wait
describe('storing global variables in ShaDa files', function()
local tempname = 'Xtest-functional-legacy-074'
@@ -14,9 +14,7 @@ describe('storing global variables in ShaDa files', function()
end)
it('is working', function()
- local nvim2 = spawn({helpers.nvim_prog, '-u', 'NONE',
- '-i', 'Xviminfo', '--embed'})
- helpers.set_session(nvim2)
+ clear{args_rm={'-i'}, args={'-i', 'Xviminfo'}}
local test_dict = {foo = 1, bar = 0, longvarible = 1000}
local test_list = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index 10703465aa..8df2d89b70 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -18,6 +18,15 @@ describe('assert function:', function()
clear()
end)
+ describe('assert_beeps', function()
+ it('works', function()
+ call('assert_beeps', 'normal h')
+ expected_empty()
+ call('assert_beeps', 'normal 0')
+ expected_errors({'command did not beep: normal 0'})
+ end)
+ end)
+
-- assert_equal({expected}, {actual}, [, {msg}])
describe('assert_equal', function()
it('should not change v:errors when expected is equal to actual', function()
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index f6f3f02f45..0fc2876d00 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local global_helpers = require('test.helpers')
local Screen = require('test.functional.ui.screen')
@@ -15,6 +16,7 @@ local neq = helpers.neq
local mkdir = helpers.mkdir
local rmdir = helpers.rmdir
local alter_slashes = helpers.alter_slashes
+local table_contains = global_helpers.table_contains
describe('startup defaults', function()
describe(':filetype', function()
@@ -160,20 +162,39 @@ describe('startup defaults', function()
end)
end)
- describe("'packpath'", function()
- it('defaults to &runtimepath', function()
- eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
- end)
+ it("'shadafile' ('viminfofile')", function()
+ local env = {XDG_DATA_HOME='Xtest-userdata', XDG_CONFIG_HOME='Xtest-userconfig'}
+ clear{args={}, args_rm={'-i'}, env=env}
+ -- Default 'shadafile' is empty.
+ -- This means use the default location. :help shada-file-name
+ eq('', meths.get_option('shadafile'))
+ eq('', meths.get_option('viminfofile'))
+ -- Check that shada data (such as v:oldfiles) is saved/restored.
+ command('edit Xtest-foo')
+ command('write')
+ local f = eval('fnamemodify(@%,":p")')
+ assert(string.len(f) > 3)
+ command('qall')
+ clear{args={}, args_rm={'-i'}, env=env}
+ eq({ f }, eval('v:oldfiles'))
+ os.remove('Xtest-foo')
+ rmdir('Xtest-userdata')
+ end)
- it('does not follow modifications to runtimepath', function()
- meths.command('set runtimepath+=foo')
- neq(meths.get_option('runtimepath'), meths.get_option('packpath'))
- meths.command('set packpath+=foo')
- eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
- end)
+ it("'packpath'", function()
+ clear()
+ -- Defaults to &runtimepath.
+ eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+
+ -- Does not follow modifications to runtimepath.
+ meths.command('set runtimepath+=foo')
+ neq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+ meths.command('set packpath+=foo')
+ eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
end)
it('v:progpath is set to the absolute path', function()
+ clear()
eq(eval("fnamemodify(v:progpath, ':p')"), eval('v:progpath'))
end)
@@ -231,6 +252,23 @@ describe('XDG-based defaults', function()
-- Need separate describe() blocks to not run clear() twice.
-- Do not put before_each() here for the same reasons.
+ it("&runtimepath data-dir matches stdpath('data') #9910", function()
+ clear()
+ local rtp = eval('split(&runtimepath, ",")')
+ local rv = {}
+ local expected = (iswin()
+ and { [[\nvim-data\site]], [[\nvim-data\site\after]], }
+ or { '/nvim/site', '/nvim/site/after', })
+
+ for _,v in ipairs(rtp) do
+ local m = string.match(v, [=[[/\]nvim[^/\]*[/\]site.*$]=])
+ if m and not table_contains(rv, m) then
+ table.insert(rv, m)
+ end
+ end
+ eq(expected, rv)
+ end)
+
describe('with empty/broken environment', function()
it('sets correct defaults', function()
clear({env={
diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/provider/clipboard_spec.lua
index 2bbc678a02..b2d75db745 100644
--- a/test/functional/clipboard/clipboard_provider_spec.lua
+++ b/test/functional/provider/clipboard_spec.lua
@@ -236,7 +236,7 @@ describe('clipboard', function()
end)
end)
-describe('clipboard', function()
+describe('clipboard (with fake clipboard.vim)', function()
local function reset(...)
clear('--cmd', 'let &rtp = "test/functional/fixtures,".&rtp', ...)
end
@@ -664,4 +664,20 @@ describe('clipboard', function()
the a sourcetarget]])
end)
+ it('setreg("*") with clipboard=unnamed #5646', function()
+ source([=[
+ function! Paste_without_yank(direction) range
+ let [reg_save,regtype_save] = [getreg('*'), getregtype('*')]
+ normal! gvp
+ call setreg('*', reg_save, regtype_save)
+ endfunction
+ xnoremap p :call Paste_without_yank('p')<CR>
+ set clipboard=unnamed
+ ]=])
+ insert('some words')
+ feed('gg0yiw')
+ feed('wviwp')
+ expect('some some')
+ eq('some', eval('getreg("*")'))
+ end)
end)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index ca5737db7f..f3849709e3 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -106,6 +106,15 @@ describe(':terminal', function()
command('stopinsert')
eq({ blocking=false, mode='n' }, nvim('get_mode'))
end)
+
+ it(':stopinsert in normal mode doesn\'t break insert mode #9889', function()
+ command(':terminal')
+ eq({ blocking=false, mode='n' }, nvim('get_mode'))
+ command(':stopinsert')
+ eq({ blocking=false, mode='n' }, nvim('get_mode'))
+ feed('a')
+ eq({ blocking=false, mode='t' }, nvim('get_mode'))
+ end)
end)
describe(':terminal (with fake shell)', function()
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 9579e0ea0b..48fedd5927 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -3,9 +3,12 @@ local Screen = require('test.functional.ui.screen')
local thelpers = require('test.functional.terminal.helpers')
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
local nvim_dir, command = helpers.nvim_dir, helpers.command
+local nvim_prog_abs = helpers.nvim_prog_abs
local eq, eval = helpers.eq, helpers.eval
+local funcs = helpers.funcs
+local nvim_set = helpers.nvim_set
-describe(':terminal window highlighting', function()
+describe(':terminal highlight', function()
local screen
before_each(function()
@@ -112,8 +115,51 @@ describe(':terminal window highlighting', function()
end)
end)
+it(':terminal highlight has lower precedence than editor #9964', function()
+ clear()
+ local screen = Screen.new(30, 4)
+ screen:set_default_attr_ids({
+ -- "Normal" highlight emitted by the child nvim process.
+ N_child = {foreground = tonumber('0x4040ff'), background = tonumber('0xffff40')},
+ -- "Search" highlight emitted by the child nvim process.
+ S_child = {background = tonumber('0xffff40'), italic = true, foreground = tonumber('0x4040ff')},
+ -- "Search" highlight in the parent nvim process.
+ S = {background = Screen.colors.Green, italic = true, foreground = Screen.colors.Red},
+ -- "Question" highlight in the parent nvim process.
+ Q = {background = tonumber('0xffff40'), bold = true, foreground = Screen.colors.SeaGreen4},
+ })
+ screen:attach({rgb=true})
+ -- Child nvim process in :terminal (with cterm colors).
+ funcs.termopen({
+ nvim_prog_abs(), '-n', '-u', 'NORC', '-i', 'NONE', '--cmd', nvim_set,
+ '+hi Normal ctermfg=Blue ctermbg=Yellow',
+ '+norm! ichild nvim',
+ '+norm! oline 2',
+ })
+ screen:expect([[
+ {N_child:^child nvim }|
+ {N_child:line 2 }|
+ {N_child: }|
+ |
+ ]])
+ command('hi Search gui=italic guifg=Red guibg=Green cterm=italic ctermfg=Red ctermbg=Green')
+ feed('/nvim<cr>')
+ screen:expect([[
+ {N_child:child }{S:^nvim}{N_child: }|
+ {N_child:line 2 }|
+ {N_child: }|
+ /nvim |
+ ]])
+ command('syntax keyword Question line')
+ screen:expect([[
+ {N_child:child }{S:^nvim}{N_child: }|
+ {Q:line}{N_child: 2 }|
+ {N_child: }|
+ /nvim |
+ ]])
+end)
-describe('terminal window highlighting with custom palette', function()
+describe(':terminal highlight with custom palette', function()
local screen
before_each(function()
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 9d0eb5e40e..469d088c57 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -255,14 +255,14 @@ describe('TUI', function()
]])
end)
- it('shows up in nvim_list_uis', function()
+ it('is included in nvim_list_uis()', function()
feed_data(':echo map(nvim_list_uis(), {k,v -> sort(items(filter(v, {k,v -> k[:3] !=# "ext_" })))})\013')
screen:expect([=[
|
{4:~ }|
{5: }|
- [[['height', 6], ['rgb', v:false], ['width', 50]]]|
- |
+ [[['height', 6], ['override', v:false], ['rgb', v:|
+ false], ['width', 50]]] |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
]=])
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
index 121e71c3c2..45808b3b1b 100644
--- a/test/functional/ui/cmdline_highlight_spec.lua
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -983,7 +983,7 @@ describe('Expressions coloring support', function()
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
- ={SQ:"}{SB:<c0>}{SQ:"}{E:<c0>"}{SB:foo}{E:"}^" |
+ ={SQ:"}{SB:<c0>}{SQ:"}{E:<c0>"}{SB:foo}{E:"}^ |
]])
end)
end)
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index 16be846647..5d563895d6 100644
--- a/test/functional/ui/cmdline_spec.lua
+++ b/test/functional/ui/cmdline_spec.lua
@@ -116,6 +116,31 @@ local function test_cmdline(linegrid)
}}}
end)
+ it('from normal mode when : is mapped', function()
+ command('nnoremap ; :')
+
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {3:n }|
+ |
+ ]]}
+
+ feed(';')
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {3:c }|
+ |
+ ]], cmdline={{
+ firstc = ":",
+ content = {{""}},
+ pos = 0,
+ }}}
+ end)
+
it('but not with scrolled messages', function()
screen:try_resize(35,10)
feed(':echoerr doesnotexist<cr>')
diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua
index 10dbc68672..9196c8af40 100644
--- a/test/functional/ui/embed_spec.lua
+++ b/test/functional/ui/embed_spec.lua
@@ -8,7 +8,7 @@ local clear = helpers.clear
local function test_embed(ext_linegrid)
local screen
local function startup(...)
- clear{headless=false, args={...}}
+ clear{args_rm={'--headless'}, args={...}}
-- attach immediately after startup, for early UI
screen = Screen.new(60, 8)
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index efa776762b..d49d2f0316 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -22,8 +22,129 @@ describe('ui/ext_messages', function()
[6] = {bold = true, reverse = true},
})
end)
+ after_each(function()
+ os.remove('Xtest')
+ end)
+
+ it('msg_show kind=confirm,confirm_sub,emsg,wmsg', function()
+ feed('iline 1\nline 2<esc>')
+
+ -- kind=confirm
+ feed(':echo confirm("test")<cr>')
+ screen:expect{grid=[[
+ line 1 |
+ line ^2 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]], messages={ {
+ content = {{"\ntest\n[O]k: ", 4}},
+ kind = 'confirm',
+ }}}
+ feed('<cr><cr>')
+ screen:expect{grid=[[
+ line 1 |
+ line ^2 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]], messages={ {
+ content = { { "\ntest\n[O]k: ", 4 } },
+ kind = "confirm"
+ }, {
+ content = { { "1" } },
+ kind = "echo"
+ }, {
+ content = { { "Press ENTER or type command to continue", 4 } },
+ kind = "return_prompt"
+ } }}
+ feed('<cr><cr>')
+
+ -- kind=confirm_sub
+ feed(':%s/i/X/gc<cr>')
+ screen:expect{grid=[[
+ l{7:i}ne 1 |
+ l{8:i}ne ^2 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]], attr_ids={
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [3] = {bold = true},
+ [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [5] = {foreground = Screen.colors.Blue1},
+ [6] = {bold = true, reverse = true},
+ [7] = {reverse = true},
+ [8] = {background = Screen.colors.Yellow},
+ }, messages={ {
+ content = { { "replace with X (y/n/a/q/l/^E/^Y)?", 4 } },
+ kind = "confirm_sub"
+ } }}
+ feed('nq')
+
+ -- kind=wmsg (editing readonly file)
+ command('write Xtest')
+ command('set readonly nohls')
+ feed('G$x')
+ screen:expect{grid=[[
+ line 1 |
+ {IGNORE}|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]], attr_ids={
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [7] = {foreground = Screen.colors.Red},
+ }, messages={ {
+ content = { { "W10: Warning: Changing a readonly file", 7 } },
+ kind = "wmsg"
+ }
+ }}
+
+ -- kind=wmsg ('wrapscan' after search reaches EOF)
+ feed('uG$/i<cr>')
+ screen:expect{grid=[[
+ l^ine 1 |
+ line 2 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]], attr_ids={
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [3] = {bold = true},
+ [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [5] = {foreground = Screen.colors.Blue1},
+ [6] = {bold = true, reverse = true},
+ [7] = {foreground = Screen.colors.Red},
+ }, messages={ {
+ content = { { "search hit BOTTOM, continuing at TOP", 7 } },
+ kind = "wmsg"
+ } }}
+
+ -- kind=emsg after :throw
+ feed(':throw "foo"<cr>')
+ screen:expect{grid=[[
+ l^ine 1 |
+ line 2 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]], messages={ {
+ content = { { "Error detected while processing :", 2 } },
+ kind = "emsg"
+ }, {
+ content = { { "E605: Exception not caught: foo", 2 } },
+ kind = ""
+ }, {
+ content = { { "Press ENTER or type command to continue", 4 } },
+ kind = "return_prompt"
+ } }
+ }
+ end)
- it('supports :echoerr', function()
+ it(':echoerr', function()
feed(':echoerr "raa"<cr>')
screen:expect{grid=[[
^ |
@@ -142,7 +263,7 @@ describe('ui/ext_messages', function()
}}
end)
- it('supports showmode', function()
+ it('&showmode', function()
command('imap <f2> <cmd>echomsg "stuff"<cr>')
feed('i')
screen:expect{grid=[[
@@ -230,7 +351,7 @@ describe('ui/ext_messages', function()
}}
end)
- it('supports showmode with recording message', function()
+ it('&showmode with macro-recording message', function()
feed('qq')
screen:expect{grid=[[
^ |
@@ -268,7 +389,7 @@ describe('ui/ext_messages', function()
]])
end)
- it('shows recording message with noshowmode', function()
+ it('shows macro-recording message with &noshowmode', function()
command("set noshowmode")
feed('qq')
-- also check mode to avoid immediate success
@@ -308,7 +429,7 @@ describe('ui/ext_messages', function()
]], mode="normal"}
end)
- it('supports showcmd and ruler', function()
+ it('supports &showcmd and &ruler', function()
command('set showcmd ruler')
screen:expect{grid=[[
^ |
@@ -529,7 +650,7 @@ describe('ui/ext_messages', function()
local screen
before_each(function()
- clear{headless=false, args={"--cmd", "set shortmess-=I"}}
+ clear{args_rm={'--headless'}, args={"--cmd", "set shortmess-=I"}}
screen = Screen.new(80, 24)
screen:attach({rgb=true, ext_messages=true, ext_popupmenu=true})
screen:set_default_attr_ids({
diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua
index c54d608ec4..c5a23e4661 100644
--- a/test/functional/ui/multigrid_spec.lua
+++ b/test/functional/ui/multigrid_spec.lua
@@ -11,7 +11,7 @@ describe('ext_multigrid', function()
local screen
before_each(function()
- clear{headless=false, args={'--cmd', 'set laststatus=2'}}
+ clear{args_rm={'--headless'}, args={'--cmd', 'set laststatus=2'}}
screen = Screen.new(53,14)
screen:attach({ext_multigrid=true})
screen:set_default_attr_ids({
diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua
index ed630259be..7ce21f5d76 100644
--- a/test/functional/ui/options_spec.lua
+++ b/test/functional/ui/options_spec.lua
@@ -115,7 +115,8 @@ describe('ui receives option updates', function()
end)
local function startup_test(headless)
- local expected = reset(nil,{headless=headless,args={'--cmd', 'set guifont=Comic\\ Sans\\ 12'}})
+ local expected = reset(nil, {args_rm=(headless and {} or {'--headless'}),
+ args={'--cmd', 'set guifont=Comic\\ Sans\\ 12'}})
expected.guifont = "Comic Sans 12"
screen:expect(function()
eq(expected, screen.options)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 983a2f3d40..53b6642207 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -74,6 +74,7 @@
local global_helpers = require('test.helpers')
local deepcopy = global_helpers.deepcopy
local shallowcopy = global_helpers.shallowcopy
+local concat_tables = global_helpers.concat_tables
local helpers = require('test.functional.helpers')(nil)
local request, run_session = helpers.request, helpers.run_session
local eq = helpers.eq
@@ -413,26 +414,23 @@ screen:redraw_debug() to show all intermediate screen states. ]])
end
end
- -- Extension features. The default expectations should cover the case of
+ -- UI extensions. The default expectations should cover the case of
-- the ext_ feature being disabled, or the feature currently not activated
- -- (for instance no external cmdline visible). Some extensions require
+ -- (e.g. no external cmdline visible). Some extensions require
-- preprocessing to represent highlights in a reproducible way.
local extstate = self:_extstate_repr(attr_state)
-
- -- convert assertion errors into invalid screen state descriptions
- local status, res = pcall(function()
- for _, k in ipairs(ext_keys) do
- -- Empty states is considered the default and need not be mentioned
- if not (expected[k] == nil and isempty(extstate[k])) then
- eq(expected[k], extstate[k], k)
+ if expected['mode'] ~= nil then
+ extstate['mode'] = self.mode
+ end
+ -- Convert assertion errors into invalid screen state descriptions.
+ for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do
+ -- Empty states are considered the default and need not be mentioned.
+ if (not (expected[k] == nil and isempty(extstate[k]))) then
+ local status, res = pcall(eq, expected[k], extstate[k], k)
+ if not status then
+ return (tostring(res)..'\nHint: full state of "'..k..'":\n '..inspect(extstate[k]))
end
end
- if expected.mode ~= nil then
- eq(expected.mode, self.mode, "mode")
- end
- end)
- if not status then
- return tostring(res)
end
end, expected)
end
diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua
index 6c5a63e6b1..c5390cbd12 100644
--- a/test/functional/viml/errorlist_spec.lua
+++ b/test/functional/viml/errorlist_spec.lua
@@ -26,7 +26,7 @@ describe('setqflist()', function()
it('sets w:quickfix_title', function()
setqflist({''}, 'r', 'foo')
command('copen')
- eq(':foo', get_cur_win_var('quickfix_title'))
+ eq('foo', get_cur_win_var('quickfix_title'))
setqflist({''}, 'r', {['title'] = 'qf_title'})
eq('qf_title', get_cur_win_var('quickfix_title'))
end)
@@ -34,7 +34,7 @@ describe('setqflist()', function()
it('allows string {what} for backwards compatibility', function()
setqflist({}, 'r', '5')
command('copen')
- eq(':5', get_cur_win_var('quickfix_title'))
+ eq('5', get_cur_win_var('quickfix_title'))
end)
it('requires a dict for {what}', function()
@@ -64,8 +64,8 @@ describe('setloclist()', function()
setloclist(1, {}, 'r', 'foo')
setloclist(2, {}, 'r', 'bar')
command('lopen')
- eq(':bar', get_cur_win_var('quickfix_title'))
+ eq('bar', get_cur_win_var('quickfix_title'))
command('lclose | wincmd w | lopen')
- eq(':foo', get_cur_win_var('quickfix_title'))
+ eq('foo', get_cur_win_var('quickfix_title'))
end)
end)