aboutsummaryrefslogtreecommitdiff
path: root/test/functional/terminal/tui_spec.lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /test/functional/terminal/tui_spec.lua
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-aucmd_textputpost.tar.gz
rneovim-aucmd_textputpost.tar.bz2
rneovim-aucmd_textputpost.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'test/functional/terminal/tui_spec.lua')
-rw-r--r--test/functional/terminal/tui_spec.lua921
1 files changed, 667 insertions, 254 deletions
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 1d9e7b8e11..b17eed00f9 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -8,7 +8,6 @@ local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
-local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data
local clear = helpers.clear
local command = helpers.command
@@ -28,10 +27,9 @@ 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 feed = helpers.feed
-local eval = helpers.eval
+local write_file = helpers.write_file
-if helpers.skip(helpers.is_os('win')) then return end
+if helpers.skip(is_os('win')) then return end
describe('TUI', function()
local screen
@@ -69,13 +67,13 @@ describe('TUI', function()
local function expect_child_buf_lines(expected)
assert(type({}) == type(expected))
retry(nil, nil, function()
- local _, buflines = child_session:request(
- 'nvim_buf_get_lines', 0, 0, -1, false)
+ local _, buflines = child_session:request('nvim_buf_get_lines', 0, 0, -1, false)
eq(expected, buflines)
end)
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([[
@@ -109,14 +107,14 @@ describe('TUI', function()
end)
it('accepts resize while pager is active', function()
- child_session:request("nvim_command", [[
- set more
- func! ManyErr()
- for i in range(10)
- echoerr "FAIL ".i
- endfor
- endfunc
- ]])
+ child_session:request('nvim_exec2', [[
+ set more
+ func! ManyErr()
+ for i in range(20)
+ echoerr "FAIL ".i
+ endfor
+ endfunc
+ ]], {})
feed_data(':call ManyErr()\r')
screen:expect{grid=[[
{8:Error detected while processing function ManyErr:} |
@@ -128,7 +126,35 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]]}
- feed_data('d')
+ screen:try_resize(50,10)
+ screen:expect{grid=[[
+ :call ManyErr() |
+ {8:Error detected while processing function ManyErr:} |
+ {11:line 2:} |
+ {8:FAIL 0} |
+ {8:FAIL 1} |
+ {8:FAIL 2} |
+ |
+ |
+ {10:-- More --}{1: } |
+ {3:-- TERMINAL --} |
+ ]]}
+
+ feed_data('j')
+ screen:expect{grid=[[
+ {8:Error detected while processing function ManyErr:} |
+ {11:line 2:} |
+ {8:FAIL 0} |
+ {8:FAIL 1} |
+ {8:FAIL 2} |
+ {8:FAIL 3} |
+ {8:FAIL 4} |
+ {8:FAIL 5} |
+ {10:-- More --}{1: } |
+ {3:-- TERMINAL --} |
+ ]]}
+
+ screen:try_resize(50,7)
screen:expect{grid=[[
{8:FAIL 1} |
{8:FAIL 2} |
@@ -212,7 +238,7 @@ describe('TUI', function()
it('interprets leading <Esc> byte as ALT modifier in normal-mode', function()
local keys = 'dfghjkl'
for c in keys:gmatch('.') do
- feed_command('nnoremap <a-'..c..'> ialt-'..c..'<cr><esc>')
+ feed_data(':nnoremap <a-'..c..'> ialt-'..c..'<cr><esc>\r')
feed_data('\027'..c)
end
screen:expect([[
@@ -252,9 +278,11 @@ 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>')
+ child_session:request('nvim_exec2', [[
+ nnoremap <M-;> <Nop>
+ nnoremap <Esc> AESC<Esc>
+ nnoremap ; Asemicolon<Esc>
+ ]], {})
feed_data('\027[27u;')
screen:expect([[
ESCsemicolo{1:n} |
@@ -291,22 +319,22 @@ describe('TUI', function()
local attrs = screen:get_default_attr_ids()
attrs[11] = {foreground = 81}
screen:expect([[
- {11:^G^V^M}{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
+ {11:^G^V^M}{1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
]], attrs)
end)
- it('accepts mouse wheel events #19992', function()
- child_session:request('nvim_command', [[
+ local function test_mouse_wheel(esc)
+ child_session:request('nvim_exec2', [[
set number nostartofline nowrap mousescroll=hor:1,ver:1
call setline(1, repeat([join(range(10), '----')], 10))
vsplit
- ]])
+ ]], {})
screen:expect([[
{11: 1 }{1:0}----1----2----3----4│{11: 1 }0----1----2----3----|
{11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----|
@@ -317,7 +345,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelDown> in active window
- feed_data('\027[<65;8;1M')
+ if esc then
+ feed_data('\027[<65;8;1M')
+ else
+ meths.input_mouse('wheel', 'down', '', 0, 0, 7)
+ end
screen:expect([[
{11: 2 }{1:0}----1----2----3----4│{11: 1 }0----1----2----3----|
{11: 3 }0----1----2----3----4│{11: 2 }0----1----2----3----|
@@ -328,7 +360,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelDown> in inactive window
- feed_data('\027[<65;48;1M')
+ if esc then
+ feed_data('\027[<65;48;1M')
+ else
+ meths.input_mouse('wheel', 'down', '', 0, 0, 47)
+ end
screen:expect([[
{11: 2 }{1:0}----1----2----3----4│{11: 2 }0----1----2----3----|
{11: 3 }0----1----2----3----4│{11: 3 }0----1----2----3----|
@@ -339,7 +375,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelRight> in active window
- feed_data('\027[<67;8;1M')
+ if esc then
+ feed_data('\027[<67;8;1M')
+ else
+ meths.input_mouse('wheel', 'right', '', 0, 0, 7)
+ end
screen:expect([[
{11: 2 }{1:-}---1----2----3----4-│{11: 2 }0----1----2----3----|
{11: 3 }----1----2----3----4-│{11: 3 }0----1----2----3----|
@@ -350,7 +390,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelRight> in inactive window
- feed_data('\027[<67;48;1M')
+ if esc then
+ feed_data('\027[<67;48;1M')
+ else
+ meths.input_mouse('wheel', 'right', '', 0, 0, 47)
+ end
screen:expect([[
{11: 2 }{1:-}---1----2----3----4-│{11: 2 }----1----2----3----4|
{11: 3 }----1----2----3----4-│{11: 3 }----1----2----3----4|
@@ -361,7 +405,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelDown> in active window
- feed_data('\027[<69;8;1M')
+ if esc then
+ feed_data('\027[<69;8;1M')
+ else
+ meths.input_mouse('wheel', 'down', 'S', 0, 0, 7)
+ end
screen:expect([[
{11: 5 }{1:-}---1----2----3----4-│{11: 2 }----1----2----3----4|
{11: 6 }----1----2----3----4-│{11: 3 }----1----2----3----4|
@@ -372,7 +420,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelDown> in inactive window
- feed_data('\027[<69;48;1M')
+ if esc then
+ feed_data('\027[<69;48;1M')
+ else
+ meths.input_mouse('wheel', 'down', 'S', 0, 0, 47)
+ end
screen:expect([[
{11: 5 }{1:-}---1----2----3----4-│{11: 5 }----1----2----3----4|
{11: 6 }----1----2----3----4-│{11: 6 }----1----2----3----4|
@@ -383,7 +435,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelRight> in active window
- feed_data('\027[<71;8;1M')
+ if esc then
+ feed_data('\027[<71;8;1M')
+ else
+ meths.input_mouse('wheel', 'right', 'S', 0, 0, 7)
+ end
screen:expect([[
{11: 5 }{1:-}---6----7----8----9 │{11: 5 }----1----2----3----4|
{11: 6 }----6----7----8----9 │{11: 6 }----1----2----3----4|
@@ -394,7 +450,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelRight> in inactive window
- feed_data('\027[<71;48;1M')
+ if esc then
+ feed_data('\027[<71;48;1M')
+ else
+ meths.input_mouse('wheel', 'right', 'S', 0, 0, 47)
+ end
screen:expect([[
{11: 5 }{1:-}---6----7----8----9 │{11: 5 }5----6----7----8----|
{11: 6 }----6----7----8----9 │{11: 6 }5----6----7----8----|
@@ -405,7 +465,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelUp> in active window
- feed_data('\027[<64;8;1M')
+ if esc then
+ feed_data('\027[<64;8;1M')
+ else
+ meths.input_mouse('wheel', 'up', '', 0, 0, 7)
+ end
screen:expect([[
{11: 4 }----6----7----8----9 │{11: 5 }5----6----7----8----|
{11: 5 }{1:-}---6----7----8----9 │{11: 6 }5----6----7----8----|
@@ -416,7 +480,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelUp> in inactive window
- feed_data('\027[<64;48;1M')
+ if esc then
+ feed_data('\027[<64;48;1M')
+ else
+ meths.input_mouse('wheel', 'up', '', 0, 0, 47)
+ end
screen:expect([[
{11: 4 }----6----7----8----9 │{11: 4 }5----6----7----8----|
{11: 5 }{1:-}---6----7----8----9 │{11: 5 }5----6----7----8----|
@@ -427,7 +495,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelLeft> in active window
- feed_data('\027[<66;8;1M')
+ if esc then
+ feed_data('\027[<66;8;1M')
+ else
+ meths.input_mouse('wheel', 'left', '', 0, 0, 7)
+ end
screen:expect([[
{11: 4 }5----6----7----8----9│{11: 4 }5----6----7----8----|
{11: 5 }5{1:-}---6----7----8----9│{11: 5 }5----6----7----8----|
@@ -438,7 +510,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <ScrollWheelLeft> in inactive window
- feed_data('\027[<66;48;1M')
+ if esc then
+ feed_data('\027[<66;48;1M')
+ else
+ meths.input_mouse('wheel', 'left', '', 0, 0, 47)
+ end
screen:expect([[
{11: 4 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
{11: 5 }5{1:-}---6----7----8----9│{11: 5 }-5----6----7----8---|
@@ -449,7 +525,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelUp> in active window
- feed_data('\027[<68;8;1M')
+ if esc then
+ feed_data('\027[<68;8;1M')
+ else
+ meths.input_mouse('wheel', 'up', 'S', 0, 0, 7)
+ end
screen:expect([[
{11: 1 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
{11: 2 }5----6----7----8----9│{11: 5 }-5----6----7----8---|
@@ -460,7 +540,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelUp> in inactive window
- feed_data('\027[<68;48;1M')
+ if esc then
+ feed_data('\027[<68;48;1M')
+ else
+ meths.input_mouse('wheel', 'up', 'S', 0, 0, 47)
+ end
screen:expect([[
{11: 1 }5----6----7----8----9│{11: 1 }-5----6----7----8---|
{11: 2 }5----6----7----8----9│{11: 2 }-5----6----7----8---|
@@ -471,7 +555,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelLeft> in active window
- feed_data('\027[<70;8;1M')
+ if esc then
+ feed_data('\027[<70;8;1M')
+ else
+ meths.input_mouse('wheel', 'left', 'S', 0, 0, 7)
+ end
screen:expect([[
{11: 1 }0----1----2----3----4│{11: 1 }-5----6----7----8---|
{11: 2 }0----1----2----3----4│{11: 2 }-5----6----7----8---|
@@ -482,7 +570,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
-- <S-ScrollWheelLeft> in inactive window
- feed_data('\027[<70;48;1M')
+ if esc then
+ feed_data('\027[<70;48;1M')
+ else
+ meths.input_mouse('wheel', 'left', 'S', 0, 0, 47)
+ end
screen:expect([[
{11: 1 }0----1----2----3----4│{11: 1 }0----1----2----3----|
{11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----|
@@ -492,6 +584,136 @@ describe('TUI', function()
|
{3:-- TERMINAL --} |
]])
+ end
+
+ describe('accepts mouse wheel events', function()
+ it('(mouse events sent to host)', function()
+ test_mouse_wheel(false)
+ end)
+
+ it('(escape sequences sent to child)', function()
+ test_mouse_wheel(true)
+ end)
+ end)
+
+ local function test_mouse_popup(esc)
+ child_session:request('nvim_exec2', [[
+ call setline(1, 'popup menu test')
+ set mouse=a mousemodel=popup
+
+ aunmenu PopUp
+ menu PopUp.foo :let g:menustr = 'foo'<CR>
+ menu PopUp.bar :let g:menustr = 'bar'<CR>
+ menu PopUp.baz :let g:menustr = 'baz'<CR>
+ highlight Pmenu ctermbg=NONE ctermfg=NONE cterm=underline,reverse
+ highlight PmenuSel ctermbg=NONE ctermfg=NONE cterm=underline,reverse,bold
+ ]], {})
+ if esc then
+ feed_data('\027[<2;5;1M')
+ else
+ meths.input_mouse('right', 'press', '', 0, 0, 4)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }{13: foo }{4: }|
+ {4:~ }{13: bar }{4: }|
+ {4:~ }{13: baz }{4: }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ if esc then
+ feed_data('\027[<2;5;1m')
+ else
+ meths.input_mouse('right', 'release', '', 0, 0, 4)
+ end
+ screen:expect_unchanged()
+ if esc then
+ feed_data('\027[<35;7;4M')
+ else
+ meths.input_mouse('move', '', '', 0, 3, 6)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }{13: foo }{4: }|
+ {4:~ }{13: bar }{4: }|
+ {4:~ }{14: baz }{4: }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ if esc then
+ feed_data('\027[<0;7;3M')
+ else
+ meths.input_mouse('left', 'press', '', 0, 2, 6)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ :let g:menustr = 'bar' |
+ {3:-- TERMINAL --} |
+ ]])
+ if esc then
+ feed_data('\027[<0;7;3m')
+ else
+ meths.input_mouse('left', 'release', '', 0, 2, 6)
+ end
+ screen:expect_unchanged()
+ if esc then
+ feed_data('\027[<2;45;3M')
+ else
+ meths.input_mouse('right', 'press', '', 0, 2, 44)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }{13: foo }{4: }|
+ {5:[No Name] [+] }{13: bar }{5: }|
+ :let g:menustr = 'bar' {13: baz } |
+ {3:-- TERMINAL --} |
+ ]])
+ if esc then
+ feed_data('\027[<34;48;6M')
+ else
+ meths.input_mouse('right', 'drag', '', 0, 5, 47)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }{13: foo }{4: }|
+ {5:[No Name] [+] }{13: bar }{5: }|
+ :let g:menustr = 'bar' {14: baz } |
+ {3:-- TERMINAL --} |
+ ]])
+ if esc then
+ feed_data('\027[<2;48;6m')
+ else
+ meths.input_mouse('right', 'release', '', 0, 5, 47)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ :let g:menustr = 'baz' |
+ {3:-- TERMINAL --} |
+ ]])
+ end
+
+ describe('mouse events work with right-click menu', function()
+ it('(mouse events sent to host)', function()
+ test_mouse_popup(false)
+ end)
+
+ it('(escape sequences sent to child)', function()
+ test_mouse_popup(true)
+ end)
end)
it('accepts keypad keys from kitty keyboard protocol #19180', function()
@@ -632,11 +854,11 @@ describe('TUI', function()
|
{3:-- TERMINAL --} |
]])
- child_session:request('nvim_command', [[
+ child_session:request('nvim_exec2', [[
tab split
tabnew
highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline
- ]])
+ ]], {})
screen:expect([[
{12: + [No Name] + [No Name] }{3: [No Name] }{1: }{12:X}|
{1: } |
@@ -668,52 +890,26 @@ describe('TUI', function()
]])
end)
- it('mouse events work with right-click menu', function()
- child_session:request('nvim_command', [[
- call setline(1, 'popup menu test')
- set mouse=a mousemodel=popup
-
- aunmenu PopUp
- menu PopUp.foo :let g:menustr = 'foo'<CR>
- menu PopUp.bar :let g:menustr = 'bar'<CR>
- menu PopUp.baz :let g:menustr = 'baz'<CR>
- highlight Pmenu ctermbg=NONE ctermfg=NONE cterm=underline,reverse
- highlight PmenuSel ctermbg=NONE ctermfg=NONE cterm=underline,reverse,bold
- ]])
- meths.input_mouse('right', 'press', '', 0, 0, 4)
- screen:expect([[
- {1:p}opup menu test |
- {4:~ }{13: foo }{4: }|
- {4:~ }{13: bar }{4: }|
- {4:~ }{13: baz }{4: }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- meths.input_mouse('right', 'release', '', 0, 0, 4)
- screen:expect_unchanged()
- meths.input_mouse('move', '', '', 0, 3, 6)
- screen:expect([[
- {1:p}opup menu test |
- {4:~ }{13: foo }{4: }|
- {4:~ }{13: bar }{4: }|
- {4:~ }{14: baz }{4: }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- meths.input_mouse('left', 'press', '', 0, 2, 6)
+ it('supports Super and Meta modifiers', function()
+ feed_data('i')
+ feed_data('\022\027[106;9u') -- Super + j
+ feed_data('\022\027[107;33u') -- Meta + k
+ feed_data('\022\027[13;41u') -- Super + Meta + Enter
+ feed_data('\022\027[127;48u') -- Shift + Alt + Ctrl + Super + Meta + Backspace
+ feed_data('\n')
+ feed_data('\022\027[57376;9u') -- Super + F13
+ feed_data('\022\027[57377;33u') -- Meta + F14
+ feed_data('\022\027[57378;41u') -- Super + Meta + F15
+ feed_data('\022\027[57379;48u') -- Shift + Alt + Ctrl + Super + Meta + F16
screen:expect([[
- {1:p}opup menu test |
- {4:~ }|
+ <D-j><T-k><T-D-CR><M-T-C-S-D-BS> |
+ <D-F13><T-F14><T-D-F15><M-T-C-S-D-F16>{1: } |
{4:~ }|
{4:~ }|
{5:[No Name] [+] }|
- :let g:menustr = 'bar' |
+ {3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- meths.input_mouse('left', 'release', '', 0, 2, 6)
- screen:expect_unchanged()
end)
it('paste: Insert mode', function()
@@ -753,8 +949,7 @@ describe('TUI', function()
]])
-- Dot-repeat/redo.
feed_data('2.')
- expect_child_buf_lines(
- {'"pasted from terminapasted from terminalpasted from terminall"'})
+ expect_child_buf_lines({'"pasted from terminapasted from terminalpasted from terminall"'})
screen:expect([[
"pasted from terminapasted from terminalpasted fro|
m termina{1:l}l" |
@@ -807,13 +1002,13 @@ describe('TUI', function()
'this is line 2',
'line 3 is here',
'',
- }
+ }
-- Redo.
feed_data('\18') -- <C-r>
expect_child_buf_lines{
'thisjust paste it™3 is here',
'',
- }
+ }
end)
it('paste: terminal mode', function()
@@ -875,17 +1070,15 @@ describe('TUI', function()
screen:expect{grid=expected_grid1, attr_ids=expected_attr}
-- Dot-repeat/redo.
feed_data('.')
- screen:expect{
- grid=[[
- ESC:{11:^[} / CR: |
- xline 1 |
- ESC:{11:^[} / CR: |
- {1:x} |
- {5:[No Name] [+] 5,1 Bot}|
- |
- {3:-- TERMINAL --} |
- ]],
- attr_ids=expected_attr}
+ screen:expect{grid=[[
+ ESC:{11:^[} / CR: |
+ xline 1 |
+ ESC:{11:^[} / CR: |
+ {1:x} |
+ {5:[No Name] [+] 5,1 Bot}|
+ |
+ {3:-- TERMINAL --} |
+ ]], attr_ids=expected_attr}
-- Undo.
feed_data('u')
expect_child_buf_lines(expected_crlf)
@@ -1172,8 +1365,7 @@ describe('TUI', function()
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
- ]],
- attr_ids={
+ ]], attr_ids={
[1] = {reverse = true},
[2] = {background = tonumber('0x00000b')},
[3] = {bold = true},
@@ -1352,7 +1544,7 @@ describe('TUI', function()
it('forwards :term palette colors with termguicolors', function()
if is_ci('github') then
- pending("tty-test complains about not owning the terminal -- actions/runner#241")
+ pending("tty-test complains about not owning the terminal -- actions/runner#241")
end
screen:set_rgb_cterm(true)
screen:set_default_attr_ids({
@@ -1398,24 +1590,41 @@ describe('TUI', function()
]]}
end)
- it('is included in nvim_list_uis()', function()
- feed_data(':echo map(nvim_list_uis(), {k,v -> sort(items(filter(v, {k,v -> k[:3] !=# "ext_" })))})\r')
- screen:expect([=[
- |
- {4:~ }|
- {5: }|
- [[['chan', 1], ['height', 6], ['override', v:false|
- ], ['rgb', v:false], ['width', 50]]] |
- {10:Press ENTER or type command to continue}{1: } |
- {3:-- TERMINAL --} |
- ]=])
+ it('in nvim_list_uis()', function()
+ -- $TERM in :terminal.
+ local exp_term = is_os('bsd') and 'builtin_xterm' or 'xterm-256color'
+ local expected = {
+ {
+ chan = 1,
+ ext_cmdline = false,
+ ext_hlstate = false,
+ ext_linegrid = true,
+ ext_messages = false,
+ ext_multigrid = false,
+ ext_popupmenu = false,
+ ext_tabline = false,
+ ext_termcolors = true,
+ ext_wildmenu = false,
+ height = 6,
+ override = false,
+ rgb = false,
+ stdin_tty = true,
+ stdout_tty = true,
+ term_background = '',
+ term_colors = 256,
+ term_name = exp_term,
+ width = 50
+ },
+ }
+ local _, rv = child_session:request('nvim_list_uis')
+ eq(expected, rv)
end)
it('allows grid to assume wider ambiguous-width characters than host terminal #19686', function()
child_session:request('nvim_buf_set_lines', 0, 0, -1, true, { ('℃'):rep(60), ('℃'):rep(60) })
- child_session:request('nvim_win_set_option', 0, 'cursorline', true)
- child_session:request('nvim_win_set_option', 0, 'list', true)
- child_session:request('nvim_win_set_option', 0, 'listchars', 'eol:$')
+ 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:℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃}|
@@ -1426,21 +1635,21 @@ describe('TUI', function()
|
{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.
+ -- 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:@@@}|
+ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ {4:@@@@}|
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]]
screen:expect(singlewidth_screen)
- child_session:request('nvim_set_option', 'ambiwidth', 'double')
+ child_session:request('nvim_set_option_value', 'ambiwidth', 'double', {})
screen:expect(doublewidth_screen)
- child_session:request('nvim_set_option', 'ambiwidth', 'single')
+ child_session:request('nvim_set_option_value', 'ambiwidth', 'single', {})
screen:expect(singlewidth_screen)
child_session:request('nvim_call_function', 'setcellwidths', {{{0x2103, 0x2103, 2}}})
screen:expect(doublewidth_screen)
@@ -1449,22 +1658,19 @@ describe('TUI', function()
end)
it('draws correctly when cursor_address overflows #21643', function()
- helpers.skip(helpers.is_os('mac'), 'FIXME: crashes/errors on macOS')
- screen:try_resize(77, 834)
+ helpers.skip(is_os('mac'), 'FIXME: crashes/errors on macOS')
+ screen:try_resize(77, 855)
retry(nil, nil, function()
- eq({true, 831}, {child_session:request('nvim_win_get_height', 0)})
+ eq({true, 852}, {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'})
-- Going to top-left corner needs 3 bytes.
-- Setting underline attribute needs 9 bytes.
- -- With screen width 77, 63857 characters need 829 full screen lines.
- -- Drawing each full screen line needs 77 + 2 = 79 bytes (2 bytes for CR LF).
- -- The incomplete screen line needs 24 + 3 = 27 bytes.
- -- The whole line needs 3 + 9 + 79 * 829 + 27 = 65530 bytes.
+ -- The whole line needs 3 + 9 + 65515 + 3 = 65530 bytes.
-- The cursor_address that comes after will overflow the 65535-byte buffer.
- local line = ('a'):rep(63857) .. '℃'
+ local line = ('a'):rep(65515) .. '℃'
child_session:notify('nvim_exec_lua', [[
vim.api.nvim_buf_set_lines(0, 0, -1, true, {...})
vim.o.cursorline = true
@@ -1473,8 +1679,8 @@ describe('TUI', function()
feed_data('\n')
screen:expect(
'{13:a}{12:' .. ('a'):rep(76) .. '}|\n'
- .. ('{12:' .. ('a'):rep(77) .. '}|\n'):rep(828)
- .. '{12:' .. ('a'):rep(24) .. '℃' .. (' '):rep(52) .. '}|\n' .. dedent([[
+ .. ('{12:' .. ('a'):rep(77) .. '}|\n'):rep(849)
+ .. '{12:' .. ('a'):rep(65) .. '℃' .. (' '):rep(11) .. '}|\n' .. dedent([[
b |
{5:[No Name] [+] }|
|
@@ -1509,16 +1715,105 @@ describe('TUI', function()
end)
it('no assert failure on deadly signal #21896', function()
- exec_lua([[vim.loop.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
- screen:expect({any = '%[Process exited 1%]'})
+ exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
+ screen:expect{grid=[[
+ Vim: Caught deadly signal 'SIGTERM' |
+ |
+ |
+ [Process exited 1]{1: } |
+ |
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+ end)
+
+ it('no stack-use-after-scope with cursor color #22432', function()
+ screen:set_option('rgb', true)
+ command('set termguicolors')
+ child_session:request('nvim_exec2', [[
+ set tgc
+ hi Cursor guifg=Red guibg=Green
+ set guicursor=n:block-Cursor/lCursor
+ ]], {})
+ screen:set_default_attr_ids({
+ [1] = {reverse = true},
+ [2] = {bold = true, foreground = Screen.colors.Blue},
+ [3] = {foreground = Screen.colors.Blue},
+ [4] = {reverse = true, bold = true},
+ [5] = {bold = true},
+ })
+ screen:expect([[
+ {1: } |
+ {2:~}{3: }|
+ {2:~}{3: }|
+ {2:~}{3: }|
+ {4:[No Name] }|
+ |
+ {5:-- TERMINAL --} |
+ ]])
+ feed_data('i')
+ screen:expect([[
+ {1: } |
+ {2:~}{3: }|
+ {2:~}{3: }|
+ {2:~}{3: }|
+ {4:[No Name] }|
+ {5:-- INSERT --} |
+ {5:-- TERMINAL --} |
+ ]])
+ end)
+
+ it('redraws on SIGWINCH even if terminal size is unchanged #23411', function()
+ child_session:request('nvim_echo', {{'foo'}}, false, {})
+ screen:expect([[
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] }|
+ foo |
+ {3:-- TERMINAL --} |
+ ]])
+ exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigwinch')]])
+ screen:expect([[
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+
+ it('supports hiding cursor', function()
+ child_session:request('nvim_command',
+ "let g:id = jobstart([v:progpath, '--clean', '--headless'])")
+ feed_data(':call jobwait([g:id])\n')
+ screen:expect([[
+ |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] }|
+ :call jobwait([g:id]) |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\003')
+ screen:expect([[
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] }|
+ Type :qa and press <Enter> to exit Nvim |
+ {3:-- TERMINAL --} |
+ ]])
end)
end)
describe('TUI', function()
before_each(clear)
- after_each(function()
- os.remove('testF')
- end)
it('resize at startup #17285 #15044 #11330', function()
local screen = Screen.new(50, 10)
@@ -1544,12 +1839,51 @@ describe('TUI', function()
{2:~ }│{4:~ }|
{2:~ }│{5:[No Name] 0,0-1 All}|
{2:~ }│ |
- {5:new }{MATCH:<.*[/\]nvim }|
+ {5:new }{1:{MATCH:<.*[/\]nvim }}|
|
]])
end)
+ it('argv[0] can be overridden #23953', function()
+ if not exec_lua('return pcall(require, "ffi")') then
+ pending('missing LuaJIT FFI')
+ end
+ local script_file = 'Xargv0.lua'
+ write_file(script_file, [=[
+ local ffi = require('ffi')
+ ffi.cdef([[int execl(const char *, const char *, ...);]])
+ ffi.C.execl(vim.v.progpath, 'Xargv0nvim', '--clean')
+ ]=])
+ finally(function()
+ os.remove(script_file)
+ end)
+ local screen = thelpers.screen_setup(0, string.format([=[["%s", "--clean", "-l", "%s"]]=],
+ nvim_prog, script_file))
+ screen:expect{grid=[[
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+ feed_data(':put =v:argv + [v:progname]\n')
+ screen:expect{grid=[[
+ Xargv0nvim |
+ --embed |
+ --clean |
+ {1:X}argv0nvim |
+ {5:[No Name] [+] 5,1 Bot}|
+ 4 more lines |
+ {3:-- TERMINAL --} |
+ ]]}
+ end)
+
it('with non-tty (pipe) stdout/stderr', function()
+ finally(function()
+ os.remove('testF')
+ end)
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')
@@ -1588,6 +1922,30 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
end)
+
+ it('draws line with many trailing spaces correctly #24955', function()
+ local screen = thelpers.screen_setup(0, '["'..nvim_prog..[[", "-u", "NONE", "-i", "NONE"]]
+ ..[[, "--cmd", "call setline(1, ['1st line' .. repeat(' ', 153), '2nd line'])"]]..']', 80)
+ screen:expect{grid=[[
+ {1:1}st line |
+ |
+ |
+ 2nd line |
+ {5:[No Name] [+] 1,1 All}|
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+ feed_data('$')
+ screen:expect{grid=[[
+ 1st line |
+ |
+ {1: } |
+ 2nd line |
+ {5:[No Name] [+] 1,161 All}|
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+ end)
end)
describe('TUI UIEnter/UILeave', function()
@@ -1626,12 +1984,16 @@ end)
describe('TUI FocusGained/FocusLost', function()
local screen
+ local child_session
before_each(function()
clear()
- screen = thelpers.screen_setup(0, '["'..nvim_prog
- ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]')
- screen:expect{grid=[[
+ local child_server = new_pipename()
+ screen = thelpers.screen_setup(0,
+ string.format(
+ [=[["%s", "--listen", "%s", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]]=],
+ nvim_prog, child_server))
+ screen:expect([[
{1: } |
{4:~ }|
{4:~ }|
@@ -1639,22 +2001,16 @@ describe('TUI FocusGained/FocusLost', function()
{5:[No Name] }|
|
{3:-- TERMINAL --} |
- ]]}
- feed_data(":autocmd FocusGained * echo 'gained'\n")
- feed_data(":autocmd FocusLost * echo 'lost'\n")
+ ]])
+ child_session = helpers.connect(child_server)
+ child_session:request('nvim_exec2', [[
+ autocmd FocusGained * echo 'gained'
+ autocmd FocusLost * echo 'lost'
+ ]], {})
feed_data("\034\016") -- CTRL-\ CTRL-N
end)
it('in normal-mode', function()
- screen:expect{grid=[[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] }|
- :autocmd FocusLost * echo 'lost' |
- {3:-- TERMINAL --} |
- ]]}
retry(2, 3 * screen.timeout, function()
feed_data('\027[I')
screen:expect([[
@@ -1681,7 +2037,7 @@ describe('TUI FocusGained/FocusLost', function()
end)
it('in insert-mode', function()
- feed_command('set noshowmode')
+ feed_data(':set noshowmode\r')
feed_data('i')
screen:expect{grid=[[
{1: } |
@@ -1746,18 +2102,11 @@ describe('TUI FocusGained/FocusLost', function()
-- Set up autocmds that modify the buffer, instead of just calling :echo.
-- This is how we can test handling of focus gained/lost during cmdline-mode.
-- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419.
- feed_data(":autocmd!\n")
- feed_data(":autocmd FocusLost * call append(line('$'), 'lost')\n")
- feed_data(":autocmd FocusGained * call append(line('$'), 'gained')\n")
- screen:expect{grid=[[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]]}
+ child_session:request('nvim_exec2', [[
+ autocmd!
+ autocmd FocusLost * call append(line('$'), 'lost')
+ autocmd FocusGained * call append(line('$'), 'gained')
+ ]], {})
retry(2, 3 * screen.timeout, function()
-- Enter cmdline-mode.
feed_data(':')
@@ -1774,26 +2123,26 @@ describe('TUI FocusGained/FocusLost', function()
end)
it('in terminal-mode', function()
- feed_data(':set shell='..testprg('shell-test')..'\n')
+ feed_data(':set shell='..testprg('shell-test')..' shellcmdflag=EXE\n')
feed_data(':set noshowmode laststatus=0\n')
- feed_data(':terminal\n')
+ feed_data(':terminal zia\n')
-- Wait for terminal to be ready.
screen:expect{grid=[[
- {1:r}eady $ |
- [Process exited 0] |
+ {1:r}eady $ zia |
|
+ [Process exited 0] |
|
|
- :terminal |
+ :terminal zia |
{3:-- TERMINAL --} |
]]}
feed_data('\027[I')
screen:expect{grid=[[
- {1:r}eady $ |
- [Process exited 0] |
+ {1:r}eady $ zia |
|
+ [Process exited 0] |
|
|
gained |
@@ -1802,9 +2151,9 @@ describe('TUI FocusGained/FocusLost', function()
feed_data('\027[O')
screen:expect([[
- {1:r}eady $ |
- [Process exited 0] |
+ {1:r}eady $ zia |
|
+ [Process exited 0] |
|
|
lost |
@@ -1845,7 +2194,7 @@ describe("TUI 't_Co' (terminal colors)", function()
local screen
local function assert_term_colors(term, colorterm, maxcolors)
- helpers.clear({env={TERM=term}, args={}})
+ clear({env={TERM=term}, args={}})
-- This is ugly because :term/termopen() forces TERM=xterm-256color.
-- TODO: Revisit this after jobstart/termopen accept `env` dict.
screen = thelpers.screen_setup(0, string.format(
@@ -2210,45 +2559,44 @@ describe("TUI", function()
end)
+-- See test/unit/tui_spec.lua for unit tests.
describe('TUI bg color', function()
local screen
- local function setup()
- -- Only single integration test.
- -- See test/unit/tui_spec.lua for unit tests.
+ local function setup_bg_test()
clear()
screen = thelpers.screen_setup(0, '["'..nvim_prog
..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile", '
..'"-c", "autocmd OptionSet background echo \\"did OptionSet, yay!\\""]')
end
- before_each(setup)
+ before_each(setup_bg_test)
it('triggers OptionSet event on unsplit terminal-response', function()
screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
]])
- feed_data('\027]11;rgb:ffff/ffff/ffff\007')
+ feed_data('\027]11;rgb:ffff/ffff/ffff\027\\')
screen:expect{any='did OptionSet, yay!'}
feed_data(':echo "new_bg=".&background\n')
screen:expect{any='new_bg=light'}
- setup()
+ setup_bg_test()
screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
]])
feed_data('\027]11;rgba:ffff/ffff/ffff/8000\027\\')
screen:expect{any='did OptionSet, yay!'}
@@ -2259,13 +2607,13 @@ describe('TUI bg color', function()
it('triggers OptionSet event with split terminal-response', function()
screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
]])
-- Send a background response with the OSC command part split.
feed_data('\027]11;rgb')
@@ -2275,19 +2623,19 @@ describe('TUI bg color', function()
feed_data(':echo "new_bg=".&background\n')
screen:expect{any='new_bg=light'}
- setup()
+ setup_bg_test()
screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
]])
-- Send a background response with the Pt portion split.
feed_data('\027]11;rgba:ffff/fff')
- feed_data('f/ffff/8000\007')
+ feed_data('f/ffff/8000\027\\')
screen:expect{any='did OptionSet, yay!'}
feed_data(':echo "new_bg=".&background\n')
@@ -2296,13 +2644,13 @@ describe('TUI bg color', function()
it('not triggers OptionSet event with invalid terminal-response', function()
screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
]])
feed_data('\027]11;rgb:ffff/ffff/ffff/8000\027\\')
screen:expect_unchanged()
@@ -2310,17 +2658,17 @@ describe('TUI bg color', function()
feed_data(':echo "new_bg=".&background\n')
screen:expect{any='new_bg=dark'}
- setup()
+ setup_bg_test()
screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
]])
- feed_data('\027]11;rgba:ffff/foo/ffff/8000\007')
+ feed_data('\027]11;rgba:ffff/foo/ffff/8000\027\\')
screen:expect_unchanged()
feed_data(':echo "new_bg=".&background\n')
@@ -2365,18 +2713,31 @@ describe("TUI as a client", function()
set_session(client_super)
local screen_client = thelpers.screen_setup(0,
- string.format([=[["%s", "-u", "NONE", "-i", "NONE", "--server", "%s", "--remote-ui"]]=],
+ string.format([=[["%s", "--server", "%s", "--remote-ui"]]=],
nvim_prog, server_pipe))
- screen_client:expect{grid=[[
- Hello, Worl{1:d} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]]}
+ screen_client:expect{grid=[[
+ Hello, Worl{1:d} |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+
+ -- grid smaller than containing terminal window is cleared properly
+ feed_data(":call setline(1,['a'->repeat(&columns)]->repeat(&lines))\n")
+ feed_data("0:set lines=3\n")
+ screen_server:expect{grid=[[
+ {1:a}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {5:[No Name] [+] }|
+ |
+ |
+ |
+ |
+ {3:-- TERMINAL --} |
+ ]]}
feed_data(":q!\n")
@@ -2385,19 +2746,19 @@ describe("TUI as a client", function()
end)
it("connects to remote instance (--headless)", function()
- local server = helpers.spawn_argv(false) -- equivalent to clear()
+ local server = spawn_argv(false) -- equivalent to clear()
local client_super = spawn_argv(true)
set_session(server)
- local server_pipe = eval'v:servername'
- feed'iHalloj!<esc>'
+ local server_pipe = meths.get_vvar('servername')
+ server:request('nvim_input', 'iHalloj!<Esc>')
set_session(client_super)
- local screen = thelpers.screen_setup(0,
- string.format([=[["%s", "-u", "NONE", "-i", "NONE", "--server", "%s", "--remote-ui"]]=],
+ local screen_client = thelpers.screen_setup(0,
+ string.format([=[["%s", "--server", "%s", "--remote-ui"]]=],
nvim_prog, server_pipe))
- screen:expect{grid=[[
+ screen_client:expect{grid=[[
Halloj{1:!} |
{4:~ }|
{4:~ }|
@@ -2407,15 +2768,32 @@ describe("TUI as a client", function()
{3:-- TERMINAL --} |
]]}
+ -- No heap-use-after-free when receiving UI events after deadly signal #22184
+ server:request('nvim_input', ('a'):rep(1000))
+ exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
+ screen_client:expect{grid=[[
+ Vim: Caught deadly signal 'SIGTERM' |
+ |
+ |
+ [Process exited 1]{1: } |
+ |
+ |
+ {3:-- TERMINAL --} |
+ ]]}
+
+ eq(0, meths.get_vvar('shell_error'))
+ -- exits on input eof #22244
+ funcs.system({nvim_prog, '--server', server_pipe, '--remote-ui'})
+ eq(1, meths.get_vvar('shell_error'))
+
client_super:close()
server:close()
end)
-
it("throws error when no server exists", function()
clear()
local screen = thelpers.screen_setup(0,
- string.format([=[["%s", "-u", "NONE", "-i", "NONE", "--server", "127.0.0.1:2436546", "--remote-ui"]]=],
+ string.format([=[["%s", "--server", "127.0.0.1:2436546", "--remote-ui"]]=],
nvim_prog), 60)
screen:expect([[
@@ -2429,7 +2807,7 @@ describe("TUI as a client", function()
]])
end)
- it("exits when server quits", function()
+ local function test_remote_tui_quit(status)
local server_super = spawn_argv(false) -- equivalent to clear()
local client_super = spawn_argv(true)
@@ -2438,6 +2816,15 @@ describe("TUI as a client", function()
local screen_server = thelpers.screen_setup(0,
string.format([=[["%s", "--listen", "%s", "-u", "NONE", "-i", "NONE", "--cmd", "%s laststatus=2 background=dark"]]=],
nvim_prog, server_pipe, nvim_set))
+ screen_server:expect{grid=[[
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] }|
+ |
+ {3:-- TERMINAL --} |
+ ]]}
feed_data("iHello, World")
screen_server:expect{grid=[[
@@ -2462,7 +2849,7 @@ describe("TUI as a client", function()
set_session(client_super)
local screen_client = thelpers.screen_setup(0,
- string.format([=[["%s", "-u", "NONE", "-i", "NONE", "--server", "%s", "--remote-ui"]]=],
+ string.format([=[["%s", "--server", "%s", "--remote-ui"]]=],
nvim_prog, server_pipe))
screen_client:expect{grid=[[
@@ -2477,13 +2864,39 @@ describe("TUI as a client", function()
-- quitting the server
set_session(server_super)
- feed_data(":q!\n")
- screen_server:expect({any="Process exited 0"})
-
+ feed_data(status and ':' .. status .. 'cquit!\n' or ":quit!\n")
+ status = status and status or 0
+ screen_server:expect{grid=[[
+ |
+ [Process exited ]] .. status .. [[]{1: }{MATCH:%s+}|
+ |
+ |
+ |
+ |
+ {3:-- TERMINAL --} |
+ ]]}
-- assert that client has exited
- screen_client:expect({any="Process exited 0"})
+ screen_client:expect{grid=[[
+ |
+ [Process exited ]] .. status .. [[]{1: }{MATCH:%s+}|
+ |
+ |
+ |
+ |
+ {3:-- TERMINAL --} |
+ ]]}
server_super:close()
client_super:close()
+ end
+
+ describe("exits when server quits", function()
+ it("with :quit", function()
+ test_remote_tui_quit()
+ end)
+
+ it("with :cquit", function()
+ test_remote_tui_quit(42)
+ end)
end)
end)