neovim/test/functional/ui/cmdline_highlight_spec.lua
bfredl a9a48d6b5f refactor(message): simplify msg_puts_display and use batched grid updates
msg_puts_display was more complex than necessary in nvim, as in
nvim, it no longer talks directly with a terminal.

In particular we don't need to scroll the grid before emiting the last
char. The TUI already takes care of things like that, for terminals
where it matters.
2023-10-03 15:20:09 +02:00

992 lines
37 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 clear = helpers.clear
local meths = helpers.meths
local funcs = helpers.funcs
local source = helpers.source
local exec_capture = helpers.exec_capture
local dedent = helpers.dedent
local command = helpers.command
local curbufmeths = helpers.curbufmeths
local screen
-- Bug in input() handling: :redraw! will erase the whole prompt up until
-- user types something. It exists in Vim as well, so using `h<BS>` as
-- a workaround.
local function redraw_input()
feed('{REDRAW}h<BS>')
end
before_each(function()
clear()
screen = Screen.new(40, 8)
screen:attach()
source([[
highlight RBP1 guibg=Red
highlight RBP2 guibg=Yellow
highlight RBP3 guibg=Green
highlight RBP4 guibg=Blue
let g:NUM_LVLS = 4
function Redraw()
mode
return "\<Ignore>"
endfunction
let g:id = ''
cnoremap <expr> {REDRAW} Redraw()
function DoPrompt(do_return) abort
let id = g:id
let Cb = g:Nvim_color_input{g:id}
let out = input({'prompt': ':', 'highlight': Cb})
let g:out{id} = out
return (a:do_return ? out : "\<Ignore>")
endfunction
nnoremap <expr> {PROMPT} DoPrompt(0)
cnoremap <expr> {PROMPT} DoPrompt(1)
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
function SplitMultibyteStart(cmdline)
let ret = []
let i = 0
while i < len(a:cmdline)
let char = nr2char(char2nr(a:cmdline[i:]))
if a:cmdline[i:i + len(char) - 1] is# char
if len(char) > 1
call add(ret, [i + 1, i + len(char), 'RBP2'])
endif
let i += len(char)
else
let i += 1
endif
endwhile
return ret
endfunction
function SplitMultibyteEnd(cmdline)
let ret = []
let i = 0
while i < len(a:cmdline)
let char = nr2char(char2nr(a:cmdline[i:]))
if a:cmdline[i:i + len(char) - 1] is# char
if len(char) > 1
call add(ret, [i, i + 1, 'RBP1'])
endif
let i += len(char)
else
let i += 1
endif
endwhile
return ret
endfunction
function Echoing(cmdline)
echo 'HERE'
return v:_null_list
endfunction
function Echoning(cmdline)
echon 'HERE'
return v:_null_list
endfunction
function Echomsging(cmdline)
echomsg 'HERE'
return v:_null_list
endfunction
function Echoerring(cmdline)
echoerr 'HERE'
return v:_null_list
endfunction
function Redrawing(cmdline)
redraw!
return v:_null_list
endfunction
function Throwing(cmdline)
throw "ABC"
return v:_null_list
endfunction
function Halting(cmdline)
while 1
endwhile
endfunction
function ReturningGlobal(cmdline)
return g:callback_return
endfunction
function ReturningGlobal2(cmdline)
return g:callback_return[:len(a:cmdline)-1]
endfunction
function ReturningGlobalN(n, cmdline)
return g:callback_return{a:n}
endfunction
let g:recording_calls = []
function Recording(cmdline)
call add(g:recording_calls, a:cmdline)
return []
endfunction
]])
screen:set_default_attr_ids({
RBP1={background = Screen.colors.Red},
RBP2={background = Screen.colors.Yellow},
RBP3={background = Screen.colors.Green},
RBP4={background = Screen.colors.Blue},
EOB={bold = true, foreground = Screen.colors.Blue1},
ERR={foreground = Screen.colors.Grey100, background = Screen.colors.Red},
SK={foreground = Screen.colors.Blue},
PE={bold = true, foreground = Screen.colors.SeaGreen4},
NUM={foreground = Screen.colors.Blue2},
NPAR={foreground = Screen.colors.Yellow},
SQ={foreground = Screen.colors.Blue3},
SB={foreground = Screen.colors.Blue4},
E={foreground = Screen.colors.Red, background = Screen.colors.Blue},
M={bold = true},
MSEP={bold = true, reverse = true};
})
end)
local function set_color_cb(funcname, callback_return, id)
meths.set_var('id', id or '')
if id and id ~= '' and funcs.exists('*' .. funcname .. 'N') then
command(('let g:Nvim_color_input%s = {cmdline -> %sN(%s, cmdline)}'):format(
id, funcname, id))
if callback_return then
meths.set_var('callback_return' .. id, callback_return)
end
else
meths.set_var('Nvim_color_input', funcname)
if callback_return then
meths.set_var('callback_return', callback_return)
end
end
end
local function start_prompt(text)
feed('{PROMPT}' .. (text or ''))
end
describe('Command-line coloring', function()
it('works', function()
set_color_cb('RainBowParens')
meths.set_option_value('more', false, {})
start_prompt()
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:^ |
]])
feed('e')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:e^ |
]])
feed('cho ')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo ^ |
]])
feed('(')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}^ |
]])
feed('(')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}{RBP2:(}^ |
]])
feed('42')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}{RBP2:(}42^ |
]])
feed('))')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}{RBP2:(}42{RBP2:)}{RBP1:)}^ |
]])
feed('<BS>')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}{RBP2:(}42{RBP2:)}^ |
]])
redraw_input()
screen:expect{grid=[[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}{RBP2:(}42{RBP2:)}^ |
]], reset=true}
end)
for _, func_part in ipairs({'', 'n', 'msg'}) do
it('disables :echo' .. func_part .. ' messages', function()
set_color_cb('Echo' .. func_part .. 'ing')
start_prompt('echo')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo^ |
]])
end)
end
it('does the right thing when hl start appears to split multibyte char',
function()
set_color_cb('SplitMultibyteStart')
start_prompt('echo "«')
screen:expect{grid=[[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:echo " |
{ERR:E5405: Chunk 0 start 7 splits multibyte }|
{ERR:character} |
:echo "«^ |
]]}
feed('»')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:echo " |
{ERR:E5405: Chunk 0 start 7 splits multibyte }|
{ERR:character} |
:echo "«»^ |
]])
end)
it('does the right thing when hl end appears to split multibyte char',
function()
set_color_cb('SplitMultibyteEnd')
start_prompt('echo "«')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:echo " |
{ERR:E5406: Chunk 0 end 7 splits multibyte ch}|
{ERR:aracter} |
:echo "«^ |
]])
end)
it('does the right thing when erroring', function()
set_color_cb('Echoerring')
start_prompt('e')
screen:expect([[
|
{EOB:~ }|
{MSEP: }|
: |
{ERR:E5407: Callback has thrown an exception:}|
{ERR: function DoPrompt[3]..Echoerring, line }|
{ERR:1: Vim(echoerr):HERE} |
:e^ |
]])
end)
it('silences :echo', function()
set_color_cb('Echoing')
start_prompt('e')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:e^ |
]])
eq('', exec_capture('messages'))
end)
it('silences :echon', function()
set_color_cb('Echoning')
start_prompt('e')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:e^ |
]])
eq('', exec_capture('messages'))
end)
it('silences :echomsg', function()
set_color_cb('Echomsging')
start_prompt('e')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:e^ |
]])
eq('', exec_capture('messages'))
end)
it('does the right thing when throwing', function()
set_color_cb('Throwing')
start_prompt('e')
screen:expect([[
|
{EOB:~ }|
{MSEP: }|
: |
{ERR:E5407: Callback has thrown an exception:}|
{ERR: function DoPrompt[3]..Throwing, line 1:}|
{ERR: ABC} |
:e^ |
]])
end)
it('stops executing callback after a number of errors', function()
set_color_cb('SplitMultibyteStart')
start_prompt('let x = "«»«»«»«»«»"')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:let x = " |
{ERR:E5405: Chunk 0 start 10 splits multibyte}|
{ERR: character} |
:let x = "«»«»«»«»«»"^ |
]])
feed('\n')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
|
]])
feed('\n')
eq('let x = "«»«»«»«»«»"', meths.get_var('out'))
local msg = '\nE5405: Chunk 0 start 10 splits multibyte character'
eq(msg:rep(1), funcs.execute('messages'))
end)
it('allows interrupting callback with <C-c>', function()
set_color_cb('Halting')
start_prompt('echo 42')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
|
]])
screen:sleep(500)
feed('<C-c>')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
: |
{ERR:E5407: Callback has thrown an exception:}|
{ERR: Keyboard interrupt} |
:echo 42^ |
]])
redraw_input()
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo 42^ |
]])
feed('\n')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo 42 |
]])
feed('\n')
eq('echo 42', meths.get_var('out'))
feed('<C-c>')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
Type :qa and pre...nter> to exit Nvim |
]])
end)
it('works fine with NUL, NL, CR', function()
set_color_cb('RainBowParens')
start_prompt('echo ("<C-v><CR><C-v><Nul><C-v><NL>")')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}"{SK:^M^@^@}"{RBP1:)}^ |
]])
end)
it('errors out when callback returns something wrong', function()
command('cnoremap + ++')
set_color_cb('ReturningGlobal', '')
start_prompt('#')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
: |
{ERR:E5400: Callback should return list} |
:#^ |
]])
feed('<CR><CR><CR>')
set_color_cb('ReturningGlobal', {{0, 1, 'Normal'}, 42})
start_prompt('#')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
: |
{ERR:E5401: List item 1 is not a List} |
:#^ |
]])
feed('<CR><CR><CR>')
set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {1}})
start_prompt('+')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:+ |
{ERR:E5402: List item 1 has incorrect length:}|
{ERR: 1 /= 3} |
:++^ |
]])
feed('<CR><CR><CR>')
set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {2, 3, 'Normal'}})
start_prompt('+')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:+ |
{ERR:E5403: Chunk 1 start 2 not in range [1, }|
{ERR:2)} |
:++^ |
]])
feed('<CR><CR><CR>')
set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {1, 3, 'Normal'}})
start_prompt('+')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:+ |
{ERR:E5404: Chunk 1 end 3 not in range (1, 2]}|
:++^ |
]])
end)
it('does not error out when called from a errorred out cycle', function()
set_color_cb('ReturningGlobal', {{0, 1, 'Normal'}})
feed(dedent([[
:set regexpengine=2
:for pat in [' \ze*', ' \zs*']
: try
: let l = matchlist('x x', pat)
: $put =input({'prompt':'>','highlight':'ReturningGlobal'})
:
: $put ='E888 NOT detected for ' . pat
: catch
: $put =input({'prompt':'>','highlight':'ReturningGlobal'})
:
: $put ='E888 detected for ' . pat
: endtry
:endfor
:
:
:
:
:
:
]]))
eq({'', ':', 'E888 detected for \\ze*', ':', 'E888 detected for \\zs*'},
curbufmeths.get_lines(0, -1, false))
eq('', funcs.execute('messages'))
end)
it('allows nesting input()s', function()
set_color_cb('ReturningGlobal', {{0, 1, 'RBP1'}}, '')
start_prompt('1')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:{RBP1:1}^ |
]])
set_color_cb('ReturningGlobal', {{0, 1, 'RBP2'}}, '1')
start_prompt('2')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:{RBP2:2}^ |
]])
set_color_cb('ReturningGlobal', {{0, 1, 'RBP3'}}, '2')
start_prompt('3')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:{RBP3:3}^ |
]])
set_color_cb('ReturningGlobal', {{0, 1, 'RBP4'}}, '3')
start_prompt('4')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:{RBP4:4}^ |
]])
feed('<CR>')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:{RBP3:3}4^ |
]])
feed('<CR>')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:{RBP2:2}34^ |
]])
feed('<CR>')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:{RBP1:1}234^ |
]])
feed('<CR><CR><C-l>')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
|
]])
eq('1234', meths.get_var('out'))
eq('234', meths.get_var('out1'))
eq('34', meths.get_var('out2'))
eq('4', meths.get_var('out3'))
eq(0, funcs.exists('g:out4'))
end)
it('runs callback with the same data only once', function()
local function new_recording_calls(...)
eq({...}, meths.get_var('recording_calls'))
meths.set_var('recording_calls', {})
end
set_color_cb('Recording')
start_prompt('')
-- Regression test. Disambiguation:
--
-- new_recording_calls(expected_result) -- (actual_before_fix)
--
feed('a')
new_recording_calls('a') -- ('a', 'a')
feed('b')
new_recording_calls('ab') -- ('a', 'ab', 'ab')
feed('c')
new_recording_calls('abc') -- ('ab', 'abc', 'abc')
feed('<BS>')
new_recording_calls('ab') -- ('abc', 'ab', 'ab')
feed('<BS>')
new_recording_calls('a') -- ('ab', 'a', 'a')
feed('<BS>')
new_recording_calls() -- ('a')
feed('<CR><CR>')
eq('', meths.get_var('out'))
end)
it('does not crash when callback has caught not-a-editor-command exception',
function()
source([[
function CaughtExc(cmdline) abort
try
gibberish
catch
" Do nothing
endtry
return []
endfunction
]])
set_color_cb('CaughtExc')
start_prompt('1')
eq(1, meths.eval('1'))
end)
end)
describe('Ex commands coloring', function()
it('works', function()
meths.set_var('Nvim_color_cmdline', 'RainBowParens')
feed(':echo (((1)))')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:echo {RBP1:(}{RBP2:(}{RBP3:(}1{RBP3:)}{RBP2:)}{RBP1:)}^ |
]])
end)
it('still executes command-line even if errored out', function()
meths.set_var('Nvim_color_cmdline', 'SplitMultibyteStart')
feed(':let x = "«"\n')
eq('«', meths.get_var('x'))
local msg = 'E5405: Chunk 0 start 10 splits multibyte character'
eq('\n'..msg, funcs.execute('messages'))
end)
it('does not error out when called from a errorred out cycle', function()
-- Apparently when there is a cycle in which one of the commands errors out
-- this error may be caught by color_cmdline before it is presented to the
-- user.
feed(dedent([[
:set regexpengine=2
:for pat in [' \ze*', ' \zs*']
: try
: let l = matchlist('x x', pat)
: $put ='E888 NOT detected for ' . pat
: catch
: $put ='E888 detected for ' . pat
: endtry
:endfor
]]))
eq({'', 'E888 detected for \\ze*', 'E888 detected for \\zs*'},
curbufmeths.get_lines(0, -1, false))
eq('', funcs.execute('messages'))
end)
it('does not crash when using `n` in debug mode', function()
feed(':debug execute "echo 1"\n')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
Entering Debug mode. Type "cont" to con|
tinue. |
cmd: execute "echo 1" |
>^ |
]])
feed('n\n')
screen:expect([[
|
{MSEP: }|
Entering Debug mode. Type "cont" to con|
tinue. |
cmd: execute "echo 1" |
>n |
1 |
{PE:Press ENTER or type command to continue}^ |
]])
feed('\n')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
|
]])
end)
it('mapping error does not cancel prompt', function()
command("cnoremap <expr> x execute('throw 42')[-1]")
feed(':#x')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{MSEP: }|
:# |
{ERR:Error detected while processing :} |
{ERR:E605: Exception not caught: 42} |
:#^ |
]])
feed('<CR>')
screen:expect([[
|
{EOB:~ }|
{MSEP: }|
:# |
{ERR:Error detected while processing :} |
{ERR:E605: Exception not caught: 42} |
{ERR:E749: Empty buffer} |
{PE:Press ENTER or type command to continue}^ |
]])
feed('<CR>')
eq('Error detected while processing :\nE605: Exception not caught: 42\nE749: Empty buffer',
exec_capture('messages'))
end)
it('errors out when failing to get callback', function()
meths.set_var('Nvim_color_cmdline', 42)
feed(':#')
screen:expect([[
|
{EOB:~ }|
{MSEP: }|
: |
{ERR:E5408: Unable to get g:Nvim_color_cmdlin}|
{ERR:e callback: Vim:E6000: Argument is not a}|
{ERR: function or function name} |
:#^ |
]])
end)
end)
describe('Expressions coloring support', function()
it('works', function()
meths.command('hi clear NvimNumber')
meths.command('hi clear NvimNestingParenthesis')
meths.command('hi NvimNumber guifg=Blue2')
meths.command('hi NvimNestingParenthesis guifg=Yellow')
feed(':echo <C-r>=(((1)))')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
={NPAR:(((}{NUM:1}{NPAR:)))}^ |
]])
end)
it('does not use Nvim_color_expr', function()
meths.set_var('Nvim_color_expr', 42)
-- Used to error out due to failing to get callback.
meths.command('hi clear NvimNumber')
meths.command('hi NvimNumber guifg=Blue2')
feed(':<C-r>=1')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
={NUM:1}^ |
]])
end)
it('works correctly with non-ASCII and control characters', function()
meths.command('hi clear NvimStringBody')
meths.command('hi clear NvimStringQuote')
meths.command('hi clear NvimInvalid')
meths.command('hi NvimStringQuote guifg=Blue3')
meths.command('hi NvimStringBody guifg=Blue4')
meths.command('hi NvimInvalid guifg=Red guibg=Blue')
feed('i<C-r>="«»"«»')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
={SQ:"}{SB:«»}{SQ:"}{E:«»}^ |
]])
feed('<C-c>')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{M:-- INSERT --} |
]])
feed('<Esc>')
screen:expect([[
^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
|
]])
feed(':<C-\\>e"<C-v><C-x>"<C-v><C-x>')
-- TODO(ZyX-I): Parser highlighting should not override special character
-- highlighting.
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
={SQ:"}{SB:^X}{SQ:"}{ERR:^X}^ |
]])
feed('<C-c>')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
:^ |
]])
funcs.setreg('a', {'\192'})
feed('<C-r>="<C-r><C-r>a"<C-r><C-r>a"foo"')
screen:expect([[
|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
={SQ:"}{SB:<c0>}{SQ:"}{E:<c0>"}{SB:foo}{E:"}^ |
]])
end)
end)