mirror of
https://github.com/neovim/neovim.git
synced 2025-09-11 22:08:18 +00:00

Avoid clearing the screen in most situations. NOT_VALID should be equivalent to CLEAR unless some external force messed up the terminal, for these situations <c-l> and :mode will still clear the screen. Also eliminate some obsolete code in screen.c, that dealt with that in vim drawing window 1 can mess up window 2, but this never happens in nvim. But what about slow terminals? There is two common meanings in which a terminal is said to be "slow": Most commonly (and in the sense of vim:s nottyfast) it means low bandwidth for sending bytes from nvim to the terminal. If the screen is very similar before and after the update_screen(CLEAR) this change should reduce bandwidth. If the screen is quite different, but there is no new regions of contiguous whitespace, clearing doesn't reduce bandwidth significantly. If the new screen contains a lot of whitespace, it will depend of if vsplits are used or not: as long as there is no vsplits, ce is used to cheaply clear the rest of the line, so full-screen clear is not needed to reduce bandwith. However a left vsplit currently needs to be padded with whitespace all the way to the separator. It is possible ec (clear N chars) can be used to reduce bandwidth here if this is a problem. (All of this assumes that one doesn't set Normal guibg=... on a non-BCE terminal, if you do you are doomed regardless of this change). Slow can also mean that drawing pixels on the screen is slow. E-ink screens is a recent example. Avoiding clearing and redrawing the unchanged part of the screen will always improve performance in these cases.
442 lines
14 KiB
Lua
442 lines
14 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 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},
|
|
})
|
|
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'))
|
|
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({"cancelreturn": []})'))
|
|
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({"cancelreturn": []})'))
|
|
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)
|