mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 21:25:04 -07:00
e61228a214
Before calling "attach" a screen object is just a dummy container for (row, col) values whose purpose is to be sent as part of the "attach" function call anyway. Just create the screen in an attached state directly. Keep the complete (row, col, options) config together. It is still completely valid to later detach and re-attach as needed, including to another session.
337 lines
10 KiB
Lua
337 lines
10 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
local eq = t.eq
|
|
local eval = n.eval
|
|
local clear = n.clear
|
|
local source = n.source
|
|
local exc_exec = n.exc_exec
|
|
local pcall_err = t.pcall_err
|
|
local fn = n.fn
|
|
local command = n.command
|
|
local feed = n.feed
|
|
local is_os = t.is_os
|
|
|
|
describe('execute()', function()
|
|
before_each(clear)
|
|
|
|
it('captures the same result as :redir', function()
|
|
command([[
|
|
echomsg 'foo 1'
|
|
echomsg 'foo 2'
|
|
redir => g:__redir_output
|
|
silent! messages
|
|
redir END
|
|
]])
|
|
eq(eval('g:__redir_output'), fn.execute('messages'))
|
|
end)
|
|
|
|
it('captures the concatenated outputs of a List of commands', function()
|
|
eq('foobar', fn.execute({ 'echon "foo"', 'echon "bar"' }))
|
|
eq('\nfoo\nbar', fn.execute({ 'echo "foo"', 'echo "bar"' }))
|
|
end)
|
|
|
|
it('supports nested execute("execute(...)")', function()
|
|
eq('42', fn.execute([[echon execute("echon execute('echon 42')")]]))
|
|
end)
|
|
|
|
it('supports nested :redir to a variable', function()
|
|
source([[
|
|
function! g:Foo()
|
|
let a = ''
|
|
redir => a
|
|
silent echon "foo"
|
|
redir END
|
|
return a
|
|
endfunction
|
|
function! g:Bar()
|
|
let a = ''
|
|
redir => a
|
|
silent echon "bar1"
|
|
call g:Foo()
|
|
silent echon "bar2"
|
|
redir END
|
|
silent echon "bar3"
|
|
return a
|
|
endfunction
|
|
]])
|
|
eq('top1bar1foobar2bar3', fn.execute('echon "top1"|call g:Bar()'))
|
|
end)
|
|
|
|
it('supports nested :redir to a register', function()
|
|
source([[
|
|
let @a = ''
|
|
function! g:Foo()
|
|
redir @a>>
|
|
silent echon "foo"
|
|
redir END
|
|
return @a
|
|
endfunction
|
|
function! g:Bar()
|
|
redir @a>>
|
|
silent echon "bar1"
|
|
call g:Foo()
|
|
silent echon "bar2"
|
|
redir END
|
|
silent echon "bar3"
|
|
return @a
|
|
endfunction
|
|
]])
|
|
eq('top1bar1foobar2bar3', fn.execute('echon "top1"|call g:Bar()'))
|
|
-- :redir itself doesn't nest, so the redirection ends in g:Foo
|
|
eq('bar1foo', eval('@a'))
|
|
end)
|
|
|
|
it('captures a transformed string', function()
|
|
eq('^A', fn.execute('echon "\\<C-a>"'))
|
|
end)
|
|
|
|
it('returns empty string if the argument list is empty', function()
|
|
eq('', fn.execute({}))
|
|
eq(0, exc_exec('let g:ret = execute(v:_null_list)'))
|
|
eq('', eval('g:ret'))
|
|
end)
|
|
|
|
it('captures errors', function()
|
|
local ret
|
|
ret = exc_exec('call execute(v:_null_dict)')
|
|
eq('Vim(call):E731: Using a Dictionary as a String', ret)
|
|
ret = exc_exec('call execute(function("tr"))')
|
|
eq('Vim(call):E729: Using a Funcref as a String', ret)
|
|
ret = exc_exec('call execute(["echo 42", v:_null_dict, "echo 44"])')
|
|
eq('Vim:E731: Using a Dictionary as a String', ret)
|
|
ret = exc_exec('call execute(["echo 42", function("tr"), "echo 44"])')
|
|
eq('Vim:E729: Using a Funcref as a String', ret)
|
|
end)
|
|
|
|
it('captures output with highlights', function()
|
|
eq(
|
|
'\nErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red',
|
|
eval('execute("hi ErrorMsg")')
|
|
)
|
|
end)
|
|
|
|
it('does not corrupt the command display #5422', function()
|
|
local screen = Screen.new(70, 7)
|
|
feed(':echo execute("hi ErrorMsg")<CR>')
|
|
screen:expect(
|
|
[[
|
|
|
|
|
{1:~ }|*2
|
|
{2: }|
|
|
|
|
|
ErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red |
|
|
{3:Press ENTER or type command to continue}^ |
|
|
]],
|
|
{
|
|
[1] = { bold = true, foreground = Screen.colors.Blue1 },
|
|
[2] = { bold = true, reverse = true },
|
|
[3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
|
|
}
|
|
)
|
|
feed('<CR>')
|
|
end)
|
|
|
|
it('places cursor correctly #6035', function()
|
|
local screen = Screen.new(40, 6)
|
|
source([=[
|
|
" test 1: non-silenced output goes as usual
|
|
function! Test1()
|
|
echo 1234
|
|
let x = execute('echon "abcdef"', '')
|
|
echon 'ABCD'
|
|
endfunction
|
|
|
|
" test 2: silenced output does not affect ui
|
|
function! Test2()
|
|
echo 1234
|
|
let x = execute('echon "abcdef"', 'silent')
|
|
echon 'ABCD'
|
|
endfunction
|
|
|
|
" test 3: silenced! error does not affect ui
|
|
function! Test3()
|
|
echo 1234
|
|
let x = execute('echoerr "abcdef"', 'silent!')
|
|
echon 'ABCDXZYZ'
|
|
endfunction
|
|
|
|
" test 4: silenced echoerr goes as usual
|
|
" bug here
|
|
function! Test4()
|
|
echo 1234
|
|
let x = execute('echoerr "abcdef"', 'silent')
|
|
echon 'ABCD'
|
|
endfunction
|
|
|
|
" test 5: silenced! echoerr does not affect ui
|
|
function! Test5()
|
|
echo 1234
|
|
let x = execute('echoerr "abcdef"', 'silent!')
|
|
echon 'ABCD'
|
|
endfunction
|
|
|
|
" test 6: silenced error goes as usual
|
|
function! Test6()
|
|
echo 1234
|
|
let x = execute('echo undefined', 'silent')
|
|
echon 'ABCD'
|
|
endfunction
|
|
|
|
" test 7: existing error does not mess the result
|
|
function! Test7()
|
|
" display from Test6() is still visible
|
|
" why does the "abcdef" goes into a newline
|
|
let x = execute('echon "abcdef"', '')
|
|
echon 'ABCD'
|
|
endfunction
|
|
]=])
|
|
|
|
feed([[:call Test1()<cr>]])
|
|
screen:expect([[
|
|
^ |
|
|
{1:~ }|*4
|
|
ABCD |
|
|
]])
|
|
|
|
feed([[:call Test2()<cr>]])
|
|
screen:expect([[
|
|
^ |
|
|
{1:~ }|*4
|
|
1234ABCD |
|
|
]])
|
|
|
|
feed([[:call Test3()<cr>]])
|
|
screen:expect([[
|
|
^ |
|
|
{1:~ }|*4
|
|
1234ABCDXZYZ |
|
|
]])
|
|
|
|
feed([[:call Test4()<cr>]])
|
|
-- unexpected: need to fix
|
|
-- echoerr does not set did_emsg
|
|
-- "ef" was overwritten since msg_col was recovered wrongly
|
|
screen:expect([[
|
|
1234 |
|
|
{9:Error detected while processing function}|
|
|
{9: Test4:} |
|
|
{8:line 2:} |
|
|
{9:abcd}ABCD |
|
|
{6:Press ENTER or type command to continue}^ |
|
|
]])
|
|
|
|
feed([[<cr>]]) -- to clear screen
|
|
feed([[:call Test5()<cr>]])
|
|
screen:expect([[
|
|
^ |
|
|
{1:~ }|*4
|
|
1234ABCD |
|
|
]])
|
|
|
|
feed([[:call Test6()<cr>]])
|
|
screen:expect([[
|
|
|
|
|
{9:Error detected while processing function}|
|
|
{9: Test6:} |
|
|
{8:line 2:} |
|
|
{9:E121}ABCD |
|
|
{6:Press ENTER or type command to continue}^ |
|
|
]])
|
|
|
|
feed([[:call Test7()<cr>]])
|
|
screen:expect([[
|
|
{9:Error detected while processing function}|
|
|
{9: Test6:} |
|
|
{8:line 2:} |
|
|
{9:E121}ABCD |
|
|
ABCD |
|
|
{6:Press ENTER or type command to continue}^ |
|
|
]])
|
|
end)
|
|
|
|
-- This deviates from vim behavior, but is consistent
|
|
-- with how nvim currently displays the output.
|
|
it('captures shell-command output', function()
|
|
local win_lf = is_os('win') and '\13' or ''
|
|
eq('\n:!echo foo\r\n\nfoo' .. win_lf .. '\n', fn.execute('!echo foo'))
|
|
end)
|
|
|
|
describe('{silent} argument', function()
|
|
it('captures & displays output for ""', function()
|
|
local screen = Screen.new(40, 5)
|
|
command('let g:mes = execute("echon 42", "")')
|
|
screen:expect([[
|
|
^ |
|
|
{1:~ }|*3
|
|
42 |
|
|
]])
|
|
eq('42', eval('g:mes'))
|
|
end)
|
|
|
|
it('gives E493 instead of prompting on backwards range for ""', function()
|
|
command('split')
|
|
eq(
|
|
'Vim(windo):E493: Backwards range given: 2,1windo echo',
|
|
pcall_err(fn.execute, '2,1windo echo', '')
|
|
)
|
|
eq(
|
|
'Vim(windo):E493: Backwards range given: 2,1windo echo',
|
|
pcall_err(fn.execute, { '2,1windo echo' }, '')
|
|
)
|
|
end)
|
|
|
|
it('captures but does not display output for "silent"', function()
|
|
local screen = Screen.new(40, 5)
|
|
command('let g:mes = execute("echon 42")')
|
|
screen:expect([[
|
|
^ |
|
|
{1:~ }|*3
|
|
|
|
|
]])
|
|
eq('42', eval('g:mes'))
|
|
|
|
command('let g:mes = execute("echon 13", "silent")')
|
|
screen:expect {
|
|
grid = [[
|
|
^ |
|
|
{1:~ }|*3
|
|
|
|
|
]],
|
|
unchanged = true,
|
|
}
|
|
eq('13', eval('g:mes'))
|
|
end)
|
|
|
|
it('suppresses errors for "silent!"', function()
|
|
eq(0, exc_exec('let g:mes = execute(0.0, "silent!")'))
|
|
eq('', eval('g:mes'))
|
|
|
|
eq(0, exc_exec('let g:mes = execute("echon add(1, 1)", "silent!")'))
|
|
eq('1', eval('g:mes'))
|
|
|
|
eq(0, exc_exec('let g:mes = execute(["echon 42", "echon add(1, 1)"], "silent!")'))
|
|
eq('421', eval('g:mes'))
|
|
end)
|
|
|
|
it('propagates errors for "" and "silent"', function()
|
|
local ret
|
|
ret = exc_exec('call execute(v:_null_dict, "silent")')
|
|
eq('Vim(call):E731: Using a Dictionary as a String', ret)
|
|
|
|
ret = exc_exec('call execute("echo add(1, 1)", "")')
|
|
eq('Vim(echo):E897: List or Blob required', ret)
|
|
|
|
ret = exc_exec('call execute(["echon 42", "echo add(1, 1)"], "")')
|
|
eq('Vim(echo):E897: List or Blob required', ret)
|
|
|
|
ret = exc_exec('call execute("echo add(1, 1)", "silent")')
|
|
eq('Vim(echo):E897: List or Blob required', ret)
|
|
|
|
ret = exc_exec('call execute(["echon 42", "echo add(1, 1)"], "silent")')
|
|
eq('Vim(echo):E897: List or Blob required', ret)
|
|
end)
|
|
end)
|
|
end)
|