diff options
Diffstat (limited to 'test')
21 files changed, 1364 insertions, 27 deletions
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 437a1858f3..3db44f3f11 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2087,4 +2087,67 @@ describe('API', function() eq("", meths.exec("messages", true)) end) end) + + + describe('nvim_open_term', function() + local screen + + before_each(function() + clear() + screen = Screen.new(100, 35) + screen:attach() + screen:set_default_attr_ids({ + [0] = {bold=true, foreground=Screen.colors.Blue}, + [1] = {background = Screen.colors.Plum1}; + [2] = {background = tonumber('0xffff40'), bg_indexed = true}; + [3] = {background = Screen.colors.Plum1, fg_indexed = true, foreground = tonumber('0x00e000')}; + [4] = {bold = true, reverse = true, background = Screen.colors.Plum1}; + }) + end) + + it('can batch process sequences', function() + local b = meths.create_buf(true,true) + meths.open_win(b, false, {width=79, height=31, row=1, col=1, relative='editor'}) + local t = meths.open_term(b, {}) + + meths.chan_send(t, io.open("test/functional/fixtures/smile2.cat", "r"):read("*a")) + screen:expect{grid=[[ + ^ | + {0:~}{1::smile }{0: }| + {0:~}{1: }{2:oooo$$$$$$$$$$$$oooo}{1: }{0: }| + {0:~}{1: }{2:oo$$$$$$$$$$$$$$$$$$$$$$$$o}{1: }{0: }| + {0:~}{1: }{2:oo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o}{1: }{2:o$}{1: }{2:$$}{1: }{2:o$}{1: }{0: }| + {0:~}{1: }{2:o}{1: }{2:$}{1: }{2:oo}{1: }{2:o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o}{1: }{2:$$}{1: }{2:$$}{1: }{2:$$o$}{1: }{0: }| + {0:~}{1: }{2:oo}{1: }{2:$}{1: }{2:$}{1: "}{2:$}{1: }{2:o$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$}{1: }{2:$$$$$$$$$o}{1: }{2:$$$o$$o$}{1: }{0: }| + {0:~}{1: "}{2:$$$$$$o$}{1: }{2:o$$$$$$$$$}{1: }{2:$$$$$$$$$$$}{1: }{2:$$$$$$$$$$o}{1: }{2:$$$$$$$$}{1: }{0: }| + {0:~}{1: }{2:$$$$$$$}{1: }{2:$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$}{1: }{0: }| + {0:~}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$$}{1: """}{2:$$$}{1: }{0: }| + {0:~}{1: "}{2:$$$}{1:""""}{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: "}{2:$$$}{1: }{0: }| + {0:~}{1: }{2:$$$}{1: }{2:o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: "}{2:$$$o}{1: }{0: }| + {0:~}{1: }{2:o$$}{1:" }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$o}{1: }{0: }| + {0:~}{1: }{2:$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1:" "}{2:$$$$$$ooooo$$$$o}{1: }{0: }| + {0:~}{1: }{2:o$$$oooo$$$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:o$$$$$$$$$$$$$$$$$}{1: }{0: }| + {0:~}{1: }{2:$$$$$$$$}{1:"}{2:$$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$$}{1:"""""""" }{0: }| + {0:~}{1: """" }{2:$$$$}{1: "}{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1:" }{2:o$$$}{1: }{0: }| + {0:~}{1: "}{2:$$$o}{1: """}{2:$$$$$$$$$$$$$$$$$$}{1:"}{2:$$}{1:" }{2:$$$}{1: }{0: }| + {0:~}{1: }{2:$$$o}{1: "}{2:$$}{1:""}{2:$$$$$$}{1:"""" }{2:o$$$}{1: }{0: }| + {0:~}{1: }{2:$$$$o}{1: }{2:o$$$}{1:" }{0: }| + {0:~}{1: "}{2:$$$$o}{1: }{2:o$$$$$$o}{1:"}{2:$$$$o}{1: }{2:o$$$$}{1: }{0: }| + {0:~}{1: "}{2:$$$$$oo}{1: ""}{2:$$$$o$$$$$o}{1: }{2:o$$$$}{1:"" }{0: }| + {0:~}{1: ""}{2:$$$$$oooo}{1: "}{2:$$$o$$$$$$$$$}{1:""" }{0: }| + {0:~}{1: ""}{2:$$$$$$$oo}{1: }{2:$$$$$$$$$$}{1: }{0: }| + {0:~}{1: """"}{2:$$$$$$$$$$$}{1: }{0: }| + {0:~}{1: }{2:$$$$$$$$$$$$}{1: }{0: }| + {0:~}{1: }{2:$$$$$$$$$$}{1:" }{0: }| + {0:~}{1: "}{2:$$$}{1:"""" }{0: }| + {0:~}{1: }{0: }| + {0:~}{3:Press ENTER or type command to continue}{1: }{0: }| + {0:~}{4:term://~/config2/docs/pres//32693:vim --clean +smile 29,39 All}{0: }| + {0:~}{1::call nvim__screenshot("smile2.cat") }{0: }| + {0:~ }| + {0:~ }| + | + ]]} + end) + end) end) 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/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/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua index 1b1fc2589f..bcd5e22492 100644 --- a/test/functional/fixtures/fake-lsp-server.lua +++ b/test/functional/fixtures/fake-lsp-server.lua @@ -154,6 +154,7 @@ function tests.capabilities_for_client_supports_method() hoverProvider = true; definitionProvider = false; referencesProvider = false; + codeLensProvider = { resolveProvider = true; }; } } end; diff --git a/test/functional/fixtures/smile2.cat b/test/functional/fixtures/smile2.cat new file mode 100644 index 0000000000..0feb32f293 --- /dev/null +++ b/test/functional/fixtures/smile2.cat @@ -0,0 +1,32 @@ +31,79 +[?25l[H[2J:smile
+ [103moooo$$$$$$$$$$$$oooo(B[m
+ [103moo$$$$$$$$$$$$$$$$$$$$$$$$o(B[m
+ [103moo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o(B[m [103mo$(B[m [103m$$(B[m [103mo$(B[m
+ [103mo(B[m [103m$(B[m [103moo(B[m [103mo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o(B[m [103m$$(B[m [103m$$(B[m [103m$$o$(B[m
+ [103moo(B[m [103m$(B[m [103m$(B[m "[103m$(B[m [103mo$$$$$$$$$(B[m [103m$$$$$$$$$$$$$(B[m [103m$$$$$$$$$o(B[m [103m$$$o$$o$(B[m
+ "[103m$$$$$$o$(B[m [103mo$$$$$$$$$(B[m [103m$$$$$$$$$$$(B[m [103m$$$$$$$$$$o(B[m [103m$$$$$$$$(B[m
+ [103m$$$$$$$(B[m [103m$$$$$$$$$$$(B[m [103m$$$$$$$$$$$(B[m [103m$$$$$$$$$$$$$$$$$$$$$$$(B[m
+ [103m$$$$$$$$$$$$$$$$$$$$$$$(B[m [103m$$$$$$$$$$$$$(B[m [103m$$$$$$$$$$$$$$(B[m """[103m$$$(B[m
+ "[103m$$$(B[m""""[103m$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$(B[m "[103m$$$(B[m
+ [103m$$$(B[m [103mo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$(B[m "[103m$$$o(B[m
+ [103mo$$(B[m" [103m$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$(B[m [103m$$$o(B[m
+ [103m$$$(B[m [103m$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$(B[m" "[103m$$$$$$ooooo$$$$o(B[m
+ [103mo$$$oooo$$$$$(B[m [103m$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$(B[m [103mo$$$$$$$$$$$$$$$$$(B[m
+ [103m$$$$$$$$(B[m"[103m$$$$(B[m [103m$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$(B[m [103m$$$$(B[m""""""""
+ """" [103m$$$$(B[m "[103m$$$$$$$$$$$$$$$$$$$$$$$$$$$$(B[m" [103mo$$$(B[m
+ "[103m$$$o(B[m """[103m$$$$$$$$$$$$$$$$$$(B[m"[103m$$(B[m" [103m$$$(B[m
+ [103m$$$o(B[m "[103m$$(B[m""[103m$$$$$$(B[m"""" [103mo$$$(B[m
+ [103m$$$$o(B[m [103mo$$$(B[m"
+ "[103m$$$$o(B[m [103mo$$$$$$o(B[m"[103m$$$$o(B[m [103mo$$$$(B[m
+ "[103m$$$$$oo(B[m ""[103m$$$$o$$$$$o(B[m [103mo$$$$(B[m""
+ ""[103m$$$$$oooo(B[m "[103m$$$o$$$$$$$$$(B[m"""
+ ""[103m$$$$$$$oo(B[m [103m$$$$$$$$$$(B[m
+ """"[103m$$$$$$$$$$$(B[m
+ [103m$$$$$$$$$$$$(B[m
+ [103m$$$$$$$$$$(B[m"
+ "[103m$$$(B[m""""
+
+[32mPress ENTER or type command to continue(B[m
+(B[0;1;7mterm://~/config2/docs/pres//32693:vim --clean +smile 29,39 All
+(B[m:call nvim__screenshot("smile2.cat") [?25h
\ No newline at end of file diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua index 5f7bbd887f..97ac96804e 100644 --- a/test/functional/legacy/memory_usage_spec.lua +++ b/test/functional/legacy/memory_usage_spec.lua @@ -157,8 +157,8 @@ describe('memory usage', function() -- The usage may be a bit less than the last value, use 80%. -- Allow for 20% tolerance at the upper limit. That's very permissive, but -- otherwise the test fails sometimes. On Sourcehut CI with FreeBSD we need to - -- be even more permissive. - local upper_multiplier = uname() == 'freebsd' and 15 or 12 + -- be even much more permissive. + local upper_multiplier = uname() == 'freebsd' and 19 or 12 local lower = before.last * 8 / 10 local upper = load_adjust((after.max + (after.last - before.last)) * upper_multiplier / 10) check_result({before=before, after=after, last=last}, diff --git a/test/functional/legacy/options_spec.lua b/test/functional/legacy/options_spec.lua index d7f5df3a1e..023cdd4ae1 100644 --- a/test/functional/legacy/options_spec.lua +++ b/test/functional/legacy/options_spec.lua @@ -42,6 +42,20 @@ describe('set', function() matches('E36: Not enough room', exc_exec('set wmh=1')) end) + it('winminheight works with tabline', function() + local screen = Screen.new(20, 11) + screen:attach() + source([[ + set wmh=0 stal=2 + split + split + split + split + tabnew + ]]) + matches('E36: Not enough room', exc_exec('set wmh=1')) + end) + it('scroll works', function() local screen = Screen.new(42, 16) screen:attach() diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index 7a6b5be8bc..6d7d9b4d8b 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -666,6 +666,70 @@ describe('lua: nvim_buf_attach on_bytes', function() } end) + it("tab with noexpandtab and softtabstop", function() + command("set noet") + command("set ts=4") + command("set sw=2") + command("set sts=2") + + local check_events = setup_eventcheck(verify, {'asdfasdf'}) + + feed("gg0i<tab>") + + check_events { + { "test1", "bytes", 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 1 }, + { "test1", "bytes", 1, 4, 0, 1, 1, 0, 0, 0, 0, 1, 1 }, + } + feed("<tab>") + + -- when spaces are merged into a tabstop + check_events { + { "test1", "bytes", 1, 5, 0, 2, 2, 0, 0, 0, 0, 1, 1 }, + { "test1", "bytes", 1, 6, 0, 3, 3, 0, 0, 0, 0, 1, 1 }, + { "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 }, + { "test1", "bytes", 1, 8, 0, 0, 0, 0, 4, 4, 0, 0, 0 } + } + + -- in REPLACE mode + feed("R<tab><tab>") + check_events { + { "test1", "bytes", 1, 9, 0, 0, 0, 0, 1, 1, 0, 1, 1 }, + { "test1", "bytes", 1, 10, 0, 1, 1, 0, 0, 0, 0, 1, 1 }, + { "test1", "bytes", 1, 11, 0, 2, 2, 0, 1, 1, 0, 1, 1 }, + { "test1", "bytes", 1, 12, 0, 3, 3, 0, 0, 0, 0, 1, 1 }, + { "test1", "bytes", 1, 13, 0, 0, 0, 0, 4, 4, 0, 1, 1 }, + } + feed("<esc>u") + check_events { + { "test1", "bytes", 1, 14, 0, 0, 0, 0, 1, 1, 0, 4, 4 }, + { "test1", "bytes", 1, 14, 0, 2, 2, 0, 2, 2, 0, 1, 1 }, + { "test1", "bytes", 1, 14, 0, 0, 0, 0, 2, 2, 0, 1, 1 } + } + + -- in VISUALREPLACE mode + feed("gR<tab><tab>") + check_events { + { "test1", "bytes", 1, 15, 0, 0, 0, 0, 1, 1, 0, 1, 1 }; + { "test1", "bytes", 1, 16, 0, 1, 1, 0, 1, 1, 0, 1, 1 }; + { "test1", "bytes", 1, 17, 0, 2, 2, 0, 1, 1, 0, 1, 1 }; + { "test1", "bytes", 1, 18, 0, 3, 3, 0, 1, 1, 0, 1, 1 }; + { "test1", "bytes", 1, 19, 0, 3, 3, 0, 1, 1, 0, 0, 0 }; + { "test1", "bytes", 1, 20, 0, 3, 3, 0, 0, 0, 0, 1, 1 }; + { "test1", "bytes", 1, 22, 0, 2, 2, 0, 1, 1, 0, 0, 0 }; + { "test1", "bytes", 1, 23, 0, 2, 2, 0, 0, 0, 0, 1, 1 }; + { "test1", "bytes", 1, 25, 0, 1, 1, 0, 1, 1, 0, 0, 0 }; + { "test1", "bytes", 1, 26, 0, 1, 1, 0, 0, 0, 0, 1, 1 }; + { "test1", "bytes", 1, 28, 0, 0, 0, 0, 1, 1, 0, 0, 0 }; + { "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 }; + } + end) + it("sends events when undoing with undofile", function() write_file("Xtest-undofile", dedent([[ 12345 @@ -717,6 +781,26 @@ describe('lua: nvim_buf_attach on_bytes', function() command("bw!") end) + it("blockwise paste with uneven line lengths", function() + local check_events = setup_eventcheck(verify, {'aaaa', 'aaa', 'aaa'}) + + -- eq({}, meths.buf_get_lines(0, 0, -1, true)) + feed("gg0<c-v>jj$d") + + check_events { + { "test1", "bytes", 1, 3, 0, 0, 0, 0, 4, 4, 0, 0, 0 }, + { "test1", "bytes", 1, 3, 1, 0, 1, 0, 3, 3, 0, 0, 0 }, + { "test1", "bytes", 1, 3, 2, 0, 2, 0, 3, 3, 0, 0, 0 }, + } + + feed("p") + check_events { + { "test1", "bytes", 1, 4, 0, 0, 0, 0, 0, 0, 0, 4, 4 }, + { "test1", "bytes", 1, 4, 1, 0, 5, 0, 0, 0, 0, 3, 3 }, + { "test1", "bytes", 1, 4, 2, 0, 9, 0, 0, 0, 0, 3, 3 }, + } + + end) teardown(function() os.remove "Xtest-reload" diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index cdc3017323..66b33cc9e1 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -11,6 +11,8 @@ local pesc = helpers.pesc local insert = helpers.insert local retry = helpers.retry local NIL = helpers.NIL +local read_file = require('test.helpers').read_file +local write_file = require('test.helpers').write_file -- Use these to get access to a coroutine so that I can run async tests and use -- yield. @@ -27,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') @@ -34,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', @@ -63,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({}, { @@ -118,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" @@ -248,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}; @@ -312,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 = { @@ -336,6 +353,8 @@ describe('LSP', function() local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") eq(full_kind, client.resolved_capabilities().text_document_did_change) eq(true, client.resolved_capabilities().text_document_save) + eq(false, client.resolved_capabilities().code_lens) + eq(false, client.resolved_capabilities().code_lens_resolve) end; on_exit = function(code, signal) eq(0, code, "exit code", fake_lsp_logfile) @@ -361,6 +380,8 @@ describe('LSP', function() eq(true, client.resolved_capabilities().hover) eq(false, client.resolved_capabilities().goto_definition) eq(false, client.resolved_capabilities().rename) + eq(true, client.resolved_capabilities().code_lens) + eq(true, client.resolved_capabilities().code_lens_resolve) -- known methods for resolved capabilities eq(true, client.supports_method("textDocument/hover")) @@ -935,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) @@ -1259,6 +1280,99 @@ describe('LSP', function() return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false) ]], make_workspace_edit(edits), target_bufnr)) end) + it('Supports file creation with CreateFile payload', function() + local tmpfile = helpers.tmpname() + os.remove(tmpfile) -- Should not exist, only interested in a tmpname + local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) + local edit = { + documentChanges = { + { + kind = 'create', + uri = uri, + }, + } + } + exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit) + eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile)) + end) + it('createFile does not touch file if it exists and ignoreIfExists is set', function() + local tmpfile = helpers.tmpname() + write_file(tmpfile, 'Dummy content') + local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) + local edit = { + documentChanges = { + { + kind = 'create', + uri = uri, + options = { + ignoreIfExists = true, + }, + }, + } + } + exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit) + eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile)) + eq('Dummy content', read_file(tmpfile)) + end) + it('createFile overrides file if overwrite is set', function() + local tmpfile = helpers.tmpname() + write_file(tmpfile, 'Dummy content') + local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) + local edit = { + documentChanges = { + { + kind = 'create', + uri = uri, + options = { + overwrite = true, + ignoreIfExists = true, -- overwrite must win over ignoreIfExists + }, + }, + } + } + exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit) + eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile)) + eq('', read_file(tmpfile)) + end) + it('DeleteFile delete file and buffer', function() + local tmpfile = helpers.tmpname() + write_file(tmpfile, 'Be gone') + local uri = exec_lua([[ + local fname = select(1, ...) + local bufnr = vim.fn.bufadd(fname) + vim.fn.bufload(bufnr) + return vim.uri_from_fname(fname) + ]], tmpfile) + local edit = { + documentChanges = { + { + kind = 'delete', + uri = uri, + } + } + } + eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit)) + eq(false, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile)) + eq(false, exec_lua('return vim.api.nvim_buf_is_loaded(vim.fn.bufadd(...))', tmpfile)) + end) + it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function() + local tmpfile = helpers.tmpname() + os.remove(tmpfile) + local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) + local edit = { + documentChanges = { + { + kind = 'delete', + uri = uri, + options = { + ignoreIfNotExists = false, + } + } + } + } + eq(false, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit)) + eq(false, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile)) + end) end) describe('completion_list_to_complete_items', function() @@ -1305,6 +1419,72 @@ describe('LSP', function() end) end) + describe('lsp.util.rename', function() + it('Can rename an existing file', function() + local old = helpers.tmpname() + write_file(old, 'Test content') + local new = helpers.tmpname() + os.remove(new) -- only reserve the name, file must not exist for the test scenario + local lines = exec_lua([[ + local old = select(1, ...) + local new = select(2, ...) + vim.lsp.util.rename(old, new) + + -- after rename the target file must have the contents of the source file + local bufnr = vim.fn.bufadd(new) + return vim.api.nvim_buf_get_lines(bufnr, 0, -1, true) + ]], old, new) + eq({'Test content'}, lines) + local exists = exec_lua('return vim.loop.fs_stat(...) ~= nil', old) + eq(false, exists) + exists = exec_lua('return vim.loop.fs_stat(...) ~= nil', new) + eq(true, exists) + os.remove(new) + end) + it('Does not rename file if target exists and ignoreIfExists is set or overwrite is false', function() + local old = helpers.tmpname() + write_file(old, 'Old File') + local new = helpers.tmpname() + write_file(new, 'New file') + + exec_lua([[ + local old = select(1, ...) + local new = select(2, ...) + + vim.lsp.util.rename(old, new, { ignoreIfExists = true }) + ]], old, new) + + eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', old)) + eq('New file', read_file(new)) + + exec_lua([[ + local old = select(1, ...) + local new = select(2, ...) + + vim.lsp.util.rename(old, new, { overwrite = false }) + ]], old, new) + + eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', old)) + eq('New file', read_file(new)) + end) + it('Does override target if overwrite is true', function() + local old = helpers.tmpname() + write_file(old, 'Old file') + local new = helpers.tmpname() + write_file(new, 'New file') + exec_lua([[ + local old = select(1, ...) + local new = select(2, ...) + + vim.lsp.util.rename(old, new, { overwrite = true }) + ]], old, new) + + eq(false, exec_lua('return vim.loop.fs_stat(...) ~= nil', old)) + eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', new)) + eq('Old file\n', read_file(new)) + end) + end) + describe('lsp.util.locations_to_items', function() it('Convert Location[] to items', function() local expected = { 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..d80d0fdbaf 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -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/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua index e1a72ced05..f75f700fb5 100644 --- a/test/functional/ui/cursor_spec.lua +++ b/test/functional/ui/cursor_spec.lua @@ -212,10 +212,10 @@ describe('ui/cursor', function() if m.blinkwait then m.blinkwait = 700 end end if m.hl_id then - m.hl_id = 55 + m.hl_id = 56 m.attr = {background = Screen.colors.DarkGray} end - if m.id_lm then m.id_lm = 56 end + if m.id_lm then m.id_lm = 57 end end -- Assert the new expectation. diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 6cf549909a..295a54aec8 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -179,7 +179,7 @@ describe('decorations providers', function() | ]]} - meths.set_hl_ns(ns1) + meths._set_hl_ns(ns1) screen:expect{grid=[[ {10: 1 }{11:// just to see if there was an accid}| {10: }{11:ent} | @@ -205,7 +205,7 @@ describe('decorations providers', function() local ns2 = a.nvim_create_namespace 'ns2' a.nvim_set_decoration_provider (ns2, { on_win = function (_, win, buf) - a.nvim_set_hl_ns(win == thewin and _G.ns1 or ns2) + a.nvim__set_hl_ns(win == thewin and _G.ns1 or ns2) end; }) ]] @@ -252,7 +252,7 @@ describe('decorations providers', function() ]]} meths.set_hl(ns1, 'LinkGroup', {fg = 'Blue'}) - meths.set_hl_ns(ns1) + meths._set_hl_ns(ns1) screen:expect{grid=[[ // just to see if there was an accident | @@ -288,7 +288,7 @@ describe('decorations providers', function() ]]} meths.set_hl(ns1, 'LinkGroup', {fg = 'Blue', default=true}) - meths.set_hl_ns(ns1) + meths._set_hl_ns(ns1) feed 'k' screen:expect{grid=[[ @@ -302,6 +302,35 @@ describe('decorations providers', function() | ]]} end) + + it('can have virtual text', 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 = {{'+', 'ErrorMsg'}}; + virt_text_pos='overlay'; + ephemeral = true; + }) + end + end + ]] + + screen:expect{grid=[[ + {2:+}/ just to see if there was an accident | + {2:+}/ on Mulholland Drive | + {2:+}ry_start(); | + {2:+}ufref_T save_buf; | + {2:+}witch_buffer(&save_buf, buf); | + {2:+}osp = getmark(mark, false); | + {2:+}estore_buffer(&save_buf);^ | + | + ]]} + end) end) describe('extmark decorations', function() diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua index 69b6ab8cf0..a8d9fb02fc 100644 --- a/test/functional/ui/diff_spec.lua +++ b/test/functional/ui/diff_spec.lua @@ -1049,6 +1049,8 @@ it('diff updates line numbers below filler lines', function() [9] = {background = Screen.colors.LightMagenta}, [10] = {bold = true, foreground = Screen.colors.Brown}, [11] = {foreground = Screen.colors.Brown}, + [12] = {foreground = Screen.colors.Brown, bold = true, background = Screen.colors.Red}; + [13] = {background = Screen.colors.Gray90}; }) source([[ call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b']) @@ -1107,4 +1109,22 @@ it('diff updates line numbers below filler lines', function() {3:[No Name] [+] }{7:[No Name] [+] }| | ]]) + command("set signcolumn number tgc cursorline") + command("hi CursorLineNr guibg=red") + screen:expect{grid=[[ + {1: }a {3:│}{11: 2 }a | + {1: }a {3:│}{11: 1 }a | + {1: }a {3:│}{12:3 }{13:^a }| + {1: }{8:x}{9: }{3:│}{11: 1 }{8:y}{9: }| + {1: }{4:x }{3:│}{11: }{2:----------------}| + {1: }{4:x }{3:│}{11: }{2:----------------}| + {1: }b {3:│}{11: 2 }b | + {1: }b {3:│}{11: 3 }b | + {1: }b {3:│}{11: 4 }b | + {1: }b {3:│}{11: 5 }b | + {1: }b {3:│}{11: 6 }b | + {6:~ }{3:│}{6:~ }| + {3:[No Name] [+] }{7:[No Name] [+] }| + signcolumn=auto | + ]]} end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 32f9ae030f..664b8e7ab7 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -14,7 +14,7 @@ local funcs = helpers.funcs local run = helpers.run local pcall_err = helpers.pcall_err -describe('floatwin', function() +describe('float window', function() before_each(function() clear() end) @@ -131,7 +131,7 @@ describe('floatwin', function() local screen before_each(function() screen = Screen.new(40,7) - screen:attach({ext_multigrid=multigrid}) + screen:attach {ext_multigrid=multigrid} screen:set_default_attr_ids(attrs) end) @@ -595,6 +595,310 @@ describe('floatwin', function() end end) + it('can have border', function() + local buf = meths.create_buf(false, false) + meths.buf_set_lines(buf, 0, -1, true, {' halloj! ', + ' BORDAA '}) + local win = meths.open_win(buf, false, {relative='editor', width=9, height=2, row=2, col=5, border="double"}) + + 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 + + meths.win_set_config(win, {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 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 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:xååååååååå\}| + {5:n̈̊}{1: halloj! }{5:n̈̊}| + {5:n̈̊}{1: BORDAA }{5:n̈̊}| + {5:\åååååååååx}| + ]], 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:x}{7:ååååååååå}{5:\}{0: }| + {0:~ }{17:n̈̊}{1: halloj! }{17:n̈̊}{0: }| + {0:~ }{17:n̈̊}{1: BORDAA }{17:n̈̊}{0: }| + {0:~ }{5:\}{7:ååååååååå}{5:x}{0: }| + | + ]]} + end + + meths.win_set_config(win, {border="none"}) + 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 + {1: halloj! }| + {1: BORDAA }| + ]], 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:~ }{1: halloj! }{0: }| + {0:~ }{1: BORDAA }{0: }| + {0:~ }| + {0:~ }| + | + ]]} + end + end) + + it('with border show popupmenu', function() + screen:try_resize(40,10) + local buf = meths.create_buf(false, false) + meths.buf_set_lines(buf, 0, -1, true, {'aaa aab ', + 'abb acc ', ''}) + meths.open_win(buf, true, {relative='editor', width=9, height=3, row=0, col=5, border="double"}) + feed 'G' + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:╔═════════╗}| + {5:║}{1:aaa aab }{5:║}| + {5:║}{1:abb acc }{5:║}| + {5:║}{1:^ }{5:║}| + {5:╚═════════╝}| + ]], float_pos={ + [5] = { { id = 1002 }, "NW", 1, 0, 5, true } + }, 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 = 0}; + }} + else + screen:expect{grid=[[ + {5:╔═════════╗} | + {0:~ }{5:║}{1:aaa aab }{5:║}{0: }| + {0:~ }{5:║}{1:abb acc }{5:║}{0: }| + {0:~ }{5:║}{1:^ }{5:║}{0: }| + {0:~ }{5:╚═════════╝}{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]} + end + + feed 'i<c-x><c-p>' + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {3:-- }{8:match 1 of 4} | + ## grid 5 + {5:╔═════════╗}| + {5:║}{1:aaa aab }{5:║}| + {5:║}{1:abb acc }{5:║}| + {5:║}{1:acc^ }{5:║}| + {5:╚═════════╝}| + ## grid 6 + {1: aaa }| + {1: aab }| + {1: abb }| + {13: acc }| + ]], float_pos={ + [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}; + }} + else + screen:expect{grid=[[ + {5:╔═════════╗} | + {0:~ }{5:║}{1:aaa aab }{5:║}{0: }| + {0:~ }{5:║}{1:abb acc }{5:║}{0: }| + {0:~ }{5:║}{1:acc^ }{5:║}{0: }| + {0:~ }{1: aaa }{0: }| + {0:~ }{1: aab }{0: }| + {0:~ }{1: abb }{0: }| + {0:~ }{13: acc }{0: }| + {0:~ }| + {3:-- }{8:match 1 of 4} | + ]]} + end + end) + it('can have minimum size', function() insert("the background text") local buf = meths.create_buf(false, true) @@ -5433,6 +5737,155 @@ describe('floatwin', function() ]]) end end) + + it("correctly redraws when overlaid windows are resized #13991", function() + helpers.source([[ + let popup_config = {"relative" : "editor", + \ "width" : 7, + \ "height" : 3, + \ "row" : 1, + \ "col" : 1, + \ "style" : "minimal"} + + let border_config = {"relative" : "editor", + \ "width" : 9, + \ "height" : 5, + \ "row" : 0, + \ "col" : 0, + \ "style" : "minimal"} + + let popup_buffer = nvim_create_buf(v:false, v:true) + let border_buffer = nvim_create_buf(v:false, v:true) + let popup_win = nvim_open_win(popup_buffer, v:true, popup_config) + let border_win = nvim_open_win(border_buffer, v:false, border_config) + + call nvim_buf_set_lines(popup_buffer, 0, -1, v:true, + \ ["long", "longer", "longest"]) + + call nvim_buf_set_lines(border_buffer, 0, -1, v:true, + \ ["---------", "- -", "- -"]) + ]]) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 5 + {2:^long }| + {2:longer }| + {2:longest}| + ## grid 6 + {2:---------}| + {2:- -}| + {2:- -}| + {2: }| + {2: }| + ]], attr_ids={ + [1] = {foreground = Screen.colors.Blue1, bold = true}; + [2] = {background = Screen.colors.LightMagenta}; + }, float_pos={ + [5] = { { + id = 1002 + }, "NW", 1, 1, 1, true }, + [6] = { { + id = 1003 + }, "NW", 1, 0, 0, true } + }} + else + screen:expect([[ + {1:---------} | + {1:-^long -}{0: }| + {1:-longer -}{0: }| + {1: longest }{0: }| + {1: }{0: }| + {0:~ }| + | + ]]) + end + + helpers.source([[ + let new_popup_config = {"width" : 1, "height" : 3} + let new_border_config = {"width" : 3, "height" : 5} + + function! Resize() + call nvim_win_set_config(g:popup_win, g:new_popup_config) + call nvim_win_set_config(g:border_win, g:new_border_config) + + call nvim_buf_set_lines(g:border_buffer, 0, -1, v:true, + \ ["---", "- -", "- -"]) + endfunction + + nnoremap zz <cmd>call Resize()<cr> + ]]) + + helpers.feed("zz") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 5 + {2:^l}| + {2:o}| + {2:n}| + ## grid 6 + {2:---}| + {2:- -}| + {2:- -}| + {2: }| + {2: }| + ]], attr_ids={ + [1] = {foreground = Screen.colors.Blue1, bold = true}; + [2] = {background = Screen.colors.LightMagenta}; + }, float_pos={ + [5] = { { + id = 1002 + }, "NW", 1, 1, 1, true }, + [6] = { { + id = 1003 + }, "NW", 1, 0, 0, true } + }} + else + screen:expect([[ + {1:---} | + {1:-^l-}{0: }| + {1:-o-}{0: }| + {1: n }{0: }| + {1: }{0: }| + {0:~ }| + | + ]]) + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index d3b1d33956..8883ad8270 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -464,6 +464,206 @@ describe("folded lines", function() end end) + it("works with vsplit", function() + insert([[ + aa + bb + cc + dd + ee + ff]]) + feed_command('2') + command("set foldcolumn=1") + feed('zf3j') + feed_command('1') + feed('zf2j') + feed('zO') + feed_command("rightbelow vnew") + insert([[ + aa + bb + cc + dd + ee + ff]]) + feed_command('2') + command("set foldcolumn=1") + feed('zf3j') + feed_command('1') + feed('zf2j') + if multigrid then + meths.input_mouse('left', 'press', '', 4, 0, 0) + screen:expect([[ + ## grid 1 + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + {2:[No Name] [+] }{3:[No Name] [+] }| + [3:---------------------------------------------]| + ## grid 2 + {7:-}aa | + {7:-}bb | + {7:2}cc | + {7:2}dd | + {7:2}ee | + {7:│}ff | + ## grid 3 + :1 | + ## grid 4 + {7:-}^aa | + {7:+}{5:+--- 4 lines: bb····}| + {7:│}ff | + {1:~ }| + {1:~ }| + {1:~ }| + ]]) + else + meths.input_mouse('left', 'press', '', 0, 0, 23) + screen:expect([[ + {7:-}aa {2:│}{7:-}^aa | + {7:-}bb {2:│}{7:+}{5:+--- 4 lines: bb····}| + {7:2}cc {2:│}{7:│}ff | + {7:2}dd {2:│}{1:~ }| + {7:2}ee {2:│}{1:~ }| + {7:│}ff {2:│}{1:~ }| + {2:[No Name] [+] }{3:[No Name] [+] }| + :1 | + ]]) + end + + if multigrid then + meths.input_mouse('left', 'press', '', 4, 1, 0) + screen:expect([[ + ## grid 1 + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + {2:[No Name] [+] }{3:[No Name] [+] }| + [3:---------------------------------------------]| + ## grid 2 + {7:-}aa | + {7:-}bb | + {7:2}cc | + {7:2}dd | + {7:2}ee | + {7:│}ff | + ## grid 3 + :1 | + ## grid 4 + {7:-}^aa | + {7:-}bb | + {7:2}cc | + {7:2}dd | + {7:2}ee | + {7:│}ff | + ]]) + else + meths.input_mouse('left', 'press', '', 0, 1, 23) + screen:expect([[ + {7:-}aa {2:│}{7:-}^aa | + {7:-}bb {2:│}{7:-}bb | + {7:2}cc {2:│}{7:2}cc | + {7:2}dd {2:│}{7:2}dd | + {7:2}ee {2:│}{7:2}ee | + {7:│}ff {2:│}{7:│}ff | + {2:[No Name] [+] }{3:[No Name] [+] }| + :1 | + ]]) + end + + if multigrid then + meths.input_mouse('left', 'press', '', 2, 1, 0) + screen:expect([[ + ## grid 1 + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + {3:[No Name] [+] }{2:[No Name] [+] }| + [3:---------------------------------------------]| + ## grid 2 + {7:-}aa | + {7:+}{5:^+--- 4 lines: bb····}| + {7:│}ff | + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + :1 | + ## grid 4 + {7:-}aa | + {7:-}bb | + {7:2}cc | + {7:2}dd | + {7:2}ee | + {7:│}ff | + ]]) + else + meths.input_mouse('left', 'press', '', 0, 1, 0) + screen:expect([[ + {7:-}aa {2:│}{7:-}aa | + {7:+}{5:^+--- 4 lines: bb····}{2:│}{7:-}bb | + {7:│}ff {2:│}{7:2}cc | + {1:~ }{2:│}{7:2}dd | + {1:~ }{2:│}{7:2}ee | + {1:~ }{2:│}{7:│}ff | + {3:[No Name] [+] }{2:[No Name] [+] }| + :1 | + ]]) + end + + if multigrid then + meths.input_mouse('left', 'press', '', 2, 0, 0) + screen:expect([[ + ## grid 1 + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + [2:----------------------]{2:│}[4:----------------------]| + {3:[No Name] [+] }{2:[No Name] [+] }| + [3:---------------------------------------------]| + ## grid 2 + {7:+}{5:^+-- 6 lines: aa·····}| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + :1 | + ## grid 4 + {7:-}aa | + {7:-}bb | + {7:2}cc | + {7:2}dd | + {7:2}ee | + {7:│}ff | + ]]) + else + meths.input_mouse('left', 'press', '', 0, 0, 0) + screen:expect([[ + {7:+}{5:^+-- 6 lines: aa·····}{2:│}{7:-}aa | + {1:~ }{2:│}{7:-}bb | + {1:~ }{2:│}{7:2}cc | + {1:~ }{2:│}{7:2}dd | + {1:~ }{2:│}{7:2}ee | + {1:~ }{2:│}{7:│}ff | + {3:[No Name] [+] }{2:[No Name] [+] }| + :1 | + ]]) + end + end) + it("works with tab", function() insert([[ aa diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index ef3acd7d2e..8992ee27ce 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -333,10 +333,10 @@ describe('highlight defaults', function() command('highlight clear EndOfBuffer') screen:expect{grid=[[ ^ | - ~ | - ~ | + {1:~ }| + {1:~ }| | - ]], hl_groups={EndOfBuffer=0, MsgSeparator=2}} + ]], hl_groups={EndOfBuffer=1, MsgSeparator=2}} end) end) 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/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index ff9f30d0a1..958e137f65 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -24,10 +24,6 @@ describe('screen', function() } ) end) - after_each(function() - screen:detach() - end) - it('default initial screen', function() screen:expect([[ ^ | @@ -67,10 +63,6 @@ local function screen_tests(linegrid) } ) end) - after_each(function() - screen:detach() - end) - describe(':suspend', function() it('is forwarded to the UI', function() local function check() @@ -1004,3 +996,39 @@ describe('Screen default colors', function() end} end) end) + + +describe('screen with msgsep deactivated on startup', function() + local screen + + before_each(function() + clear('--cmd', 'set display-=msgsep') + screen = Screen.new() + screen:attach() + screen:set_default_attr_ids { + [0] = {bold=true, foreground=255}; + [7] = {bold = true, foreground = Screen.colors.SeaGreen}; + } + end) + + it('execute command with multi-line output', function() + feed ':ls<cr>' + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + :ls | + 1 %a "[No Name]" line 1 | + {7:Press ENTER or type command to continue}^ | + ]]) + feed '<cr>' -- skip the "Press ENTER..." state or tests will hang + end) +end) 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) |