diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/api/highlight_spec.lua | 95 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/api/window_spec.lua | 14 | ||||
-rw-r--r-- | test/functional/core/job_spec.lua | 26 | ||||
-rw-r--r-- | test/functional/eval/null_spec.lua | 5 | ||||
-rw-r--r-- | test/functional/fixtures/streams-test.c | 17 | ||||
-rw-r--r-- | test/functional/legacy/011_autocommands_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/legacy/delete_spec.lua | 78 | ||||
-rw-r--r-- | test/functional/legacy/mksession_spec.lua | 42 | ||||
-rw-r--r-- | test/functional/legacy/packadd_spec.lua | 3 | ||||
-rw-r--r-- | test/functional/lua/buffer_updates_spec.lua | 51 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 474 | ||||
-rw-r--r-- | test/functional/plugin/lsp/diagnostic_spec.lua | 33 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 151 | ||||
-rw-r--r-- | test/functional/treesitter/parser_spec.lua | 96 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 88 | ||||
-rw-r--r-- | test/functional/ui/messages_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 29 |
18 files changed, 1052 insertions, 160 deletions
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua index 058706718a..21e3094f8e 100644 --- a/test/functional/api/highlight_spec.lua +++ b/test/functional/api/highlight_spec.lua @@ -158,3 +158,98 @@ describe('API: highlight',function() assert_alive() end) end) + +describe("API: set highlight", function() + local highlight_color = { + fg = tonumber('0xff0000'), + bg = tonumber('0x0032aa'), + ctermfg = 8, + ctermbg = 15, + } + local highlight1 = { + background = highlight_color.bg, + foreground = highlight_color.fg, + bold = true, + italic = true, + } + local highlight2_config = { + ctermbg = highlight_color.ctermbg, + ctermfg = highlight_color.ctermfg, + underline = true, + reverse = true, + } + local highlight2_result = { + background = highlight_color.ctermbg, + foreground = highlight_color.ctermfg, + underline = true, + reverse = true, + } + local highlight3_config = { + background = highlight_color.bg, + foreground = highlight_color.fg, + ctermbg = highlight_color.ctermbg, + ctermfg = highlight_color.ctermfg, + bold = true, + italic = true, + reverse = true, + undercurl = true, + underline = true, + cterm = { + italic = true, + reverse = true, + undercurl = true, + } + } + local highlight3_result_gui = { + background = highlight_color.bg, + foreground = highlight_color.fg, + bold = true, + italic = true, + reverse = true, + undercurl = true, + underline = true, + } + local highlight3_result_cterm = { + background = highlight_color.ctermbg, + foreground = highlight_color.ctermfg, + italic = true, + reverse = true, + undercurl = true, + } + + local function get_ns() + local ns = meths.create_namespace('Test_set_hl') + meths._set_hl_ns(ns) + return ns + end + + before_each(clear) + + it ("can set gui highlight", function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight1) + eq(highlight1, meths.get_hl_by_name('Test_hl', true)) + end) + + it ("can set cterm highlight", function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight2_config) + eq(highlight2_result, meths.get_hl_by_name('Test_hl', false)) + end) + + it ("cterm attr defaults to gui attr", function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight1) + eq({ + bold = true, + italic = true, + }, meths.get_hl_by_name('Test_hl', false)) + end) + + it ("can overwrite attr for cterm", function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight3_config) + eq(highlight3_result_gui, meths.get_hl_by_name('Test_hl', true)) + eq(highlight3_result_cterm, meths.get_hl_by_name('Test_hl', false)) + end) +end) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 6926022ee3..0c0f610401 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1986,6 +1986,10 @@ describe('API', function() eq(meths.get_option_info'winhighlight', options_info.winhighlight) end) + + it('should not crash when echoed', function() + meths.exec("echo nvim_get_all_options_info()", true) + end) end) describe('nvim_get_option_info', function() diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index ceeb84cec9..a57826f7e7 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -387,4 +387,18 @@ describe('API/win', function() eq({oldbuf}, meths.list_bufs()) end) end) + + describe('open_win', function() + it('noautocmd option works', function() + command('autocmd BufEnter,BufLeave,BufWinEnter * let g:fired = 1') + meths.open_win(meths.create_buf(true, true), true, { + relative='win', row=3, col=3, width=12, height=3, noautocmd=true + }) + eq(0, funcs.exists('g:fired')) + meths.open_win(meths.create_buf(true, true), true, { + relative='win', row=3, col=3, width=12, height=3 + }) + eq(1, funcs.exists('g:fired')) + end) + end) end) diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 9de0d08e79..34ab90d760 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -118,6 +118,32 @@ describe('jobs', function() end end) + it('handles case-insensitively matching #env vars', function() + nvim('command', "let $TOTO = 'abc'") + -- Since $Toto is being set in the job, it should take precedence over the + -- global $TOTO on Windows + nvim('command', "let g:job_opts = {'env': {'Toto': 'def'}, 'stdout_buffered': v:true}") + if iswin() then + nvim('command', [[let j = jobstart('set | find /I "toto="', g:job_opts)]]) + else + nvim('command', [[let j = jobstart('env | grep -i toto=', g:job_opts)]]) + end + nvim('command', "call jobwait([j])") + nvim('command', "let g:output = Normalize(g:job_opts.stdout)") + local actual = eval('g:output') + local expected + if iswin() then + -- Toto is normalized to TOTO so we can detect duplicates, and because + -- Windows doesn't care about case + expected = {'TOTO=def', ''} + else + expected = {'TOTO=abc', 'Toto=def', ''} + end + table.sort(actual) + table.sort(expected) + eq(expected, actual) + end) + it('uses &shell and &shellcmdflag if passed a string', function() nvim('command', "let $VAR = 'abc'") if iswin() then diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua index d403fbc878..b1ceff9115 100644 --- a/test/functional/eval/null_spec.lua +++ b/test/functional/eval/null_spec.lua @@ -73,6 +73,7 @@ describe('NULL', function() null_expr_test('does not crash col()', 'col(L)', 0, 0) null_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0) null_expr_test('does not crash line()', 'line(L)', 0, 0) + null_expr_test('does not crash line() with window id', 'line(L, 1000)', 0, 0) null_expr_test('does not crash count()', 'count(L, 1)', 0, 0) null_expr_test('does not crash cursor()', 'cursor(L)', 'E474: Invalid argument', -1) null_expr_test('does not crash map()', 'map(L, "v:val")', 0, {}) @@ -96,7 +97,7 @@ describe('NULL', function() null_expr_test('makes filter() return v:_null_list', 'filter(L, "1") is# L', 0, 1) null_test('is treated by :let as empty list', ':let [l] = L', 'Vim(let):E688: More targets than List items') null_expr_test('is accepted as an empty list by inputlist()', '[feedkeys("\\n"), inputlist(L)]', - 'Type number and <Enter> or click with mouse (empty cancels): ', {0, 0}) + 'Type number and <Enter> or click with the mouse (q or empty cancels): ', {0, 0}) null_expr_test('is accepted as an empty list by writefile()', ('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname), 0, {0, {}}) @@ -149,6 +150,7 @@ describe('NULL', function() null_test('does not crash :execute', 'execute S', 0) null_expr_test('does not crash execute()', 'execute(S)', 0, '') null_expr_test('makes executable() error out', 'executable(S)', 'E928: String required', 0) + null_expr_test('makes timer_start() error out', 'timer_start(0, S)', 'E921: Invalid callback argument', -1) null_expr_test('does not crash filereadable()', 'filereadable(S)', 0, 0) null_expr_test('does not crash filewritable()', 'filewritable(S)', 0, 0) null_expr_test('does not crash fnamemodify()', 'fnamemodify(S, S)', 0, '') @@ -161,7 +163,6 @@ describe('NULL', function() null_expr_test('does not crash mkdir()', 'mkdir(S)', 0, 0) null_expr_test('does not crash sort()', 'sort(["b", S, "a"])', 0, {'', 'a', 'b'}) null_expr_test('does not crash split()', 'split(S)', 0, {}) - null_test('can be used to set an option', 'let &grepprg = S', 0) null_expr_test('is equal to non-existent variable', 'S == V', 0, 1) diff --git a/test/functional/fixtures/streams-test.c b/test/functional/fixtures/streams-test.c index eec447153c..be40edfe7e 100644 --- a/test/functional/fixtures/streams-test.c +++ b/test/functional/fixtures/streams-test.c @@ -6,23 +6,22 @@ #include <uv.h> -uv_loop_t *loop; -uv_process_t child_req; -uv_process_options_t options; - int main(int argc, char **argv) { - loop = uv_default_loop(); + uv_loop_t *loop = uv_default_loop(); + uv_process_t child_req; char * args[3]; args[0] = "sleep"; args[1] = "10"; args[2] = NULL; - options.exit_cb = NULL; - options.file = "sleep"; - options.args = args; - options.flags = UV_PROCESS_DETACHED; + uv_process_options_t options = { + .exit_cb = NULL, + .file = "sleep", + .args = args, + .flags = UV_PROCESS_DETACHED, + }; int r; if ((r = uv_spawn(loop, &child_req, &options))) { diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua index c9c004eec1..7cc31dc787 100644 --- a/test/functional/legacy/011_autocommands_spec.lua +++ b/test/functional/legacy/011_autocommands_spec.lua @@ -70,7 +70,7 @@ describe('file reading, writing and bufnew and filter autocommands', function() feed_command('let $GZIP = ""') --execute('au FileChangedShell * echo "caught FileChangedShell"') feed_command('set bin') - feed_command("au FileReadPost *.gz '[,']!GZIP= gzip -d") + feed_command("au FileReadPost *.gz '[,']!gzip -d") -- Read and decompress the testfile. feed_command('$r Xtestfile.gz') expect('\n'..text1) diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua index 3d2c4a7d91..f2ced8942d 100644 --- a/test/functional/legacy/delete_spec.lua +++ b/test/functional/legacy/delete_spec.lua @@ -17,6 +17,33 @@ describe('Test for delete()', function() eq(-1, eval("delete('Xfile')")) end) + it('directory delete', function() + command("call mkdir('Xdir1')") + eq(1, eval("isdirectory('Xdir1')")) + eq(0, eval("delete('Xdir1', 'd')")) + eq(0, eval("isdirectory('Xdir1')")) + eq(-1, eval("delete('Xdir1', 'd')")) + end) + it('recursive delete', function() + command("call mkdir('Xdir1')") + command("call mkdir('Xdir1/subdir')") + command("call mkdir('Xdir1/empty')") + command('split Xdir1/Xfile') + command("call setline(1, ['a', 'b'])") + command('w') + command('w Xdir1/subdir/Xfile') + command('close') + + eq(1, eval("isdirectory('Xdir1')")) + eq(eval("['a', 'b']"), eval("readfile('Xdir1/Xfile')")) + eq(1, eval("isdirectory('Xdir1/subdir')")) + eq(eval("['a', 'b']"), eval("readfile('Xdir1/subdir/Xfile')")) + eq(1, eval("isdirectory('Xdir1/empty')")) + eq(0, eval("delete('Xdir1', 'rf')")) + eq(0, eval("isdirectory('Xdir1')")) + eq(-1, eval("delete('Xdir1', 'd')")) + end) + it('symlink delete', function() source([[ split Xfile @@ -36,4 +63,55 @@ describe('Test for delete()', function() eq(-1, eval("delete('Xlink')")) eq(0, eval("delete('Xfile')")) end) + + it('symlink directory delete', function() + command("call mkdir('Xdir1')") + if helpers.iswin() then + command("silent !mklink /j Xlink Xdir1") + else + command("silent !ln -s Xdir1 Xlink") + end + eq(1, eval("isdirectory('Xdir1')")) + eq(1, eval("isdirectory('Xlink')")) + -- Delete the link, not the directory + eq(0, eval("delete('Xlink')")) + eq(-1, eval("delete('Xlink')")) + eq(0, eval("delete('Xdir1', 'd')")) + end) + + it('symlink recursive delete', function() + source([[ + call mkdir('Xdir3') + call mkdir('Xdir3/subdir') + call mkdir('Xdir4') + split Xdir3/Xfile + call setline(1, ['a', 'b']) + w + w Xdir3/subdir/Xfile + w Xdir4/Xfile + close + if has('win32') + silent !mklink /j Xdir3\Xlink Xdir4 + else + silent !ln -s ../Xdir4 Xdir3/Xlink + endif + ]]) + + eq(1, eval("isdirectory('Xdir3')")) + eq(eval("['a', 'b']"), eval("readfile('Xdir3/Xfile')")) + eq(1, eval("isdirectory('Xdir3/subdir')")) + eq(eval("['a', 'b']"), eval("readfile('Xdir3/subdir/Xfile')")) + eq(1, eval("isdirectory('Xdir4')")) + eq(1, eval("isdirectory('Xdir3/Xlink')")) + eq(eval("['a', 'b']"), eval("readfile('Xdir4/Xfile')")) + + eq(0, eval("delete('Xdir3', 'rf')")) + eq(0, eval("isdirectory('Xdir3')")) + eq(-1, eval("delete('Xdir3', 'd')")) + -- symlink is deleted, not the directory it points to + eq(1, eval("isdirectory('Xdir4')")) + eq(eval("['a', 'b']"), eval("readfile('Xdir4/Xfile')")) + eq(0, eval("delete('Xdir4/Xfile')")) + eq(0, eval("delete('Xdir4', 'd')")) + end) end) diff --git a/test/functional/legacy/mksession_spec.lua b/test/functional/legacy/mksession_spec.lua new file mode 100644 index 0000000000..a2af891107 --- /dev/null +++ b/test/functional/legacy/mksession_spec.lua @@ -0,0 +1,42 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local command = helpers.command +local funcs = helpers.funcs +local eq = helpers.eq + +describe('mksession', function() + before_each(clear) + + after_each(function() + os.remove('Xtest_mks.out') + end) + + it('supports "skiprtp" value', function() + command('set sessionoptions&vi') + command('set rtp+=$HOME') + command('set pp+=$HOME') + command('mksession! Xtest_mks.out') + local found_rtp = 0 + local found_pp = 0 + for _, line in pairs(funcs.readfile('Xtest_mks.out', 'b')) do + if line:find('set runtimepath') then + found_rtp = found_rtp + 1 + end + if line:find('set packpath') then + found_pp = found_pp + 1 + end + end + eq(1, found_rtp) + eq(1, found_pp) + + command('set sessionoptions+=skiprtp') + command('mksession! Xtest_mks.out') + local found_rtp_or_pp = 0 + for _, line in pairs(funcs.readfile('Xtest_mks.out', 'b')) do + if line:find('set runtimepath') or line:find('set packpath') then + found_rtp_or_pp = found_rtp_or_pp + 1 + end + end + eq(0, found_rtp_or_pp) + end) +end) diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua index 3c84105c6b..486a1fe471 100644 --- a/test/functional/legacy/packadd_spec.lua +++ b/test/functional/legacy/packadd_spec.lua @@ -20,7 +20,6 @@ describe('packadd', function() func SetUp() let s:topdir = expand(getcwd() . '/Xdir') - call delete(s:topdir, 'rf') exe 'set packpath=' . s:topdir let s:plugdir = expand(s:topdir . '/pack/mine/opt/mytest') endfunc @@ -268,6 +267,8 @@ describe('packadd', function() call assert_match('look-here', tags1[0]) let tags2 = readfile(docdir2 . '/tags') call assert_match('look-away', tags2[0]) + + call assert_fails('helptags abcxyz', 'E150:') endfunc func Test_colorscheme() diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index d4c65eae5b..1b2c21783e 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -401,8 +401,8 @@ describe('lua: nvim_buf_attach on_bytes', function() } 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 }; + { "test1", "bytes", 1, 4, 7, 0, 114, 0, 4, 4, 0, 0, 0 }; + { "test1", "bytes", 1, 5, 7, 0, 114, 0, 0, 0, 1, 4, 5 }; } end) @@ -447,8 +447,8 @@ describe('lua: nvim_buf_attach on_bytes', function() 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 }; + { "test1", "bytes", 1, 6, 1, 2, 13, 0, 1, 1, 0, 0, 0 }; + { "test1", "bytes", 1, 7, 1, 2, 13, 0, 0, 0, 1, 3, 4 }; } end) @@ -936,6 +936,26 @@ describe('lua: nvim_buf_attach on_bytes', function() } end) + it("virtual edit", function () + local check_events = setup_eventcheck(verify, { "", " " }) + + meths.set_option("virtualedit", "all") + + feed [[<Right><Right>iab<ESC>]] + + check_events { + { "test1", "bytes", 1, 3, 0, 0, 0, 0, 0, 0, 0, 2, 2 }; + { "test1", "bytes", 1, 4, 0, 2, 2, 0, 0, 0, 0, 2, 2 }; + } + + feed [[j<Right><Right>iab<ESC>]] + + check_events { + { "test1", "bytes", 1, 5, 1, 0, 5, 0, 1, 1, 0, 8, 8 }; + { "test1", "bytes", 1, 6, 1, 5, 10, 0, 0, 0, 0, 2, 2 }; + } + end) + it("block visual paste", function() local check_events = setup_eventcheck(verify, {"AAA", "BBB", @@ -958,6 +978,29 @@ describe('lua: nvim_buf_attach on_bytes', function() } end) + it("nvim_buf_set_lines", function() + local check_events = setup_eventcheck(verify, {"AAA", "BBB"}) + + -- delete + meths.buf_set_lines(0, 0, 1, true, {}) + + check_events { + { "test1", "bytes", 1, 3, 0, 0, 0, 1, 0, 4, 0, 0, 0 }; + } + + -- add + meths.buf_set_lines(0, 0, 0, true, {'asdf'}) + check_events { + { "test1", "bytes", 1, 4, 0, 0, 0, 0, 0, 0, 1, 0, 5 }; + } + + -- replace + meths.buf_set_lines(0, 0, 1, true, {'asdf', 'fdsa'}) + check_events { + { "test1", "bytes", 1, 5, 0, 0, 0, 1, 0, 5, 2, 0, 10 }; + } + end) + teardown(function() os.remove "Xtest-reload" os.remove "Xtest-undofile" diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 9bf00b594b..08a0552a38 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -945,12 +945,20 @@ describe('lua stdlib', function() exec_lua [[ vim.api.nvim_set_var("testing", "hi") vim.api.nvim_set_var("other", 123) + vim.api.nvim_set_var("floaty", 5120.1) + vim.api.nvim_set_var("nullvar", vim.NIL) vim.api.nvim_set_var("to_delete", {hello="world"}) ]] eq('hi', funcs.luaeval "vim.g.testing") eq(123, funcs.luaeval "vim.g.other") + eq(5120.1, funcs.luaeval "vim.g.floaty") eq(NIL, funcs.luaeval "vim.g.nonexistant") + eq(NIL, funcs.luaeval "vim.g.nullvar") + -- lost over RPC, so test locally: + eq({false, true}, exec_lua [[ + return {vim.g.nonexistant == vim.NIL, vim.g.nullvar == vim.NIL} + ]]) eq({hello="world"}, funcs.luaeval "vim.g.to_delete") exec_lua [[ @@ -963,12 +971,20 @@ describe('lua stdlib', function() exec_lua [[ vim.api.nvim_buf_set_var(0, "testing", "hi") vim.api.nvim_buf_set_var(0, "other", 123) + vim.api.nvim_buf_set_var(0, "floaty", 5120.1) + vim.api.nvim_buf_set_var(0, "nullvar", vim.NIL) vim.api.nvim_buf_set_var(0, "to_delete", {hello="world"}) ]] eq('hi', funcs.luaeval "vim.b.testing") eq(123, funcs.luaeval "vim.b.other") + eq(5120.1, funcs.luaeval "vim.b.floaty") eq(NIL, funcs.luaeval "vim.b.nonexistant") + eq(NIL, funcs.luaeval "vim.b.nullvar") + -- lost over RPC, so test locally: + eq({false, true}, exec_lua [[ + return {vim.b.nonexistant == vim.NIL, vim.b.nullvar == vim.NIL} + ]]) eq({hello="world"}, funcs.luaeval "vim.b.to_delete") exec_lua [[ @@ -1097,6 +1113,464 @@ describe('lua stdlib', function() eq(0, funcs.luaeval "vim.wo[1000].cole") end) + describe('vim.opt', function() + -- TODO: We still need to write some tests for optlocal, opt and then getting the options + -- Probably could also do some stuff with getting things from viml side as well to confirm behavior is the same. + + it('should allow setting number values', function() + local scrolloff = exec_lua [[ + vim.opt.scrolloff = 10 + return vim.o.scrolloff + ]] + eq(scrolloff, 10) + end) + + pending('should handle STUPID window things', function() + local result = exec_lua [[ + local result = {} + + table.insert(result, vim.api.nvim_get_option('scrolloff')) + table.insert(result, vim.api.nvim_win_get_option(0, 'scrolloff')) + + return result + ]] + + eq({}, result) + end) + + it('should allow setting tables', function() + local wildignore = exec_lua [[ + vim.opt.wildignore = { 'hello', 'world' } + return vim.o.wildignore + ]] + eq(wildignore, "hello,world") + end) + + it('should allow setting tables with shortnames', function() + local wildignore = exec_lua [[ + vim.opt.wig = { 'hello', 'world' } + return vim.o.wildignore + ]] + eq(wildignore, "hello,world") + end) + + it('should error when you attempt to set string values to numeric options', function() + local result = exec_lua [[ + return { + pcall(function() vim.opt.textwidth = 'hello world' end) + } + ]] + + eq(false, result[1]) + end) + + it('should error when you attempt to setlocal a global value', function() + local result = exec_lua [[ + return pcall(function() vim.opt_local.clipboard = "hello" end) + ]] + + eq(false, result) + end) + + it('should allow you to set boolean values', function() + eq({true, false, true}, exec_lua [[ + local results = {} + + vim.opt.autoindent = true + table.insert(results, vim.bo.autoindent) + + vim.opt.autoindent = false + table.insert(results, vim.bo.autoindent) + + vim.opt.autoindent = not vim.opt.autoindent:get() + table.insert(results, vim.bo.autoindent) + + return results + ]]) + end) + + it('should change current buffer values and defaults for global local values', function() + local result = exec_lua [[ + local result = {} + + vim.opt.makeprg = "global-local" + table.insert(result, vim.api.nvim_get_option('makeprg')) + table.insert(result, (pcall(vim.api.nvim_buf_get_option, 0, 'makeprg'))) + + vim.opt_local.mp = "only-local" + table.insert(result, vim.api.nvim_get_option('makeprg')) + table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg')) + + vim.opt_global.makeprg = "only-global" + table.insert(result, vim.api.nvim_get_option('makeprg')) + table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg')) + + vim.opt.makeprg = "global-local" + table.insert(result, vim.api.nvim_get_option('makeprg')) + table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg')) + return result + ]] + + -- Set -> global & local + eq("global-local", result[1]) + eq(false, result[2]) + + -- Setlocal -> only local + eq("global-local", result[3]) + eq("only-local", result[4]) + + -- Setglobal -> only global + eq("only-global", result[5]) + eq("only-local", result[6]) + + -- set -> doesn't override previously set value + eq("global-local", result[7]) + eq("only-local", result[8]) + end) + + it('should allow all sorts of string manipulation', function() + eq({'hello', 'hello world', 'start hello world'}, exec_lua [[ + local results = {} + + vim.opt.makeprg = "hello" + table.insert(results, vim.o.makeprg) + + vim.opt.makeprg = vim.opt.makeprg + " world" + table.insert(results, vim.o.makeprg) + + vim.opt.makeprg = vim.opt.makeprg ^ "start " + table.insert(results, vim.o.makeprg) + + return results + ]]) + end) + + describe('option:get()', function() + it('should work for boolean values', function() + eq(false, exec_lua [[ + vim.opt.number = false + return vim.opt.number:get() + ]]) + end) + + it('should work for number values', function() + local tabstop = exec_lua[[ + vim.opt.tabstop = 10 + return vim.opt.tabstop:get() + ]] + + eq(10, tabstop) + end) + + it('should work for string values', function() + eq("hello world", exec_lua [[ + vim.opt.makeprg = "hello world" + return vim.opt.makeprg:get() + ]]) + end) + + it('should work for set type flaglists', function() + local formatoptions = exec_lua [[ + vim.opt.formatoptions = 'tcro' + return vim.opt.formatoptions:get() + ]] + + eq(true, formatoptions.t) + eq(true, not formatoptions.q) + end) + + it('should work for set type flaglists', function() + local formatoptions = exec_lua [[ + vim.opt.formatoptions = { t = true, c = true, r = true, o = true } + return vim.opt.formatoptions:get() + ]] + + eq(true, formatoptions.t) + eq(true, not formatoptions.q) + end) + + it('should work for array list type options', function() + local wildignore = exec_lua [[ + vim.opt.wildignore = "*.c,*.o,__pycache__" + return vim.opt.wildignore:get() + ]] + + eq(3, #wildignore) + eq("*.c", wildignore[1]) + end) + + it('should work for key-value pair options', function() + local listchars = exec_lua [[ + vim.opt.listchars = "tab:>~,space:_" + return vim.opt.listchars:get() + ]] + + eq({ + tab = ">~", + space = "_", + }, listchars) + end) + + it('should allow you to add numeric options', function() + eq(16, exec_lua [[ + vim.opt.tabstop = 12 + vim.opt.tabstop = vim.opt.tabstop + 4 + return vim.bo.tabstop + ]]) + end) + + it('should allow you to subtract numeric options', function() + eq(2, exec_lua [[ + vim.opt.tabstop = 4 + vim.opt.tabstop = vim.opt.tabstop - 2 + return vim.bo.tabstop + ]]) + end) + end) + + describe('key:value style options', function() + it('should handle dictionary style', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + + return vim.o.listchars + ]] + eq("eol:~,space:.", listchars) + end) + + it('should allow adding dictionary style', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + + vim.opt.listchars = vim.opt.listchars + { space = "-" } + + return vim.o.listchars + ]] + + eq("eol:~,space:-", listchars) + end) + + it('should allow adding dictionary style', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + vim.opt.listchars = vim.opt.listchars + { space = "-" } + { space = "_" } + + return vim.o.listchars + ]] + + eq("eol:~,space:_", listchars) + end) + + it('should allow completely new keys', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + vim.opt.listchars = vim.opt.listchars + { tab = ">>>" } + + return vim.o.listchars + ]] + + eq("eol:~,space:.,tab:>>>", listchars) + end) + + it('should allow subtracting dictionary style', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + vim.opt.listchars = vim.opt.listchars - "space" + + return vim.o.listchars + ]] + + eq("eol:~", listchars) + end) + + it('should allow subtracting dictionary style', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + vim.opt.listchars = vim.opt.listchars - "space" - "eol" + + return vim.o.listchars + ]] + + eq("", listchars) + end) + + it('should allow subtracting dictionary style multiple times', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + vim.opt.listchars = vim.opt.listchars - "space" - "space" + + return vim.o.listchars + ]] + + eq("eol:~", listchars) + end) + + it('should allow adding a key:value string to a listchars', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + vim.opt.listchars = vim.opt.listchars + "tab:>~" + + return vim.o.listchars + ]] + + eq("eol:~,space:.,tab:>~", listchars) + end) + + it('should allow prepending a key:value string to a listchars', function() + local listchars = exec_lua [[ + vim.opt.listchars = { + eol = "~", + space = ".", + } + vim.opt.listchars = vim.opt.listchars ^ "tab:>~" + + return vim.o.listchars + ]] + + eq("eol:~,space:.,tab:>~", listchars) + end) + end) + + it('should automatically set when calling remove', function() + eq("foo,baz", exec_lua [[ + vim.opt.wildignore = "foo,bar,baz" + vim.opt.wildignore:remove("bar") + + return vim.o.wildignore + ]]) + end) + + it('should automatically set when calling remove with a table', function() + eq("foo", exec_lua [[ + vim.opt.wildignore = "foo,bar,baz" + vim.opt.wildignore:remove { "bar", "baz" } + + return vim.o.wildignore + ]]) + end) + + it('should automatically set when calling append', function() + eq("foo,bar,baz,bing", exec_lua [[ + vim.opt.wildignore = "foo,bar,baz" + vim.opt.wildignore:append("bing") + + return vim.o.wildignore + ]]) + end) + + it('should automatically set when calling append with a table', function() + eq("foo,bar,baz,bing,zap", exec_lua [[ + vim.opt.wildignore = "foo,bar,baz" + vim.opt.wildignore:append { "bing", "zap" } + + return vim.o.wildignore + ]]) + end) + + it('should allow adding tables', function() + local wildignore = exec_lua [[ + vim.opt.wildignore = 'foo' + return vim.o.wildignore + ]] + eq(wildignore, 'foo') + + wildignore = exec_lua [[ + vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } + return vim.o.wildignore + ]] + eq(wildignore, 'foo,bar,baz') + end) + + it('should handle adding duplicates', function() + local wildignore = exec_lua [[ + vim.opt.wildignore = 'foo' + return vim.o.wildignore + ]] + eq(wildignore, 'foo') + + wildignore = exec_lua [[ + vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } + return vim.o.wildignore + ]] + eq(wildignore, 'foo,bar,baz') + + wildignore = exec_lua [[ + vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } + return vim.o.wildignore + ]] + eq(wildignore, 'foo,bar,baz') + end) + + it('should allow adding multiple times', function() + local wildignore = exec_lua [[ + vim.opt.wildignore = 'foo' + vim.opt.wildignore = vim.opt.wildignore + 'bar' + 'baz' + return vim.o.wildignore + ]] + eq(wildignore, 'foo,bar,baz') + end) + + it('should remove values when you use minus', function() + local wildignore = exec_lua [[ + vim.opt.wildignore = 'foo' + return vim.o.wildignore + ]] + eq(wildignore, 'foo') + + wildignore = exec_lua [[ + vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } + return vim.o.wildignore + ]] + eq(wildignore, 'foo,bar,baz') + + wildignore = exec_lua [[ + vim.opt.wildignore = vim.opt.wildignore - 'bar' + return vim.o.wildignore + ]] + eq(wildignore, 'foo,baz') + end) + + it('should prepend values when using ^', function() + local wildignore = exec_lua [[ + vim.opt.wildignore = 'foo' + vim.opt.wildignore = vim.opt.wildignore ^ 'first' + return vim.o.wildignore + ]] + eq('first,foo', wildignore) + + wildignore = exec_lua [[ + vim.opt.wildignore = vim.opt.wildignore ^ 'super_first' + return vim.o.wildignore + ]] + eq(wildignore, 'super_first,first,foo') + end) + + end) + it('vim.cmd', function() exec_lua [[ vim.cmd "autocmd BufNew * ++once lua BUF = vim.fn.expand('<abuf>')" diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua index 8c91c4ab2c..962028e7e1 100644 --- a/test/functional/plugin/lsp/diagnostic_spec.lua +++ b/test/functional/plugin/lsp/diagnostic_spec.lua @@ -86,6 +86,39 @@ describe('vim.lsp.diagnostic', function() eq(2, #result[1]) eq('Diagnostic #1', result[1][1].message) end) + it('Can convert diagnostic to quickfix items format', function() + local bufnr = exec_lua([[ + local fake_uri = ... + return vim.uri_to_bufnr(fake_uri) + ]], fake_uri) + local result = exec_lua([[ + local bufnr = ... + vim.lsp.diagnostic.save( + { + make_error('Diagnostic #1', 1, 1, 1, 1), + make_error('Diagnostic #2', 2, 1, 2, 1), + }, bufnr, 1 + ) + return vim.lsp.util.diagnostics_to_items(vim.lsp.diagnostic.get_all()) + ]], bufnr) + local expected = { + { + bufnr = bufnr, + col = 2, + lnum = 2, + text = 'Diagnostic #1', + type = 'E' + }, + { + bufnr = bufnr, + col = 2, + lnum = 3, + text = 'Diagnostic #2', + type = 'E' + }, + } + eq(expected, result) + end) it('should be able to save and count a single client error', function() eq(1, exec_lua [[ vim.lsp.diagnostic.save( diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 2b7198bf63..663271deab 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -9,6 +9,7 @@ local eq = helpers.eq local pcall_err = helpers.pcall_err local pesc = helpers.pesc local insert = helpers.insert +local funcs = helpers.funcs local retry = helpers.retry local NIL = helpers.NIL local read_file = require('test.helpers').read_file @@ -1392,10 +1393,10 @@ describe('LSP', function() { label='foocar', sortText="e", insertText='foodar', textEdit={newText='foobar'} }, { label='foocar', sortText="f", textEdit={newText='foobar'} }, -- real-world snippet text - { 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={} }, + { label='foocar', sortText="g", insertText='foodar', insertTextFormat=2, textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} }, + { label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', insertTextFormat=2, textEdit={} }, -- nested snippet tokens - { label='foocar', sortText="i", 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\\}', insertTextFormat=2, textEdit={} }, -- plain text { label='foocar', sortText="j", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} }, } @@ -1407,9 +1408,9 @@ describe('LSP', function() { 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 = 'foobar(place holder, more ...holder{})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="g", insertText='foodar', insertTextFormat=2, 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\\}', insertTextFormat=2, 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\\}', insertTextFormat=2, 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={} } } } } }, } @@ -1820,36 +1821,20 @@ describe('LSP', function() end) describe('lsp.util.jump_to_location', function() - local default_target_bufnr - local default_target_uri = 'file://fake/uri' - - local create_buf = function(uri, lines) - for i, line in ipairs(lines) do - lines[i] = '"' .. line .. '"' - end - lines = table.concat(lines, ", ") - - -- Let's set "hidden" to true in order to avoid errors when switching - -- between buffers in test. - local code = string.format([[ - vim.api.nvim_set_option('hidden', true) + local target_bufnr - local bufnr = vim.uri_to_bufnr("%s") - local lines = {%s} + before_each(function() + target_bufnr = exec_lua [[ + local bufnr = vim.uri_to_bufnr("file://fake/uri") + local lines = {"1st line of text", "å å ɧ 汉语 ↥ 🤦 🦄"} vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines) return bufnr - ]], uri, lines) - - return exec_lua(code) - end - - before_each(function() - default_target_bufnr = create_buf(default_target_uri, {'1st line of text', 'å å ɧ 汉语 ↥ 🤦 🦄'}) + ]] end) - local location = function(uri, start_line, start_char, end_line, end_char) + local location = function(start_line, start_char, end_line, end_char) return { - uri = uri, + uri = "file://fake/uri", range = { start = { line = start_line, character = start_char }, ["end"] = { line = end_line, character = end_char }, @@ -1857,9 +1842,9 @@ describe('LSP', function() } end - local jump = function(bufnr, msg) + local jump = function(msg) eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg)) - eq(bufnr, exec_lua[[return vim.fn.bufnr('%')]]) + eq(target_bufnr, exec_lua[[return vim.fn.bufnr('%')]]) return { line = exec_lua[[return vim.fn.line('.')]], col = exec_lua[[return vim.fn.col('.')]], @@ -1867,13 +1852,13 @@ describe('LSP', function() end it('jumps to a Location', function() - local pos = jump(default_target_bufnr, location(default_target_uri, 0, 9, 0, 9)) + local pos = jump(location(0, 9, 0, 9)) eq(1, pos.line) eq(10, pos.col) end) it('jumps to a LocationLink', function() - local pos = jump(default_target_bufnr, { + local pos = jump({ targetUri = "file://fake/uri", targetSelectionRange = { start = { line = 0, character = 4 }, @@ -1889,104 +1874,22 @@ describe('LSP', function() end) it('jumps to the correct multibyte column', function() - local pos = jump(default_target_bufnr, location(default_target_uri, 1, 2, 1, 2)) + local pos = jump(location(1, 2, 1, 2)) eq(2, pos.line) eq(4, pos.col) eq('å', exec_lua[[return vim.fn.expand('<cword>')]]) end) it('adds current position to jumplist before jumping', function() - exec_lua([[ - vim.api.nvim_win_set_buf(0, ...) - vim.api.nvim_win_set_cursor(0, {2, 0}) - ]], default_target_bufnr) - jump(default_target_bufnr, location(default_target_uri, 0, 9, 0, 9)) - - local mark = exec_lua([[return vim.inspect(vim.api.nvim_buf_get_mark(..., "'"))]], default_target_bufnr) - eq('{ 2, 0 }', mark) - end) - - it('should not push item to tagstack if destination is the same as source', function() - -- Set cursor at the 2nd line, 1st character. This is the source position - -- for the test, and will also be the destination one, making the cursor - -- "motionless", thus not triggering a push to the tagstack. - exec_lua(string.format([[ - vim.api.nvim_win_set_buf(0, %d) - vim.api.nvim_win_set_cursor(0, {2, 0}) - ]], default_target_bufnr)) - - -- Jump to 'f' in 'foobar', at the 2nd line. - jump(default_target_bufnr, location(default_target_uri, 1, 0, 1, 0)) + funcs.nvim_win_set_buf(0, target_bufnr) + local mark = funcs.nvim_buf_get_mark(target_bufnr, "'") + eq({ 1, 0 }, mark) - local stack = exec_lua[[return vim.fn.gettagstack()]] - eq(0, stack.length) - end) - - it('should not push the same item from same buffer twice to tagstack', function() - -- Set cursor at the 2nd line, 5th character. - exec_lua(string.format([[ - vim.api.nvim_win_set_buf(0, %d) - vim.api.nvim_win_set_cursor(0, {2, 4}) - ]], default_target_bufnr)) - - local stack - - -- Jump to 1st line, 1st column. - jump(default_target_bufnr, location(default_target_uri, 0, 0, 0, 0)) - - stack = exec_lua[[return vim.fn.gettagstack()]] - eq({default_target_bufnr, 2, 5, 0}, stack.items[1].from) - - -- Go back to 5th character at 2nd line, which is currently at the top of - -- the tagstack. - exec_lua(string.format([[ - vim.api.nvim_win_set_cursor(0, {2, 4}) - ]], default_target_bufnr)) - - -- Jump again to 1st line, 1st column. Since we're jumping from the same - -- position we have just jumped from, this jump shouldn't be pushed to - -- the tagstack. - jump(default_target_bufnr, location(default_target_uri, 0, 0, 0, 0)) + funcs.nvim_win_set_cursor(0, {2, 3}) + jump(location(0, 9, 0, 9)) - stack = exec_lua[[return vim.fn.gettagstack()]] - eq({default_target_bufnr, 2, 5, 0}, stack.items[1].from) - eq(1, stack.length) - end) - - it('should not push the same item from another buffer twice to tagstack', function() - local target_uri = 'file://foo/bar' - local target_bufnr = create_buf(target_uri, {'this is a line', 'foobar'}) - - -- Set cursor at the 1st line, 3rd character of the default test buffer. - exec_lua(string.format([[ - vim.api.nvim_win_set_buf(0, %d) - vim.api.nvim_win_set_cursor(0, {1, 2}) - ]], default_target_bufnr)) - - local stack - - -- Jump to 1st line, 1st column of a different buffer from the source - -- position. - jump(target_bufnr, location(target_uri, 0, 0, 0, 0)) - - stack = exec_lua[[return vim.fn.gettagstack()]] - eq({default_target_bufnr, 1, 3, 0}, stack.items[1].from) - - -- Go back to 3rd character at 1st line of the default test buffer, which - -- is currently at the top of the tagstack. - exec_lua(string.format([[ - vim.api.nvim_win_set_buf(0, %d) - vim.api.nvim_win_set_cursor(0, {1, 2}) - ]], default_target_bufnr)) - - -- Jump again to 1st line, 1st column of the different buffer. Since - -- we're jumping from the same position we have just jumped from, this - -- jump shouldn't be pushed to the tagstack. - jump(target_bufnr, location(target_uri, 0, 0, 0, 0)) - - stack = exec_lua[[return vim.fn.gettagstack()]] - eq({default_target_bufnr, 1, 3, 0}, stack.items[1].from) - eq(1, stack.length) + mark = funcs.nvim_buf_get_mark(target_bufnr, "'") + eq({ 2, 3 }, mark) end) end) diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index f267f9fb5d..d2f9148e8f 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -235,6 +235,100 @@ void ui_refresh(void) }, res) end) + it('can match special regex characters like \\ * + ( with `vim-match?`', function() + if pending_c_parser(pending) then return end + + insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') + + local res = exec_lua([[ + cquery = vim.treesitter.parse_query("c", '((_) @plus (vim-match? @plus "^\\\\+$"))'.. + '((_) @times (vim-match? @times "^\\\\*$"))'.. + '((_) @paren (vim-match? @paren "^\\\\($"))'.. + '((_) @escape (vim-match? @escape "^\\\\\\\\n$"))'.. + '((_) @string (vim-match? @string "^\\"\\\\\\\\n\\"$"))') + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for pattern, match in cquery:iter_matches(tree:root(), 0) 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({ + { 2, { { "times", '*', 0, 4, 0, 5 } } }, + { 5, { { "string", 'string_literal', 0, 16, 0, 20 } } }, + { 4, { { "escape", 'escape_sequence', 0, 17, 0, 19 } } }, + { 3, { { "paren", '(', 0, 22, 0, 23 } } }, + { 1, { { "plus", '+', 0, 25, 0, 26 } } }, + { 2, { { "times", '*', 0, 30, 0, 31 } } }, + }, res) + end) + + it('supports builtin query predicate any-of?', function() + if pending_c_parser(pending) then return end + + insert([[ + #include <stdio.h> + + int main(void) { + int i; + for(i=1; i<=100; i++) { + if(((i%3)||(i%5))== 0) + printf("number= %d FizzBuzz\n", i); + else if((i%3)==0) + printf("number= %d Fizz\n", i); + else if((i%5)==0) + printf("number= %d Buzz\n", i); + else + printf("number= %d\n",i); + } + return 0; + } + ]]) + exec_lua([[ + function get_query_result(query_text) + cquery = vim.treesitter.parse_query("c", query_text) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for cid, node in cquery:iter_captures(tree:root(), 0) do + -- can't transmit node over RPC. just check the name, range, and text + local text = vim.treesitter.get_node_text(node, 0) + local range = {node:range()} + table.insert(res, {cquery.captures[cid], node:type(), range, text}) + end + return res + end + ]]) + + local res0 = exec_lua([[return get_query_result(...)]], + [[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]]) + eq({ + { "c-keyword", "primitive_type", { 2, 2, 2, 5 }, "int" }, + { "c-keyword", "primitive_type", { 3, 4, 3, 7 }, "int" }, + }, res0) + + local res1 = exec_lua([[return get_query_result(...)]], + [[ + ((string_literal) @fizzbuzz-strings (#any-of? @fizzbuzz-strings + "\"number= %d FizzBuzz\\n\"" + "\"number= %d Fizz\\n\"" + "\"number= %d Buzz\\n\"" + )) + ]]) + eq({ + { "fizzbuzz-strings", "string_literal", { 6, 15, 6, 38 }, "\"number= %d FizzBuzz\\n\""}, + { "fizzbuzz-strings", "string_literal", { 8, 15, 8, 34 }, "\"number= %d Fizz\\n\""}, + { "fizzbuzz-strings", "string_literal", { 10, 15, 10, 34 }, "\"number= %d Buzz\\n\""}, + }, res1) + end) + it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function() if pending_c_parser(pending) then return end @@ -308,7 +402,7 @@ void ui_refresh(void) return list ]] - eq({ 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) + eq({ 'any-of?', 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 66aaf0c941..f3b840da21 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -64,10 +64,13 @@ describe('float window', function() it('win_execute() should work' , function() local buf = meths.create_buf(false, false) - meths.buf_set_lines(buf, 0, -1, true, {'the floatwin'}) + meths.buf_set_lines(buf, 0, -1, true, {'the floatwin', 'abc', 'def'}) local win = meths.open_win(buf, false, {relative='win', width=16, height=1, row=0, col=10}) local line = funcs.win_execute(win, 'echo getline(1)') eq('\nthe floatwin', line) + eq('\n1', funcs.win_execute(win, 'echo line(".",'..win.id..')')) + eq('\n3', funcs.win_execute(win, 'echo line("$",'..win.id..')')) + eq('\n0', funcs.win_execute(win, 'echo line("$", 123456)')) funcs.win_execute(win, 'bwipe!') end) @@ -1077,8 +1080,8 @@ describe('float window', function() {1: abb }| {13: acc }| ]], float_pos={ - [5] = { { id = 1002 }, "NW", 1, 0, 5, true }, - [6] = { { id = -1 }, "NW", 5, 4, 0, false } + [5] = { { id = 1002 }, "NW", 1, 0, 5, true, 50 }, + [6] = { { id = -1 }, "NW", 5, 4, 0, false, 100 } }, win_viewport={ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0}; [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 3}; @@ -2755,8 +2758,8 @@ describe('float window', function() {1: word }| {1: longtext }| ]], float_pos={ - [4] = {{ id = 1001 }, "NW", 1, 2, 5, true}, - [5] = {{ id = -1 }, "NW", 4, 1, 1, false} + [4] = {{ id = 1001 }, "NW", 1, 2, 5, true, 50}, + [5] = {{ id = -1 }, "NW", 4, 1, 1, false, 100} }} else screen:expect([[ @@ -2842,8 +2845,8 @@ describe('float window', function() {1:yy }| {1:zz }| ]], float_pos={ - [4] = {{ id = 1001 }, "NW", 1, 2, 5, true}, - [5] = {{ id = -1 }, "NW", 2, 1, 0, false} + [4] = {{ id = 1001 }, "NW", 1, 2, 5, true, 50}, + [5] = {{ id = -1 }, "NW", 2, 1, 0, false, 100} }} else screen:expect([[ @@ -3104,7 +3107,7 @@ describe('float window', function() {1:word }| {1:longtext }| ]], float_pos={ - [4] = {{id = -1}, "NW", 2, 1, 0, false}} + [4] = {{id = -1}, "NW", 2, 1, 0, false, 100}} } else screen:expect([[ @@ -3148,8 +3151,8 @@ describe('float window', function() {15:some info }| {15:about item }| ]], float_pos={ - [4] = {{id = -1}, "NW", 2, 1, 0, false}, - [6] = {{id = 1002}, "NW", 2, 1, 12, true}, + [4] = {{id = -1}, "NW", 2, 1, 0, false, 100}, + [6] = {{id = 1002}, "NW", 2, 1, 12, true, 50}, }} else screen:expect([[ @@ -3263,7 +3266,7 @@ describe('float window', function() {1:word }| {1:longtext }| ]], float_pos={ - [4] = {{id = -1}, "NW", 2, 1, 0, false}, + [4] = {{id = -1}, "NW", 2, 1, 0, false, 100}, }} else screen:expect([[ @@ -6296,6 +6299,69 @@ describe('float window', function() ]]} end end) + + it('can use z-index', function() + local buf = meths.create_buf(false,false) + local win1 = meths.open_win(buf, false, {relative='editor', width=20, height=3, row=1, col=5, zindex=30}) + meths.win_set_option(win1, "winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg") + local win2 = meths.open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=6, zindex=50}) + meths.win_set_option(win2, "winhl", "Normal:Search,EndOfBuffer:Search") + local win3 = meths.open_win(buf, false, {relative='editor', width=20, height=3, row=3, col=7, zindex=40}) + meths.win_set_option(win3, "winhl", "Normal:Question,EndOfBuffer:Question") + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {7: }| + {7:~ }| + {7:~ }| + ## grid 5 + {17: }| + {17:~ }| + {17:~ }| + ## grid 6 + {8: }| + {8:~ }| + {8:~ }| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 5, true, 30}; + [5] = {{id = 1002}, "NW", 1, 2, 6, true, 50}; + [6] = {{id = 1003}, "NW", 1, 3, 7, true, 40}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0}; + [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }{7: }{0: }| + {0:~ }{7:~}{17: }{0: }| + {0:~ }{7:~}{17:~ }{8: }{0: }| + {0:~ }{17:~ }{8: }{0: }| + {0:~ }{8:~ }{0: }| + | + ]]} + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 9d7719a7c0..72468392ee 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -811,7 +811,7 @@ describe('ui/ext_messages', function() {1:~ }| {1:^~ }| ]], messages={ - {content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Helli"\nType number and <Enter> or click with mouse (empty cancels): ' } }, kind = ""} + {content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Helli"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""} }} feed('1') @@ -822,7 +822,7 @@ describe('ui/ext_messages', function() {1:~ }| {1:^~ }| ]], messages={ - {content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Helli"\nType number and <Enter> or click with mouse (empty cancels): ' } }, kind = ""}, + {content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Helli"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""}, { content = { { "1" } }, kind = "" } }} diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index fcf6926433..f73d051857 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -429,6 +429,15 @@ screen:redraw_debug() to show all intermediate screen states. ]]) extstate.win_viewport = nil end + if expected.float_pos then + expected.float_pos = deepcopy(expected.float_pos) + for _, v in pairs(expected.float_pos) do + if not v.external and v[7] == nil then + v[7] = 50 + end + end + end + -- Convert assertion errors into invalid screen state descriptions. for _, k in ipairs(concat_tables(ext_keys, {'mode', 'mouse_enabled'})) do -- Empty states are considered the default and need not be mentioned. @@ -1287,6 +1296,11 @@ function Screen:get_snapshot(attrs, ignore) end local function fmt_ext_state(name, state) + local function remove_all_metatables(item, path) + if path[#path] ~= inspect.METATABLE then + return item + end + end if name == "win_viewport" then local str = "{\n" for k,v in pairs(state) do @@ -1295,13 +1309,18 @@ local function fmt_ext_state(name, state) ..", curcol = "..v.curcol.."};\n") end return str .. "}" - else - -- TODO(bfredl): improve formatting of more states - local function remove_all_metatables(item, path) - if path[#path] ~= inspect.METATABLE then - return item + elseif name == "float_pos" then + local str = "{\n" + for k,v in pairs(state) do + str = str.." ["..k.."] = {{id = "..v[1].id.."}" + for i = 2, #v do + str = str..", "..inspect(v[i]) end + str = str .. "};\n" end + return str .. "}" + else + -- TODO(bfredl): improve formatting of more states return inspect(state,{process=remove_all_metatables}) end end |