diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/functional/api/buffer_spec.lua | 35 | ||||
| -rw-r--r-- | test/functional/api/buffer_updates_spec.lua | 26 | ||||
| -rw-r--r-- | test/functional/api/vim_spec.lua | 22 | ||||
| -rw-r--r-- | test/functional/api/window_spec.lua | 37 | ||||
| -rw-r--r-- | test/functional/eval/let_spec.lua | 39 | ||||
| -rw-r--r-- | test/functional/fixtures/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | test/functional/fixtures/printenv-test.c | 59 | ||||
| -rw-r--r-- | test/functional/terminal/tui_spec.lua | 100 | ||||
| -rw-r--r-- | test/functional/ui/float_spec.lua | 3061 | ||||
| -rw-r--r-- | test/functional/ui/screen.lua | 70 | ||||
| -rw-r--r-- | test/functional/ui/wildmode_spec.lua | 30 | ||||
| -rw-r--r-- | test/functional/viml/completion_spec.lua | 113 | ||||
| -rw-r--r-- | test/helpers.lua | 7 | ||||
| -rw-r--r-- | test/unit/helpers.lua | 12 | ||||
| -rw-r--r-- | test/unit/os/env_spec.lua | 79 | ||||
| -rw-r--r-- | test/unit/search_spec.lua | 33 |
16 files changed, 3653 insertions, 74 deletions
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index d9412f0f13..93599c04f1 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -1,7 +1,9 @@ local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq local curbufmeths, ok = helpers.curbufmeths, helpers.ok +local meths = helpers.meths local funcs = helpers.funcs local request = helpers.request local exc_exec = helpers.exc_exec @@ -11,6 +13,7 @@ local NIL = helpers.NIL local meth_pcall = helpers.meth_pcall local command = helpers.command local bufmeths = helpers.bufmeths +local feed = helpers.feed describe('api/buf', function() before_each(clear) @@ -299,6 +302,38 @@ describe('api/buf', function() local retval = exc_exec("call nvim_buf_set_lines(1, 0, 1, v:false, ['test'])") eq(0, retval) end) + + it("set_lines of invisible buffer doesn't move cursor in current window", function() + local screen = Screen.new(20, 5) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [2] = {bold = true}, + }) + screen:attach() + + insert([[ + Who would win? + A real window + with proper text]]) + local buf = meths.create_buf(false,true) + screen:expect([[ + Who would win? | + A real window | + with proper tex^t | + {1:~ }| + | + ]]) + + meths.buf_set_lines(buf, 0, -1, true, {'or some', 'scratchy text'}) + feed('i') -- provoke redraw + screen:expect([[ + Who would win? | + A real window | + with proper tex^t | + {1:~ }| + {2:-- INSERT --} | + ]]) + end) end) describe('get_offset', function() diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua index b54d9e1f6e..b894d2facd 100644 --- a/test/functional/api/buffer_updates_spec.lua +++ b/test/functional/api/buffer_updates_spec.lua @@ -678,6 +678,32 @@ describe('API: buffer events:', function() expectn('Hello There', {}) end) + it(':edit! (reload) causes detach #9642', function() + local b, tick = editoriginal(true, {'AAA', 'BBB'}) + command('set undoreload=1') + + command('normal! x') + tick = tick + 1 + expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + + command('edit!') + expectn('nvim_buf_detach_event', {b}) + end) + + it(':enew! does not detach hidden buffer', function() + local b, tick = editoriginal(true, {'AAA', 'BBB'}) + local channel = nvim('get_api_info')[1] + + command('set undoreload=1 hidden') + command('normal! x') + tick = tick + 1 + expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + + command('enew!') + eval('rpcnotify('..channel..', "Hello There")') + expectn('Hello There', {}) + end) + it('stays attached if the buffer is hidden', function() local b, tick = editoriginal(true, {'AAA'}) local channel = nvim('get_api_info')[1] diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index b10076c6da..75b9fb71c9 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1359,6 +1359,9 @@ describe('API', function() eq({id=1}, meths.get_current_buf()) local screen = Screen.new(20, 4) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + }) screen:attach() -- @@ -1373,7 +1376,7 @@ describe('API', function() end -- - -- Visiting a scratch-buffer DOES change its properties. + -- Visiting a scratch-buffer DOES NOT change its properties. -- meths.set_current_buf(edited_buf) screen:expect([[ @@ -1381,12 +1384,19 @@ describe('API', function() {1:~ }| {1:~ }| | - ]], { - [1] = {bold = true, foreground = Screen.colors.Blue1}, - }) - eq('', meths.buf_get_option(edited_buf, 'buftype')) - eq('', meths.buf_get_option(edited_buf, 'bufhidden')) + ]]) + eq('nofile', meths.buf_get_option(edited_buf, 'buftype')) + eq('hide', meths.buf_get_option(edited_buf, 'bufhidden')) eq(false, meths.buf_get_option(edited_buf, 'swapfile')) + + -- scratch buffer can be wiped without error + command('bwipe') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + | + ]]) end) end) end) diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 4496e1f644..4ff299cd18 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -286,4 +286,41 @@ describe('API/win', function() ok(not window('is_valid', win)) end) end) + + describe('close', function() + it('can close current window', function() + local oldwin = meths.get_current_win() + command('split') + local newwin = meths.get_current_win() + meths.win_close(newwin,false) + eq({oldwin}, meths.list_wins()) + end) + + it('can close noncurrent window', function() + local oldwin = meths.get_current_win() + command('split') + local newwin = meths.get_current_win() + meths.win_close(oldwin,false) + eq({newwin}, meths.list_wins()) + end) + + it('handles changed buffer', function() + local oldwin = meths.get_current_win() + insert('text') + command('new') + local newwin = meths.get_current_win() + eq({false,"Vim:E37: No write since last change (add ! to override)"}, + meth_pcall(meths.win_close, oldwin,false)) + eq({newwin,oldwin}, meths.list_wins()) + end) + + it('handles changed buffer with force', function() + local oldwin = meths.get_current_win() + insert('text') + command('new') + local newwin = meths.get_current_win() + meths.win_close(oldwin,true) + eq({newwin}, meths.list_wins()) + end) + end) end) diff --git a/test/functional/eval/let_spec.lua b/test/functional/eval/let_spec.lua index 1bd3405698..0cbf40137e 100644 --- a/test/functional/eval/let_spec.lua +++ b/test/functional/eval/let_spec.lua @@ -2,13 +2,16 @@ local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq local clear = helpers.clear +local command = helpers.command +local eval = helpers.eval local meths = helpers.meths local redir_exec = helpers.redir_exec local source = helpers.source +local nvim_dir = helpers.nvim_dir before_each(clear) -describe(':let command', function() +describe(':let', function() it('correctly lists variables with curly-braces', function() meths.set_var('v', {0}) eq('\nv [0]', redir_exec('let {"v"}')) @@ -42,4 +45,38 @@ describe(':let command', function() call feedkeys(":\e:echo l1 l3\n:echo 42\n:cq\n", "t") ]=]) end) + + it("multibyte env var #8398 #9267", function() + command("let $NVIM_TEST = 'AìaB'") + eq('AìaB', eval('$NVIM_TEST')) + command("let $NVIM_TEST = 'AaあB'") + eq('AaあB', eval('$NVIM_TEST')) + local mbyte = [[\p* .ม .ม .ม .ม่ .ม่ .ม่ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ ֹֻ + .ֹֻ .ֹֻ .ֹֻ ֹֻ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ + .ֹֻ .ֹֻ .ֹֻ a a a ca ca ca à à à]] + command("let $NVIM_TEST = '"..mbyte.."'") + eq(mbyte, eval('$NVIM_TEST')) + end) + + it("multibyte env var to child process #8398 #9267", function() + if (not helpers.iswin()) and require('test.helpers').isCI() then + -- Fails on non-Windows CI. Buffering/timing issue? + pending('fails on unix CI', function() end) + end + local cmd_get_child_env = "let g:env_from_child = system(['"..nvim_dir.."/printenv-test', 'NVIM_TEST'])" + command("let $NVIM_TEST = 'AìaB'") + command(cmd_get_child_env) + eq(eval('$NVIM_TEST'), eval('g:env_from_child')) + + command("let $NVIM_TEST = 'AaあB'") + command(cmd_get_child_env) + eq(eval('$NVIM_TEST'), eval('g:env_from_child')) + + local mbyte = [[\p* .ม .ม .ม .ม่ .ม่ .ม่ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ ֹֻ + .ֹֻ .ֹֻ .ֹֻ ֹֻ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ + .ֹֻ .ֹֻ .ֹֻ a a a ca ca ca à à à]] + command("let $NVIM_TEST = '"..mbyte.."'") + command(cmd_get_child_env) + eq(eval('$NVIM_TEST'), eval('g:env_from_child')) + end) end) diff --git a/test/functional/fixtures/CMakeLists.txt b/test/functional/fixtures/CMakeLists.txt index 8537ea390f..a7cd214b6b 100644 --- a/test/functional/fixtures/CMakeLists.txt +++ b/test/functional/fixtures/CMakeLists.txt @@ -3,3 +3,7 @@ target_link_libraries(tty-test ${LIBUV_LIBRARIES}) add_executable(shell-test shell-test.c) add_executable(printargs-test printargs-test.c) +add_executable(printenv-test printenv-test.c) +if(WIN32) + set_target_properties(printenv-test PROPERTIES LINK_FLAGS -municode) +endif() diff --git a/test/functional/fixtures/printenv-test.c b/test/functional/fixtures/printenv-test.c new file mode 100644 index 0000000000..5ac076f653 --- /dev/null +++ b/test/functional/fixtures/printenv-test.c @@ -0,0 +1,59 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include <stdio.h> + +#ifdef WIN32 +# include <windows.h> +#else +# include <stdlib.h> +#endif + +#ifdef WIN32 +int wmain(int argc, wchar_t **argv) +#else +int main(int argc, char **argv) +#endif +{ + if (argc != 2) { + return 1; + } + +#ifdef WIN32 + wchar_t *value = _wgetenv(argv[1]); + if (value == NULL) { + return 1; + } + int utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + value, + -1, + NULL, + 0, + NULL, + NULL); + if (utf8_len == 0) { + return (int)GetLastError(); + } + char *utf8_value = (char *)calloc((size_t)utf8_len, sizeof(char)); + utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + value, + -1, + utf8_value, + utf8_len, + NULL, + NULL); + fprintf(stderr, "%s", utf8_value); + free(utf8_value); +#else + char *value = getenv(argv[1]); + if (value == NULL) { + fprintf(stderr, "env var not found: %s", argv[1]); + return 1; + } + // Print to stderr to avoid buffering. + fprintf(stderr, "%s", value); +#endif + return 0; +} diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index f1ad2bdb95..a0adb45630 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -269,7 +269,7 @@ describe('TUI', function() end) end) -describe('tui with non-tty file descriptors', function() +describe('TUI with non-tty file descriptors', function() before_each(helpers.clear) after_each(function() @@ -277,7 +277,7 @@ describe('tui with non-tty file descriptors', function() end) it('can handle pipes as stdout and stderr', function() - local screen = thelpers.screen_setup(0, '"'..helpers.nvim_prog + local screen = thelpers.screen_setup(0, '"'..nvim_prog ..' -u NONE -i NONE --cmd \'set noswapfile noshowcmd noruler\' --cmd \'normal iabc\' > /dev/null 2>&1 && cat testF && rm testF"') feed_data(':w testF\n:q\n') screen:expect([[ @@ -292,12 +292,12 @@ describe('tui with non-tty file descriptors', function() end) end) -describe('tui FocusGained/FocusLost', function() +describe('TUI FocusGained/FocusLost', function() local screen before_each(function() helpers.clear() - screen = thelpers.screen_setup(0, '["'..helpers.nvim_prog + screen = thelpers.screen_setup(0, '["'..nvim_prog ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]') feed_data(":autocmd FocusGained * echo 'gained'\n") feed_data(":autocmd FocusLost * echo 'lost'\n") @@ -459,7 +459,7 @@ end) -- These tests require `thelpers` because --headless/--embed -- does not initialize the TUI. -describe("tui 't_Co' (terminal colors)", function() +describe("TUI 't_Co' (terminal colors)", function() local screen local is_freebsd = (string.lower(uname()) == 'freebsd') @@ -731,7 +731,7 @@ end) -- These tests require `thelpers` because --headless/--embed -- does not initialize the TUI. -describe("tui 'term' option", function() +describe("TUI 'term' option", function() local screen local is_bsd = not not string.find(string.lower(uname()), 'bsd') local is_macos = not not string.find(string.lower(uname()), 'darwin') @@ -783,7 +783,7 @@ end) -- These tests require `thelpers` because --headless/--embed -- does not initialize the TUI. -describe("tui", function() +describe("TUI", function() local screen local logfile = 'Xtest_tui_verbose_log' after_each(function() @@ -826,3 +826,89 @@ describe("tui", function() end) end) + +describe('TUI background color', function() + local screen + + before_each(function() + clear() + screen = thelpers.screen_setup(0, '["'..nvim_prog + ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]') + end) + + it("triggers OptionSet event on terminal-response", function() + feed_data('\027:autocmd OptionSet background echo "did OptionSet, yay!"\n') + + -- The child Nvim is running asynchronously; wait for it to register the + -- OptionSet handler. + feed_data('\027:autocmd OptionSet\n') + screen:expect({any='--- Autocommands ---'}) + + feed_data('\012') -- CTRL-L: clear the screen + screen:expect([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] 0,0-1 All}| + | + {3:-- TERMINAL --} | + ]]) + feed_data('\027]11;rgb:ffff/ffff/ffff\007') + screen:expect{any='did OptionSet, yay!'} + end) + + local function assert_bg(color, bg) + it('handles '..color..' as '..bg, function() + feed_data('\027]11;rgb:'..color..'\007:echo &background\n') + screen:expect(string.format([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] 0,0-1 All}| + %-5s | + {3:-- TERMINAL --} | + ]], bg)) + end) + end + + assert_bg('0000/0000/0000', 'dark') + assert_bg('ffff/ffff/ffff', 'light') + assert_bg('000/000/000', 'dark') + assert_bg('fff/fff/fff', 'light') + assert_bg('00/00/00', 'dark') + assert_bg('ff/ff/ff', 'light') + assert_bg('0/0/0', 'dark') + assert_bg('f/f/f', 'light') + + assert_bg('f/0/0', 'dark') + assert_bg('0/f/0', 'light') + assert_bg('0/0/f', 'dark') + + assert_bg('1/1/1', 'dark') + assert_bg('2/2/2', 'dark') + assert_bg('3/3/3', 'dark') + assert_bg('4/4/4', 'dark') + assert_bg('5/5/5', 'dark') + assert_bg('6/6/6', 'dark') + assert_bg('7/7/7', 'dark') + assert_bg('8/8/8', 'light') + assert_bg('9/9/9', 'light') + assert_bg('a/a/a', 'light') + assert_bg('b/b/b', 'light') + assert_bg('c/c/c', 'light') + assert_bg('d/d/d', 'light') + assert_bg('e/e/e', 'light') + + assert_bg('0/e/0', 'light') + assert_bg('0/d/0', 'light') + assert_bg('0/c/0', 'dark') + assert_bg('0/b/0', 'dark') + + assert_bg('f/0/f', 'dark') + assert_bg('f/1/f', 'dark') + assert_bg('f/2/f', 'dark') + assert_bg('f/3/f', 'light') + assert_bg('f/4/f', 'light') +end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua new file mode 100644 index 0000000000..2ed3606491 --- /dev/null +++ b/test/functional/ui/float_spec.lua @@ -0,0 +1,3061 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local os = require('os') +local clear, feed = helpers.clear, helpers.feed +local command, feed_command = helpers.command, helpers.feed_command +local eval = helpers.eval +local eq = helpers.eq +local meths = helpers.meths +local curbufmeths = helpers.curbufmeths +local funcs = helpers.funcs +local run = helpers.run +local meth_pcall = helpers.meth_pcall + +describe('floating windows', function() + before_each(function() + clear() + end) + local attrs = { + [0] = {bold=true, foreground=Screen.colors.Blue}, + [1] = {background = Screen.colors.LightMagenta}, + [2] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1}, + [3] = {bold = true}, + [4] = {bold = true, reverse = true}, + [5] = {reverse = true}, + [6] = {background = Screen.colors.LightMagenta, bold = true, reverse = true}, + [7] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + [8] = {bold = true, foreground = Screen.colors.SeaGreen4}, + [9] = {background = Screen.colors.LightGrey, underline = true}, + [10] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta}, + [11] = {bold = true, foreground = Screen.colors.Magenta}, + [12] = {background = Screen.colors.Red, bold = true, foreground = Screen.colors.Blue1}, + [13] = {background = Screen.colors.WebGray} + } + + local function with_ext_multigrid(multigrid) + local screen + before_each(function() + screen = Screen.new(40,7) + screen:attach({ext_multigrid=multigrid}) + screen:set_default_attr_ids(attrs) + end) + + it('can be created and reconfigured', function() + local buf = meths.create_buf(false,false) + local win = meths.open_win(buf, false, 20, 2, {relative='editor', row=2, col=5}) + meths.win_set_option(win , 'winhl', 'Normal:PMenu') + local expected_pos = { + [3]={{id=1001}, 'NW', 1, 2, 5, true}, + } + + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1: }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ | + {0:~ }| + {0:~ }{1: }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + + meths.win_config(win,0,0,{relative='editor', row=0, col=10}) + expected_pos[3][4] = 0 + expected_pos[3][5] = 10 + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1: }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ {1: } | + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end + + meths.win_close(win, false) + if multigrid then + screen:expect([[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]]) + else + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it('API has proper error messages', function() + local buf = meths.create_buf(false,false) + eq({false, "Invalid options key 'bork'"}, + meth_pcall(meths.open_win,buf, false, 20, 2, {bork=true})) + eq({false, "'win' option is only valid with relative='win'"}, + meth_pcall(meths.open_win,buf, false, 20, 2, {relative='editor',row=0,col=0,win=0})) + eq({false, "Only one of 'relative' and 'external' should be used"}, + meth_pcall(meths.open_win,buf, false, 20, 2, {relative='editor',row=0,col=0,external=true})) + eq({false, "Invalid value of 'relative' option"}, + meth_pcall(meths.open_win,buf, false, 20, 2, {relative='shell',row=0,col=0})) + eq({false, "Invalid value of 'anchor' option"}, + meth_pcall(meths.open_win,buf, false, 20, 2, {relative='editor',row=0,col=0,anchor='bottom'})) + eq({false, "All of 'relative', 'row', and 'col' has to be specified at once"}, + meth_pcall(meths.open_win,buf, false, 20, 2, {relative='editor'})) + end) + + it('can be placed relative window or cursor', function() + screen:try_resize(40,9) + meths.buf_set_lines(0, 0, -1, true, {'just some', 'example text'}) + feed('gge') + local oldwin = meths.get_current_win() + command('below split') + if multigrid then + screen:expect([[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + just some | + example text | + {0:~ }| + ## grid 3 + jus^t some | + example text | + {0:~ }| + ]]) + else + screen:expect([[ + just some | + example text | + {0:~ }| + {5:[No Name] [+] }| + jus^t some | + example text | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + local buf = meths.create_buf(false,false) + -- no 'win' arg, relative default window + local win = meths.open_win(buf, false, 20, 2, {relative='win', row=0, col=10}) + meths.win_set_option(win, 'winhl', 'Normal:PMenu') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + just some | + example text | + {0:~ }| + ## grid 3 + jus^t some | + example text | + {0:~ }| + ## grid 4 + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1002}, "NW", 3, 0, 10, true} + }} + else + screen:expect([[ + just some | + example text | + {0:~ }| + {5:[No Name] [+] }| + jus^t some {1: } | + example te{2:~ } | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + meths.win_config(win, -1, -1, {relative='cursor', row=1, col=-2}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + just some | + example text | + {0:~ }| + ## grid 3 + jus^t some | + example text | + {0:~ }| + ## grid 4 + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1002}, "NW", 3, 1, 1, true} + }} + else + screen:expect([[ + just some | + example text | + {0:~ }| + {5:[No Name] [+] }| + jus^t some | + e{1: } | + {0:~}{2:~ }{0: }| + {4:[No Name] [+] }| + | + ]]) + end + + meths.win_config(win, -1, -1, {relative='cursor', row=0, col=0, anchor='SW'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + just some | + example text | + {0:~ }| + ## grid 3 + jus^t some | + example text | + {0:~ }| + ## grid 4 + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1002}, "SW", 3, 0, 3, true} + }} + else + screen:expect([[ + just some | + example text | + {0:~ }{1: }{0: }| + {5:[No}{2:~ }{5: }| + jus^t some | + example text | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + + meths.win_config(win, -1, -1, {relative='win', win=oldwin, row=1, col=10, anchor='NW'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + just some | + example text | + {0:~ }| + ## grid 3 + jus^t some | + example text | + {0:~ }| + ## grid 4 + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1002}, "NW", 2, 1, 10, true} + }} + else + screen:expect([[ + just some | + example te{1: } | + {0:~ }{2:~ }{0: }| + {5:[No Name] [+] }| + jus^t some | + example text | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + meths.win_config(win, -1, -1, {relative='win', win=oldwin, row=3, col=39, anchor='SE'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + just some | + example text | + {0:~ }| + ## grid 3 + jus^t some | + example text | + {0:~ }| + ## grid 4 + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1002}, "SE", 2, 3, 39, true} + }} + else + screen:expect([[ + just some | + example text {1: } | + {0:~ }{2:~ }{0: }| + {5:[No Name] [+] }| + jus^t some | + example text | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + meths.win_config(win, -1, -1, {relative='win', win=0, row=0, col=50, anchor='NE'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + just some | + example text | + {0:~ }| + ## grid 3 + jus^t some | + example text | + {0:~ }| + ## grid 4 + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1002}, "NE", 3, 0, 50, true} + }} + else + screen:expect([[ + just some | + example text | + {0:~ }| + {5:[No Name] [+] }| + jus^t some {1: }| + example text {2:~ }| + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + end) + + if multigrid then + pending("supports second UI without multigrid", function() + local session2 = helpers.connect(eval('v:servername')) + print(session2:request("nvim_eval", "2+2")) + local screen2 = Screen.new(40,7) + screen2:attach(nil, session2) + screen2:set_default_attr_ids(attrs) + local buf = meths.create_buf(false,false) + local win = meths.open_win(buf, true, 20, 2, {relative='editor', row=2, col=5}) + meths.win_set_option(win, 'winhl', 'Normal:PMenu') + local expected_pos = { + [2]={{id=1001}, 'NW', 1, 2, 5} + } + screen:expect{grid=[[ + ## grid 1 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ## grid 2 + {1:^ }| + {2:~ }| + ]], float_pos=expected_pos} + screen2:expect([[ + | + {0:~ }| + {0:~ }{1:^ }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end) + end + + + it('handles resized screen', function() + local buf = meths.create_buf(false,false) + meths.buf_set_lines(buf, 0, -1, true, {'such', 'very', 'float'}) + local win = meths.open_win(buf, false, 15, 4, {relative='editor', row=2, col=10}) + meths.win_set_option(win , 'winhl', 'Normal:PMenu') + local expected_pos = { + [4]={{id=1002}, 'NW', 1, 2, 10, true}, + } + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:such }| + {1:very }| + {1:float }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ | + {0:~ }| + {0:~ }{1:such }{0: }| + {0:~ }{1:very }{0: }| + {0:~ }{1:float }{0: }| + {0:~ }{2:~ }{0: }| + | + ]]) + end + + screen:try_resize(40,5) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:such }| + {1:very }| + {1:float }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ {1:such } | + {0:~ }{1:very }{0: }| + {0:~ }{1:float }{0: }| + {0:~ }{2:~ }{0: }| + | + ]]) + end + + screen:try_resize(40,4) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + ## grid 4 + {1:such }| + {1:very }| + {1:float }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ {1:such } | + {0:~ }{1:very }{0: }| + {0:~ }{1:float }{0: }| + | + ]]) + end + + screen:try_resize(40,3) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^ | + {0:~ }| + ## grid 4 + {1:such }| + {1:very }| + {1:float }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ {1:such } | + {0:~ }{1:very }{0: }| + | + ]]) + end + feed('<c-w>wjj') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + | + {0:~ }| + ## grid 4 + {1:such }| + {1:very }| + {1:^float }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + {1:very } | + {0:~ }{1:^float }{0: }| + | + ]]) + end + + screen:try_resize(40,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:such }| + {1:very }| + {1:^float }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{1:very }{0: }| + {0:~ }{1:^float }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + meths.win_config(win, -1, 3, {}) + feed('gg') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{1:^such }{0: }| + {0:~ }{1:very }{0: }| + {0:~ }{1:float }{0: }| + {0:~ }| + | + ]]) + end + + screen:try_resize(26,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:--------------------------]| + [2:--------------------------]| + [2:--------------------------]| + [2:--------------------------]| + [2:--------------------------]| + [2:--------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{1:^such }{0: }| + {0:~ }{1:very }{0: }| + {0:~ }{1:float }{0: }| + {0:~ }| + | + ]]) + end + + screen:try_resize(25,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{1:^such }| + {0:~ }{1:very }| + {0:~ }{1:float }| + {0:~ }| + | + ]]) + end + + screen:try_resize(24,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:------------------------]| + [2:------------------------]| + [2:------------------------]| + [2:------------------------]| + [2:------------------------]| + [2:------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{1:^such }| + {0:~ }{1:very }| + {0:~ }{1:float }| + {0:~ }| + | + ]]) + end + + screen:try_resize(16,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------]| + [2:----------------]| + [2:----------------]| + [2:----------------]| + [2:----------------]| + [2:----------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {0:~}{1:^such }| + {0:~}{1:very }| + {0:~}{1:float }| + {0:~ }| + | + ]]) + end + + screen:try_resize(15,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------]| + [2:---------------]| + [2:---------------]| + [2:---------------]| + [2:---------------]| + [2:---------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {1:^such }| + {1:very }| + {1:float }| + {0:~ }| + | + ]]) + end + + screen:try_resize(14,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:--------------]| + [2:--------------]| + [2:--------------]| + [2:--------------]| + [2:--------------]| + [2:--------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {1:^such }| + {1:very }| + {1:float }| + {0:~ }| + | + ]]) + end + + screen:try_resize(12,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:------------]| + [2:------------]| + [2:------------]| + [2:------------]| + [2:------------]| + [2:------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {1:^such }| + {1:very }| + {1:float }| + {0:~ }| + | + ]]) + end + + -- Doesn't make much sense, but check nvim doesn't crash + screen:try_resize(1,1) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:------------]| + | + ## grid 2 + | + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + {1:^such }| + | + ]]) + end + + screen:try_resize(40,7) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 4 + {1:^such }| + {1:very }| + {1:float }| + ]], float_pos=expected_pos} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{1:^such }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + describe('and completion', function() + before_each(function() + local buf = meths.create_buf(false,false) + local win = meths.open_win(buf, true, 12, 4, {relative='editor', row=2, col=5}) + meths.win_set_option(win , 'winhl', 'Normal:ErrorMsg') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:^ }| + {12:~ }| + {12:~ }| + {12:~ }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + }} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{7:^ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + | + ]]) + end + end) + + it('with builtin popupmenu', function() + feed('ix ') + funcs.complete(3, {'aa', 'word', 'longtext'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x aa^ }| + {12:~ }| + {12:~ }| + {12:~ }| + ## grid 4 + {13: aa }| + {1: word }| + {1: longtext }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + [4] = {{ id = -1 }, "NW", 3, 1, 1, false} + }} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{7:x aa^ }{0: }| + {0:~ }{12:~}{13: aa }{0: }| + {0:~ }{12:~}{1: word }{0: }| + {0:~ }{12:~}{1: longtext }{0: }| + {3:-- INSERT --} | + ]]) + end + + feed('<esc>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x a^a }| + {12:~ }| + {12:~ }| + {12:~ }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + }} + + else + screen:expect([[ + | + {0:~ }| + {0:~ }{7:x a^a }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + | + ]]) + end + + feed('<c-w>wi') + funcs.complete(1, {'xx', 'yy', 'zz'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + xx^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x aa }| + {12:~ }| + {12:~ }| + {12:~ }| + ## grid 4 + {13:xx }| + {1:yy }| + {1:zz }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + [4] = {{ id = -1 }, "NW", 2, 1, 0, false} + }} + else + screen:expect([[ + xx^ | + {13:xx }{0: }| + {1:yy }{7: }{0: }| + {1:zz }{12: }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {3:-- INSERT --} | + ]]) + end + + feed('<c-y>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + xx^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x aa }| + {12:~ }| + {12:~ }| + {12:~ }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + }} + else + screen:expect([[ + xx^ | + {0:~ }| + {0:~ }{7:x aa }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {3:-- INSERT --} | + ]]) + end + end) + + it('with ext_popupmenu', function() + screen:set_option('ext_popupmenu', true) + feed('ix ') + funcs.complete(3, {'aa', 'word', 'longtext'}) + local items = {{"aa", "", "", ""}, {"word", "", "", ""}, {"longtext", "", "", ""}} + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x aa^ }| + {12:~ }| + {12:~ }| + {12:~ }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + }, popupmenu={ + anchor = {0, 2, 3}, items = items, pos = 0 + }} + else + screen:expect{grid=[[ + | + {0:~ }| + {0:~ }{7:x aa^ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {3:-- INSERT --} | + ]], popupmenu={ + anchor = {2, 7}, items = items, pos = 0 + }} + end + + feed('<esc>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x a^a }| + {12:~ }| + {12:~ }| + {12:~ }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + }} + else + screen:expect([[ + | + {0:~ }| + {0:~ }{7:x a^a }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + | + ]]) + end + + feed('<c-w>wi') + funcs.complete(1, {'xx', 'yy', 'zz'}) + items = {{"xx", "", "", ""}, {"yy", "", "", ""}, {"zz", "", "", ""}} + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + xx^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x aa }| + {12:~ }| + {12:~ }| + {12:~ }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + }, popupmenu={ + anchor = {0, 0, 2}, items = items, pos = 0 + }} + else + screen:expect{grid=[[ + xx^ | + {0:~ }| + {0:~ }{7:x aa }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {3:-- INSERT --} | + ]], popupmenu={ + anchor = {0, 0}, items = items, pos = 0 + }} + end + + feed('<c-y>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + xx^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {7:x aa }| + {12:~ }| + {12:~ }| + {12:~ }| + ]], float_pos={ + [3] = {{ id = 1001 }, "NW", 1, 2, 5, true}, + }} + else + screen:expect([[ + xx^ | + {0:~ }| + {0:~ }{7:x aa }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {0:~ }{12:~ }{0: }| + {3:-- INSERT --} | + ]]) + end + end) + + end) + + + describe("handles :wincmd", function() + local win + local expected_pos + before_each(function() + -- the default, but be explicit: + command("set laststatus=1") + command("set hidden") + meths.buf_set_lines(0,0,-1,true,{"x"}) + local buf = meths.create_buf(false,false) + win = meths.open_win(buf, false, 20, 2, {relative='editor', row=2, col=5}) + meths.buf_set_lines(buf,0,-1,true,{"y"}) + meths.win_set_option(win , 'winhl', 'Normal:PMenu') + expected_pos = { + [3]={{id=1001}, 'NW', 1, 2, 5, true} + } + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("w", function() + feed("<c-w>w") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {0:~ }{1:^y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + feed("<c-w>w") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("w with focusable=false", function() + meths.win_config(win, -1, -1, {focusable=false}) + expected_pos[3][6] = false + feed("<c-w>wi") -- i to provoke redraw + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + {3:-- INSERT --} | + ]]) + end + + feed("<esc><c-w>w") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("W", function() + feed("<c-w>W") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {0:~ }{1:^y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + feed("<c-w>W") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("focus by mouse", function() + if multigrid then + meths.input_mouse('left', 'press', '', 3, 0, 0) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]], float_pos=expected_pos} + else + meths.input_mouse('left', 'press', '', 0, 2, 5) + screen:expect([[ + x | + {0:~ }| + {0:~ }{1:^y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + if multigrid then + meths.input_mouse('left', 'press', '', 1, 0, 0) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + meths.input_mouse('left', 'press', '', 0, 0, 0) + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("focus by mouse (focusable=false)", function() + meths.win_config(win, -1, -1, {focusable=false}) + meths.buf_set_lines(0, -1, -1, true, {"a"}) + expected_pos[3][6] = false + if multigrid then + meths.input_mouse('left', 'press', '', 3, 0, 0) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + a | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + meths.input_mouse('left', 'press', '', 0, 2, 5) + screen:expect([[ + x | + ^a | + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + if multigrid then + meths.input_mouse('left', 'press', '', 1, 0, 0) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + a | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos, unchanged=true} + else + meths.input_mouse('left', 'press', '', 0, 0, 0) + screen:expect([[ + ^x | + a | + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + + it("j", function() + feed("<c-w>ji") -- INSERT to trigger screen change + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {3:-- INSERT --} | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + {3:-- INSERT --} | + ]]) + end + + feed("<esc><c-w>w") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {0:~ }{1:^y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + feed("<c-w>j") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + + end) + + it("s :split (non-float)", function() + feed("<c-w>s") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {4:[No N}{1:y }{4: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + | + ]]) + end + + feed("<c-w>w") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {5:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + ^x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {5:[No N}{1:y }{5: }| + ^x {2:~ } | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + feed("<c-w>w") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {5:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ## grid 4 + x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {5:[No N}{1:^y }{5: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + | + ]]) + end + + + feed("<c-w>w") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {4:[No N}{1:y }{4: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + | + ]]) + end + end) + + it("s :split (float)", function() + feed("<c-w>w<c-w>s") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + {1:^y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + {1:^y }| + {2:~ }| + {4:[No N}{1:y }{4: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + | + ]]) + end + + feed(":set winhighlight=<cr><c-l>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^y | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^y | + {0:~ }| + {4:[No N}{1:y }{4: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + | + ]]) + end + + + feed("<c-w>j") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {5:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + ^x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + y | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + y | + {0:~ }| + {5:[No N}{1:y }{5: }| + ^x {2:~ } | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + feed("<c-w>ji") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {5:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {4:[No Name] [+] }| + {3:-- INSERT --} | + ## grid 2 + ^x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + y | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + y | + {0:~ }| + {5:[No N}{1:y }{5: }| + ^x {2:~ } | + {0:~ }| + {4:[No Name] [+] }| + {3:-- INSERT --} | + ]]) + end + end) + + it(":new (non-float)", function() + feed(":new<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + :new | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ | + {0:~ }| + {4:[No N}{1:y }{4: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + :new | + ]]) + end + end) + + it(":new (float)", function() + feed("<c-w>w:new<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + :new | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ | + {0:~ }| + {4:[No N}{1:y }{4: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + :new | + ]]) + end + end) + + it("v :vsplit (non-float)", function() + feed("<c-w>v") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + {4:[No Name] [+] }{5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x {5:│}x | + {0:~ }{5:│}{0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }{5:│}{0:~ }| + {4:[No Name] [+] }{5:[No Name] [+] }| + | + ]]) + end + end) + + it(":vnew (non-float)", function() + feed(":vnew<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + {4:[No Name] }{5:[No Name] [+] }| + :vnew | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ {5:│}x | + {0:~ }{5:│}{0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }{5:│}{0:~ }| + {4:[No Name] }{5:[No Name] [+] }| + :vnew | + ]]) + end + end) + + it(":vnew (float)", function() + feed("<c-w>w:vnew<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + [4:--------------------]{5:│}[2:-------------------]| + {4:[No Name] }{5:[No Name] [+] }| + :vnew | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^ {5:│}x | + {0:~ }{5:│}{0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }{5:│}{0:~ }| + {4:[No Name] }{5:[No Name] [+] }| + :vnew | + ]]) + end + end) + + it("q (:quit) last non-float exits nvim", function() + command('autocmd VimLeave * call rpcrequest(1, "exit")') + -- avoid unsaved change in other buffer + feed("<c-w><c-w>:w Xtest_written2<cr><c-w><c-w>") + -- quit in last non-float + feed(":wq Xtest_written<cr>") + local exited = false + local function on_request(name, args) + eq("exit", name) + eq({}, args) + exited = true + return 0 + end + local function on_setup() + feed(":wq Xtest_written<cr>") + end + run(on_request, nil, on_setup) + os.remove('Xtest_written') + os.remove('Xtest_written2') + eq(exited, true) + end) + + it("o (:only) non-float", function() + feed("<c-w>o") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]]} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("o (:only) float fails", function() + feed("<c-w>w<c-w>o") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {4: }| + {7:E5601: Cannot close window, only floatin}| + {7:g window would remain} | + {8:Press ENTER or type command to continue}^ | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {0:~ }{1:y }{0: }| + {4: }| + {7:E5601: Cannot close window, only floatin}| + {7:g window would remain} | + {8:Press ENTER or type command to continue}^ | + ]]) + end + + -- test message clear + feed('<cr>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {0:~ }{1:^y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("o (:only) non-float with split", function() + feed("<c-w>s") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {4:[No N}{1:y }{4: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + | + ]]) + end + + feed("<c-w>o") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + | + ## grid 4 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]]} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end + end) + + it("o (:only) float with split", function() + feed("<c-w>s<c-w>W") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {5:[No Name] [+] }| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ## grid 4 + x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {5:[No N}{1:^y }{5: }| + x {2:~ } | + {0:~ }| + {5:[No Name] [+] }| + | + ]]) + end + + feed("<c-w>o") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:----------------------------------------]| + [4:----------------------------------------]| + {5:[No Name] [+] }| + {4: }| + {7:E5601: Cannot close window, only floatin}| + {7:g window would remain} | + {8:Press ENTER or type command to continue}^ | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x | + {0:~ }| + {5:[No N}{1:y }{5: }| + {4: }| + {7:E5601: Cannot close window, only floatin}| + {7:g window would remain} | + {8:Press ENTER or type command to continue}^ | + ]]) + end + end) + + it("J (float)", function() + feed("<c-w>w<c-w>J") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]]} + else + screen:expect([[ + x | + {0:~ }| + {5:[No Name] [+] }| + {1:^y }| + {2:~ }| + {4:[No Name] [+] }| + | + ]]) + end + + if multigrid then + meths.win_config(0,-1,-1,{external=true}) + expected_pos = {[3]={external=true}} + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]], float_pos=expected_pos} + else + eq({false, "UI doesn't support external windows"}, + meth_pcall(meths.win_config, 0,-1,-1,{external=true})) + return + end + + feed("<c-w>J") + if multigrid then + screen:expect([[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [3:----------------------------------------]| + [3:----------------------------------------]| + {4:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:^y }| + {2:~ }| + ]]) + end + + end) + + it('movements with nested split layout', function() + command("set hidden") + feed("<c-w>s<c-w>v<c-w>b<c-w>v") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [5:--------------------]{5:│}[4:-------------------]| + [5:--------------------]{5:│}[4:-------------------]| + {5:[No Name] [+] [No Name] [+] }| + [6:--------------------]{5:│}[2:-------------------]| + [6:--------------------]{5:│}[2:-------------------]| + {4:[No Name] [+] }{5:[No Name] [+] }| + | + ## grid 2 + x | + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + x | + {0:~ }| + ## grid 5 + x | + {0:~ }| + ## grid 6 + ^x | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + x {5:│}x | + {0:~ }{5:│}{0:~ }| + {5:[No N}{1:y }{5:Name] [+] }| + ^x {2:~ } | + {0:~ }{5:│}{0:~ }| + {4:[No Name] [+] }{5:[No Name] [+] }| + | + ]]) + end + + -- verify that N<c-w>w works + for i = 1,5 do + feed(i.."<c-w>w") + feed_command("enew") + curbufmeths.set_lines(0,-1,true,{tostring(i)}) + end + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [5:-------------------]{5:│}[4:--------------------]| + [5:-------------------]{5:│}[4:--------------------]| + {5:[No Name] [+] [No Name] [+] }| + [6:-------------------]{5:│}[2:--------------------]| + [6:-------------------]{5:│}[2:--------------------]| + {5:[No Name] [+] [No Name] [+] }| + :enew | + ## grid 2 + 4 | + {0:~ }| + ## grid 3 + ^5 | + {0:~ }| + ## grid 4 + 2 | + {0:~ }| + ## grid 5 + 1 | + {0:~ }| + ## grid 6 + 3 | + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + 1 {5:│}2 | + {0:~ }{5:│}{0:~ }| + {5:[No N}^5 {5:ame] [+] }| + 3 {0:~ } | + {0:~ }{5:│}{0:~ }| + {5:[No Name] [+] [No Name] [+] }| + :enew | + ]]) + end + + local movements = { + w={2,3,4,5,1}, + W={5,1,2,3,4}, + h={1,1,3,3,3}, + j={3,3,3,4,4}, + k={1,2,1,1,1}, + l={2,2,4,4,4}, + t={1,1,1,1,1}, + b={4,4,4,4,4}, + } + + for k,v in pairs(movements) do + for i = 1,5 do + feed(i.."<c-w>w") + feed('<c-w>'..k) + local nr = funcs.winnr() + eq(v[i],nr, "when using <c-w>"..k.." from window "..i) + end + end + + for i = 1,5 do + feed(i.."<c-w>w") + for j = 1,5 do + if j ~= i then + feed(j.."<c-w>w") + feed('<c-w>p') + local nr = funcs.winnr() + eq(i,nr, "when using <c-w>p to window "..i.." from window "..j) + end + end + end + + end) + + it(":tabnew and :tabnext", function() + feed(":tabnew<cr>") + if multigrid then + -- grid is not freed, but float is marked as closed (should it rather be "invisible"?) + screen:expect{grid=[[ + ## grid 1 + {9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + :tabnew | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]]} + else + screen:expect([[ + {9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}| + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + :tabnew | + ]]) + end + + feed(":tabnext<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + {3: }{11:2}{3:+ [No Name] }{9: [No Name] }{5: }{9:X}| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {4:[No Name] [+] }| + :tabnext | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]], float_pos=expected_pos} + else + screen:expect([[ + {3: }{11:2}{3:+ [No Name] }{9: [No Name] }{5: }{9:X}| + ^x | + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {4:[No Name] [+] }| + :tabnext | + ]]) + end + + feed(":tabnext<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + {9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + :tabnext | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]]} + else + screen:expect([[ + {9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}| + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + :tabnext | + ]]) + end + end) + + it(":tabnew and :tabnext (external)", function() + if multigrid then + meths.win_config(win,-1,-1,{external=true}) + expected_pos = {[3]={external=true}} + feed(":tabnew<cr>") + screen:expect{grid=[[ + ## grid 1 + {9: + [No Name] }{3: }{11:2}{3:+ [No Name] }{5: }{9:X}| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + :tabnew | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]], float_pos=expected_pos} + else + eq({false, "UI doesn't support external windows"}, + meth_pcall(meths.win_config, 0,-1,-1,{external=true})) + end + + feed(":tabnext<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + {3: }{11:2}{3:+ [No Name] }{9: [No Name] }{5: }{9:X}| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + {4:[No Name] [+] }| + :tabnext | + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]], float_pos=expected_pos} + end + + feed(":tabnext<cr>") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + {9: + [No Name] }{3: }{11:2}{3:+ [No Name] }{5: }{9:X}| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] }| + :tabnext | + ## grid 2 + x | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {1:y }| + {2:~ }| + ## grid 4 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + ]], float_pos=expected_pos} + end + end) + end) + end + + describe('with ext_multigrid', function() + with_ext_multigrid(true) + end) + describe('without ext_multigrid', function() + with_ext_multigrid(false) + end) + +end) + diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 2eae549ebd..8b1b77eb81 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -158,6 +158,7 @@ function Screen.new(width, height) wildmenu_items = nil, wildmenu_selected = nil, win_position = {}, + float_pos = {}, _session = nil, messages = {}, msg_history = {}, @@ -227,10 +228,9 @@ function Screen:attach(options, session) -- simplify test code by doing the same. self._options.rgb = true end - if self._options.ext_multigrid then + if self._options.ext_multigrid or self._options.ext_float then self._options.ext_linegrid = true end - self._session = session end function Screen:detach() @@ -256,7 +256,7 @@ end -- canonical order of ext keys, used to generate asserts local ext_keys = { 'popupmenu', 'cmdline', 'cmdline_block', 'wildmenu_items', 'wildmenu_pos', - 'messages', 'showmode', 'showcmd', 'ruler', + 'messages', 'showmode', 'showcmd', 'ruler', 'float_pos', } -- Asserts that the screen state eventually matches an expected state @@ -642,7 +642,7 @@ function Screen:_handle_grid_resize(grid, width, height) end if self._cursor.grid == grid then - self._cursor.row = 1 + self._cursor.row = 1 -- -1 ? self._cursor.col = 1 end self._grids[grid] = { @@ -676,7 +676,6 @@ function Screen:_reset() self.wildmenu_pos = nil end - function Screen:_handle_mode_info_set(cursor_style_enabled, mode_info) self._cursor_style_enabled = cursor_style_enabled for _, item in pairs(mode_info) do @@ -713,7 +712,6 @@ end function Screen:_handle_grid_destroy(grid) self._grids[grid] = nil if self._options.ext_multigrid then - assert(self.win_position[grid]) self.win_position[grid] = nil end end @@ -734,6 +732,36 @@ function Screen:_handle_grid_cursor_goto(grid, row, col) self._cursor.col = col + 1 end +function Screen:_handle_win_pos(grid, win, startrow, startcol, width, height) + self.win_position[grid] = { + win = win, + startrow = startrow, + startcol = startcol, + width = width, + height = height + } + self.float_pos[grid] = nil +end + +function Screen:_handle_win_float_pos(grid, ...) + self.win_position[grid] = nil + self.float_pos[grid] = {...} +end + +function Screen:_handle_win_external_pos(grid) + self.win_position[grid] = nil + self.float_pos[grid] = {external=true} +end + +function Screen:_handle_win_hide(grid) + self.win_position[grid] = nil + self.float_pos[grid] = nil +end + +function Screen:_handle_win_close(grid) + self.float_pos[grid] = nil +end + function Screen:_handle_busy_start() self._busy = true end @@ -815,20 +843,6 @@ function Screen:_handle_hl_attr_define(id, rgb_attrs, cterm_attrs, info) self._new_attrs = true end -function Screen:_handle_win_pos(grid, win, startrow, startcol, width, height) - self.win_position[grid] = { - win = win, - startrow = startrow, - startcol = startcol, - width = width, - height = height - } -end - -function Screen:_handle_win_hide(grid) - self.win_position[grid] = nil -end - function Screen:get_hl(val) if self._options.ext_newgrid then return self._attr_table[val][1] @@ -922,8 +936,11 @@ function Screen:_handle_option_set(name, value) self.options[name] = value end -function Screen:_handle_popupmenu_show(items, selected, row, col) - self.popupmenu = {items=items, pos=selected, anchor={row, col}} +function Screen:_handle_popupmenu_show(items, selected, row, col, grid) + if (not self._options.ext_multigrid) and grid == 1 then + grid = nil + end + self.popupmenu = {items=items, pos=selected, anchor={row, col, grid}} end function Screen:_handle_popupmenu_select(selected) @@ -1112,6 +1129,7 @@ function Screen:_extstate_repr(attr_state) showcmd=self:_chunks_repr(self.showcmd, attr_state), ruler=self:_chunks_repr(self.ruler, attr_state), msg_history=msg_history, + float_pos=self.float_pos } end @@ -1146,7 +1164,10 @@ function Screen:redraw_debug(attrs, ignore, timeout) local function notification_cb(method, args) assert(method == 'redraw') for _, update in ipairs(args) do - print(require('inspect')(update)) + -- mode_info_set is quite verbose, comment out the condition to debug it. + if update[1] ~= "mode_info_set" then + print(inspect(update)) + end end self:_redraw(args) self:print_snapshot(attrs, ignore) @@ -1159,7 +1180,7 @@ function Screen:redraw_debug(attrs, ignore, timeout) end function Screen:render(headers, attr_state, preview) - headers = headers and self._options.ext_multigrid + headers = headers and (self._options.ext_multigrid or self._options._debug_float) local rv = {} for igrid,grid in pairs(self._grids) do if headers then @@ -1227,6 +1248,7 @@ function Screen:print_snapshot(attrs, ignore) io.stdout:write( "]]"..attrstr) for _, k in ipairs(ext_keys) do if ext_state[k] ~= nil then + -- TODO(bfredl): improve formating, remove ext metatables io.stdout:write(", "..k.."="..inspect(ext_state[k])) end end diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index ffe71cfadf..7cd09fb222 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -171,19 +171,21 @@ end) describe('command line completion', function() local screen - before_each(function() - clear() screen = Screen.new(40, 5) - screen:attach() - screen:set_default_attr_ids({[1]={bold=true, foreground=Screen.colors.Blue}}) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow}, + [3] = {bold = true, reverse = true}, + }) end) - after_each(function() os.remove('Xtest-functional-viml-compl-dir') end) it('lists directories with empty PATH', function() + clear() + screen:attach() local tmp = funcs.tempname() command('e '.. tmp) command('cd %:h') @@ -198,6 +200,24 @@ describe('command line completion', function() :!Xtest-functional-viml-compl-dir^ | ]]) end) + + it('completes (multibyte) env var names #9655', function() + clear({env={ + ['XTEST_1AaあB']='foo', + ['XTEST_2']='bar', + }}) + screen:attach() + command('set wildmode=full') + command('set wildmenu') + feed(':!echo $XTEST_<tab>') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {2:XTEST_1AaあB}{3: XTEST_2 }| + :!echo $XTEST_1AaあB^ | + ]]) + end) end) describe('ui/ext_wildmenu', function() diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua index 70b4717c32..cd1b312265 100644 --- a/test/functional/viml/completion_spec.lua +++ b/test/functional/viml/completion_spec.lua @@ -466,6 +466,7 @@ describe('completion', function() ]]) expect('August') end) + it("repeats correctly after backspace #2674", function () feed('o<C-x><C-u>Ja') screen:expect([[ @@ -712,6 +713,118 @@ describe('completion', function() end) end) + it("does not indent until an item is selected #8345", function () + -- Indents on "ind", unindents on "unind". + source([[ + function! TestIndent() + let line = getline(v:lnum) + if (line =~ '^\s*ind') + return indent(v:lnum-1) + shiftwidth() + elseif (line =~ '^\s*unind') + return indent(v:lnum-1) - shiftwidth() + else + return indent(v:lnum-1) + endif + endfunction + set indentexpr=TestIndent() + set indentkeys=o,O,!^F,=ind,=unind + set completeopt+=menuone + ]]) + + -- Give some words to complete. + feed("iinc uninc indent unindent<CR>") + + -- Does not indent when "ind" is typed. + feed("in<C-X><C-N>") + -- Completion list is generated incorrectly if we send everything at once + -- via nvim_input(). So wait() before sending <BS>. #8480 + wait() + feed("<BS>d") + + screen:expect([[ + inc uninc indent unindent | + ind^ | + {2:indent }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + ]]) + + -- Indents when the item is selected + feed("<C-Y>") + screen:expect([[ + inc uninc indent unindent | + indent^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:-- INSERT --} | + ]]) + -- Indents when completion is exited using ESC. + feed("<CR>in<C-N><BS>d<Esc>") + screen:expect([[ + inc uninc indent unindent | + indent | + in^d | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + -- Works for unindenting too. + feed("ounin<C-X><C-N>") + helpers.wait() + feed("<BS>d") + screen:expect([[ + inc uninc indent unindent | + indent | + ind | + unind^ | + {0:~ }{2: unindent }{0: }| + {0:~ }| + {0:~ }| + {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + ]]) + -- Works when going back and forth. + feed("<BS>c") + screen:expect([[ + inc uninc indent unindent | + indent | + ind | + uninc^ | + {0:~ }{2: uninc }{0: }| + {0:~ }| + {0:~ }| + {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + ]]) + feed("<BS>d") + screen:expect([[ + inc uninc indent unindent | + indent | + ind | + unind^ | + {0:~ }{2: unindent }{0: }| + {0:~ }| + {0:~ }| + {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + ]]) + feed("<C-N><C-N><C-Y><Esc>") + screen:expect([[ + inc uninc indent unindent | + indent | + ind | + uninden^t | + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end) it('disables folding during completion', function () feed_command("set foldmethod=indent") diff --git a/test/helpers.lua b/test/helpers.lua index 59da274e87..e4c3019adc 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -47,8 +47,8 @@ local check_logs_useless_lines = { ['See README_MISSING_SYSCALL_OR_IOCTL for guidance']=3, } -local function eq(expected, actual, ctx) - return assert.are.same(expected, actual, ctx) +local function eq(expected, actual, context) + return assert.are.same(expected, actual, context) end local function neq(expected, actual, context) return assert.are_not.same(expected, actual, context) @@ -708,7 +708,7 @@ end local function isCI() local is_travis = nil ~= os.getenv('TRAVIS') local is_appveyor = nil ~= os.getenv('APPVEYOR') - local is_quickbuild = nil ~= os.getenv('PR_NUMBER') + local is_quickbuild = nil ~= lfs.attributes('/usr/home/quickbuild') return is_travis or is_appveyor or is_quickbuild end @@ -751,6 +751,7 @@ local module = { hasenv = hasenv, hexdump = hexdump, intchar2lua = intchar2lua, + isCI = isCI, map = map, matches = matches, mergedicts_copy = mergedicts_copy, diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua index f8143a0125..beb25f25db 100644 --- a/test/unit/helpers.lua +++ b/test/unit/helpers.lua @@ -645,16 +645,16 @@ local function itp_child(wr, func) s = s:sub(1, hook_msglen - 2) sc.write(wr, '>' .. s .. (' '):rep(hook_msglen - 2 - #s) .. '\n') end - local err, emsg = pcall(init) - if err then + local status, result = pcall(init) + if status then collectgarbage('stop') child_sethook(wr) - err, emsg = pcall(func) + status, result = pcall(func) debug.sethook() end - emsg = tostring(emsg) sc.write(wr, trace_end_msg) - if not err then + if not status then + local emsg = tostring(result) if #emsg > 99999 then emsg = emsg:sub(1, 99999) end @@ -668,7 +668,7 @@ local function itp_child(wr, func) collectgarbage() sc.write(wr, '$\n') sc.close(wr) - sc.exit(err and 0 or 1) + sc.exit(status and 0 or 1) end local function check_child_err(rd) diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua index c54d5a9b77..c543551607 100644 --- a/test/unit/os/env_spec.lua +++ b/test/unit/os/env_spec.lua @@ -8,17 +8,22 @@ local ffi = helpers.ffi local cstr = helpers.cstr local to_cstr = helpers.to_cstr local NULL = helpers.NULL +local OK = 0 require('lfs') local cimp = cimport('./src/nvim/os/os.h') describe('env.c', function() + local function os_env_exists(name) + return cimp.os_env_exists(to_cstr(name)) + end + local function os_setenv(name, value, override) return cimp.os_setenv(to_cstr(name), to_cstr(value), override) end - local function os_unsetenv(name, _, _) + local function os_unsetenv(name) return cimp.os_unsetenv(to_cstr(name)) end @@ -31,25 +36,44 @@ describe('env.c', function() end end - describe('os_setenv', function() - local OK = 0 + itp('os_env_exists', function() + eq(false, os_env_exists('')) + eq(false, os_env_exists(' ')) + eq(false, os_env_exists('\t')) + eq(false, os_env_exists('\n')) + eq(false, os_env_exists('AaあB <= very weird name...')) - itp('sets an env variable and returns OK', function() + local varname = 'NVIM_UNIT_TEST_os_env_exists' + eq(false, os_env_exists(varname)) + eq(OK, os_setenv(varname, 'foo bar baz ...', 1)) + eq(true, os_env_exists(varname)) + end) + + describe('os_setenv', function() + itp('sets an env var and returns success', function() local name = 'NVIM_UNIT_TEST_SETENV_1N' local value = 'NVIM_UNIT_TEST_SETENV_1V' eq(nil, os.getenv(name)) - eq(OK, (os_setenv(name, value, 1))) + eq(OK, os_setenv(name, value, 1)) eq(value, os.getenv(name)) + + -- Set empty, then set non-empty, then retrieve. + eq(OK, os_setenv(name, '', 1)) + eq('', os.getenv(name)) + eq(OK, os_setenv(name, 'non-empty', 1)) + eq('non-empty', os.getenv(name)) end) - itp("dosn't overwrite an env variable if overwrite is 0", function() + itp("`overwrite` behavior", function() local name = 'NVIM_UNIT_TEST_SETENV_2N' local value = 'NVIM_UNIT_TEST_SETENV_2V' local value_updated = 'NVIM_UNIT_TEST_SETENV_2V_UPDATED' - eq(OK, (os_setenv(name, value, 0))) + eq(OK, os_setenv(name, value, 0)) eq(value, os.getenv(name)) - eq(OK, (os_setenv(name, value_updated, 0))) + eq(OK, os_setenv(name, value_updated, 0)) eq(value, os.getenv(name)) + eq(OK, os_setenv(name, value_updated, 1)) + eq(value_updated, os.getenv(name)) end) end) @@ -93,31 +117,42 @@ describe('env.c', function() end) describe('os_getenv', function() - itp('reads an env variable', function() + itp('reads an env var', function() local name = 'NVIM_UNIT_TEST_GETENV_1N' local value = 'NVIM_UNIT_TEST_GETENV_1V' eq(NULL, os_getenv(name)) -- Use os_setenv because Lua dosen't have setenv. os_setenv(name, value, 1) eq(value, os_getenv(name)) + + -- Get a big value. + local bigval = ('x'):rep(256) + eq(OK, os_setenv(name, bigval, 1)) + eq(bigval, os_getenv(name)) + + -- Set non-empty, then set empty. + eq(OK, os_setenv(name, 'non-empty', 1)) + eq('non-empty', os_getenv(name)) + eq(OK, os_setenv(name, '', 1)) + eq(NULL, os_getenv(name)) end) - itp('returns NULL if the env variable is not found', function() - local name = 'NVIM_UNIT_TEST_GETENV_NOTFOUND' - return eq(NULL, os_getenv(name)) + itp('returns NULL if the env var is not found', function() + eq(NULL, os_getenv('NVIM_UNIT_TEST_GETENV_NOTFOUND')) end) end) - describe('os_unsetenv', function() - itp('unsets environment variable', function() - local name = 'TEST_UNSETENV' - local value = 'TESTVALUE' - os_setenv(name, value, 1) - os_unsetenv(name) - neq(os_getenv(name), value) - -- Depending on the platform the var might be unset or set as '' - assert.True(os_getenv(name) == nil or os_getenv(name) == '') - end) + itp('os_unsetenv', function() + local name = 'TEST_UNSETENV' + local value = 'TESTVALUE' + os_setenv(name, value, 1) + eq(OK, os_unsetenv(name)) + neq(os_getenv(name), value) + -- Depending on the platform the var might be unset or set as '' + assert.True(os_getenv(name) == nil or os_getenv(name) == '') + if os_getenv(name) == nil then + eq(false, os_env_exists(name)) + end end) describe('os_getenvname_at_index', function() diff --git a/test/unit/search_spec.lua b/test/unit/search_spec.lua new file mode 100644 index 0000000000..3c2d485e0e --- /dev/null +++ b/test/unit/search_spec.lua @@ -0,0 +1,33 @@ +local helpers = require("test.unit.helpers")(after_each) +local itp = helpers.gen_itp(it) + +local to_cstr = helpers.to_cstr +local eq = helpers.eq + +local search = helpers.cimport("./src/nvim/search.h") + +itp('pat_has_uppercase', function() + -- works on empty string + eq(false, search.pat_has_uppercase(to_cstr(""))) + + -- works with utf uppercase + eq(false, search.pat_has_uppercase(to_cstr("ä"))) + eq(true, search.pat_has_uppercase(to_cstr("Ä"))) + eq(true, search.pat_has_uppercase(to_cstr("äaÅ"))) + + -- works when pat ends with backslash + eq(false, search.pat_has_uppercase(to_cstr("\\"))) + eq(false, search.pat_has_uppercase(to_cstr("ab$\\"))) + + -- skips escaped characters + eq(false, search.pat_has_uppercase(to_cstr("\\Ab"))) + eq(true, search.pat_has_uppercase(to_cstr("\\AU"))) + + -- skips _X escaped characters + eq(false, search.pat_has_uppercase(to_cstr("\\_Ab"))) + eq(true, search.pat_has_uppercase(to_cstr("\\_AU"))) + + -- skips %X escaped characters + eq(false, search.pat_has_uppercase(to_cstr("aa\\%Ab"))) + eq(true, search.pat_has_uppercase(to_cstr("aab\\%AU"))) +end) |