aboutsummaryrefslogtreecommitdiff
path: root/test/functional/terminal
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
commit931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch)
treed8c1843a95da5ea0bb4acc09f7e37843d9995c86 /test/functional/terminal
parent142d9041391780ac15b89886a54015fdc5c73995 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-userreg.tar.gz
rneovim-userreg.tar.bz2
rneovim-userreg.zip
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'test/functional/terminal')
-rw-r--r--test/functional/terminal/api_spec.lua8
-rw-r--r--test/functional/terminal/buffer_spec.lua158
-rw-r--r--test/functional/terminal/channel_spec.lua96
-rw-r--r--test/functional/terminal/cursor_spec.lua71
-rw-r--r--test/functional/terminal/edit_spec.lua7
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua59
-rw-r--r--test/functional/terminal/helpers.lua9
-rw-r--r--test/functional/terminal/mouse_spec.lua78
-rw-r--r--test/functional/terminal/scrollback_spec.lua75
-rw-r--r--test/functional/terminal/tui_spec.lua923
-rw-r--r--test/functional/terminal/window_spec.lua45
-rw-r--r--test/functional/terminal/window_split_tab_spec.lua4
12 files changed, 1130 insertions, 403 deletions
diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua
index 724791343d..93641fc576 100644
--- a/test/functional/terminal/api_spec.lua
+++ b/test/functional/terminal/api_spec.lua
@@ -66,10 +66,10 @@ describe('api', function()
screen:expect([[
[tui] insert-mode |
- [socket 1] this is more t{4: }|
- han 25 columns {4: }|
- [socket 2] input{1: } {4: }|
- {4:~ }|
+ [socket 1] this is more t |
+ han 25 columns |
+ [socket 2] input{1: } |
+ {4:~ } |
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 9c8b983ff7..6fcd029a5b 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -17,14 +17,14 @@ local sleep = helpers.sleep
local funcs = helpers.funcs
local is_os = helpers.is_os
local skip = helpers.skip
+local nvim_prog = helpers.nvim_prog
describe(':terminal buffer', function()
local screen
before_each(function()
clear()
- feed_command('set modifiable swapfile undolevels=20')
- poke_eventloop()
+ command('set modifiable swapfile undolevels=20')
screen = thelpers.screen_setup()
end)
@@ -197,12 +197,11 @@ describe(':terminal buffer', function()
it('handles loss of focus gracefully', function()
-- Change the statusline to avoid printing the file name, which varies.
- nvim('set_option', 'statusline', '==========')
- feed_command('set laststatus=0')
+ nvim('set_option_value', 'statusline', '==========', {})
-- Save the buffer number of the terminal for later testing.
local tbuf = eval('bufnr("%")')
- local exitcmd = helpers.is_os('win')
+ local exitcmd = is_os('win')
and "['cmd', '/c', 'exit']"
or "['sh', '-c', 'exit']"
source([[
@@ -231,8 +230,6 @@ describe(':terminal buffer', function()
neq(tbuf, eval('bufnr("%")'))
feed_command('quit!') -- Should exit the new window, not the terminal.
eq(tbuf, eval('bufnr("%")'))
-
- feed_command('set laststatus=1') -- Restore laststatus to the default.
end)
it('term_close() use-after-free #4393', function()
@@ -281,6 +278,7 @@ describe(':terminal buffer', function()
end)
it('requires bang (!) to close a running job #15402', function()
+ skip(is_os('win'), "Test freezes the CI and makes it time out")
eq('Vim(wqall):E948: Job still running', exc_exec('wqall'))
for _, cmd in ipairs({ 'bdelete', '%bdelete', 'bwipeout', 'bunload' }) do
matches('^Vim%('..cmd:gsub('%%', '')..'%):E89: term://.*tty%-test.* will be killed %(add %! to override%)$',
@@ -412,14 +410,6 @@ describe('on_lines does not emit out-of-bounds line indexes when', function()
feed_command('bdelete!')
eq('', exec_lua([[return _G.cb_error]]))
end)
-
- it('runs TextChangedT event', function()
- meths.set_var('called', 0)
- command('autocmd TextChangedT * ++once let g:called = 1')
- feed_command('terminal')
- feed('iaa')
- eq(1, meths.get_var('called'))
- end)
end)
it('terminal truncates number of composing characters to 5', function()
@@ -429,3 +419,141 @@ it('terminal truncates number of composing characters to 5', function()
meths.chan_send(chan, 'a' .. composing:rep(8))
retry(nil, nil, function() eq('a' .. composing:rep(5), meths.get_current_line()) end)
end)
+
+describe('terminal input', function()
+ before_each(function()
+ clear()
+ exec_lua([[
+ _G.input_data = ''
+ vim.api.nvim_open_term(0, { on_input = function(_, _, _, data)
+ _G.input_data = _G.input_data .. data
+ end })
+ ]])
+ feed('i')
+ poke_eventloop()
+ end)
+
+ it('<C-Space> is sent as NUL byte', function()
+ feed('aaa<C-Space>bbb')
+ eq('aaa\0bbb', exec_lua([[return _G.input_data]]))
+ end)
+
+ it('unknown special keys are not sent', function()
+ feed('aaa<Help>bbb')
+ eq('aaabbb', exec_lua([[return _G.input_data]]))
+ end)
+end)
+
+describe('terminal input', function()
+ it('sends various special keys with modifiers', function()
+ clear()
+ local screen = thelpers.screen_setup(0,
+ string.format([=[["%s", "-u", "NONE", "-i", "NONE", "--cmd", "startinsert"]]=], nvim_prog))
+ screen:expect{grid=[[
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] 0,1 All}|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]]}
+ for _, key in ipairs({
+ '<M-Tab>', '<M-CR>', '<M-Esc>',
+ '<BS>', '<S-Tab>', '<Insert>', '<Del>', '<PageUp>', '<PageDown>',
+ '<S-Up>', '<C-Up>', '<Up>', '<S-Down>', '<C-Down>', '<Down>',
+ '<S-Left>', '<C-Left>', '<Left>', '<S-Right>', '<C-Right>', '<Right>',
+ '<S-Home>', '<C-Home>', '<Home>', '<S-End>', '<C-End>', '<End>',
+ '<C-LeftMouse>', '<C-LeftRelease>', '<2-LeftMouse>', '<2-LeftRelease>',
+ '<S-RightMouse>', '<S-RightRelease>', '<2-RightMouse>', '<2-RightRelease>',
+ '<M-MiddleMouse>', '<M-MiddleRelease>', '<2-MiddleMouse>', '<2-MiddleRelease>',
+ '<S-ScrollWheelUp>', '<S-ScrollWheelDown>', '<ScrollWheelUp>', '<ScrollWheelDown>',
+ '<S-ScrollWheelLeft>', '<S-ScrollWheelRight>', '<ScrollWheelLeft>', '<ScrollWheelRight>',
+ }) do
+ feed('<CR><C-V>' .. key)
+ retry(nil, nil, function() eq(key, meths.get_current_line()) end)
+ end
+ end)
+end)
+
+if is_os('win') then
+ describe(':terminal in Windows', function()
+ local screen
+
+ before_each(function()
+ clear()
+ feed_command('set modifiable swapfile undolevels=20')
+ poke_eventloop()
+ local cmd = '["cmd.exe","/K","PROMPT=$g$s"]'
+ screen = thelpers.screen_setup(nil, cmd)
+ end)
+
+ it('"put" operator sends data normally', function()
+ feed('<c-\\><c-n>G')
+ feed_command('let @a = ":: tty ready"')
+ feed_command('let @a = @a . "\\n:: appended " . @a . "\\n\\n"')
+ feed('"ap"ap')
+ screen:expect([[
+ |
+ > :: tty ready |
+ > :: appended :: tty ready |
+ > :: tty ready |
+ > :: appended :: tty ready |
+ ^> {2: } |
+ :let @a = @a . "\n:: appended " . @a . "\n\n" |
+ ]])
+ -- operator count is also taken into consideration
+ feed('3"ap')
+ screen:expect([[
+ > :: appended :: tty ready |
+ > :: tty ready |
+ > :: appended :: tty ready |
+ > :: tty ready |
+ > :: appended :: tty ready |
+ ^> {2: } |
+ :let @a = @a . "\n:: appended " . @a . "\n\n" |
+ ]])
+ end)
+
+ it('":put" command sends data normally', function()
+ feed('<c-\\><c-n>G')
+ feed_command('let @a = ":: tty ready"')
+ feed_command('let @a = @a . "\\n:: appended " . @a . "\\n\\n"')
+ feed_command('put a')
+ screen:expect([[
+ |
+ > :: tty ready |
+ > :: appended :: tty ready |
+ > {2: } |
+ |
+ ^ |
+ :put a |
+ ]])
+ -- line argument is only used to move the cursor
+ feed_command('6put a')
+ screen:expect([[
+ |
+ > :: tty ready |
+ > :: appended :: tty ready |
+ > :: tty ready |
+ > :: appended :: tty ready |
+ ^> {2: } |
+ :6put a |
+ ]])
+ end)
+ end)
+end
+
+describe('termopen()', function()
+ before_each(clear)
+
+ it('disallowed when textlocked and in cmdwin buffer', function()
+ command("autocmd TextYankPost <buffer> ++once call termopen('foo')")
+ matches("Vim%(call%):E565: Not allowed to change text or change window$",
+ pcall_err(command, "normal! yy"))
+
+ feed("q:")
+ eq("Vim:E11: Invalid in command-line window; <CR> executes, CTRL-C quits",
+ pcall_err(funcs.termopen, "bar"))
+ end)
+end)
diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua
index 2ca7cdb0a2..8510df5347 100644
--- a/test/functional/terminal/channel_spec.lua
+++ b/test/functional/terminal/channel_spec.lua
@@ -8,6 +8,10 @@ local pcall_err = helpers.pcall_err
local feed = helpers.feed
local poke_eventloop = helpers.poke_eventloop
local is_os = helpers.is_os
+local meths = helpers.meths
+local async_meths = helpers.async_meths
+local testprg = helpers.testprg
+local assert_alive = helpers.assert_alive
describe('terminal channel is closed and later released if', function()
local screen
@@ -24,6 +28,7 @@ describe('terminal channel is closed and later released if', function()
-- channel hasn't been released yet
eq("Vim(call):Can't send data to closed stream",
pcall_err(command, [[bdelete! | call chansend(id, 'test')]]))
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after one main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -40,6 +45,7 @@ describe('terminal channel is closed and later released if', function()
feed('i<CR>')
-- need to first process input
poke_eventloop()
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after another main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -55,6 +61,7 @@ describe('terminal channel is closed and later released if', function()
-- 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')]]))
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after one main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -72,6 +79,7 @@ describe('terminal channel is closed and later released if', function()
feed('i<CR>')
-- need to first process input
poke_eventloop()
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after another main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -89,21 +97,105 @@ describe('terminal channel is closed and later released if', function()
-- 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')]]))
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after one main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
end)
it('chansend sends lines to terminal channel in proper order', function()
- clear()
+ clear({args = {'--cmd', 'set laststatus=2'}})
local screen = Screen.new(100, 20)
screen:attach()
local shells = is_os('win') and {'cmd.exe', 'pwsh.exe -nop', 'powershell.exe -nop'} or {'sh'}
for _, sh in ipairs(shells) do
- command([[bdelete! | let id = termopen(']] .. sh .. [[')]])
+ command([[let id = termopen(']] .. sh .. [[')]])
command([[call chansend(id, ['echo "hello"', 'echo "world"', ''])]])
screen:expect{
any=[[echo "hello".*echo "world"]]
}
+ command('bdelete!')
+ screen:expect{
+ any='%[No Name%]'
+ }
end
end)
+
+describe('no crash when TermOpen autocommand', function()
+ local screen
+
+ before_each(function()
+ clear()
+ meths.set_option_value('shell', testprg('shell-test'), {})
+ command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=')
+ screen = Screen.new(60, 4)
+ screen:set_default_attr_ids({
+ [0] = {bold = true, foreground = Screen.colors.Blue};
+ })
+ screen:attach()
+ end)
+
+ it('processes job exit event when using termopen()', function()
+ command([[autocmd TermOpen * call input('')]])
+ async_meths.command('terminal foobar')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ ^ |
+ ]]}
+ feed('<CR>')
+ screen:expect{grid=[[
+ ^ready $ foobar |
+ |
+ [Process exited 0] |
+ |
+ ]]}
+ feed('i<CR>')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ assert_alive()
+ end)
+
+ it('wipes buffer and processes events when using termopen()', function()
+ command([[autocmd TermOpen * bwipe! | call input('')]])
+ async_meths.command('terminal foobar')
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ ^ |
+ ]]}
+ feed('<CR>')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ assert_alive()
+ end)
+
+ it('wipes buffer and processes events when using nvim_open_term()', function()
+ command([[autocmd TermOpen * bwipe! | call input('')]])
+ async_meths.open_term(0, {})
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ ^ |
+ ]]}
+ feed('<CR>')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ assert_alive()
+ end)
+end)
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index 98ac03211a..8285bcc26e 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -6,7 +6,7 @@ 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 poke_eventloop = helpers.poke_eventloop
local hide_cursor = thelpers.hide_cursor
local show_cursor = thelpers.show_cursor
local is_os = helpers.is_os
@@ -153,7 +153,8 @@ describe('cursor with customized highlighting', function()
})
screen:attach({rgb=false})
command('call termopen(["'..testprg('tty-test')..'"])')
- feed_command('startinsert')
+ feed('i')
+ poke_eventloop()
end)
it('overrides the default highlighting', function()
@@ -187,13 +188,16 @@ describe('buffer cursor position is correct in terminal without number column',
..[[", "-u", "NONE", "-i", "NONE", "-E", "--cmd", "let @r = ']]..str..[['", ]]
-- <Left> and <Right> don't always work
..[["--cmd", "cnoremap <C-X> <Left>", "--cmd", "cnoremap <C-O> <Right>"]]..']', 70)
+ -- Also check for real cursor position, as it is used for stuff like input methods
+ screen._handle_busy_start = function() end
+ screen._handle_busy_stop = function() end
screen:expect([[
|
|
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :{1: } |
+ :{1:^ } |
{3:-- TERMINAL --} |
]])
end
@@ -213,7 +217,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaaaa{1: } |
+ :aaaaaaaa{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 9}, eval('nvim_win_get_cursor(0)'))
@@ -238,7 +242,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaa{1:a}a |
+ :aaaaaa{1:^a}a |
{3:-- TERMINAL --} |
]])
eq({6, 7}, eval('nvim_win_get_cursor(0)'))
@@ -263,7 +267,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :a{1:a}aaaaaa |
+ :a{1:^a}aaaaaa |
{3:-- TERMINAL --} |
]])
eq({6, 2}, eval('nvim_win_get_cursor(0)'))
@@ -294,7 +298,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µµµµµµµµ{1: } |
+ :µµµµµµµµ{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 17}, eval('nvim_win_get_cursor(0)'))
@@ -319,7 +323,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µµµµµµ{1:µ}µ |
+ :µµµµµµ{1:^µ}µ |
{3:-- TERMINAL --} |
]])
eq({6, 13}, eval('nvim_win_get_cursor(0)'))
@@ -344,7 +348,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ{1:µ}µµµµµµ |
+ :µ{1:^µ}µµµµµµ |
{3:-- TERMINAL --} |
]])
eq({6, 3}, eval('nvim_win_get_cursor(0)'))
@@ -377,7 +381,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1: } |
+ :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 33}, eval('nvim_win_get_cursor(0)'))
@@ -402,7 +406,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳µ̳µ̳µ̳µ̳µ̳{1:µ̳}µ̳ |
+ :µ̳µ̳µ̳µ̳µ̳µ̳{1:^µ̳}µ̳ |
{3:-- TERMINAL --} |
]])
eq({6, 25}, eval('nvim_win_get_cursor(0)'))
@@ -427,7 +431,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳{1:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
+ :µ̳{1:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
{3:-- TERMINAL --} |
]])
eq({6, 5}, eval('nvim_win_get_cursor(0)'))
@@ -446,7 +450,7 @@ describe('buffer cursor position is correct in terminal without number column',
end)
describe('in a line with double-cell multibyte characters and no trailing spaces,', function()
- skip(is_os('win'), "Encoding problem?")
+ if skip(is_os('win'), "Encoding problem?") then return end
before_each(function()
setup_ex_register('哦哦哦哦哦哦哦哦')
@@ -460,7 +464,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦哦哦哦哦哦哦哦{1: } |
+ :哦哦哦哦哦哦哦哦{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 25}, eval('nvim_win_get_cursor(0)'))
@@ -485,7 +489,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦哦哦哦哦哦{1:哦}哦 |
+ :哦哦哦哦哦哦{1:^哦}哦 |
{3:-- TERMINAL --} |
]])
eq({6, 19}, eval('nvim_win_get_cursor(0)'))
@@ -510,7 +514,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦{1:哦}哦哦哦哦哦哦 |
+ :哦{1:^哦}哦哦哦哦哦哦 |
{3:-- TERMINAL --} |
]])
eq({6, 4}, eval('nvim_win_get_cursor(0)'))
@@ -537,7 +541,7 @@ describe('buffer cursor position is correct in terminal without number column',
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaaaa {1: } |
+ :aaaaaaaa {1:^ } |
{3:-- TERMINAL --} |
]])
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
@@ -564,13 +568,16 @@ describe('buffer cursor position is correct in terminal with number column', fun
..[[", "-u", "NONE", "-i", "NONE", "-E", "--cmd", "let @r = ']]..str..[['", ]]
-- <Left> and <Right> don't always work
..[["--cmd", "cnoremap <C-X> <Left>", "--cmd", "cnoremap <C-O> <Right>"]]..']', 70)
+ -- Also check for real cursor position, as it is used for stuff like input methods
+ screen._handle_busy_start = function() end
+ screen._handle_busy_stop = function() end
screen:expect([[
{7: 1 } |
{7: 2 } |
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:{1: } |
+ {7: 6 }:{1:^ } |
{3:-- TERMINAL --} |
]])
end
@@ -593,7 +600,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaaaa{1: } |
+ {7: 6 }:aaaaaaaa{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 9}, eval('nvim_win_get_cursor(0)'))
@@ -618,7 +625,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaa{1:a}a |
+ {7: 6 }:aaaaaa{1:^a}a |
{3:-- TERMINAL --} |
]])
eq({6, 7}, eval('nvim_win_get_cursor(0)'))
@@ -643,7 +650,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:a{1:a}aaaaaa |
+ {7: 6 }:a{1:^a}aaaaaa |
{3:-- TERMINAL --} |
]])
eq({6, 2}, eval('nvim_win_get_cursor(0)'))
@@ -674,7 +681,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µµµµµµµµ{1: } |
+ {7: 6 }:µµµµµµµµ{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 17}, eval('nvim_win_get_cursor(0)'))
@@ -699,7 +706,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µµµµµµ{1:µ}µ |
+ {7: 6 }:µµµµµµ{1:^µ}µ |
{3:-- TERMINAL --} |
]])
eq({6, 13}, eval('nvim_win_get_cursor(0)'))
@@ -724,7 +731,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ{1:µ}µµµµµµ |
+ {7: 6 }:µ{1:^µ}µµµµµµ |
{3:-- TERMINAL --} |
]])
eq({6, 3}, eval('nvim_win_get_cursor(0)'))
@@ -757,7 +764,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1: } |
+ {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 33}, eval('nvim_win_get_cursor(0)'))
@@ -782,7 +789,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{1:µ̳}µ̳ |
+ {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{1:^µ̳}µ̳ |
{3:-- TERMINAL --} |
]])
eq({6, 25}, eval('nvim_win_get_cursor(0)'))
@@ -807,7 +814,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳{1:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
+ {7: 6 }:µ̳{1:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
{3:-- TERMINAL --} |
]])
eq({6, 5}, eval('nvim_win_get_cursor(0)'))
@@ -826,7 +833,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
end)
describe('in a line with double-cell multibyte characters and no trailing spaces,', function()
- skip(is_os('win'), "Encoding problem?")
+ if skip(is_os('win'), "Encoding problem?") then return end
before_each(function()
setup_ex_register('哦哦哦哦哦哦哦哦')
@@ -840,7 +847,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦哦哦哦哦哦哦哦{1: } |
+ {7: 6 }:哦哦哦哦哦哦哦哦{1:^ } |
{3:-- TERMINAL --} |
]])
eq({6, 25}, eval('nvim_win_get_cursor(0)'))
@@ -865,7 +872,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦哦哦哦哦哦{1:哦}哦 |
+ {7: 6 }:哦哦哦哦哦哦{1:^哦}哦 |
{3:-- TERMINAL --} |
]])
eq({6, 19}, eval('nvim_win_get_cursor(0)'))
@@ -890,7 +897,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦{1:哦}哦哦哦哦哦哦 |
+ {7: 6 }:哦{1:^哦}哦哦哦哦哦哦 |
{3:-- TERMINAL --} |
]])
eq({6, 4}, eval('nvim_win_get_cursor(0)'))
@@ -917,7 +924,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaaaa {1: } |
+ {7: 6 }:aaaaaaaa {1:^ } |
{3:-- TERMINAL --} |
]])
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
index 80287bb3d0..29361bc0fa 100644
--- a/test/functional/terminal/edit_spec.lua
+++ b/test/functional/terminal/edit_spec.lua
@@ -21,8 +21,8 @@ describe(':edit term://*', function()
before_each(function()
clear()
- meths.set_option('shell', testprg('shell-test'))
- meths.set_option('shellcmdflag', 'EXE')
+ meths.set_option_value('shell', testprg('shell-test'), {})
+ meths.set_option_value('shellcmdflag', 'EXE', {})
end)
it('runs TermOpen event', function()
@@ -36,11 +36,10 @@ describe(':edit term://*', function()
end)
it("runs TermOpen early enough to set buffer-local 'scrollback'", function()
- if helpers.skip(helpers.is_os('win')) then return end
local columns, lines = 20, 4
local scr = get_screen(columns, lines)
local rep = 97
- meths.set_option('shellcmdflag', 'REP ' .. rep)
+ meths.set_option_value('shellcmdflag', 'REP ' .. rep, {})
command('set shellxquote=') -- win: avoid extra quotes
local sb = 10
command('autocmd TermOpen * :setlocal scrollback='..tostring(sb)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 6b7e93a864..f628e261a2 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -99,7 +99,7 @@ describe(':terminal', function()
end)
it('nvim_get_mode() in :terminal', function()
- command(':terminal')
+ command('terminal')
eq({ blocking=false, mode='nt' }, nvim('get_mode'))
feed('i')
eq({ blocking=false, mode='t' }, nvim('get_mode'))
@@ -108,21 +108,37 @@ describe(':terminal', function()
end)
it(':stopinsert RPC request exits terminal-mode #7807', function()
- command(':terminal')
+ command('terminal')
feed('i[tui] insert-mode')
eq({ blocking=false, mode='t' }, nvim('get_mode'))
command('stopinsert')
+ feed('<Ignore>') -- Add input to separate two RPC requests
eq({ blocking=false, mode='nt' }, nvim('get_mode'))
end)
it(':stopinsert in normal mode doesn\'t break insert mode #9889', function()
- command(':terminal')
+ command('terminal')
eq({ blocking=false, mode='nt' }, nvim('get_mode'))
- command(':stopinsert')
+ command('stopinsert')
+ feed('<Ignore>') -- Add input to separate two RPC requests
eq({ blocking=false, mode='nt' }, nvim('get_mode'))
feed('a')
eq({ blocking=false, mode='t' }, nvim('get_mode'))
end)
+
+ it('switching to terminal buffer in Insert mode goes to Terminal mode #7164', function()
+ command('terminal')
+ command('vnew')
+ feed('i')
+ command('let g:events = []')
+ command('autocmd InsertLeave * let g:events += ["InsertLeave"]')
+ command('autocmd TermEnter * let g:events += ["TermEnter"]')
+ command('inoremap <F2> <Cmd>wincmd p<CR>')
+ eq({ blocking=false, mode='i' }, nvim('get_mode'))
+ feed('<F2>')
+ eq({ blocking=false, mode='t' }, nvim('get_mode'))
+ eq({'InsertLeave', 'TermEnter'}, eval('g:events'))
+ end)
end)
describe(':terminal (with fake shell)', function()
@@ -133,31 +149,37 @@ 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', testprg('shell-test'))
- nvim('set_option', 'shellcmdflag', 'EXE')
+ nvim('set_option_value', 'shell', testprg('shell-test'), {})
+ nvim('set_option_value', 'shellcmdflag', 'EXE', {})
+ nvim('set_option_value', 'shellxquote', '', {})
end)
-- Invokes `:terminal {cmd}` using a fake shell (shell-test.c) which prints
- -- the {cmd} and exits immediately .
+ -- the {cmd} and exits immediately.
+ -- When no argument is given and the exit code is zero, the terminal buffer
+ -- closes automatically.
local function terminal_with_fake_shell(cmd)
feed_command("terminal "..(cmd and cmd or ""))
end
it('with no argument, acts like termopen()', function()
skip(is_os('win'))
- terminal_with_fake_shell()
+ -- Use the EXIT subcommand to end the process with a non-zero exit code to
+ -- prevent the buffer from closing automatically
+ nvim('set_option_value', 'shellcmdflag', 'EXIT', {})
+ terminal_with_fake_shell(1)
retry(nil, 4 * screen.timeout, function()
screen:expect([[
- ^ready $ |
- [Process exited 0] |
+ ^ |
+ [Process exited 1] |
|
- :terminal |
+ :terminal 1 |
]])
end)
end)
it("with no argument, and 'shell' is set to empty string", function()
- nvim('set_option', 'shell', '')
+ nvim('set_option_value', 'shell', '', {})
terminal_with_fake_shell()
screen:expect([[
^ |
@@ -169,7 +191,7 @@ describe(':terminal (with fake shell)', function()
it("with no argument, but 'shell' has arguments, acts like termopen()", function()
skip(is_os('win'))
- nvim('set_option', 'shell', testprg('shell-test')..' -t jeff')
+ nvim('set_option_value', 'shell', testprg('shell-test')..' -t jeff', {})
terminal_with_fake_shell()
screen:expect([[
^jeff $ |
@@ -193,7 +215,7 @@ describe(':terminal (with fake shell)', function()
it("executes a given command through the shell, when 'shell' has arguments", function()
skip(is_os('win'))
- nvim('set_option', 'shell', testprg('shell-test')..' -t jeff')
+ nvim('set_option_value', 'shell', testprg('shell-test')..' -t jeff', {})
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell('echo hi')
screen:expect([[
@@ -243,12 +265,13 @@ describe(':terminal (with fake shell)', function()
it('works with :find', function()
skip(is_os('win'))
- terminal_with_fake_shell()
+ nvim('set_option_value', 'shellcmdflag', 'EXIT', {})
+ terminal_with_fake_shell(1)
screen:expect([[
- ^ready $ |
- [Process exited 0] |
+ ^ |
+ [Process exited 1] |
|
- :terminal |
+ :terminal 1 |
]])
eq('term://', string.match(eval('bufname("%")'), "^term://"))
feed([[<C-\><C-N>]])
diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua
index 7247361649..62d3dd67a3 100644
--- a/test/functional/terminal/helpers.lua
+++ b/test/functional/terminal/helpers.lua
@@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')(nil)
local Screen = require('test.functional.ui.screen')
local testprg = helpers.testprg
local exec_lua = helpers.exec_lua
-local feed_command, nvim = helpers.feed_command, helpers.nvim
+local nvim = helpers.nvim
local function feed_data(data)
if type(data) == 'table' then
@@ -82,15 +82,16 @@ local function screen_setup(extra_rows, command, cols, opts)
screen:attach(opts or {rgb=false})
- feed_command('enew | call termopen('..command..')')
+ nvim('command', 'enew | call termopen('..command..')')
nvim('input', '<CR>')
local vim_errmsg = nvim('eval', 'v:errmsg')
if vim_errmsg and "" ~= vim_errmsg then
error(vim_errmsg)
end
- feed_command('setlocal scrollback=10')
- feed_command('startinsert')
+ nvim('command', 'setlocal scrollback=10')
+ nvim('command', 'startinsert')
+ nvim('input', '<Ignore>') -- Add input to separate two RPC requests
-- tty-test puts the terminal into raw mode and echoes input. Tests work by
-- feeding termcodes to control the display and asserting by screen:expect.
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index 50c8f5e7df..3291a38e03 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -11,7 +11,7 @@ describe(':terminal mouse', function()
before_each(function()
clear()
- nvim('set_option', 'statusline', '==========')
+ nvim('set_option_value', 'statusline', '==========', {})
command('highlight StatusLine cterm=NONE')
command('highlight StatusLineNC cterm=NONE')
command('highlight VertSplit cterm=NONE')
@@ -67,9 +67,23 @@ describe(':terminal mouse', function()
eq('nt', eval('mode(1)'))
end)
- it('does not leave terminal mode on left-release', function()
- skip(is_os('win'))
- feed('<LeftRelease>')
+ it('will not exit focus on left-release', function()
+ eq('t', eval('mode(1)'))
+ feed('<LeftRelease><0,0>')
+ eq('t', eval('mode(1)'))
+ command('setlocal number')
+ eq('t', eval('mode(1)'))
+ feed('<LeftRelease><0,0>')
+ eq('t', eval('mode(1)'))
+ end)
+
+ it('will not exit focus on mouse movement', function()
+ eq('t', eval('mode(1)'))
+ feed('<MouseMove><0,0>')
+ eq('t', eval('mode(1)'))
+ command('setlocal number')
+ eq('t', eval('mode(1)'))
+ feed('<MouseMove><0,0>')
eq('t', eval('mode(1)'))
end)
@@ -232,7 +246,6 @@ describe(':terminal mouse', function()
end)
describe('with a split window and other buffer', function()
- skip(is_os('win'))
before_each(function()
feed('<c-\\><c-n>:vsp<cr>')
screen:expect([[
@@ -289,7 +302,7 @@ describe(':terminal mouse', function()
]])
end)
- it("won't lose focus if another window is scrolled", function()
+ it("scrolling another window keeps focus and respects 'mousescroll'", function()
feed('<ScrollWheelUp><4,0><ScrollWheelUp><4,0>')
screen:expect([[
{7: 21 }line │line30 |
@@ -310,22 +323,8 @@ describe(':terminal mouse', function()
========== ========== |
{3:-- TERMINAL --} |
]])
- end)
-
- it("scrolling another window respects 'mousescroll'", function()
- command('set mousescroll=ver:1')
- feed('<ScrollWheelUp><4,0>')
- screen:expect([[
- {7: 26 }line │line30 |
- {7: 27 }line │rows: 5, cols: 25 |
- {7: 28 }line │rows: 5, cols: 24 |
- {7: 29 }line │mouse enabled |
- {7: 30 }line │{1: } |
- ========== ========== |
- {3:-- TERMINAL --} |
- ]])
command('set mousescroll=ver:10')
- feed('<ScrollWheelUp><4,0>')
+ feed('<ScrollWheelUp><0,0>')
screen:expect([[
{7: 16 }line │line30 |
{7: 17 }line │rows: 5, cols: 25 |
@@ -336,8 +335,41 @@ describe(':terminal mouse', function()
{3:-- TERMINAL --} |
]])
command('set mousescroll=ver:0')
- feed('<ScrollWheelUp><4,0>')
+ feed('<ScrollWheelUp><0,0>')
screen:expect_unchanged()
+ feed([[<C-\><C-N><C-W>w]])
+ command('setlocal nowrap')
+ feed('0<C-V>gg3ly$4p<C-W>wi')
+ screen:expect([[
+ {7: 1 }linelinelinelineline │line30 |
+ {7: 2 }linelinelinelineline │rows: 5, cols: 25 |
+ {7: 3 }linelinelinelineline │rows: 5, cols: 24 |
+ {7: 4 }linelinelinelineline │mouse enabled |
+ {7: 5 }linelinelinelineline │{1: } |
+ ========== ========== |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<ScrollWheelRight><4,0>')
+ screen:expect([[
+ {7: 1 }nelinelineline │line30 |
+ {7: 2 }nelinelineline │rows: 5, cols: 25 |
+ {7: 3 }nelinelineline │rows: 5, cols: 24 |
+ {7: 4 }nelinelineline │mouse enabled |
+ {7: 5 }nelinelineline │{1: } |
+ ========== ========== |
+ {3:-- TERMINAL --} |
+ ]])
+ command('set mousescroll=hor:4')
+ feed('<ScrollWheelLeft><4,0>')
+ screen:expect([[
+ {7: 1 }nelinelinelineline │line30 |
+ {7: 2 }nelinelinelineline │rows: 5, cols: 25 |
+ {7: 3 }nelinelinelineline │rows: 5, cols: 24 |
+ {7: 4 }nelinelinelineline │mouse enabled |
+ {7: 5 }nelinelinelineline │{1: } |
+ ========== ========== |
+ {3:-- TERMINAL --} |
+ ]])
end)
it('will lose focus if another window is clicked', function()
@@ -354,7 +386,7 @@ describe(':terminal mouse', function()
end)
it('handles terminal size when switching buffers', function()
- nvim('set_option', 'hidden', true)
+ nvim('set_option_value', 'hidden', true, {})
feed('<c-\\><c-n><c-w><c-w>')
screen:expect([[
{7: 27 }line │line30 |
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index a4899c8219..1e278e4cff 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -2,13 +2,12 @@ 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, testprg, feed_command = helpers.feed, helpers.testprg, helpers.feed_command
+local feed, testprg = helpers.feed, helpers.testprg
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
+local meths = helpers.meths
local nvim = helpers.nvim
local feed_data = thelpers.feed_data
local pcall_err = helpers.pcall_err
@@ -140,7 +139,6 @@ describe(':terminal scrollback', function()
describe('and height decreased by 1', function()
- if skip(is_os('win')) then return end
local function will_hide_top_line()
feed([[<C-\><C-N>]])
screen:try_resize(screen._width - 2, screen._height - 1)
@@ -347,12 +345,10 @@ end)
describe(':terminal prints more lines than the screen height and exits', function()
it('will push extra lines to scrollback', function()
- skip(is_os('win'))
clear()
local screen = Screen.new(30, 7)
screen:attach({rgb=false})
- feed_command(("call termopen(['%s', '10']) | startinsert"):format(testprg('tty-test')))
- poke_eventloop()
+ command(("call termopen(['%s', '10']) | startinsert"):format(testprg('tty-test')))
screen:expect([[
line6 |
line7 |
@@ -382,9 +378,7 @@ describe("'scrollback' option", function()
end)
local function set_fake_shell()
- -- shell-test.c is a fake shell that prints its arguments and exits.
- nvim('set_option', 'shell', testprg('shell-test'))
- nvim('set_option', 'shellcmdflag', 'EXE')
+ nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
end
local function expect_lines(expected, epsilon)
@@ -403,7 +397,7 @@ describe("'scrollback' option", function()
screen = thelpers.screen_setup(nil, "['sh']", 30)
end
- curbufmeths.set_option('scrollback', 0)
+ meths.set_option_value('scrollback', 0, {})
feed_data(('%s REP 31 line%s'):format(testprg('shell-test'), is_os('win') and '\r' or '\n'))
screen:expect{any='30: line '}
retry(nil, nil, function() expect_lines(7) end)
@@ -419,7 +413,7 @@ describe("'scrollback' option", function()
screen = thelpers.screen_setup(nil, "['sh']", 30)
end
- curbufmeths.set_option('scrollback', 200)
+ meths.set_option_value('scrollback', 200, {})
-- Wait for prompt.
screen:expect{any='%$'}
@@ -428,10 +422,10 @@ describe("'scrollback' option", function()
screen:expect{any='30: line '}
retry(nil, nil, function() expect_lines(33, 2) end)
- curbufmeths.set_option('scrollback', 10)
+ meths.set_option_value('scrollback', 10, {})
poke_eventloop()
retry(nil, nil, function() expect_lines(16) end)
- curbufmeths.set_option('scrollback', 10000)
+ meths.set_option_value('scrollback', 10000, {})
retry(nil, nil, function() expect_lines(16) end)
-- Terminal job data is received asynchronously, may happen before the
-- 'scrollback' option is synchronized with the internal sb_buffer.
@@ -462,8 +456,8 @@ describe("'scrollback' option", function()
expect_lines(58)
-- Verify off-screen state
- matches((is_os('win') and '^36: line[ ]*$' or '^35: line[ ]*$'), eval("getline(line('w0') - 1)"))
- matches((is_os('win') and '^27: line[ ]*$' or '^26: line[ ]*$'), eval("getline(line('w0') - 10)"))
+ eq((is_os('win') and '36: line' or '35: line'), eval("getline(line('w0') - 1)->trim(' ', 2)"))
+ eq((is_os('win') and '27: line' or '26: line'), eval("getline(line('w0') - 10)->trim(' ', 2)"))
end)
it('deletes extra lines immediately', function()
@@ -486,18 +480,18 @@ describe("'scrollback' option", function()
]])
local term_height = 6 -- Actual terminal screen height, not the scrollback
-- Initial
- local scrollback = curbufmeths.get_option('scrollback')
+ local scrollback = meths.get_option_value('scrollback', {})
eq(scrollback + term_height, eval('line("$")'))
-- Reduction
scrollback = scrollback - 2
- curbufmeths.set_option('scrollback', scrollback)
+ meths.set_option_value('scrollback', scrollback, {})
eq(scrollback + term_height, eval('line("$")'))
end)
it('defaults to 10000 in :terminal buffers', function()
set_fake_shell()
command('terminal')
- eq(10000, curbufmeths.get_option('scrollback'))
+ eq(10000, meths.get_option_value('scrollback', {}))
end)
it('error if set to invalid value', function()
@@ -509,7 +503,7 @@ describe("'scrollback' option", function()
it('defaults to -1 on normal buffers', function()
command('new')
- eq(-1, curbufmeths.get_option('scrollback'))
+ eq(-1, meths.get_option_value('scrollback', {}))
end)
it(':setlocal in a :terminal buffer', function()
@@ -518,45 +512,45 @@ describe("'scrollback' option", function()
-- _Global_ scrollback=-1 defaults :terminal to 10_000.
command('setglobal scrollback=-1')
command('terminal')
- eq(10000, curbufmeths.get_option('scrollback'))
+ eq(10000, meths.get_option_value('scrollback', {}))
-- _Local_ scrollback=-1 in :terminal forces the _maximum_.
command('setlocal scrollback=-1')
retry(nil, nil, function() -- Fixup happens on refresh, not immediately.
- eq(100000, curbufmeths.get_option('scrollback'))
+ eq(100000, meths.get_option_value('scrollback', {}))
end)
-- _Local_ scrollback=-1 during TermOpen forces the maximum. #9605
command('setglobal scrollback=-1')
command('autocmd TermOpen * setlocal scrollback=-1')
command('terminal')
- eq(100000, curbufmeths.get_option('scrollback'))
+ eq(100000, meths.get_option_value('scrollback', {}))
end)
it(':setlocal in a normal buffer', function()
command('new')
-- :setlocal to -1.
command('setlocal scrollback=-1')
- eq(-1, curbufmeths.get_option('scrollback'))
+ eq(-1, meths.get_option_value('scrollback', {}))
-- :setlocal to anything except -1. Currently, this just has no effect.
command('setlocal scrollback=42')
- eq(42, curbufmeths.get_option('scrollback'))
+ eq(42, meths.get_option_value('scrollback', {}))
end)
it(':set updates local value and global default', function()
set_fake_shell()
command('set scrollback=42') -- set global value
- eq(42, curbufmeths.get_option('scrollback'))
+ eq(42, meths.get_option_value('scrollback', {}))
command('terminal')
- eq(42, curbufmeths.get_option('scrollback')) -- inherits global default
+ eq(42, meths.get_option_value('scrollback', {})) -- inherits global default
command('setlocal scrollback=99')
- eq(99, curbufmeths.get_option('scrollback'))
+ eq(99, meths.get_option_value('scrollback', {}))
command('set scrollback<') -- reset to global default
- eq(42, curbufmeths.get_option('scrollback'))
+ eq(42, meths.get_option_value('scrollback', {}))
command('setglobal scrollback=734') -- new global default
- eq(42, curbufmeths.get_option('scrollback')) -- local value did not change
+ eq(42, meths.get_option_value('scrollback', {})) -- local value did not change
command('terminal')
- eq(734, curbufmeths.get_option('scrollback'))
+ eq(734, meths.get_option_value('scrollback', {}))
end)
end)
@@ -577,12 +571,12 @@ describe("pending scrollback line handling", function()
it("does not crash after setting 'number' #14891", function()
exec_lua [[
- local a = vim.api
- local buf = a.nvim_create_buf(true, true)
- local chan = a.nvim_open_term(buf, {})
- a.nvim_win_set_option(0, "number", true)
- a.nvim_chan_send(chan, ("a\n"):rep(11) .. "a")
- a.nvim_win_set_buf(0, buf)
+ local api = vim.api
+ local buf = api.nvim_create_buf(true, true)
+ local chan = api.nvim_open_term(buf, {})
+ vim.wo.number = true
+ api.nvim_chan_send(chan, ("a\n"):rep(11) .. "a")
+ api.nvim_win_set_buf(0, buf)
]]
screen:expect [[
{1: 1 }^a |
@@ -609,12 +603,11 @@ describe("pending scrollback line handling", function()
it("does not crash after nvim_buf_call #14891", function()
skip(is_os('win'))
exec_lua [[
- local a = vim.api
- local bufnr = a.nvim_create_buf(false, true)
- a.nvim_buf_call(bufnr, function()
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_buf_call(bufnr, function()
vim.fn.termopen({"echo", ("hi\n"):rep(11)})
end)
- a.nvim_win_set_buf(0, bufnr)
+ vim.api.nvim_win_set_buf(0, bufnr)
vim.cmd("startinsert")
]]
screen:expect [[
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index b28728057f..b17eed00f9 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -8,12 +8,12 @@ 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
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
@@ -27,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
@@ -68,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([[
@@ -108,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:} |
@@ -127,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} |
@@ -211,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([[
@@ -251,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} |
@@ -290,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----|
@@ -316,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----|
@@ -327,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----|
@@ -338,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----|
@@ -349,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|
@@ -360,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|
@@ -371,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|
@@ -382,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|
@@ -393,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----|
@@ -404,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----|
@@ -415,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----|
@@ -426,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----|
@@ -437,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---|
@@ -448,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---|
@@ -459,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---|
@@ -470,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---|
@@ -481,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----|
@@ -491,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()
@@ -631,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: } |
@@ -667,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()
@@ -752,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" |
@@ -806,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()
@@ -874,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)
@@ -1171,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},
@@ -1351,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({
@@ -1397,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:℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃}|
@@ -1425,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)
@@ -1448,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
@@ -1472,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] [+] }|
|
@@ -1506,13 +1713,107 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]]}
end)
+
+ it('no assert failure on deadly signal #21896', function()
+ 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)
@@ -1538,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')
@@ -1582,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()
@@ -1620,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:~ }|
@@ -1633,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([[
@@ -1675,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: } |
@@ -1740,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(':')
@@ -1768,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 |
@@ -1796,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 |
@@ -1839,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(
@@ -2204,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!'}
@@ -2253,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')
@@ -2269,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')
@@ -2290,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()
@@ -2304,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')
@@ -2359,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")
@@ -2379,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:~ }|
@@ -2401,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([[
@@ -2423,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)
@@ -2432,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=[[
@@ -2456,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=[[
@@ -2471,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)
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index 80e9d78400..39fc2c2562 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -44,7 +44,7 @@ describe(':terminal window', function()
{7:6 } |
{3:-- TERMINAL --} |
]])
- feed_data({'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'})
+ feed_data('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
screen:expect([[
{7:1 }tty ready |
{7:2 }rows: 6, cols: 48 |
@@ -55,8 +55,6 @@ describe(':terminal window', function()
{3:-- TERMINAL --} |
]])
- skip(is_os('win'), 'win: :terminal resize is unreliable #7007')
-
-- numberwidth=9
feed([[<C-\><C-N>]])
feed([[:set numberwidth=9 number<CR>i]])
@@ -64,17 +62,17 @@ describe(':terminal window', function()
{7: 1 }tty ready |
{7: 2 }rows: 6, cols: 48 |
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
- {7: 4 }WXYZrows: 6, cols: 41 |
+ {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 |
{7: 5 }{1: } |
{7: 6 } |
{3:-- TERMINAL --} |
]])
- feed_data({' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'})
+ feed_data(' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
screen:expect([[
{7: 1 }tty ready |
{7: 2 }rows: 6, cols: 48 |
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
- {7: 4 }WXYZrows: 6, cols: 41 |
+ {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 |
{7: 5 } abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN|
{7: 6 }OPQRSTUVWXYZ{1: } |
{3:-- TERMINAL --} |
@@ -82,6 +80,41 @@ describe(':terminal window', function()
end)
end)
+ describe("with 'statuscolumn'", function()
+ it('wraps text', function()
+ command([[set number statuscolumn=++%l\ \ ]])
+ screen:expect([[
+ {7:++1 }tty ready |
+ {7:++2 }rows: 6, cols: 45 |
+ {7:++3 }{1: } |
+ {7:++4 } |
+ {7:++5 } |
+ {7:++6 } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\n\n\n\n\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
+ screen:expect([[
+ {7:++4 } |
+ {7:++5 } |
+ {7:++6 } |
+ {7:++7 } |
+ {7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS|
+ {7:++9 }TUVWXYZ{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
+ screen:expect([[
+ {7:++7 } |
+ {7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
+ {7:++9 }STUVWXYZ |
+ {7:++10 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
+ {7:++11 }STUVWXYZrows: 6, cols: 44 |
+ {7:++12 }{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+ end)
+
describe("with 'colorcolumn'", function()
before_each(function()
feed([[<C-\><C-N>]])
diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua
index 1d77e1e92e..da14531fa2 100644
--- a/test/functional/terminal/window_split_tab_spec.lua
+++ b/test/functional/terminal/window_split_tab_spec.lua
@@ -19,7 +19,7 @@ describe(':terminal', function()
clear()
-- set the statusline to a constant value because of variables like pid
-- and current directory and to improve visibility of splits
- meths.set_option('statusline', '==========')
+ meths.set_option_value('statusline', '==========', {})
command('highlight StatusLine cterm=NONE')
command('highlight StatusLineNC cterm=NONE')
command('highlight VertSplit cterm=NONE')
@@ -71,7 +71,7 @@ describe(':terminal', function()
end)
it('does not change size if updated when not visible in any window #19665', function()
- local channel = meths.buf_get_option(0, 'channel')
+ local channel = meths.get_option_value('channel', {})
command('enew')
sleep(100)
meths.chan_send(channel, 'foo')