aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/vim_spec.lua38
-rw-r--r--test/functional/api/window_spec.lua40
-rw-r--r--test/functional/autoread/focus_spec.lua7
-rw-r--r--test/functional/core/job_spec.lua5
-rw-r--r--test/functional/eval/null_spec.lua26
-rw-r--r--test/functional/eval/writefile_spec.lua10
-rw-r--r--test/functional/ex_cmds/dict_notifications_spec.lua75
-rw-r--r--test/functional/ex_cmds/excmd_spec.lua2
-rw-r--r--test/functional/legacy/011_autocommands_spec.lua2
-rw-r--r--test/functional/legacy/delete_spec.lua78
-rw-r--r--test/functional/legacy/packadd_spec.lua3
-rw-r--r--test/functional/lua/buffer_updates_spec.lua187
-rw-r--r--test/functional/plugin/health_spec.lua2
-rw-r--r--test/functional/plugin/lsp_spec.lua175
-rw-r--r--test/functional/terminal/buffer_spec.lua7
-rw-r--r--test/functional/treesitter/highlight_spec.lua100
-rw-r--r--test/functional/treesitter/language_spec.lua2
-rw-r--r--test/functional/treesitter/parser_spec.lua140
-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.lua436
-rw-r--r--test/functional/ui/messages_spec.lua2
-rw-r--r--test/functional/ui/searchhl_spec.lua14
-rw-r--r--test/functional/ui/sign_spec.lua18
-rw-r--r--test/functional/viml/errorlist_spec.lua13
-rw-r--r--test/helpers.lua6
26 files changed, 1406 insertions, 158 deletions
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/api/window_spec.lua b/test/functional/api/window_spec.lua
index 7471f50dbd..ceeb84cec9 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -347,4 +347,44 @@ describe('API/win', function()
eq('', funcs.getcmdwintype())
end)
end)
+
+ describe('hide', function()
+ it('can hide current window', function()
+ local oldwin = meths.get_current_win()
+ command('split')
+ local newwin = meths.get_current_win()
+ meths.win_hide(newwin)
+ eq({oldwin}, meths.list_wins())
+ end)
+ it('can hide noncurrent window', function()
+ local oldwin = meths.get_current_win()
+ command('split')
+ local newwin = meths.get_current_win()
+ meths.win_hide(oldwin)
+ eq({newwin}, meths.list_wins())
+ end)
+ it('does not close the buffer', function()
+ local oldwin = meths.get_current_win()
+ local oldbuf = meths.get_current_buf()
+ local buf = meths.create_buf(true, false)
+ local newwin = meths.open_win(buf, true, {
+ relative='win', row=3, col=3, width=12, height=3
+ })
+ meths.win_hide(newwin)
+ eq({oldwin}, meths.list_wins())
+ eq({oldbuf, buf}, meths.list_bufs())
+ end)
+ it('deletes the buffer when bufhidden=wipe', function()
+ local oldwin = meths.get_current_win()
+ local oldbuf = meths.get_current_buf()
+ local buf = meths.create_buf(true, false)
+ local newwin = meths.open_win(buf, true, {
+ relative='win', row=3, col=3, width=12, height=3
+ })
+ meths.buf_set_option(buf, 'bufhidden', 'wipe')
+ meths.win_hide(newwin)
+ eq({oldwin}, meths.list_wins())
+ eq({oldbuf}, meths.list_bufs())
+ end)
+ end)
end)
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..9de0d08e79 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -963,8 +963,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 +981,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..d403fbc878 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()
@@ -129,6 +130,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 +144,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/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua
index 5c67431221..e5c9a20db3 100644
--- a/test/functional/ex_cmds/dict_notifications_spec.lua
+++ b/test/functional/ex_cmds/dict_notifications_spec.lua
@@ -371,4 +371,79 @@ describe('VimL dictionary notifications', function()
eq(1, eval('g:called'))
end)
+ it('does not crash when using dictwatcherdel in callback', function()
+ source([[
+ let g:d = {}
+
+ function! W1(...)
+ " Delete current and following watcher.
+ call dictwatcherdel(g:d, '*', function('W1'))
+ call dictwatcherdel(g:d, '*', function('W2'))
+ try
+ call dictwatcherdel({}, 'meh', function('tr'))
+ catch
+ let g:exc = v:exception
+ endtry
+ endfunction
+ call dictwatcheradd(g:d, '*', function('W1'))
+
+ function! W2(...)
+ endfunction
+ call dictwatcheradd(g:d, '*', function('W2'))
+
+ let g:d.foo = 23
+ ]])
+ eq(23, eval('g:d.foo'))
+ eq("Vim(call):Couldn't find a watcher matching key and callback", eval('g:exc'))
+ end)
+
+ it('does not call watcher added in callback', function()
+ source([[
+ let g:d = {}
+ let g:calls = []
+
+ function! W1(...) abort
+ call add(g:calls, 'W1')
+ call dictwatcheradd(g:d, '*', function('W2'))
+ endfunction
+
+ function! W2(...) abort
+ call add(g:calls, 'W2')
+ endfunction
+
+ call dictwatcheradd(g:d, '*', function('W1'))
+ let g:d.foo = 23
+ ]])
+ eq(23, eval('g:d.foo'))
+ eq({"W1"}, eval('g:calls'))
+ end)
+
+ it('calls watcher deleted in callback', function()
+ source([[
+ let g:d = {}
+ let g:calls = []
+
+ function! W1(...) abort
+ call add(g:calls, "W1")
+ call dictwatcherdel(g:d, '*', function('W2'))
+ endfunction
+
+ function! W2(...) abort
+ call add(g:calls, "W2")
+ endfunction
+
+ call dictwatcheradd(g:d, '*', function('W1'))
+ call dictwatcheradd(g:d, '*', function('W2'))
+ let g:d.foo = 123
+
+ unlet g:d
+ let g:d = {}
+ call dictwatcheradd(g:d, '*', function('W2'))
+ call dictwatcheradd(g:d, '*', function('W1'))
+ let g:d.foo = 123
+ ]])
+ eq(123, eval('g:d.foo'))
+ eq({"W1", "W2", "W2", "W1"}, eval('g:calls'))
+ end)
+
end)
diff --git a/test/functional/ex_cmds/excmd_spec.lua b/test/functional/ex_cmds/excmd_spec.lua
index aac2a9f469..33794eb50d 100644
--- a/test/functional/ex_cmds/excmd_spec.lua
+++ b/test/functional/ex_cmds/excmd_spec.lua
@@ -24,8 +24,6 @@ describe('Ex cmds', function()
pcall_err(command, ':menu 9999999999999999999999999999999999999999'))
eq('Vim(bdelete):E939: Positive count required',
pcall_err(command, ':bdelete 9999999999999999999999999999999999999999'))
- eq('Vim(retab):E487: Argument must be positive',
- pcall_err(command, ':retab 9999999999999999999999999999999999999999'))
assert_alive()
end)
end)
diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua
index 7cc31dc787..c9c004eec1 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 -d")
+ feed_command("au FileReadPost *.gz '[,']!GZIP= 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 f2ced8942d..3d2c4a7d91 100644
--- a/test/functional/legacy/delete_spec.lua
+++ b/test/functional/legacy/delete_spec.lua
@@ -17,33 +17,6 @@ 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
@@ -63,55 +36,4 @@ 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/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua
index 609f825177..d92409059e 100644
--- a/test/functional/legacy/packadd_spec.lua
+++ b/test/functional/legacy/packadd_spec.lua
@@ -20,6 +20,7 @@ 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
@@ -267,6 +268,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..5bfab1d52d 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,86 @@ 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("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/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..2b7198bf63 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -29,6 +29,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 +46,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 +76,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 +131,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 +261,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 +329,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 +956,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 +1124,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';
@@ -1805,20 +1820,36 @@ describe('LSP', function()
end)
describe('lsp.util.jump_to_location', function()
- local target_bufnr
+ local default_target_bufnr
+ local default_target_uri = 'file://fake/uri'
- before_each(function()
- target_bufnr = exec_lua [[
- local bufnr = vim.uri_to_bufnr("file://fake/uri")
- local lines = {"1st line of text", "å å ɧ 汉语 ↥ 🤦 🦄"}
+ 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 bufnr = vim.uri_to_bufnr("%s")
+ local lines = {%s}
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(start_line, start_char, end_line, end_char)
+ local location = function(uri, start_line, start_char, end_line, end_char)
return {
- uri = "file://fake/uri",
+ uri = uri,
range = {
start = { line = start_line, character = start_char },
["end"] = { line = end_line, character = end_char },
@@ -1826,9 +1857,9 @@ describe('LSP', function()
}
end
- local jump = function(msg)
+ local jump = function(bufnr, msg)
eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg))
- eq(target_bufnr, exec_lua[[return vim.fn.bufnr('%')]])
+ eq(bufnr, exec_lua[[return vim.fn.bufnr('%')]])
return {
line = exec_lua[[return vim.fn.line('.')]],
col = exec_lua[[return vim.fn.col('.')]],
@@ -1836,13 +1867,13 @@ describe('LSP', function()
end
it('jumps to a Location', function()
- local pos = jump(location(0, 9, 0, 9))
+ local pos = jump(default_target_bufnr, location(default_target_uri, 0, 9, 0, 9))
eq(1, pos.line)
eq(10, pos.col)
end)
it('jumps to a LocationLink', function()
- local pos = jump({
+ local pos = jump(default_target_bufnr, {
targetUri = "file://fake/uri",
targetSelectionRange = {
start = { line = 0, character = 4 },
@@ -1858,11 +1889,105 @@ describe('LSP', function()
end)
it('jumps to the correct multibyte column', function()
- local pos = jump(location(1, 2, 1, 2))
+ local pos = jump(default_target_bufnr, location(default_target_uri, 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))
+
+ 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))
+
+ 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)
+ 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 cb73bfbbe1..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}})
@@ -472,4 +472,102 @@ describe('treesitter highlighting', function()
|
]]}
end)
+
+ it("supports overriding queries, like ", function()
+ if pending_c_parser(pending) then return end
+
+ insert([[
+ int x = INT_MAX;
+ #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+ #define foo void main() { \
+ return 42; \
+ }
+ ]])
+
+ exec_lua [[
+ local injection_query = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"
+ require('vim.treesitter.query').set_query("c", "highlights", hl_query)
+ require('vim.treesitter.query').set_query("c", "injections", injection_query)
+
+ vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, "c"))
+ ]]
+
+ screen:expect{grid=[[
+ {3:int} x = {5:INT_MAX}; |
+ #define {5:READ_STRING}(x, y) ({3:char_u} *)read_string((x), ({3:size_t})(y))|
+ #define foo {3:void} main() { \ |
+ {4:return} {5:42}; \ |
+ } |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it("supports highlighting with custom highlight groups", function()
+ if pending_c_parser(pending) then return end
+
+ insert(hl_text)
+
+ exec_lua [[
+ local parser = vim.treesitter.get_parser(0, "c")
+ test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
+ ]]
+
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
+ || {6:lstate} != {6:lstate}) { |
+ {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
+ {4:return} {11:lua_error}(lstate); |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ ^} |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ -- This will change ONLY the literal strings to look like comments
+ -- The only literal string is the "vim.schedule: expected function" in this test.
+ exec_lua [[vim.cmd("highlight link cString comment")]]
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
+ || {6:lstate} != {6:lstate}) { |
+ {11:lua_pushliteral}(lstate, {2:"vim.schedule: expected function"}); |
+ {4:return} {11:lua_error}(lstate); |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ ^} |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ screen:expect{ unchanged=true }
+ end)
end)
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..1017913709 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -235,6 +235,41 @@ 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('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
if pending_c_parser(pending) then return end
@@ -468,7 +503,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 +524,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 +541,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 +601,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 +634,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..66aaf0c941 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,24 @@ 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'})
+ 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)
+ 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 +666,6 @@ describe('float window', function()
end
meths.win_set_config(win, {border="single"})
-
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -687,9 +708,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 +773,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 +835,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 +1040,6 @@ describe('float window', function()
end
feed 'i<c-x><c-p>'
-
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -873,12 +1077,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 },
+ [6] = { { id = -1 }, "NW", 5, 4, 0, false }
}, 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};
@@ -5886,6 +6086,216 @@ 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)
end
describe('with ext_multigrid', function()
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 1fe3a4128e..9d7719a7c0 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)
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/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua
index 9acc61e398..077d816903 100644
--- a/test/functional/viml/errorlist_spec.lua
+++ b/test/functional/viml/errorlist_spec.lua
@@ -68,4 +68,17 @@ describe('setloclist()', function()
command('lclose | wincmd w | lopen')
eq('foo', get_cur_win_var('quickfix_title'))
end)
+
+ it("doesn't crash when when window is closed in the middle #13721", function()
+ helpers.insert([[
+ hello world]])
+
+ command("vsplit")
+ command("autocmd WinLeave * :call nvim_win_close(0, v:true)")
+
+ command("call setloclist(0, [])")
+ command("lopen")
+
+ helpers.assert_alive()
+ end)
end)
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