aboutsummaryrefslogtreecommitdiff
path: root/test/functional/terminal/tui_spec.lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/terminal/tui_spec.lua')
-rw-r--r--test/functional/terminal/tui_spec.lua256
1 files changed, 187 insertions, 69 deletions
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 94690524d3..d4628ea626 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -4,33 +4,38 @@
-- "bracketed paste" terminal feature:
-- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode
-local helpers = require('test.functional.helpers')(after_each)
-local thelpers = require('test.functional.terminal.helpers')
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local eq = helpers.eq
-local feed_data = thelpers.feed_data
-local clear = helpers.clear
-local command = helpers.command
-local dedent = helpers.dedent
-local exec = helpers.exec
-local exec_lua = helpers.exec_lua
-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 fn = helpers.fn
-local api = helpers.api
-local is_ci = helpers.is_ci
-local is_os = helpers.is_os
-local new_pipename = helpers.new_pipename
-local spawn_argv = helpers.spawn_argv
-local set_session = helpers.set_session
-local write_file = helpers.write_file
-local eval = helpers.eval
-
-if helpers.skip(is_os('win')) then
+local tt = require('test.functional.terminal.testutil')
+
+local eq = t.eq
+local feed_data = tt.feed_data
+local clear = n.clear
+local command = n.command
+local dedent = t.dedent
+local exec = n.exec
+local exec_lua = n.exec_lua
+local testprg = n.testprg
+local retry = t.retry
+local nvim_prog = n.nvim_prog
+local nvim_set = n.nvim_set
+local ok = t.ok
+local read_file = t.read_file
+local fn = n.fn
+local api = n.api
+local is_ci = t.is_ci
+local is_os = t.is_os
+local new_pipename = n.new_pipename
+local spawn_argv = n.spawn_argv
+local set_session = n.set_session
+local write_file = t.write_file
+local eval = n.eval
+local assert_log = t.assert_log
+
+local testlog = 'Xtest-tui-log'
+
+if t.skip(is_os('win')) then
return
end
@@ -42,7 +47,7 @@ describe('TUI', function()
before_each(function()
clear()
local child_server = new_pipename()
- screen = thelpers.setup_child_nvim({
+ screen = tt.setup_child_nvim({
'--listen',
child_server,
'-u',
@@ -61,8 +66,8 @@ describe('TUI', function()
|
{3:-- TERMINAL --} |
]])
- child_session = helpers.connect(child_server)
- child_exec_lua = thelpers.make_lua_executor(child_session)
+ child_session = n.connect(child_server)
+ child_exec_lua = tt.make_lua_executor(child_session)
end)
-- Wait for mode in the child Nvim (avoid "typeahead race" #10826).
@@ -83,7 +88,6 @@ describe('TUI', function()
end
it('rapid resize #7572 #7628', function()
- helpers.skip(helpers.is_asan(), 'Test extra unstable with ASAN. See #23762')
-- Need buffer rows to provoke the behavior.
feed_data(':edit test/functional/fixtures/bigfile.txt\n')
screen:expect([[
@@ -1345,15 +1349,15 @@ describe('TUI', function()
it('paste: big burst of input', function()
feed_data(':set ruler\n')
- local t = {}
+ local q = {}
for i = 1, 3000 do
- t[i] = 'item ' .. tostring(i)
+ q[i] = 'item ' .. tostring(i)
end
feed_data('i')
wait_for_mode('i')
-- "bracketed paste"
- feed_data('\027[200~' .. table.concat(t, '\n') .. '\027[201~')
- expect_child_buf_lines(t)
+ feed_data('\027[200~' .. table.concat(q, '\n') .. '\027[201~')
+ expect_child_buf_lines(q)
feed_data(' end')
screen:expect([[
item 2997 |
@@ -1486,7 +1490,8 @@ describe('TUI', function()
feed_data('\027[201~') -- phase 3
screen:expect_unchanged()
local _, rv = child_session:request('nvim_exec_lua', [[return _G.paste_phases]], {})
- eq({ 1, 2, 3 }, rv)
+ -- In rare cases there may be multiple chunks of phase 2 because of timing.
+ eq({ 1, 2, 3 }, { rv[1], rv[2], rv[#rv] })
end)
it('allows termguicolors to be set at runtime', function()
@@ -1588,6 +1593,35 @@ describe('TUI', function()
}
end)
+ -- Note: libvterm doesn't support colored underline or undercurl.
+ it('supports undercurl and underdouble when run in :terminal', function()
+ screen:set_default_attr_ids({
+ [1] = { reverse = true },
+ [2] = { bold = true, reverse = true },
+ [3] = { bold = true },
+ [4] = { foreground = 12 },
+ [5] = { undercurl = true },
+ [6] = { underdouble = true },
+ })
+ child_session:request('nvim_set_hl', 0, 'Visual', { undercurl = true })
+ feed_data('ifoobar\027V')
+ screen:expect([[
+ {5:fooba}{1:r} |
+ {4:~ }|*3
+ {2:[No Name] [+] }|
+ {3:-- VISUAL LINE --} |
+ {3:-- TERMINAL --} |
+ ]])
+ child_session:request('nvim_set_hl', 0, 'Visual', { underdouble = true })
+ screen:expect([[
+ {6:fooba}{1:r} |
+ {4:~ }|*3
+ {2:[No Name] [+] }|
+ {3:-- VISUAL LINE --} |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+
it('in nvim_list_uis()', function()
-- $TERM in :terminal.
local exp_term = is_os('bsd') and 'builtin_xterm' or 'xterm-256color'
@@ -1618,7 +1652,7 @@ describe('TUI', function()
eq(expected, rv)
end)
- it('allows grid to assume wider ambiguous-width characters than host terminal #19686', function()
+ it('allows grid to assume wider ambiwidth chars than host terminal', function()
child_session:request(
'nvim_buf_set_lines',
0,
@@ -1662,8 +1696,52 @@ describe('TUI', function()
screen:expect(singlewidth_screen)
end)
+ it('allows grid to assume wider non-ambiwidth chars than host terminal', function()
+ child_session:request(
+ 'nvim_buf_set_lines',
+ 0,
+ 0,
+ -1,
+ true,
+ { ('✓'):rep(60), ('✓'):rep(60) }
+ )
+ child_session:request('nvim_set_option_value', 'cursorline', true, {})
+ child_session:request('nvim_set_option_value', 'list', true, {})
+ child_session:request('nvim_set_option_value', 'listchars', 'eol:$', { win = 0 })
+ feed_data('gg')
+ local singlewidth_screen = [[
+ {13:✓}{12:✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓}|
+ {12:✓✓✓✓✓✓✓✓✓✓}{15:$}{12: }|
+ ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓|
+ ✓✓✓✓✓✓✓✓✓✓{4:$} |
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]]
+ -- When grid assumes "✓" to be double-width but host terminal assumes it to be single-width,
+ -- the second cell of "✓" is a space and the attributes of the "✓" are applied to it.
+ local doublewidth_screen = [[
+ {13:✓}{12: ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }|
+ {12:✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }|
+ {12:✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }{15:$}{12: }|
+ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ {4:@@@@}|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]]
+ screen:expect(singlewidth_screen)
+ child_session:request('nvim_set_option_value', 'ambiwidth', 'double', {})
+ screen:expect_unchanged()
+ child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2713, 0x2713, 2 } } })
+ screen:expect(doublewidth_screen)
+ child_session:request('nvim_set_option_value', 'ambiwidth', 'single', {})
+ screen:expect_unchanged()
+ child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2713, 0x2713, 1 } } })
+ screen:expect(singlewidth_screen)
+ end)
+
it('draws correctly when cursor_address overflows #21643', function()
- helpers.skip(is_os('mac'), 'FIXME: crashes/errors on macOS')
+ t.skip(is_os('mac'), 'FIXME: crashes/errors on macOS')
screen:try_resize(77, 855)
retry(nil, nil, function()
eq({ true, 852 }, { child_session:request('nvim_win_get_height', 0) })
@@ -1925,6 +2003,39 @@ describe('TUI', function()
]])
end)
+ it('invalidated regions are cleared with terminal background attr', function()
+ local screen = Screen.new(50, 10)
+ screen:set_default_attr_ids({ [1] = { foreground = Screen.colors.Black } })
+ screen:attach()
+ fn.termopen({
+ nvim_prog,
+ '--clean',
+ '--cmd',
+ 'set termguicolors',
+ '--cmd',
+ 'sleep 10',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ })
+ screen:expect({
+ grid = [[
+ {1:^ }|
+ {1: }|*8
+ |
+ ]],
+ })
+ screen:try_resize(51, 11)
+ screen:expect({
+ grid = [[
+ {1:^ }|
+ {1: }|*9
+ |
+ ]],
+ })
+ end)
+
it('argv[0] can be overridden #23953', function()
if not exec_lua('return pcall(require, "ffi")') then
pending('missing LuaJIT FFI')
@@ -1941,7 +2052,7 @@ describe('TUI', function()
finally(function()
os.remove(script_file)
end)
- local screen = thelpers.setup_child_nvim({ '--clean', '-l', script_file })
+ local screen = tt.setup_child_nvim({ '--clean', '-l', script_file })
screen:expect {
grid = [[
{1: } |
@@ -1969,7 +2080,7 @@ describe('TUI', function()
finally(function()
os.remove('testF')
end)
- local screen = thelpers.screen_setup(
+ local screen = tt.screen_setup(
0,
('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format(
nvim_prog
@@ -1990,7 +2101,7 @@ describe('TUI', function()
end)
it('<C-h> #10134', function()
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2023,7 +2134,7 @@ describe('TUI', function()
end)
it('draws line with many trailing spaces correctly #24955', function()
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2062,7 +2173,7 @@ describe('TUI', function()
it('no heap-buffer-overflow when changing &columns', function()
-- Set a different bg colour and change $TERM to something dumber so the `print_spaces()`
-- codepath in `clear_region()` is hit.
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2105,7 +2216,7 @@ end)
describe('TUI UIEnter/UILeave', function()
it('fires exactly once, after VimEnter', function()
clear()
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2152,7 +2263,7 @@ describe('TUI FocusGained/FocusLost', function()
before_each(function()
clear()
local child_server = new_pipename()
- screen = thelpers.setup_child_nvim({
+ screen = tt.setup_child_nvim({
'--listen',
child_server,
'-u',
@@ -2172,7 +2283,7 @@ describe('TUI FocusGained/FocusLost', function()
|
{3:-- TERMINAL --} |
]])
- child_session = helpers.connect(child_server)
+ child_session = n.connect(child_server)
child_session:request(
'nvim_exec2',
[[
@@ -2364,14 +2475,14 @@ describe('TUI FocusGained/FocusLost', function()
end)
end)
--- These tests require `thelpers` because --headless/--embed
+-- These tests require `tt` because --headless/--embed
-- does not initialize the TUI.
describe("TUI 't_Co' (terminal colors)", function()
local screen
local function assert_term_colors(term, colorterm, maxcolors)
clear({ env = { TERM = term }, args = {} })
- screen = thelpers.setup_child_nvim({
+ screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2647,14 +2758,14 @@ describe("TUI 't_Co' (terminal colors)", function()
end)
end)
--- These tests require `thelpers` because --headless/--embed
+-- These tests require `tt` because --headless/--embed
-- does not initialize the TUI.
describe("TUI 'term' option", function()
local screen
local function assert_term(term_envvar, term_expected)
clear()
- screen = thelpers.setup_child_nvim({
+ screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2702,7 +2813,7 @@ describe("TUI 'term' option", function()
end)
end)
--- These tests require `thelpers` because --headless/--embed
+-- These tests require `tt` because --headless/--embed
-- does not initialize the TUI.
describe('TUI', function()
local screen
@@ -2714,7 +2825,7 @@ describe('TUI', function()
-- Runs (child) `nvim` in a TTY (:terminal), to start the builtin TUI.
local function nvim_tui(extra_args)
clear()
- screen = thelpers.setup_child_nvim({
+ screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2795,7 +2906,7 @@ describe('TUI', function()
]])
local child_server = new_pipename()
- screen = thelpers.setup_child_nvim({
+ screen = tt.setup_child_nvim({
'--listen',
child_server,
'-u',
@@ -2815,7 +2926,7 @@ describe('TUI', function()
screen:expect({ any = '%[No Name%]' })
- local child_session = helpers.connect(child_server)
+ local child_session = n.connect(child_server)
retry(nil, 1000, function()
eq({
Tc = true,
@@ -2845,7 +2956,7 @@ describe('TUI', function()
]])
local child_server = new_pipename()
- screen = thelpers.setup_child_nvim({
+ screen = tt.setup_child_nvim({
'--listen',
child_server,
-- Use --clean instead of -u NONE to load the osc52 plugin
@@ -2861,7 +2972,7 @@ describe('TUI', function()
screen:expect({ any = '%[No Name%]' })
- local child_session = helpers.connect(child_server)
+ local child_session = n.connect(child_server)
retry(nil, 1000, function()
eq('Ms', eval("get(g:, 'xtgettcap', '')"))
eq({ true, 'OSC 52' }, { child_session:request('nvim_eval', 'g:clipboard.name') })
@@ -2876,7 +2987,7 @@ describe('TUI bg color', function()
command('highlight clear Normal')
command('set background=dark') -- set outer Nvim background
local child_server = new_pipename()
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'--listen',
child_server,
'-u',
@@ -2889,7 +3000,7 @@ describe('TUI bg color', function()
'set noswapfile',
})
screen:expect({ any = '%[No Name%]' })
- local child_session = helpers.connect(child_server)
+ local child_session = n.connect(child_server)
retry(nil, nil, function()
eq({ true, 'dark' }, { child_session:request('nvim_eval', '&background') })
end)
@@ -2899,7 +3010,7 @@ describe('TUI bg color', function()
command('highlight clear Normal')
command('set background=light') -- set outer Nvim background
local child_server = new_pipename()
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'--listen',
child_server,
'-u',
@@ -2912,7 +3023,7 @@ describe('TUI bg color', function()
'set noswapfile',
})
screen:expect({ any = '%[No Name%]' })
- local child_session = helpers.connect(child_server)
+ local child_session = n.connect(child_server)
retry(nil, nil, function()
eq({ true, 'light' }, { child_session:request('nvim_eval', '&background') })
end)
@@ -2930,7 +3041,7 @@ describe('TUI bg color', function()
end,
})
]])
- thelpers.setup_child_nvim({
+ tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2946,7 +3057,7 @@ describe('TUI bg color', function()
end)
it('triggers OptionSet from automatic background processing', function()
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'-u',
'NONE',
'-i',
@@ -2968,16 +3079,20 @@ describe('TUI bg color', function()
end)
end)
--- These tests require `thelpers` because --headless/--embed
+-- These tests require `tt` because --headless/--embed
-- does not initialize the TUI.
describe('TUI as a client', function()
+ after_each(function()
+ os.remove(testlog)
+ end)
+
it('connects to remote instance (with its own TUI)', function()
local server_super = spawn_argv(false) -- equivalent to clear()
local client_super = spawn_argv(true)
set_session(server_super)
local server_pipe = new_pipename()
- local screen_server = thelpers.setup_child_nvim({
+ local screen_server = tt.setup_child_nvim({
'--listen',
server_pipe,
'-u',
@@ -3012,7 +3127,7 @@ describe('TUI as a client', function()
}
set_session(client_super)
- local screen_client = thelpers.setup_child_nvim({
+ local screen_client = tt.setup_child_nvim({
'--server',
server_pipe,
'--remote-ui',
@@ -3048,7 +3163,7 @@ describe('TUI as a client', function()
it('connects to remote instance (--headless)', function()
local server = spawn_argv(false) -- equivalent to clear()
- local client_super = spawn_argv(true)
+ local client_super = spawn_argv(true, { env = { NVIM_LOG_FILE = testlog } })
set_session(server)
local server_pipe = api.nvim_get_vvar('servername')
@@ -3056,7 +3171,7 @@ describe('TUI as a client', function()
server:request('nvim_command', 'set notermguicolors')
set_session(client_super)
- local screen_client = thelpers.setup_child_nvim({
+ local screen_client = tt.setup_child_nvim({
'--server',
server_pipe,
'--remote-ui',
@@ -3091,11 +3206,14 @@ describe('TUI as a client', function()
client_super:close()
server:close()
+ if is_os('mac') then
+ assert_log('uv_tty_set_mode failed: Unknown system error %-102', testlog)
+ end
end)
it('throws error when no server exists', function()
clear()
- local screen = thelpers.setup_child_nvim({
+ local screen = tt.setup_child_nvim({
'--server',
'127.0.0.1:2436546',
'--remote-ui',
@@ -3116,7 +3234,7 @@ describe('TUI as a client', function()
set_session(server_super)
local server_pipe = new_pipename()
- local screen_server = thelpers.setup_child_nvim({
+ local screen_server = tt.setup_child_nvim({
'--listen',
server_pipe,
'-u',
@@ -3160,7 +3278,7 @@ describe('TUI as a client', function()
}
set_session(client_super)
- local screen_client = thelpers.setup_child_nvim({
+ local screen_client = tt.setup_child_nvim({
'--server',
server_pipe,
'--remote-ui',