mirror of
https://github.com/neovim/neovim.git
synced 2024-12-29 14:41:06 -07:00
d5328ea408
Problem: Several errors are not tested for.
Solution: Add tests. (Yegappan Lakshmanan, closes vim/vim#5892)
ee4e0c1e9a
Omit Test_range() change: reverted in patch 8.2.0615.
Cherry-pick Test_z_no_space_before_xxx() from patch 8.2.0195.
Cherry-pick Test_reverse_sort_uniq() change from patch 8.2.0183.
Make uniq() error behavior consistent with sort().
Cherry-pick Test_set_ttytype() change from patch 8.1.1826.
Cherry-pick quickfix checks from patch 8.1.2373 to test_preview.vim.
Test_viminfo_error() is applicable.
Cherry-pick E1058 from patch 8.2.0149 and port Test_deep_nest() to Lua.
563 lines
18 KiB
Lua
563 lines
18 KiB
Lua
local helpers = require('test.functional.helpers')(after_each)
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
local eq = helpers.eq
|
|
local feed = helpers.feed
|
|
local meths = helpers.meths
|
|
local clear = helpers.clear
|
|
local source = helpers.source
|
|
local command = helpers.command
|
|
local exc_exec = helpers.exc_exec
|
|
local pcall_err = helpers.pcall_err
|
|
local async_meths = helpers.async_meths
|
|
local NIL = helpers.NIL
|
|
|
|
local screen
|
|
|
|
before_each(function()
|
|
clear()
|
|
screen = Screen.new(25, 5)
|
|
screen:attach()
|
|
source([[
|
|
hi Test ctermfg=Red guifg=Red term=bold
|
|
function CustomCompl(...)
|
|
return 'TEST'
|
|
endfunction
|
|
function CustomListCompl(...)
|
|
return ['FOO']
|
|
endfunction
|
|
|
|
highlight RBP1 guibg=Red
|
|
highlight RBP2 guibg=Yellow
|
|
highlight RBP3 guibg=Green
|
|
highlight RBP4 guibg=Blue
|
|
let g:NUM_LVLS = 4
|
|
function Redraw()
|
|
redraw!
|
|
return ''
|
|
endfunction
|
|
cnoremap <expr> {REDRAW} Redraw()
|
|
function RainBowParens(cmdline)
|
|
let ret = []
|
|
let i = 0
|
|
let lvl = 0
|
|
while i < len(a:cmdline)
|
|
if a:cmdline[i] is# '('
|
|
call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)])
|
|
let lvl += 1
|
|
elseif a:cmdline[i] is# ')'
|
|
let lvl -= 1
|
|
call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)])
|
|
endif
|
|
let i += 1
|
|
endwhile
|
|
return ret
|
|
endfunction
|
|
]])
|
|
screen:set_default_attr_ids({
|
|
EOB={bold = true, foreground = Screen.colors.Blue1},
|
|
T={foreground=Screen.colors.Red},
|
|
RBP1={background=Screen.colors.Red},
|
|
RBP2={background=Screen.colors.Yellow},
|
|
RBP3={background=Screen.colors.Green},
|
|
RBP4={background=Screen.colors.Blue},
|
|
SEP={bold = true, reverse = true},
|
|
CONFIRM={bold = true, foreground = Screen.colors.SeaGreen4},
|
|
})
|
|
end)
|
|
|
|
describe('input()', function()
|
|
it('works with multiline prompts', function()
|
|
feed([[:call input("Test\nFoo")<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{SEP: }|
|
|
Test |
|
|
Foo^ |
|
|
]])
|
|
end)
|
|
it('works with multiline prompts and :echohl', function()
|
|
feed([[:echohl Test | call input("Test\nFoo")<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{SEP: }|
|
|
{T:Test} |
|
|
{T:Foo}^ |
|
|
]])
|
|
command('redraw!')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo}^ |
|
|
]])
|
|
end)
|
|
it('allows unequal numeric arguments when using multiple args', function()
|
|
command('echohl Test')
|
|
feed([[:call input(1, 2)<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}2^ |
|
|
]])
|
|
feed('<BS>')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}^ |
|
|
]])
|
|
end)
|
|
it('allows unequal numeric values when using {opts} dictionary', function()
|
|
command('echohl Test')
|
|
meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
|
|
feed([[:echo input(opts)<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}2^ |
|
|
]])
|
|
feed('<BS>')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}^ |
|
|
]])
|
|
feed('<Esc>')
|
|
screen:expect([[
|
|
^ |
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:3} |
|
|
]])
|
|
end)
|
|
it('works with redraw', function()
|
|
command('echohl Test')
|
|
meths.set_var('opts', {prompt='Foo>', default='Bar'})
|
|
feed([[:echo inputdialog(opts)<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Bar^ |
|
|
]])
|
|
command('mode')
|
|
screen:expect{grid=[[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Bar^ |
|
|
]], reset=true}
|
|
feed('<BS>')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Ba^ |
|
|
]])
|
|
command('mode')
|
|
screen:expect{grid=[[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Ba^ |
|
|
]], reset=true}
|
|
end)
|
|
it('allows omitting everything with dictionary argument', function()
|
|
command('echohl Test')
|
|
feed([[:call input({})<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
^ |
|
|
]])
|
|
end)
|
|
it('supports completion', function()
|
|
feed(':let var = input("", "", "custom,CustomCompl")<CR>')
|
|
feed('<Tab><CR>')
|
|
eq('TEST', meths.get_var('var'))
|
|
|
|
feed(':let var = input({"completion": "customlist,CustomListCompl"})<CR>')
|
|
feed('<Tab><CR>')
|
|
eq('FOO', meths.get_var('var'))
|
|
end)
|
|
it('supports cancelreturn', function()
|
|
feed(':let var = input({"cancelreturn": "BAR"})<CR>')
|
|
feed('<Esc>')
|
|
eq('BAR', meths.get_var('var'))
|
|
feed(':let var = input({"cancelreturn": []})<CR>')
|
|
feed('<Esc>')
|
|
eq({}, meths.get_var('var'))
|
|
feed(':let var = input({"cancelreturn": v:false})<CR>')
|
|
feed('<Esc>')
|
|
eq(false, meths.get_var('var'))
|
|
feed(':let var = input({"cancelreturn": v:null})<CR>')
|
|
feed('<Esc>')
|
|
eq(NIL, meths.get_var('var'))
|
|
end)
|
|
it('supports default string', function()
|
|
feed(':let var = input("", "DEF1")<CR>')
|
|
feed('<CR>')
|
|
eq('DEF1', meths.get_var('var'))
|
|
|
|
feed(':let var = input({"default": "DEF2"})<CR>')
|
|
feed('<CR>')
|
|
eq('DEF2', meths.get_var('var'))
|
|
end)
|
|
it('errors out on invalid inputs', function()
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call input([])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call input("", [])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call input("", "", [])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call input({"prompt": []})'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call input({"default": []})'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call input({"completion": []})'))
|
|
eq('Vim(call):E5050: {opts} must be the only argument',
|
|
exc_exec('call input({}, "default")'))
|
|
eq('Vim(call):E118: Too many arguments for function: input',
|
|
exc_exec('call input("prompt> ", "default", "file", "extra")'))
|
|
end)
|
|
it('supports highlighting', function()
|
|
command('nnoremap <expr> X input({"highlight": "RainBowParens"})[-1]')
|
|
feed([[X]])
|
|
feed('(())')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{RBP1:(}{RBP2:()}{RBP1:)}^ |
|
|
]])
|
|
end)
|
|
it('is not hidden by :silent', function()
|
|
feed([[:silent call input('Foo: ')<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{SEP: }|
|
|
Foo: ^ |
|
|
|
|
|
]])
|
|
feed('Bar')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{SEP: }|
|
|
Foo: Bar^ |
|
|
|
|
|
]])
|
|
feed('<CR>')
|
|
end)
|
|
end)
|
|
describe('inputdialog()', function()
|
|
it('works with multiline prompts', function()
|
|
feed([[:call inputdialog("Test\nFoo")<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{SEP: }|
|
|
Test |
|
|
Foo^ |
|
|
]])
|
|
end)
|
|
it('works with multiline prompts and :echohl', function()
|
|
feed([[:echohl Test | call inputdialog("Test\nFoo")<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{SEP: }|
|
|
{T:Test} |
|
|
{T:Foo}^ |
|
|
]])
|
|
command('redraw!')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo}^ |
|
|
]])
|
|
end)
|
|
it('allows unequal numeric arguments when using multiple args', function()
|
|
command('echohl Test')
|
|
feed([[:call inputdialog(1, 2)<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}2^ |
|
|
]])
|
|
feed('<BS>')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}^ |
|
|
]])
|
|
end)
|
|
it('allows unequal numeric values when using {opts} dictionary', function()
|
|
command('echohl Test')
|
|
meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
|
|
feed([[:echo input(opts)<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}2^ |
|
|
]])
|
|
feed('<BS>')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:1}^ |
|
|
]])
|
|
feed('<Esc>')
|
|
screen:expect([[
|
|
^ |
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:3} |
|
|
]])
|
|
end)
|
|
it('works with redraw', function()
|
|
command('echohl Test')
|
|
meths.set_var('opts', {prompt='Foo>', default='Bar'})
|
|
feed([[:echo input(opts)<CR>]])
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Bar^ |
|
|
]])
|
|
command('mode')
|
|
screen:expect{grid=[[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Bar^ |
|
|
]], reset=true}
|
|
feed('<BS>')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Ba^ |
|
|
]])
|
|
command('mode')
|
|
screen:expect{grid=[[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{T:Foo>}Ba^ |
|
|
]], reset=true}
|
|
end)
|
|
it('allows omitting everything with dictionary argument', function()
|
|
command('echohl Test')
|
|
feed(':echo inputdialog({})<CR>')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
^ |
|
|
]])
|
|
end)
|
|
it('supports completion', function()
|
|
feed(':let var = inputdialog({"completion": "customlist,CustomListCompl"})<CR>')
|
|
feed('<Tab><CR>')
|
|
eq('FOO', meths.get_var('var'))
|
|
end)
|
|
it('supports cancelreturn', function()
|
|
feed(':let var = inputdialog("", "", "CR1")<CR>')
|
|
feed('<Esc>')
|
|
eq('CR1', meths.get_var('var'))
|
|
|
|
feed(':let var = inputdialog({"cancelreturn": "BAR"})<CR>')
|
|
feed('<Esc>')
|
|
eq('BAR', meths.get_var('var'))
|
|
end)
|
|
it('supports default string', function()
|
|
feed(':let var = inputdialog("", "DEF1")<CR>')
|
|
feed('<CR>')
|
|
eq('DEF1', meths.get_var('var'))
|
|
|
|
feed(':let var = inputdialog({"default": "DEF2"})<CR>')
|
|
feed('<CR>')
|
|
eq('DEF2', meths.get_var('var'))
|
|
end)
|
|
it('errors out on invalid inputs', function()
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call inputdialog([])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call inputdialog("", [])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call inputdialog("", "", [])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call inputdialog({"prompt": []})'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call inputdialog({"default": []})'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
exc_exec('call inputdialog({"completion": []})'))
|
|
eq('Vim(call):E5050: {opts} must be the only argument',
|
|
exc_exec('call inputdialog({}, "default")'))
|
|
eq('Vim(call):E118: Too many arguments for function: inputdialog',
|
|
exc_exec('call inputdialog("prompt> ", "default", "file", "extra")'))
|
|
end)
|
|
it('supports highlighting', function()
|
|
command('nnoremap <expr> X inputdialog({"highlight": "RainBowParens"})[-1]')
|
|
feed([[X]])
|
|
feed('(())')
|
|
screen:expect([[
|
|
|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{EOB:~ }|
|
|
{RBP1:(}{RBP2:()}{RBP1:)}^ |
|
|
]])
|
|
end)
|
|
end)
|
|
|
|
describe('confirm()', function()
|
|
-- oldtest: Test_confirm()
|
|
it('works', function()
|
|
meths.set_option('more', false) -- Avoid hit-enter prompt
|
|
meths.set_option('laststatus', 2)
|
|
-- screen:expect() calls are needed to avoid feeding input too early
|
|
screen:expect({any = '%[No Name%]'})
|
|
|
|
async_meths.command([[let a = confirm('Press O to proceed')]])
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('o')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(1, meths.get_var('a'))
|
|
|
|
async_meths.command([[let a = 'Are you sure?'->confirm("&Yes\n&No")]])
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('y')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(1, meths.get_var('a'))
|
|
|
|
async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('n')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(2, meths.get_var('a'))
|
|
|
|
-- Not possible to match Vim's CTRL-C test here as CTRL-C always sets got_int in Nvim.
|
|
|
|
-- confirm() should return 0 when pressing ESC.
|
|
async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('<Esc>')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(0, meths.get_var('a'))
|
|
|
|
-- Default choice is returned when pressing <CR>.
|
|
async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('<CR>')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(1, meths.get_var('a'))
|
|
|
|
async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 2)]])
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('<CR>')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(2, meths.get_var('a'))
|
|
|
|
async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 0)]])
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('<CR>')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(0, meths.get_var('a'))
|
|
|
|
-- Test with the {type} 4th argument
|
|
for _, type in ipairs({'Error', 'Question', 'Info', 'Warning', 'Generic'}) do
|
|
async_meths.command(([[let a = confirm('Are you sure?', "&Yes\n&No", 1, '%s')]]):format(type))
|
|
screen:expect({any = '{CONFIRM:.+: }'})
|
|
feed('y')
|
|
screen:expect({any = '%[No Name%]'})
|
|
eq(1, meths.get_var('a'))
|
|
end
|
|
|
|
eq('Vim(call):E730: using List as a String',
|
|
pcall_err(command, 'call confirm([])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
pcall_err(command, 'call confirm("Are you sure?", [])'))
|
|
eq('Vim(call):E745: Using a List as a Number',
|
|
pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", [])'))
|
|
eq('Vim(call):E730: using List as a String',
|
|
pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", 0, [])'))
|
|
end)
|
|
|
|
it("shows dialog even if :silent #8788", function()
|
|
command("autocmd BufNewFile * call confirm('test')")
|
|
|
|
local function check_and_clear(edit_line)
|
|
screen:expect([[
|
|
|
|
|
{SEP: }|
|
|
]]..edit_line..[[
|
|
{CONFIRM:test} |
|
|
{CONFIRM:[O]k: }^ |
|
|
]])
|
|
feed('<cr>')
|
|
command('redraw')
|
|
command('bdelete!')
|
|
end
|
|
|
|
-- With shortmess-=F
|
|
command('set shortmess-=F')
|
|
feed(':edit foo<cr>')
|
|
check_and_clear('"foo" [New] |\n')
|
|
|
|
-- With shortmess+=F
|
|
command('set shortmess+=F')
|
|
feed(':edit foo<cr>')
|
|
check_and_clear(':edit foo |\n')
|
|
|
|
-- With :silent
|
|
feed(':silent edit foo<cr>')
|
|
check_and_clear(':silent edit foo |\n')
|
|
|
|
-- With API (via eval/VimL) call and shortmess+=F
|
|
feed(':call nvim_command("edit x")<cr>')
|
|
check_and_clear(':call nvim_command("edit |\n')
|
|
|
|
async_meths.command('edit x')
|
|
check_and_clear(' |\n')
|
|
end)
|
|
end)
|