diff options
Diffstat (limited to 'test/functional/terminal/buffer_spec.lua')
-rw-r--r-- | test/functional/terminal/buffer_spec.lua | 371 |
1 files changed, 250 insertions, 121 deletions
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 6fcd029a5b..376b7b849e 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -1,23 +1,24 @@ local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local assert_alive = helpers.assert_alive -local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim +local feed, clear = helpers.feed, helpers.clear local poke_eventloop = helpers.poke_eventloop +local nvim_prog = helpers.nvim_prog local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source local pcall_err = helpers.pcall_err local eq, neq = helpers.eq, helpers.neq -local meths = helpers.meths +local api = helpers.api local retry = helpers.retry local write_file = helpers.write_file local command = helpers.command local exc_exec = helpers.exc_exec local matches = helpers.matches local exec_lua = helpers.exec_lua -local sleep = helpers.sleep -local funcs = helpers.funcs +local sleep = vim.uv.sleep +local fn = helpers.fn local is_os = helpers.is_os local skip = helpers.skip -local nvim_prog = helpers.nvim_prog describe(':terminal buffer', function() local screen @@ -31,13 +32,19 @@ describe(':terminal buffer', function() it('terminal-mode forces various options', function() feed([[<C-\><C-N>]]) command('setlocal cursorline cursorlineopt=both cursorcolumn scrolloff=4 sidescrolloff=7') - eq({ 'both', 1, 1, 4, 7 }, eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]')) + eq( + { 'both', 1, 1, 4, 7 }, + eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]') + ) eq('nt', eval('mode(1)')) -- Enter terminal-mode ("insert" mode in :terminal). feed('i') eq('t', eval('mode(1)')) - eq({ 'number', 1, 0, 0, 0 }, eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]')) + eq( + { 'number', 1, 0, 0, 0 }, + eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]') + ) end) it('terminal-mode does not change cursorlineopt if cursorline is disabled', function() @@ -59,11 +66,7 @@ describe(':terminal buffer', function() feed('<c-\\><c-n>:set bufhidden=wipe<cr>:enew<cr>') screen:expect([[ ^ | - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| + {4:~ }|*5 :enew | ]]) end) @@ -72,11 +75,7 @@ describe(':terminal buffer', function() feed(':bnext:l<esc>') screen:expect([[ ^ | - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| + {4:~ }|*5 | ]]) end) @@ -88,21 +87,17 @@ describe(':terminal buffer', function() screen:expect([[ tty ready | {2:^ } | - | - | - | - | - | + |*5 ]]) end) it('does not create swap files', function() - local swapfile = nvim('exec', 'swapname', true):gsub('\n', '') + local swapfile = api.nvim_exec('swapname', true):gsub('\n', '') eq(nil, io.open(swapfile)) end) it('does not create undofiles files', function() - local undofile = nvim('eval', 'undofile(bufname("%"))') + local undofile = api.nvim_eval('undofile(bufname("%"))') eq(nil, io.open(undofile)) end) end) @@ -112,10 +107,7 @@ describe(':terminal buffer', function() screen:expect([[ tty ready | {2:^ } | - | - | - | - | + |*4 {8:E21: Cannot make changes, 'modifiable' is off} | ]]) end) @@ -126,22 +118,16 @@ describe(':terminal buffer', function() feed('"ap"ap') screen:expect([[ ^tty ready | - appended tty ready | - appended tty ready | + appended tty ready |*2 {2: } | - | - | + |*2 :let @a = "appended " . @a | ]]) -- operator count is also taken into consideration feed('3"ap') screen:expect([[ ^tty ready | - appended tty ready | - appended tty ready | - appended tty ready | - appended tty ready | - appended tty ready | + appended tty ready |*5 :let @a = "appended " . @a | ]]) end) @@ -154,17 +140,14 @@ describe(':terminal buffer', function() ^tty ready | appended tty ready | {2: } | - | - | - | + |*3 :put a | ]]) -- line argument is only used to move the cursor feed_command('6put a') screen:expect([[ tty ready | - appended tty ready | - appended tty ready | + appended tty ready |*2 {2: } | | ^ | @@ -176,34 +159,24 @@ describe(':terminal buffer', function() feed('<c-\\><c-n>:bd!<cr>') screen:expect([[ ^ | - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| + {4:~ }|*5 :bd! | ]]) feed_command('bnext') screen:expect([[ ^ | - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| - {4:~ }| + {4:~ }|*5 :bnext | ]]) end) it('handles loss of focus gracefully', function() -- Change the statusline to avoid printing the file name, which varies. - nvim('set_option_value', 'statusline', '==========', {}) + api.nvim_set_option_value('statusline', '==========', {}) -- Save the buffer number of the terminal for later testing. local tbuf = eval('bufnr("%")') - local exitcmd = is_os('win') - and "['cmd', '/c', 'exit']" - or "['sh', '-c', 'exit']" + local exitcmd = is_os('win') and "['cmd', '/c', 'exit']" or "['sh', '-c', 'exit']" source([[ function! SplitWindow(id, data, event) new @@ -211,7 +184,7 @@ describe(':terminal buffer', function() endfunction startinsert - call jobstart(]]..exitcmd..[[, {'on_exit': function("SplitWindow")}) + call jobstart(]] .. exitcmd .. [[, {'on_exit': function("SplitWindow")}) call feedkeys("\<C-\>", 't') " vim will expect <C-n>, but be exited out of " the terminal before it can be entered. ]]) @@ -228,7 +201,7 @@ describe(':terminal buffer', function() ]]) neq(tbuf, eval('bufnr("%")')) - feed_command('quit!') -- Should exit the new window, not the terminal. + feed_command('quit!') -- Should exit the new window, not the terminal. eq(tbuf, eval('bufnr("%")')) end) @@ -243,46 +216,46 @@ describe(':terminal buffer', function() feed_command('terminal') feed('<c-\\><c-n>') feed_command('confirm bdelete') - screen:expect{any='Close "term://'} + screen:expect { any = 'Close "term://' } end) it('with &confirm', function() feed_command('terminal') feed('<c-\\><c-n>') feed_command('bdelete') - screen:expect{any='E89'} + screen:expect { any = 'E89' } feed('<cr>') eq('terminal', eval('&buftype')) feed_command('set confirm | bdelete') - screen:expect{any='Close "term://'} + screen:expect { any = 'Close "term://' } feed('y') neq('terminal', eval('&buftype')) end) end) it('it works with set rightleft #11438', function() - skip(is_os('win')) local columns = eval('&columns') feed(string.rep('a', columns)) command('set rightleft') screen:expect([[ ydaer ytt| {1:a}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - | - | - | - | + |*4 {3:-- TERMINAL --} | ]]) command('bdelete!') end) it('requires bang (!) to close a running job #15402', function() - skip(is_os('win'), "Test freezes the CI and makes it time out") + 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%)$', - exc_exec(cmd)) + matches( + '^Vim%(' + .. cmd:gsub('%%', '') + .. '%):E89: term://.*tty%-test.* will be killed %(add %! to override%)$', + exc_exec(cmd) + ) end command('call jobstop(&channel)') assert(0 >= eval('jobwait([&channel], 1000)[0]')) @@ -299,51 +272,97 @@ describe(':terminal buffer', function() it('does not segfault when pasting empty register #13955', function() feed('<c-\\><c-n>') - feed_command('put a') -- register a is empty + feed_command('put a') -- register a is empty helpers.assert_alive() end) it([[can use temporary normal mode <c-\><c-o>]], function() - eq('t', funcs.mode(1)) + eq('t', fn.mode(1)) feed [[<c-\><c-o>]] - screen:expect{grid=[[ + screen:expect { + grid = [[ tty ready | {2:^ } | - | - | - | - | + |*4 {3:-- (terminal) --} | - ]]} - eq('ntT', funcs.mode(1)) + ]], + } + eq('ntT', fn.mode(1)) feed [[:let g:x = 17]] - screen:expect{grid=[[ + screen:expect { + grid = [[ tty ready | {2: } | - | - | - | - | + |*4 :let g:x = 17^ | - ]]} + ]], + } feed [[<cr>]] - screen:expect{grid=[[ + screen:expect { + grid = [[ tty ready | {1: } | - | - | - | - | + |*4 {3:-- TERMINAL --} | - ]]} - eq('t', funcs.mode(1)) + ]], + } + eq('t', fn.mode(1)) end) it('writing to an existing file with :w fails #13549', function() - eq('Vim(write):E13: File exists (add ! to override)', - pcall_err(command, 'write test/functional/fixtures/tty-test.c')) + eq( + 'Vim(write):E13: File exists (add ! to override)', + pcall_err(command, 'write test/functional/fixtures/tty-test.c') + ) + end) + + it('emits TermRequest events #26972', function() + command('new') + local term = api.nvim_open_term(0, {}) + local termbuf = api.nvim_get_current_buf() + + -- Test that autocommand buffer is associated with the terminal buffer, not the current buffer + command('au TermRequest * let g:termbuf = +expand("<abuf>")') + command('wincmd p') + + -- cwd will be inserted in a file URI, which cannot contain backs + local cwd = fn.getcwd():gsub('\\', '/') + local parent = cwd:match('^(.+/)') + local expected = '\027]7;file://host' .. parent + api.nvim_chan_send(term, string.format('%s\027\\', expected)) + eq(expected, eval('v:termrequest')) + eq(termbuf, eval('g:termbuf')) + end) + + it('TermReqeust synchronization #27572', function() + command('new') + command('autocmd! nvim_terminal TermRequest') + local term = exec_lua([[ + _G.input = {} + local term = vim.api.nvim_open_term(0, { + on_input = function(_, _, _, data) + table.insert(_G.input, data) + end, + force_crlf = false, + }) + vim.api.nvim_create_autocmd('TermRequest', { + callback = function(args) + if args.data == '\027]11;?' then + table.insert(_G.input, '\027]11;rgb:0000/0000/0000\027\\') + end + end + }) + return term + ]]) + api.nvim_chan_send(term, '\027]11;?\007\027[5n\027]11;?\007\027[5n') + eq({ + '\027]11;rgb:0000/0000/0000\027\\', + '\027[0n', + '\027]11;rgb:0000/0000/0000\027\\', + '\027[0n', + }, exec_lua('return _G.input')) end) end) @@ -351,7 +370,7 @@ describe('No heap-buffer-overflow when using', function() local testfilename = 'Xtestfile-functional-terminal-buffers_spec' before_each(function() - write_file(testfilename, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa") + write_file(testfilename, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa') end) after_each(function() @@ -414,10 +433,12 @@ end) it('terminal truncates number of composing characters to 5', function() clear() - local chan = meths.open_term(0, {}) + local chan = api.nvim_open_term(0, {}) local composing = ('a̳'):sub(2) - meths.chan_send(chan, 'a' .. composing:rep(8)) - retry(nil, nil, function() eq('a' .. composing:rep(5), meths.get_current_line()) end) + api.nvim_chan_send(chan, 'a' .. composing:rep(8)) + retry(nil, nil, function() + eq('a' .. composing:rep(5), api.nvim_get_current_line()) + end) end) describe('terminal input', function() @@ -447,31 +468,80 @@ 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=[[ + local screen = thelpers.setup_child_nvim({ + '-u', + 'NONE', + '-i', + 'NONE', + '--cmd', + 'colorscheme vim', + '--cmd', + 'set notermguicolors', + '--cmd', + 'startinsert', + }) + screen:expect { + grid = [[ {1: } | - {4:~ }| - {4:~ }| - {4:~ }| + {4:~ }|*3 {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>', + '<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) + retry(nil, nil, function() + eq(key, api.nvim_get_current_line()) + end) end end) end) @@ -484,7 +554,7 @@ if is_os('win') then clear() feed_command('set modifiable swapfile undolevels=20') poke_eventloop() - local cmd = '["cmd.exe","/K","PROMPT=$g$s"]' + local cmd = { 'cmd.exe', '/K', 'PROMPT=$g$s' } screen = thelpers.screen_setup(nil, cmd) end) @@ -549,11 +619,70 @@ describe('termopen()', function() 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")) + 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(fn.termopen, 'bar') + ) + end) + + describe('$COLORTERM value', function() + if skip(is_os('win'), 'Not applicable for Windows') then + return + end - feed("q:") - eq("Vim:E11: Invalid in command-line window; <CR> executes, CTRL-C quits", - pcall_err(funcs.termopen, "bar")) + before_each(function() + -- Outer value should never be propagated to :terminal + fn.setenv('COLORTERM', 'wrongvalue') + end) + + local function test_term_colorterm(expected, opts) + local screen = Screen.new(50, 4) + screen:attach() + fn.termopen({ + nvim_prog, + '-u', + 'NONE', + '-i', + 'NONE', + '--headless', + '-c', + 'echo $COLORTERM | quit', + }, opts) + screen:expect(([[ + ^%s{MATCH:%%s+}| + [Process exited 0] | + |*2 + ]]):format(expected)) + end + + describe("with 'notermguicolors'", function() + before_each(function() + command('set notermguicolors') + end) + it('is empty by default', function() + test_term_colorterm('') + end) + it('can be overridden', function() + test_term_colorterm('expectedvalue', { env = { COLORTERM = 'expectedvalue' } }) + end) + end) + + describe("with 'termguicolors'", function() + before_each(function() + command('set termguicolors') + end) + it('is "truecolor" by default', function() + test_term_colorterm('truecolor') + end) + it('can be overridden', function() + test_term_colorterm('expectedvalue', { env = { COLORTERM = 'expectedvalue' } }) + end) + end) end) end) |