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.lua179
1 files changed, 101 insertions, 78 deletions
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index a7d87bb231..ded0cd99d3 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -13,7 +13,6 @@ 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
@@ -87,6 +86,21 @@ describe('TUI', function()
end)
end
+ -- Ensure both child client and child server have processed pending events.
+ local function poke_both_eventloop()
+ child_exec_lua([[
+ _G.termresponse = nil
+ vim.api.nvim_create_autocmd('TermResponse', {
+ once = true,
+ callback = function(ev) _G.termresponse = ev.data end,
+ })
+ ]])
+ feed_data('\027P0$r\027\\')
+ retry(nil, nil, function()
+ eq('\027P0$r', child_exec_lua('return _G.termresponse'))
+ end)
+ end
+
it('rapid resize #7572 #7628', function()
-- Need buffer rows to provoke the behavior.
feed_data(':edit test/functional/fixtures/bigfile.txt\n')
@@ -975,6 +989,7 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
feed_data('\027[201~') -- End paste.
+ poke_both_eventloop()
screen:expect_unchanged()
feed_data('\027[27u') -- ESC: go to Normal mode.
wait_for_mode('n')
@@ -1157,6 +1172,7 @@ describe('TUI', function()
feed_data('\027[200~line 1\nline 2\n')
wait_for_mode('c')
feed_data('line 3\nline 4\n\027[201~')
+ poke_both_eventloop()
wait_for_mode('c')
screen:expect([[
foo |
@@ -1201,22 +1217,19 @@ describe('TUI', function()
expect_cmdline('"stuff 1 more"')
-- End the paste sequence.
feed_data('\027[201~')
+ poke_both_eventloop()
expect_cmdline('"stuff 1 more"')
feed_data(' typed')
expect_cmdline('"stuff 1 more typed"')
end)
it('paste: recovers from vim.paste() failure', function()
- child_session:request(
- 'nvim_exec_lua',
- [[
+ child_exec_lua([[
_G.save_paste_fn = vim.paste
-- Stack traces for this test are non-deterministic, so disable them
_G.debug.traceback = function(msg) return msg end
vim.paste = function(lines, phase) error("fake fail") end
- ]],
- {}
- )
+ ]])
-- Prepare something for dot-repeat/redo.
feed_data('ifoo\n\027[27u')
wait_for_mode('n')
@@ -1269,7 +1282,7 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- Paste works if vim.paste() succeeds.
- child_session:request('nvim_exec_lua', [[vim.paste = _G.save_paste_fn]], {})
+ child_exec_lua([[vim.paste = _G.save_paste_fn]])
feed_data('\027[200~line A\nline B\n\027[201~')
screen:expect([[
foo |
@@ -1285,13 +1298,9 @@ describe('TUI', function()
it('paste: vim.paste() cancel (retval=false) #10865', function()
-- This test only exercises the "cancel" case. Use-case would be "dangling
-- paste", but that is not implemented yet. #10865
- child_session:request(
- 'nvim_exec_lua',
- [[
+ child_exec_lua([[
vim.paste = function(lines, phase) return false end
- ]],
- {}
- )
+ ]])
feed_data('\027[200~line A\nline B\n\027[201~')
expect_child_buf_lines({ '' })
feed_data('ifoo\n\027[27u')
@@ -1299,22 +1308,18 @@ describe('TUI', function()
end)
it('paste: vim.paste() cancel (retval=false) with streaming #30462', function()
- child_session:request(
- 'nvim_exec_lua',
- [[
- vim.paste = (function(overridden)
- return function(lines, phase)
- for i, line in ipairs(lines) do
- if line:find('!') then
- return false
- end
+ child_exec_lua([[
+ vim.paste = (function(overridden)
+ return function(lines, phase)
+ for i, line in ipairs(lines) do
+ if line:find('!') then
+ return false
end
- return overridden(lines, phase)
end
- end)(vim.paste)
- ]],
- {}
- )
+ return overridden(lines, phase)
+ end
+ end)(vim.paste)
+ ]])
feed_data('A')
wait_for_mode('i')
feed_data('\027[200~aaa')
@@ -1324,6 +1329,7 @@ describe('TUI', function()
feed_data('ccc!') -- This chunk is cancelled.
expect_child_buf_lines({ 'aaabbb' })
feed_data('ddd\027[201~') -- This chunk is ignored.
+ poke_both_eventloop()
expect_child_buf_lines({ 'aaabbb' })
feed_data('\027[27u')
wait_for_mode('n')
@@ -1334,15 +1340,11 @@ describe('TUI', function()
end)
it("paste: 'nomodifiable' buffer", function()
- child_session:request('nvim_command', 'set nomodifiable')
- child_session:request(
- 'nvim_exec_lua',
- [[
+ child_exec_lua([[
+ vim.bo.modifiable = false
-- Truncate the error message to hide the line number
_G.debug.traceback = function(msg) return msg:sub(-49) end
- ]],
- {}
- )
+ ]])
feed_data('\027[200~fail 1\nfail 2\n\027[201~')
screen:expect([[
|
@@ -1354,7 +1356,7 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
feed_data('\n') -- <Enter> to dismiss hit-enter prompt
- child_session:request('nvim_command', 'set modifiable')
+ child_exec_lua('vim.bo.modifiable = true')
feed_data('\027[200~success 1\nsuccess 2\n\027[201~')
screen:expect([[
success 1 |
@@ -1509,9 +1511,7 @@ describe('TUI', function()
end)
it('paste: streamed paste with isolated "stop paste" code', function()
- child_session:request(
- 'nvim_exec_lua',
- [[
+ child_exec_lua([[
_G.paste_phases = {}
vim.paste = (function(overridden)
return function(lines, phase)
@@ -1519,9 +1519,7 @@ describe('TUI', function()
overridden(lines, phase)
end
end)(vim.paste)
- ]],
- {}
- )
+ ]])
feed_data('i')
wait_for_mode('i')
feed_data('\027[200~pasted') -- phase 1
@@ -1542,8 +1540,9 @@ describe('TUI', function()
]])
-- Send isolated "stop paste" sequence.
feed_data('\027[201~') -- phase 3
+ poke_both_eventloop()
screen:expect_unchanged()
- local _, rv = child_session:request('nvim_exec_lua', [[return _G.paste_phases]], {})
+ local rv = child_exec_lua('return _G.paste_phases')
-- 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)
@@ -1729,9 +1728,7 @@ describe('TUI', function()
eq(expected, rv)
---@type table
- local expected_version = ({
- child_session:request('nvim_exec_lua', 'return vim.version()', {}),
- })[2]
+ local expected_version = child_exec_lua('return vim.version()')
-- vim.version() returns `prerelease` string. Coerce it to boolean.
expected_version.prerelease = not not expected_version.prerelease
@@ -1855,45 +1852,73 @@ describe('TUI', function()
end)
it('draws correctly when cursor_address overflows #21643', function()
- t.skip(is_os('mac'), 'FIXME: crashes/errors on macOS')
- screen:try_resize(77, 855)
+ screen:try_resize(70, 333)
retry(nil, nil, function()
- eq({ true, 852 }, { child_session:request('nvim_win_get_height', 0) })
+ eq({ true, 330 }, { child_session:request('nvim_win_get_height', 0) })
end)
+ child_session:request('nvim_set_option_value', 'cursorline', true, {})
-- Use full screen message so that redrawing afterwards is more deterministic.
child_session:notify('nvim_command', 'intro')
- screen:expect({ any = 'Nvim' })
+ screen:expect({ any = 'Nvim is open source and freely distributable' })
-- Going to top-left corner needs 3 bytes.
-- Setting underline attribute needs 9 bytes.
- -- The whole line needs 3 + 9 + 65513 + 3 = 65528 bytes.
+ -- A Ꝩ character takes 3 bytes.
+ -- The whole line needs 3 + 9 + 3 * 21838 + 3 = 65529 bytes.
-- The cursor_address that comes after will overflow the 65535-byte buffer.
- local line = ('a'):rep(65513) .. '℃'
- child_session:notify(
- 'nvim_exec_lua',
- [[
- vim.api.nvim_buf_set_lines(0, 0, -1, true, {...})
- vim.o.cursorline = true
- ]],
- { line, 'b' }
- )
+ local line = ('Ꝩ'):rep(21838) .. '℃'
+ child_session:notify('nvim_buf_set_lines', 0, 0, -1, true, { line, 'b' })
-- Close the :intro message and redraw the lines.
feed_data('\n')
- screen:expect(
- '{13:a}{12:'
- .. ('a'):rep(76)
- .. '}|\n'
- .. ('{12:' .. ('a'):rep(77) .. '}|\n'):rep(849)
- .. '{12:'
- .. ('a'):rep(63)
- .. '℃'
- .. (' '):rep(13)
- .. '}|\n'
- .. dedent([[
- b |
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |]])
- )
+ screen:expect([[
+ {13:Ꝩ}{12:ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ}|
+ {12:ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ}|*310
+ {12:ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ℃ }|
+ b |
+ {4:~ }|*17
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+
+ it('draws correctly when setting title overflows #30793', function()
+ screen:try_resize(67, 327)
+ retry(nil, nil, function()
+ eq({ true, 324 }, { child_session:request('nvim_win_get_height', 0) })
+ end)
+ child_exec_lua([[
+ vim.o.cmdheight = 0
+ vim.o.laststatus = 0
+ vim.o.ruler = false
+ vim.o.showcmd = false
+ vim.o.termsync = false
+ vim.o.title = true
+ ]])
+ retry(nil, nil, function()
+ eq('[No Name] - Nvim', api.nvim_buf_get_var(0, 'term_title'))
+ eq({ true, 326 }, { child_session:request('nvim_win_get_height', 0) })
+ end)
+ -- Use full screen message so that redrawing afterwards is more deterministic.
+ child_session:notify('nvim_command', 'intro')
+ screen:expect({ any = 'Nvim is open source and freely distributable' })
+ -- Going to top-left corner needs 3 bytes.
+ -- A Ꝩ character takes 3 bytes.
+ -- The whole line needs 3 + 3 * 21842 = 65529 bytes.
+ -- The title will be updated because the buffer is now modified.
+ -- The start of the OSC 0 sequence to set title can fit in the 65535-byte buffer,
+ -- but the title string cannot.
+ local line = ('Ꝩ'):rep(21842)
+ child_session:notify('nvim_buf_set_lines', 0, 0, -1, true, { line })
+ -- Close the :intro message and redraw the lines.
+ feed_data('\n')
+ screen:expect([[
+ {1:Ꝩ}ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ|
+ ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ|*325
+ {3:-- TERMINAL --} |
+ ]])
+ retry(nil, nil, function()
+ eq('[No Name] + - Nvim', api.nvim_buf_get_var(0, 'term_title'))
+ end)
end)
it('visual bell (padding) does not crash #21610', function()
@@ -2089,7 +2114,6 @@ describe('TUI', function()
[5] = { bold = true, reverse = true },
[6] = { foreground = Screen.colors.White, background = Screen.colors.DarkGreen },
})
- screen:attach()
fn.termopen({
nvim_prog,
'--clean',
@@ -2122,7 +2146,6 @@ describe('TUI', function()
for _, guicolors in ipairs({ 'notermguicolors', 'termguicolors' }) do
it('has no black flicker when clearing regions during startup with ' .. guicolors, function()
local screen = Screen.new(50, 10)
- screen:attach()
fn.termopen({
nvim_prog,
'--clean',