aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/highlight_spec.lua95
-rw-r--r--test/functional/api/vim_spec.lua38
-rw-r--r--test/functional/autoread/focus_spec.lua7
-rw-r--r--test/functional/core/job_spec.lua31
-rw-r--r--test/functional/eval/null_spec.lua29
-rw-r--r--test/functional/eval/writefile_spec.lua10
-rw-r--r--test/functional/legacy/packadd_spec.lua2
-rw-r--r--test/functional/lua/buffer_updates_spec.lua207
-rw-r--r--test/functional/lua/vim_spec.lua16
-rw-r--r--test/functional/plugin/health_spec.lua2
-rw-r--r--test/functional/plugin/lsp_spec.lua64
-rw-r--r--test/functional/terminal/buffer_spec.lua7
-rw-r--r--test/functional/treesitter/highlight_spec.lua2
-rw-r--r--test/functional/treesitter/language_spec.lua2
-rw-r--r--test/functional/treesitter/parser_spec.lua201
-rw-r--r--test/functional/ui/cmdline_spec.lua13
-rw-r--r--test/functional/ui/decorations_spec.lua163
-rw-r--r--test/functional/ui/float_spec.lua518
-rw-r--r--test/functional/ui/messages_spec.lua6
-rw-r--r--test/functional/ui/screen.lua29
-rw-r--r--test/functional/ui/searchhl_spec.lua14
-rw-r--r--test/functional/ui/sign_spec.lua18
-rw-r--r--test/helpers.lua6
23 files changed, 1393 insertions, 87 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 3db44f3f11..6926022ee3 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -193,6 +193,44 @@ describe('API', function()
eq('', nvim('exec', 'echo', true))
eq('foo 42', nvim('exec', 'echo "foo" 42', true))
end)
+
+ it('displays messages when output=false', function()
+ local screen = Screen.new(40, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ })
+ meths.exec("echo 'hello'", false)
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ hello |
+ ]]}
+ end)
+
+ it('does\'t display messages when output=true', function()
+ local screen = Screen.new(40, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ })
+ meths.exec("echo 'hello'", true)
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end)
end)
describe('nvim_command', function()
diff --git a/test/functional/autoread/focus_spec.lua b/test/functional/autoread/focus_spec.lua
index 1d52e9948f..3f9a0ad09b 100644
--- a/test/functional/autoread/focus_spec.lua
+++ b/test/functional/autoread/focus_spec.lua
@@ -9,6 +9,7 @@ local feed_data = thelpers.feed_data
if helpers.pending_win32(pending) then return end
describe('autoread TUI FocusGained/FocusLost', function()
+ local f1 = 'xtest-foo'
local screen
before_each(function()
@@ -17,8 +18,12 @@ describe('autoread TUI FocusGained/FocusLost', function()
..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]')
end)
+ teardown(function()
+ os.remove(f1)
+ end)
+
it('external file change', function()
- local path = 'xtest-foo'
+ local path = f1
local expected_addition = [[
line 1
line 2
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index b59d87eb12..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
@@ -963,8 +989,10 @@ describe('jobs', function()
return rv
end
+ local j
local function send(str)
- nvim('command', 'call jobsend(j, "'..str..'")')
+ -- check no nvim_chan_free double free with pty job (#14198)
+ meths.chan_send(j, str)
end
before_each(function()
@@ -979,6 +1007,7 @@ describe('jobs', function()
nvim('command', 'let g:job_opts.pty = 1')
nvim('command', 'let exec = [expand("<cfile>:p")]')
nvim('command', "let j = jobstart(exec, g:job_opts)")
+ j = eval'j'
eq('tty ready', next_chunk())
end)
diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua
index fa8f7d873f..8f0041ff27 100644
--- a/test/functional/eval/null_spec.lua
+++ b/test/functional/eval/null_spec.lua
@@ -14,7 +14,8 @@ describe('NULL', function()
clear()
command('let L = v:_null_list')
command('let D = v:_null_dict')
- command('let S = $XXX_NONEXISTENT_VAR_XXX')
+ command('let S = v:_null_string')
+ command('let V = $XXX_NONEXISTENT_VAR_XXX')
end)
local tmpfname = 'Xtest-functional-viml-null'
after_each(function()
@@ -72,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, {})
@@ -95,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, {}})
@@ -129,6 +131,7 @@ describe('NULL', function()
null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, 0)
null_test('is accepted by :cexpr', 'cexpr L', 0)
null_test('is accepted by :lexpr', 'lexpr L', 0)
+ null_expr_test('does not crash execute()', 'execute(L)', 0, '')
end)
describe('dict', function()
it('does not crash when indexing NULL dict', function()
@@ -142,4 +145,26 @@ describe('NULL', function()
null_expr_test('makes map() return v:_null_dict', 'map(D, "v:val") is# D', 0, 1)
null_expr_test('makes filter() return v:_null_dict', 'filter(D, "1") is# D', 0, 1)
end)
+ describe('string', function()
+ null_test('does not crash :echomsg', 'echomsg S', 0)
+ 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('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, '')
+ null_expr_test('does not crash getfperm()', 'getfperm(S)', 0, '')
+ null_expr_test('does not crash getfsize()', 'getfsize(S)', 0, -1)
+ null_expr_test('does not crash getftime()', 'getftime(S)', 0, -1)
+ null_expr_test('does not crash getftype()', 'getftype(S)', 0, '')
+ null_expr_test('does not crash glob()', 'glob(S)', 0, '')
+ null_expr_test('does not crash globpath()', 'globpath(S, S)', 0, '')
+ 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)
+ end)
end)
diff --git a/test/functional/eval/writefile_spec.lua b/test/functional/eval/writefile_spec.lua
index 0bb7523d7e..356680ba7c 100644
--- a/test/functional/eval/writefile_spec.lua
+++ b/test/functional/eval/writefile_spec.lua
@@ -59,6 +59,16 @@ describe('writefile()', function()
eq('\n', read_file(fname))
end)
+ it('writes list with a null string to a file', function()
+ eq(0, exc_exec(
+ ('call writefile([v:_null_string], "%s", "b")'):format(
+ fname)))
+ eq('', read_file(fname))
+ eq(0, exc_exec(('call writefile([v:_null_string], "%s")'):format(
+ fname)))
+ eq('\n', read_file(fname))
+ end)
+
it('appends to a file', function()
eq(nil, read_file(fname))
eq(0, funcs.writefile({'abc', 'def', 'ghi'}, fname))
diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua
index 609f825177..486a1fe471 100644
--- a/test/functional/legacy/packadd_spec.lua
+++ b/test/functional/legacy/packadd_spec.lua
@@ -267,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 6d7d9b4d8b..54e10fabd6 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -461,6 +461,36 @@ describe('lua: nvim_buf_attach on_bytes', function()
}
end)
+ it("deleting lines", function()
+ local check_events = setup_eventcheck(verify, origlines)
+
+ feed("dd")
+
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 0, 0, 1, 0, 16, 0, 0, 0 };
+ }
+
+ feed("d2j")
+
+ check_events {
+ { "test1", "bytes", 1, 4, 0, 0, 0, 3, 0, 48, 0, 0, 0 };
+ }
+
+ feed("ld<c-v>2j")
+
+ check_events {
+ { "test1", "bytes", 1, 5, 0, 1, 1, 0, 1, 1, 0, 0, 0 };
+ { "test1", "bytes", 1, 5, 1, 1, 16, 0, 1, 1, 0, 0, 0 };
+ { "test1", "bytes", 1, 5, 2, 1, 31, 0, 1, 1, 0, 0, 0 };
+ }
+
+ feed("vjwd")
+
+ check_events {
+ { "test1", "bytes", 1, 10, 0, 1, 1, 1, 9, 23, 0, 0, 0 };
+ }
+ end)
+
it("changing lines", function()
local check_events = setup_eventcheck(verify, origlines)
@@ -537,20 +567,65 @@ describe('lua: nvim_buf_attach on_bytes', function()
end)
it('inccomand=nosplit and substitute', function()
- local check_events = setup_eventcheck(verify, {"abcde"})
+ local check_events = setup_eventcheck(verify,
+ {"abcde", "12345"})
meths.set_option('inccommand', 'nosplit')
- feed ':%s/bcd/'
+ -- linewise substitute
+ feed(':%s/bcd/')
check_events {
{ "test1", "bytes", 1, 3, 0, 1, 1, 0, 3, 3, 0, 0, 0 };
{ "test1", "bytes", 1, 5, 0, 1, 1, 0, 0, 0, 0, 3, 3 };
}
- feed 'a'
+ feed('a')
check_events {
{ "test1", "bytes", 1, 3, 0, 1, 1, 0, 3, 3, 0, 1, 1 };
{ "test1", "bytes", 1, 5, 0, 1, 1, 0, 1, 1, 0, 3, 3 };
}
+
+ feed("<esc>")
+
+ -- splitting lines
+ feed([[:%s/abc/\r]])
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 0, 0, 0, 3, 3, 1, 0, 1 };
+ { "test1", "bytes", 1, 6, 0, 0, 0, 1, 0, 1, 0, 3, 3 };
+ }
+
+ feed("<esc>")
+ -- multi-line regex
+ feed([[:%s/de\n123/a]])
+
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 3, 3, 1, 3, 6, 0, 1, 1 };
+ { "test1", "bytes", 1, 6, 0, 3, 3, 0, 1, 1, 1, 3, 6 };
+ }
+
+ feed("<esc>")
+ -- replacing with unicode
+ feed(":%s/b/β†’")
+
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 3, 3 };
+ { "test1", "bytes", 1, 5, 0, 1, 1, 0, 3, 3, 0, 1, 1 };
+ }
+
+ feed("<esc>")
+ -- replacing with escaped characters
+ feed([[:%s/b/\\]])
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 1, 1 };
+ { "test1", "bytes", 1, 5, 0, 1, 1, 0, 1, 1, 0, 1, 1 };
+ }
+
+ feed("<esc>")
+ -- replacing with expression register
+ feed([[:%s/b/\=5+5]])
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 2, 2 };
+ { "test1", "bytes", 1, 5, 0, 1, 1, 0, 2, 2, 0, 1, 1 };
+ }
end)
it('nvim_buf_set_text insert', function()
@@ -670,7 +745,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
command("set noet")
command("set ts=4")
command("set sw=2")
- command("set sts=2")
+ command("set sts=4")
local check_events = setup_eventcheck(verify, {'asdfasdf'})
@@ -689,6 +764,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
{ "test1", "bytes", 1, 7, 0, 0, 0, 0, 4, 4, 0, 1, 1 },
}
+
feed("<esc>u")
check_events {
{ "test1", "bytes", 1, 8, 0, 0, 0, 0, 1, 1, 0, 4, 4 },
@@ -728,6 +804,29 @@ describe('lua: nvim_buf_attach on_bytes', function()
{ "test1", "bytes", 1, 29, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
{ "test1", "bytes", 1, 31, 0, 0, 0, 0, 4, 4, 0, 1, 1 };
}
+
+ -- inserting tab after other tabs
+ command("set sw=4")
+ feed("<esc>0a<tab>")
+ check_events {
+ { "test1", "bytes", 1, 32, 0, 1, 1, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 33, 0, 2, 2, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 34, 0, 3, 3, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 35, 0, 4, 4, 0, 0, 0, 0, 1, 1 };
+ { "test1", "bytes", 1, 36, 0, 1, 1, 0, 4, 4, 0, 1, 1 };
+ }
+ end)
+
+ it("retab", function()
+ command("set noet")
+ command("set ts=4")
+
+ local check_events = setup_eventcheck(verify, {" asdf"})
+ command("retab 8")
+
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 0, 0, 0, 7, 7, 0, 9, 9 };
+ }
end)
it("sends events when undoing with undofile", function()
@@ -802,6 +901,106 @@ describe('lua: nvim_buf_attach on_bytes', function()
end)
+ it(":luado", function()
+ local check_events = setup_eventcheck(verify, {"abc", "12345"})
+
+ command(".luado return 'a'")
+
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 0, 0, 0, 3, 3, 0, 1, 1 };
+ }
+
+ command("luado return 10")
+
+ check_events {
+ { "test1", "bytes", 1, 4, 0, 0, 0, 0, 1, 1, 0, 2, 2 };
+ { "test1", "bytes", 1, 5, 1, 0, 3, 0, 5, 5, 0, 2, 2 };
+ }
+
+ end)
+
+ it("flushes deleted bytes on move", function()
+ local check_events = setup_eventcheck(verify, {"AAA", "BBB", "CCC", "DDD"})
+
+ feed(":.move+1<cr>")
+
+ check_events {
+ { "test1", "bytes", 1, 5, 0, 0, 0, 1, 0, 4, 0, 0, 0 };
+ { "test1", "bytes", 1, 5, 1, 0, 4, 0, 0, 0, 1, 0, 4 };
+ }
+
+ feed("jd2j")
+
+ check_events {
+ { "test1", "bytes", 1, 6, 2, 0, 8, 2, 0, 8, 0, 0, 0 };
+ }
+ 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",
+ "CCC",
+ "DDD",
+ "EEE",
+ "FFF"})
+ funcs.setreg("a", "___")
+ feed([[gg0l<c-v>3jl"ap]])
+
+ check_events {
+ { "test1", "bytes", 1, 3, 0, 1, 1, 0, 2, 2, 0, 0, 0 };
+ { "test1", "bytes", 1, 3, 1, 1, 3, 0, 2, 2, 0, 0, 0 };
+ { "test1", "bytes", 1, 3, 2, 1, 5, 0, 2, 2, 0, 0, 0 };
+ { "test1", "bytes", 1, 3, 3, 1, 7, 0, 2, 2, 0, 0, 0 };
+ { "test1", "bytes", 1, 5, 0, 1, 1, 0, 0, 0, 0, 3, 3 };
+ { "test1", "bytes", 1, 6, 1, 1, 6, 0, 0, 0, 0, 3, 3 };
+ { "test1", "bytes", 1, 7, 2, 1, 11, 0, 0, 0, 0, 3, 3 };
+ { "test1", "bytes", 1, 8, 3, 1, 16, 0, 0, 0, 0, 3, 3 };
+ }
+ 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..6566da4807 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 [[
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index a78ed07876..85c67be8f9 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -118,7 +118,7 @@ describe('health.vim', function()
Error = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
Heading = { bold=true, foreground=Screen.colors.Magenta },
Heading2 = { foreground = Screen.colors.SlateBlue },
- Bar = { foreground=Screen.colors.Purple },
+ Bar = { foreground = 0x6a0dad },
Bullet = { bold=true, foreground=Screen.colors.Brown },
})
command("checkhealth foo success1")
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 6d3af115fa..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
@@ -29,6 +30,16 @@ teardown(function()
os.remove(fake_lsp_logfile)
end)
+local function clear_notrace()
+ -- problem: here be dragons
+ -- solution: don't look for dragons to closely
+ clear {env={
+ NVIM_LUA_NOTRACK="1";
+ VIMRUNTIME=os.getenv"VIMRUNTIME";
+ }}
+end
+
+
local function fake_lsp_server_setup(test_name, timeout_ms, options)
exec_lua([=[
lsp = require('vim.lsp')
@@ -36,6 +47,7 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options)
TEST_RPC_CLIENT_ID = lsp.start_client {
cmd_env = {
NVIM_LOG_FILE = logfile;
+ NVIM_LUA_NOTRACK = "1";
};
cmd = {
vim.v.progpath, '-Es', '-u', 'NONE', '--headless',
@@ -65,7 +77,7 @@ end
local function test_rpc_server(config)
if config.test_name then
- clear()
+ clear_notrace()
fake_lsp_server_setup(config.test_name, config.timeout_ms or 1e3, config.options)
end
local client = setmetatable({}, {
@@ -120,7 +132,7 @@ end
describe('LSP', function()
describe('server_name specified', function()
before_each(function()
- clear()
+ clear_notrace()
-- Run an instance of nvim on the file which contains our "scripts".
-- Pass TEST_NAME to pick the script.
local test_name = "basic_init"
@@ -250,6 +262,10 @@ describe('LSP', function()
end)
it('should succeed with manual shutdown', function()
+ if 'openbsd' == helpers.uname() then
+ pending('hangs the build on openbsd #14028, re-enable with freeze timeout #14204')
+ return
+ end
local expected_callbacks = {
{NIL, "shutdown", {}, 1, NIL};
{NIL, "test", {}, 1};
@@ -314,7 +330,7 @@ describe('LSP', function()
}
end)
it('workspace/configuration returns NIL per section if client was started without config.settings', function()
- clear()
+ clear_notrace()
fake_lsp_server_setup('workspace/configuration no settings')
eq({ NIL, NIL, }, exec_lua [[
local params = {
@@ -941,7 +957,7 @@ end)
describe('LSP', function()
before_each(function()
- clear()
+ clear_notrace()
end)
local function make_edit(y_0, x_0, y_1, x_1, text)
@@ -1109,14 +1125,14 @@ describe('LSP', function()
'2nd line of θ―­text';
}, buf_lines(target_bufnr))
end)
- it('correctly goes ahead with the edit if the version is vim.NIL', function()
- -- we get vim.NIL when we decode json null value.
- local json = exec_lua[[
- return vim.fn.json_decode("{ \"a\": 1, \"b\": null }")
- ]]
- eq(json.b, exec_lua("return vim.NIL"))
-
- exec_lua('vim.lsp.util.apply_text_document_edit(...)', text_document_edit(exec_lua("return vim.NIL")))
+ it('always accepts edit with version = 0', function()
+ exec_lua([[
+ local args = {...}
+ local bufnr = select(1, ...)
+ local text_edit = select(2, ...)
+ vim.lsp.util.buf_versions[bufnr] = 10
+ vim.lsp.util.apply_text_document_edit(text_edit)
+ ]], target_bufnr, text_document_edit(0))
eq({
'First β†₯ 🀦 πŸ¦„ line of text';
'2nd line of θ―­text';
@@ -1377,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={} },
}
@@ -1392,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={} } } } } },
}
@@ -1863,6 +1879,18 @@ describe('LSP', function()
eq(4, pos.col)
eq('Γ₯', exec_lua[[return vim.fn.expand('<cword>')]])
end)
+
+ it('adds current position to jumplist before jumping', function()
+ funcs.nvim_win_set_buf(0, target_bufnr)
+ local mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ eq({ 1, 0 }, mark)
+
+ funcs.nvim_win_set_cursor(0, {2, 3})
+ jump(location(0, 9, 0, 9))
+
+ mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ eq({ 2, 3 }, mark)
+ end)
end)
describe('lsp.util._make_floating_popup_size', function()
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 209537831f..c61bf108cb 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -258,6 +258,13 @@ describe(':terminal buffer', function()
it('handles wqall', function()
eq('Vim(wqall):E948: Job still running', exc_exec('wqall'))
end)
+
+ it('does not segfault when pasting empty buffer #13955', function()
+ feed_command('terminal')
+ feed('<c-\\><c-n>')
+ feed_command('put a') -- buffer a is empty
+ helpers.assert_alive()
+ end)
end)
describe('No heap-buffer-overflow when using', function()
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index d80d0fdbaf..05e0c5fe2c 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -445,7 +445,7 @@ describe('treesitter highlighting', function()
exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", {
- queries = {c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}
+ injections = {c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}
})
local highlighter = vim.treesitter.highlighter
test_hl = highlighter.new(parser, {queries = {c = hl_query}})
diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua
index a5801271cb..afb17dd2cf 100644
--- a/test/functional/treesitter/language_spec.lua
+++ b/test/functional/treesitter/language_spec.lua
@@ -45,7 +45,7 @@ describe('treesitter API', function()
return {keys, lang.fields, symbols}
]]))
- eq({fields=true, symbols=true}, keys)
+ eq({fields=true, symbols=true, _abi_version=true}, keys)
local fset = {}
for _,f in pairs(fields) do
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index f99362fbdf..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)
@@ -468,7 +562,7 @@ int x = INT_MAX;
it("should inject a language", function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
- queries = {
+ injections = {
c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}})
]])
@@ -489,7 +583,7 @@ int x = INT_MAX;
it("should inject a language", function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
- queries = {
+ injections = {
c = "(preproc_def (preproc_arg) @c @combined) (preproc_function_def value: (preproc_arg) @c @combined)"}})
]])
@@ -506,11 +600,39 @@ int x = INT_MAX;
end)
end)
+ describe("when providing parsing information through a directive", function()
+ it("should inject a language", function()
+ exec_lua([=[
+ vim.treesitter.add_directive("inject-clang!", function(match, _, _, pred, metadata)
+ metadata.language = "c"
+ metadata.combined = true
+ metadata.content = pred[2]
+ end)
+
+ parser = vim.treesitter.get_parser(0, "c", {
+ injections = {
+ c = "(preproc_def ((preproc_arg) @_c (#inject-clang! @_c)))" ..
+ "(preproc_function_def value: ((preproc_arg) @_a (#inject-clang! @_a)))"}})
+ ]=])
+
+ eq("table", exec_lua("return type(parser:children().c)"))
+ eq(2, exec_lua("return #parser:children().c:trees()"))
+ eq({
+ {0, 0, 7, 0}, -- root tree
+ {3, 14, 5, 18}, -- VALUE 123
+ -- VALUE1 123
+ -- VALUE2 123
+ {1, 26, 2, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+ -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
+ }, get_ranges())
+ end)
+ end)
+
describe("when using the offset directive", function()
it("should shift the range by the directive amount", function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
- queries = {
+ injections = {
c = "(preproc_def ((preproc_arg) @c (#offset! @c 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @c)"}})
]])
@@ -538,7 +660,7 @@ int x = INT_MAX;
it("should return the correct language tree", function()
local result = exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
- queries = { c = "(preproc_def (preproc_arg) @c)"}})
+ injections = { c = "(preproc_def (preproc_arg) @c)"}})
local sub_tree = parser:language_for_range({1, 18, 1, 19})
@@ -571,28 +693,55 @@ int x = INT_MAX;
eq(result, "value")
end)
- end)
-
- describe("when setting for a capture match", function()
- it("should set/get the data correctly", function()
- insert([[
- int x = 3;
- ]])
-
- local result = exec_lua([[
- local result
- query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value"))')
- parser = vim.treesitter.get_parser(0, "c")
-
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
- result = metadata[pattern].key
- end
-
- return result
- ]])
-
- eq(result, "value")
+ describe("when setting a key on a capture", function()
+ it("it should create the nested table", function()
+ insert([[
+ int x = 3;
+ ]])
+
+ local result = exec_lua([[
+ local query = require("vim.treesitter.query")
+ local value
+
+ query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value"))')
+ parser = vim.treesitter.get_parser(0, "c")
+
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for _, nested_tbl in pairs(metadata) do
+ return nested_tbl.key
+ end
+ end
+ ]])
+
+ eq(result, "value")
+ end)
+
+ it("it should not overwrite the nested table", function()
+ insert([[
+ int x = 3;
+ ]])
+
+ local result = exec_lua([[
+ local query = require("vim.treesitter.query")
+ local result
+
+ query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value") (#set! @number "key2" "value2"))')
+ parser = vim.treesitter.get_parser(0, "c")
+
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for _, nested_tbl in pairs(metadata) do
+ return nested_tbl
+ end
+ end
+ ]])
+ local expected = {
+ ["key"] = "value",
+ ["key2"] = "value2",
+ }
+
+ eq(expected, result)
+ end)
end)
end)
end)
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index 21c01b3458..0ea8bab957 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 assert_alive = helpers.assert_alive
local function new_screen(opt)
local screen = Screen.new(25, 5)
@@ -758,6 +759,7 @@ local function test_cmdline(linegrid)
end)
it("doesn't send invalid events when aborting mapping #10000", function()
+ command('set notimeout')
command('cnoremap ab c')
feed(':xa')
@@ -842,3 +844,14 @@ describe('cmdline redraw', function()
]], unchanged=true}
end)
end)
+
+describe("cmdline height", function()
+ it("does not crash resized screen #14263", function()
+ clear()
+ local screen = Screen.new(25, 10)
+ screen:attach()
+ command('set cmdheight=9999')
+ screen:try_resize(25, 5)
+ assert_alive()
+ end)
+end)
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 295a54aec8..98aafd8757 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -29,6 +29,7 @@ describe('decorations providers', function()
[10] = {italic = true, background = Screen.colors.Magenta};
[11] = {foreground = Screen.colors.Red, background = tonumber('0x005028')};
[12] = {foreground = tonumber('0x990000')};
+ [13] = {background = Screen.colors.LightBlue};
}
end)
@@ -65,6 +66,18 @@ describe('decorations providers', function()
expect_events(expected, actual, "beam trace")
end
+ it('does not OOM when inserting, rather than appending, to the decoration provider vector', function()
+ -- Add a dummy decoration provider with a larger ns id than what setup_provider() creates.
+ -- This forces get_decor_provider() to insert into the providers vector,
+ -- rather than append, which used to spin in an infinite loop allocating
+ -- memory until nvim crashed/was killed.
+ setup_provider([[
+ local ns2 = a.nvim_create_namespace "ns2"
+ a.nvim_set_decoration_provider(ns2, {})
+ ]])
+ helpers.assert_alive()
+ end)
+
it('leave a trace', function()
insert(mulholland)
@@ -331,10 +344,70 @@ describe('decorations providers', function()
|
]]}
end)
+
+ it('can have virtual text of the style: right_align', function()
+ insert(mulholland)
+ setup_provider [[
+ local hl = a.nvim_get_hl_id_by_name "ErrorMsg"
+ local test_ns = a.nvim_create_namespace "mulholland"
+ function on_do(event, ...)
+ if event == "line" then
+ local win, buf, line = ...
+ a.nvim_buf_set_extmark(buf, test_ns, line, 0, {
+ virt_text = {{'+'}, {string.rep(' ', line+1), 'ErrorMsg'}};
+ virt_text_pos='right_align';
+ ephemeral = true;
+ })
+ end
+ end
+ ]]
+
+ screen:expect{grid=[[
+ // just to see if there was an acciden+{2: }|
+ // on Mulholland Drive +{2: }|
+ try_start(); +{2: }|
+ bufref_T save_buf; +{2: }|
+ switch_buffer(&save_buf, buf); +{2: }|
+ posp = getmark(mark, false); +{2: }|
+ restore_buffer(&save_buf);^ +{2: }|
+ |
+ ]]}
+ end)
+
+ it('can highlight beyond EOL', function()
+ insert(mulholland)
+ setup_provider [[
+ local test_ns = a.nvim_create_namespace "veberod"
+ function on_do(event, ...)
+ if event == "line" then
+ local win, buf, line = ...
+ if string.find(a.nvim_buf_get_lines(buf, line, line+1, true)[1], "buf") then
+ a.nvim_buf_set_extmark(buf, test_ns, line, 0, {
+ end_line = line+1;
+ hl_group = 'DiffAdd';
+ hl_eol = true;
+ ephemeral = true;
+ })
+ end
+ end
+ end
+ ]]
+
+ screen:expect{grid=[[
+ // just to see if there was an accident |
+ // on Mulholland Drive |
+ try_start(); |
+ {13:bufref_T save_buf; }|
+ {13:switch_buffer(&save_buf, buf); }|
+ posp = getmark(mark, false); |
+ {13:restore_buffer(&save_buf);^ }|
+ |
+ ]]}
+ end)
end)
describe('extmark decorations', function()
- local screen
+ local screen, ns
before_each( function()
clear()
screen = Screen.new(50, 15)
@@ -365,6 +438,8 @@ describe('extmark decorations', function()
[23] = {foreground = Screen.colors.Magenta1, background = Screen.colors.LightGrey};
[24] = {bold = true};
}
+
+ ns = meths.create_namespace 'test'
end)
local example_text = [[
@@ -385,7 +460,6 @@ end]]
insert(example_text)
feed 'gg'
- local ns = meths.create_namespace 'test'
for i = 1,9 do
meths.buf_set_extmark(0, ns, i, 0, { virt_text={{'|', 'LineNr'}}, virt_text_pos='overlay'})
if i == 3 or (i >= 6 and i <= 9) then
@@ -452,7 +526,6 @@ end]]
it('can have virtual text of overlay position and styling', function()
insert(example_text)
feed 'gg'
- local ns = meths.create_namespace 'test'
command 'set ft=lua'
command 'syntax on'
@@ -540,4 +613,88 @@ end]]
{24:-- VISUAL LINE --} |
]]}
end)
+
+ it('can have virtual text of fixed win_col position', function()
+ insert(example_text)
+ feed 'gg'
+ meths.buf_set_extmark(0, ns, 1, 0, { virt_text={{'Very', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ meths.buf_set_extmark(0, ns, 2, 10, { virt_text={{'Much', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ meths.buf_set_extmark(0, ns, 3, 15, { virt_text={{'Error', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ meths.buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_win_col=4, hl_mode='blend'})
+
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ local text, hl_id_cell, cou{4:Very} unpack(item) |
+ if hl_id_cell ~= nil then {4:Much} |
+ hl_id = hl_id_cell {4:Error} |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ {1:-} cell.text = text |
+ cell.hl_id = hl_id |
+ colpos = colpos+1 |
+ end |
+ end |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed '3G12|i<cr><esc>'
+ screen:expect{grid=[[
+ for _,item in ipairs(items) do |
+ local text, hl_id_cell, cou{4:Very} unpack(item) |
+ if hl_i {4:Much} |
+ ^d_cell ~= nil then |
+ hl_id = hl_id_cell {4:Error} |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ {1:-} cell.text = text |
+ cell.hl_id = hl_id |
+ colpos = colpos+1 |
+ end |
+ end |
+ {1:~ }|
+ |
+ ]]}
+
+ feed 'u:<cr>'
+ screen:expect{grid=[[
+ for _,item in ipairs(items) do |
+ local text, hl_id_cell, cou{4:Very} unpack(item) |
+ if hl_i^d_cell ~= nil then {4:Much} |
+ hl_id = hl_id_cell {4:Error} |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ {1:-} cell.text = text |
+ cell.hl_id = hl_id |
+ colpos = colpos+1 |
+ end |
+ end |
+ {1:~ }|
+ {1:~ }|
+ : |
+ ]]}
+
+ feed '8|i<cr><esc>'
+ screen:expect{grid=[[
+ for _,item in ipairs(items) do |
+ local text, hl_id_cell, cou{4:Very} unpack(item) |
+ if |
+ ^hl_id_cell ~= nil then {4:Much} |
+ hl_id = hl_id_cell {4:Error} |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ {1:-} cell.text = text |
+ cell.hl_id = hl_id |
+ colpos = colpos+1 |
+ end |
+ end |
+ {1:~ }|
+ |
+ ]]}
+ end)
end)
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 664b8e7ab7..f3b840da21 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -42,6 +42,10 @@ describe('float window', function()
[20] = {bold = true, foreground = Screen.colors.Brown},
[21] = {background = Screen.colors.Gray90},
[22] = {background = Screen.colors.LightRed},
+ [23] = {foreground = Screen.colors.Black, background = Screen.colors.White};
+ [24] = {foreground = Screen.colors.Black, background = Screen.colors.Grey80};
+ [25] = {blend = 100, background = Screen.colors.Gray0};
+ [26] = {blend = 80, background = Screen.colors.Gray0};
}
it('behavior', function()
@@ -58,6 +62,27 @@ describe('float window', function()
eq(1000, funcs.win_getid())
end)
+ it('win_execute() should work' , function()
+ local buf = meths.create_buf(false, false)
+ 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)
+
+ it('win_execute() call commands that not allowed' , function()
+ local buf = meths.create_buf(false, false)
+ meths.buf_set_lines(buf, 0, -1, true, {'the floatwin'})
+ local win = meths.open_win(buf, true, {relative='win', width=16, height=1, row=0, col=10})
+ eq(pcall_err(funcs.win_execute, win, 'close'), 'Vim(close):E37: No write since last change (add ! to override)')
+ eq(pcall_err(funcs.win_execute, win, 'bdelete'), 'Vim(bdelete):E89: No write since last change for buffer 2 (add ! to override)')
+ funcs.win_execute(win, 'bwipe!')
+ end)
+
it('closed immediately by autocmd #11383', function()
eq('Error executing lua: [string "<nvim>"]:0: Window was closed immediately',
pcall_err(exec_lua, [[
@@ -644,7 +669,6 @@ describe('float window', function()
end
meths.win_set_config(win, {border="single"})
-
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -687,9 +711,51 @@ describe('float window', function()
]]}
end
+ meths.win_set_config(win, {border="solid"})
+ 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 5
+ {5: }|
+ {5: }{1: halloj! }{5: }|
+ {5: }{1: BORDAA }{5: }|
+ {5: }|
+ ]], float_pos={
+ [5] = { { id = 1002 }, "NW", 1, 2, 5, true }
+ }, win_viewport={
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }{5: }{0: }|
+ {0:~ }{5: }{1: halloj! }{5: }{0: }|
+ {0:~ }{5: }{1: BORDAA }{5: }{0: }|
+ {0:~ }{5: }{0: }|
+ |
+ ]]}
+ end
+
-- support: ascii char, UTF-8 char, composed char, highlight per char
meths.win_set_config(win, {border={"x", {"Γ₯", "ErrorMsg"}, {"\\"}, {"n̈̊", "Search"}}})
-
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -710,10 +776,10 @@ describe('float window', function()
## grid 3
|
## grid 5
- {5:xΓ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯\}|
- {5:n̈̊}{1: halloj! }{5:n̈̊}|
- {5:n̈̊}{1: BORDAA }{5:n̈̊}|
- {5:\Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯x}|
+ {5:x}{7:Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯}{5:\}|
+ {17:n̈̊}{1: halloj! }{17:n̈̊}|
+ {17:n̈̊}{1: BORDAA }{17:n̈̊}|
+ {5:\}{7:Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯Γ₯}{5:x}|
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
@@ -772,6 +838,148 @@ describe('float window', function()
|
]]}
end
+
+ meths.win_set_config(win, {border={"", "", "", ">", "", "", "", "<"}})
+ 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 5
+ {5:<}{1: halloj! }{5:>}|
+ {5:<}{1: BORDAA }{5:>}|
+ ]], float_pos={
+ [5] = { { id = 1002 }, "NW", 1, 2, 5, true }
+ }, win_viewport={
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }{5:<}{1: halloj! }{5:>}{0: }|
+ {0:~ }{5:<}{1: BORDAA }{5:>}{0: }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end
+
+ insert [[
+ neeed some dummy
+ background text
+ to show the effect
+ of color blending
+ of border shadow
+ ]]
+
+ meths.win_set_config(win, {border="shadow"})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ neeed some dummy |
+ background text |
+ to show the effect |
+ of color blending |
+ of border shadow |
+ ^ |
+ ## grid 3
+ |
+ ## grid 5
+ {1: halloj! }{25: }|
+ {1: BORDAA }{26: }|
+ {25: }{26: }|
+ ]], float_pos={
+ [5] = { { id = 1002 }, "NW", 1, 2, 5, true }
+ }, win_viewport={
+ [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 5, curcol = 0};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ }}
+ else
+ screen:expect{grid=[[
+ neeed some dummy |
+ background text |
+ to {1: halloj! }{23:e}ffect |
+ of {1: BORDAA }{24:n}ding |
+ of {23:b}{24:order sha}dow |
+ ^ |
+ |
+ ]]}
+ end
+ end)
+
+ it('terminates border on edge of viewport when window extends past viewport', function()
+ local buf = meths.create_buf(false, false)
+ meths.open_win(buf, false, {relative='editor', width=40, height=7, row=0, col=0, border="single"})
+ 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
+ {5:β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”}|
+ {5:β”‚}{1: }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜}|
+ ]], float_pos={
+ [4] = { { id = 1001 }, "NW", 1, 0, 0, true }
+ }, 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};
+ }}
+ else
+ screen:expect{grid=[[
+ {5:^β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”}|
+ {5:β”‚}{1: }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β”‚}{2:~ }{5:β”‚}|
+ {5:β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜}|
+ |
+ ]]}
+ end
end)
it('with border show popupmenu', function()
@@ -835,7 +1043,6 @@ describe('float window', function()
end
feed 'i<c-x><c-p>'
-
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -873,12 +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};
@@ -2555,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([[
@@ -2642,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([[
@@ -2904,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([[
@@ -2948,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([[
@@ -3063,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([[
@@ -5886,6 +6089,279 @@ describe('float window', function()
]])
end
end)
+
+ it("correctly orders multiple opened floats (current last)", function()
+ local buf = meths.create_buf(false,false)
+ local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ meths.win_set_option(win, "winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg")
+
+ 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:~ }|
+ ]], float_pos={
+ [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
+ }, 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};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }{7: }{0: }|
+ {0:~ }{7:~ }{0: }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end
+
+ exec_lua [[
+ local buf = vim.api.nvim_create_buf(false,false)
+ local win = vim.api.nvim_open_win(buf, false, {relative='editor', width=16, height=2, row=3, col=8})
+ vim.api.nvim_win_set_option(win, "winhl", "EndOfBuffer:Normal")
+ buf = vim.api.nvim_create_buf(false,false)
+ win = vim.api.nvim_open_win(buf, true, {relative='editor', width=12, height=2, row=4, col=10})
+ vim.api.nvim_win_set_option(win, "winhl", "Normal:Search,EndOfBuffer:Search")
+ ]]
+
+ 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:~ }|
+ ## grid 5
+ {1: }|
+ {1:~ }|
+ ## grid 6
+ {17:^ }|
+ {17:~ }|
+ ]], float_pos={
+ [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
+ [5] = { { id = 1002 }, "NW", 1, 3, 8, true };
+ [6] = { { id = 1003 }, "NW", 1, 4, 10, true };
+ }, 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:~ }|
+ {0:~ }{7: }{0: }|
+ {0:~ }{7:~ }{1: }{7: }{0: }|
+ {0:~ }{1:~ }{17:^ }{1: }{0: }|
+ {0:~ }{17:~ }{0: }|
+ |
+ ]]}
+ end
+ end)
+
+ it("correctly orders multiple opened floats (non-current last)", function()
+ local buf = meths.create_buf(false,false)
+ local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ meths.win_set_option(win, "winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg")
+
+ 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:~ }|
+ ]], float_pos={
+ [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
+ }, 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};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }{7: }{0: }|
+ {0:~ }{7:~ }{0: }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end
+
+ exec_lua [[
+ local buf = vim.api.nvim_create_buf(false,false)
+ local win = vim.api.nvim_open_win(buf, true, {relative='editor', width=12, height=2, row=4, col=10})
+ vim.api.nvim_win_set_option(win, "winhl", "Normal:Search,EndOfBuffer:Search")
+ buf = vim.api.nvim_create_buf(false,false)
+ win = vim.api.nvim_open_win(buf, false, {relative='editor', width=16, height=2, row=3, col=8})
+ vim.api.nvim_win_set_option(win, "winhl", "EndOfBuffer:Normal")
+ ]]
+
+ 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:~ }|
+ ## grid 5
+ {17:^ }|
+ {17:~ }|
+ ## grid 6
+ {1: }|
+ {1:~ }|
+ ]], float_pos={
+ [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
+ [5] = { { id = 1002 }, "NW", 1, 4, 10, true };
+ [6] = { { id = 1003 }, "NW", 1, 3, 8, true };
+ }, 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:~ }|
+ {0:~ }{7: }{0: }|
+ {0:~ }{7:~ }{1: }{7: }{0: }|
+ {0:~ }{1:~ }{17:^ }{1: }{0: }|
+ {0:~ }{17:~ }{0: }|
+ |
+ ]]}
+ 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 1fe3a4128e..72468392ee 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -456,6 +456,8 @@ describe('ui/ext_messages', function()
{1:~ }|
]], messages={
{kind="echomsg", content={{"stuff"}}},
+ }, showmode={
+ { "-- INSERT --", 3 }
}}
end)
@@ -809,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')
@@ -820,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
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index 656f613c6a..5540b3c2dc 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -507,7 +507,21 @@ describe('search highlighting', function()
{1:~ }|
:syntax keyword MyGroup special |
]])
+ end)
+ it('highlights entire pattern on :%g@a/b', function()
+ command('set inccommand=nosplit')
+ feed('ia/b/c<Esc>')
+ feed(':%g@a/b')
+ screen:expect([[
+ {3:a/b}/c |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :%g@a/b^ |
+ ]])
end)
end)
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index 1937102782..06c92a4b10 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -264,6 +264,24 @@ describe('Signs', function()
{0:~ }|
|
]]}
+ -- line deletion deletes signs.
+ command('2d')
+ screen:expect([[
+ {1:>>}XX{2: }{6: 1 }a |
+ XX{1:>>}WW{6: 2 }^c |
+ {2: }{6: 3 } |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
end)
it('auto-resize sign column with minimum size (#13783)', function()
diff --git a/test/helpers.lua b/test/helpers.lua
index 8dbd82cb8c..12d9f19187 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -365,7 +365,11 @@ function module.check_cores(app, force)
db_cmd = lldb_db_cmd
else
initial_path = '.'
- re = '/core[^/]*$'
+ if 'freebsd' == module.uname() then
+ re = '/nvim.core$'
+ else
+ re = '/core[^/]*$'
+ end
exc_re = { '^/%.deps$', '^/%'..deps_prefix()..'$', local_tmpdir, '^/%node_modules$' }
db_cmd = gdb_db_cmd
random_skip = true