aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/buffer_spec.lua20
-rw-r--r--test/functional/api/extmark_spec.lua77
-rw-r--r--test/functional/api/highlight_spec.lua12
-rw-r--r--test/functional/api/vim_spec.lua14
-rw-r--r--test/functional/api/window_spec.lua8
-rw-r--r--test/functional/core/exit_spec.lua4
-rw-r--r--test/functional/core/job_spec.lua5
-rw-r--r--test/functional/eval/interrupt_spec.lua6
-rw-r--r--test/functional/ex_cmds/oldfiles_spec.lua4
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua20
-rw-r--r--test/functional/helpers.lua37
-rw-r--r--test/functional/legacy/005_bufleave_delete_buffer_spec.lua6
-rw-r--r--test/functional/legacy/006_argument_list_spec.lua8
-rw-r--r--test/functional/legacy/012_directory_spec.lua8
-rw-r--r--test/functional/legacy/023_edit_arguments_spec.lua4
-rw-r--r--test/functional/legacy/030_fileformats_spec.lua34
-rw-r--r--test/functional/legacy/033_lisp_indent_spec.lua4
-rw-r--r--test/functional/legacy/036_regexp_character_classes_spec.lua2
-rw-r--r--test/functional/legacy/045_folding_spec.lua4
-rw-r--r--test/functional/legacy/051_highlight_spec.lua4
-rw-r--r--test/functional/legacy/057_sort_spec.lua62
-rw-r--r--test/functional/legacy/074_global_var_in_viminfo_spec.lua6
-rw-r--r--test/functional/legacy/075_maparg_spec.lua4
-rw-r--r--test/functional/legacy/107_adjust_window_and_contents_spec.lua4
-rw-r--r--test/functional/legacy/arglist_spec.lua13
-rw-r--r--test/functional/legacy/autoformat_join_spec.lua4
-rw-r--r--test/functional/legacy/close_count_spec.lua10
-rw-r--r--test/functional/legacy/display_spec.lua31
-rw-r--r--test/functional/legacy/eval_spec.lua10
-rw-r--r--test/functional/legacy/mapping_spec.lua8
-rw-r--r--test/functional/legacy/memory_usage_spec.lua8
-rw-r--r--test/functional/legacy/search_mbyte_spec.lua4
-rw-r--r--test/functional/legacy/search_spec.lua107
-rw-r--r--test/functional/legacy/utf8_spec.lua4
-rw-r--r--test/functional/legacy/visual_mode_spec.lua42
-rw-r--r--test/functional/legacy/wordcount_spec.lua10
-rw-r--r--test/functional/lua/buffer_updates_spec.lua333
-rw-r--r--test/functional/lua/commands_spec.lua2
-rw-r--r--test/functional/lua/luaeval_spec.lua4
-rw-r--r--test/functional/lua/treesitter_spec.lua326
-rw-r--r--test/functional/lua/vim_spec.lua375
-rw-r--r--test/functional/normal/meta_key_spec.lua22
-rw-r--r--test/functional/options/defaults_spec.lua220
-rw-r--r--test/functional/plugin/lsp_spec.lua122
-rw-r--r--test/functional/provider/clipboard_spec.lua10
-rw-r--r--test/functional/provider/perl_spec.lua50
-rw-r--r--test/functional/provider/ruby_spec.lua22
-rw-r--r--test/functional/terminal/buffer_spec.lua4
-rw-r--r--test/functional/terminal/cursor_spec.lua2
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua14
-rw-r--r--test/functional/terminal/scrollback_spec.lua6
-rw-r--r--test/functional/terminal/window_spec.lua4
-rw-r--r--test/functional/ui/bufhl_spec.lua12
-rw-r--r--test/functional/ui/cmdline_spec.lua32
-rw-r--r--test/functional/ui/cursor_spec.lua17
-rw-r--r--test/functional/ui/decorations_spec.lua118
-rw-r--r--test/functional/ui/float_spec.lua2
-rw-r--r--test/functional/ui/fold_spec.lua46
-rw-r--r--test/functional/ui/inccommand_spec.lua58
-rw-r--r--test/functional/ui/messages_spec.lua2
-rw-r--r--test/functional/ui/mouse_spec.lua2
-rw-r--r--test/functional/ui/multigrid_spec.lua8
-rw-r--r--test/functional/ui/options_spec.lua8
-rw-r--r--test/functional/ui/popupmenu_spec.lua44
-rw-r--r--test/functional/ui/searchhl_spec.lua2
-rw-r--r--test/functional/viml/completion_spec.lua48
-rw-r--r--test/functional/viml/errorlist_spec.lua2
-rw-r--r--test/functional/visual/meta_key_spec.lua22
-rw-r--r--test/helpers.lua73
-rw-r--r--test/symbolic/klee/nvim/charset.c4
-rw-r--r--test/unit/os/env_spec.lua13
71 files changed, 2063 insertions, 574 deletions
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index da7515f012..8ed642b43e 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -534,6 +534,26 @@ describe('api/buf', function()
end)
end)
+ describe('nvim_buf_delete', function()
+ it('allows for just deleting', function()
+ nvim('command', 'new')
+ local b = nvim('get_current_buf')
+ ok(buffer('is_valid', b))
+ nvim('buf_delete', b, {})
+ ok(not buffer('is_loaded', b))
+ ok(not buffer('is_valid', b))
+ end)
+
+ it('allows for just unloading', function()
+ nvim('command', 'new')
+ local b = nvim('get_current_buf')
+ ok(buffer('is_valid', b))
+ nvim('buf_delete', b, { unload = true })
+ ok(not buffer('is_loaded', b))
+ ok(buffer('is_valid', b))
+ end)
+ end)
+
describe('nvim_buf_get_mark', function()
it('works', function()
curbuf('set_lines', -1, -1, true, {'a', 'bit of', 'text'})
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index 9ea35e50a2..ab913ba4a4 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -17,22 +17,14 @@ local function expect(contents)
return eq(contents, helpers.curbuf_contents())
end
-local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end
- local rv = curbufmeths.get_extmark_by_id(ns, mark)
- eq({er, ec}, rv)
- feed("u")
- rv = curbufmeths.get_extmark_by_id(ns, mark)
- eq({sr, sc}, rv)
- feed("<c-r>")
- rv = curbufmeths.get_extmark_by_id(ns, mark)
- eq({er, ec}, rv)
-end
-
local function set_extmark(ns_id, id, line, col, opts)
if opts == nil then
opts = {}
end
- return curbufmeths.set_extmark(ns_id, id, line, col, opts)
+ if id ~= nil and id ~= 0 then
+ opts.id = id
+ end
+ return curbufmeths.set_extmark(ns_id, line, col, opts)
end
local function get_extmarks(ns_id, start, end_, opts)
@@ -42,6 +34,24 @@ local function get_extmarks(ns_id, start, end_, opts)
return curbufmeths.get_extmarks(ns_id, start, end_, opts)
end
+local function get_extmark_by_id(ns_id, id, opts)
+ if opts == nil then
+ opts = {}
+ end
+ return curbufmeths.get_extmark_by_id(ns_id, id, opts)
+end
+
+local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end
+ local rv = get_extmark_by_id(ns, mark)
+ eq({er, ec}, rv)
+ feed("u")
+ rv = get_extmark_by_id(ns, mark)
+ eq({sr, sc}, rv)
+ feed("<c-r>")
+ rv = get_extmark_by_id(ns, mark)
+ eq({er, ec}, rv)
+end
+
local function batch_set(ns_id, positions)
local ids = {}
for _, pos in ipairs(positions) do
@@ -90,10 +100,19 @@ describe('API/extmarks', function()
ns2 = request('nvim_create_namespace', "my-fancy-plugin2")
end)
+ it("can end extranges past final newline using end_col = 0", function()
+ set_extmark(ns, marks[1], 0, 0, {
+ end_col = 0,
+ end_line = 1
+ })
+ eq("end_col value outside range",
+ pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_line = 1 }))
+ end)
+
it('adds, updates and deletes marks', function()
local rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
eq(marks[1], rv)
- rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ rv = get_extmark_by_id(ns, marks[1])
eq({positions[1][1], positions[1][2]}, rv)
-- Test adding a second mark on same row works
rv = set_extmark(ns, marks[2], positions[2][1], positions[2][2])
@@ -102,14 +121,14 @@ describe('API/extmarks', function()
-- Test an update, (same pos)
rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
eq(marks[1], rv)
- rv = curbufmeths.get_extmark_by_id(ns, marks[2])
+ rv = get_extmark_by_id(ns, marks[2])
eq({positions[2][1], positions[2][2]}, rv)
-- Test an update, (new pos)
row = positions[1][1]
col = positions[1][2] + 1
rv = set_extmark(ns, marks[1], row, col)
eq(marks[1], rv)
- rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ rv = get_extmark_by_id(ns, marks[1])
eq({row, col}, rv)
-- remove the test marks
@@ -432,7 +451,7 @@ describe('API/extmarks', function()
~ |
|
]])
- local rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ local rv = get_extmark_by_id(ns, marks[1])
eq({0, 6}, rv)
check_undo_redo(ns, marks[1], 0, 3, 0, 6)
end)
@@ -906,9 +925,9 @@ describe('API/extmarks', function()
-- Set the mark before the cursor, should stay there
set_extmark(ns, marks[2], 0, 10)
feed("i<cr><esc>")
- local rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ local rv = get_extmark_by_id(ns, marks[1])
eq({1, 3}, rv)
- rv = curbufmeths.get_extmark_by_id(ns, marks[2])
+ rv = get_extmark_by_id(ns, marks[2])
eq({0, 10}, rv)
check_undo_redo(ns, marks[1], 0, 12, 1, 3)
end)
@@ -921,12 +940,12 @@ describe('API/extmarks', function()
feed("0iint <esc>A {<cr><esc>0i1M1<esc>")
set_extmark(ns, marks[1], 1, 1)
feed("0i<c-f><esc>")
- local rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ local rv = get_extmark_by_id(ns, marks[1])
eq({1, 3}, rv)
check_undo_redo(ns, marks[1], 1, 1, 1, 3)
-- now check when cursor at eol
feed("uA<c-f><esc>")
- rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ rv = get_extmark_by_id(ns, marks[1])
eq({1, 3}, rv)
end)
@@ -937,12 +956,12 @@ describe('API/extmarks', function()
feed("0i<tab><esc>")
set_extmark(ns, marks[1], 0, 3)
feed("bi<c-d><esc>")
- local rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ local rv = get_extmark_by_id(ns, marks[1])
eq({0, 1}, rv)
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
-- check when cursor at eol
feed("uA<c-d><esc>")
- rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ rv = get_extmark_by_id(ns, marks[1])
eq({0, 1}, rv)
end)
@@ -1072,7 +1091,7 @@ describe('API/extmarks', function()
check_undo_redo(ns, marks[5], 2, 0, 3, 0)
feed('u')
feed([[:1,2s:3:\rxx<cr>]])
- eq({1, 3}, curbufmeths.get_extmark_by_id(ns, marks[3]))
+ eq({1, 3}, get_extmark_by_id(ns, marks[3]))
end)
it('substitions over multiple lines with replace in substition', function()
@@ -1311,16 +1330,16 @@ describe('API/extmarks', function()
eq("Invalid ns_id", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]))
eq("Invalid ns_id", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1]))
eq("Invalid ns_id", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2]))
- eq("Invalid ns_id", pcall_err(curbufmeths.get_extmark_by_id, ns_invalid, marks[1]))
+ eq("Invalid ns_id", pcall_err(get_extmark_by_id, ns_invalid, marks[1]))
end)
it('when col = line-length, set the mark on eol', function()
set_extmark(ns, marks[1], 0, -1)
- local rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ local rv = get_extmark_by_id(ns, marks[1])
eq({0, init_text:len()}, rv)
-- Test another
set_extmark(ns, marks[1], 0, -1)
- rv = curbufmeths.get_extmark_by_id(ns, marks[1])
+ rv = get_extmark_by_id(ns, marks[1])
eq({0, init_text:len()}, rv)
end)
@@ -1333,7 +1352,7 @@ describe('API/extmarks', function()
local invalid_col = init_text:len() + 1
local invalid_lnum = 3
eq('line value outside range', pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col))
- eq({}, curbufmeths.get_extmark_by_id(ns, marks[1]))
+ eq({}, get_extmark_by_id(ns, marks[1]))
end)
it('bug from check_col in extmark_set', function()
@@ -1357,14 +1376,14 @@ describe('API/extmarks', function()
it('can set a mark to other buffer', function()
local buf = request('nvim_create_buf', 0, 1)
request('nvim_buf_set_lines', buf, 0, -1, 1, {"", ""})
- local id = bufmeths.set_extmark(buf, ns, 0, 1, 0, {})
+ local id = bufmeths.set_extmark(buf, ns, 1, 0, {})
eq({{id, 1, 0}}, bufmeths.get_extmarks(buf, ns, 0, -1, {}))
end)
it('does not crash with append/delete/undo seqence', function()
meths.exec([[
let ns = nvim_create_namespace('myplugin')
- call nvim_buf_set_extmark(0, ns, 0, 0, 0, {})
+ call nvim_buf_set_extmark(0, ns, 0, 0, {})
call append(0, '')
%delete
undo]],false)
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index a9d4c72d31..daf20c006c 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -7,6 +7,7 @@ local meths = helpers.meths
local funcs = helpers.funcs
local pcall_err = helpers.pcall_err
local ok = helpers.ok
+local assert_alive = helpers.assert_alive
describe('API: highlight',function()
local expected_rgb = {
@@ -145,4 +146,15 @@ describe('API: highlight',function()
eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")},
meths.get_hl_by_name("Shrubbery", true))
end)
+
+ it("nvim_buf_add_highlight to other buffer doesn't crash if undo is disabled #12873", function()
+ command('vsplit file')
+ local err, _ = pcall(meths.buf_set_option, 1, 'undofile', false)
+ eq(true, err)
+ err, _ = pcall(meths.buf_set_option, 1, 'undolevels', -1)
+ eq(true, err)
+ err, _ = pcall(meths.buf_add_highlight, 1, -1, 'Question', 0, 0, -1)
+ eq(true, err)
+ assert_alive()
+ end)
end)
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 72e810e3e4..0b52d06df9 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -449,19 +449,19 @@ describe('API', function()
end)
it('reports errors', function()
- eq([[Error loading lua: [string "<nvim>"]:1: '=' expected near '+']],
+ eq([[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']],
pcall_err(meths.exec_lua, 'a+*b', {}))
- eq([[Error loading lua: [string "<nvim>"]:1: unexpected symbol near '1']],
+ eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']],
pcall_err(meths.exec_lua, '1+2', {}))
- eq([[Error loading lua: [string "<nvim>"]:1: unexpected symbol]],
+ eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol]],
pcall_err(meths.exec_lua, 'aa=bb\0', {}))
- eq([[Error executing lua: [string "<nvim>"]:1: attempt to call global 'bork' (a nil value)]],
+ eq([[Error executing lua: [string "<nvim>"]:0: attempt to call global 'bork' (a nil value)]],
pcall_err(meths.exec_lua, 'bork()', {}))
- eq('Error executing lua: [string "<nvim>"]:1: did\nthe\nfail',
+ eq('Error executing lua: [string "<nvim>"]:0: did\nthe\nfail',
pcall_err(meths.exec_lua, 'error("did\\nthe\\nfail")', {}))
end)
@@ -605,7 +605,7 @@ describe('API', function()
end)
it('vim.paste() failure', function()
nvim('exec_lua', 'vim.paste = (function(lines, phase) error("fake fail") end)', {})
- eq([[Error executing lua: [string "<nvim>"]:1: fake fail]],
+ eq([[Error executing lua: [string "<nvim>"]:0: fake fail]],
pcall_err(request, 'nvim_paste', 'line 1\nline 2\nline 3', false, 1))
end)
end)
@@ -1252,7 +1252,7 @@ describe('API', function()
{0:~ }|
{1:very fail} |
]])
- helpers.wait()
+ helpers.poke_eventloop()
-- shows up to &cmdheight lines
nvim_async('err_write', 'more fail\ntoo fail\n')
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 8c7c3208c0..7471f50dbd 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -3,7 +3,7 @@ local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
ok, feed, insert, eval = helpers.clear, helpers.nvim, helpers.curbuf,
helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq,
helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local curwinmeths = helpers.curwinmeths
local funcs = helpers.funcs
local request = helpers.request
@@ -82,7 +82,7 @@ describe('API/win', function()
insert("epilogue")
local win = curwin()
feed('gg')
- wait() -- let nvim process the 'gg' command
+ poke_eventloop() -- let nvim process the 'gg' command
-- cursor position is at beginning
eq({1, 0}, window('get_cursor', win))
@@ -128,7 +128,7 @@ describe('API/win', function()
insert("second line")
feed('gg')
- wait() -- let nvim process the 'gg' command
+ poke_eventloop() -- let nvim process the 'gg' command
-- cursor position is at beginning
local win = curwin()
@@ -139,7 +139,7 @@ describe('API/win', function()
-- move down a line
feed('j')
- wait() -- let nvim process the 'j' command
+ poke_eventloop() -- let nvim process the 'j' command
-- cursor is still in column 5
eq({2, 5}, window('get_cursor', win))
diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua
index 80c65e4544..230b7f8e01 100644
--- a/test/functional/core/exit_spec.lua
+++ b/test/functional/core/exit_spec.lua
@@ -8,7 +8,7 @@ local run = helpers.run
local funcs = helpers.funcs
local nvim_prog = helpers.nvim_prog
local redir_exec = helpers.redir_exec
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('v:exiting', function()
local cid
@@ -52,7 +52,7 @@ describe(':cquit', function()
local function test_cq(cmdline, exit_code, redir_msg)
if redir_msg then
eq('\n' .. redir_msg, redir_exec(cmdline))
- wait()
+ poke_eventloop()
eq(2, eval("1+1")) -- Still alive?
else
funcs.system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', '--cmd', cmdline})
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 57e6f4fd63..6d1182478a 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -11,7 +11,7 @@ local os_kill = helpers.os_kill
local retry = helpers.retry
local meths = helpers.meths
local NIL = helpers.NIL
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local iswin = helpers.iswin
local get_pathsep = helpers.get_pathsep
local pathroot = helpers.pathroot
@@ -93,6 +93,7 @@ describe('jobs', function()
{'notification', 'stdout', {0, {'hello world %VAR%', ''}}}
})
else
+ nvim('command', "set shell=/bin/sh")
nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
expect_msg_seq({
{'notification', 'stdout', {0, {'hello world', ''}}}
@@ -427,7 +428,7 @@ describe('jobs', function()
\ }
let job = jobstart(['cat', '-'], g:callbacks)
]])
- wait()
+ poke_eventloop()
source([[
function! g:JobHandler(job_id, data, event)
endfunction
diff --git a/test/functional/eval/interrupt_spec.lua b/test/functional/eval/interrupt_spec.lua
index 7f4ca95317..05b1f4ff57 100644
--- a/test/functional/eval/interrupt_spec.lua
+++ b/test/functional/eval/interrupt_spec.lua
@@ -4,7 +4,7 @@ local command = helpers.command
local meths = helpers.meths
local clear = helpers.clear
local sleep = helpers.sleep
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local feed = helpers.feed
local eq = helpers.eq
@@ -39,7 +39,7 @@ describe('List support code', function()
feed(':let t_rt = reltime()<CR>:let t_bl = copy(bl)<CR>')
sleep(min_dur / 16 * 1000)
feed('<C-c>')
- wait()
+ poke_eventloop()
command('let t_dur = reltimestr(reltime(t_rt))')
local t_dur = tonumber(meths.get_var('t_dur'))
if t_dur >= dur / 8 then
@@ -50,7 +50,7 @@ describe('List support code', function()
feed(':let t_rt = reltime()<CR>:let t_j = join(bl)<CR>')
sleep(min_dur / 16 * 1000)
feed('<C-c>')
- wait()
+ poke_eventloop()
command('let t_dur = reltimestr(reltime(t_rt))')
local t_dur = tonumber(meths.get_var('t_dur'))
print(('t_dur: %g'):format(t_dur))
diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua
index 802c3f68c6..003ab64dd4 100644
--- a/test/functional/ex_cmds/oldfiles_spec.lua
+++ b/test/functional/ex_cmds/oldfiles_spec.lua
@@ -3,7 +3,7 @@ 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, wait = helpers.feed, helpers.wait
+local feed, poke_eventloop = helpers.feed, helpers.poke_eventloop
local ok = helpers.ok
local eval = helpers.eval
@@ -90,7 +90,7 @@ describe(':browse oldfiles', function()
feed_command('edit testfile2')
filename2 = buf.get_name()
feed_command('wshada')
- wait()
+ poke_eventloop()
_clear()
-- Ensure nvim is out of "Press ENTER..." prompt.
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index dca7f35923..a30eb748d0 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -125,6 +125,26 @@ function tests.basic_check_capabilities()
}
end
+function tests.capabilities_for_client_supports_method()
+ skeleton {
+ on_init = function(params)
+ local expected_capabilities = protocol.make_client_capabilities()
+ assert_eq(params.capabilities, expected_capabilities)
+ return {
+ capabilities = {
+ textDocumentSync = protocol.TextDocumentSyncKind.Full;
+ completionProvider = true;
+ hoverProvider = true;
+ definitionProvider = false;
+ referencesProvider = false;
+ }
+ }
+ end;
+ body = function()
+ end;
+ }
+end
+
function tests.basic_finish()
skeleton {
on_init = function(params)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index e8435cd3b7..0bd378d832 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -22,6 +22,7 @@ local ok = global_helpers.ok
local sleep = global_helpers.sleep
local tbl_contains = global_helpers.tbl_contains
local write_file = global_helpers.write_file
+local fail = global_helpers.fail
local module = {
NIL = mpack.NIL,
@@ -553,9 +554,9 @@ function module.curbuf(method, ...)
return module.buffer(method, 0, ...)
end
-function module.wait()
- -- Execute 'nvim_eval' (a deferred function) to block
- -- until all pending input is processed.
+function module.poke_eventloop()
+ -- Execute 'nvim_eval' (a deferred function) to
+ -- force at least one main_loop iteration
session:request('nvim_eval', '1')
end
@@ -565,7 +566,7 @@ end
--@see buf_lines()
function module.curbuf_contents()
- module.wait() -- Before inspecting the buffer, process all input.
+ module.poke_eventloop() -- Before inspecting the buffer, do whatever.
return table.concat(module.curbuf('get_lines', 0, -1, true), '\n')
end
@@ -592,6 +593,24 @@ function module.expect_any(contents)
return ok(nil ~= string.find(module.curbuf_contents(), contents, 1, true))
end
+function module.expect_events(expected, received, kind)
+ local inspect = require'vim.inspect'
+ if not pcall(eq, expected, received) then
+ local msg = 'unexpected '..kind..' received.\n\n'
+
+ msg = msg .. 'received events:\n'
+ for _, e in ipairs(received) do
+ msg = msg .. ' ' .. inspect(e) .. ';\n'
+ end
+ msg = msg .. '\nexpected events:\n'
+ for _, e in ipairs(expected) do
+ msg = msg .. ' ' .. inspect(e) .. ';\n'
+ end
+ fail(msg)
+ end
+ return received
+end
+
-- Checks that the Nvim session did not terminate.
function module.assert_alive()
assert(2 == module.eval('1+1'), 'crash? request failed')
@@ -769,14 +788,14 @@ end
function module.missing_provider(provider)
if provider == 'ruby' or provider == 'node' or provider == 'perl' then
- local prog = module.funcs['provider#' .. provider .. '#Detect']()
- return prog == '' and (provider .. ' not detected') or false
+ local e = module.funcs['provider#'..provider..'#Detect']()[2]
+ return e ~= '' and e or false
elseif provider == 'python' or provider == 'python3' then
local py_major_version = (provider == 'python3' and 3 or 2)
- local errors = module.funcs['provider#pythonx#Detect'](py_major_version)[2]
- return errors ~= '' and errors or false
+ local e = module.funcs['provider#pythonx#Detect'](py_major_version)[2]
+ return e ~= '' and e or false
else
- assert(false, 'Unknown provider: ' .. provider)
+ assert(false, 'Unknown provider: '..provider)
end
end
diff --git a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua
index 8b92c877a6..8e977aa73e 100644
--- a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua
+++ b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua
@@ -4,7 +4,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, expect = helpers.command, helpers.expect
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('test5', function()
setup(clear)
@@ -34,7 +34,7 @@ describe('test5', function()
command('bwipe')
feed('G?this is a<cr>')
feed('othis is some more text<esc>')
- wait()
+ poke_eventloop()
-- Append some text to this file.
@@ -45,7 +45,7 @@ describe('test5', function()
command('bwipe!')
-- Append an extra line to the output register.
feed('ithis is another test line<esc>:yank A<cr>')
- wait()
+ poke_eventloop()
-- Output results
command('%d')
diff --git a/test/functional/legacy/006_argument_list_spec.lua b/test/functional/legacy/006_argument_list_spec.lua
index 9f75a91fa8..d269bf8ec9 100644
--- a/test/functional/legacy/006_argument_list_spec.lua
+++ b/test/functional/legacy/006_argument_list_spec.lua
@@ -4,7 +4,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, dedent, eq = helpers.command, helpers.dedent, helpers.eq
local curbuf_contents = helpers.curbuf_contents
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('argument list', function()
setup(clear)
@@ -17,7 +17,7 @@ describe('argument list', function()
this is a test
this is a test
end of test file Xxx]])
- wait()
+ poke_eventloop()
command('au BufReadPost Xxx2 next Xxx2 Xxx1')
command('/^start of')
@@ -30,7 +30,7 @@ describe('argument list', function()
-- Write test file Xxx3
feed('$r3:.,/end of/w! Xxx3<cr>')
- wait()
+ poke_eventloop()
-- Redefine arglist; go to Xxx1
command('next! Xxx1 Xxx2 Xxx3')
@@ -43,7 +43,7 @@ describe('argument list', function()
-- Append contents of last window (Xxx1)
feed('')
- wait()
+ poke_eventloop()
command('%yank A')
-- should now be in Xxx2
diff --git a/test/functional/legacy/012_directory_spec.lua b/test/functional/legacy/012_directory_spec.lua
index cec4f93737..48dd24db9e 100644
--- a/test/functional/legacy/012_directory_spec.lua
+++ b/test/functional/legacy/012_directory_spec.lua
@@ -8,7 +8,7 @@ local lfs = require('lfs')
local eq = helpers.eq
local neq = helpers.neq
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local funcs = helpers.funcs
local meths = helpers.meths
local clear = helpers.clear
@@ -64,7 +64,7 @@ describe("'directory' option", function()
eq(nil, lfs.attributes('.Xtest1.swp'))
command('edit! Xtest1')
- wait()
+ poke_eventloop()
eq('Xtest1', funcs.buffer_name('%'))
-- Verify that the swapfile exists. In the legacy test this was done by
-- reading the output from :!ls.
@@ -72,7 +72,7 @@ describe("'directory' option", function()
meths.set_option('directory', './Xtest2,.')
command('edit Xtest1')
- wait()
+ poke_eventloop()
-- swapfile should no longer exist in CWD.
eq(nil, lfs.attributes('.Xtest1.swp'))
@@ -82,7 +82,7 @@ describe("'directory' option", function()
meths.set_option('directory', 'Xtest.je')
command('edit Xtest2/Xtest3')
eq(true, curbufmeths.get_option('swapfile'))
- wait()
+ poke_eventloop()
eq({ "Xtest3" }, ls_dir_sorted("Xtest2"))
eq({ "Xtest3.swp" }, ls_dir_sorted("Xtest.je"))
diff --git a/test/functional/legacy/023_edit_arguments_spec.lua b/test/functional/legacy/023_edit_arguments_spec.lua
index e705397a2b..f59d192c1e 100644
--- a/test/functional/legacy/023_edit_arguments_spec.lua
+++ b/test/functional/legacy/023_edit_arguments_spec.lua
@@ -3,7 +3,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, insert = helpers.clear, helpers.insert
local command, expect = helpers.command, helpers.expect
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe(':edit', function()
setup(clear)
@@ -13,7 +13,7 @@ describe(':edit', function()
The result should be in Xfile1: "fooPIPEbar", in Xfile2: "fooSLASHbar"
foo|bar
foo/bar]])
- wait()
+ poke_eventloop()
-- Prepare some test files
command('$-1w! Xfile1')
diff --git a/test/functional/legacy/030_fileformats_spec.lua b/test/functional/legacy/030_fileformats_spec.lua
index 2fd51602d8..15dbd05cf5 100644
--- a/test/functional/legacy/030_fileformats_spec.lua
+++ b/test/functional/legacy/030_fileformats_spec.lua
@@ -3,7 +3,7 @@
local helpers = require('test.functional.helpers')(after_each)
local feed, clear, command = helpers.feed, helpers.clear, helpers.command
local eq, write_file = helpers.eq, helpers.write_file
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('fileformats option', function()
setup(function()
@@ -107,7 +107,7 @@ describe('fileformats option', function()
command('bwipe XXDosMac')
command('e! XXEol')
feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>')
- wait()
+ poke_eventloop()
command('w! XXtt54')
command('bwipeout! XXEol')
command('set fileformats=dos,mac')
@@ -116,7 +116,7 @@ describe('fileformats option', function()
command('bwipe XXUxDs')
command('e! XXUxMac')
feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>')
- wait()
+ poke_eventloop()
command('w! XXtt62')
command('bwipeout! XXUxMac')
command('e! XXUxDsMc')
@@ -124,7 +124,7 @@ describe('fileformats option', function()
command('bwipe XXUxDsMc')
command('e! XXMacEol')
feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>')
- wait()
+ poke_eventloop()
command('w! XXtt64')
command('bwipeout! XXMacEol')
@@ -135,7 +135,7 @@ describe('fileformats option', function()
command('bwipe XXUxDsMc')
command('e! XXEol')
feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>')
- wait()
+ poke_eventloop()
command('w! XXtt72')
command('bwipeout! XXEol')
command('set fileformats=mac,dos,unix')
@@ -144,7 +144,7 @@ describe('fileformats option', function()
command('bwipe XXUxDsMc')
command('e! XXEol')
feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>')
- wait()
+ poke_eventloop()
command('w! XXtt82')
command('bwipeout! XXEol')
-- Try with 'binary' set.
@@ -165,7 +165,7 @@ describe('fileformats option', function()
-- char was.
command('set fileformat=unix nobin')
feed('ggdGaEND<esc>')
- wait()
+ poke_eventloop()
command('w >>XXtt01')
command('w >>XXtt02')
command('w >>XXtt11')
@@ -204,52 +204,52 @@ describe('fileformats option', function()
command('$r XXtt01')
command('$r XXtt02')
feed('Go1<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt11')
command('$r XXtt12')
command('$r XXtt13')
feed('Go2<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt21')
command('$r XXtt22')
command('$r XXtt23')
feed('Go3<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt31')
command('$r XXtt32')
command('$r XXtt33')
feed('Go4<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt41')
command('$r XXtt42')
command('$r XXtt43')
feed('Go5<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt51')
command('$r XXtt52')
command('$r XXtt53')
command('$r XXtt54')
feed('Go6<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt61')
command('$r XXtt62')
command('$r XXtt63')
command('$r XXtt64')
feed('Go7<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt71')
command('$r XXtt72')
feed('Go8<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt81')
command('$r XXtt82')
feed('Go9<esc>')
- wait()
+ poke_eventloop()
command('$r XXtt91')
command('$r XXtt92')
command('$r XXtt93')
feed('Go10<esc>')
- wait()
+ poke_eventloop()
command('$r XXUnix')
command('set nobinary ff&')
diff --git a/test/functional/legacy/033_lisp_indent_spec.lua b/test/functional/legacy/033_lisp_indent_spec.lua
index 5132333a5c..b27de6c16d 100644
--- a/test/functional/legacy/033_lisp_indent_spec.lua
+++ b/test/functional/legacy/033_lisp_indent_spec.lua
@@ -4,7 +4,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, expect = helpers.command, helpers.expect
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('lisp indent', function()
setup(clear)
@@ -39,7 +39,7 @@ describe('lisp indent', function()
command('set lisp')
command('/^(defun')
feed('=G:/^(defun/,$yank A<cr>')
- wait()
+ poke_eventloop()
-- Put @a and clean empty line
command('%d')
diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua
index 38e8145d1c..6f66efcb67 100644
--- a/test/functional/legacy/036_regexp_character_classes_spec.lua
+++ b/test/functional/legacy/036_regexp_character_classes_spec.lua
@@ -15,7 +15,7 @@ end
local function diff(text, nodedent)
local fname = helpers.tmpname()
command('w! '..fname)
- helpers.wait()
+ helpers.poke_eventloop()
local data = io.open(fname):read('*all')
if nodedent then
helpers.eq(text, data)
diff --git a/test/functional/legacy/045_folding_spec.lua b/test/functional/legacy/045_folding_spec.lua
index 1e5239ceac..7d7856fd37 100644
--- a/test/functional/legacy/045_folding_spec.lua
+++ b/test/functional/legacy/045_folding_spec.lua
@@ -59,7 +59,7 @@ describe('folding', function()
feed('kYpj')
feed_command('call append("$", foldlevel("."))')
- helpers.wait()
+ helpers.poke_eventloop()
screen:expect([[
dd {{{ |
ee {{{ }}} |
@@ -88,7 +88,7 @@ describe('folding', function()
feed_command('call append("$", foldlevel(2))')
feed('zR')
- helpers.wait()
+ helpers.poke_eventloop()
screen:expect([[
aa |
bb |
diff --git a/test/functional/legacy/051_highlight_spec.lua b/test/functional/legacy/051_highlight_spec.lua
index 0c9c9621ee..d3f2897493 100644
--- a/test/functional/legacy/051_highlight_spec.lua
+++ b/test/functional/legacy/051_highlight_spec.lua
@@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, feed = helpers.clear, helpers.feed
local expect = helpers.expect
local eq = helpers.eq
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local exc_exec = helpers.exc_exec
local feed_command = helpers.feed_command
@@ -34,7 +34,7 @@ describe(':highlight', function()
-- More --^ |
]])
feed('q')
- wait() -- wait until we're back to normal
+ poke_eventloop() -- wait until we're back to normal
feed_command('hi Search')
feed_command('hi Normal')
diff --git a/test/functional/legacy/057_sort_spec.lua b/test/functional/legacy/057_sort_spec.lua
index bdc2c9779c..328d6f6fa0 100644
--- a/test/functional/legacy/057_sort_spec.lua
+++ b/test/functional/legacy/057_sort_spec.lua
@@ -2,8 +2,8 @@
local helpers = require('test.functional.helpers')(after_each)
-local insert, command, clear, expect, eq, wait = helpers.insert,
- helpers.command, helpers.clear, helpers.expect, helpers.eq, helpers.wait
+local insert, command, clear, expect, eq, poke_eventloop = helpers.insert,
+ helpers.command, helpers.clear, helpers.expect, helpers.eq, helpers.poke_eventloop
local exc_exec = helpers.exc_exec
describe(':sort', function()
@@ -27,7 +27,7 @@ describe(':sort', function()
it('alphabetical', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort')
expect([[
@@ -67,7 +67,7 @@ describe(':sort', function()
b321
b321b
]])
- wait()
+ poke_eventloop()
command('sort n')
expect([[
abc
@@ -92,7 +92,7 @@ describe(':sort', function()
it('hexadecimal', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort x')
expect([[
@@ -114,7 +114,7 @@ describe(':sort', function()
it('alphabetical, unique', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort u')
expect([[
@@ -135,7 +135,7 @@ describe(':sort', function()
it('alphabetical, reverse', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort!')
expect([[
c321d
@@ -157,7 +157,7 @@ describe(':sort', function()
it('numerical, reverse', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort! n')
expect([[
b322b
@@ -179,7 +179,7 @@ describe(':sort', function()
it('unique, reverse', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort! u')
expect([[
c321d
@@ -200,7 +200,7 @@ describe(':sort', function()
it('octal', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort o')
expect([[
abc
@@ -222,7 +222,7 @@ describe(':sort', function()
it('reverse, hexadecimal', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort! x')
expect([[
c321d
@@ -244,7 +244,7 @@ describe(':sort', function()
it('alphabetical, skip first character', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort/./')
expect([[
a
@@ -266,7 +266,7 @@ describe(':sort', function()
it('alphabetical, skip first 2 characters', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort/../')
expect([[
ab
@@ -288,7 +288,7 @@ describe(':sort', function()
it('alphabetical, unique, skip first 2 characters', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort/../u')
expect([[
ab
@@ -309,7 +309,7 @@ describe(':sort', function()
it('numerical, skip first character', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort/./n')
expect([[
abc
@@ -331,7 +331,7 @@ describe(':sort', function()
it('alphabetical, sort on first character', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort/./r')
expect([[
@@ -353,7 +353,7 @@ describe(':sort', function()
it('alphabetical, sort on first 2 characters', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort/../r')
expect([[
a
@@ -375,7 +375,7 @@ describe(':sort', function()
it('numerical, sort on first character', function()
insert(text)
- wait()
+ poke_eventloop()
command('sort/./rn')
expect([[
abc
@@ -397,7 +397,7 @@ describe(':sort', function()
it('alphabetical, skip past first digit', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d/]])
expect([[
abc
@@ -419,7 +419,7 @@ describe(':sort', function()
it('alphabetical, sort on first digit', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d/r]])
expect([[
abc
@@ -441,7 +441,7 @@ describe(':sort', function()
it('numerical, skip past first digit', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d/n]])
expect([[
abc
@@ -463,7 +463,7 @@ describe(':sort', function()
it('numerical, sort on first digit', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d/rn]])
expect([[
abc
@@ -485,7 +485,7 @@ describe(':sort', function()
it('alphabetical, skip past first 2 digits', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d\d/]])
expect([[
abc
@@ -507,7 +507,7 @@ describe(':sort', function()
it('numerical, skip past first 2 digits', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d\d/n]])
expect([[
abc
@@ -529,7 +529,7 @@ describe(':sort', function()
it('hexadecimal, skip past first 2 digits', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d\d/x]])
expect([[
abc
@@ -551,7 +551,7 @@ describe(':sort', function()
it('alpha, on first 2 digits', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d\d/r]])
expect([[
abc
@@ -573,7 +573,7 @@ describe(':sort', function()
it('numeric, on first 2 digits', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d\d/rn]])
expect([[
abc
@@ -595,7 +595,7 @@ describe(':sort', function()
it('hexadecimal, on first 2 digits', function()
insert(text)
- wait()
+ poke_eventloop()
command([[sort/\d\d/rx]])
expect([[
abc
@@ -638,7 +638,7 @@ describe(':sort', function()
0b100010
0b100100
0b100010]])
- wait()
+ poke_eventloop()
command([[sort b]])
expect([[
0b000000
@@ -673,7 +673,7 @@ describe(':sort', function()
0b101010
0b000000
b0b111000]])
- wait()
+ poke_eventloop()
command([[sort b]])
expect([[
0b000000
@@ -700,7 +700,7 @@ describe(':sort', function()
1.15e-6
-1.1e3
-1.01e3]])
- wait()
+ poke_eventloop()
command([[sort f]])
expect([[
-1.1e3
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 f7f074c61a..445d742c1f 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 =
+local clear, command, eq, neq, eval, poke_eventloop =
helpers.clear, helpers.command, helpers.eq, helpers.neq, helpers.eval,
- helpers.wait
+ helpers.poke_eventloop
describe('storing global variables in ShaDa files', function()
local tempname = 'Xtest-functional-legacy-074'
@@ -36,7 +36,7 @@ describe('storing global variables in ShaDa files', function()
eq(test_list, eval('MY_GLOBAL_LIST'))
command('wsh! ' .. tempname)
- wait()
+ poke_eventloop()
-- Assert that the shada file exists.
neq(nil, lfs.attributes(tempname))
diff --git a/test/functional/legacy/075_maparg_spec.lua b/test/functional/legacy/075_maparg_spec.lua
index ee2b041b51..ad6c190104 100644
--- a/test/functional/legacy/075_maparg_spec.lua
+++ b/test/functional/legacy/075_maparg_spec.lua
@@ -4,7 +4,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed = helpers.clear, helpers.feed
local command, expect = helpers.command, helpers.expect
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('maparg()', function()
setup(clear)
@@ -25,7 +25,7 @@ describe('maparg()', function()
command('map abc y<S-char-114>y')
command([[call append('$', maparg('abc'))]])
feed('Go<esc>:<cr>')
- wait()
+ poke_eventloop()
-- Outside of the range, minimum
command('inoremap <Char-0x1040> a')
diff --git a/test/functional/legacy/107_adjust_window_and_contents_spec.lua b/test/functional/legacy/107_adjust_window_and_contents_spec.lua
index 239f60341a..841eeef0af 100644
--- a/test/functional/legacy/107_adjust_window_and_contents_spec.lua
+++ b/test/functional/legacy/107_adjust_window_and_contents_spec.lua
@@ -3,7 +3,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local clear = helpers.clear
local insert = helpers.insert
local command = helpers.command
@@ -16,7 +16,7 @@ describe('107', function()
screen:attach()
insert('start:')
- wait()
+ poke_eventloop()
command('new')
command('call setline(1, range(1,256))')
command('let r=[]')
diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua
index 241a19d940..67c5750033 100644
--- a/test/functional/legacy/arglist_spec.lua
+++ b/test/functional/legacy/arglist_spec.lua
@@ -42,9 +42,7 @@ describe('argument list commands', function()
end)
it('test that argadd() works', function()
- -- Fails with “E474: Invalid argument”. Not sure whether it is how it is
- -- supposed to behave.
- -- command('%argdelete')
+ command('%argdelete')
command('argadd a b c')
eq(0, eval('argidx()'))
@@ -176,9 +174,14 @@ describe('argument list commands', function()
command('last')
command('argdelete %')
eq({'b'}, eval('argv()'))
- assert_fails('argdelete', 'E471:')
+ assert_fails('argdelete', 'E610:')
assert_fails('1,100argdelete', 'E16:')
- command('%argd')
+ reset_arglist()
+ command('args a b c d')
+ command('next')
+ command('argdel')
+ eq({'a', 'c', 'd'}, eval('argv()'))
+ command('%argdel')
end)
it('test for the :next, :prev, :first, :last, :rewind commands', function()
diff --git a/test/functional/legacy/autoformat_join_spec.lua b/test/functional/legacy/autoformat_join_spec.lua
index 84d661c190..22b1c258fe 100644
--- a/test/functional/legacy/autoformat_join_spec.lua
+++ b/test/functional/legacy/autoformat_join_spec.lua
@@ -3,7 +3,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, expect = helpers.command, helpers.expect
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('autoformat join', function()
setup(clear)
@@ -21,7 +21,7 @@ Results:]])
feed('gg')
feed('0gqj<cr>')
- wait()
+ poke_eventloop()
command([[let a=string(getpos("'[")).'/'.string(getpos("']"))]])
command("g/^This line/;'}-join")
diff --git a/test/functional/legacy/close_count_spec.lua b/test/functional/legacy/close_count_spec.lua
index 9b932e2ef0..60ae155fbf 100644
--- a/test/functional/legacy/close_count_spec.lua
+++ b/test/functional/legacy/close_count_spec.lua
@@ -3,7 +3,7 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local eval = helpers.eval
local feed = helpers.feed
local clear = helpers.clear
@@ -110,23 +110,23 @@ describe('close_count', function()
command('for i in range(5)|new|endfor')
command('4wincmd w')
feed('<C-W>c<cr>')
- wait()
+ poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
eq({25, 24, 23, 21, 1}, eval('buffers'))
feed('1<C-W>c<cr>')
- wait()
+ poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
eq({24, 23, 21, 1}, eval('buffers'))
feed('9<C-W>c<cr>')
- wait()
+ poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
eq({24, 23, 21}, eval('buffers'))
command('1wincmd w')
feed('2<C-W>c<cr>')
- wait()
+ poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
eq({24, 21}, eval('buffers'))
diff --git a/test/functional/legacy/display_spec.lua b/test/functional/legacy/display_spec.lua
new file mode 100644
index 0000000000..3fbbe96947
--- /dev/null
+++ b/test/functional/legacy/display_spec.lua
@@ -0,0 +1,31 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local poke_eventloop = helpers.poke_eventloop
+local feed = helpers.feed
+local feed_command = helpers.feed_command
+
+describe('display', function()
+ local screen
+
+ it('scroll when modified at topline', function()
+ clear()
+ screen = Screen.new(20, 4)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true},
+ })
+
+ feed_command([[call setline(1, repeat('a', 21))]])
+ poke_eventloop()
+ feed('O')
+ screen:expect([[
+ ^ |
+ aaaaaaaaaaaaaaaaaaaa|
+ a |
+ {1:-- INSERT --} |
+ ]])
+ end)
+end)
+
diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
index 4198ea8bfe..ee9bd29fc4 100644
--- a/test/functional/legacy/eval_spec.lua
+++ b/test/functional/legacy/eval_spec.lua
@@ -4,7 +4,7 @@ local helpers = require('test.functional.helpers')(after_each)
local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, command, expect = helpers.clear, helpers.command, helpers.expect
local eq, eval, write_file = helpers.eq, helpers.eval, helpers.write_file
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local exc_exec = helpers.exc_exec
local dedent = helpers.dedent
@@ -71,7 +71,7 @@ describe('eval', function()
command([[call SetReg('I', 'abcI')]])
feed('Go{{{1 Appending single lines with setreg()<esc>')
- wait()
+ poke_eventloop()
command([[call SetReg('A', 'abcAc', 'c')]])
command([[call SetReg('A', 'abcAl', 'l')]])
command([[call SetReg('A', 'abcAc2','c')]])
@@ -700,13 +700,13 @@ describe('eval', function()
start:]])
command('/^012345678')
feed('6l')
- wait()
+ poke_eventloop()
command('let sp = getcurpos()')
feed('0')
- wait()
+ poke_eventloop()
command("call setpos('.', sp)")
feed('jyl')
- wait()
+ poke_eventloop()
command('$put')
expect([[
012345678
diff --git a/test/functional/legacy/mapping_spec.lua b/test/functional/legacy/mapping_spec.lua
index 56a5652184..92a757ca85 100644
--- a/test/functional/legacy/mapping_spec.lua
+++ b/test/functional/legacy/mapping_spec.lua
@@ -2,7 +2,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local feed_command, expect, wait = helpers.feed_command, helpers.expect, helpers.wait
+local feed_command, expect, poke_eventloop = helpers.feed_command, helpers.expect, helpers.poke_eventloop
describe('mapping', function()
before_each(clear)
@@ -29,9 +29,9 @@ describe('mapping', function()
feed_command('cunmap <c-c>')
feed('GA<cr>')
feed('TEST2: CTRL-C |')
- wait()
+ poke_eventloop()
feed('<c-c>A|<cr><esc>')
- wait()
+ poke_eventloop()
feed_command('unmap <c-c>')
feed_command('unmap! <c-c>')
@@ -46,7 +46,7 @@ describe('mapping', function()
feed('GV')
-- XXX: For some reason the mapping is only triggered
-- when <C-c> is in a separate feed command.
- wait()
+ poke_eventloop()
feed('<c-c>')
feed_command('vunmap <c-c>')
diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua
index 251e6a5ea4..fb0bacc2d2 100644
--- a/test/functional/legacy/memory_usage_spec.lua
+++ b/test/functional/legacy/memory_usage_spec.lua
@@ -7,7 +7,7 @@ local iswin = helpers.iswin
local retry = helpers.retry
local ok = helpers.ok
local source = helpers.source
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local uname = helpers.uname
local load_adjust = helpers.load_adjust
@@ -102,7 +102,7 @@ describe('memory usage', function()
call s:f(0)
endfor
]])
- wait()
+ poke_eventloop()
local after = monitor_memory_usage(pid)
-- Estimate the limit of max usage as 2x initial usage.
-- The lower limit can fluctuate a bit, use 97%.
@@ -147,11 +147,11 @@ describe('memory usage', function()
call s:f()
endfor
]])
- wait()
+ poke_eventloop()
local after = monitor_memory_usage(pid)
for _ = 1, 3 do
feed_command('so '..fname)
- wait()
+ poke_eventloop()
end
local last = monitor_memory_usage(pid)
-- The usage may be a bit less than the last value, use 80%.
diff --git a/test/functional/legacy/search_mbyte_spec.lua b/test/functional/legacy/search_mbyte_spec.lua
index a365f79cdf..ef7e41aa30 100644
--- a/test/functional/legacy/search_mbyte_spec.lua
+++ b/test/functional/legacy/search_mbyte_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local clear = helpers.clear
local insert = helpers.insert
local expect = helpers.expect
@@ -15,7 +15,7 @@ describe('search_mbyte', function()
Test bce:
A]=])
- wait()
+ poke_eventloop()
command('/^Test bce:/+1')
command([[$put =search('A', 'bce', line('.'))]])
diff --git a/test/functional/legacy/search_spec.lua b/test/functional/legacy/search_spec.lua
index a207b176d3..4ed08881de 100644
--- a/test/functional/legacy/search_spec.lua
+++ b/test/functional/legacy/search_spec.lua
@@ -6,7 +6,7 @@ local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
local funcs = helpers.funcs
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('search cmdline', function()
local screen
@@ -21,6 +21,7 @@ describe('search cmdline', function()
err = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
more = { bold = true, foreground = Screen.colors.SeaGreen4 },
tilde = { bold = true, foreground = Screen.colors.Blue1 },
+ hl = { background = Screen.colors.Yellow },
})
end)
@@ -482,9 +483,9 @@ describe('search cmdline', function()
-- "interactive". This mimics Vim's test_override("char_avail").
-- (See legacy test: test_search.vim)
feed('?the')
- wait()
+ poke_eventloop()
feed('<c-g>')
- wait()
+ poke_eventloop()
feed('<cr>')
screen:expect([[
1 the first |
@@ -495,11 +496,11 @@ describe('search cmdline', function()
command('$')
feed('?the')
- wait()
+ poke_eventloop()
feed('<c-g>')
- wait()
+ poke_eventloop()
feed('<c-g>')
- wait()
+ poke_eventloop()
feed('<cr>')
screen:expect([[
1 ^the first |
@@ -510,13 +511,13 @@ describe('search cmdline', function()
command('$')
feed('?the')
- wait()
+ poke_eventloop()
feed('<c-g>')
- wait()
+ poke_eventloop()
feed('<c-g>')
- wait()
+ poke_eventloop()
feed('<c-g>')
- wait()
+ poke_eventloop()
feed('<cr>')
screen:expect([[
1 the first |
@@ -527,9 +528,9 @@ describe('search cmdline', function()
command('$')
feed('?the')
- wait()
+ poke_eventloop()
feed('<c-t>')
- wait()
+ poke_eventloop()
feed('<cr>')
screen:expect([[
1 ^the first |
@@ -540,11 +541,11 @@ describe('search cmdline', function()
command('$')
feed('?the')
- wait()
+ poke_eventloop()
feed('<c-t>')
- wait()
+ poke_eventloop()
feed('<c-t>')
- wait()
+ poke_eventloop()
feed('<cr>')
screen:expect([[
1 the first |
@@ -555,13 +556,13 @@ describe('search cmdline', function()
command('$')
feed('?the')
- wait()
+ poke_eventloop()
feed('<c-t>')
- wait()
+ poke_eventloop()
feed('<c-t>')
- wait()
+ poke_eventloop()
feed('<c-t>')
- wait()
+ poke_eventloop()
feed('<cr>')
screen:expect([[
1 the first |
@@ -570,4 +571,72 @@ describe('search cmdline', function()
?the |
]])
end)
+
+ it('incsearch works with :sort', function()
+ -- oldtest: Test_incsearch_sort_dump().
+ screen:try_resize(20, 4)
+ command('set incsearch hlsearch scrolloff=0')
+ funcs.setline(1, {'another one 2', 'that one 3', 'the one 1'})
+
+ feed(':sort ni u /on')
+ screen:expect([[
+ another {inc:on}e 2 |
+ that {hl:on}e 3 |
+ the {hl:on}e 1 |
+ :sort ni u /on^ |
+ ]])
+ feed('<esc>')
+ end)
+
+ it('incsearch works with :vimgrep family', function()
+ -- oldtest: Test_incsearch_vimgrep_dump().
+ screen:try_resize(30, 4)
+ command('set incsearch hlsearch scrolloff=0')
+ funcs.setline(1, {'another one 2', 'that one 3', 'the one 1'})
+
+ feed(':vimgrep on')
+ screen:expect([[
+ another {inc:on}e 2 |
+ that {hl:on}e 3 |
+ the {hl:on}e 1 |
+ :vimgrep on^ |
+ ]])
+ feed('<esc>')
+
+ feed(':vimg /on/ *.txt')
+ screen:expect([[
+ another {inc:on}e 2 |
+ that {hl:on}e 3 |
+ the {hl:on}e 1 |
+ :vimg /on/ *.txt^ |
+ ]])
+ feed('<esc>')
+
+ feed(':vimgrepadd "\\<LT>on')
+ screen:expect([[
+ another {inc:on}e 2 |
+ that {hl:on}e 3 |
+ the {hl:on}e 1 |
+ :vimgrepadd "\<on^ |
+ ]])
+ feed('<esc>')
+
+ feed(':lv "tha')
+ screen:expect([[
+ another one 2 |
+ {inc:tha}t one 3 |
+ the one 1 |
+ :lv "tha^ |
+ ]])
+ feed('<esc>')
+
+ feed(':lvimgrepa "the" **/*.txt')
+ screen:expect([[
+ ano{inc:the}r one 2 |
+ that one 3 |
+ {hl:the} one 1 |
+ :lvimgrepa "the" **/*.txt^ |
+ ]])
+ feed('<esc>')
+ end)
end)
diff --git a/test/functional/legacy/utf8_spec.lua b/test/functional/legacy/utf8_spec.lua
index 5b93f25b24..8b5fc02d11 100644
--- a/test/functional/legacy/utf8_spec.lua
+++ b/test/functional/legacy/utf8_spec.lua
@@ -5,7 +5,7 @@ local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, expect = helpers.command, helpers.expect
local eq, eval = helpers.eq, helpers.eval
local source = helpers.source
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('utf8', function()
before_each(clear)
@@ -18,7 +18,7 @@ describe('utf8', function()
-- Visual block Insert adjusts for multi-byte char
feed('gg0l<C-V>jjIx<Esc>')
- wait()
+ poke_eventloop()
command('let r = getline(1, "$")')
command('bwipeout!')
diff --git a/test/functional/legacy/visual_mode_spec.lua b/test/functional/legacy/visual_mode_spec.lua
new file mode 100644
index 0000000000..c8e83ed649
--- /dev/null
+++ b/test/functional/legacy/visual_mode_spec.lua
@@ -0,0 +1,42 @@
+-- Test visual line mode selection redraw after scrolling
+
+local helpers = require('test.functional.helpers')(after_each)
+
+local Screen = require('test.functional.ui.screen')
+local call = helpers.call
+local clear = helpers.clear
+local feed = helpers.feed
+local feed_command = helpers.feed_command
+local funcs = helpers.funcs
+local meths = helpers.meths
+local eq = helpers.eq
+
+describe('visual line mode', function()
+ local screen
+
+ it('redraws properly after scrolling with matchparen loaded and scrolloff=1', function()
+ clear{args={'-u', 'NORC'}}
+ screen = Screen.new(30, 7)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true},
+ [2] = {background = Screen.colors.LightGrey},
+ })
+
+ eq(1, meths.get_var('loaded_matchparen'))
+ feed_command('set scrolloff=1')
+ funcs.setline(1, {'a', 'b', 'c', 'd', 'e', '', '{', '}', '{', 'f', 'g', '}'})
+ call('cursor', 5, 1)
+
+ feed('V<c-d><c-d>')
+ screen:expect([[
+ {2:{} |
+ {2:}} |
+ {2:{} |
+ {2:f} |
+ ^g |
+ } |
+ {1:-- VISUAL LINE --} |
+ ]])
+ end)
+end)
diff --git a/test/functional/legacy/wordcount_spec.lua b/test/functional/legacy/wordcount_spec.lua
index 0c8bd2cdcc..826743b0ca 100644
--- a/test/functional/legacy/wordcount_spec.lua
+++ b/test/functional/legacy/wordcount_spec.lua
@@ -4,7 +4,7 @@ local helpers = require('test.functional.helpers')(after_each)
local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, command = helpers.clear, helpers.command
local eq, eval = helpers.eq, helpers.eval
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('wordcount', function()
before_each(clear)
@@ -14,7 +14,7 @@ describe('wordcount', function()
insert([=[
RESULT test:]=])
- wait()
+ poke_eventloop()
command('new')
source([=[
@@ -127,7 +127,7 @@ describe('wordcount', function()
-- -- Start visual mode quickly and select complete buffer.
command('0')
feed('V2jy<cr>')
- wait()
+ poke_eventloop()
command('set stl= ls=1')
command('let log=DoRecordWin([3,99,0])')
command('let log[1]=g:visual_stat')
@@ -144,7 +144,7 @@ describe('wordcount', function()
-- Start visual mode quickly and select complete buffer.
command('0')
feed('v$y<cr>')
- wait()
+ poke_eventloop()
command('set stl= ls=1')
command('let log=DoRecordWin([3,99,0])')
command('let log[1]=g:visual_stat')
@@ -161,7 +161,7 @@ describe('wordcount', function()
-- Start visual mode quickly and select complete buffer.
command('2')
feed('0v$y<cr>')
- wait()
+ poke_eventloop()
command('set stl= ls=1')
command('let log=DoRecordWin([3,99,0])')
command('let log[1]=g:visual_stat')
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 77f8189bb9..7e4de7c39a 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -3,10 +3,14 @@ local helpers = require('test.functional.helpers')(after_each)
local command = helpers.command
local meths = helpers.meths
+local funcs = helpers.funcs
local clear = helpers.clear
local eq = helpers.eq
+local fail = helpers.fail
local exec_lua = helpers.exec_lua
local feed = helpers.feed
+local deepcopy = helpers.deepcopy
+local expect_events = helpers.expect_events
local origlines = {"original line 1",
"original line 2",
@@ -16,32 +20,37 @@ local origlines = {"original line 1",
"original line 6",
" indented line"}
-describe('lua: buffer event callbacks', function()
- before_each(function()
- clear()
- exec_lua([[
- local events = {}
+local function attach_buffer(evname)
+ exec_lua([[
+ local evname = ...
+ local events = {}
- function test_register(bufnr, id, changedtick, utf_sizes)
- local function callback(...)
- table.insert(events, {id, ...})
- if test_unreg == id then
- return true
- end
+ function test_register(bufnr, id, changedtick, utf_sizes)
+ local function callback(...)
+ table.insert(events, {id, ...})
+ if test_unreg == id then
+ return true
end
- local opts = {on_lines=callback, on_detach=callback, utf_sizes=utf_sizes}
- if changedtick then
- opts.on_changedtick = callback
- end
- vim.api.nvim_buf_attach(bufnr, false, opts)
end
-
- function get_events()
- local ret_events = events
- events = {}
- return ret_events
+ local opts = {[evname]=callback, on_detach=callback, utf_sizes=utf_sizes}
+ if changedtick then
+ opts.on_changedtick = callback
end
- ]])
+ vim.api.nvim_buf_attach(bufnr, false, opts)
+ end
+
+ function get_events()
+ local ret_events = events
+ events = {}
+ return ret_events
+ end
+ ]], evname)
+end
+
+describe('lua buffer event callbacks: on_lines', function()
+ before_each(function()
+ clear()
+ attach_buffer('on_lines')
end)
@@ -62,7 +71,7 @@ describe('lua: buffer event callbacks', function()
local function check_events(expected)
local events = exec_lua("return get_events(...)" )
if utf_sizes then
- -- this test case uses ASCII only, so sizes sshould be the same.
+ -- this test case uses ASCII only, so sizes should be the same.
-- Unicode is tested below.
for _, event in ipairs(expected) do
event[9] = event[8]
@@ -216,4 +225,282 @@ describe('lua: buffer event callbacks', function()
eq(1, meths.get_var('listener_cursor_line'))
end)
+ it('does not SEGFAULT when calling win_findbuf in on_detach', function()
+
+ exec_lua[[
+ local buf = vim.api.nvim_create_buf(false, false)
+
+ vim.cmd"split"
+ vim.api.nvim_win_set_buf(0, buf)
+
+ vim.api.nvim_buf_attach(buf, false, {
+ on_detach = function(_, buf)
+ vim.fn.win_findbuf(buf)
+ end
+ })
+ ]]
+
+ command("q!")
+ helpers.assert_alive()
+ end)
+
+ it('#12718 lnume', function()
+ meths.buf_set_lines(0, 0, -1, true, {'1', '2', '3'})
+ exec_lua([[
+ vim.api.nvim_buf_attach(0, false, {
+ on_lines = function(...)
+ vim.api.nvim_set_var('linesev', { ... })
+ end,
+ })
+ ]])
+ feed('1G0')
+ feed('y<C-v>2j')
+ feed('G0')
+ feed('p')
+ -- Is the last arg old_byte_size correct? Doesn't matter for this PR
+ eq(meths.get_var('linesev'), { "lines", 1, 4, 2, 3, 5, 4 })
+
+ feed('2G0')
+ feed('p')
+ eq(meths.get_var('linesev'), { "lines", 1, 5, 1, 4, 4, 8 })
+
+ feed('1G0')
+ feed('P')
+ eq(meths.get_var('linesev'), { "lines", 1, 6, 0, 3, 3, 9 })
+
+ end)
+end)
+
+describe('lua: nvim_buf_attach on_bytes', function()
+ before_each(function()
+ clear()
+ attach_buffer('on_bytes')
+ end)
+
+ -- verifying the sizes with nvim_buf_get_offset is nice (checks we cannot
+ -- assert the wrong thing), but masks errors with unflushed lines (as
+ -- nvim_buf_get_offset forces a flush of the memline). To be safe run the
+ -- test both ways.
+ local function setup_eventcheck(verify, start_txt)
+ meths.buf_set_lines(0, 0, -1, true, start_txt)
+ local shadow = deepcopy(start_txt)
+ local shadowbytes = table.concat(shadow, '\n') .. '\n'
+ -- TODO: while we are brewing the real strong coffe,
+ -- verify should check buf_get_offset after every check_events
+ if verify then
+ meths.buf_get_offset(0, meths.buf_line_count(0))
+ end
+ exec_lua("return test_register(...)", 0, "test1",false, nil)
+ meths.buf_get_changedtick(0)
+
+ local verify_name = "test1"
+ local function check_events(expected)
+ local events = exec_lua("return get_events(...)" )
+ expect_events(expected, events, "byte updates")
+
+ if not verify then
+ return
+ end
+
+ for _, event in ipairs(events) do
+ for _, elem in ipairs(event) do
+ if type(elem) == "number" and elem < 0 then
+ fail(string.format("Received event has negative values"))
+ end
+ end
+
+ if event[1] == verify_name and event[2] == "bytes" then
+ local _, _, _, _, _, _, start_byte, _, _, old_byte, _, _, new_byte = unpack(event)
+ local before = string.sub(shadowbytes, 1, start_byte)
+ -- no text in the tests will contain 0xff bytes (invalid UTF-8)
+ -- so we can use it as marker for unknown bytes
+ local unknown = string.rep('\255', new_byte)
+ local after = string.sub(shadowbytes, start_byte + old_byte + 1)
+ shadowbytes = before .. unknown .. after
+ end
+ end
+
+ local text = meths.buf_get_lines(0, 0, -1, true)
+ local bytes = table.concat(text, '\n') .. '\n'
+
+ eq(string.len(bytes), string.len(shadowbytes), '\non_bytes: total bytecount of buffer is wrong')
+ for i = 1, string.len(shadowbytes) do
+ local shadowbyte = string.sub(shadowbytes, i, i)
+ if shadowbyte ~= '\255' then
+ eq(string.sub(bytes, i, i), shadowbyte, i)
+ end
+ end
+ end
+
+ return check_events
+ end
+
+ -- Yes, we can do both
+ local function do_both(verify)
+ it('single and multiple join', function()
+ local check_events = setup_eventcheck(verify, origlines)
+ feed 'ggJ'
+ check_events {
+ {'test1', 'bytes', 1, 3, 0, 15, 15, 1, 0, 1, 0, 1, 1};
+ }
+
+ feed '3J'
+ check_events {
+ {'test1', 'bytes', 1, 5, 0, 31, 31, 1, 0, 1, 0, 1, 1};
+ {'test1', 'bytes', 1, 5, 0, 47, 47, 1, 0, 1, 0, 1, 1};
+ }
+ end)
+
+ it('opening lines', function()
+ local check_events = setup_eventcheck(verify, origlines)
+ -- meths.buf_set_option(0, 'autoindent', true)
+ feed 'Go'
+ check_events {
+ { "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 1 };
+ }
+ feed '<cr>'
+ check_events {
+ { "test1", "bytes", 1, 5, 7, 0, 114, 0, 0, 0, 1, 0, 1 };
+ }
+ end)
+
+ it('opening lines with autoindent', function()
+ local check_events = setup_eventcheck(verify, origlines)
+ meths.buf_set_option(0, 'autoindent', true)
+ feed 'Go'
+ check_events {
+ { "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 5 };
+ }
+ feed '<cr>'
+ check_events {
+ { "test1", "bytes", 1, 4, 8, 0, 115, 0, 4, 4, 0, 0, 0 };
+ { "test1", "bytes", 1, 5, 7, 4, 118, 0, 0, 0, 1, 4, 5 };
+ }
+ end)
+
+ it('setline(num, line)', function()
+ local check_events = setup_eventcheck(verify, origlines)
+ funcs.setline(2, "babla")
+ check_events {
+ { "test1", "bytes", 1, 3, 1, 0, 16, 0, 15, 15, 0, 5, 5 };
+ }
+
+ funcs.setline(2, {"foo", "bar"})
+ check_events {
+ { "test1", "bytes", 1, 4, 1, 0, 16, 0, 5, 5, 0, 3, 3 };
+ { "test1", "bytes", 1, 5, 2, 0, 20, 0, 15, 15, 0, 3, 3 };
+ }
+
+ local buf_len = meths.buf_line_count(0)
+ funcs.setline(buf_len + 1, "baz")
+ check_events {
+ { "test1", "bytes", 1, 6, 7, 0, 90, 0, 0, 0, 1, 0, 4 };
+ }
+ end)
+
+ it('continuing comments with fo=or', function()
+ local check_events = setup_eventcheck(verify, {'// Comment'})
+ meths.buf_set_option(0, 'formatoptions', 'ro')
+ meths.buf_set_option(0, 'filetype', 'c')
+ feed 'A<CR>'
+ check_events {
+ { "test1", "bytes", 1, 4, 0, 10, 10, 0, 0, 0, 1, 3, 4 };
+ }
+
+ feed '<ESC>'
+ check_events {
+ { "test1", "bytes", 1, 4, 1, 2, 13, 0, 1, 1, 0, 0, 0 };
+ }
+
+ feed 'ggo' -- goto first line to continue testing
+ check_events {
+ { "test1", "bytes", 1, 6, 1, 0, 11, 0, 0, 0, 1, 0, 4 };
+ }
+
+ feed '<CR>'
+ check_events {
+ { "test1", "bytes", 1, 6, 2, 2, 16, 0, 1, 1, 0, 0, 0 };
+ { "test1", "bytes", 1, 7, 1, 3, 14, 0, 0, 0, 1, 3, 4 };
+ }
+ end)
+
+ it('editing empty buffers', function()
+ local check_events = setup_eventcheck(verify, {})
+
+ feed 'ia'
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
+ }
+ end)
+
+ it("changing lines", function()
+ local check_events = setup_eventcheck(verify, origlines)
+
+ feed "cc"
+ check_events {
+ { "test1", "bytes", 1, 4, 0, 0, 0, 0, 15, 15, 0, 0, 0 };
+ }
+
+ feed "<ESC>"
+ check_events {}
+
+ feed "c3j"
+ check_events {
+ { "test1", "bytes", 1, 4, 1, 0, 1, 3, 0, 48, 0, 0, 0 };
+ }
+ end)
+
+ it("visual charwise paste", function()
+ local check_events = setup_eventcheck(verify, {'1234567890'})
+ funcs.setreg('a', '___')
+
+ feed '1G1|vll'
+ check_events {}
+
+ feed '"ap'
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 0, 0, 0, 3, 3, 0, 0, 0 };
+ { "test1", "bytes", 1, 5, 0, 0, 0, 0, 0, 0, 0, 3, 3 };
+ }
+ end)
+
+ it('blockwise paste', function()
+ local check_events = setup_eventcheck(verify, {'1', '2', '3'})
+ feed('1G0')
+ feed('y<C-v>2j')
+ feed('G0')
+ feed('p')
+ check_events {
+ { "test1", "bytes", 1, 3, 2, 1, 5, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 3, 3, 0, 7, 0, 0, 0, 0, 3, 3 };
+ { "test1", "bytes", 1, 3, 4, 0, 10, 0, 0, 0, 0, 3, 3 };
+ }
+
+ feed('2G0')
+ feed('p')
+ check_events {
+ { "test1", "bytes", 1, 4, 1, 1, 3, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 4, 2, 1, 6, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 4, 3, 1, 10, 0, 0, 0, 0, 1, 1 };
+ }
+
+ feed('1G0')
+ feed('P')
+ check_events {
+ { "test1", "bytes", 1, 5, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 5, 1, 0, 3, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 5, 2, 0, 7, 0, 0, 0, 0, 1, 1 };
+ }
+
+ end)
+ end
+
+ describe('(with verify) handles', function()
+ do_both(true)
+ end)
+
+ describe('(without verify) handles', function()
+ do_both(false)
+ end)
end)
+
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index cbc3aee557..f2a1b7dede 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -43,7 +43,7 @@ describe(':lua command', function()
eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
end)
it('throws catchable errors', function()
- eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:1: unexpected symbol near ')']],
+ eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']],
pcall_err(command, 'lua ()'))
eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: TEST]],
exc_exec('lua error("TEST")'))
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index 75966393b1..2ec48777fd 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -477,14 +477,14 @@ describe('v:lua', function()
eq(NIL, eval('v:lua.mymod.noisy("eval")'))
eq("hey eval", meths.get_current_line())
- eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)",
+ eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
pcall_err(eval, 'v:lua.mymod.crashy()'))
end)
it('works in :call', function()
command(":call v:lua.mymod.noisy('command')")
eq("hey command", meths.get_current_line())
- eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)",
+ eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
pcall_err(command, 'call v:lua.mymod.crashy()'))
end)
diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua
index aa3d55b06d..3526b64395 100644
--- a/test/functional/lua/treesitter_spec.lua
+++ b/test/functional/lua/treesitter_spec.lua
@@ -15,17 +15,16 @@ before_each(clear)
describe('treesitter API', function()
-- error tests not requiring a parser library
it('handles missing language', function()
- eq("Error executing lua: .../treesitter.lua: no parser for 'borklang' language",
- pcall_err(exec_lua, "parser = vim.treesitter.create_parser(0, 'borklang')"))
+ eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')"))
-- actual message depends on platform
matches("Error executing lua: Failed to load parser: uv_dlopen: .+",
pcall_err(exec_lua, "parser = vim.treesitter.require_language('borklang', 'borkbork.so')"))
- eq("Error executing lua: .../treesitter.lua: no parser for 'borklang' language",
+ eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')"))
end)
-
end)
describe('treesitter API with C parser', function()
@@ -127,6 +126,58 @@ void ui_refresh(void)
}
}]]
+ it('allows to iterate over nodes children', function()
+ if not check_parser() then return end
+
+ insert(test_text);
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+
+ func_node = parser:parse():root():child(0)
+
+ res = {}
+ for node, field in func_node:iter_children() do
+ table.insert(res, {node:type(), field})
+ end
+ return res
+ ]])
+
+ eq({
+ {"primitive_type", "type"},
+ {"function_declarator", "declarator"},
+ {"compound_statement", "body"}
+ }, res)
+ end)
+
+ it('allows to get a child by field', function()
+ if not check_parser() then return end
+
+ insert(test_text);
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+
+ func_node = parser:parse():root():child(0)
+
+ local res = {}
+ for _, node in ipairs(func_node:field("type")) do
+ table.insert(res, {node:type(), node:range()})
+ end
+ return res
+ ]])
+
+ eq({{ "primitive_type", 0, 0, 0, 4 }}, res)
+
+ local res_fail = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+
+ return #func_node:field("foo") == 0
+ ]])
+
+ assert(res_fail)
+ end)
+
local query = [[
((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (eq? @minfunc "MIN"))
"for" @keyword
@@ -134,6 +185,16 @@ void ui_refresh(void)
(field_expression argument: (identifier) @fieldarg)
]]
+ it("supports runtime queries", function()
+ if not check_parser() then return end
+
+ local ret = exec_lua [[
+ return require"vim.treesitter.query".get_query("c", "highlights").captures[1]
+ ]]
+
+ eq('variable', ret)
+ end)
+
it('support query and iter by capture', function()
if not check_parser() then return end
@@ -198,6 +259,82 @@ void ui_refresh(void)
}, res)
end)
+ it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
+ if not check_parser() then return end
+
+ insert('char* astring = "Hello World!";')
+
+ local res = exec_lua([[
+ cquery = vim.treesitter.parse_query("c", '((_) @quote (vim-match? @quote "^\\"$")) ((_) @quote (lua-match? @quote "^\\"$"))')
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()
+ res = {}
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 0, 1) do
+ -- can't transmit node over RPC. just check the name and range
+ local mrepr = {}
+ for cid,node in pairs(match) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
+ table.insert(res, {pattern, mrepr})
+ end
+ return res
+ ]])
+
+ eq({
+ { 1, { { "quote", '"', 0, 16, 0, 17 } } },
+ { 2, { { "quote", '"', 0, 16, 0, 17 } } },
+ { 1, { { "quote", '"', 0, 29, 0, 30 } } },
+ { 2, { { "quote", '"', 0, 29, 0, 30 } } },
+ }, res)
+ end)
+
+ it('allows to add predicates', function()
+ insert([[
+ int main(void) {
+ return 0;
+ }
+ ]])
+
+ local custom_query = "((identifier) @main (#is-main? @main))"
+
+ local res = exec_lua([[
+ local query = require"vim.treesitter.query"
+
+ local function is_main(match, pattern, bufnr, predicate)
+ local node = match[ predicate[2] ]
+
+ return query.get_node_text(node, bufnr)
+ end
+
+ local parser = vim.treesitter.get_parser(0, "c")
+
+ query.add_predicate("is-main?", is_main)
+
+ local query = query.parse_query("c", ...)
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse():root(), 0, 0, 19) do
+ table.insert(nodes, {node:range()})
+ end
+
+ return nodes
+ ]], custom_query)
+
+ eq({{0, 4, 0, 8}}, res)
+
+ local res_list = exec_lua[[
+ local query = require'vim.treesitter.query'
+
+ local list = query.list_predicates()
+
+ table.sort(list)
+
+ return list
+ ]]
+
+ eq({ 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
+ end)
+
it('supports highlighting', function()
if not check_parser() then return end
@@ -243,10 +380,10 @@ static int nlua_schedule(lua_State *const lstate)
(primitive_type) @type
(sized_type_specifier) @type
-; defaults to very magic syntax, for best compatibility
-((identifier) @Identifier (#match? @Identifier "^l(u)a_"))
-; still support \M etc prefixes
-((identifier) @Constant (#match? @Constant "\M^\[A-Z_]\+$"))
+; Use lua regexes
+((identifier) @Identifier (#contains? @Identifier "lua_"))
+((identifier) @Constant (#lua-match? @Constant "^[A-Z_]+$"))
+((identifier) @Normal (#vim-match? @Constant "^lstate$"))
((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right) (#eq? @WarningMsg.left @WarningMsg.right))
@@ -292,13 +429,14 @@ static int nlua_schedule(lua_State *const lstate)
]]}
exec_lua([[
- local TSHighlighter = vim.treesitter.TSHighlighter
+ local parser = vim.treesitter.get_parser(0, "c")
+ local highlighter = vim.treesitter.highlighter
local query = ...
- test_hl = TSHighlighter.new(query, 0, "c")
+ test_hl = highlighter.new(parser, query)
]], hl_query)
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
{4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
|| {6:lstate} != {6:lstate}) { |
@@ -306,9 +444,9 @@ static int nlua_schedule(lua_State *const lstate)
{4:return} {11:lua_error}(lstate); |
} |
|
- {7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
|
- multiqueue_put(main_loop.events, nlua_schedule_event, |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
@@ -317,10 +455,33 @@ static int nlua_schedule(lua_State *const lstate)
|
]]}
+ feed("5Goc<esc>dd")
+
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
+ || {6:lstate} != {6:lstate}) { |
+ {11:^lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
+ {4:return} {11:lua_error}(lstate); |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ } |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
feed('7Go*/<esc>')
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
{4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
|| {6:lstate} != {6:lstate}) { |
@@ -329,9 +490,9 @@ static int nlua_schedule(lua_State *const lstate)
{8:*^/} |
} |
|
- {7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
|
- multiqueue_put(main_loop.events, nlua_schedule_event, |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
} |
@@ -342,7 +503,7 @@ static int nlua_schedule(lua_State *const lstate)
feed('3Go/*<esc>')
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
{2:/^*} |
{2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
@@ -352,9 +513,9 @@ static int nlua_schedule(lua_State *const lstate)
{2:*/} |
} |
|
- {7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
|
- multiqueue_put(main_loop.events, nlua_schedule_event, |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
{8:}} |
@@ -365,7 +526,7 @@ static int nlua_schedule(lua_State *const lstate)
feed("~")
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queu^E} |
- {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
{2:/*} |
{2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
@@ -375,9 +536,9 @@ static int nlua_schedule(lua_State *const lstate)
{2:*/} |
} |
|
- {7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
|
- multiqueue_put(main_loop.events, nlua_schedule_event, |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
{8:}} |
@@ -388,7 +549,7 @@ static int nlua_schedule(lua_State *const lstate)
feed("re")
screen:expect{grid=[[
{2:/// Schedule Lua callback on main loop's event queu^e} |
- {3:static} {3:int} nlua_schedule({3:lua_State} *{3:const} lstate) |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
{2:/*} |
{2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
@@ -398,9 +559,9 @@ static int nlua_schedule(lua_State *const lstate)
{2:*/} |
} |
|
- {7:LuaRef} cb = nlua_ref(lstate, {5:1}); |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
|
- multiqueue_put(main_loop.events, nlua_schedule_event, |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
{8:}} |
@@ -408,6 +569,72 @@ static int nlua_schedule(lua_State *const lstate)
]]}
end)
+ it("supports highlighting with custom parser", function()
+ if not check_parser() then return end
+
+ local screen = Screen.new(65, 18)
+ screen:attach()
+ screen:set_default_attr_ids({ {bold = true, foreground = Screen.colors.SeaGreen4} })
+
+ insert(test_text)
+
+ screen:expect{ grid= [[
+ int width = INT_MAX, height = INT_MAX; |
+ bool ext_widgets[kUIExtCount]; |
+ for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
+ ext_widgets[i] = true; |
+ } |
+ |
+ bool inclusive = ui_override(); |
+ for (size_t i = 0; i < ui_count; i++) { |
+ UI *ui = uis[i]; |
+ width = MIN(ui->width, width); |
+ height = MIN(ui->height, height); |
+ foo = BAR(ui->bazaar, bazaar); |
+ for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
+ } |
+ } |
+ ^} |
+ |
+ ]] }
+
+ exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+ query = vim.treesitter.parse_query("c", "(declaration) @decl")
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse():root(), 0, 0, 19) do
+ table.insert(nodes, node)
+ end
+
+ parser:set_included_ranges(nodes)
+
+ local hl = vim.treesitter.highlighter.new(parser, "(identifier) @type")
+ ]])
+
+ screen:expect{ grid = [[
+ int {1:width} = {1:INT_MAX}, {1:height} = {1:INT_MAX}; |
+ bool {1:ext_widgets}[{1:kUIExtCount}]; |
+ for (UIExtension {1:i} = 0; (int)i < kUIExtCount; i++) { |
+ ext_widgets[i] = true; |
+ } |
+ |
+ bool {1:inclusive} = {1:ui_override}(); |
+ for (size_t {1:i} = 0; i < ui_count; i++) { |
+ UI *{1:ui} = {1:uis}[{1:i}]; |
+ width = MIN(ui->width, width); |
+ height = MIN(ui->height, height); |
+ foo = BAR(ui->bazaar, bazaar); |
+ for (UIExtension {1:j} = 0; (int)j < kUIExtCount; j++) { |
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
+ } |
+ } |
+ ^} |
+ |
+ ]] }
+ end)
+
it('inspects language', function()
if not check_parser() then return end
@@ -453,23 +680,29 @@ static int nlua_schedule(lua_State *const lstate)
insert(test_text)
- local res = exec_lua([[
+ local res = exec_lua [[
parser = vim.treesitter.get_parser(0, "c")
return { parser:parse():root():range() }
- ]])
+ ]]
eq({0, 0, 19, 0}, res)
-- The following sets the included ranges for the current parser
-- As stated here, this only includes the function (thus the whole buffer, without the last line)
- local res2 = exec_lua([[
+ local res2 = exec_lua [[
local root = parser:parse():root()
parser:set_included_ranges({root:child(0)})
parser.valid = false
return { parser:parse():root():range() }
- ]])
+ ]]
eq({0, 0, 18, 1}, res2)
+
+ local range = exec_lua [[
+ return parser:included_ranges()
+ ]]
+
+ eq(range, { { 0, 0, 18, 1 } })
end)
it("allows to set complex ranges", function()
if not check_parser() then return end
@@ -477,7 +710,7 @@ static int nlua_schedule(lua_State *const lstate)
insert(test_text)
- local res = exec_lua([[
+ local res = exec_lua [[
parser = vim.treesitter.get_parser(0, "c")
query = vim.treesitter.parse_query("c", "(declaration) @decl")
@@ -495,7 +728,7 @@ static int nlua_schedule(lua_State *const lstate)
table.insert(res, { root:named_child(i):range() })
end
return res
- ]])
+ ]]
eq({
{ 2, 2, 2, 40 },
@@ -509,4 +742,35 @@ static int nlua_schedule(lua_State *const lstate)
{ 10, 5, 10, 20 },
{ 14, 9, 14, 27 } }, res)
end)
+
+ it("allows to create string parsers", function()
+ local ret = exec_lua [[
+ local parser = vim.treesitter.get_string_parser("int foo = 42;", "c")
+ return { parser:parse():root():range() }
+ ]]
+
+ eq({ 0, 0, 0, 13 }, ret)
+ end)
+
+ it("allows to run queries with string parsers", function()
+ local txt = [[
+ int foo = 42;
+ int bar = 13;
+ ]]
+
+ local ret = exec_lua([[
+ local str = ...
+ local parser = vim.treesitter.get_string_parser(str, "c")
+
+ local nodes = {}
+ local query = vim.treesitter.parse_query("c", '((identifier) @id (eq? @id "foo"))')
+
+ for _, node in query:iter_captures(parser:parse():root(), str, 0, 2) do
+ table.insert(nodes, { node:range() })
+ end
+
+ return nodes]], txt)
+
+ eq({ {0, 10, 0, 13} }, ret)
+ end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 9b2697b3c2..1cbf6b21e3 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -4,13 +4,14 @@ local Screen = require('test.functional.ui.screen')
local funcs = helpers.funcs
local meths = helpers.meths
+local dedent = helpers.dedent
local command = helpers.command
local clear = helpers.clear
local eq = helpers.eq
local ok = helpers.ok
local eval = helpers.eval
local feed = helpers.feed
-local pcall_err = helpers.pcall_err
+local pcall_err_withfile = helpers.pcall_err_withfile
local exec_lua = helpers.exec_lua
local matches = helpers.matches
local source = helpers.source
@@ -128,8 +129,8 @@ describe('lua stdlib', function()
eq(false, funcs.luaeval('vim.startswith("123", "2")'))
eq(false, funcs.luaeval('vim.startswith("123", "1234")'))
- eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith("123", nil)')))
- eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith(nil, "123")')))
+ eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.startswith("123", nil)')))
+ eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.startswith(nil, "123")')))
end)
it('vim.endswith', function()
@@ -142,8 +143,8 @@ describe('lua stdlib', function()
eq(false, funcs.luaeval('vim.endswith("123", "2")'))
eq(false, funcs.luaeval('vim.endswith("123", "1234")'))
- eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith("123", nil)')))
- eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith(nil, "123")')))
+ eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.endswith("123", nil)')))
+ eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.endswith(nil, "123")')))
end)
it("vim.str_utfindex/str_byteindex", function()
@@ -182,10 +183,10 @@ describe('lua stdlib', function()
eq({"yy","xx"}, exec_lua("return test_table"))
-- Validates args.
- eq('Error executing lua: vim.schedule: expected function',
- pcall_err(exec_lua, "vim.schedule('stringly')"))
- eq('Error executing lua: vim.schedule: expected function',
- pcall_err(exec_lua, "vim.schedule()"))
+ eq('.../helpers.lua:0: Error executing lua: vim.schedule: expected function',
+ pcall_err_withfile(exec_lua, "vim.schedule('stringly')"))
+ eq('.../helpers.lua:0: Error executing lua: vim.schedule: expected function',
+ pcall_err_withfile(exec_lua, "vim.schedule()"))
exec_lua([[
vim.schedule(function()
@@ -257,17 +258,29 @@ describe('lua stdlib', function()
}
for _, t in ipairs(loops) do
- matches(".*Infinite loop detected", pcall_err(split, t[1], t[2]))
+ matches(".*Infinite loop detected", pcall_err_withfile(split, t[1], t[2]))
end
-- Validates args.
eq(true, pcall(split, 'string', 'string'))
- eq('Error executing lua: .../shared.lua: s: expected string, got number',
- pcall_err(split, 1, 'string'))
- eq('Error executing lua: .../shared.lua: sep: expected string, got number',
- pcall_err(split, 'string', 1))
- eq('Error executing lua: .../shared.lua: plain: expected boolean, got number',
- pcall_err(split, 'string', 'string', 1))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number
+ stack traceback:
+ shared.lua:0: in function 'gsplit'
+ shared.lua:0: in function <shared.lua:0>]]),
+ pcall_err_withfile(split, 1, 'string'))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: shared.lua:0: sep: expected string, got number
+ stack traceback:
+ shared.lua:0: in function 'gsplit'
+ shared.lua:0: in function <shared.lua:0>]]),
+ pcall_err_withfile(split, 'string', 1))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: shared.lua:0: plain: expected boolean, got number
+ stack traceback:
+ shared.lua:0: in function 'gsplit'
+ shared.lua:0: in function <shared.lua:0>]]),
+ pcall_err_withfile(split, 'string', 'string', 1))
end)
it('vim.trim', function()
@@ -287,8 +300,11 @@ describe('lua stdlib', function()
end
-- Validates args.
- eq('Error executing lua: .../shared.lua: s: expected string, got number',
- pcall_err(trim, 2))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number
+ stack traceback:
+ shared.lua:0: in function <shared.lua:0>]]),
+ pcall_err_withfile(trim, 2))
end)
it('vim.inspect', function()
@@ -353,8 +369,8 @@ describe('lua stdlib', function()
return t1.f() ~= t2.f()
]]))
- eq('Error executing lua: .../shared.lua: Cannot deepcopy object of type thread',
- pcall_err(exec_lua, [[
+ eq('.../helpers.lua:0: Error executing lua: shared.lua:0: Cannot deepcopy object of type thread',
+ pcall_err_withfile(exec_lua, [[
local thread = coroutine.create(function () return 0 end)
local t = {thr = thread}
vim.deepcopy(t)
@@ -366,8 +382,11 @@ describe('lua stdlib', function()
eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]]))
-- Validates args.
- eq('Error executing lua: .../shared.lua: s: expected string, got number',
- pcall_err(exec_lua, [[return vim.pesc(2)]]))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number
+ stack traceback:
+ shared.lua:0: in function <shared.lua:0>]]),
+ pcall_err_withfile(exec_lua, [[return vim.pesc(2)]]))
end)
it('vim.tbl_keys', function()
@@ -491,20 +510,20 @@ describe('lua stdlib', function()
return c.x.a == 1 and c.x.b == 2 and c.x.c == nil and count == 1
]]))
- eq('Error executing lua: .../shared.lua: invalid "behavior": nil',
- pcall_err(exec_lua, [[
+ eq('.../helpers.lua:0: Error executing lua: shared.lua:0: invalid "behavior": nil',
+ pcall_err_withfile(exec_lua, [[
return vim.tbl_extend()
]])
)
- eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)',
- pcall_err(exec_lua, [[
+ eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 1, expected at least 3)',
+ pcall_err_withfile(exec_lua, [[
return vim.tbl_extend("keep")
]])
)
- eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)',
- pcall_err(exec_lua, [[
+ eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 2, expected at least 3)',
+ pcall_err_withfile(exec_lua, [[
return vim.tbl_extend("keep", {})
]])
)
@@ -579,20 +598,20 @@ describe('lua stdlib', function()
return vim.tbl_islist(c) and count == 0
]]))
- eq('Error executing lua: .../shared.lua: invalid "behavior": nil',
- pcall_err(exec_lua, [[
+ eq('.../helpers.lua:0: Error executing lua: shared.lua:0: invalid "behavior": nil',
+ pcall_err_withfile(exec_lua, [[
return vim.tbl_deep_extend()
]])
)
- eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)',
- pcall_err(exec_lua, [[
+ eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 1, expected at least 3)',
+ pcall_err_withfile(exec_lua, [[
return vim.tbl_deep_extend("keep")
]])
)
- eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)',
- pcall_err(exec_lua, [[
+ eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 2, expected at least 3)',
+ pcall_err_withfile(exec_lua, [[
return vim.tbl_deep_extend("keep", {})
]])
)
@@ -624,8 +643,11 @@ describe('lua stdlib', function()
it('vim.list_extend', function()
eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]])
- eq('Error executing lua: .../shared.lua: src: expected table, got nil',
- pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]]))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: shared.lua:0: src: expected table, got nil
+ stack traceback:
+ shared.lua:0: in function <shared.lua:0>]]),
+ pcall_err_withfile(exec_lua, [[ return vim.list_extend({1}, nil) ]]))
eq({1,2}, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]])
eq(true, exec_lua [[ local a = {1} return vim.list_extend(a, {2;a=1}) == a ]])
eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1) ]])
@@ -648,8 +670,8 @@ describe('lua stdlib', function()
assert(vim.deep_equal(a, { A = 1; [1] = 'A'; }))
vim.tbl_add_reverse_lookup(a)
]]
- matches('Error executing lua: .../shared.lua: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"',
- pcall_err(exec_lua, code))
+ matches('.../helpers.lua:0: Error executing lua: shared.lua:0: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"',
+ pcall_err_withfile(exec_lua, code))
end)
it('vim.call, vim.fn', function()
@@ -820,34 +842,77 @@ describe('lua stdlib', function()
exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}")
exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}")
- eq("Error executing lua: .../shared.lua: 1: expected table, got number",
- pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
- eq("Error executing lua: .../shared.lua: invalid type name: x",
- pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
- eq("Error executing lua: .../shared.lua: invalid type name: 1",
- pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
- eq("Error executing lua: .../shared.lua: invalid type name: nil",
- pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{ 1, 'x' }"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: x
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: 1
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: nil
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1 }}"))
-- Validated parameters are required by default.
- eq("Error executing lua: .../shared.lua: arg1: expected string, got nil",
- pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
-- Explicitly required.
- eq("Error executing lua: .../shared.lua: arg1: expected string, got nil",
- pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
-
- eq("Error executing lua: .../shared.lua: arg1: expected table, got number",
- pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}"))
- eq("Error executing lua: .../shared.lua: arg2: expected string, got number",
- pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
- eq("Error executing lua: .../shared.lua: arg2: expected string, got nil",
- pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
- eq("Error executing lua: .../shared.lua: arg2: expected string, got nil",
- pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
- eq("Error executing lua: .../shared.lua: arg1: expected even number, got 3",
- pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
- eq("Error executing lua: .../shared.lua: arg1: expected ?, got 3",
- pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
+
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{arg1={1, 't'}}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
+
+ -- Pass an additional message back.
+ eq(dedent([[
+ .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG
+ stack traceback:
+ [string "<nvim>"]:0: in main chunk]]),
+ pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}"))
end)
it('vim.is_callable', function()
@@ -992,10 +1057,10 @@ describe('lua stdlib', function()
]]
eq('', funcs.luaeval "vim.bo.filetype")
eq(true, funcs.luaeval "vim.bo[BUF].modifiable")
- matches("^Error executing lua: .*: Invalid option name: 'nosuchopt'$",
- pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
- matches("^Error executing lua: .*: Expected lua string$",
- pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
+ matches("^.../helpers.lua:0: Error executing lua: .*: Invalid option name: 'nosuchopt'$",
+ pcall_err_withfile(exec_lua, 'return vim.bo.nosuchopt'))
+ matches("^.../helpers.lua:0: Error executing lua: .*: Expected lua string$",
+ pcall_err_withfile(exec_lua, 'return vim.bo[0][0].autoread'))
end)
it('vim.wo', function()
@@ -1011,10 +1076,10 @@ describe('lua stdlib', function()
eq(0, funcs.luaeval "vim.wo.cole")
eq(0, funcs.luaeval "vim.wo[0].cole")
eq(0, funcs.luaeval "vim.wo[1001].cole")
- matches("^Error executing lua: .*: Invalid option name: 'notanopt'$",
- pcall_err(exec_lua, 'return vim.wo.notanopt'))
- matches("^Error executing lua: .*: Expected lua string$",
- pcall_err(exec_lua, 'return vim.wo[0][0].list'))
+ matches("^.../helpers.lua:0: Error executing lua: .*: Invalid option name: 'notanopt'$",
+ pcall_err_withfile(exec_lua, 'return vim.wo.notanopt'))
+ matches("^.../helpers.lua:0: Error executing lua: .*: Expected lua string$",
+ pcall_err_withfile(exec_lua, 'return vim.wo[0][0].list'))
eq(2, funcs.luaeval "vim.wo[1000].cole")
exec_lua [[
vim.wo[1000].cole = 0
@@ -1068,6 +1133,104 @@ describe('lua stdlib', function()
eq({5,15}, exec_lua[[ return vim.region(0,{1,5},{1,14},'v',true)[1] ]])
end)
+ describe('vim.execute_on_keystroke', function()
+ it('should keep track of keystrokes', function()
+ helpers.insert([[hello world ]])
+
+ exec_lua [[
+ KeysPressed = {}
+
+ vim.register_keystroke_callback(function(buf)
+ if buf:byte() == 27 then
+ buf = "<ESC>"
+ end
+
+ table.insert(KeysPressed, buf)
+ end)
+ ]]
+
+ helpers.insert([[next 🤦 lines å ]])
+
+ -- It has escape in the keys pressed
+ eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(KeysPressed, '')]])
+ end)
+
+ it('should allow removing trackers.', function()
+ helpers.insert([[hello world]])
+
+ exec_lua [[
+ KeysPressed = {}
+
+ return vim.register_keystroke_callback(function(buf)
+ if buf:byte() == 27 then
+ buf = "<ESC>"
+ end
+
+ table.insert(KeysPressed, buf)
+ end, vim.api.nvim_create_namespace("logger"))
+ ]]
+
+ helpers.insert([[next lines]])
+
+ exec_lua("vim.register_keystroke_callback(nil, vim.api.nvim_create_namespace('logger'))")
+
+ helpers.insert([[more lines]])
+
+ -- It has escape in the keys pressed
+ eq('inext lines<ESC>', exec_lua [[return table.concat(KeysPressed, '')]])
+ end)
+
+ it('should not call functions that error again.', function()
+ helpers.insert([[hello world]])
+
+ exec_lua [[
+ KeysPressed = {}
+
+ return vim.register_keystroke_callback(function(buf)
+ if buf:byte() == 27 then
+ buf = "<ESC>"
+ end
+
+ table.insert(KeysPressed, buf)
+
+ if buf == 'l' then
+ error("Dumb Error")
+ end
+ end)
+ ]]
+
+ helpers.insert([[next lines]])
+ helpers.insert([[more lines]])
+
+ -- Only the first letter gets added. After that we remove the callback
+ eq('inext l', exec_lua [[ return table.concat(KeysPressed, '') ]])
+ end)
+
+ it('should process mapped keys, not unmapped keys', function()
+ exec_lua [[
+ KeysPressed = {}
+
+ vim.cmd("inoremap hello world")
+
+ vim.register_keystroke_callback(function(buf)
+ if buf:byte() == 27 then
+ buf = "<ESC>"
+ end
+
+ table.insert(KeysPressed, buf)
+ end)
+ ]]
+
+ helpers.insert("hello")
+
+ local next_status = exec_lua [[
+ return table.concat(KeysPressed, '')
+ ]]
+
+ eq("iworld<ESC>", next_status)
+ end)
+ end)
+
describe('vim.wait', function()
before_each(function()
exec_lua[[
@@ -1116,6 +1279,23 @@ describe('lua stdlib', function()
]])
end)
+ it('should not process non-fast events when commanded', function()
+ eq({wait_result = false}, exec_lua[[
+ start_time = get_time()
+
+ vim.g.timer_result = false
+ timer = vim.loop.new_timer()
+ timer:start(100, 0, vim.schedule_wrap(function()
+ vim.g.timer_result = true
+ end))
+
+ wait_result = vim.wait(300, function() return vim.g.timer_result end, nil, true)
+
+ return {
+ wait_result = wait_result,
+ }
+ ]])
+ end)
it('should work with vim.defer_fn', function()
eq({time = true, wait_result = true}, exec_lua[[
start_time = get_time()
@@ -1130,22 +1310,38 @@ describe('lua stdlib', function()
]])
end)
- it('should require functions to be passed', function()
+ it('should not crash when callback errors', function()
local pcall_result = exec_lua [[
- return {pcall(function() vim.wait(1000, 13) end)}
+ return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)}
]]
eq(pcall_result[1], false)
- matches('condition must be a function', pcall_result[2])
+ matches('As Expected', pcall_result[2])
end)
- it('should not crash when callback errors', function()
+ it('if callback is passed, it must be a function', function()
local pcall_result = exec_lua [[
- return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)}
+ return {pcall(function() vim.wait(1000, 13) end)}
]]
eq(pcall_result[1], false)
- matches('As Expected', pcall_result[2])
+ matches('if passed, condition must be a function', pcall_result[2])
+ end)
+
+ it('should allow waiting with no callback, explicit', function()
+ eq(true, exec_lua [[
+ local start_time = vim.loop.hrtime()
+ vim.wait(50, nil)
+ return vim.loop.hrtime() - start_time > 25000
+ ]])
+ end)
+
+ it('should allow waiting with no callback, implicit', function()
+ eq(true, exec_lua [[
+ local start_time = vim.loop.hrtime()
+ vim.wait(50)
+ return vim.loop.hrtime() - start_time > 25000
+ ]])
end)
it('should call callbacks exactly once if they return true immediately', function()
@@ -1232,4 +1428,29 @@ describe('lua stdlib', function()
eq(false, pcall_result)
end)
end)
+
+ describe('vim.api.nvim_buf_call', function()
+ it('can access buf options', function()
+ local buf1 = meths.get_current_buf()
+ local buf2 = exec_lua [[
+ buf2 = vim.api.nvim_create_buf(false, true)
+ return buf2
+ ]]
+
+ eq(false, meths.buf_get_option(buf1, 'autoindent'))
+ eq(false, meths.buf_get_option(buf2, 'autoindent'))
+
+ local val = exec_lua [[
+ return vim.api.nvim_buf_call(buf2, function()
+ vim.cmd "set autoindent"
+ return vim.api.nvim_get_current_buf()
+ end)
+ ]]
+
+ eq(false, meths.buf_get_option(buf1, 'autoindent'))
+ eq(true, meths.buf_get_option(buf2, 'autoindent'))
+ eq(buf1, meths.get_current_buf())
+ eq(buf2, val)
+ end)
+ end)
end)
diff --git a/test/functional/normal/meta_key_spec.lua b/test/functional/normal/meta_key_spec.lua
new file mode 100644
index 0000000000..9f9fad67d2
--- /dev/null
+++ b/test/functional/normal/meta_key_spec.lua
@@ -0,0 +1,22 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local command = helpers.command
+local expect = helpers.expect
+
+describe('meta-keys-in-normal-mode', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('ALT/META', function()
+ -- Unmapped ALT-chords behave as Esc+c
+ insert('hello')
+ feed('0<A-x><M-x>')
+ expect('llo')
+ -- Mapped ALT-chord behaves as mapped.
+ command('nnoremap <M-l> Ameta-l<Esc>')
+ command('nnoremap <A-j> Aalt-j<Esc>')
+ feed('<A-j><M-l>')
+ expect('lloalt-jmeta-l')
+ end)
+end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index 11ce26410d..92d077ed14 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -290,9 +290,6 @@ describe('XDG-based defaults', function()
end)
end)
- -- TODO(jkeyes): tests below fail on win32 because of path separator.
- if helpers.pending_win32(pending) then return end
-
local function vimruntime_and_libdir()
local vimruntime = eval('$VIMRUNTIME')
-- libdir is hard to calculate reliably across various ci platforms
@@ -301,71 +298,78 @@ describe('XDG-based defaults', function()
return vimruntime, libdir
end
+ local env_sep = iswin() and ';' or ':'
+ local data_dir = iswin() and 'nvim-data' or 'nvim'
+ local root_path = iswin() and 'C:' or ''
+
describe('with too long XDG variables', function()
before_each(function()
clear({env={
- XDG_CONFIG_HOME=('/x'):rep(4096),
- XDG_CONFIG_DIRS=(('/a'):rep(2048)
- .. ':' .. ('/b'):rep(2048)
- .. (':/c'):rep(512)),
- XDG_DATA_HOME=('/X'):rep(4096),
- XDG_DATA_DIRS=(('/A'):rep(2048)
- .. ':' .. ('/B'):rep(2048)
- .. (':/C'):rep(512)),
+ XDG_CONFIG_HOME=(root_path .. ('/x'):rep(4096)),
+ XDG_CONFIG_DIRS=(root_path .. ('/a'):rep(2048)
+ .. env_sep.. root_path .. ('/b'):rep(2048)
+ .. (env_sep .. root_path .. '/c'):rep(512)),
+ XDG_DATA_HOME=(root_path .. ('/X'):rep(4096)),
+ XDG_DATA_DIRS=(root_path .. ('/A'):rep(2048)
+ .. env_sep .. root_path .. ('/B'):rep(2048)
+ .. (env_sep .. root_path .. '/C'):rep(512)),
}})
end)
it('are correctly set', function()
local vimruntime, libdir = vimruntime_and_libdir()
- eq((('/x'):rep(4096) .. '/nvim'
- .. ',' .. ('/a'):rep(2048) .. '/nvim'
- .. ',' .. ('/b'):rep(2048) .. '/nvim'
- .. (',' .. '/c/nvim'):rep(512)
- .. ',' .. ('/X'):rep(4096) .. '/nvim/site'
- .. ',' .. ('/A'):rep(2048) .. '/nvim/site'
- .. ',' .. ('/B'):rep(2048) .. '/nvim/site'
- .. (',' .. '/C/nvim/site'):rep(512)
+ eq(((root_path .. ('/x'):rep(4096) .. '/nvim'
+ .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim'
+ .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim'
+ .. (',' .. root_path .. '/c/nvim'):rep(512)
+ .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site'
+ .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site'
+ .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site'
+ .. (',' .. root_path .. '/C/nvim/site'):rep(512)
.. ',' .. vimruntime
.. ',' .. libdir
- .. (',' .. '/C/nvim/site/after'):rep(512)
- .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
- .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
- .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after'
- .. (',' .. '/c/nvim/after'):rep(512)
- .. ',' .. ('/b'):rep(2048) .. '/nvim/after'
- .. ',' .. ('/a'):rep(2048) .. '/nvim/after'
- .. ',' .. ('/x'):rep(4096) .. '/nvim/after'
- ), meths.get_option('runtimepath'))
+ .. (',' .. root_path .. '/C/nvim/site/after'):rep(512)
+ .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site/after'
+ .. (',' .. root_path .. '/c/nvim/after'):rep(512)
+ .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim/after'
+ .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
+ .. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
+ ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
meths.command('set runtimepath&')
meths.command('set backupdir&')
meths.command('set directory&')
meths.command('set undodir&')
meths.command('set viewdir&')
- eq((('/x'):rep(4096) .. '/nvim'
- .. ',' .. ('/a'):rep(2048) .. '/nvim'
- .. ',' .. ('/b'):rep(2048) .. '/nvim'
- .. (',' .. '/c/nvim'):rep(512)
- .. ',' .. ('/X'):rep(4096) .. '/nvim/site'
- .. ',' .. ('/A'):rep(2048) .. '/nvim/site'
- .. ',' .. ('/B'):rep(2048) .. '/nvim/site'
- .. (',' .. '/C/nvim/site'):rep(512)
+ eq(((root_path .. ('/x'):rep(4096) .. '/nvim'
+ .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim'
+ .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim'
+ .. (',' .. root_path .. '/c/nvim'):rep(512)
+ .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site'
+ .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site'
+ .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site'
+ .. (',' .. root_path .. '/C/nvim/site'):rep(512)
.. ',' .. vimruntime
.. ',' .. libdir
- .. (',' .. '/C/nvim/site/after'):rep(512)
- .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
- .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
- .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after'
- .. (',' .. '/c/nvim/after'):rep(512)
- .. ',' .. ('/b'):rep(2048) .. '/nvim/after'
- .. ',' .. ('/a'):rep(2048) .. '/nvim/after'
- .. ',' .. ('/x'):rep(4096) .. '/nvim/after'
- ), meths.get_option('runtimepath'))
- eq('.,' .. ('/X'):rep(4096) .. '/nvim/backup',
- meths.get_option('backupdir'))
- eq(('/X'):rep(4096) .. '/nvim/swap//', meths.get_option('directory'))
- eq(('/X'):rep(4096) .. '/nvim/undo', meths.get_option('undodir'))
- eq(('/X'):rep(4096) .. '/nvim/view', meths.get_option('viewdir'))
+ .. (',' .. root_path .. '/C/nvim/site/after'):rep(512)
+ .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site/after'
+ .. (',' .. root_path .. '/c/nvim/after'):rep(512)
+ .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim/after'
+ .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
+ .. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
+ ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup',
+ (meths.get_option('backupdir'):gsub('\\', '/')))
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/swap//',
+ (meths.get_option('directory')):gsub('\\', '/'))
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo',
+ (meths.get_option('undodir')):gsub('\\', '/'))
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view',
+ (meths.get_option('viewdir')):gsub('\\', '/'))
end)
end)
@@ -381,53 +385,61 @@ describe('XDG-based defaults', function()
it('are not expanded', function()
local vimruntime, libdir = vimruntime_and_libdir()
- eq(('$XDG_DATA_HOME/nvim'
+ eq((('$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
- .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site'
.. ',$XDG_CONFIG_DIRS/nvim/site'
.. ',' .. vimruntime
.. ',' .. libdir
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
- .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
- ), meths.get_option('runtimepath'))
+ ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
meths.command('set runtimepath&')
meths.command('set backupdir&')
meths.command('set directory&')
meths.command('set undodir&')
meths.command('set viewdir&')
- eq(('$XDG_DATA_HOME/nvim'
+ eq((('$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
- .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site'
.. ',$XDG_CONFIG_DIRS/nvim/site'
.. ',' .. vimruntime
.. ',' .. libdir
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
- .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
- ), meths.get_option('runtimepath'))
- eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir'))
- eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory'))
- eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir'))
- eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir'))
+ ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'),
+ meths.get_option('backupdir'):gsub('\\', '/'))
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
+ meths.get_option('directory'):gsub('\\', '/'))
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'),
+ meths.get_option('undodir'):gsub('\\', '/'))
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'),
+ meths.get_option('viewdir'):gsub('\\', '/'))
meths.command('set all&')
eq(('$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
- .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site'
.. ',$XDG_CONFIG_DIRS/nvim/site'
.. ',' .. vimruntime
.. ',' .. libdir
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
- .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
- ), meths.get_option('runtimepath'))
- eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir'))
- eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory'))
- eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir'))
- eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir'))
+ ):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'),
+ meths.get_option('backupdir'):gsub('\\', '/'))
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
+ meths.get_option('directory'):gsub('\\', '/'))
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'),
+ meths.get_option('undodir'):gsub('\\', '/'))
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'),
+ meths.get_option('viewdir'):gsub('\\', '/'))
end)
end)
@@ -435,53 +447,58 @@ describe('XDG-based defaults', function()
before_each(function()
clear({env={
XDG_CONFIG_HOME=', , ,',
- XDG_CONFIG_DIRS=',-,-,:-,-,-',
+ XDG_CONFIG_DIRS=',-,-,' .. env_sep .. '-,-,-',
XDG_DATA_HOME=',=,=,',
- XDG_DATA_DIRS=',≡,≡,:≡,≡,≡',
+ XDG_DATA_DIRS=',≡,≡,' .. env_sep .. '≡,≡,≡',
}})
end)
it('are escaped properly', function()
local vimruntime, libdir = vimruntime_and_libdir()
- eq(('\\, \\, \\,/nvim'
- .. ',\\,-\\,-\\,/nvim'
- .. ',-\\,-\\,-/nvim'
- .. ',\\,=\\,=\\,/nvim/site'
- .. ',\\,≡\\,≡\\,/nvim/site'
- .. ',≡\\,≡\\,≡/nvim/site'
+ local path_sep = iswin() and '\\' or '/'
+ eq(('\\, \\, \\,' .. path_sep .. 'nvim'
+ .. ',\\,-\\,-\\,' .. path_sep .. 'nvim'
+ .. ',-\\,-\\,-' .. path_sep .. 'nvim'
+ .. ',\\,=\\,=\\,' .. path_sep .. data_dir .. path_sep .. 'site'
+ .. ',\\,≡\\,≡\\,' .. path_sep .. 'nvim' .. path_sep .. 'site'
+ .. ',≡\\,≡\\,≡' .. path_sep .. 'nvim' .. path_sep .. 'site'
.. ',' .. vimruntime
.. ',' .. libdir
- .. ',≡\\,≡\\,≡/nvim/site/after'
- .. ',\\,≡\\,≡\\,/nvim/site/after'
- .. ',\\,=\\,=\\,/nvim/site/after'
- .. ',-\\,-\\,-/nvim/after'
- .. ',\\,-\\,-\\,/nvim/after'
- .. ',\\, \\, \\,/nvim/after'
+ .. ',≡\\,≡\\,≡' .. path_sep .. 'nvim' .. path_sep .. 'site' .. path_sep .. 'after'
+ .. ',\\,≡\\,≡\\,' .. path_sep .. 'nvim' .. path_sep .. 'site' .. path_sep .. 'after'
+ .. ',\\,=\\,=\\,' .. path_sep.. data_dir .. path_sep .. 'site' .. path_sep .. 'after'
+ .. ',-\\,-\\,-' .. path_sep .. 'nvim' .. path_sep .. 'after'
+ .. ',\\,-\\,-\\,' .. path_sep .. 'nvim' .. path_sep .. 'after'
+ .. ',\\, \\, \\,' .. path_sep .. 'nvim' .. path_sep .. 'after'
), meths.get_option('runtimepath'))
meths.command('set runtimepath&')
meths.command('set backupdir&')
meths.command('set directory&')
meths.command('set undodir&')
meths.command('set viewdir&')
- eq(('\\, \\, \\,/nvim'
- .. ',\\,-\\,-\\,/nvim'
- .. ',-\\,-\\,-/nvim'
- .. ',\\,=\\,=\\,/nvim/site'
- .. ',\\,≡\\,≡\\,/nvim/site'
- .. ',≡\\,≡\\,≡/nvim/site'
+ eq(('\\, \\, \\,' .. path_sep .. 'nvim'
+ .. ',\\,-\\,-\\,' .. path_sep ..'nvim'
+ .. ',-\\,-\\,-' .. path_sep ..'nvim'
+ .. ',\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'site'
+ .. ',\\,≡\\,≡\\,' .. path_sep ..'nvim' .. path_sep ..'site'
+ .. ',≡\\,≡\\,≡' .. path_sep ..'nvim' .. path_sep ..'site'
.. ',' .. vimruntime
.. ',' .. libdir
- .. ',≡\\,≡\\,≡/nvim/site/after'
- .. ',\\,≡\\,≡\\,/nvim/site/after'
- .. ',\\,=\\,=\\,/nvim/site/after'
- .. ',-\\,-\\,-/nvim/after'
- .. ',\\,-\\,-\\,/nvim/after'
- .. ',\\, \\, \\,/nvim/after'
+ .. ',≡\\,≡\\,≡' .. path_sep ..'nvim' .. path_sep ..'site' .. path_sep ..'after'
+ .. ',\\,≡\\,≡\\,' .. path_sep ..'nvim' .. path_sep ..'site' .. path_sep ..'after'
+ .. ',\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'site' .. path_sep ..'after'
+ .. ',-\\,-\\,-' .. path_sep ..'nvim' .. path_sep ..'after'
+ .. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after'
+ .. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after'
), meths.get_option('runtimepath'))
- eq('.,\\,=\\,=\\,/nvim/backup', meths.get_option('backupdir'))
- eq('\\,=\\,=\\,/nvim/swap//', meths.get_option('directory'))
- eq('\\,=\\,=\\,/nvim/undo', meths.get_option('undodir'))
- eq('\\,=\\,=\\,/nvim/view', meths.get_option('viewdir'))
+ eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup',
+ meths.get_option('backupdir'))
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
+ meths.get_option('directory'))
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo',
+ meths.get_option('undodir'))
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view',
+ meths.get_option('viewdir'))
end)
end)
end)
@@ -491,6 +508,7 @@ describe('stdpath()', function()
-- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions
-- due to XDG_CONFIG_HOME and XDG_DATA_HOME being the same.
local datadir = iswin() and 'nvim-data' or 'nvim'
+ local env_sep = iswin() and ';' or ':'
it('acceptance', function()
clear() -- Do not explicitly set any env vars.
@@ -634,13 +652,13 @@ describe('stdpath()', function()
local function set_paths_via_system(var_name, paths)
local env = base_env()
- env[var_name] = table.concat(paths, ':')
+ env[var_name] = table.concat(paths, env_sep)
clear({env=env})
end
local function set_paths_at_runtime(var_name, paths)
clear({env=base_env()})
- meths.set_var('env_val', table.concat(paths, ':'))
+ meths.set_var('env_val', table.concat(paths, env_sep))
command(('let $%s=g:env_val'):format(var_name))
end
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 1002011999..73f3fe5d0c 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -270,6 +270,76 @@ describe('LSP', function()
test_name = "basic_check_capabilities";
on_init = function(client)
client.stop()
+ local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
+ eq(full_kind, client.resolved_capabilities().text_document_did_change)
+ end;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end;
+ on_callback = function(...)
+ eq(table.remove(expected_callbacks), {...}, "expected callback")
+ end;
+ }
+ end)
+
+ it('client.supports_methods() should validate capabilities', function()
+ local expected_callbacks = {
+ {NIL, "shutdown", {}, 1};
+ }
+ test_rpc_server {
+ test_name = "capabilities_for_client_supports_method";
+ on_init = function(client)
+ client.stop()
+ local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
+ eq(full_kind, client.resolved_capabilities().text_document_did_change)
+ eq(true, client.resolved_capabilities().completion)
+ eq(true, client.resolved_capabilities().hover)
+ eq(false, client.resolved_capabilities().goto_definition)
+ eq(false, client.resolved_capabilities().rename)
+
+ -- known methods for resolved capabilities
+ eq(true, client.supports_method("textDocument/hover"))
+ eq(false, client.supports_method("textDocument/definition"))
+
+ -- unknown methods are assumed to be supported.
+ eq(true, client.supports_method("unknown-method"))
+ end;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end;
+ on_callback = function(...)
+ eq(table.remove(expected_callbacks), {...}, "expected callback")
+ end;
+ }
+ end)
+
+ it('should call unsupported_method when trying to call an unsupported method', function()
+ local expected_callbacks = {
+ {NIL, "shutdown", {}, 1};
+ }
+ test_rpc_server {
+ test_name = "capabilities_for_client_supports_method";
+ on_setup = function()
+ exec_lua([=[
+ vim.lsp.callbacks['textDocument/hover'] = function(err, method)
+ vim.lsp._last_lsp_callback = { err = err; method = method }
+ end
+ vim.lsp._unsupported_method = function(method)
+ vim.lsp._last_unsupported_method = method
+ return 'fake-error'
+ end
+ vim.lsp.buf.hover()
+ ]=])
+ end;
+ on_init = function(client)
+ client.stop()
+ local method = exec_lua("return vim.lsp._last_unsupported_method")
+ eq("textDocument/hover", method)
+ local lsp_cb_call = exec_lua("return vim.lsp._last_lsp_callback")
+ eq("fake-error", lsp_cb_call.err)
+ eq("textDocument/hover", lsp_cb_call.method)
end;
on_exit = function(code, signal)
eq(0, code, "exit code", fake_lsp_logfile)
@@ -747,8 +817,16 @@ describe('LSP', function()
end)
it('should invalid cmd argument', function()
- eq('Error executing lua: .../shared.lua: cmd: expected list, got nvim', pcall_err(_cmd_parts, "nvim"))
- eq('Error executing lua: .../shared.lua: cmd argument: expected string, got number', pcall_err(_cmd_parts, {"nvim", 1}))
+ eq(dedent([[
+ Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim
+ stack traceback:
+ .../lsp.lua:0: in function .../lsp.lua:0>]]),
+ pcall_err(_cmd_parts, 'nvim'))
+ eq(dedent([[
+ Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number
+ stack traceback:
+ .../lsp.lua:0: in function .../lsp.lua:0>]]),
+ pcall_err(_cmd_parts, {'nvim', 1}))
end)
end)
end)
@@ -971,34 +1049,34 @@ describe('LSP', function()
local prefix = 'foo'
local completion_list = {
-- resolves into label
- { label='foobar' },
- { label='foobar', textEdit={} },
+ { label='foobar', sortText="a" },
+ { label='foobar', sortText="b", textEdit={} },
-- resolves into insertText
- { label='foocar', insertText='foobar' },
- { label='foocar', insertText='foobar', textEdit={} },
+ { label='foocar', sortText="c", insertText='foobar' },
+ { label='foocar', sortText="d", insertText='foobar', textEdit={} },
-- resolves into textEdit.newText
- { label='foocar', insertText='foodar', textEdit={newText='foobar'} },
- { label='foocar', textEdit={newText='foobar'} },
+ { label='foocar', sortText="e", insertText='foodar', textEdit={newText='foobar'} },
+ { label='foocar', sortText="f", textEdit={newText='foobar'} },
-- real-world snippet text
- { label='foocar', insertText='foodar', textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} },
- { label='foocar', insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', textEdit={} },
+ { label='foocar', sortText="g", insertText='foodar', textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} },
+ { label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', textEdit={} },
-- nested snippet tokens
- { label='foocar', insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', textEdit={} },
+ { label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', textEdit={} },
-- plain text
- { label='foocar', insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} },
+ { label='foocar', sortText="j", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} },
}
local completion_list_items = {items=completion_list}
local expected = {
- { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label = 'foobar' } } } } },
- { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foobar', textEdit={} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foobar' } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foobar', textEdit={} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foodar', textEdit={newText='foobar'} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', textEdit={newText='foobar'} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar(place holder, more ...holder{})', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foodar', textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(var1 typ1, var2 *typ2) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', textEdit={} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(var1 typ2,typ3 tail) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', textEdit={} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(${1:var1})', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} } } } } },
+ { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label = 'foobar', sortText="a" } } } } },
+ { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foobar', sortText="b", textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="c", insertText='foobar' } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="d", insertText='foobar', textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="e", insertText='foodar', textEdit={newText='foobar'} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="f", textEdit={newText='foobar'} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar(place holder, more ...holder{})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="g", insertText='foodar', textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(var1 typ1, var2 *typ2) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(var1 typ2,typ3 tail) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(${1:var1})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="j", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} } } } } },
}
eq(expected, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], completion_list, prefix))
diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua
index da9dd09129..1431054494 100644
--- a/test/functional/provider/clipboard_spec.lua
+++ b/test/functional/provider/clipboard_spec.lua
@@ -153,6 +153,16 @@ describe('clipboard', function()
eq('', eval('provider#clipboard#Error()'))
end)
+ it('g:clipboard using lists', function()
+ source([[let g:clipboard = {
+ \ 'name': 'custom',
+ \ 'copy': { '+': ['any', 'command'], '*': ['some', 'other'] },
+ \ 'paste': { '+': ['any', 'command'], '*': ['some', 'other'] },
+ \}]])
+ eq('custom', eval('provider#clipboard#Executable()'))
+ eq('', eval('provider#clipboard#Error()'))
+ end)
+
it('g:clipboard using VimL functions', function()
-- Implements a fake clipboard provider. cache_enabled is meaningless here.
source([[let g:clipboard = {
diff --git a/test/functional/provider/perl_spec.lua b/test/functional/provider/perl_spec.lua
index 7b446e4ab3..125674660b 100644
--- a/test/functional/provider/perl_spec.lua
+++ b/test/functional/provider/perl_spec.lua
@@ -5,6 +5,10 @@ local command = helpers.command
local write_file = helpers.write_file
local eval = helpers.eval
local retry = helpers.retry
+local curbufmeths = helpers.curbufmeths
+local insert = helpers.insert
+local expect = helpers.expect
+local feed = helpers.feed
do
clear()
@@ -19,7 +23,51 @@ before_each(function()
clear()
end)
-describe('perl host', function()
+describe('legacy perl provider', function()
+ if helpers.pending_win32(pending) then return end
+
+ it('feature test', function()
+ eq(1, eval('has("perl")'))
+ end)
+
+ it(':perl command', function()
+ command('perl $vim->vars->{set_by_perl} = [100, 0];')
+ eq({100, 0}, eval('g:set_by_perl'))
+ end)
+
+ it(':perlfile command', function()
+ local fname = 'perlfile.pl'
+ write_file(fname, '$vim->command("let set_by_perlfile = 123")')
+ command('perlfile perlfile.pl')
+ eq(123, eval('g:set_by_perlfile'))
+ os.remove(fname)
+ end)
+
+ it(':perldo command', function()
+ -- :perldo 1; doesn't change $_,
+ -- the buffer should not be changed
+ command('normal :perldo 1;')
+ eq(false, curbufmeths.get_option('modified'))
+ -- insert some text
+ insert('abc\ndef\nghi')
+ expect([[
+ abc
+ def
+ ghi]])
+ -- go to top and select and replace the first two lines
+ feed('ggvj:perldo $_ = reverse ($_)."$linenr"<CR>')
+ expect([[
+ cba1
+ fed2
+ ghi]])
+ end)
+
+ it('perleval()', function()
+ eq({1, 2, {['key'] = 'val'}}, eval([[perleval('[1, 2, {"key" => "val"}]')]]))
+ end)
+end)
+
+describe('perl provider', function()
if helpers.pending_win32(pending) then return end
teardown(function ()
os.remove('Xtest-perl-hello.pl')
diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua
index bb7d23ede6..2729d8dfa2 100644
--- a/test/functional/provider/ruby_spec.lua
+++ b/test/functional/provider/ruby_spec.lua
@@ -5,6 +5,7 @@ local command = helpers.command
local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
local eval = helpers.eval
+local exc_exec = helpers.exc_exec
local expect = helpers.expect
local feed = helpers.feed
local feed_command = helpers.feed_command
@@ -109,3 +110,24 @@ describe('ruby provider', function()
eq(2, eval('1+1')) -- Still alive?
end)
end)
+
+describe('rubyeval()', function()
+ it('evaluates ruby objects', function()
+ eq({1, 2, {['key'] = 'val'}}, funcs.rubyeval('[1, 2, {key: "val"}]'))
+ end)
+
+ it('returns nil for empty strings', function()
+ eq(helpers.NIL, funcs.rubyeval(''))
+ end)
+
+ it('errors out when given non-string', function()
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(10)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(v:_null_dict)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(v:_null_list)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(0.0)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(function("tr"))'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(v:true)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(v:false)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call rubyeval(v:null)'))
+ end)
+end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 6372cd935e..8e171d31aa 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source
local eq, neq = helpers.eq, helpers.neq
local write_file = helpers.write_file
@@ -13,7 +13,7 @@ describe(':terminal buffer', function()
before_each(function()
clear()
feed_command('set modifiable swapfile undolevels=20')
- wait()
+ poke_eventloop()
screen = thelpers.screen_setup()
end)
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index ef12438ecc..8d70ebf679 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -70,7 +70,7 @@ describe(':terminal cursor', function()
:set number |
]])
feed('i')
- helpers.wait()
+ helpers.poke_eventloop()
screen:expect([[
{7: 1 }tty ready |
{7: 2 }rows: 6, cols: 46 |
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 138befd978..4b512605e1 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, wait, nvim = helpers.clear, helpers.wait, helpers.nvim
+local clear, poke_eventloop, nvim = helpers.clear, helpers.poke_eventloop, helpers.nvim
local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq
local feed = helpers.feed
local feed_command, eval = helpers.feed_command, helpers.eval
@@ -29,7 +29,7 @@ describe(':terminal', function()
-- Invoke a command that emits frequent terminal activity.
feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 9999 !terminal_output!<cr>]])
feed([[<C-\><C-N>]])
- wait()
+ poke_eventloop()
-- Wait for some terminal activity.
retry(nil, 4000, function()
ok(funcs.line('$') > 6)
@@ -60,7 +60,7 @@ describe(':terminal', function()
feed_command([[terminal while true; do echo foo; sleep .1; done]])
end
feed([[<C-\><C-N>M]]) -- move cursor away from last line
- wait()
+ poke_eventloop()
eq(3, eval("line('$')")) -- window height
eq(2, eval("line('.')")) -- cursor is in the middle
feed_command('vsplit')
@@ -76,11 +76,11 @@ describe(':terminal', function()
-- Create a new line (in the shell). For a normal buffer this
-- increments the jumplist; for a terminal-buffer it should not. #3723
feed('i')
- wait()
+ poke_eventloop()
feed('<CR><CR><CR><CR>')
- wait()
+ poke_eventloop()
feed([[<C-\><C-N>]])
- wait()
+ poke_eventloop()
-- Wait for >=1 lines to be created.
retry(nil, 4000, function()
ok(funcs.line('$') > lines_before)
@@ -210,7 +210,7 @@ describe(':terminal (with fake shell)', function()
it('ignores writes if the backing stream closes', function()
terminal_with_fake_shell()
feed('iiXXXXXXX')
- wait()
+ poke_eventloop()
-- Race: Though the shell exited (and streams were closed by SIGCHLD
-- handler), :terminal cleanup is pending on the main-loop.
-- This write should be ignored (not crash, #5445).
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index 1df8df6f6e..77fdba7fc4 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -6,7 +6,7 @@ local feed, nvim_dir, feed_command = helpers.feed, helpers.nvim_dir, helpers.fee
local iswin = helpers.iswin
local eval = helpers.eval
local command = helpers.command
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local retry = helpers.retry
local curbufmeths = helpers.curbufmeths
local nvim = helpers.nvim
@@ -347,7 +347,7 @@ describe(':terminal prints more lines than the screen height and exits', functio
local screen = Screen.new(30, 7)
screen:attach({rgb=false})
feed_command('call termopen(["'..nvim_dir..'/tty-test", "10"]) | startinsert')
- wait()
+ poke_eventloop()
screen:expect([[
line6 |
line7 |
@@ -423,7 +423,7 @@ describe("'scrollback' option", function()
retry(nil, nil, function() expect_lines(33, 2) end)
curbufmeths.set_option('scrollback', 10)
- wait()
+ poke_eventloop()
retry(nil, nil, function() expect_lines(16) end)
curbufmeths.set_option('scrollback', 10000)
retry(nil, nil, function() expect_lines(16) end)
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index f1c828d17e..9f278fd157 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local feed_data = thelpers.feed_data
local feed, clear = helpers.feed, helpers.clear
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local iswin = helpers.iswin
local command = helpers.command
local retry = helpers.retry
@@ -127,7 +127,7 @@ describe(':terminal window', function()
it('wont show any folds', function()
feed([[<C-\><C-N>ggvGzf]])
- wait()
+ poke_eventloop()
screen:expect([[
^tty ready |
line1 |
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index 3cb592c714..d7269d2c29 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -690,7 +690,7 @@ describe('Buffer highlighting', function()
end)
it('can be retrieved', function()
- local get_virtual_text = curbufmeths.get_virtual_text
+ local get_extmarks = curbufmeths.get_extmarks
local line_count = curbufmeths.line_count
local s1 = {{'Köttbullar', 'Comment'}, {'Kräuterbutter'}}
@@ -699,12 +699,14 @@ describe('Buffer highlighting', function()
-- TODO: only a virtual text from the same ns curretly overrides
-- an existing virtual text. We might add a prioritation system.
set_virtual_text(id1, 0, s1, {})
- eq(s1, get_virtual_text(0))
+ eq({{1, 0, 0, {virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
- set_virtual_text(-1, line_count(), s2, {})
- eq(s2, get_virtual_text(line_count()))
+ -- TODO: is this really valid? shouldn't the max be line_count()-1?
+ local lastline = line_count()
+ set_virtual_text(id1, line_count(), s2, {})
+ eq({{3, lastline, 0, {virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
- eq({}, get_virtual_text(line_count() + 9000))
+ eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {}))
end)
it('is not highlighted by visual selection', function()
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index 21c01b3458..01f0d8a4d7 100644
--- a/test/functional/ui/cmdline_spec.lua
+++ b/test/functional/ui/cmdline_spec.lua
@@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, feed = helpers.clear, helpers.feed
local source = helpers.source
local command = helpers.command
+local feed_command = helpers.feed_command
local function new_screen(opt)
local screen = Screen.new(25, 5)
@@ -842,3 +843,34 @@ describe('cmdline redraw', function()
]], unchanged=true}
end)
end)
+
+describe('cmdline', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('prints every executed Ex command if verbose >= 16', function()
+ local screen = Screen.new(50, 12)
+ screen:attach()
+ source([[
+ command DoSomething echo 'hello' |set ts=4 |let v = '123' |echo v
+ call feedkeys("\r", 't') " for the hit-enter prompt
+ set verbose=20
+ ]])
+ feed_command('DoSomething')
+ screen:expect([[
+ |
+ ~ |
+ |
+ Executing: DoSomething |
+ Executing: echo 'hello' |set ts=4 |let v = '123' ||
+ echo v |
+ hello |
+ Executing: set ts=4 |let v = '123' |echo v |
+ Executing: let v = '123' |echo v |
+ Executing: echo v |
+ 123 |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index 6c913124ac..e1a72ced05 100644
--- a/test/functional/ui/cursor_spec.lua
+++ b/test/functional/ui/cursor_spec.lua
@@ -286,6 +286,21 @@ describe('ui/cursor', function()
eq(173, named.normal.blinkon)
eq(42, named.showmatch.cell_percentage)
end)
+
+ -- If there is no setting for guicursor, it becomes the default setting.
+ meths.set_option('guicursor', 'n:ver35-blinkwait171-blinkoff172-blinkon173-Cursor/lCursor')
+ screen:expect(function()
+ for _,m in ipairs(screen._mode_info) do
+ if m.name ~= 'normal' then
+ eq('block', m.cursor_shape or 'block')
+ eq(0, m.blinkon or 0)
+ eq(0, m.blinkoff or 0)
+ eq(0, m.blinkwait or 0)
+ eq(0, m.hl_id or 0)
+ eq(0, m.id_lm or 0)
+ end
+ end
+ end)
end)
it("empty 'guicursor' sets cursor_shape=block in all modes", function()
@@ -297,6 +312,8 @@ describe('ui/cursor', function()
if m['cursor_shape'] ~= nil then
eq('block', m.cursor_shape)
eq(0, m.blinkon)
+ eq(0, m.hl_id)
+ eq(0, m.id_lm)
end
end
end)
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
new file mode 100644
index 0000000000..304c5aecb1
--- /dev/null
+++ b/test/functional/ui/decorations_spec.lua
@@ -0,0 +1,118 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+
+local clear = helpers.clear
+local feed = helpers.feed
+local insert = helpers.insert
+local exec_lua = helpers.exec_lua
+local expect_events = helpers.expect_events
+
+describe('decorations provider', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(40, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold=true, foreground=Screen.colors.Blue},
+ })
+ end)
+
+ local mudholland = [[
+ // just to see if there was an accident
+ // on Mulholland Drive
+ try_start();
+ bufref_T save_buf;
+ switch_buffer(&save_buf, buf);
+ posp = getmark(mark, false);
+ restore_buffer(&save_buf); ]]
+
+ local function setup_provider(code)
+ exec_lua ([[
+ local a = vim.api
+ test1 = a.nvim_create_namespace "test1"
+ ]] .. (code or [[
+ beamtrace = {}
+ function on_do(kind, ...)
+ table.insert(beamtrace, {kind, ...})
+ end
+ ]]) .. [[
+ a.nvim_set_decoration_provider(
+ test1, {
+ on_start = on_do; on_buf = on_do;
+ on_win = on_do; on_line = on_do;
+ on_end = on_do;
+ })
+ ]])
+ end
+
+ local function check_trace(expected)
+ local actual = exec_lua [[ local b = beamtrace beamtrace = {} return b ]]
+ expect_events(expected, actual, "beam trace")
+ end
+
+ it('leaves a trace', function()
+ insert(mudholland)
+
+ setup_provider()
+
+ screen:expect{grid=[[
+ // just to see if there was an accident |
+ // on Mulholland Drive |
+ try_start(); |
+ bufref_T save_buf; |
+ switch_buffer(&save_buf, buf); |
+ posp = getmark(mark, false); |
+ restore_buffer(&save_buf);^ |
+ |
+ ]]}
+ check_trace {
+ { "start", 4, 40 };
+ { "win", 1000, 1, 0, 8 };
+ { "line", 1000, 1, 0 };
+ { "line", 1000, 1, 1 };
+ { "line", 1000, 1, 2 };
+ { "line", 1000, 1, 3 };
+ { "line", 1000, 1, 4 };
+ { "line", 1000, 1, 5 };
+ { "line", 1000, 1, 6 };
+ { "end", 4 };
+ }
+
+ feed "iü<esc>"
+ screen:expect{grid=[[
+ // just to see if there was an accident |
+ // on Mulholland Drive |
+ try_start(); |
+ bufref_T save_buf; |
+ switch_buffer(&save_buf, buf); |
+ posp = getmark(mark, false); |
+ restore_buffer(&save_buf);^ü |
+ |
+ ]]}
+ check_trace {
+ { "start", 5, 10 };
+ { "buf", 1 };
+ { "win", 1000, 1, 0, 8 };
+ { "line", 1000, 1, 6 };
+ { "end", 5 };
+ }
+ end)
+
+ it('single provider', function()
+ insert(mudholland)
+ setup_provider [[
+ local hl = a.nvim_get_hl_id_by_name "ErrorMsg"
+ function do_it(event, ...)
+ if event == "line" then
+ local win, buf, line = ...
+ a.nvim_buf_set_extmark(buf, test_ns, line, line,
+ { end_line = line, end_col = line+1,
+ hl_group = hl,
+ ephemeral = true
+ })
+ end
+ end
+ ]]
+ end)
+end)
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 11fe861de8..eec8eb93d4 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -59,7 +59,7 @@ describe('floatwin', function()
end)
it('closed immediately by autocmd #11383', function()
- eq('Error executing lua: [string "<nvim>"]:4: Window was closed immediately',
+ eq('Error executing lua: [string "<nvim>"]:0: Window was closed immediately',
pcall_err(exec_lua, [[
local a = vim.api
local function crashes(contents)
diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua
index 6ec45064da..9877f30206 100644
--- a/test/functional/ui/fold_spec.lua
+++ b/test/functional/ui/fold_spec.lua
@@ -6,6 +6,8 @@ local feed_command = helpers.feed_command
local insert = helpers.insert
local funcs = helpers.funcs
local meths = helpers.meths
+local source = helpers.source
+local assert_alive = helpers.assert_alive
describe("folded lines", function()
local screen
@@ -21,6 +23,8 @@ describe("folded lines", function()
[5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
[6] = {background = Screen.colors.Yellow},
[7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
+ [8] = {foreground = Screen.colors.Brown },
+ [9] = {bold = true, foreground = Screen.colors.Brown}
})
end)
@@ -29,7 +33,7 @@ describe("folded lines", function()
feed("i<cr><esc>")
feed("vkzf")
screen:expect([[
- {5: ^+-- 2 lines: ·············}|
+ {7: }{5:^+-- 2 lines: ·············}|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -49,8 +53,8 @@ describe("folded lines", function()
funcs.setline(4, 'line 2')
feed("j")
screen:expect([[
- {7:+ }{5: 1 +-- 2 lines: ·························}|
- {7:+ }{5: 0 ^+-- 2 lines: ·························}|
+ {7:+ }{8: 1 }{5:+-- 2 lines: ·························}|
+ {7:+ }{9: 0 }{5:^+-- 2 lines: ·························}|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -130,8 +134,8 @@ describe("folded lines", function()
]])
feed('vkzf')
- screen:expect([[
- {5:^+-- 2 lines: å 语 x̎͂̀̂͛͛ ﺎﻠﻋَﺮَﺒِﻳَّﺓ·················}|
+ screen:expect{grid=[[
+ {5:^+-- 2 lines: å 语 x̎͂̀̂͛͛ العَرَبِيَّة·················}|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -139,7 +143,7 @@ describe("folded lines", function()
{1:~ }|
{1:~ }|
|
- ]])
+ ]]}
feed_command("set noarabicshape")
screen:expect([[
@@ -155,7 +159,7 @@ describe("folded lines", function()
feed_command("set number foldcolumn=2")
screen:expect([[
- {7:+ }{5: 1 ^+-- 2 lines: å 语 x̎͂̀̂͛͛ العَرَبِيَّة···········}|
+ {7:+ }{8: 1 }{5:^+-- 2 lines: å 语 x̎͂̀̂͛͛ العَرَبِيَّة···········}|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -168,7 +172,7 @@ describe("folded lines", function()
-- Note: too much of the folded line gets cut off.This is a vim bug.
feed_command("set rightleft")
screen:expect([[
- {5:+-- 2 lines: å ······················^· 1 }{7: +}|
+ {5:···········ةيَّبِرَعَلا x̎͂̀̂͛͛ 语 å :senil 2 --^+}{8: 1 }{7: +}|
{1: ~}|
{1: ~}|
{1: ~}|
@@ -180,7 +184,7 @@ describe("folded lines", function()
feed_command("set nonumber foldcolumn=0")
screen:expect([[
- {5:+-- 2 lines: å 语 x̎͂̀̂͛͛ ال·····················^·}|
+ {5:·················ةيَّبِرَعَلا x̎͂̀̂͛͛ 语 å :senil 2 --^+}|
{1: ~}|
{1: ~}|
{1: ~}|
@@ -192,7 +196,7 @@ describe("folded lines", function()
feed_command("set arabicshape")
screen:expect([[
- {5:+-- 2 lines: å 语 x̎͂̀̂͛͛ ﺍﻟ·····················^·}|
+ {5:·················ةيَّبِرَعَلا x̎͂̀̂͛͛ 语 å :senil 2 --^+}|
{1: ~}|
{1: ~}|
{1: ~}|
@@ -355,4 +359,26 @@ describe("folded lines", function()
|
]]}
end)
+
+ it('does not crash when foldtext is longer than columns #12988', function()
+ source([[
+ function! MyFoldText() abort
+ return repeat('-', &columns + 100)
+ endfunction
+ ]])
+ command('set foldtext=MyFoldText()')
+ feed("i<cr><esc>")
+ feed("vkzf")
+ screen:expect{grid=[[
+ {5:^---------------------------------------------}|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ assert_alive()
+ end)
end)
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index afb0c9cfa6..712c1f377a 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -14,7 +14,7 @@ local neq = helpers.neq
local ok = helpers.ok
local retry = helpers.retry
local source = helpers.source
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
local nvim = helpers.nvim
local sleep = helpers.sleep
local nvim_dir = helpers.nvim_dir
@@ -114,7 +114,7 @@ describe(":substitute, inccommand=split interactivity", function()
it("no preview if invoked by a script", function()
source('%s/tw/MO/g')
- wait()
+ poke_eventloop()
eq(1, eval("bufnr('$')"))
-- sanity check: assert the buffer state
expect(default_text:gsub("tw", "MO"))
@@ -123,10 +123,10 @@ describe(":substitute, inccommand=split interactivity", function()
it("no preview if invoked by feedkeys()", function()
-- in a script...
source([[:call feedkeys(":%s/tw/MO/g\<CR>")]])
- wait()
+ poke_eventloop()
-- or interactively...
feed([[:call feedkeys(":%s/tw/MO/g\<CR>")<CR>]])
- wait()
+ poke_eventloop()
eq(1, eval("bufnr('$')"))
-- sanity check: assert the buffer state
expect(default_text:gsub("tw", "MO"))
@@ -162,7 +162,7 @@ describe(":substitute, 'inccommand' preserves", function()
insert(default_text)
feed_command("set inccommand=" .. case)
- local delims = { '/', '#', ';', '%', ',', '@', '!', ''}
+ local delims = { '/', '#', ';', '%', ',', '@', '!' }
for _,delim in pairs(delims) do
feed_command("%s"..delim.."lines"..delim.."LINES"..delim.."g")
expect([[
@@ -194,7 +194,7 @@ describe(":substitute, 'inccommand' preserves", function()
-- Start typing an incomplete :substitute command.
feed([[:%s/e/YYYY/g]])
- wait()
+ poke_eventloop()
-- Cancel the :substitute.
feed([[<C-\><C-N>]])
@@ -230,7 +230,7 @@ describe(":substitute, 'inccommand' preserves", function()
-- Start typing an incomplete :substitute command.
feed([[:%s/e/YYYY/g]])
- wait()
+ poke_eventloop()
-- Cancel the :substitute.
feed([[<C-\><C-N>]])
@@ -251,7 +251,7 @@ describe(":substitute, 'inccommand' preserves", function()
some text 1
some text 2]])
feed(":%s/e/XXX/")
- wait()
+ poke_eventloop()
eq(expected_tick, eval("b:changedtick"))
end)
@@ -1128,15 +1128,15 @@ describe(":substitute, inccommand=split", function()
feed(":%s/tw/Xo/g")
-- Delete and re-type the g a few times.
feed("<BS>")
- wait()
+ poke_eventloop()
feed("g")
- wait()
+ poke_eventloop()
feed("<BS>")
- wait()
+ poke_eventloop()
feed("g")
- wait()
+ poke_eventloop()
feed("<CR>")
- wait()
+ poke_eventloop()
feed(":vs tmp<enter>")
eq(3, helpers.call('bufnr', '$'))
end)
@@ -1171,7 +1171,7 @@ describe(":substitute, inccommand=split", function()
feed_command("silent edit! test/functional/fixtures/bigfile_oneline.txt")
-- Start :substitute with a slow pattern.
feed([[:%s/B.*N/x]])
- wait()
+ poke_eventloop()
-- Assert that 'inccommand' is DISABLED in cmdline mode.
eq("", eval("&inccommand"))
@@ -1360,7 +1360,7 @@ describe("inccommand=nosplit", function()
feed("<Esc>")
command("set icm=nosplit")
feed(":%s/tw/OKOK")
- wait()
+ poke_eventloop()
screen:expect([[
Inc substitution on |
{12:OKOK}o lines |
@@ -2592,7 +2592,7 @@ describe(":substitute", function()
feed("<C-c>")
feed('gg')
- wait()
+ poke_eventloop()
feed([[:%s/\(some\)\@<lt>!thing/one/]])
screen:expect([[
something |
@@ -2613,7 +2613,7 @@ describe(":substitute", function()
]])
feed([[<C-c>]])
- wait()
+ poke_eventloop()
feed([[:%s/some\(thing\)\@=/every/]])
screen:expect([[
{12:every}thing |
@@ -2634,7 +2634,7 @@ describe(":substitute", function()
]])
feed([[<C-c>]])
- wait()
+ poke_eventloop()
feed([[:%s/some\(thing\)\@!/every/]])
screen:expect([[
something |
@@ -2718,7 +2718,7 @@ it(':substitute with inccommand during :terminal activity', function()
feed('gg')
feed(':%s/foo/ZZZ')
sleep(20) -- Allow some terminal activity.
- helpers.wait()
+ helpers.poke_eventloop()
screen:expect_unchanged()
end)
end)
@@ -2750,6 +2750,26 @@ it(':substitute with inccommand, timer-induced :redraw #9777', function()
]])
end)
+it(":substitute doesn't crash with inccommand, if undo is empty #12932", function()
+ local screen = Screen.new(10,5)
+ clear()
+ command('set undolevels=-1')
+ common_setup(screen, 'split', 'test')
+ feed(':%s/test')
+ sleep(100)
+ feed('/')
+ sleep(100)
+ feed('f')
+ screen:expect([[
+ {12:f} |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/test/f^ |
+ ]])
+ assert_alive()
+end)
+
it('long :%s/ with inccommand does not collapse cmdline', function()
local screen = Screen.new(10,5)
clear()
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index efc02db159..5df4a1d533 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -323,7 +323,7 @@ describe('ui/ext_messages', function()
{1:~ }|
{1:~ }|
]], messages={
- {content = {{"/line [1/2] W"}}, kind = "search_count"}
+ {content = {{"/line W [1/2]"}}, kind = "search_count"}
}}
feed('n')
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index d857b57a31..a741136111 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -546,7 +546,7 @@ describe('ui/mouse/input', function()
:tabprevious |
]])
feed('<LeftMouse><10,0><LeftRelease>') -- go to second tab
- helpers.wait()
+ helpers.poke_eventloop()
feed('<LeftMouse><0,1>')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua
index e4d1187dea..6601c2d68e 100644
--- a/test/functional/ui/multigrid_spec.lua
+++ b/test/functional/ui/multigrid_spec.lua
@@ -4,7 +4,7 @@ local clear = helpers.clear
local feed, command, insert = helpers.feed, helpers.command, helpers.insert
local eq = helpers.eq
local meths = helpers.meths
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('ext_multigrid', function()
@@ -1846,8 +1846,8 @@ describe('ext_multigrid', function()
meths.input_mouse('left', 'press', '', 1,6, 20)
-- TODO(bfredl): "batching" input_mouse is formally not supported yet.
-- Normally it should work fine in async context when nvim is not blocked,
- -- but add a wait be sure.
- wait()
+ -- but add a poke_eventloop be sure.
+ poke_eventloop()
meths.input_mouse('left', 'drag', '', 1, 4, 20)
screen:expect{grid=[[
## grid 1
@@ -1921,7 +1921,7 @@ describe('ext_multigrid', function()
]]}
meths.input_mouse('left', 'press', '', 1,8, 26)
- wait()
+ poke_eventloop()
meths.input_mouse('left', 'drag', '', 1, 6, 30)
screen:expect{grid=[[
## grid 1
diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua
index 9646c3fdad..2f113f6ac6 100644
--- a/test/functional/ui/options_spec.lua
+++ b/test/functional/ui/options_spec.lua
@@ -14,10 +14,10 @@ describe('UI receives option updates', function()
arabicshape=true,
emoji=true,
guifont='',
- guifontset='',
guifontwide='',
linespace=0,
pumblend=0,
+ mousefocus=false,
showtabline=1,
termguicolors=false,
ttimeout=true,
@@ -110,6 +110,12 @@ describe('UI receives option updates', function()
eq(expected, screen.options)
end)
+ command("set mousefocus")
+ expected.mousefocus = true
+ screen:expect(function()
+ eq(expected, screen.options)
+ end)
+
command("set nottimeout")
expected.ttimeout = false
screen:expect(function()
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index c1c5d1ce2e..3f984ff943 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -1213,10 +1213,10 @@ describe('builtin popupmenu', function()
funcs.complete(29, {'word', 'choice', 'text', 'thing'})
screen:expect([[
some long prefix before the ^ |
- {n:word }{1: }|
- {n:choice }{1: }|
- {n:text }{1: }|
- {n:thing }{1: }|
+ {1:~ }{n: word }|
+ {1:~ }{n: choice}|
+ {1:~ }{n: text }|
+ {1:~ }{n: thing }|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -1261,10 +1261,10 @@ describe('builtin popupmenu', function()
feed('<c-p>')
screen:expect([[
some long prefix before the text|
- {n:^word }{1: }|
- {n:choice }{1: }|
- {s:text }{1: }|
- {n:thing }{1: }|
+ {1:^~ }{n: word }|
+ {1:~ }{n: choice}|
+ {1:~ }{s: text }|
+ {1:~ }{n: thing }|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -1341,10 +1341,10 @@ describe('builtin popupmenu', function()
screen:expect([[
some long prefix |
before the text^ |
- {1:~ }{n: word }|
- {1:~ }{n: choice }|
- {1:~ }{s: text }|
- {1:~ }{n: thing }|
+ {1:~ }{n: word }{1: }|
+ {1:~ }{n: choice }{1: }|
+ {1:~ }{s: text }{1: }|
+ {1:~ }{n: thing }{1: }|
{1:~ }|
{2:-- INSERT --} |
]])
@@ -1358,10 +1358,10 @@ describe('builtin popupmenu', function()
funcs.complete(29, {'word', 'choice', 'text', 'thing'})
screen:expect([[
some long prefix before the ^ |
- {n:word }{1: }|
- {n:choice }{1: }|
- {n:text }{1: }|
- {n:thing }{1: }|
+ {1:~ }{n: word }|
+ {1:~ }{n: choice}|
+ {1:~ }{n: text }|
+ {1:~ }{n: thing }|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -2168,8 +2168,8 @@ describe('builtin popupmenu', function()
funcs.complete(29, {'word', 'choice', 'text', 'thing'})
screen:expect([[
some long prefix before the ^ |
- {n:word }{c: }{1: }|
- {n:choice }{s: }{1: }|
+ {1:~ }{n: word }{c: }|
+ {1:~ }{n: choice}{s: }|
{1:~ }|
{1:~ }|
{1:~ }|
@@ -2187,10 +2187,10 @@ describe('builtin popupmenu', function()
funcs.complete(29, {'word', 'choice', 'text', 'thing'})
screen:expect([[
some long prefix before the ^ |
- {n:word }{1: }|
- {n:choice }{1: }|
- {n:text }{1: }|
- {n:thing }{1: }|
+ {1:~ }{n: word }|
+ {1:~ }{n: choice}|
+ {1:~ }{n: text }|
+ {1:~ }{n: thing }|
{1:~ }|
{1:~ }|
{2:-- INSERT --} |
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index 635ce7392b..222275eb4d 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -158,7 +158,7 @@ describe('search highlighting', function()
bar foo baz
]])
feed('/foo')
- helpers.wait()
+ helpers.poke_eventloop()
screen:expect_unchanged()
end)
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index 9d4cb325d9..01fc50289d 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -6,7 +6,7 @@ local feed_command, source, expect = helpers.feed_command, helpers.source, helpe
local curbufmeths = helpers.curbufmeths
local command = helpers.command
local meths = helpers.meths
-local wait = helpers.wait
+local poke_eventloop = helpers.poke_eventloop
describe('completion', function()
local screen
@@ -737,8 +737,8 @@ describe('completion', function()
-- Does not indent when "ind" is typed.
feed("in<C-X><C-N>")
-- Completion list is generated incorrectly if we send everything at once
- -- via nvim_input(). So wait() before sending <BS>. #8480
- wait()
+ -- via nvim_input(). So poke_eventloop() before sending <BS>. #8480
+ poke_eventloop()
feed("<BS>d")
screen:expect([[
@@ -778,7 +778,7 @@ describe('completion', function()
]])
-- Works for unindenting too.
feed("ounin<C-X><C-N>")
- helpers.wait()
+ helpers.poke_eventloop()
feed("<BS>d")
screen:expect([[
inc uninc indent unindent |
@@ -1000,65 +1000,65 @@ describe('completion', function()
command('let g:foo = []')
feed('o')
- wait()
+ poke_eventloop()
feed('<esc>')
eq({'I'}, eval('g:foo'))
command('let g:foo = []')
feed('S')
- wait()
+ poke_eventloop()
feed('f')
- wait()
+ poke_eventloop()
eq({'I', 'I'}, eval('g:foo'))
feed('<esc>')
command('let g:foo = []')
feed('S')
- wait()
+ poke_eventloop()
feed('f')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
eq({'I', 'I', 'P'}, eval('g:foo'))
feed('<esc>')
command('let g:foo = []')
feed('S')
- wait()
+ poke_eventloop()
feed('f')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
eq({'I', 'I', 'P', 'P'}, eval('g:foo'))
feed('<esc>')
command('let g:foo = []')
feed('S')
- wait()
+ poke_eventloop()
feed('f')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
eq({'I', 'I', 'P', 'P', 'P'}, eval('g:foo'))
feed('<esc>')
command('let g:foo = []')
feed('S')
- wait()
+ poke_eventloop()
feed('f')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
feed('<C-N>')
- wait()
+ poke_eventloop()
feed('<C-N>')
eq({'I', 'I', 'P', 'P', 'P', 'P'}, eval('g:foo'))
feed('<esc>')
diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua
index c5390cbd12..9acc61e398 100644
--- a/test/functional/viml/errorlist_spec.lua
+++ b/test/functional/viml/errorlist_spec.lua
@@ -27,7 +27,7 @@ describe('setqflist()', function()
setqflist({''}, 'r', 'foo')
command('copen')
eq('foo', get_cur_win_var('quickfix_title'))
- setqflist({''}, 'r', {['title'] = 'qf_title'})
+ setqflist({}, 'r', {['title'] = 'qf_title'})
eq('qf_title', get_cur_win_var('quickfix_title'))
end)
diff --git a/test/functional/visual/meta_key_spec.lua b/test/functional/visual/meta_key_spec.lua
new file mode 100644
index 0000000000..11f7203da0
--- /dev/null
+++ b/test/functional/visual/meta_key_spec.lua
@@ -0,0 +1,22 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local command = helpers.command
+local expect = helpers.expect
+
+describe('meta-keys-in-visual-mode', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('ALT/META', function()
+ -- Unmapped ALT-chords behave as Esc+c
+ insert('peaches')
+ feed('viw<A-x>viw<M-x>')
+ expect('peach')
+ -- Mapped ALT-chord behaves as mapped.
+ command('vnoremap <M-l> Ameta-l<Esc>')
+ command('vnoremap <A-j> Aalt-j<Esc>')
+ feed('viw<A-j>viw<M-l>')
+ expect('peachalt-jmeta-l')
+ end)
+end)
diff --git a/test/helpers.lua b/test/helpers.lua
index 40b93d9935..68f0c92244 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -82,6 +82,17 @@ end
function module.ok(res, msg, logfile)
return dumplog(logfile, assert.is_true, res, msg)
end
+
+-- TODO(bfredl): this should "failure" not "error" (issue with dumplog() )
+local function epicfail(state, arguments, _)
+ state.failure_message = arguments[1]
+ return false
+end
+assert:register("assertion", "epicfail", epicfail)
+function module.fail(msg, logfile)
+ return dumplog(logfile, assert.epicfail, msg)
+end
+
function module.matches(pat, actual)
if nil ~= string.match(actual, pat) then
return true
@@ -105,8 +116,12 @@ function module.assert_log(pat, logfile)
pat, nrlines, logfile, logtail))
end
--- Invokes `fn` and returns the error string (may truncate full paths), or
--- raises an error if `fn` succeeds.
+-- Invokes `fn` and returns the error string (with truncated paths), or raises
+-- an error if `fn` succeeds.
+--
+-- Replaces line/column numbers with zero:
+-- shared.lua:0: in function 'gsplit'
+-- shared.lua:0: in function <shared.lua:0>'
--
-- Usage:
-- -- Match exact string.
@@ -114,29 +129,36 @@ end
-- -- Match Lua pattern.
-- matches('e[or]+$', pcall_err(function(a, b) error('some error') end, 'arg1', 'arg2'))
--
-function module.pcall_err(fn, ...)
+function module.pcall_err_withfile(fn, ...)
assert(type(fn) == 'function')
local status, rv = pcall(fn, ...)
if status == true then
error('expected failure, but got success')
end
- -- From this:
- -- /home/foo/neovim/runtime/lua/vim/shared.lua:186: Expected string, got number
- -- to this:
- -- Expected string, got number
- local errmsg = tostring(rv):gsub('^[^:]+:%d+: ', '')
- -- From this:
- -- Error executing lua: /very/long/foo.lua:186: Expected string, got number
- -- to this:
- -- Error executing lua: .../foo.lua:186: Expected string, got number
- errmsg = errmsg:gsub([[lua: [a-zA-Z]?:?[^:]-[/\]([^:/\]+):%d+: ]], 'lua: .../%1: ')
- -- Compiled modules will not have a path and will just be a name like
- -- shared.lua:186, so strip the number.
- errmsg = errmsg:gsub([[lua: ([^:/\ ]+):%d+: ]], 'lua: .../%1: ')
- -- ^ Windows drive-letter (C:)
+ -- From:
+ -- C:/long/path/foo.lua:186: Expected string, got number
+ -- to:
+ -- .../foo.lua:0: Expected string, got number
+ local errmsg = tostring(rv):gsub('[^%s]-[/\\]([^%s:/\\]+):%d+', '.../%1:0')
+ -- Scrub numbers in paths/stacktraces:
+ -- shared.lua:0: in function 'gsplit'
+ -- shared.lua:0: in function <shared.lua:0>'
+ errmsg = errmsg:gsub('([^%s]):%d+', '%1:0')
+ -- Scrub tab chars:
+ errmsg = errmsg:gsub('\t', ' ')
+ -- In Lua 5.1, we sometimes get a "(tail call): ?" on the last line.
+ -- We remove this so that the tests are not lua dependent.
+ errmsg = errmsg:gsub('%s*%(tail call%): %?', '')
+
return errmsg
end
+function module.pcall_err(fn, ...)
+ local errmsg = module.pcall_err_withfile(fn, ...)
+
+ return errmsg:gsub('.../helpers.lua:0: ', '')
+end
+
-- initial_path: directory to recurse into
-- re: include pattern (string)
-- exc_re: exclude pattern(s) (string or table)
@@ -200,14 +222,25 @@ function module.check_logs()
end
end
fd:close()
- os.remove(file)
if #lines > 0 then
+ local status, f
local out = io.stdout
+ if os.getenv('SYMBOLIZER') then
+ status, f = pcall(module.popen_r, os.getenv('SYMBOLIZER'), '-l', file)
+ end
out:write(start_msg .. '\n')
- out:write('= ' .. table.concat(lines, '\n= ') .. '\n')
+ if status then
+ for line in f:lines() do
+ out:write('= '..line..'\n')
+ end
+ f:close()
+ else
+ out:write('= ' .. table.concat(lines, '\n= ') .. '\n')
+ end
out:write(select(1, start_msg:gsub('.', '=')) .. '\n')
table.insert(runtime_errors, file)
end
+ os.remove(file)
end
end
end
@@ -323,7 +356,7 @@ function module.check_cores(app, force)
exc_re = { os.getenv('NVIM_TEST_CORE_EXC_RE'), local_tmpdir }
db_cmd = os.getenv('NVIM_TEST_CORE_DB_CMD') or gdb_db_cmd
random_skip = os.getenv('NVIM_TEST_CORE_RANDOM_SKIP')
- elseif os.getenv('TRAVIS_OS_NAME') == 'osx' then
+ elseif 'darwin' == module.uname() then
initial_path = '/cores'
re = nil
exc_re = { local_tmpdir }
diff --git a/test/symbolic/klee/nvim/charset.c b/test/symbolic/klee/nvim/charset.c
index 95853a6834..f9bc3fabc4 100644
--- a/test/symbolic/klee/nvim/charset.c
+++ b/test/symbolic/klee/nvim/charset.c
@@ -69,7 +69,7 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
&& !STRING_ENDED(ptr + 1)
&& ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9') {
pre = ptr[1];
- // Detect hexadecimal: 0x or 0X follwed by hex digit
+ // Detect hexadecimal: 0x or 0X followed by hex digit
if ((what & STR2NR_HEX)
&& !STRING_ENDED(ptr + 2)
&& (pre == 'X' || pre == 'x')
@@ -77,7 +77,7 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
ptr += 2;
goto vim_str2nr_hex;
}
- // Detect binary: 0b or 0B follwed by 0 or 1
+ // Detect binary: 0b or 0B followed by 0 or 1
if ((what & STR2NR_BIN)
&& !STRING_ENDED(ptr + 2)
&& (pre == 'B' || pre == 'b')
diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua
index ad05b134e0..e7cb5e5d5e 100644
--- a/test/unit/os/env_spec.lua
+++ b/test/unit/os/env_spec.lua
@@ -78,15 +78,22 @@ describe('env.c', function()
end)
describe('os_setenv_append_path', function()
- itp('appends /foo/bar to $PATH', function()
+ itp('appends :/foo/bar to $PATH', function()
local original_path = os.getenv('PATH')
- eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz')))
+ eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz.exe')))
eq(original_path..':/foo/bar', os.getenv('PATH'))
end)
+ itp('avoids redundant separator when appending to $PATH #7377', function()
+ os_setenv('PATH', '/a/b/c:', true)
+ eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz.exe')))
+ -- Must not have duplicate separators. #7377
+ eq('/a/b/c:/foo/bar', os.getenv('PATH'))
+ end)
+
itp('returns false if `fname` is not absolute', function()
local original_path = os.getenv('PATH')
- eq(false, cimp.os_setenv_append_path(to_cstr('foo/bar/baz')))
+ eq(false, cimp.os_setenv_append_path(to_cstr('foo/bar/baz.exe')))
eq(original_path, os.getenv('PATH'))
end)
end)