2024-04-20 08:44:13 -07:00
|
|
|
local t = require('test.testutil')
|
|
|
|
local n = require('test.functional.testnvim')()
|
2017-05-10 06:04:49 -07:00
|
|
|
local Screen = require('test.functional.ui.screen')
|
2024-04-08 02:03:20 -07:00
|
|
|
local tt = require('test.functional.terminal.testutil')
|
|
|
|
|
2024-04-20 08:44:13 -07:00
|
|
|
local assert_alive = n.assert_alive
|
|
|
|
local mkdir, write_file, rmdir = t.mkdir, t.write_file, n.rmdir
|
2024-04-08 02:03:20 -07:00
|
|
|
local eq = t.eq
|
2024-04-20 08:44:13 -07:00
|
|
|
local feed = n.feed
|
|
|
|
local feed_command = n.feed_command
|
|
|
|
local clear = n.clear
|
|
|
|
local command = n.command
|
|
|
|
local testprg = n.testprg
|
|
|
|
local nvim_dir = n.nvim_dir
|
|
|
|
local has_powershell = n.has_powershell
|
|
|
|
local set_shell_powershell = n.set_shell_powershell
|
2024-04-08 02:03:20 -07:00
|
|
|
local skip = t.skip
|
|
|
|
local is_os = t.is_os
|
2016-08-15 16:42:12 -07:00
|
|
|
|
2023-04-27 00:51:44 -07:00
|
|
|
clear() -- for has_powershell()
|
|
|
|
|
2016-07-14 19:11:49 -07:00
|
|
|
describe('shell command :!', function()
|
|
|
|
local screen
|
|
|
|
before_each(function()
|
2018-02-07 02:33:05 -07:00
|
|
|
clear()
|
2024-04-08 02:03:20 -07:00
|
|
|
screen = tt.setup_child_nvim({
|
2023-12-05 15:26:46 -07:00
|
|
|
'-u',
|
|
|
|
'NONE',
|
|
|
|
'-i',
|
|
|
|
'NONE',
|
|
|
|
'--cmd',
|
|
|
|
'colorscheme vim',
|
2023-12-06 19:16:00 -07:00
|
|
|
'--cmd',
|
2024-04-20 08:44:13 -07:00
|
|
|
n.nvim_set .. ' notermguicolors',
|
2023-12-05 15:26:46 -07:00
|
|
|
})
|
2016-07-14 19:11:49 -07:00
|
|
|
screen:expect([[
|
|
|
|
{1: } |
|
2023-12-09 05:42:00 -07:00
|
|
|
{4:~ }|*4
|
2016-07-14 19:11:49 -07:00
|
|
|
|
|
2016-08-09 08:01:56 -07:00
|
|
|
{3:-- TERMINAL --} |
|
2016-07-14 19:11:49 -07:00
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
|
|
|
after_each(function()
|
2024-04-08 02:03:20 -07:00
|
|
|
tt.feed_data('\3') -- Ctrl-C
|
2016-07-14 19:11:49 -07:00
|
|
|
end)
|
|
|
|
|
2017-01-19 06:19:59 -07:00
|
|
|
it('displays output without LF/EOF. #4646 #4569 #3772', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
skip(is_os('win'))
|
2016-07-14 19:11:49 -07:00
|
|
|
-- NOTE: We use a child nvim (within a :term buffer)
|
|
|
|
-- to avoid triggering a UI flush.
|
2024-04-08 02:03:20 -07:00
|
|
|
tt.feed_data(':!printf foo; sleep 200\n')
|
2016-07-14 19:11:49 -07:00
|
|
|
screen:expect([[
|
2018-03-31 02:12:27 -07:00
|
|
|
|
|
2023-12-09 05:42:00 -07:00
|
|
|
{4:~ }|*2
|
2018-03-31 02:12:27 -07:00
|
|
|
{5: }|
|
2016-09-14 17:59:09 -07:00
|
|
|
:!printf foo; sleep 200 |
|
|
|
|
foo |
|
2016-08-09 08:01:56 -07:00
|
|
|
{3:-- TERMINAL --} |
|
2016-07-14 19:11:49 -07:00
|
|
|
]])
|
|
|
|
end)
|
2016-09-29 17:33:50 -07:00
|
|
|
|
2016-10-07 04:18:24 -07:00
|
|
|
it('throttles shell-command output greater than ~10KB', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
skip(is_os('openbsd'), 'FIXME #10804')
|
2023-03-11 14:56:16 -07:00
|
|
|
skip(is_os('win'))
|
2024-04-08 02:03:20 -07:00
|
|
|
tt.feed_data((':!%s REP 30001 foo\n'):format(testprg('shell-test')))
|
2016-10-07 04:18:24 -07:00
|
|
|
|
|
|
|
-- If we observe any line starting with a dot, then throttling occurred.
|
2017-06-26 05:49:15 -07:00
|
|
|
-- Avoid false failure on slow systems.
|
|
|
|
screen:expect { any = '\n%.', timeout = 20000 }
|
2016-10-07 04:18:24 -07:00
|
|
|
|
|
|
|
-- Final chunk of output should always be displayed, never skipped.
|
|
|
|
-- (Throttling is non-deterministic, this test is merely a sanity check.)
|
|
|
|
screen:expect(
|
|
|
|
[[
|
2019-08-08 07:02:28 -07:00
|
|
|
29997: foo |
|
|
|
|
29998: foo |
|
|
|
|
29999: foo |
|
|
|
|
30000: foo |
|
2018-01-13 02:14:41 -07:00
|
|
|
|
|
2016-10-07 04:18:24 -07:00
|
|
|
{10:Press ENTER or type command to continue}{1: } |
|
|
|
|
{3:-- TERMINAL --} |
|
2018-11-20 02:52:49 -07:00
|
|
|
]],
|
|
|
|
{
|
2024-04-20 08:44:13 -07:00
|
|
|
-- test/functional/testnvim.lua defaults to background=light.
|
2018-11-20 02:52:49 -07:00
|
|
|
[1] = { reverse = true },
|
|
|
|
[3] = { bold = true },
|
|
|
|
[10] = { foreground = 2 },
|
|
|
|
}
|
|
|
|
)
|
2016-09-29 17:33:50 -07:00
|
|
|
end)
|
2016-07-14 19:11:49 -07:00
|
|
|
end)
|
2017-05-10 06:04:49 -07:00
|
|
|
|
|
|
|
describe('shell command :!', function()
|
|
|
|
before_each(function()
|
2018-02-07 02:33:05 -07:00
|
|
|
clear()
|
2017-05-10 06:04:49 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
it('cat a binary file #4142', function()
|
|
|
|
feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>")
|
2021-09-01 09:42:53 -07:00
|
|
|
assert_alive()
|
2017-05-10 06:04:49 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
it([[display \x08 char #4142]], function()
|
|
|
|
feed(':silent !echo \08<CR>')
|
2021-09-01 09:42:53 -07:00
|
|
|
assert_alive()
|
2017-05-10 06:04:49 -07:00
|
|
|
end)
|
|
|
|
|
2018-08-20 09:51:25 -07:00
|
|
|
it('handles control codes', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
skip(is_os('win'), 'missing printf')
|
2017-05-10 06:04:49 -07:00
|
|
|
local screen = Screen.new(50, 4)
|
|
|
|
screen:attach()
|
|
|
|
-- Print TAB chars. #2958
|
|
|
|
feed([[:!printf '1\t2\t3'<CR>]])
|
2022-08-17 07:19:35 -07:00
|
|
|
screen:expect {
|
|
|
|
grid = [[
|
2024-04-07 23:32:45 -07:00
|
|
|
{3: }|
|
2017-05-10 06:04:49 -07:00
|
|
|
:!printf '1\t2\t3' |
|
|
|
|
1 2 3 |
|
2024-04-07 23:32:45 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2022-08-17 07:19:35 -07:00
|
|
|
]],
|
|
|
|
}
|
2017-05-10 06:04:49 -07:00
|
|
|
feed([[<CR>]])
|
2022-08-17 07:19:35 -07:00
|
|
|
|
2017-05-10 06:04:49 -07:00
|
|
|
-- Print BELL control code. #4338
|
2018-02-07 02:23:19 -07:00
|
|
|
screen.bell = false
|
2018-06-13 20:03:37 -07:00
|
|
|
feed([[:!printf '\007\007\007\007text'<CR>]])
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect {
|
|
|
|
grid = [[
|
2024-04-07 23:32:45 -07:00
|
|
|
{3: }|
|
2018-06-13 20:03:37 -07:00
|
|
|
:!printf '\007\007\007\007text' |
|
2018-02-07 02:23:19 -07:00
|
|
|
text |
|
2024-04-07 23:32:45 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2018-08-20 09:51:25 -07:00
|
|
|
]],
|
|
|
|
condition = function()
|
2018-02-07 02:23:19 -07:00
|
|
|
eq(true, screen.bell)
|
2018-08-20 09:51:25 -07:00
|
|
|
end,
|
|
|
|
}
|
2017-05-10 06:04:49 -07:00
|
|
|
feed([[<CR>]])
|
2022-08-17 07:19:35 -07:00
|
|
|
|
2017-05-10 06:04:49 -07:00
|
|
|
-- Print BS control code.
|
2018-06-13 20:03:37 -07:00
|
|
|
feed([[:echo system('printf ''\010\n''')<CR>]])
|
2017-05-10 06:04:49 -07:00
|
|
|
screen:expect([[
|
2024-04-07 23:32:45 -07:00
|
|
|
{3: }|
|
|
|
|
{18:^H} |
|
2017-05-10 06:04:49 -07:00
|
|
|
|
|
2024-04-07 23:32:45 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2017-05-10 06:04:49 -07:00
|
|
|
]])
|
|
|
|
feed([[<CR>]])
|
2022-08-17 07:19:35 -07:00
|
|
|
|
2017-05-10 06:04:49 -07:00
|
|
|
-- Print LF control code.
|
|
|
|
feed([[:!printf '\n'<CR>]])
|
|
|
|
screen:expect([[
|
|
|
|
:!printf '\n' |
|
2023-12-09 05:42:00 -07:00
|
|
|
|*2
|
2024-04-07 23:32:45 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2017-05-10 06:04:49 -07:00
|
|
|
]])
|
|
|
|
feed([[<CR>]])
|
|
|
|
end)
|
2018-02-07 02:33:05 -07:00
|
|
|
|
|
|
|
describe('', function()
|
|
|
|
local screen
|
|
|
|
before_each(function()
|
|
|
|
rmdir('bang_filter_spec')
|
|
|
|
mkdir('bang_filter_spec')
|
|
|
|
write_file('bang_filter_spec/f1', 'f1')
|
|
|
|
write_file('bang_filter_spec/f2', 'f2')
|
|
|
|
write_file('bang_filter_spec/f3', 'f3')
|
|
|
|
screen = Screen.new(53, 10)
|
|
|
|
screen:attach()
|
|
|
|
end)
|
|
|
|
|
|
|
|
after_each(function()
|
|
|
|
rmdir('bang_filter_spec')
|
|
|
|
end)
|
|
|
|
|
|
|
|
it("doesn't truncate Last line of shell output #3269", function()
|
2022-11-21 17:13:30 -07:00
|
|
|
command(
|
2017-10-03 14:39:17 -07:00
|
|
|
is_os('win') and [[nnoremap <silent>\l :!dir /b bang_filter_spec<cr>]]
|
|
|
|
or [[nnoremap <silent>\l :!ls bang_filter_spec<cr>]]
|
2022-11-21 17:13:30 -07:00
|
|
|
)
|
|
|
|
local result = (
|
2017-10-03 14:39:17 -07:00
|
|
|
is_os('win') and [[:!dir /b bang_filter_spec]] or [[:!ls bang_filter_spec ]]
|
|
|
|
)
|
2018-02-07 02:33:05 -07:00
|
|
|
feed([[\l]])
|
|
|
|
screen:expect([[
|
2018-03-31 02:12:27 -07:00
|
|
|
|
|
2023-12-09 05:42:00 -07:00
|
|
|
{1:~ }|*2
|
2024-04-07 23:32:45 -07:00
|
|
|
{3: }|
|
2017-10-03 14:39:17 -07:00
|
|
|
]] .. result .. [[ |
|
2018-02-07 02:33:05 -07:00
|
|
|
f1 |
|
|
|
|
f2 |
|
|
|
|
f3 |
|
|
|
|
|
|
2024-04-07 23:32:45 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2018-02-07 02:33:05 -07:00
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('handles binary and multibyte data', function()
|
|
|
|
feed_command('!cat test/functional/fixtures/shell_data.txt')
|
|
|
|
screen.bell = false
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect {
|
|
|
|
grid = [[
|
2018-03-31 02:12:27 -07:00
|
|
|
|
|
2018-02-07 02:33:05 -07:00
|
|
|
{1:~ }|
|
2024-04-07 23:32:45 -07:00
|
|
|
{3: }|
|
2018-02-07 02:33:05 -07:00
|
|
|
:!cat test/functional/fixtures/shell_data.txt |
|
2024-04-07 23:32:45 -07:00
|
|
|
{18:^@^A^B^C^D^E^F^H} |
|
|
|
|
{18:^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_} |
|
|
|
|
ö 한글 {18:<a5><c3>} |
|
|
|
|
t {18:<ff>} |
|
2018-02-07 02:33:05 -07:00
|
|
|
|
|
2024-04-07 23:32:45 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2018-08-20 09:51:25 -07:00
|
|
|
]],
|
|
|
|
condition = function()
|
2018-02-07 02:33:05 -07:00
|
|
|
eq(true, screen.bell)
|
2018-08-20 09:51:25 -07:00
|
|
|
end,
|
|
|
|
}
|
2018-02-07 02:33:05 -07:00
|
|
|
end)
|
2018-02-08 07:11:56 -07:00
|
|
|
|
|
|
|
it('handles multibyte sequences split over buffer boundaries', function()
|
|
|
|
command('cd ' .. nvim_dir)
|
2022-11-21 17:13:30 -07:00
|
|
|
local cmd = is_os('win') and '!shell-test UTF-8 ' or '!./shell-test UTF-8'
|
2018-02-08 07:11:56 -07:00
|
|
|
feed_command(cmd)
|
|
|
|
-- Note: only the first example of split composed char works
|
|
|
|
screen:expect([[
|
2018-03-31 02:12:27 -07:00
|
|
|
|
|
2024-04-07 23:32:45 -07:00
|
|
|
{3: }|
|
2018-02-08 07:11:56 -07:00
|
|
|
:]] .. cmd .. [[ |
|
|
|
|
å |
|
|
|
|
ref: å̲ |
|
|
|
|
1: å̲ |
|
2023-11-06 06:52:27 -07:00
|
|
|
2: å ̲ |
|
|
|
|
3: å ̲ |
|
2018-02-08 07:11:56 -07:00
|
|
|
|
|
2024-04-07 23:32:45 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2018-02-08 07:11:56 -07:00
|
|
|
]])
|
|
|
|
end)
|
2018-02-07 02:33:05 -07:00
|
|
|
end)
|
2019-12-31 12:21:57 -07:00
|
|
|
if has_powershell() then
|
2019-10-10 01:16:02 -07:00
|
|
|
it('powershell supports literal strings', function()
|
|
|
|
set_shell_powershell()
|
2020-11-19 21:12:01 -07:00
|
|
|
local screen = Screen.new(45, 4)
|
2019-10-10 01:16:02 -07:00
|
|
|
screen:attach()
|
2019-10-10 21:30:20 -07:00
|
|
|
feed_command([[!'Write-Output $a']])
|
2020-11-19 21:12:01 -07:00
|
|
|
screen:expect([[
|
|
|
|
:!'Write-Output $a' |
|
|
|
|
Write-Output $a |
|
|
|
|
|
|
2024-03-22 03:02:52 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2020-11-19 21:12:01 -07:00
|
|
|
]])
|
2019-10-10 21:30:20 -07:00
|
|
|
feed_command([[!$a = 1; Write-Output '$a']])
|
2020-11-19 21:12:01 -07:00
|
|
|
screen:expect([[
|
|
|
|
:!$a = 1; Write-Output '$a' |
|
|
|
|
$a |
|
|
|
|
|
|
2024-03-22 03:02:52 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2020-11-19 21:12:01 -07:00
|
|
|
]])
|
2019-10-10 21:30:20 -07:00
|
|
|
feed_command([[!"Write-Output $a"]])
|
2020-11-19 21:12:01 -07:00
|
|
|
screen:expect([[
|
|
|
|
:!"Write-Output $a" |
|
|
|
|
Write-Output |
|
|
|
|
|
|
2024-03-22 03:02:52 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2020-11-19 21:12:01 -07:00
|
|
|
]])
|
2019-10-10 21:30:20 -07:00
|
|
|
feed_command([[!$a = 1; Write-Output "$a"]])
|
2020-11-19 21:12:01 -07:00
|
|
|
screen:expect([[
|
|
|
|
:!$a = 1; Write-Output "$a" |
|
|
|
|
1 |
|
|
|
|
|
|
2024-03-22 03:02:52 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2020-11-19 21:12:01 -07:00
|
|
|
]])
|
2022-11-21 17:13:30 -07:00
|
|
|
if is_os('win') then
|
2020-11-19 21:12:01 -07:00
|
|
|
feed_command([[!& 'cmd.exe' /c 'echo $a']])
|
|
|
|
screen:expect([[
|
|
|
|
:!& 'cmd.exe' /c 'echo $a' |
|
|
|
|
$a |
|
|
|
|
|
|
2024-03-22 03:02:52 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2020-11-19 21:12:01 -07:00
|
|
|
]])
|
|
|
|
else
|
|
|
|
feed_command([[!& '/bin/sh' -c 'echo ''$a''']])
|
|
|
|
screen:expect([[
|
|
|
|
:!& '/bin/sh' -c 'echo ''$a''' |
|
|
|
|
$a |
|
|
|
|
|
|
2024-03-22 03:02:52 -07:00
|
|
|
{6:Press ENTER or type command to continue}^ |
|
2020-11-19 21:12:01 -07:00
|
|
|
]])
|
|
|
|
end
|
2019-10-10 01:16:02 -07:00
|
|
|
end)
|
|
|
|
end
|
2017-05-10 06:04:49 -07:00
|
|
|
end)
|