diff options
Diffstat (limited to 'test/functional/terminal')
-rw-r--r-- | test/functional/terminal/api_spec.lua | 8 | ||||
-rw-r--r-- | test/functional/terminal/buffer_spec.lua | 1 | ||||
-rw-r--r-- | test/functional/terminal/channel_spec.lua | 87 | ||||
-rw-r--r-- | test/functional/terminal/cursor_spec.lua | 60 | ||||
-rw-r--r-- | test/functional/terminal/edit_spec.lua | 5 | ||||
-rw-r--r-- | test/functional/terminal/ex_terminal_spec.lua | 17 | ||||
-rw-r--r-- | test/functional/terminal/helpers.lua | 10 | ||||
-rw-r--r-- | test/functional/terminal/highlight_spec.lua | 25 | ||||
-rw-r--r-- | test/functional/terminal/mouse_spec.lua | 30 | ||||
-rw-r--r-- | test/functional/terminal/scrollback_spec.lua | 47 | ||||
-rw-r--r-- | test/functional/terminal/tui_spec.lua | 260 | ||||
-rw-r--r-- | test/functional/terminal/window_spec.lua | 1 |
12 files changed, 475 insertions, 76 deletions
diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua index e28cc03597..5305b8af9c 100644 --- a/test/functional/terminal/api_spec.lua +++ b/test/functional/terminal/api_spec.lua @@ -6,7 +6,7 @@ if helpers.pending_win32(pending) then return end describe('api', function() local screen - local socket_name = "Xtest_functional_api.sock" + local socket_name = "./Xtest_functional_api.sock" before_each(function() helpers.clear() @@ -29,7 +29,7 @@ describe('api', function() {4:~ }| {4:~ }| {4:~ }| - ]]..socket_name..[[ | + ]]..socket_name..[[ | {3:-- TERMINAL --} | ]]) @@ -48,8 +48,8 @@ describe('api', function() {3:-- TERMINAL --} | ]]) - ok(socket_session1:request("nvim_ui_attach", 42, 6, {rgb=true})) - ok(socket_session2:request("nvim_ui_attach", 25, 30, {rgb=true})) + ok((socket_session1:request("nvim_ui_attach", 42, 6, {rgb=true}))) + ok((socket_session2:request("nvim_ui_attach", 25, 30, {rgb=true}))) socket_session1:notify("nvim_input", "\n[socket 1] this is more than 25 columns") socket_session2:notify("nvim_input", "\n[socket 2] input") diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index beb43e0271..1cef771f0d 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -258,6 +258,7 @@ describe(':terminal buffer', function() end) it('it works with set rightleft #11438', function() + if helpers.pending_win32(pending) then return end local columns = eval('&columns') feed(string.rep('a', columns)) command('set rightleft') diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua index 7223f5ba61..b5f3c2bd31 100644 --- a/test/functional/terminal/channel_spec.lua +++ b/test/functional/terminal/channel_spec.lua @@ -1,45 +1,94 @@ local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local clear = helpers.clear local eq = helpers.eq +local eval = helpers.eval local command = helpers.command local pcall_err = helpers.pcall_err local feed = helpers.feed -local sleep = helpers.sleep local poke_eventloop = helpers.poke_eventloop -describe('associated channel is closed and later freed for terminal', function() - before_each(clear) +describe('terminal channel is closed and later released if', function() + local screen + + before_each(function() + clear() + screen = Screen.new() + screen:attach() + end) it('opened by nvim_open_term() and deleted by :bdelete!', function() command([[let id = nvim_open_term(0, {})]]) - -- channel hasn't been freed yet - eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[bdelete! | call chansend(id, 'test')]])) - -- channel has been freed after one main loop iteration - eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]])) + local chans = eval('len(nvim_list_chans())') + -- channel hasn't been released yet + eq("Vim(call):Can't send data to closed stream", + pcall_err(command, [[bdelete! | call chansend(id, 'test')]])) + -- channel has been released after one main loop iteration + eq(chans - 1, eval('len(nvim_list_chans())')) + end) + + it('opened by nvim_open_term(), closed by chanclose(), and deleted by pressing a key', function() + command('let id = nvim_open_term(0, {})') + local chans = eval('len(nvim_list_chans())') + -- channel has been closed but not released + eq("Vim(call):Can't send data to closed stream", + pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]])) + screen:expect({any='%[Terminal closed%]'}) + eq(chans, eval('len(nvim_list_chans())')) + -- delete terminal + feed('i<CR>') + -- need to first process input + poke_eventloop() + -- channel has been released after another main loop iteration + eq(chans - 1, eval('len(nvim_list_chans())')) + end) + + it('opened by nvim_open_term(), closed by chanclose(), and deleted by :bdelete', function() + command('let id = nvim_open_term(0, {})') + local chans = eval('len(nvim_list_chans())') + -- channel has been closed but not released + eq("Vim(call):Can't send data to closed stream", + pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]])) + screen:expect({any='%[Terminal closed%]'}) + eq(chans, eval('len(nvim_list_chans())')) + -- channel still hasn't been released yet + eq("Vim(call):Can't send data to closed stream", + pcall_err(command, [[bdelete | call chansend(id, 'test')]])) + -- channel has been released after one main loop iteration + eq(chans - 1, eval('len(nvim_list_chans())')) end) it('opened by termopen(), exited, and deleted by pressing a key', function() command([[let id = termopen('echo')]]) - sleep(500) - -- process has exited - eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[call chansend(id, 'test')]])) + local chans = eval('len(nvim_list_chans())') + -- wait for process to exit + screen:expect({any='%[Process exited 0%]'}) + -- process has exited but channel has't been released + eq("Vim(call):Can't send data to closed stream", + pcall_err(command, [[call chansend(id, 'test')]])) + eq(chans, eval('len(nvim_list_chans())')) -- delete terminal feed('i<CR>') -- need to first process input poke_eventloop() - -- channel has been freed after another main loop iteration - eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]])) + -- channel has been released after another main loop iteration + eq(chans - 1, eval('len(nvim_list_chans())')) end) -- This indirectly covers #16264 it('opened by termopen(), exited, and deleted by :bdelete', function() command([[let id = termopen('echo')]]) - sleep(500) - -- process has exited - eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[call chansend(id, 'test')]])) - -- channel hasn't been freed yet - eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[bdelete | call chansend(id, 'test')]])) - -- channel has been freed after one main loop iteration - eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]])) + local chans = eval('len(nvim_list_chans())') + -- wait for process to exit + screen:expect({any='%[Process exited 0%]'}) + -- process has exited but channel hasn't been released + eq("Vim(call):Can't send data to closed stream", + pcall_err(command, [[call chansend(id, 'test')]])) + eq(chans, eval('len(nvim_list_chans())')) + -- channel still hasn't been released yet + eq("Vim(call):Can't send data to closed stream", + pcall_err(command, [[bdelete | call chansend(id, 'test')]])) + -- channel has been released after one main loop iteration + eq(chans - 1, eval('len(nvim_list_chans())')) end) end) diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua index e9495f45a2..2d1c790d2f 100644 --- a/test/functional/terminal/cursor_spec.lua +++ b/test/functional/terminal/cursor_spec.lua @@ -2,9 +2,10 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim -local nvim_dir, command = helpers.nvim_dir, helpers.command +local testprg, command = helpers.testprg, helpers.command local nvim_prog = helpers.nvim_prog local eq, eval = helpers.eq, helpers.eval +local matches = helpers.matches local feed_command = helpers.feed_command local hide_cursor = thelpers.hide_cursor local show_cursor = thelpers.show_cursor @@ -87,6 +88,7 @@ describe(':terminal cursor', function() describe('when invisible', function() it('is not highlighted and is detached from screen cursor', function() + if helpers.pending_win32(pending) then return end hide_cursor() screen:expect([[ tty ready | @@ -148,7 +150,7 @@ describe('cursor with customized highlighting', function() [3] = {bold = true}, }) screen:attach({rgb=false}) - command('call termopen(["'..nvim_dir..'/tty-test"])') + command('call termopen(["'..testprg('tty-test')..'"])') feed_command('startinsert') end) @@ -523,6 +525,33 @@ describe('buffer cursor position is correct in terminal without number column', eq({6, 1}, eval('nvim_win_get_cursor(0)')) end) end) + + it('at the end of a line with trailing spaces #16234', function() + setup_ex_register('aaaaaaaa ') + feed('<C-R>r') + screen:expect([[ + | + | + | + | + Entering Ex mode. Type "visual" to go to Normal mode. | + :aaaaaaaa {1: } | + {3:-- TERMINAL --} | + ]]) + matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()')) + eq({6, 13}, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ + | + | + | + | + Entering Ex mode. Type "visual" to go to Normal mode. | + :aaaaaaaa ^ {2: } | + | + ]]) + eq({6, 12}, eval('nvim_win_get_cursor(0)')) + end) end) describe('buffer cursor position is correct in terminal with number column', function() @@ -876,4 +905,31 @@ describe('buffer cursor position is correct in terminal with number column', fun eq({6, 1}, eval('nvim_win_get_cursor(0)')) end) end) + + it('at the end of a line with trailing spaces #16234', function() + setup_ex_register('aaaaaaaa ') + feed('<C-R>r') + screen:expect([[ + {7: 1 } | + {7: 2 } | + {7: 3 } | + {7: 4 } | + {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | + {7: 6 }:aaaaaaaa {1: } | + {3:-- TERMINAL --} | + ]]) + matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()')) + eq({6, 13}, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ + {7: 1 } | + {7: 2 } | + {7: 3 } | + {7: 4 } | + {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | + {7: 6 }:aaaaaaaa ^ {2: } | + | + ]]) + eq({6, 12}, eval('nvim_win_get_cursor(0)')) + end) end) diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua index fabc5524ed..aeb4b7cc2e 100644 --- a/test/functional/terminal/edit_spec.lua +++ b/test/functional/terminal/edit_spec.lua @@ -3,7 +3,7 @@ local screen = require('test.functional.ui.screen') local curbufmeths = helpers.curbufmeths local curwinmeths = helpers.curwinmeths -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg local command = helpers.command local funcs = helpers.funcs local meths = helpers.meths @@ -21,7 +21,7 @@ describe(':edit term://*', function() before_each(function() clear() - meths.set_option('shell', nvim_dir .. '/shell-test') + meths.set_option('shell', testprg('shell-test')) meths.set_option('shellcmdflag', 'EXE') end) @@ -36,6 +36,7 @@ describe(':edit term://*', function() end) it("runs TermOpen early enough to set buffer-local 'scrollback'", function() + if helpers.pending_win32(pending) then return end local columns, lines = 20, 4 local scr = get_screen(columns, lines) local rep = 97 diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index 065dd72485..23b69319f0 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local assert_alive = helpers.assert_alive local clear, poke_eventloop, nvim = helpers.clear, helpers.poke_eventloop, helpers.nvim -local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq +local testprg, source, eq = helpers.testprg, helpers.source, helpers.eq local feed = helpers.feed local feed_command, eval = helpers.feed_command, helpers.eval local funcs = helpers.funcs @@ -28,7 +28,7 @@ describe(':terminal', function() echomsg "msg3" ]]) -- Invoke a command that emits frequent terminal activity. - feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 9999 !terminal_output!<cr>]]) + feed([[:terminal "]]..testprg('shell-test')..[[" REP 9999 !terminal_output!<cr>]]) feed([[<C-\><C-N>]]) poke_eventloop() -- Wait for some terminal activity. @@ -131,7 +131,7 @@ describe(':terminal (with fake shell)', function() screen = Screen.new(50, 4) screen:attach({rgb=false}) -- shell-test.c is a fake shell that prints its arguments and exits. - nvim('set_option', 'shell', nvim_dir..'/shell-test') + nvim('set_option', 'shell', testprg('shell-test')) nvim('set_option', 'shellcmdflag', 'EXE') end) @@ -142,6 +142,7 @@ describe(':terminal (with fake shell)', function() end it('with no argument, acts like termopen()', function() + if helpers.pending_win32(pending) then return end terminal_with_fake_shell() retry(nil, 4 * screen.timeout, function() screen:expect([[ @@ -165,7 +166,8 @@ describe(':terminal (with fake shell)', function() end) it("with no argument, but 'shell' has arguments, acts like termopen()", function() - nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff') + if helpers.pending_win32(pending) then return end + nvim('set_option', 'shell', testprg('shell-test')..' -t jeff') terminal_with_fake_shell() screen:expect([[ ^jeff $ | @@ -176,6 +178,7 @@ describe(':terminal (with fake shell)', function() end) it('executes a given command through the shell', function() + if helpers.pending_win32(pending) then return end command('set shellxquote=') -- win: avoid extra quotes terminal_with_fake_shell('echo hi') screen:expect([[ @@ -187,7 +190,8 @@ describe(':terminal (with fake shell)', function() end) it("executes a given command through the shell, when 'shell' has arguments", function() - nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff') + if helpers.pending_win32(pending) then return end + nvim('set_option', 'shell', testprg('shell-test')..' -t jeff') command('set shellxquote=') -- win: avoid extra quotes terminal_with_fake_shell('echo hi') screen:expect([[ @@ -199,6 +203,7 @@ describe(':terminal (with fake shell)', function() end) it('allows quotes and slashes', function() + if helpers.pending_win32(pending) then return end command('set shellxquote=') -- win: avoid extra quotes terminal_with_fake_shell([[echo 'hello' \ "world"]]) screen:expect([[ @@ -235,6 +240,7 @@ describe(':terminal (with fake shell)', function() end) it('works with :find', function() + if helpers.pending_win32(pending) then return end terminal_with_fake_shell() screen:expect([[ ^ready $ | @@ -253,6 +259,7 @@ describe(':terminal (with fake shell)', function() end) it('works with gf', function() + if helpers.pending_win32(pending) then return end command('set shellxquote=') -- win: avoid extra quotes terminal_with_fake_shell([[echo "scripts/shadacat.py"]]) retry(nil, 4 * screen.timeout, function() diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua index d909888613..bcfd3559e6 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/helpers.lua @@ -3,11 +3,13 @@ -- operate on the _host_ session, _not_ the child session. local helpers = require('test.functional.helpers')(nil) local Screen = require('test.functional.ui.screen') -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg local feed_command, nvim = helpers.feed_command, helpers.nvim local function feed_data(data) - nvim('set_var', 'term_data', data) + -- A string containing NUL bytes is not converted to a Blob when + -- calling nvim_set_var() API, so convert it using Lua instead. + nvim('exec_lua', 'vim.g.term_data = ...', {data}) nvim('command', 'call jobsend(b:terminal_job_id, term_data)') end @@ -35,7 +37,7 @@ local function clear_attrs() feed_termcode('[0;10m') end local function enable_mouse() feed_termcode('[?1002h') end local function disable_mouse() feed_termcode('[?1002l') end -local default_command = '["'..nvim_dir..'/tty-test'..'"]' +local default_command = '["'..testprg('tty-test')..'"]' local function screen_setup(extra_rows, command, cols, opts) extra_rows = extra_rows and extra_rows or 0 @@ -94,7 +96,7 @@ local function screen_setup(extra_rows, command, cols, opts) table.insert(expected, '{3:-- TERMINAL --}' .. ((' '):rep(cols - 14))) screen:expect(table.concat(expected, '|\n')..'|') else - -- This eval also acts as a wait(). + -- This eval also acts as a poke_eventloop(). if 0 == nvim('eval', "exists('b:terminal_job_id')") then error("terminal job failed to start") end diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua index 8d3f0218af..28ca07d815 100644 --- a/test/functional/terminal/highlight_spec.lua +++ b/test/functional/terminal/highlight_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim -local nvim_dir, command = helpers.nvim_dir, helpers.command +local testprg, command = helpers.testprg, helpers.command local nvim_prog_abs = helpers.nvim_prog_abs local eq, eval = helpers.eq, helpers.eval local funcs = helpers.funcs @@ -28,7 +28,7 @@ describe(':terminal highlight', function() [11] = {background = 11}, }) screen:attach({rgb=false}) - command('enew | call termopen(["'..nvim_dir..'/tty-test"])') + command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) feed('i') screen:expect([[ tty ready | @@ -173,7 +173,7 @@ describe(':terminal highlight forwarding', function() [4] = {{foreground = tonumber('0xff8000')}, {}}, }) screen:attach() - command('enew | call termopen(["'..nvim_dir..'/tty-test"])') + command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) feed('i') screen:expect([[ tty ready | @@ -214,7 +214,7 @@ describe(':terminal highlight with custom palette', function() clear() screen = Screen.new(50, 7) screen:set_default_attr_ids({ - [1] = {foreground = tonumber('0x123456')}, -- no fg_indexed when overriden + [1] = {foreground = tonumber('0x123456')}, -- no fg_indexed when overridden [2] = {foreground = 12}, [3] = {bold = true, reverse = true}, [5] = {background = 11}, @@ -225,7 +225,7 @@ describe(':terminal highlight with custom palette', function() }) screen:attach({rgb=true}) nvim('set_var', 'terminal_color_3', '#123456') - command('enew | call termopen(["'..nvim_dir..'/tty-test"])') + command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) feed('i') screen:expect([[ tty ready | @@ -304,10 +304,17 @@ describe('synIDattr()', function() eq('79', eval('synIDattr(hlID("Keyword"), "fg")')) end) - it('returns "1" if group has "strikethrough" attribute', function() - eq('', eval('synIDattr(hlID("Normal"), "strikethrough")')) - eq('1', eval('synIDattr(hlID("Keyword"), "strikethrough")')) - eq('1', eval('synIDattr(hlID("Keyword"), "strikethrough", "gui")')) + it('returns "1" if group has given highlight attribute', function() + local hl_attrs = { + 'underline', 'undercurl', 'underdouble', 'underdotted', 'underdashed', 'strikethrough' + } + for _,hl_attr in ipairs(hl_attrs) do + local context = 'using ' .. hl_attr .. ' attr' + command('highlight Keyword cterm=' .. hl_attr .. ' gui=' .. hl_attr) + eq('', eval('synIDattr(hlID("Normal"), "'.. hl_attr .. '")'), context) + eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '")'), context) + eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '", "gui")'), context) + end end) end) diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index 780a0b9b5a..6e2c851df7 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, eval = helpers.clear, helpers.eq, helpers.eval -local feed, nvim = helpers.feed, helpers.nvim +local feed, nvim, command = helpers.feed, helpers.nvim, helpers.command local feed_data = thelpers.feed_data describe(':terminal mouse', function() @@ -10,9 +10,9 @@ describe(':terminal mouse', function() before_each(function() clear() nvim('set_option', 'statusline', '==========') - nvim('command', 'highlight StatusLine cterm=NONE') - nvim('command', 'highlight StatusLineNC cterm=NONE') - nvim('command', 'highlight VertSplit cterm=NONE') + command('highlight StatusLine cterm=NONE') + command('highlight StatusLineNC cterm=NONE') + command('highlight VertSplit cterm=NONE') screen = thelpers.screen_setup() local lines = {} for i = 1, 30 do @@ -38,6 +38,26 @@ describe(':terminal mouse', function() eq('nt', eval('mode(1)')) end) + it('will exit focus and trigger Normal mode mapping on mouse click', function() + command('let g:got_leftmouse = 0') + command('nnoremap <LeftMouse> <Cmd>let g:got_leftmouse = 1<CR>') + eq('t', eval('mode(1)')) + eq(0, eval('g:got_leftmouse')) + feed('<LeftMouse>') + eq('nt', eval('mode(1)')) + eq(1, eval('g:got_leftmouse')) + end) + + it('will exit focus and trigger Normal mode mapping on mouse click with modifier', function() + command('let g:got_ctrl_leftmouse = 0') + command('nnoremap <C-LeftMouse> <Cmd>let g:got_ctrl_leftmouse = 1<CR>') + eq('t', eval('mode(1)')) + eq(0, eval('g:got_ctrl_leftmouse')) + feed('<C-LeftMouse>') + eq('nt', eval('mode(1)')) + eq(1, eval('g:got_ctrl_leftmouse')) + end) + it('will exit focus on <C-\\> + mouse-scroll', function() eq('t', eval('mode(1)')) feed('<C-\\>') @@ -180,7 +200,7 @@ describe(':terminal mouse', function() it('will forward mouse clicks to the program with the correct even if set nu', function() if helpers.pending_win32(pending) then return end - nvim('command', 'set number') + command('set number') -- When the display area such as a number is clicked, it returns to the -- normal mode. feed('<LeftMouse><3,0>') diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua index 11bdc73a47..b491cb2735 100644 --- a/test/functional/terminal/scrollback_spec.lua +++ b/test/functional/terminal/scrollback_spec.lua @@ -2,10 +2,11 @@ local Screen = require('test.functional.ui.screen') local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf -local feed, nvim_dir, feed_command = helpers.feed, helpers.nvim_dir, helpers.feed_command +local feed, testprg, feed_command = helpers.feed, helpers.testprg, helpers.feed_command local iswin = helpers.iswin local eval = helpers.eval local command = helpers.command +local matches = helpers.matches local poke_eventloop = helpers.poke_eventloop local retry = helpers.retry local curbufmeths = helpers.curbufmeths @@ -345,10 +346,11 @@ end) describe(':terminal prints more lines than the screen height and exits', function() it('will push extra lines to scrollback', function() + if helpers.pending_win32(pending) then return end clear() local screen = Screen.new(30, 7) screen:attach({rgb=false}) - feed_command('call termopen(["'..nvim_dir..'/tty-test", "10"]) | startinsert') + feed_command(("call termopen(['%s', '10']) | startinsert"):format(testprg('tty-test'))) poke_eventloop() screen:expect([[ line6 | @@ -380,7 +382,7 @@ describe("'scrollback' option", function() local function set_fake_shell() -- shell-test.c is a fake shell that prints its arguments and exits. - nvim('set_option', 'shell', nvim_dir..'/shell-test') + nvim('set_option', 'shell', testprg('shell-test')) nvim('set_option', 'shellcmdflag', 'EXE') end @@ -401,7 +403,7 @@ describe("'scrollback' option", function() end curbufmeths.set_option('scrollback', 0) - feed_data(nvim_dir..'/shell-test REP 31 line'..(iswin() and '\r' or '\n')) + feed_data(('%s REP 31 line%s'):format(testprg('shell-test'), iswin() and '\r' or '\n')) screen:expect{any='30: line '} retry(nil, nil, function() expect_lines(7) end) end) @@ -421,7 +423,7 @@ describe("'scrollback' option", function() -- Wait for prompt. screen:expect{any='%$'} - feed_data(nvim_dir.."/shell-test REP 31 line"..(iswin() and '\r' or '\n')) + feed_data(('%s REP 31 line%s'):format(testprg('shell-test'), iswin() and '\r' or '\n')) screen:expect{any='30: line '} retry(nil, nil, function() expect_lines(33, 2) end) @@ -434,7 +436,7 @@ describe("'scrollback' option", function() -- 'scrollback' option is synchronized with the internal sb_buffer. command('sleep 100m') - feed_data(nvim_dir.."/shell-test REP 41 line"..(iswin() and '\r' or '\n')) + feed_data(('%s REP 41 line%s'):format(testprg('shell-test'), iswin() and '\r' or '\n')) if iswin() then screen:expect{grid=[[ 37: line | @@ -459,8 +461,36 @@ describe("'scrollback' option", function() expect_lines(58) -- Verify off-screen state - eq((iswin() and '36: line' or '35: line'), eval("getline(line('w0') - 1)")) - eq((iswin() and '27: line' or '26: line'), eval("getline(line('w0') - 10)")) + matches((iswin() and '^36: line[ ]*$' or '^35: line[ ]*$'), eval("getline(line('w0') - 1)")) + matches((iswin() and '^27: line[ ]*$' or '^26: line[ ]*$'), eval("getline(line('w0') - 10)")) + end) + + it('deletes extra lines immediately', function() + -- Scrollback is 10 on screen_setup + local screen = thelpers.screen_setup(nil, nil, 30) + local lines = {} + for i = 1, 30 do + table.insert(lines, 'line'..tostring(i)) + end + table.insert(lines, '') + feed_data(lines) + screen:expect([[ + line26 | + line27 | + line28 | + line29 | + line30 | + {1: } | + {3:-- TERMINAL --} | + ]]) + local term_height = 6 -- Actual terminal screen height, not the scrollback + -- Initial + local scrollback = curbufmeths.get_option('scrollback') + eq(scrollback + term_height, eval('line("$")')) + -- Reduction + scrollback = scrollback - 2 + curbufmeths.set_option('scrollback', scrollback) + eq(scrollback + term_height, eval('line("$")')) end) it('defaults to 10000 in :terminal buffers', function() @@ -576,6 +606,7 @@ describe("pending scrollback line handling", function() end) it("does not crash after nvim_buf_call #14891", function() + if helpers.pending_win32(pending) then return end exec_lua [[ local a = vim.api local bufnr = a.nvim_create_buf(false, true) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index faf44fa01d..dd88379344 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -14,12 +14,13 @@ local feed_command = helpers.feed_command local feed_data = thelpers.feed_data local clear = helpers.clear local command = helpers.command -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg local retry = helpers.retry local nvim_prog = helpers.nvim_prog local nvim_set = helpers.nvim_set local ok = helpers.ok local read_file = helpers.read_file +local funcs = helpers.funcs if helpers.pending_win32(pending) then return end @@ -85,6 +86,24 @@ describe('TUI', function() assert_alive() end) + it('resize at startup', function() + -- Issues: #17285 #15044 #11330 + screen:try_resize(50, 10) + feed_command([[call termopen([v:progpath, '--clean', '--cmd', 'let start = reltime() | while v:true | if reltimefloat(reltime(start)) > 2 | break | endif | endwhile']) | sleep 500m | vs new]]) + screen:expect([[ + {1: } │ | + {4:~ }│{4:~ }| + {4:~ }│{4:~ }| + {4:~ }│{4:~ }| + {4:~ }│{4:~ }| + {4:~ }│{5:[No Name] 0,0-1 All}| + {4:~ }│ | + {5:new }{MATCH:<.*[/\]nvim }| + | + {3:-- TERMINAL --} | + ]]) + end) + it('accepts resize while pager is active', function() child_session:request("nvim_command", [[ set more @@ -214,7 +233,7 @@ describe('TUI', function() ]]) end) - it('interprets ESC+key as ALT chord', function() + it('interprets ESC+key as ALT chord in i_CTRL-V', function() -- Vim represents ALT/META by setting the "high bit" of the modified key: -- ALT+j inserts "ê". Nvim does not (#3982). feed_data('i\022\027j') @@ -229,6 +248,38 @@ describe('TUI', function() ]]) end) + it('interprets <Esc>[27u as <Esc>', function() + feed_command('nnoremap <M-;> <Nop>') + feed_command('nnoremap <Esc> AESC<Esc>') + feed_command('nnoremap ; Asemicolon<Esc>') + feed_data('\027[27u;') + screen:expect([[ + ESCsemicolo{1:n} | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + -- <Esc>; should be recognized as <M-;> when <M-;> is mapped + feed_data('\027;') + screen:expect_unchanged() + end) + + it('interprets <Esc><Nul> as <M-C-Space> #17198', function() + feed_data('i\022\027\000') + screen:expect([[ + <M-C-Space>{1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + end) + it('accepts ASCII control sequences', function() feed_data('i') feed_data('\022\007') -- ctrl+g @@ -247,6 +298,179 @@ describe('TUI', function() ]], attrs) end) + it('accepts keypad keys from kitty keyboard protocol #19180', function() + feed_data('i') + feed_data(funcs.nr2char(57399)) -- KP_0 + feed_data(funcs.nr2char(57400)) -- KP_1 + feed_data(funcs.nr2char(57401)) -- KP_2 + feed_data(funcs.nr2char(57402)) -- KP_3 + feed_data(funcs.nr2char(57403)) -- KP_4 + feed_data(funcs.nr2char(57404)) -- KP_5 + feed_data(funcs.nr2char(57405)) -- KP_6 + feed_data(funcs.nr2char(57406)) -- KP_7 + feed_data(funcs.nr2char(57407)) -- KP_8 + feed_data(funcs.nr2char(57408)) -- KP_9 + feed_data(funcs.nr2char(57409)) -- KP_DECIMAL + feed_data(funcs.nr2char(57410)) -- KP_DIVIDE + feed_data(funcs.nr2char(57411)) -- KP_MULTIPLY + feed_data(funcs.nr2char(57412)) -- KP_SUBTRACT + feed_data(funcs.nr2char(57413)) -- KP_ADD + feed_data(funcs.nr2char(57414)) -- KP_ENTER + feed_data(funcs.nr2char(57415)) -- KP_EQUAL + screen:expect([[ + 0123456789./*-+ | + ={1: } | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57417)) -- KP_LEFT + screen:expect([[ + 0123456789./*-+ | + {1:=} | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57418)) -- KP_RIGHT + screen:expect([[ + 0123456789./*-+ | + ={1: } | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57419)) -- KP_UP + screen:expect([[ + 0{1:1}23456789./*-+ | + = | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57420)) -- KP_DOWN + screen:expect([[ + 0123456789./*-+ | + ={1: } | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57425)) -- KP_INSERT + screen:expect([[ + 0123456789./*-+ | + ={1: } | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- REPLACE --} | + {3:-- TERMINAL --} | + ]]) + feed_data('\027[27u') -- ESC + screen:expect([[ + 0123456789./*-+ | + {1:=} | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + feed_data('\027[57417;5u') -- CTRL + KP_LEFT + screen:expect([[ + {1:0}123456789./*-+ | + = | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + feed_data('\027[57418;2u') -- SHIFT + KP_RIGHT + screen:expect([[ + 0123456789{1:.}/*-+ | + = | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57426)) -- KP_DELETE + screen:expect([[ + 0123456789{1:/}*-+ | + = | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57423)) -- KP_HOME + screen:expect([[ + {1:0}123456789/*-+ | + = | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + feed_data(funcs.nr2char(57424)) -- KP_END + screen:expect([[ + 0123456789/*-{1:+} | + = | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + feed_data(':tab split\r:tabnew\r') + feed_data(':highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline\r') + local attrs = screen:get_default_attr_ids() + attrs[11] = {underline = true} + screen:expect([[ + {11: + [No Name] + [No Name] }{3: [No Name] }{1: }{11:X}| + {1: } | + {4:~ }| + {4:~ }| + {5:[No Name] }| + | + {3:-- TERMINAL --} | + ]], attrs) + feed_data('\027[57421;5u') -- CTRL + KP_PAGE_UP + screen:expect([[ + {11: + [No Name] }{3: + [No Name] }{11: [No Name] }{1: }{11:X}| + 0123456789/*-{1:+} | + = | + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]], attrs) + feed_data('\027[57422;5u') -- CTRL + KP_PAGE_DOWN + screen:expect([[ + {11: + [No Name] + [No Name] }{3: [No Name] }{1: }{11:X}| + {1: } | + {4:~ }| + {4:~ }| + {5:[No Name] }| + | + {3:-- TERMINAL --} | + ]], attrs) + end) + it('paste: Insert mode', function() -- "bracketed paste" feed_data('i""\027i\027[200~') @@ -271,7 +495,7 @@ describe('TUI', function() {3:-- TERMINAL --} | ]]) feed_data('\027[201~') -- End paste. - feed_data('\027\000') -- ESC: go to Normal mode. + feed_data('\027[27u') -- ESC: go to Normal mode. wait_for_mode('n') screen:expect([[ "pasted from termina{1:l}" | @@ -323,7 +547,7 @@ describe('TUI', function() feed_data('just paste it™') feed_data('\027[201~') screen:expect{grid=[[ - thisjust paste it™{1:3} is here | + thisjust paste it{1:™}3 is here | | {4:~ }| {4:~ }| @@ -353,7 +577,7 @@ describe('TUI', function() return end feed_data(':set statusline=^^^^^^^\n') - feed_data(':terminal '..nvim_dir..'/tty-test\n') + feed_data(':terminal '..testprg('tty-test')..'\n') feed_data('i') screen:expect{grid=[[ tty ready | @@ -379,7 +603,7 @@ describe('TUI', function() end) it('paste: normal-mode (+CRLF #10872)', function() - feed_data(':set ruler') + feed_data(':set ruler | echo') wait_for_mode('c') feed_data('\n') wait_for_mode('n') @@ -423,13 +647,13 @@ describe('TUI', function() expect_child_buf_lines(expected_crlf) feed_data('u') expect_child_buf_lines({''}) + feed_data(':echo') + wait_for_mode('c') + feed_data('\n') + wait_for_mode('n') -- CRLF input feed_data('\027[200~'..table.concat(expected_lf,'\r\n')..'\027[201~') - screen:expect{ - grid=expected_grid1:gsub( - ':set ruler *', - '3 fewer lines; before #1 0 seconds ago '), - attr_ids=expected_attr} + screen:expect{grid=expected_grid1, attr_ids=expected_attr} expect_child_buf_lines(expected_crlf) end) @@ -453,7 +677,7 @@ describe('TUI', function() {3:-- TERMINAL --} | ]]} -- Dot-repeat/redo. - feed_data('\027\000') + feed_data('\027[27u') wait_for_mode('n') feed_data('.') screen:expect{grid=[[ @@ -499,7 +723,7 @@ describe('TUI', function() vim.paste = function(lines, phase) error("fake fail") end ]], {}) -- Prepare something for dot-repeat/redo. - feed_data('ifoo\n\027\000') + feed_data('ifoo\n\027[27u') wait_for_mode('n') screen:expect{grid=[[ foo | @@ -541,7 +765,7 @@ describe('TUI', function() {3:-- TERMINAL --} | ]]} -- Editor should still work after failed/drained paste. - feed_data('ityped input...\027\000') + feed_data('ityped input...\027[27u') screen:expect{grid=[[ foo | foo | @@ -575,7 +799,7 @@ describe('TUI', function() vim.paste = function(lines, phase) return false end ]], {}) feed_data('\027[200~line A\nline B\n\027[201~') - feed_data('ifoo\n\027\000') + feed_data('ifoo\n\027[27u') expect_child_buf_lines({'foo',''}) end) @@ -669,7 +893,7 @@ describe('TUI', function() {3:-- INSERT --} | {3:-- TERMINAL --} | ]]) - feed_data('\027\000') -- ESC: go to Normal mode. + feed_data('\027[27u') -- ESC: go to Normal mode. wait_for_mode('n') -- Dot-repeat/redo. feed_data('.') @@ -871,7 +1095,7 @@ describe('TUI', function() feed_data(':set statusline=^^^^^^^\n') feed_data(':set termguicolors\n') - feed_data(':terminal '..nvim_dir..'/tty-test\n') + feed_data(':terminal '..testprg('tty-test')..'\n') -- Depending on platform the above might or might not fit in the cmdline -- so clear it for consistent behavior. feed_data(':\027') @@ -1098,7 +1322,7 @@ describe('TUI FocusGained/FocusLost', function() end) it('in terminal-mode', function() - feed_data(':set shell='..nvim_dir..'/shell-test\n') + feed_data(':set shell='..testprg('shell-test')..'\n') feed_data(':set noshowmode laststatus=0\n') feed_data(':terminal\n') diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua index 9f278fd157..0d3295cf32 100644 --- a/test/functional/terminal/window_spec.lua +++ b/test/functional/terminal/window_spec.lua @@ -18,6 +18,7 @@ describe(':terminal window', function() end) it('sets topline correctly #8556', function() + if helpers.pending_win32(pending) then return end -- Test has hardcoded assumptions of dimensions. eq(7, eval('&lines')) feed_data('\n\n\n') -- Add blank lines. |