aboutsummaryrefslogtreecommitdiff
path: root/test/functional/ui
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2017-12-03 16:49:30 +0300
committerZyX <kp-pav@yandex.ru>2017-12-03 16:49:30 +0300
commitc49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57 (patch)
treeb7e59c416d1435725c65f8952b6e55c70544d97e /test/functional/ui
parent62108c3b0be46936c83f6d4c98b44ceb5e6f77fd (diff)
parent27a577586eace687c47e7398845178208cae524a (diff)
downloadrneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.gz
rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.bz2
rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.zip
Merge branch 'master' into s-dash-stdin
Diffstat (limited to 'test/functional/ui')
-rw-r--r--test/functional/ui/bufhl_spec.lua50
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua893
-rw-r--r--test/functional/ui/cmdline_spec.lua525
-rw-r--r--test/functional/ui/cursor_spec.lua246
-rw-r--r--test/functional/ui/highlight_spec.lua696
-rw-r--r--test/functional/ui/inccommand_spec.lua1103
-rw-r--r--test/functional/ui/input_spec.lua6
-rw-r--r--test/functional/ui/mode_spec.lua227
-rw-r--r--test/functional/ui/mouse_spec.lua78
-rw-r--r--test/functional/ui/quickfix_spec.lua52
-rw-r--r--test/functional/ui/screen.lua69
-rw-r--r--test/functional/ui/screen_basic_spec.lua269
-rw-r--r--test/functional/ui/searchhl_spec.lua34
-rw-r--r--test/functional/ui/sign_spec.lua14
-rw-r--r--test/functional/ui/syntax_conceal_spec.lua70
-rw-r--r--test/functional/ui/tabline_spec.lua54
-rw-r--r--test/functional/ui/wildmode_spec.lua256
17 files changed, 4008 insertions, 634 deletions
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index 53fe303762..2143c01139 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -1,7 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local execute, request, neq = helpers.execute, helpers.request, helpers.neq
+local command, request, neq = helpers.command, helpers.request, helpers.neq
if helpers.pending_win32(pending) then return end
@@ -11,7 +12,7 @@ describe('Buffer highlighting', function()
before_each(function()
clear()
- execute("syntax on")
+ command('syntax on')
screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
@@ -23,7 +24,8 @@ describe('Buffer highlighting', function()
[6] = {foreground = Screen.colors.DarkCyan}, -- Identifier
[7] = {bold = true},
[8] = {underline = true, bold = true, foreground = Screen.colors.SlateBlue},
- [9] = {foreground = Screen.colors.SlateBlue, underline = true}
+ [9] = {foreground = Screen.colors.SlateBlue, underline = true},
+ [10] = {foreground = Screen.colors.Red}
})
curbuf = request('nvim_get_current_buf')
end)
@@ -106,7 +108,7 @@ describe('Buffer highlighting', function()
combining highlights
from different sources]])
- execute("hi ImportantWord gui=bold cterm=bold")
+ command("hi ImportantWord gui=bold cterm=bold")
id1 = add_hl(0, "ImportantWord", 0, 2, 8)
add_hl(id1, "ImportantWord", 1, 12, -1)
add_hl(id1, "ImportantWord", 2, 0, 9)
@@ -131,7 +133,7 @@ describe('Buffer highlighting', function()
{1:~ }|
{1:~ }|
{1:~ }|
- :hi ImportantWord gui=bold cterm=bold |
+ |
]])
end)
@@ -145,7 +147,7 @@ describe('Buffer highlighting', function()
{1:~ }|
{1:~ }|
{1:~ }|
- :hi ImportantWord gui=bold cterm=bold |
+ |
]])
end)
@@ -159,7 +161,7 @@ describe('Buffer highlighting', function()
{1:~ }|
{1:~ }|
{1:~ }|
- :hi ImportantWord gui=bold cterm=bold |
+ |
]])
end)
@@ -175,7 +177,7 @@ describe('Buffer highlighting', function()
{1:~ }|
{1:~ }|
{1:~ }|
- :hi ImportantWord gui=bold cterm=bold |
+ |
]])
end)
@@ -192,7 +194,7 @@ describe('Buffer highlighting', function()
|
]])
- execute(':3move 4')
+ command(':3move 4')
screen:expect([[
a {5:longer} example |
|
@@ -201,7 +203,7 @@ describe('Buffer highlighting', function()
{1:~ }|
{1:~ }|
{1:~ }|
- ::3move 4 |
+ |
]])
end)
end)
@@ -254,4 +256,32 @@ describe('Buffer highlighting', function()
|
]])
end)
+
+ it('works with new syntax groups', function()
+ insert([[
+ fancy code in a new fancy language]])
+ add_hl(-1, "FancyLangItem", 0, 0, 5)
+ screen:expect([[
+ fancy code in a new fancy languag^e |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+
+ command('hi FancyLangItem guifg=red')
+ screen:expect([[
+ {10:fancy} code in a new fancy languag^e |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
new file mode 100644
index 0000000000..d87ce72599
--- /dev/null
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -0,0 +1,893 @@
+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 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()
+ redraw!
+ return ''
+ 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 : '')
+ 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 SplittedMultibyteStart(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 SplittedMultibyteEnd(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}
+ })
+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('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([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :echo {RBP1:(}{RBP2:(}42{RBP2:)}^ |
+ ]])
+ 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('SplittedMultibyteStart')
+ start_prompt('echo "«')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :echo " |
+ {ERR:E5405: Chunk 0 start 7 splits multibyte }|
+ {ERR:character} |
+ :echo "«^ |
+ ]])
+ feed('»')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :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('SplittedMultibyteEnd')
+ start_prompt('echo "«')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :echo " |
+ {ERR:E5406: Chunk 0 end 7 splits multibyte ch}|
+ {ERR:aracter} |
+ :echo "«^ |
+ ]])
+ end)
+ it('does the right thing when errorring', function()
+ set_color_cb('Echoerring')
+ start_prompt('e')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ : |
+ {ERR:E5407: Callback has thrown an exception:}|
+ {ERR: 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('', meths.command_output('messages'))
+ end)
+ it('silences :echon', function()
+ set_color_cb('Echoning')
+ start_prompt('e')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :e^ |
+ ]])
+ eq('', meths.command_output('messages'))
+ end)
+ it('silences :echomsg', function()
+ set_color_cb('Echomsging')
+ start_prompt('e')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :e^ |
+ ]])
+ eq('', meths.command_output('messages'))
+ end)
+ it('does the right thing when throwing', function()
+ set_color_cb('Throwing')
+ start_prompt('e')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ : |
+ {ERR:E5407: Callback has thrown an exception:}|
+ {ERR: ABC} |
+ :e^ |
+ ]])
+ end)
+ it('stops executing callback after a number of errors', function()
+ set_color_cb('SplittedMultibyteStart')
+ start_prompt('let x = "«»«»«»«»«»"\n')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :let x = " |
+ {ERR:E5405: Chunk 0 start 10 splits multibyte}|
+ {ERR: character} |
+ ^:let x = "«»«»«»«»«»" |
+ ]])
+ feed('\n')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ |
+ ]])
+ 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:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ : |
+ {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 :quit<Enter> 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:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ : |
+ {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:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ : |
+ {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:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :+ |
+ {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:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :+ |
+ {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:~ }|
+ {EOB:~ }|
+ :+ |
+ {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)
+end)
+describe('Ex commands coloring support', 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', 'SplittedMultibyteStart')
+ 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:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ Entering Debug mode. Type "cont" to con|
+ tinue. |
+ cmd: execute "echo 1" |
+ >^ |
+ ]])
+ feed('n\n')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ 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('does not prevent mapping error from cancelling prompt', function()
+ command("cnoremap <expr> x execute('throw 42')[-1]")
+ feed(':#x')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :# |
+ {ERR:Error detected while processing :} |
+ {ERR:E605: Exception not caught: 42} |
+ :#^ |
+ ]])
+ feed('<CR>')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ |
+ ]])
+ feed('<CR>')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ |
+ ]])
+ eq('\nError detected while processing :\nE605: Exception not caught: 42',
+ meths.command_output('messages'))
+ end)
+ it('errors out when failing to get callback', function()
+ meths.set_var('Nvim_color_cmdline', 42)
+ feed(':#')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ : |
+ {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.set_var('Nvim_color_expr', 'RainBowParens')
+ feed(':echo <C-r>=(((1)))')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ={RBP1:(}{RBP2:(}{RBP3:(}1{RBP3:)}{RBP2:)}{RBP1:)}^ |
+ ]])
+ end)
+ it('errors out when failing to get callback', function()
+ meths.set_var('Nvim_color_expr', 42)
+ feed(':<C-r>=1')
+ screen:expect([[
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ = |
+ {ERR:E5409: Unable to get g:Nvim_color_expr c}|
+ {ERR:allback: Vim:E6000: Argument is not a fu}|
+ {ERR:nction or function name} |
+ =1^ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
new file mode 100644
index 0000000000..0f8302b036
--- /dev/null
+++ b/test/functional/ui/cmdline_spec.lua
@@ -0,0 +1,525 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq
+local source = helpers.source
+local ok = helpers.ok
+local command = helpers.command
+
+describe('external cmdline', function()
+ local screen
+ local last_level = 0
+ local cmdline = {}
+ local block = nil
+
+ before_each(function()
+ clear()
+ cmdline, block = {}, nil
+ screen = Screen.new(25, 5)
+ screen:attach({rgb=true, ext_cmdline=true})
+ screen:set_on_event_handler(function(name, data)
+ if name == "cmdline_show" then
+ local content, pos, firstc, prompt, indent, level = unpack(data)
+ ok(level > 0)
+ cmdline[level] = {content=content, pos=pos, firstc=firstc,
+ prompt=prompt, indent=indent}
+ last_level = level
+ elseif name == "cmdline_hide" then
+ local level = data[1]
+ cmdline[level] = nil
+ elseif name == "cmdline_special_char" then
+ local char, shift, level = unpack(data)
+ cmdline[level].special = {char, shift}
+ elseif name == "cmdline_pos" then
+ local pos, level = unpack(data)
+ cmdline[level].pos = pos
+ elseif name == "cmdline_block_show" then
+ block = data[1]
+ elseif name == "cmdline_block_append" then
+ block[#block+1] = data[1]
+ elseif name == "cmdline_block_hide" then
+ block = nil
+ end
+ end)
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ local function expect_cmdline(level, expected)
+ local attr_ids = screen._default_attr_ids
+ local attr_ignore = screen._default_attr_ignore
+ local actual = ''
+ for _, chunk in ipairs(cmdline[level] and cmdline[level].content or {}) do
+ local attrs, text = chunk[1], chunk[2]
+ if screen:_equal_attrs(attrs, {}) then
+ actual = actual..text
+ else
+ local attr_id = screen:_get_attr_id(attr_ids, attr_ignore, attrs)
+ actual = actual..'{' .. attr_id .. ':' .. text .. '}'
+ end
+ end
+ eq(expected, actual)
+ end
+
+ it('works', function()
+ feed(':')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq(1, last_level)
+ eq({{
+ content = { { {}, "" } },
+ firstc = ":",
+ indent = 0,
+ pos = 0,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('sign')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<Left>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign" } },
+ firstc = ":",
+ indent = 0,
+ pos = 3,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<bs>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sin" } },
+ firstc = ":",
+ indent = 0,
+ pos = 2,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+ end)
+
+ it("works with input()", function()
+ feed(':call input("input", "default")<cr>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "default" } },
+ firstc = "",
+ indent = 0,
+ pos = 7,
+ prompt = "input"
+ }}, cmdline)
+ end)
+ feed('<cr>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+
+ end)
+
+ it("works with special chars and nested cmdline", function()
+ feed(':xx<c-r>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "xx" } },
+ firstc = ":",
+ indent = 0,
+ pos = 2,
+ prompt = "",
+ special = {'"', true},
+ }}, cmdline)
+ end)
+
+ feed('=')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "xx" } },
+ firstc = ":",
+ indent = 0,
+ pos = 2,
+ prompt = "",
+ special = {'"', true},
+ },{
+ content = { { {}, "" } },
+ firstc = "=",
+ indent = 0,
+ pos = 0,
+ prompt = "",
+ }}, cmdline)
+ end)
+
+ feed('1+2')
+ local expectation = {{
+ content = { { {}, "xx" } },
+ firstc = ":",
+ indent = 0,
+ pos = 2,
+ prompt = "",
+ special = {'"', true},
+ },{
+ content = { { {}, "1+2" } },
+ firstc = "=",
+ indent = 0,
+ pos = 3,
+ prompt = "",
+ }}
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq(expectation, cmdline)
+ end)
+
+ -- erase information, so we check if it is retransmitted
+ cmdline = {}
+ command("redraw!")
+ -- redraw! forgets cursor position. Be OK with that, as UI should indicate
+ -- focus is at external cmdline anyway.
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ^ |
+ ]], nil, nil, function()
+ eq(expectation, cmdline)
+ end)
+
+
+ feed('<cr>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ^ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "xx3" } },
+ firstc = ":",
+ indent = 0,
+ pos = 3,
+ prompt = "",
+ }}, cmdline)
+ end)
+
+ feed('<esc>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+ end)
+
+ it("works with function definitions", function()
+ feed(':function Foo()<cr>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "" } },
+ firstc = ":",
+ indent = 2,
+ pos = 0,
+ prompt = "",
+ }}, cmdline)
+ eq({{{{}, 'function Foo()'}}}, block)
+ end)
+
+ feed('line1<cr>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{{{}, 'function Foo()'}},
+ {{{}, ' line1'}}}, block)
+ end)
+
+ block = {}
+ command("redraw!")
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ^ |
+ ]], nil, nil, function()
+ eq({{{{}, 'function Foo()'}},
+ {{{}, ' line1'}}}, block)
+ end)
+
+
+ feed('endfunction<cr>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq(nil, block)
+ end)
+ end)
+
+ it("works with cmdline window", function()
+ feed(':make')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "make" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<c-f>')
+ screen:expect([[
+ |
+ [No Name] |
+ :make^ |
+ [Command Line] |
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+
+ -- nested cmdline
+ feed(':yank')
+ screen:expect([[
+ |
+ [No Name] |
+ :make^ |
+ [Command Line] |
+ |
+ ]], nil, nil, function()
+ eq({nil, {
+ content = { { {}, "yank" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ cmdline = {}
+ command("redraw!")
+ screen:expect([[
+ |
+ [No Name] |
+ :make |
+ [Command Line] |
+ ^ |
+ ]], nil, nil, function()
+ eq({nil, {
+ content = { { {}, "yank" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed("<c-c>")
+ screen:expect([[
+ |
+ [No Name] |
+ :make^ |
+ [Command Line] |
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+
+ feed("<c-c>")
+ screen:expect([[
+ |
+ [No Name] |
+ :make^ |
+ [Command Line] |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "make" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ cmdline = {}
+ command("redraw!")
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ^ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "make" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+ end)
+
+ it('works with inputsecret()', function()
+ feed(":call inputsecret('secret:')<cr>abc123")
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "******" } },
+ firstc = "",
+ indent = 0,
+ pos = 6,
+ prompt = "secret:"
+ }}, cmdline)
+ end)
+ end)
+
+ it('works with highlighted cmdline', function()
+ source([[
+ highlight RBP1 guibg=Red
+ highlight RBP2 guibg=Yellow
+ highlight RBP3 guibg=Green
+ highlight RBP4 guibg=Blue
+ let g:NUM_LVLS = 4
+ 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
+ map <f5> :let x = input({'prompt':'>','highlight':'RainBowParens'})<cr>
+ "map <f5> :let x = input({'prompt':'>'})<cr>
+ ]])
+ 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}
+ })
+ feed('<f5>(a(b)a)')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ |
+ ]], nil, nil, function()
+ expect_cmdline(1, '{RBP1:(}a{RBP2:(}b{RBP2:)}a{RBP1:)}')
+ end)
+ end)
+end)
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
new file mode 100644
index 0000000000..b47210a777
--- /dev/null
+++ b/test/functional/ui/cursor_spec.lua
@@ -0,0 +1,246 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, meths = helpers.clear, helpers.meths
+local eq = helpers.eq
+local command = helpers.command
+
+describe('ui/cursor', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25, 5)
+ screen:attach()
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ it("'guicursor' is published as a UI event", function()
+ local expected_mode_info = {
+ [1] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 0,
+ cursor_shape = 'block',
+ name = 'normal',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'n' },
+ [2] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 0,
+ cursor_shape = 'block',
+ name = 'visual',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'v' },
+ [3] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 25,
+ cursor_shape = 'vertical',
+ name = 'insert',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'i' },
+ [4] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 20,
+ cursor_shape = 'horizontal',
+ name = 'replace',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'r' },
+ [5] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 0,
+ cursor_shape = 'block',
+ name = 'cmdline_normal',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'c' },
+ [6] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 25,
+ cursor_shape = 'vertical',
+ name = 'cmdline_insert',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'ci' },
+ [7] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 20,
+ cursor_shape = 'horizontal',
+ name = 'cmdline_replace',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'cr' },
+ [8] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 20,
+ cursor_shape = 'horizontal',
+ name = 'operator',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 'o' },
+ [9] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 25,
+ cursor_shape = 'vertical',
+ name = 'visual_select',
+ hl_id = 0,
+ id_lm = 0,
+ mouse_shape = 0,
+ short_name = 've' },
+ [10] = {
+ name = 'cmdline_hover',
+ mouse_shape = 0,
+ short_name = 'e' },
+ [11] = {
+ name = 'statusline_hover',
+ mouse_shape = 0,
+ short_name = 's' },
+ [12] = {
+ name = 'statusline_drag',
+ mouse_shape = 0,
+ short_name = 'sd' },
+ [13] = {
+ name = 'vsep_hover',
+ mouse_shape = 0,
+ short_name = 'vs' },
+ [14] = {
+ name = 'vsep_drag',
+ mouse_shape = 0,
+ short_name = 'vd' },
+ [15] = {
+ name = 'more',
+ mouse_shape = 0,
+ short_name = 'm' },
+ [16] = {
+ name = 'more_lastline',
+ mouse_shape = 0,
+ short_name = 'ml' },
+ [17] = {
+ blinkoff = 0,
+ blinkon = 0,
+ blinkwait = 0,
+ cell_percentage = 0,
+ cursor_shape = 'block',
+ name = 'showmatch',
+ hl_id = 0,
+ id_lm = 0,
+ short_name = 'sm' },
+ }
+
+ screen:expect(function()
+ -- Default 'guicursor', published on startup.
+ eq(expected_mode_info, screen._mode_info)
+ eq(true, screen._cursor_style_enabled)
+ eq('normal', screen.mode)
+ end)
+
+ -- Event is published ONLY if the cursor style changed.
+ screen._mode_info = nil
+ command("echo 'test'")
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ test |
+ ]], nil, nil, function()
+ eq(nil, screen._mode_info)
+ end)
+
+ -- Change the cursor style.
+ helpers.command('set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20'
+ ..',a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor'
+ ..',sm:block-blinkwait175-blinkoff150-blinkon175')
+
+ -- Update the expected values.
+ for _, m in ipairs(expected_mode_info) do
+ if m.name == 'showmatch' then
+ if m.blinkon then m.blinkon = 175 end
+ if m.blinkoff then m.blinkoff = 150 end
+ if m.blinkwait then m.blinkwait = 175 end
+ else
+ if m.blinkon then m.blinkon = 250 end
+ if m.blinkoff then m.blinkoff = 400 end
+ if m.blinkwait then m.blinkwait = 700 end
+ end
+ if m.hl_id then m.hl_id = 48 end
+ if m.id_lm then m.id_lm = 49 end
+ end
+
+ -- Assert the new expectation.
+ screen:expect(function()
+ eq(expected_mode_info, screen._mode_info)
+ eq(true, screen._cursor_style_enabled)
+ eq('normal', screen.mode)
+ end)
+
+ -- Another cursor style.
+ meths.set_option('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173'
+ ..',ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42')
+ screen:expect(function()
+ local named = {}
+ for _, m in ipairs(screen._mode_info) do
+ named[m.name] = m
+ end
+ eq('vertical', named.normal.cursor_shape)
+ eq(35, named.normal.cell_percentage)
+ eq('horizontal', named.visual_select.cursor_shape)
+ eq(35, named.visual_select.cell_percentage)
+ eq('vertical', named.operator.cursor_shape)
+ eq(50, named.operator.cell_percentage)
+ eq('block', named.insert.cursor_shape)
+ eq('vertical', named.showmatch.cursor_shape)
+ eq(90, named.cmdline_replace.cell_percentage)
+ eq(171, named.normal.blinkwait)
+ eq(172, named.normal.blinkoff)
+ eq(173, named.normal.blinkon)
+ eq(42, named.showmatch.cell_percentage)
+ end)
+ end)
+
+ it("empty 'guicursor' sets cursor_shape=block in all modes", function()
+ meths.set_option('guicursor', '')
+ screen:expect(function()
+ -- Empty 'guicursor' sets enabled=false.
+ eq(false, screen._cursor_style_enabled)
+ for _, m in ipairs(screen._mode_info) do
+ if m['cursor_shape'] ~= nil then
+ eq('block', m.cursor_shape)
+ eq(0, m.blinkon)
+ end
+ end
+ end)
+ end)
+
+end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 945b16ef92..2252e3580f 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -2,23 +2,22 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local os = require('os')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local execute, request, eq = helpers.execute, helpers.request, helpers.eq
+local command = helpers.command
+local eval, exc_exec = helpers.eval, helpers.exc_exec
+local feed_command, eq = helpers.feed_command, helpers.eq
+local curbufmeths = helpers.curbufmeths
-if helpers.pending_win32(pending) then return end
-
-describe('color scheme compatibility', function()
+describe('colorscheme compatibility', function()
before_each(function()
clear()
end)
it('t_Co is set to 256 by default', function()
- eq('256', request('vim_eval', '&t_Co'))
- request('nvim_set_option', 't_Co', '88')
- eq('88', request('vim_eval', '&t_Co'))
+ eq('256', eval('&t_Co'))
end)
end)
-describe('manual syntax highlight', function()
+describe('highlight: `:syntax manual`', function()
-- When using manual syntax highlighting, it should be preserved even when
-- switching buffers... bug did only occur without :set hidden
-- Ref: vim patch 7.4.1236
@@ -41,18 +40,18 @@ describe('manual syntax highlight', function()
end)
it("works with buffer switch and 'hidden'", function()
- execute('e tmp1.vim')
- execute('e Xtest-functional-ui-highlight.tmp.vim')
- execute('filetype on')
- execute('syntax manual')
- execute('set ft=vim')
- execute('set syntax=ON')
+ feed_command('e tmp1.vim')
+ feed_command('e Xtest-functional-ui-highlight.tmp.vim')
+ feed_command('filetype on')
+ feed_command('syntax manual')
+ feed_command('set ft=vim')
+ feed_command('set syntax=ON')
feed('iecho 1<esc>0')
- execute('set hidden')
- execute('w')
- execute('bn')
- execute('bp')
+ feed_command('set hidden')
+ feed_command('w')
+ feed_command('bn')
+ feed_command('bp')
screen:expect([[
{1:^echo} 1 |
{0:~ }|
@@ -63,32 +62,32 @@ describe('manual syntax highlight', function()
end)
it("works with buffer switch and 'nohidden'", function()
- execute('e tmp1.vim')
- execute('e Xtest-functional-ui-highlight.tmp.vim')
- execute('filetype on')
- execute('syntax manual')
- execute('set ft=vim')
- execute('set syntax=ON')
+ command('e tmp1.vim')
+ command('e Xtest-functional-ui-highlight.tmp.vim')
+ command('filetype on')
+ command('syntax manual')
+ command('set filetype=vim fileformat=unix')
+ command('set syntax=ON')
feed('iecho 1<esc>0')
- execute('set nohidden')
- execute('w')
- execute('bn')
- execute('bp')
+ command('set nohidden')
+ command('w')
+ command('silent bn')
+ eq("tmp1.vim", eval("fnamemodify(bufname('%'), ':t')"))
+ feed_command('silent bp')
+ eq("Xtest-functional-ui-highlight.tmp.vim", eval("fnamemodify(bufname('%'), ':t')"))
screen:expect([[
{1:^echo} 1 |
{0:~ }|
{0:~ }|
{0:~ }|
- <ht.tmp.vim" 1L, 7C |
+ :silent bp |
]])
end)
end)
-describe('Default highlight groups', function()
- -- Test the default attributes for highlight groups shown by the :highlight
- -- command
+describe('highlight defaults', function()
local screen
before_each(function()
@@ -107,7 +106,7 @@ describe('Default highlight groups', function()
[1] = {reverse = true, bold = true}, -- StatusLine
[2] = {reverse = true} -- StatusLineNC
})
- execute('sp', 'vsp', 'vsp')
+ feed_command('sp', 'vsp', 'vsp')
screen:expect([[
^ {2:|} {2:|} |
{0:~ }{2:|}{0:~ }{2:|}{0:~ }|
@@ -200,58 +199,31 @@ describe('Default highlight groups', function()
it('insert mode text', function()
feed('i')
+ screen:try_resize(53, 4)
screen:expect([[
^ |
{0:~ }|
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
{1:-- INSERT --} |
]], {[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {bold = true}})
end)
it('end of file markers', function()
+ screen:try_resize(53, 4)
screen:expect([[
^ |
{1:~ }|
{1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
|
]], {[1] = {bold = true, foreground = Screen.colors.Blue}})
end)
it('"wait return" text', function()
+ screen:try_resize(53, 4)
feed(':ls<cr>')
screen:expect([[
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
:ls |
1 %a "[No Name]" line 1 |
{1:Press ENTER or type command to continue}^ |
@@ -259,89 +231,84 @@ describe('Default highlight groups', function()
[1] = {bold = true, foreground = Screen.colors.SeaGreen}})
feed('<cr>') -- skip the "Press ENTER..." state or tests will hang
end)
+
it('can be cleared and linked to other highlight groups', function()
- execute('highlight clear ModeMsg')
+ screen:try_resize(53, 4)
+ feed_command('highlight clear ModeMsg')
feed('i')
screen:expect([[
^ |
{0:~ }|
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
-- INSERT -- |
]], {[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {bold=true}})
feed('<esc>')
- execute('highlight CustomHLGroup guifg=red guibg=green')
- execute('highlight link ModeMsg CustomHLGroup')
+ feed_command('highlight CustomHLGroup guifg=red guibg=green')
+ feed_command('highlight link ModeMsg CustomHLGroup')
feed('i')
screen:expect([[
^ |
{0:~ }|
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
{1:-- INSERT --} |
]], {[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {foreground = Screen.colors.Red, background = Screen.colors.Green}})
end)
+
it('can be cleared by assigning NONE', function()
- execute('syn keyword TmpKeyword neovim')
- execute('hi link TmpKeyword ErrorMsg')
+ screen:try_resize(53, 4)
+ feed_command('syn keyword TmpKeyword neovim')
+ feed_command('hi link TmpKeyword ErrorMsg')
insert('neovim')
screen:expect([[
{1:neovi^m} |
{0:~ }|
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
|
]], {
[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {foreground = Screen.colors.White, background = Screen.colors.Red}
})
- execute("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE"
+ feed_command("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE"
.. " gui=NONE guifg=NONE guibg=NONE guisp=NONE")
screen:expect([[
neovi^m |
{0:~ }|
{0:~ }|
+ |
+ ]], {[0] = {bold=true, foreground=Screen.colors.Blue}})
+ end)
+
+ it('Cursor after `:hi clear|syntax reset` #6508', function()
+ command('highlight clear|syntax reset')
+ eq('guifg=bg guibg=fg', eval([[matchstr(execute('hi Cursor'), '\v(gui|cterm).*$')]]))
+ end)
+
+ it('Whitespace highlight', function()
+ screen:try_resize(53, 4)
+ feed_command('highlight NonText gui=NONE guifg=#FF0000')
+ feed_command('set listchars=space:.,tab:>-,trail:*,eol:¬ list')
+ insert(' ne \t o\tv im ')
+ screen:expect([[
+ ne{0:.>----.}o{0:>-----}v{0:..}im{0:*^*¬} |
{0:~ }|
{0:~ }|
+ |
+ ]], {
+ [0] = {foreground=Screen.colors.Red},
+ [1] = {foreground=Screen.colors.Blue},
+ })
+ feed_command('highlight Whitespace gui=NONE guifg=#0000FF')
+ screen:expect([[
+ ne{1:.>----.}o{1:>-----}v{1:..}im{1:*^*}{0:¬} |
{0:~ }|
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]], {[0] = {bold=true, foreground=Screen.colors.Blue}})
+ :highlight Whitespace gui=NONE guifg=#0000FF |
+ ]], {
+ [0] = {foreground=Screen.colors.Red},
+ [1] = {foreground=Screen.colors.Blue},
+ })
end)
end)
@@ -355,19 +322,19 @@ describe('guisp (special/undercurl)', function()
end)
it('can be set and is applied like foreground or background', function()
- execute('syntax on')
- execute('syn keyword TmpKeyword neovim')
- execute('syn keyword TmpKeyword1 special')
- execute('syn keyword TmpKeyword2 specialwithbg')
- execute('syn keyword TmpKeyword3 specialwithfg')
- execute('hi! Awesome guifg=red guibg=yellow guisp=red')
- execute('hi! Awesome1 guisp=red')
- execute('hi! Awesome2 guibg=yellow guisp=red')
- execute('hi! Awesome3 guifg=red guisp=red')
- execute('hi link TmpKeyword Awesome')
- execute('hi link TmpKeyword1 Awesome1')
- execute('hi link TmpKeyword2 Awesome2')
- execute('hi link TmpKeyword3 Awesome3')
+ feed_command('syntax on')
+ feed_command('syn keyword TmpKeyword neovim')
+ feed_command('syn keyword TmpKeyword1 special')
+ feed_command('syn keyword TmpKeyword2 specialwithbg')
+ feed_command('syn keyword TmpKeyword3 specialwithfg')
+ feed_command('hi! Awesome guifg=red guibg=yellow guisp=red')
+ feed_command('hi! Awesome1 guisp=red')
+ feed_command('hi! Awesome2 guibg=yellow guisp=red')
+ feed_command('hi! Awesome3 guifg=red guisp=red')
+ feed_command('hi link TmpKeyword Awesome')
+ feed_command('hi link TmpKeyword1 Awesome1')
+ feed_command('hi link TmpKeyword2 Awesome2')
+ feed_command('hi link TmpKeyword3 Awesome3')
insert([[
neovim
awesome neovim
@@ -401,7 +368,7 @@ describe('guisp (special/undercurl)', function()
end)
end)
-describe("'cursorline' with 'listchars'", function()
+describe("'listchars' highlight", function()
local screen
before_each(function()
@@ -419,8 +386,8 @@ describe("'cursorline' with 'listchars'", function()
[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {background=Screen.colors.Grey90}
})
- execute('highlight clear ModeMsg')
- execute('set cursorline')
+ feed_command('highlight clear ModeMsg')
+ feed_command('set cursorline')
feed('i')
screen:expect([[
{1:^ }|
@@ -445,7 +412,7 @@ describe("'cursorline' with 'listchars'", function()
{0:~ }|
|
]])
- execute('set nocursorline')
+ feed_command('set nocursorline')
screen:expect([[
abcdefg |
kkasd^f |
@@ -469,8 +436,8 @@ describe("'cursorline' with 'listchars'", function()
^f |
|
]])
- execute('set cursorline')
- execute('set cursorcolumn')
+ feed_command('set cursorline')
+ feed_command('set cursorcolumn')
feed('kkiabcdefghijk<esc>hh')
screen:expect([[
kkasd {1: } |
@@ -509,11 +476,11 @@ describe("'cursorline' with 'listchars'", function()
foreground=Screen.colors.Red,
},
})
- execute('highlight clear ModeMsg')
- execute('highlight SpecialKey guifg=#FF0000')
- execute('set cursorline')
- execute('set tabstop=8')
- execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
+ feed_command('highlight clear ModeMsg')
+ feed_command('highlight Whitespace guifg=#FF0000')
+ feed_command('set cursorline')
+ feed_command('set tabstop=8')
+ feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
feed('i\t abcd <cr>\t abcd <cr><esc>k')
screen:expect([[
{5:>-------.}abcd{5:*}{4:¬} |
@@ -530,7 +497,7 @@ describe("'cursorline' with 'listchars'", function()
{4:~ }|
|
]])
- execute('set nocursorline')
+ feed_command('set nocursorline')
screen:expect([[
{5:^>-------.}abcd{5:*}{4:¬} |
{5:>-------.}abcd{5:*}{4:¬} |
@@ -538,7 +505,7 @@ describe("'cursorline' with 'listchars'", function()
{4:~ }|
:set nocursorline |
]])
- execute('set nowrap')
+ feed_command('set nowrap')
feed('ALorem ipsum dolor sit amet<ESC>0')
screen:expect([[
{5:^>-------.}abcd{5:.}Lorem{4:>}|
@@ -547,7 +514,7 @@ describe("'cursorline' with 'listchars'", function()
{4:~ }|
|
]])
- execute('set cursorline')
+ feed_command('set cursorline')
screen:expect([[
{2:^>-------.}{1:abcd}{2:.}{1:Lorem}{4:>}|
{5:>-------.}abcd{5:*}{4:¬} |
@@ -605,12 +572,12 @@ describe("'cursorline' with 'listchars'", function()
bold=true,
},
})
- execute('highlight clear ModeMsg')
- execute('highlight SpecialKey guifg=#FF0000')
- execute('set cursorline')
- execute('set tabstop=8')
- execute('set nowrap')
- execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
+ feed_command('highlight clear ModeMsg')
+ feed_command('highlight Whitespace guifg=#FF0000')
+ feed_command('set cursorline')
+ feed_command('set tabstop=8')
+ feed_command('set nowrap')
+ feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0')
screen:expect([[
{2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }|
@@ -644,4 +611,453 @@ describe("'cursorline' with 'listchars'", function()
|
]])
end)
+
+ it("'cursorline' with :match", function()
+ screen:set_default_attr_ids({
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = {background=Screen.colors.Grey90},
+ [2] = {foreground=Screen.colors.Red},
+ [3] = {foreground=Screen.colors.Green1},
+ })
+ feed_command('highlight clear ModeMsg')
+ feed_command('highlight Whitespace guifg=#FF0000')
+ feed_command('highlight Error guifg=#00FF00')
+ feed_command('set nowrap')
+ feed('ia \t bc \t <esc>')
+ screen:expect([[
+ a bc ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
+ screen:expect([[
+ a{2:.>-----.}bc{2:*>---*^*}{0:¬} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed_command('match Error /\\s\\+$/')
+ screen:expect([[
+ a{2:.>-----.}bc{3:*>---*^*}{0:¬} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+end)
+
+describe("'winhighlight' highlight", function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(20,8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = {background = Screen.colors.DarkBlue},
+ [2] = {background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Blue1},
+ [3] = {bold = true, reverse = true},
+ [4] = {reverse = true},
+ [5] = {background = Screen.colors.DarkGreen},
+ [6] = {background = Screen.colors.DarkGreen, bold = true, foreground = Screen.colors.Blue1},
+ [7] = {background = Screen.colors.DarkMagenta},
+ [8] = {background = Screen.colors.DarkMagenta, bold = true, foreground = Screen.colors.Blue1},
+ [9] = {foreground = Screen.colors.Brown},
+ [10] = {foreground = Screen.colors.Brown, background = Screen.colors.DarkBlue},
+ [11] = {background = Screen.colors.DarkBlue, bold = true, reverse = true},
+ [12] = {background = Screen.colors.DarkGreen, reverse = true},
+ [13] = {background = Screen.colors.Magenta4, reverse = true},
+ [14] = {background = Screen.colors.DarkBlue, reverse = true},
+ [15] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [16] = {foreground = Screen.colors.Blue1},
+ [17] = {background = Screen.colors.LightRed},
+ [18] = {background = Screen.colors.Gray90},
+ [19] = {foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray},
+ [20] = {background = Screen.colors.LightGrey, underline = true},
+ [21] = {bold = true},
+ [22] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [23] = {background = Screen.colors.LightMagenta},
+ [24] = {background = Screen.colors.WebGray},
+ })
+ command("hi Background1 guibg=DarkBlue")
+ command("hi Background2 guibg=DarkGreen")
+ end)
+
+ it('works for background color', function()
+ insert("aa")
+ command("split")
+ command("set winhl=Normal:Background1")
+ screen:expect([[
+ {1:a^a }|
+ {2:~ }|
+ {2:~ }|
+ {11:[No Name] [+] }|
+ aa |
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+
+ command("enew")
+ screen:expect([[
+ {1:^ }|
+ {2:~ }|
+ {2:~ }|
+ {11:[No Name] }|
+ aa |
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end)
+
+ it('handles invalid values', function()
+ command("set winhl=Normal:Background1")
+ screen:expect([[
+ {1:^ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ |
+ ]])
+
+ eq('Vim(set):E474: Invalid argument: winhl=xxx:yyy',
+ exc_exec("set winhl=xxx:yyy"))
+ eq('Normal:Background1', eval('&winhl'))
+ screen:expect([[
+ {1:^ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ |
+ ]])
+ end)
+
+
+ it('works local to the buffer', function()
+ insert("aa")
+ command("split")
+ command("setlocal winhl=Normal:Background1")
+ screen:expect([[
+ {1:a^a }|
+ {2:~ }|
+ {2:~ }|
+ {11:[No Name] [+] }|
+ aa |
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+
+ command("enew")
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {3:[No Name] }|
+ aa |
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+
+ command("bnext")
+ screen:expect([[
+ {1:^aa }|
+ {2:~ }|
+ {2:~ }|
+ {11:[No Name] [+] }|
+ aa |
+ {0:~ }|
+ {4:[No Name] [+] }|
+ <f 1 --100%-- col 1 |
+ ]])
+ end)
+
+ it('for inactive window background works', function()
+ command("set winhl=Normal:Background1,NormalNC:Background2")
+ -- tests global value is copied across split
+ command("split")
+ screen:expect([[
+ {1:^ }|
+ {2:~ }|
+ {2:~ }|
+ {11:[No Name] }|
+ {5: }|
+ {6:~ }|
+ {12:[No Name] }|
+ |
+ ]])
+
+ feed("<c-w><c-w>")
+ screen:expect([[
+ {5: }|
+ {6:~ }|
+ {6:~ }|
+ {12:[No Name] }|
+ {1:^ }|
+ {2:~ }|
+ {11:[No Name] }|
+ |
+ ]])
+
+ feed("<c-w><c-w>")
+ screen:expect([[
+ {1:^ }|
+ {2:~ }|
+ {2:~ }|
+ {11:[No Name] }|
+ {5: }|
+ {6:~ }|
+ {12:[No Name] }|
+ |
+ ]])
+ end)
+
+ it('works with NormalNC', function()
+ command("hi NormalNC guibg=DarkMagenta")
+ -- tests global value is copied across split
+ command("split")
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {3:[No Name] }|
+ {7: }|
+ {8:~ }|
+ {13:[No Name] }|
+ |
+ ]])
+
+ command("wincmd w")
+ screen:expect([[
+ {7: }|
+ {8:~ }|
+ {8:~ }|
+ {13:[No Name] }|
+ ^ |
+ {0:~ }|
+ {3:[No Name] }|
+ |
+ ]])
+
+
+ -- winbg=Normal:... overrides global NormalNC
+ command("set winhl=Normal:Background1")
+ screen:expect([[
+ {7: }|
+ {8:~ }|
+ {8:~ }|
+ {13:[No Name] }|
+ {1:^ }|
+ {2:~ }|
+ {11:[No Name] }|
+ |
+ ]])
+
+ command("wincmd w")
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {3:[No Name] }|
+ {1: }|
+ {2:~ }|
+ {14:[No Name] }|
+ |
+ ]])
+
+ command("wincmd w")
+ command("set winhl=Normal:Background1,NormalNC:Background2")
+ screen:expect([[
+ {7: }|
+ {8:~ }|
+ {8:~ }|
+ {13:[No Name] }|
+ {1:^ }|
+ {2:~ }|
+ {11:[No Name] }|
+ |
+ ]])
+
+ command("wincmd w")
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {3:[No Name] }|
+ {5: }|
+ {6:~ }|
+ {12:[No Name] }|
+ |
+ ]])
+ end)
+
+ it('background applies also to non-text', function()
+ insert('Lorem ipsum dolor sit amet ')
+ command('set shiftwidth=2')
+ feed('>>')
+ command('set number')
+ command('set breakindent')
+ command('set briopt=shift:5,min:0')
+ command('set list')
+ command('set showbreak=↪')
+ screen:expect([[
+ {9: 1 } ^Lorem ipsum do|
+ {9: } {0:↪}lor sit |
+ {9: } {0:↪}amet{0:-} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+
+ command('set winhl=Normal:Background1')
+ screen:expect([[
+ {10: 1 }{1: ^Lorem ipsum do}|
+ {10: }{1: }{2:↪}{1:lor sit }|
+ {10: }{1: }{2:↪}{1:amet}{2:-}{1: }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ |
+ ]])
+
+ command('set nowrap')
+ command('set listchars+=extends:❯,precedes:❮')
+ feed('3w')
+ screen:expect([[
+ {10: 1 }{2:❮}{1: dolor ^sit ame}{2:❯}|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ |
+ ]])
+ end)
+
+ it('can override NonText, Conceal and EndOfBuffer', function()
+ curbufmeths.set_lines(0,-1,true, {"raa\000"})
+ command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})')
+ command('set cole=2 cocu=nvic')
+ command('split')
+ command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})')
+ command('set winhl=SpecialKey:ErrorMsg,EndOfBuffer:Background1,'
+ ..'Conceal:Background2')
+
+ screen:expect([[
+ ^r{5:#}a{15:^@} |
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] [+] }|
+ r{19:#}a{16:^@} |
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end)
+
+ it('can override LineNr, CursorColumn and ColorColumn', function()
+ insert('very text\nmore text')
+ command('set number')
+ command('set colorcolumn=2')
+ command('set cursorcolumn')
+
+ command('split')
+ command('set winhl=LineNr:Background1,CursorColumn:Background2,'
+ ..'ColorColumn:ErrorMsg')
+ screen:expect([[
+ {1: 1 }v{15:e}ry tex{5:t} |
+ {1: 2 }m{15:o}re tex^t |
+ {0:~ }|
+ {3:[No Name] [+] }|
+ {9: 1 }v{17:e}ry tex{18:t} |
+ {9: 2 }m{17:o}re text |
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end)
+
+ it('can override Tabline', function()
+ command('tabnew')
+ command('set winhl=TabLine:Background1,TabLineSel:ErrorMsg')
+
+ screen:expect([[
+ {20: No Name] }{15: No Name]}{20:X}|
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ command("tabnext")
+ screen:expect([[
+ {21: No Name] }{1: No Name]}{20:X}|
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ it('can override popupmenu', function()
+ insert('word wording wordy')
+ command('split')
+ command('set winhl=Pmenu:Background1,PmenuSel:Background2,'
+ ..'PmenuSbar:ErrorMsg,PmenuThumb:Normal')
+ screen:expect([[
+ word wording word^y |
+ {0:~ }|
+ {0:~ }|
+ {3:[No Name] [+] }|
+ word wording wordy |
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+
+ feed('oword<c-x><c-p>')
+ screen:expect([[
+ word wording wordy |
+ wordy^ |
+ {1:word }{0: }|
+ {1:wording }{3: }|
+ {5:wordy }rdy |
+ wordy |
+ {4:[No Name] [+] }|
+ {21:-- }{22:match 1 of 3} |
+ ]])
+
+ feed('<esc>u<c-w><c-w>oword<c-x><c-p>')
+ screen:expect([[
+ word wording wordy |
+ wordy |
+ {23:word }{0: }|
+ {23:wording }{4: }|
+ {24:wordy }rdy |
+ wordy^ |
+ {3:[No Name] [+] }|
+ {21:-- }{22:match 1 of 3} |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 3b31da0397..53fd17c309 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -1,10 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
+local command = helpers.command
local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
local eval = helpers.eval
-local execute = helpers.execute
+local feed_command = helpers.feed_command
local expect = helpers.expect
local feed = helpers.feed
local insert = helpers.insert
@@ -13,17 +14,54 @@ local neq = helpers.neq
local ok = helpers.ok
local source = helpers.source
local wait = helpers.wait
+local nvim = helpers.nvim
local default_text = [[
Inc substitution on
two lines
]]
+local multiline_text = [[
+ 1 2 3
+ A B C
+ 4 5 6
+ X Y Z
+ 7 8 9
+]]
+
+local multimatch_text = [[
+ a bdc eae a fgl lzia r
+ x
+]]
+
+local multibyte_text = [[
+ £ ¥ ѫѫ PEPPERS
+£ ¥ ѫfѫ
+ a£ ѫ¥KOL
+£ ¥ libm
+£ ¥
+]]
+
+local long_multiline_text = [[
+ 1 2 3
+ A B C
+ 4 5 6
+ X Y Z
+ 7 8 9
+ K L M
+ a b c
+ d e f
+ q r s
+ x y z
+ £ m n
+ t œ ¥
+]]
+
local function common_setup(screen, inccommand, text)
if screen then
- execute("syntax on")
- execute("set nohlsearch")
- execute("hi Substitute guifg=red guibg=yellow")
+ command("syntax on")
+ command("set nohlsearch")
+ command("hi Substitute guifg=red guibg=yellow")
screen:attach()
screen:set_default_attr_ids({
[1] = {foreground = Screen.colors.Fuchsia},
@@ -46,7 +84,7 @@ local function common_setup(screen, inccommand, text)
})
end
- execute("set inccommand=" .. (inccommand and inccommand or ""))
+ command("set inccommand=" .. (inccommand and inccommand or ""))
if text then
insert(text)
@@ -91,8 +129,8 @@ describe(":substitute, 'inccommand' preserves", function()
local screen = Screen.new(30,10)
common_setup(screen, "split", "ABC")
- execute("%s/AB/BA/")
- execute("ls")
+ feed_command("%s/AB/BA/")
+ feed_command("ls")
screen:expect([[
{15:~ }|
@@ -111,25 +149,25 @@ describe(":substitute, 'inccommand' preserves", function()
for _, case in pairs{"", "split", "nosplit"} do
it("various delimiters (inccommand="..case..")", function()
insert(default_text)
- execute("set inccommand=" .. case)
+ feed_command("set inccommand=" .. case)
local delims = { '/', '#', ';', '%', ',', '@', '!', ''}
for _,delim in pairs(delims) do
- execute("%s"..delim.."lines"..delim.."LINES"..delim.."g")
+ feed_command("%s"..delim.."lines"..delim.."LINES"..delim.."g")
expect([[
Inc substitution on
two LINES
]])
- execute("undo")
+ feed_command("undo")
end
end)
end
for _, case in pairs{"", "split", "nosplit"} do
it("'undolevels' (inccommand="..case..")", function()
- execute("set undolevels=139")
- execute("setlocal undolevels=34")
- execute("set inccommand=" .. case)
+ feed_command("set undolevels=139")
+ feed_command("setlocal undolevels=34")
+ feed_command("set inccommand=" .. case)
insert("as")
feed(":%s/as/glork/<enter>")
eq(meths.get_option('undolevels'), 139)
@@ -139,8 +177,8 @@ describe(":substitute, 'inccommand' preserves", function()
for _, case in ipairs({"", "split", "nosplit"}) do
it("empty undotree() (inccommand="..case..")", function()
- execute("set undolevels=1000")
- execute("set inccommand=" .. case)
+ feed_command("set undolevels=1000")
+ feed_command("set inccommand=" .. case)
local expected_undotree = eval("undotree()")
-- Start typing an incomplete :substitute command.
@@ -157,8 +195,8 @@ describe(":substitute, 'inccommand' preserves", function()
for _, case in ipairs({"", "split", "nosplit"}) do
it("undotree() with branches (inccommand="..case..")", function()
- execute("set undolevels=1000")
- execute("set inccommand=" .. case)
+ feed_command("set undolevels=1000")
+ feed_command("set inccommand=" .. case)
-- Make some changes.
feed([[isome text 1<C-\><C-N>]])
feed([[osome text 2<C-\><C-N>]])
@@ -192,7 +230,7 @@ describe(":substitute, 'inccommand' preserves", function()
for _, case in pairs{"", "split", "nosplit"} do
it("b:changedtick (inccommand="..case..")", function()
- execute("set inccommand=" .. case)
+ feed_command("set inccommand=" .. case)
feed([[isome text 1<C-\><C-N>]])
feed([[osome text 2<C-\><C-N>]])
local expected_tick = eval("b:changedtick")
@@ -271,18 +309,18 @@ describe(":substitute, 'inccommand' preserves undo", function()
local function test_sub(substring, split, redoable)
clear()
- execute("set inccommand=" .. split)
+ feed_command("set inccommand=" .. split)
insert("1")
feed("o2<esc>")
- execute("undo")
+ feed_command("undo")
feed("o3<esc>")
if redoable then
feed("o4<esc>")
- execute("undo")
+ feed_command("undo")
end
feed(substring.. "<enter>")
- execute("undo")
+ feed_command("undo")
feed("g-")
expect([[
@@ -297,15 +335,15 @@ describe(":substitute, 'inccommand' preserves undo", function()
local function test_notsub(substring, split, redoable)
clear()
- execute("set inccommand=" .. split)
+ feed_command("set inccommand=" .. split)
insert("1")
feed("o2<esc>")
- execute("undo")
+ feed_command("undo")
feed("o3<esc>")
if redoable then
feed("o4<esc>")
- execute("undo")
+ feed_command("undo")
end
feed(substring .. "<esc>")
@@ -331,7 +369,7 @@ describe(":substitute, 'inccommand' preserves undo", function()
local function test_threetree(substring, split)
clear()
- execute("set inccommand=" .. split)
+ feed_command("set inccommand=" .. split)
insert("1")
feed("o2<esc>")
@@ -424,22 +462,22 @@ describe(":substitute, 'inccommand' preserves undo", function()
for _, case in pairs(cases) do
clear()
common_setup(nil, case, default_text)
- execute("set undolevels=0")
+ feed_command("set undolevels=0")
feed("1G0")
insert("X")
feed(":%s/tw/MO/<esc>")
- execute("undo")
+ feed_command("undo")
expect(default_text)
- execute("undo")
+ feed_command("undo")
expect(default_text:gsub("Inc", "XInc"))
- execute("undo")
+ feed_command("undo")
- execute("%s/tw/MO/g")
+ feed_command("%s/tw/MO/g")
expect(default_text:gsub("tw", "MO"))
- execute("undo")
+ feed_command("undo")
expect(default_text)
- execute("undo")
+ feed_command("undo")
expect(default_text:gsub("tw", "MO"))
end
end)
@@ -450,13 +488,13 @@ describe(":substitute, 'inccommand' preserves undo", function()
for _, case in pairs(cases) do
clear()
common_setup(screen, case, default_text)
- execute("set undolevels=1")
+ feed_command("set undolevels=1")
feed("1G0")
insert("X")
feed("IY<esc>")
feed(":%s/tw/MO/<esc>")
- -- execute("undo") here would cause "Press ENTER".
+ -- feed_command("undo") here would cause "Press ENTER".
feed("u")
expect(default_text:gsub("Inc", "XInc"))
feed("u")
@@ -508,13 +546,13 @@ describe(":substitute, 'inccommand' preserves undo", function()
for _, case in pairs(cases) do
clear()
common_setup(screen, case, default_text)
- execute("set undolevels=2")
+ feed_command("set undolevels=2")
feed("2GAx<esc>")
feed("Ay<esc>")
feed("Az<esc>")
feed(":%s/tw/AR<esc>")
- -- using execute("undo") here will result in a "Press ENTER" prompt
+ -- feed_command("undo") here would cause "Press ENTER".
feed("u")
expect(default_text:gsub("lines", "linesxy"))
feed("u")
@@ -601,9 +639,9 @@ describe(":substitute, 'inccommand' preserves undo", function()
clear()
common_setup(screen, case, default_text)
- execute("set undolevels=-1")
+ feed_command("set undolevels=-1")
feed(":%s/tw/MO/g<enter>")
- -- using execute("undo") here will result in a "Press ENTER" prompt
+ -- feed_command("undo") here will result in a "Press ENTER" prompt
feed("u")
if case == "split" then
screen:expect([[
@@ -637,7 +675,7 @@ describe(":substitute, 'inccommand' preserves undo", function()
clear()
common_setup(screen, case, default_text)
- execute("set undolevels=-1")
+ feed_command("set undolevels=-1")
feed("1G")
feed("IL<esc>")
feed(":%s/tw/MO/g<esc>")
@@ -676,18 +714,18 @@ describe(":substitute, inccommand=split", function()
end)
it("preserves 'modified' buffer flag", function()
- execute("set nomodified")
+ feed_command("set nomodified")
feed(":%s/tw")
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] }|
- |2| two lines |
- |4| two lines |
- |
+ |2| {12:tw}o lines |
+ |4| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -699,18 +737,37 @@ describe(":substitute, inccommand=split", function()
eq(0, eval("&modified"))
end)
+ it("shows preview when cmd modifiers are present", function()
+ -- one modifier
+ feed(':keeppatterns %s/tw/to')
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
+ feed('<Esc>')
+ screen:expect([[two lines]], nil, nil, nil, true)
+
+ -- multiple modifiers
+ feed(':keeppatterns silent %s/tw/to')
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
+ feed('<Esc>')
+ screen:expect([[two lines]], nil, nil, nil, true)
+
+ -- non-modifier prefix
+ feed(':silent tabedit %s/tw/to')
+ screen:expect([[two lines]], nil, nil, nil, true)
+ feed('<Esc>')
+ end)
+
it('shows split window when typing the pattern', function()
feed(":%s/tw")
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
- |2| two lines |
- |4| two lines |
- |
+ |2| {12:tw}o lines |
+ |4| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -731,7 +788,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -743,14 +800,14 @@ describe(":substitute, inccommand=split", function()
feed("x")
screen:expect([[
Inc substitution on |
- xo lines |
+ {12:x}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
|2| {12:x}o lines |
|4| {12:x}o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -769,7 +826,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -784,14 +841,14 @@ describe(":substitute, inccommand=split", function()
feed(":%s/tw/XX")
screen:expect([[
Inc substitution on |
- XXo lines |
+ {12:XX}o lines |
|
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
|2| {12:XX}o lines |
|4| {12:XX}o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -804,10 +861,10 @@ describe(":substitute, inccommand=split", function()
it('does not show split window for :s/', function()
feed("2gg")
feed(":s/tw")
- wait()
+ screen:sleep(1)
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
Inc substitution on |
two lines |
|
@@ -825,7 +882,7 @@ describe(":substitute, inccommand=split", function()
end)
it("'hlsearch' is active, 'cursorline' is not", function()
- execute("set hlsearch cursorline")
+ feed_command("set hlsearch cursorline")
feed("gg")
-- Assert that 'cursorline' is active.
@@ -851,14 +908,14 @@ describe(":substitute, inccommand=split", function()
-- 'cursorline' is NOT active during preview.
screen:expect([[
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
|
{11:[No Name] [+] }|
- |2| {9:tw}o lines |
- |4| {9:tw}o lines |
- |
+ |2| {12:tw}o lines |
+ |4| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -873,14 +930,14 @@ describe(":substitute, inccommand=split", function()
feed('M M M<esc>')
feed(':%s/M/123/g')
screen:expect([[
- 123 123 123 |
+ {12:123} {12:123} {12:123} |
Inc substitution on |
two lines |
Inc substitution on |
two lines |
{11:[No Name] [+] }|
|1| {12:123} {12:123} {12:123} |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -891,6 +948,53 @@ describe(":substitute, inccommand=split", function()
]])
end)
+ it("highlights nothing when there's no match", function()
+ feed('gg')
+ feed(':%s/Inx')
+ screen:expect([[
+ Inc substitution on |
+ two lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/Inx^ |
+ ]])
+ end)
+
+ it('previews correctly when previewhight is small', function()
+ feed_command('set cwh=3')
+ feed_command('set hls')
+ feed('ggdG')
+ insert(string.rep('abc abc abc\n', 20))
+ feed(':%s/abc/MMM/g')
+ screen:expect([[
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |
+ {11:[No Name] [+] }|
+ | 1| {12:MMM} {12:MMM} {12:MMM} |
+ | 2| {12:MMM} {12:MMM} {12:MMM} |
+ | 3| {12:MMM} {12:MMM} {12:MMM} |
+ {10:[Preview] }|
+ :%s/abc/MMM/g^ |
+ ]])
+ end)
+
it('actually replaces text', function()
feed(":%s/tw/XX/g<Enter>")
@@ -917,15 +1021,15 @@ describe(":substitute, inccommand=split", function()
feed("gg")
feed("2yy")
feed("2000p")
- execute("1,1000s/tw/BB/g")
+ feed_command("1,1000s/tw/BB/g")
feed(":%s/tw/X")
screen:expect([[
BBo lines |
Inc substitution on |
- Xo lines |
+ {12:X}o lines |
Inc substitution on |
- Xo lines |
+ {12:X}o lines |
{11:[No Name] [+] }|
|1001| {12:X}o lines |
|1003| {12:X}o lines |
@@ -983,9 +1087,9 @@ describe(":substitute, inccommand=split", function()
-- Assert that 'inccommand' is ENABLED initially.
eq("split", eval("&inccommand"))
-- Set 'redrawtime' to minimal value, to ensure timeout is triggered.
- execute("set redrawtime=1 nowrap")
+ feed_command("set redrawtime=1 nowrap")
-- Load a big file.
- execute("silent edit! test/functional/fixtures/bigfile.txt")
+ feed_command("silent edit! test/functional/fixtures/bigfile_oneline.txt")
-- Start :substitute with a slow pattern.
feed([[:%s/B.*N/x]])
wait()
@@ -995,19 +1099,19 @@ describe(":substitute, inccommand=split", function()
-- Assert that preview cleared (or never manifested).
screen:expect([[
0000;<control>;Cc;0;BN;;;;;N;N|
- 0001;<control>;Cc;0;BN;;;;;N;S|
- 0002;<control>;Cc;0;BN;;;;;N;S|
- 0003;<control>;Cc;0;BN;;;;;N;E|
- 0004;<control>;Cc;0;BN;;;;;N;E|
- 0005;<control>;Cc;0;BN;;;;;N;E|
- 0006;<control>;Cc;0;BN;;;;;N;A|
- 0007;<control>;Cc;0;BN;;;;;N;B|
- 0008;<control>;Cc;0;BN;;;;;N;B|
- 0009;<control>;Cc;0;S;;;;;N;CH|
- 000A;<control>;Cc;0;B;;;;;N;LI|
- 000B;<control>;Cc;0;S;;;;;N;LI|
- 000C;<control>;Cc;0;WS;;;;;N;F|
- 000D;<control>;Cc;0;B;;;;;N;CA|
+ 2F923;CJK COMPATIBILITY IDEOGR|
+ 2F924;CJK COMPATIBILITY IDEOGR|
+ 2F925;CJK COMPATIBILITY IDEOGR|
+ 2F926;CJK COMPATIBILITY IDEOGR|
+ 2F927;CJK COMPATIBILITY IDEOGR|
+ 2F928;CJK COMPATIBILITY IDEOGR|
+ 2F929;CJK COMPATIBILITY IDEOGR|
+ 2F92A;CJK COMPATIBILITY IDEOGR|
+ 2F92B;CJK COMPATIBILITY IDEOGR|
+ 2F92C;CJK COMPATIBILITY IDEOGR|
+ 2F92D;CJK COMPATIBILITY IDEOGR|
+ 2F92E;CJK COMPATIBILITY IDEOGR|
+ 2F92F;CJK COMPATIBILITY IDEOGR|
:%s/B.*N/x^ |
]])
@@ -1018,20 +1122,20 @@ describe(":substitute, inccommand=split", function()
it("clears preview if non-previewable command is edited #5585", function()
-- Put a non-previewable command in history.
- execute("echo 'foo'")
+ feed_command("echo 'foo'")
-- Start an incomplete :substitute command.
feed(":1,2s/t/X")
screen:expect([[
- Inc subsXitution on |
- Xwo lines |
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
Inc substitution on |
two lines |
|
{11:[No Name] [+] }|
|1| Inc subs{12:X}itution on |
|2| {12:X}wo lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1079,7 +1183,7 @@ describe("inccommand=nosplit", function()
end)
it("works with :smagic, :snomagic", function()
- execute("set hlsearch")
+ feed_command("set hlsearch")
insert("Line *.3.* here")
feed(":%smagic/3.*/X") -- start :smagic command
@@ -1088,7 +1192,7 @@ describe("inccommand=nosplit", function()
two lines |
Inc substitution on |
two lines |
- Line *.X |
+ Line *.{12:X} |
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1096,7 +1200,6 @@ describe("inccommand=nosplit", function()
:%smagic/3.*/X^ |
]])
-
feed([[<C-\><C-N>]]) -- cancel
feed(":%snomagic/3.*/X") -- start :snomagic command
screen:expect([[
@@ -1104,7 +1207,7 @@ describe("inccommand=nosplit", function()
two lines |
Inc substitution on |
two lines |
- Line *.X here |
+ Line *.{12:X} here |
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1113,15 +1216,57 @@ describe("inccommand=nosplit", function()
]])
end)
+ it("shows preview when cmd modifiers are present", function()
+ -- one modifier
+ feed(':keeppatterns %s/tw/to')
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
+ feed('<Esc>')
+ screen:expect([[two lines]], nil, nil, nil, true)
+
+ -- multiple modifiers
+ feed(':keeppatterns silent %s/tw/to')
+ screen:expect([[{12:to}o lines]], nil, nil, nil, true)
+ feed('<Esc>')
+ screen:expect([[two lines]], nil, nil, nil, true)
+
+ -- non-modifier prefix
+ feed(':silent tabedit %s/tw/to')
+ screen:expect([[two lines]], nil, nil, nil, true)
+ feed('<Esc>')
+ end)
+
+ it("does not show window after toggling :set inccommand", function()
+ feed(":%s/tw/OKOK")
+ feed("<Esc>")
+ command("set icm=split")
+ feed(":%s/tw/OKOK")
+ feed("<Esc>")
+ command("set icm=nosplit")
+ feed(":%s/tw/OKOK")
+ wait()
+ screen:expect([[
+ Inc substitution on |
+ {12:OKOK}o lines |
+ Inc substitution on |
+ {12:OKOK}o lines |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/tw/OKOK^ |
+ ]])
+ end)
+
it('never shows preview buffer', function()
- execute("set hlsearch")
+ feed_command("set hlsearch")
feed(":%s/tw")
screen:expect([[
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
Inc substitution on |
- {9:tw}o lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
@@ -1133,9 +1278,9 @@ describe("inccommand=nosplit", function()
feed("/BM")
screen:expect([[
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
|
{15:~ }|
{15:~ }|
@@ -1147,9 +1292,9 @@ describe("inccommand=nosplit", function()
feed("/")
screen:expect([[
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
Inc substitution on |
- BMo lines |
+ {12:BM}o lines |
|
{15:~ }|
{15:~ }|
@@ -1175,13 +1320,13 @@ describe("inccommand=nosplit", function()
it("clears preview if non-previewable command is edited", function()
-- Put a non-previewable command in history.
- execute("echo 'foo'")
+ feed_command("echo 'foo'")
-- Start an incomplete :substitute command.
feed(":1,2s/t/X")
screen:expect([[
- Inc subsXitution on |
- Xwo lines |
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
Inc substitution on |
two lines |
|
@@ -1224,7 +1369,7 @@ describe(":substitute, 'inccommand' with a failing expression", function()
it('in the pattern does nothing', function()
for _, case in pairs(cases) do
refresh(case)
- execute("set inccommand=" .. case)
+ feed_command("set inccommand=" .. case)
feed(":silent! %s/tw\\(/LARD/<enter>")
expect(default_text)
end
@@ -1236,10 +1381,10 @@ describe(":substitute, 'inccommand' with a failing expression", function()
local replacements = { "\\='LARD", "\\=xx_novar__xx" }
for _, repl in pairs(replacements) do
- execute("set inccommand=" .. case)
+ feed_command("set inccommand=" .. case)
feed(":silent! %s/tw/" .. repl .. "/<enter>")
expect(default_text:gsub("tw", ""))
- execute("undo")
+ feed_command("undo")
end
end
end)
@@ -1291,14 +1436,14 @@ describe("'inccommand' and :cnoremap", function()
it('work with remapped characters', function()
for _, case in pairs(cases) do
refresh(case)
- local command = "%s/lines/LINES/g"
+ local cmd = "%s/lines/LINES/g"
- for i = 1, string.len(command) do
- local c = string.sub(command, i, i)
- execute("cnoremap ".. c .. " " .. c)
+ for i = 1, string.len(cmd) do
+ local c = string.sub(cmd, i, i)
+ feed_command("cnoremap ".. c .. " " .. c)
end
- execute(command)
+ feed_command(cmd)
expect([[
Inc substitution on
two LINES
@@ -1309,7 +1454,7 @@ describe("'inccommand' and :cnoremap", function()
it('work when mappings move the cursor', function()
for _, case in pairs(cases) do
refresh(case)
- execute("cnoremap ,S LINES/<left><left><left><left><left><left>")
+ feed_command("cnoremap ,S LINES/<left><left><left><left><left><left>")
feed(":%s/lines/,Sor three <enter>")
expect([[
@@ -1317,21 +1462,21 @@ describe("'inccommand' and :cnoremap", function()
two or three LINES
]])
- execute("cnoremap ;S /X/<left><left><left>")
+ feed_command("cnoremap ;S /X/<left><left><left>")
feed(":%s/;SI<enter>")
expect([[
Xnc substitution on
two or three LXNES
]])
- execute("cnoremap ,T //Y/<left><left><left>")
+ feed_command("cnoremap ,T //Y/<left><left><left>")
feed(":%s,TX<enter>")
expect([[
Ync substitution on
two or three LYNES
]])
- execute("cnoremap ;T s//Z/<left><left><left>")
+ feed_command("cnoremap ;T s//Z/<left><left><left>")
feed(":%;TY<enter>")
expect([[
Znc substitution on
@@ -1343,7 +1488,7 @@ describe("'inccommand' and :cnoremap", function()
it('does not work with a failing mapping', function()
for _, case in pairs(cases) do
refresh(case)
- execute("cnoremap <expr> x execute('bwipeout!')[-1].'x'")
+ feed_command("cnoremap <expr> x execute('bwipeout!')[-1].'x'")
feed(":%s/tw/tox<enter>")
@@ -1356,7 +1501,7 @@ describe("'inccommand' and :cnoremap", function()
it('work when temporarily moving the cursor', function()
for _, case in pairs(cases) do
refresh(case)
- execute("cnoremap <expr> x cursor(1, 1)[-1].'x'")
+ feed_command("cnoremap <expr> x cursor(1, 1)[-1].'x'")
feed(":%s/tw/tox/g<enter>")
expect(default_text:gsub("tw", "tox"))
@@ -1366,7 +1511,7 @@ describe("'inccommand' and :cnoremap", function()
it("work when a mapping disables 'inccommand'", function()
for _, case in pairs(cases) do
refresh(case)
- execute("cnoremap <expr> x execute('set inccommand=')[-1]")
+ feed_command("cnoremap <expr> x execute('set inccommand=')[-1]")
feed(":%s/tw/toxa/g<enter>")
expect(default_text:gsub("tw", "toa"))
@@ -1440,7 +1585,7 @@ describe("'inccommand' autocommands", function()
local function register_autocmd(event)
meths.set_var(event .. "_fired", {})
- execute("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))")
+ feed_command("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))")
end
it('are not fired when splitting', function()
@@ -1493,12 +1638,12 @@ describe("'inccommand' split windows", function()
refresh()
feed("gg")
- execute("vsplit")
- execute("split")
+ feed_command("vsplit")
+ feed_command("split")
feed(":%s/tw")
screen:expect([[
Inc substitution on {10:|}Inc substitution on|
- two lines {10:|}two lines |
+ {12:tw}o lines {10:|}{12:tw}o lines |
{10:|} |
{15:~ }{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
@@ -1513,13 +1658,13 @@ describe("'inccommand' split windows", function()
{15:~ }{10:|}{15:~ }|
{11:[No Name] [+] }{10:|}{15:~ }|
Inc substitution on {10:|}{15:~ }|
- two lines {10:|}{15:~ }|
+ {12:tw}o lines {10:|}{15:~ }|
{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
{10:[No Name] [+] [No Name] [+] }|
- |2| two lines |
- |
+ |2| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1530,14 +1675,14 @@ describe("'inccommand' split windows", function()
]])
feed("<esc>")
- execute("only")
- execute("split")
- execute("vsplit")
+ feed_command("only")
+ feed_command("split")
+ feed_command("vsplit")
feed(":%s/tw")
screen:expect([[
Inc substitution on {10:|}Inc substitution on|
- two lines {10:|}two lines |
+ {12:tw}o lines {10:|}{12:tw}o lines |
{10:|} |
{15:~ }{10:|}{15:~ }|
{15:~ }{10:|}{15:~ }|
@@ -1552,13 +1697,13 @@ describe("'inccommand' split windows", function()
{15:~ }{10:|}{15:~ }|
{11:[No Name] [+] }{10:[No Name] [+] }|
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
{10:[No Name] [+] }|
- |2| two lines |
- |
+ |2| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1581,13 +1726,13 @@ describe("'inccommand' split windows", function()
it("are not affected by various settings", function()
for _, setting in pairs(settings) do
refresh()
- execute("set " .. setting)
+ feed_command("set " .. setting)
feed(":%s/tw")
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
@@ -1607,8 +1752,8 @@ describe("'inccommand' split windows", function()
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
- |2| two lines |
- |
+ |2| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1621,3 +1766,693 @@ describe("'inccommand' split windows", function()
end)
end)
+
+describe("'inccommand' with 'gdefault'", function()
+ before_each(function()
+ clear()
+ end)
+
+ it("does not lock up #7244", function()
+ common_setup(nil, "nosplit", "{")
+ command("set gdefault")
+ feed(":s/{\\n")
+ eq({mode='c', blocking=false}, nvim("get_mode"))
+ feed("/A<Enter>")
+ expect("A")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+ end)
+
+ it("with multiline text and range, does not lock up #7244", function()
+ common_setup(nil, "nosplit", "{\n\n{")
+ command("set gdefault")
+ feed(":%s/{\\n")
+ eq({mode='c', blocking=false}, nvim("get_mode"))
+ feed("/A<Enter>")
+ expect("A\nA")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+ end)
+
+ it("does not crash on zero-width matches #7485", function()
+ common_setup(nil, "split", default_text)
+ command("set gdefault")
+ feed("gg")
+ feed("Vj")
+ feed(":s/\\%V")
+ eq({mode='c', blocking=false}, nvim("get_mode"))
+ feed("<Esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+ end)
+
+ it("removes highlights after abort for a zero-width match", function()
+ local screen = Screen.new(30,5)
+ common_setup(screen, "nosplit", default_text)
+ command("set gdefault")
+
+ feed(":%s/\\%1c/a/")
+ screen:expect([[
+ {12:a}Inc substitution on |
+ {12:a}two lines |
+ {12:a} |
+ {15:~ }|
+ :%s/\%1c/a/^ |
+ ]])
+
+ feed("<Esc>")
+ screen:expect([[
+ Inc substitution on |
+ two lines |
+ ^ |
+ {15:~ }|
+ |
+ ]])
+ end)
+
+end)
+
+describe(":substitute", function()
+ local screen = Screen.new(30,15)
+
+ before_each(function()
+ clear()
+ end)
+
+ it(", inccommand=split, highlights multiline substitutions", function()
+ common_setup(screen, "split", multiline_text)
+ feed("gg")
+
+ feed(":%s/2\\_.*X")
+ screen:expect([[
+ 1 {12:2 3} |
+ {12:A B C} |
+ {12:4 5 6} |
+ {12:X} Y Z |
+ 7 8 9 |
+ {11:[No Name] [+] }|
+ |1| 1 {12:2 3} |
+ |2|{12: A B C} |
+ |3|{12: 4 5 6} |
+ |4|{12: X} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/2\_.*X^ |
+ ]])
+
+ feed("/MMM")
+ screen:expect([[
+ 1 {12:MMM} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| 1 {12:MMM} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/2\_.*X/MMM^ |
+ ]])
+
+ feed("\\rK\\rLLL")
+ screen:expect([[
+ 1 {12:MMM} |
+ {12:K} |
+ {12:LLL} Y Z |
+ 7 8 9 |
+ |
+ {11:[No Name] [+] }|
+ |1| 1 {12:MMM} |
+ |2|{12: K} |
+ |3|{12: LLL} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/2\_.*X/MMM\rK\rLLL^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, highlights multiline substitutions", function()
+ common_setup(screen, "nosplit", multiline_text)
+ feed("gg")
+
+ feed(":%s/2\\_.*X/MMM")
+ screen:expect([[
+ 1 {12:MMM} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/2\_.*X/MMM^ |
+ ]])
+
+ feed("\\rK\\rLLL")
+ screen:expect([[
+ 1 {12:MMM} |
+ {12:K} |
+ {12:LLL} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/2\_.*X/MMM\rK\rLLL^ |
+ ]])
+ end)
+
+ it(", inccommand=split, highlights multiple matches on a line", function()
+ common_setup(screen, "split", multimatch_text)
+ command("set gdefault")
+ feed("gg")
+
+ feed(":%s/a/XLK")
+ screen:expect([[
+ {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r|
+ x |
+ |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:X}|
+ {12:LK} r |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/a/XLK^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, highlights multiple matches on a line", function()
+ common_setup(screen, "nosplit", multimatch_text)
+ command("set gdefault")
+ feed("gg")
+
+ feed(":%s/a/XLK")
+ screen:expect([[
+ {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r|
+ x |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/a/XLK^ |
+ ]])
+ end)
+
+ it(", inccommand=split, with \\zs", function()
+ common_setup(screen, "split", multiline_text)
+ feed("gg")
+
+ feed(":%s/[0-9]\\n\\zs[A-Z]/OKO")
+ screen:expect([[
+ 1 2 3 |
+ {12:OKO} B C |
+ 4 5 6 |
+ {12:OKO} Y Z |
+ 7 8 9 |
+ {11:[No Name] [+] }|
+ |1| 1 2 3 |
+ |2| {12:OKO} B C |
+ |3| 4 5 6 |
+ |4| {12:OKO} Y Z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/[0-9]\n\zs[A-Z]/OKO^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, with \\zs", function()
+ common_setup(screen, "nosplit", multiline_text)
+ feed("gg")
+
+ feed(":%s/[0-9]\\n\\zs[A-Z]/OKO")
+ screen:expect([[
+ 1 2 3 |
+ {12:OKO} B C |
+ 4 5 6 |
+ {12:OKO} Y Z |
+ 7 8 9 |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/[0-9]\n\zs[A-Z]/OKO^ |
+ ]])
+ end)
+
+ it(", inccommand=split, substitutions of different length",
+ function()
+ common_setup(screen, "split", "T T123 T2T TTT T090804\nx")
+
+ feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g")
+ screen:expect([[
+ T {12:123123} {12:22}T TTT {12:090804090804} |
+ x |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| T {12:123123} {12:22}T TTT {12:090804090}|
+ {12:804} |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/T\([0-9]\+\)/\1\1/g^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, substitutions of different length", function()
+ common_setup(screen, "nosplit", "T T123 T2T TTT T090804\nx")
+
+ feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g")
+ screen:expect([[
+ T {12:123123} {12:22}T TTT {12:090804090804} |
+ x |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/T\([0-9]\+\)/\1\1/g^ |
+ ]])
+ end)
+
+ it(", inccommand=split, contraction of lines", function()
+ local text = [[
+ T T123 T T123 T2T TT T23423424
+ x
+ afa Q
+ adf la;lkd R
+ alx
+ ]]
+
+ common_setup(screen, "split", text)
+ feed(":%s/[QR]\\n")
+ screen:expect([[
+ afa {12:Q} |
+ adf la;lkd {12:R} |
+ alx |
+ |
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |3| afa {12:Q} |
+ |4|{12: }adf la;lkd {12:R} |
+ |5|{12: }alx |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/[QR]\n^ |
+ ]])
+
+ feed("/KKK")
+ screen:expect([[
+ x |
+ afa {12:KKK}adf la;lkd {12:KKK}alx |
+ |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |3| afa {12:KKK}adf la;lkd {12:KKK}alx |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/[QR]\n/KKK^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, contraction of lines", function()
+ local text = [[
+ T T123 T T123 T2T TT T23423424
+ x
+ afa Q
+ adf la;lkd R
+ alx
+ ]]
+
+ common_setup(screen, "nosplit", text)
+ feed(":%s/[QR]\\n/KKK")
+ screen:expect([[
+ T T123 T T123 T2T TT T23423424|
+ x |
+ afa {12:KKK}adf la;lkd {12:KKK}alx |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/[QR]\n/KKK^ |
+ ]])
+ end)
+
+ it(", inccommand=split, multibyte text", function()
+ common_setup(screen, "split", multibyte_text)
+ feed(":%s/£.*ѫ/X¥¥")
+ screen:expect([[
+ {12:X¥¥} |
+ a{12:X¥¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ |
+ {11:[No Name] [+] }|
+ |1| {12:X¥¥} PEPPERS |
+ |2| {12:X¥¥} |
+ |3| a{12:X¥¥}¥KOL |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/£.*ѫ/X¥¥^ |
+ ]])
+
+ feed("\\ra££ ¥")
+ screen:expect([[
+ {12:a££ ¥} |
+ a{12:X¥¥} |
+ {12:a££ ¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ {11:[No Name] [+] }|
+ |1| {12:X¥¥} |
+ |2|{12: a££ ¥} PEPPERS |
+ |3| {12:X¥¥} |
+ |4|{12: a££ ¥} |
+ |5| a{12:X¥¥} |
+ |6|{12: a££ ¥}¥KOL |
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/£.*ѫ/X¥¥\ra££ ¥^ |
+ ]])
+ end)
+
+ it(", inccommand=nosplit, multibyte text", function()
+ common_setup(screen, "nosplit", multibyte_text)
+ feed(":%s/£.*ѫ/X¥¥")
+ screen:expect([[
+ {12:X¥¥} PEPPERS |
+ {12:X¥¥} |
+ a{12:X¥¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/£.*ѫ/X¥¥^ |
+ ]])
+
+ feed("\\ra££ ¥")
+ screen:expect([[
+ {12:X¥¥} |
+ {12:a££ ¥} PEPPERS |
+ {12:X¥¥} |
+ {12:a££ ¥} |
+ a{12:X¥¥} |
+ {12:a££ ¥}¥KOL |
+ £ ¥ libm |
+ £ ¥ |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/£.*ѫ/X¥¥\ra££ ¥^ |
+ ]])
+ end)
+
+ it(", inccommand=split, small cmdwinheight", function()
+ common_setup(screen, "split", long_multiline_text)
+ command("set cmdwinheight=2")
+
+ feed(":%s/[a-z]")
+ screen:expect([[
+ X Y Z |
+ 7 8 9 |
+ K L M |
+ {12:a} b c |
+ {12:d} e f |
+ {12:q} r s |
+ {12:x} y z |
+ £ {12:m} n |
+ {12:t} œ ¥ |
+ |
+ {11:[No Name] [+] }|
+ | 7| {12:a} b c |
+ | 8| {12:d} e f |
+ {10:[Preview] }|
+ :%s/[a-z]^ |
+ ]])
+
+ feed("/JLKR £")
+ screen:expect([[
+ X Y Z |
+ 7 8 9 |
+ K L M |
+ {12:JLKR £} b c |
+ {12:JLKR £} e f |
+ {12:JLKR £} r s |
+ {12:JLKR £} y z |
+ £ {12:JLKR £} n |
+ {12:JLKR £} œ ¥ |
+ |
+ {11:[No Name] [+] }|
+ | 7| {12:JLKR £} b c |
+ | 8| {12:JLKR £} e f |
+ {10:[Preview] }|
+ :%s/[a-z]/JLKR £^ |
+ ]])
+
+ feed("\\rѫ ab \\rXXXX")
+ screen:expect([[
+ 7 8 9 |
+ K L M |
+ {12:JLKR £} |
+ {12:ѫ ab } |
+ {12:XXXX} b c |
+ {12:JLKR £} |
+ {12:ѫ ab } |
+ {12:XXXX} e f |
+ {12:JLKR £} |
+ {11:[No Name] [+] }|
+ | 7| {12:JLKR £} |
+ | 8|{12: ѫ ab } |
+ {10:[Preview] }|
+ :%s/[a-z]/JLKR £\rѫ ab \rXXX|
+ X^ |
+ ]])
+ end)
+
+ it(", inccommand=split, large cmdwinheight", function()
+ common_setup(screen, "split", long_multiline_text)
+ command("set cmdwinheight=11")
+
+ feed(":%s/. .$")
+ screen:expect([[
+ t {12:œ ¥} |
+ {11:[No Name] [+] }|
+ | 1| 1 {12:2 3} |
+ | 2| A {12:B C} |
+ | 3| 4 {12:5 6} |
+ | 4| X {12:Y Z} |
+ | 5| 7 {12:8 9} |
+ | 6| K {12:L M} |
+ | 7| a {12:b c} |
+ | 8| d {12:e f} |
+ | 9| q {12:r s} |
+ |10| x {12:y z} |
+ |11| £ {12:m n} |
+ {10:[Preview] }|
+ :%s/. .$^ |
+ ]])
+
+ feed("/ YYY")
+ screen:expect([[
+ t {12: YYY} |
+ {11:[No Name] [+] }|
+ | 1| 1 {12: YYY} |
+ | 2| A {12: YYY} |
+ | 3| 4 {12: YYY} |
+ | 4| X {12: YYY} |
+ | 5| 7 {12: YYY} |
+ | 6| K {12: YYY} |
+ | 7| a {12: YYY} |
+ | 8| d {12: YYY} |
+ | 9| q {12: YYY} |
+ |10| x {12: YYY} |
+ |11| £ {12: YYY} |
+ {10:[Preview] }|
+ :%s/. .$/ YYY^ |
+ ]])
+
+ feed("\\r KKK")
+ screen:expect([[
+ a {12: YYY} |
+ {11:[No Name] [+] }|
+ | 1| 1 {12: YYY} |
+ | 2|{12: KKK} |
+ | 3| A {12: YYY} |
+ | 4|{12: KKK} |
+ | 5| 4 {12: YYY} |
+ | 6|{12: KKK} |
+ | 7| X {12: YYY} |
+ | 8|{12: KKK} |
+ | 9| 7 {12: YYY} |
+ |10|{12: KKK} |
+ |11| K {12: YYY} |
+ {10:[Preview] }|
+ :%s/. .$/ YYY\r KKK^ |
+ ]])
+ end)
+
+ it(", inccommand=split, lookaround", function()
+ common_setup(screen, "split", "something\neverything\nsomeone")
+ feed([[:%s/\(some\)\@<lt>=thing/one/]])
+ screen:expect([[
+ some{12:one} |
+ everything |
+ someone |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| some{12:one} |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/\(some\)\@<=thing/one/^ |
+ ]])
+
+ feed("<C-c>")
+ wait()
+ feed([[:%s/\(some\)\@<lt>!thing/one/]])
+ screen:expect([[
+ something |
+ every{12:one} |
+ someone |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |2| every{12:one} |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/\(some\)\@<!thing/one/^ |
+ ]])
+
+ feed([[<C-c>]])
+ wait()
+ feed([[:%s/some\(thing\)\@=/every/]])
+ screen:expect([[
+ {12:every}thing |
+ everything |
+ someone |
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |1| {12:every}thing |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/some\(thing\)\@=/every/^ |
+ ]])
+
+ feed([[<C-c>]])
+ wait()
+ feed([[:%s/some\(thing\)\@!/every/]])
+ screen:expect([[
+ everything |
+ {12:every}one |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ |3| {12:every}one |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/some\(thing\)\@!/every/^ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
index cec19250d2..29d974b709 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -1,5 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim
+local clear, feed_command, nvim = helpers.clear, helpers.feed_command, helpers.nvim
local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq
local expect = helpers.expect
local Screen = require('test.functional.ui.screen')
@@ -12,7 +12,7 @@ describe('mappings', function()
local add_mapping = function(mapping, send)
local cmd = "nnoremap "..mapping.." :call rpcnotify("..cid..", 'mapped', '"
..send:gsub('<', '<lt>').."')<cr>"
- execute(cmd)
+ feed_command(cmd)
end
local check_mapping = function(mapping, expected)
@@ -57,7 +57,7 @@ describe('feeding large chunks of input with <Paste>', function()
clear()
screen = Screen.new()
screen:attach()
- execute('set ruler')
+ feed_command('set ruler')
end)
it('ok', function()
diff --git a/test/functional/ui/mode_spec.lua b/test/functional/ui/mode_spec.lua
new file mode 100644
index 0000000000..f0cedfeeb5
--- /dev/null
+++ b/test/functional/ui/mode_spec.lua
@@ -0,0 +1,227 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local command, eval = helpers.command, helpers.eval
+local eq = helpers.eq
+
+describe('ui mode_change event', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25, 4)
+ screen:attach({rgb= true})
+ screen:set_default_attr_ids( {
+ [0] = {bold=true, foreground=255},
+ [1] = {bold=true, reverse=true},
+ [2] = {bold=true},
+ [3] = {reverse=true},
+ })
+ end)
+
+ it('works in normal mode', function()
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]],nil,nil,function ()
+ eq("normal", screen.mode)
+ end)
+
+ feed('d')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]],nil,nil,function ()
+ eq("operator", screen.mode)
+ end)
+
+ feed('<esc>')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]],nil,nil,function ()
+ eq("normal", screen.mode)
+ end)
+ end)
+
+ it('works in insert mode', function()
+ feed('i')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {2:-- INSERT --} |
+ ]],nil,nil,function ()
+ eq("insert", screen.mode)
+ end)
+
+ feed('word<esc>')
+ screen:expect([[
+ wor^d |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]], nil, nil, function ()
+ eq("normal", screen.mode)
+ end)
+
+ command("set showmatch")
+ eq(eval('&matchtime'), 5) -- tenths of seconds
+ feed('a(stuff')
+ screen:expect([[
+ word(stuff^ |
+ {0:~ }|
+ {0:~ }|
+ {2:-- INSERT --} |
+ ]], nil, nil, function ()
+ eq("insert", screen.mode)
+ end)
+
+ feed(')')
+ screen:expect([[
+ word^(stuff) |
+ {0:~ }|
+ {0:~ }|
+ {2:-- INSERT --} |
+ ]], nil, nil, function ()
+ eq("showmatch", screen.mode)
+ end)
+
+ screen:sleep(400)
+ screen:expect([[
+ word(stuff)^ |
+ {0:~ }|
+ {0:~ }|
+ {2:-- INSERT --} |
+ ]], nil, nil, function ()
+ eq("insert", screen.mode)
+ end)
+ end)
+
+ it('works in replace mode', function()
+ feed('R')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {2:-- REPLACE --} |
+ ]], nil, nil, function ()
+ eq("replace", screen.mode)
+ end)
+
+ feed('word<esc>')
+ screen:expect([[
+ wor^d |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]], nil, nil, function ()
+ eq("normal", screen.mode)
+ end)
+ end)
+
+ it('works in cmdline mode', function()
+ feed(':')
+ screen:expect([[
+ |
+ {0:~ }|
+ {0:~ }|
+ :^ |
+ ]],nil,nil,function ()
+ eq("cmdline_normal", screen.mode)
+ end)
+
+ feed('x<left>')
+ screen:expect([[
+ |
+ {0:~ }|
+ {0:~ }|
+ :^x |
+ ]],nil,nil,function ()
+ eq("cmdline_insert", screen.mode)
+ end)
+
+ feed('<insert>')
+ screen:expect([[
+ |
+ {0:~ }|
+ {0:~ }|
+ :^x |
+ ]],nil,nil,function ()
+ eq("cmdline_replace", screen.mode)
+ end)
+
+
+ feed('<right>')
+ screen:expect([[
+ |
+ {0:~ }|
+ {0:~ }|
+ :x^ |
+ ]],nil,nil,function ()
+ eq("cmdline_normal", screen.mode)
+ end)
+
+ feed('<esc>')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]],nil,nil,function ()
+ eq("normal", screen.mode)
+ end)
+ end)
+
+ it('works in visal mode', function()
+ insert("text")
+ feed('v')
+ screen:expect([[
+ tex^t |
+ {0:~ }|
+ {0:~ }|
+ {2:-- VISUAL --} |
+ ]],nil,nil,function ()
+ eq("visual", screen.mode)
+ end)
+
+ feed('<esc>')
+ screen:expect([[
+ tex^t |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]],nil,nil,function ()
+ eq("normal", screen.mode)
+ end)
+
+ command('set selection=exclusive')
+ feed('v')
+ screen:expect([[
+ tex^t |
+ {0:~ }|
+ {0:~ }|
+ {2:-- VISUAL --} |
+ ]],nil,nil,function ()
+ eq("visual_select", screen.mode)
+ end)
+
+ feed('<esc>')
+ screen:expect([[
+ tex^t |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]],nil,nil,function ()
+ eq("normal", screen.mode)
+ end)
+ end)
+end)
+
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index b2fbedfb5e..3daf92eea0 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1,21 +1,18 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
-local insert, execute = helpers.insert, helpers.execute
+local insert, feed_command = helpers.insert, helpers.feed_command
local eq, funcs = helpers.eq, helpers.funcs
if helpers.pending_win32(pending) then return end
-describe('Mouse input', function()
+describe('ui/mouse/input', function()
local screen
before_each(function()
clear()
meths.set_option('mouse', 'a')
meths.set_option('listchars', 'eol:$')
- -- set mousetime to very high value to ensure that even in valgrind/travis,
- -- nvim will still pick multiple clicks
- meths.set_option('mousetime', 5000)
screen = Screen.new(25, 5)
screen:attach()
screen:set_default_attr_ids({
@@ -119,13 +116,12 @@ describe('Mouse input', function()
sel = { bold=true },
fill = { reverse=true }
})
- screen.timeout = 15000
end)
it('in tabline on filler space moves tab to the end', function()
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -160,9 +156,9 @@ describe('Mouse input', function()
return
end
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -190,9 +186,9 @@ describe('Mouse input', function()
end)
it('in tabline to the right moves tab right', function()
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -220,9 +216,9 @@ describe('Mouse input', function()
end)
it('out of tabline under filler space moves tab to the end', function()
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -265,9 +261,9 @@ describe('Mouse input', function()
return
end
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -303,9 +299,9 @@ describe('Mouse input', function()
end)
it('out of tabline to the right moves tab right', function()
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -352,9 +348,9 @@ describe('Mouse input', function()
end)
it('left click in default tabline (position 4) switches to tab', function()
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -375,9 +371,9 @@ describe('Mouse input', function()
it('left click in default tabline (position 24) closes tab', function()
meths.set_option('hidden', true)
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -398,9 +394,9 @@ describe('Mouse input', function()
it('double click in default tabline (position 4) opens new tab', function()
meths.set_option('hidden', true)
- execute('%delete')
+ feed_command('%delete')
insert('this is foo')
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
@@ -421,13 +417,13 @@ describe('Mouse input', function()
describe('%@ label', function()
before_each(function()
- execute([[
+ feed_command([[
function Test(...)
let g:reply = a:000
return copy(a:000) " Check for memory leaks: return should be freed
endfunction
]])
- execute([[
+ feed_command([[
function Test2(...)
return call('Test', a:000 + [2])
endfunction
@@ -533,9 +529,9 @@ describe('Mouse input', function()
fill = { reverse=true },
vis = { background=Screen.colors.LightGrey }
})
- execute('silent file foo | tabnew | file bar')
+ feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
- execute('tabprevious') -- go to first tab
+ feed_command('tabprevious') -- go to first tab
screen:expect([[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
mouse |
@@ -641,7 +637,7 @@ describe('Mouse input', function()
mouse scrolling
]])
screen:try_resize(53, 14)
- execute('sp', 'vsp')
+ feed_command('sp', 'vsp')
screen:expect([[
lines {4:|}lines |
to {4:|}to |
@@ -754,12 +750,12 @@ describe('Mouse input', function()
})
feed('ggdG')
- execute('set concealcursor=n')
- execute('set nowrap')
- execute('syntax match NonText "\\<amet\\>" conceal')
- execute('syntax match NonText "\\cs\\|g." conceal cchar=X')
- execute('syntax match NonText "\\%(lo\\|cl\\)." conceal')
- execute('syntax match NonText "Lo" conceal cchar=Y')
+ feed_command('set concealcursor=n')
+ feed_command('set nowrap')
+ feed_command('syntax match NonText "\\<amet\\>" conceal')
+ feed_command('syntax match NonText "\\cs\\|g." conceal cchar=X')
+ feed_command('syntax match NonText "\\%(lo\\|cl\\)." conceal')
+ feed_command('syntax match NonText "Lo" conceal cchar=Y')
insert([[
Lorem ipsum dolor sit amet, consetetur sadipscing elitr.
@@ -770,7 +766,7 @@ describe('Mouse input', function()
end)
it('(level 1) click on non-wrapped lines', function()
- execute('let &conceallevel=1', 'echo')
+ feed_command('let &conceallevel=1', 'echo')
feed('<esc><LeftMouse><0,0>')
screen:expect([[
@@ -818,7 +814,7 @@ describe('Mouse input', function()
end) -- level 1 - non wrapped
it('(level 1) click on wrapped lines', function()
- execute('let &conceallevel=1', 'let &wrap=1', 'echo')
+ feed_command('let &conceallevel=1', 'let &wrap=1', 'echo')
feed('<esc><LeftMouse><0,0>')
screen:expect([[
@@ -867,7 +863,7 @@ describe('Mouse input', function()
it('(level 2) click on non-wrapped lines', function()
- execute('let &conceallevel=2', 'echo')
+ feed_command('let &conceallevel=2', 'echo')
feed('<esc><LeftMouse><0,0>')
screen:expect([[
@@ -915,7 +911,7 @@ describe('Mouse input', function()
end) -- level 2 - non wrapped
it('(level 2) click on wrapped lines', function()
- execute('let &conceallevel=2', 'let &wrap=1', 'echo')
+ feed_command('let &conceallevel=2', 'let &wrap=1', 'echo')
feed('<esc><LeftMouse><0,0>')
screen:expect([[
@@ -964,7 +960,7 @@ describe('Mouse input', function()
it('(level 3) click on non-wrapped lines', function()
- execute('let &conceallevel=3', 'echo')
+ feed_command('let &conceallevel=3', 'echo')
feed('<esc><LeftMouse><0,0>')
screen:expect([[
@@ -1012,7 +1008,7 @@ describe('Mouse input', function()
end) -- level 3 - non wrapped
it('(level 3) click on wrapped lines', function()
- execute('let &conceallevel=3', 'let &wrap=1', 'echo')
+ feed_command('let &conceallevel=3', 'let &wrap=1', 'echo')
feed('<esc><LeftMouse><0,0>')
screen:expect([[
diff --git a/test/functional/ui/quickfix_spec.lua b/test/functional/ui/quickfix_spec.lua
index 29b28fe9f0..b0d89ee3b6 100644
--- a/test/functional/ui/quickfix_spec.lua
+++ b/test/functional/ui/quickfix_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
-local insert, execute = helpers.insert, helpers.execute
+local insert, command = helpers.insert, helpers.command
describe('quickfix selection highlight', function()
@@ -28,8 +28,8 @@ describe('quickfix selection highlight', function()
})
meths.set_option('errorformat', '%m %l')
- execute('syntax on')
- execute('highlight Search guibg=Green')
+ command('syntax on')
+ command('highlight Search guibg=Green')
insert([[
Line 1
@@ -39,7 +39,7 @@ describe('quickfix selection highlight', function()
Line 5
]])
- execute('cad')
+ command('cad')
feed('gg')
screen:expect([[
@@ -52,12 +52,12 @@ describe('quickfix selection highlight', function()
{1:~ }|
{1:~ }|
{1:~ }|
- :cad |
+ |
]])
end)
it('using default Search highlight group', function()
- execute('copen')
+ command('copen')
screen:expect([[
Line 1 |
@@ -69,10 +69,10 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :copen |
+ |
]])
- execute('cnext')
+ command('cnext')
screen:expect([[
Line 1 |
@@ -84,14 +84,14 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :cnext |
+ |
]])
end)
it('using QuickFixLine highlight group', function()
- execute('highlight QuickFixLine guibg=Red')
+ command('highlight QuickFixLine guibg=Red')
- execute('copen')
+ command('copen')
screen:expect([[
Line 1 |
@@ -103,10 +103,10 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :copen |
+ |
]])
- execute('cnext')
+ command('cnext')
screen:expect([[
Line 1 |
@@ -118,16 +118,16 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :cnext |
+ |
]])
end)
it('combines with CursorLine', function()
- execute('set cursorline')
- execute('highlight QuickFixLine guifg=Red')
- execute('highlight CursorLine guibg=Fuchsia')
+ command('set cursorline')
+ command('highlight QuickFixLine guifg=Red')
+ command('highlight CursorLine guibg=Fuchsia')
- execute('copen')
+ command('copen')
screen:expect([[
{9:Line 1 }|
@@ -139,7 +139,7 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :copen |
+ |
]])
feed('j')
@@ -154,16 +154,16 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :copen |
+ |
]])
end)
it('QuickFixLine background takes precedence over CursorLine', function()
- execute('set cursorline')
- execute('highlight QuickFixLine guibg=Red')
- execute('highlight CursorLine guibg=Fuchsia')
+ command('set cursorline')
+ command('highlight QuickFixLine guibg=Red')
+ command('highlight CursorLine guibg=Fuchsia')
- execute('copen')
+ command('copen')
screen:expect([[
{9:Line 1 }|
@@ -175,7 +175,7 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :copen |
+ |
]])
feed('j')
@@ -190,7 +190,7 @@ describe('quickfix selection highlight', function()
|{3:5}| Line |
|| |
{4:[Quickfix List] }|
- :copen |
+ |
]])
end)
end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 54f43387dc..a6b7fb2997 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -181,6 +181,7 @@ end
-- expected: Expected screen state (string). Each line represents a screen
-- row. Last character of each row (typically "|") is stripped.
-- Common indentation is stripped.
+-- Used as `condition` if NOT a string; must be the ONLY arg then.
-- attr_ids: Expected text attributes. Screen rows are transformed according
-- to this table, as follows: each substring S composed of
-- characters having the same attributes will be substituted by
@@ -191,18 +192,24 @@ end
-- any: true: Succeed if `expected` matches ANY screen line(s).
-- false (default): `expected` must match screen exactly.
function Screen:expect(expected, attr_ids, attr_ignore, condition, any)
- -- remove the last line and dedent
- expected = dedent(expected:gsub('\n[ ]+$', ''))
local expected_rows = {}
- for row in expected:gmatch('[^\n]+') do
- -- the last character should be the screen delimiter
- row = row:sub(1, #row - 1)
- table.insert(expected_rows, row)
- end
- if not any then
- assert(self._height == #expected_rows,
- "Expected screen state's row count(" .. #expected_rows
- .. ') differs from configured height(' .. self._height .. ') of Screen.')
+ if type(expected) ~= "string" then
+ assert(not (attr_ids or attr_ignore or condition or any))
+ condition = expected
+ expected = nil
+ else
+ -- Remove the last line and dedent. Note that gsub returns more then one
+ -- value.
+ expected = dedent(expected:gsub('\n[ ]+$', ''), 0)
+ for row in expected:gmatch('[^\n]+') do
+ row = row:sub(1, #row - 1) -- Last char must be the screen delimiter.
+ table.insert(expected_rows, row)
+ end
+ if not any then
+ assert(self._height == #expected_rows,
+ "Expected screen state's row count(" .. #expected_rows
+ .. ') differs from configured height(' .. self._height .. ') of Screen.')
+ end
end
local ids = attr_ids or self._default_attr_ids
local ignore = attr_ignore or self._default_attr_ignore
@@ -218,7 +225,9 @@ function Screen:expect(expected, attr_ids, attr_ignore, condition, any)
actual_rows[i] = self:_row_repr(self._rows[i], ids, ignore)
end
- if any then
+ if expected == nil then
+ return
+ elseif any then
-- Search for `expected` anywhere in the screen lines.
local actual_screen_str = table.concat(actual_rows, '\n')
if nil == string.find(actual_screen_str, expected) then
@@ -242,7 +251,7 @@ function Screen:expect(expected, attr_ids, attr_ignore, condition, any)
..'Expected:\n |'..table.concat(msg_expected_rows, '|\n |')..'|\n'
..'Actual:\n |'..table.concat(actual_rows, '|\n |')..'|\n\n'..[[
To print the expect() call that would assert the current screen state, use
-screen:snaphot_util(). In case of non-deterministic failures, use
+screen:snapshot_util(). In case of non-deterministic failures, use
screen:redraw_debug() to show all intermediate screen states. ]])
end
end
@@ -276,18 +285,13 @@ function Screen:wait(check, timeout)
if failure_after_success then
print([[
-Warning: Screen changes have been received after the expected state was seen.
-This is probably due to an indeterminism in the test. Try adding
-`wait()` (or even a separate `screen:expect(...)`) at a point of possible
-indeterminism, typically in between a `feed()` or `execute()` which is non-
-synchronous, and a synchronous api call.
-
-Note that sometimes a `wait` can trigger redraws and consequently generate more
-indeterminism. If adding `wait` calls seems to increase the frequency of these
-messages, try removing every `wait` call in the test.
-
-If everything else fails, use Screen:redraw_debug to help investigate what is
- causing the problem.
+
+Warning: Screen changes were received after the expected state. This indicates
+indeterminism in the test. Try adding wait() (or screen:expect(...)) between
+asynchronous (feed(), nvim_input()) and synchronous API calls.
+ - Use Screen:redraw_debug() to investigate the problem.
+ - wait() can trigger redraws and consequently generate more indeterminism.
+ In that case try removing every wait().
]])
local tb = debug.traceback()
local index = string.find(tb, '\n%s*%[C]')
@@ -309,10 +313,13 @@ function Screen:_redraw(updates)
-- print(require('inspect')(update))
local method = update[1]
for i = 2, #update do
- local handler = self['_handle_'..method]
+ local handler_name = '_handle_'..method
+ local handler = self[handler_name]
if handler ~= nil then
handler(self, unpack(update[i]))
else
+ assert(self._on_event,
+ "Add Screen:"..handler_name.." or call Screen:set_on_event_handler")
self._on_event(method, update[i])
end
end
@@ -343,6 +350,11 @@ function Screen:_handle_resize(width, height)
}
end
+function Screen:_handle_mode_info_set(cursor_style_enabled, mode_info)
+ self._cursor_style_enabled = cursor_style_enabled
+ self._mode_info = mode_info
+end
+
function Screen:_handle_clear()
self:_clear_block(self._scroll_region.top, self._scroll_region.bot,
self._scroll_region.left, self._scroll_region.right)
@@ -374,9 +386,8 @@ function Screen:_handle_mouse_off()
self._mouse_enabled = false
end
-function Screen:_handle_mode_change(mode)
- assert(mode == 'insert' or mode == 'replace'
- or mode == 'normal' or mode == 'cmdline')
+function Screen:_handle_mode_change(mode, idx)
+ assert(mode == self._mode_info[idx+1].name)
self.mode = mode
end
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index e511234e5e..b31d9cb32f 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -1,12 +1,13 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.clear
-local feed, execute = helpers.feed, helpers.execute
+local feed, command = helpers.feed, helpers.command
local insert = helpers.insert
local eq = helpers.eq
local eval = helpers.eval
+local iswin = helpers.iswin
-describe('Initial screen', function()
+describe('screen', function()
local screen
local nvim_argv = {helpers.nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N',
'--cmd', 'set shortmess+=I background=light noswapfile belloff= noshowcmd noruler',
@@ -27,7 +28,7 @@ describe('Initial screen', function()
screen:detach()
end)
- it('is the default initial screen', function()
+ it('default initial screen', function()
screen:expect([[
^ |
{0:~ }|
@@ -73,33 +74,29 @@ describe('Screen', function()
describe(':suspend', function()
it('is forwarded to the UI', function()
local function check()
- if not screen.suspended then
- return 'Screen was not suspended'
- end
+ eq(true, screen.suspended)
end
- execute('suspend')
- screen:wait(check)
+ command('suspend')
+ screen:expect(check)
screen.suspended = false
feed('<c-z>')
- screen:wait(check)
+ screen:expect(check)
end)
end)
describe('bell/visual bell', function()
it('is forwarded to the UI', function()
feed('<left>')
- screen:wait(function()
- if not screen.bell or screen.visual_bell then
- return 'Bell was not sent'
- end
+ screen:expect(function()
+ eq(true, screen.bell)
+ eq(false, screen.visual_bell)
end)
screen.bell = false
- execute('set visualbell')
+ command('set visualbell')
feed('<left>')
- screen:wait(function()
- if not screen.visual_bell or screen.bell then
- return 'Visual bell was not sent'
- end
+ screen:expect(function()
+ eq(true, screen.visual_bell)
+ eq(false, screen.bell)
end)
end)
end)
@@ -107,36 +104,28 @@ describe('Screen', function()
describe(':set title', function()
it('is forwarded to the UI', function()
local expected = 'test-title'
- execute('set titlestring='..expected)
- execute('set title')
- screen:wait(function()
- local actual = screen.title
- if actual ~= expected then
- return 'Expected title to be "'..expected..'" but was "'..actual..'"'
- end
+ command('set titlestring='..expected)
+ command('set title')
+ screen:expect(function()
+ eq(expected, screen.title)
end)
end)
it('has correct default title with unnamed file', function()
local expected = '[No Name] - NVIM'
- execute('set title')
- screen:wait(function()
- local actual = screen.title
- if actual ~= expected then
- return 'Expected title to be "'..expected..'" but was "'..actual..'"'
- end
+ command('set title')
+ screen:expect(function()
+ eq(expected, screen.title)
end)
end)
it('has correct default title with named file', function()
- local expected = 'myfile (/mydir) - NVIM'
- execute('set title')
- execute('file /mydir/myfile')
- screen:wait(function()
- local actual = screen.title
- if actual ~= expected then
- return 'Expected title to be "'..expected..'" but was "'..actual..'"'
- end
+ local expected = (iswin() and 'myfile (C:\\mydir) - NVIM'
+ or 'myfile (/mydir) - NVIM')
+ command('set title')
+ command(iswin() and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
+ screen:expect(function()
+ eq(expected, screen.title)
end)
end)
end)
@@ -144,13 +133,10 @@ describe('Screen', function()
describe(':set icon', function()
it('is forwarded to the UI', function()
local expected = 'test-icon'
- execute('set iconstring='..expected)
- execute('set icon')
- screen:wait(function()
- local actual = screen.icon
- if actual ~= expected then
- return 'Expected title to be "'..expected..'" but was "'..actual..'"'
- end
+ command('set iconstring='..expected)
+ command('set icon')
+ screen:expect(function()
+ eq(expected, screen.icon)
end)
end)
end)
@@ -158,7 +144,7 @@ describe('Screen', function()
describe('window', function()
describe('split', function()
it('horizontal', function()
- execute('sp')
+ command('sp')
screen:expect([[
^ |
{0:~ }|
@@ -173,13 +159,13 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{3:[No Name] }|
- :sp |
+ |
]])
end)
it('horizontal and resize', function()
- execute('sp')
- execute('resize 8')
+ command('sp')
+ command('resize 8')
screen:expect([[
^ |
{0:~ }|
@@ -194,12 +180,14 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{3:[No Name] }|
- :resize 8 |
+ |
]])
end)
it('horizontal and vertical', function()
- execute('sp', 'vsp', 'vsp')
+ command('sp')
+ command('vsp')
+ command('vsp')
screen:expect([[
^ {3:|} {3:|} |
{0:~ }{3:|}{0:~ }{3:|}{0:~ }|
@@ -239,7 +227,9 @@ describe('Screen', function()
describe('tabnew', function()
it('creates a new buffer', function()
- execute('sp', 'vsp', 'vsp')
+ command('sp')
+ command('vsp')
+ command('vsp')
insert('hello')
screen:expect([[
hell^o {3:|}hello {3:|}hello |
@@ -257,7 +247,7 @@ describe('Screen', function()
{3:[No Name] [+] }|
|
]])
- execute('tabnew')
+ command('tabnew')
insert('hello2')
feed('h')
screen:expect([[
@@ -276,7 +266,7 @@ describe('Screen', function()
{0:~ }|
|
]])
- execute('tabprevious')
+ command('tabprevious')
screen:expect([[
{2: }{6:4}{2:+ [No Name] }{4: + [No Name] }{3: }{4:X}|
hell^o {3:|}hello {3:|}hello |
@@ -321,9 +311,9 @@ describe('Screen', function()
describe('normal mode', function()
-- https://code.google.com/p/vim/issues/detail?id=339
it("setting 'ruler' doesn't reset the preferred column", function()
- execute('set virtualedit=')
+ command('set virtualedit=')
feed('i0123456<cr>789<esc>kllj')
- execute('set ruler')
+ command('set ruler')
feed('k')
screen:expect([[
0123^456 |
@@ -339,7 +329,7 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :set ruler 1,5 All |
+ 1,5 All |
]])
end)
end)
@@ -404,7 +394,9 @@ describe('Screen', function()
split
windows
]])
- execute('sp', 'vsp', 'vsp')
+ command('sp')
+ command('vsp')
+ command('vsp')
screen:expect([[
and {3:|}and {3:|}and |
clearing {3:|}clearing {3:|}clearing |
@@ -576,124 +568,61 @@ describe('Screen', function()
end)
end)
- describe('mode change', function()
- before_each(function()
- screen:try_resize(25, 5)
- end)
-
- it('works in normal mode', function()
- screen:expect([[
- ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]],nil,nil,function ()
- eq("normal", screen.mode)
- end)
- end)
-
- it('works in insert mode', function()
- feed('i')
+ describe('press enter', function()
+ it('does not crash on <F1> at “Press ENTER”', function()
+ command('nnoremap <F1> :echo "TEST"<CR>')
+ feed(':ls<CR>')
screen:expect([[
- ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {2:-- INSERT --} |
- ]],nil,nil,function ()
- eq("insert", screen.mode)
- end)
-
- feed('word<esc>')
- screen:expect([[
- wor^d |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]], nil, nil, function ()
- eq("normal", screen.mode)
- end)
- end)
-
- it('works in replace mode', function()
- feed('R')
- screen:expect([[
- ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {2:-- REPLACE --} |
- ]], nil, nil, function ()
- eq("replace", screen.mode)
- end)
-
- feed('word<esc>')
- screen:expect([[
- wor^d |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]], nil, nil, function ()
- eq("normal", screen.mode)
- end)
- end)
-
- it('works in cmdline mode', function()
- feed(':')
- screen:expect([[
- |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- :^ |
- ]],nil,nil,function ()
- eq("cmdline", screen.mode)
- end)
-
- feed('<esc>/')
- screen:expect([[
- |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- /^ |
- ]],nil,nil,function ()
- eq("cmdline", screen.mode)
- end)
-
-
- feed('<esc>?')
- screen:expect([[
- |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- ?^ |
- ]],nil,nil,function ()
- eq("cmdline", screen.mode)
- end)
-
- feed('<esc>')
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ :ls |
+ 1 %a "[No Name]" line 1 |
+ {7:Press ENTER or type command to continue}^ |
+ ]])
+ feed('<F1>')
screen:expect([[
- ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]],nil,nil,function ()
- eq("normal", screen.mode)
- end)
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ TEST |
+ ]])
end)
end)
+end)
- it('nvim_ui_attach() handles very large width/height #2180', function()
- screen:detach()
- screen = Screen.new(999, 999)
+describe('nvim_ui_attach()', function()
+ before_each(function()
+ clear()
+ end)
+ it('handles very large width/height #2180', function()
+ local screen = Screen.new(999, 999)
screen:attach()
eq(999, eval('&lines'))
eq(999, eval('&columns'))
end)
+ it('invalid option returns error', function()
+ local screen = Screen.new()
+ local status, rv = pcall(function() screen:attach({foo={'foo'}}) end)
+ eq(false, status)
+ eq('No such ui option', rv:match("No such .*"))
+ end)
end)
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index 3914648e8f..11b18d015f 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local execute = helpers.execute
+local feed_command = helpers.feed_command
if helpers.pending_win32(pending) then return end
@@ -22,7 +22,7 @@ describe('search highlighting', function()
end)
it('is disabled by ":set nohlsearch"', function()
- execute('set nohlsearch')
+ feed_command('set nohlsearch')
insert("some text\nmore text")
feed("gg/text<cr>")
screen:expect([[
@@ -79,7 +79,7 @@ describe('search highlighting', function()
/\<text\> |
]])
- execute("nohlsearch")
+ feed_command("nohlsearch")
screen:expect([[
some text |
more textstuff |
@@ -92,8 +92,8 @@ describe('search highlighting', function()
end)
it('works with incsearch', function()
- execute('set hlsearch')
- execute('set incsearch')
+ feed_command('set hlsearch')
+ feed_command('set incsearch')
insert([[
the first line
in a little file
@@ -156,8 +156,8 @@ describe('search highlighting', function()
end)
it('works with incsearch and offset', function()
- execute('set hlsearch')
- execute('set incsearch')
+ feed_command('set hlsearch')
+ feed_command('set incsearch')
insert([[
not the match you're looking for
the match is here]])
@@ -198,7 +198,7 @@ describe('search highlighting', function()
end)
it('works with multiline regexps', function()
- execute('set hlsearch')
+ feed_command('set hlsearch')
feed('4oa repeated line<esc>')
feed('/line\\na<cr>')
screen:expect([[
@@ -234,19 +234,19 @@ describe('search highlighting', function()
[6] = {italic = true, background = colors.Magenta},
[7] = {bold = true, background = colors.Yellow},
} )
- execute('set hlsearch')
+ feed_command('set hlsearch')
insert([[
very special text
]])
- execute("syntax on")
- execute("highlight MyGroup guibg=Green gui=bold")
- execute("highlight MyGroup2 guibg=Magenta gui=italic")
- execute("call matchadd('MyGroup', 'special')")
- execute("call matchadd('MyGroup2', 'text', 0)")
+ feed_command("syntax on")
+ feed_command("highlight MyGroup guibg=Green gui=bold")
+ feed_command("highlight MyGroup2 guibg=Magenta gui=italic")
+ feed_command("call matchadd('MyGroup', 'special')")
+ feed_command("call matchadd('MyGroup2', 'text', 0)")
-- searchhl and matchadd matches are exclusive, only the higest priority
-- is used (and matches with lower priorities are not combined)
- execute("/ial te")
+ feed_command("/ial te")
screen:expect([[
very {5:spec^ial}{2: te}{6:xt} |
|
@@ -257,7 +257,7 @@ describe('search highlighting', function()
{4:search hit BOTTOM, continuing at TOP} |
]])
- execute("call clearmatches()")
+ feed_command("call clearmatches()")
screen:expect([[
very spec{2:^ial te}xt |
|
@@ -270,7 +270,7 @@ describe('search highlighting', function()
-- searchhl has priority over syntax, but in this case
-- nonconflicting attributes are combined
- execute("syntax keyword MyGroup special")
+ feed_command("syntax keyword MyGroup special")
screen:expect([[
very {5:spec}{7:^ial}{2: te}xt |
|
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index d02fc83809..e5c96f2ec0 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
+local clear, feed, command = helpers.clear, helpers.feed, helpers.command
if helpers.pending_win32(pending) then return end
@@ -25,11 +25,11 @@ describe('Signs', function()
describe(':sign place', function()
it('shadows previously placed signs', function()
feed('ia<cr>b<cr>c<cr><esc>')
- execute('sign define piet text=>> texthl=Search')
- execute('sign define pietx text=>! texthl=Search')
- execute('sign place 1 line=1 name=piet buffer=1')
- execute('sign place 2 line=3 name=piet buffer=1')
- execute('sign place 3 line=1 name=pietx buffer=1')
+ command('sign define piet text=>> texthl=Search')
+ command('sign define pietx text=>! texthl=Search')
+ command('sign place 1 line=1 name=piet buffer=1')
+ command('sign place 2 line=3 name=piet buffer=1')
+ command('sign place 3 line=1 name=pietx buffer=1')
screen:expect([[
{1:>!}a |
{2: }b |
@@ -44,7 +44,7 @@ describe('Signs', function()
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
- :sign place 3 line=1 name=pietx buffer=1 |
+ |
]])
end)
end)
diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua
index ee3e4fa32a..28a104360d 100644
--- a/test/functional/ui/syntax_conceal_spec.lua
+++ b/test/functional/ui/syntax_conceal_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
+local clear, feed, command = helpers.clear, helpers.feed, helpers.command
local insert = helpers.insert
if helpers.pending_win32(pending) then return end
@@ -25,7 +25,7 @@ describe('Screen', function()
describe("match and conceal", function()
before_each(function()
- execute("let &conceallevel=1")
+ command("let &conceallevel=1")
end)
describe("multiple", function()
@@ -38,7 +38,7 @@ describe('Screen', function()
&&
&&
]])
- execute("syn match dAmpersand '[&][&]' conceal cchar=∧")
+ command("syn match dAmpersand '[&][&]' conceal cchar=∧")
end)
it("double characters.", function()
@@ -52,7 +52,7 @@ describe('Screen', function()
^ |
{0:~ }|
{0:~ }|
- :syn match dAmpersand '[&][&]' conceal cchar=∧ |
+ |
]])
end)
@@ -68,7 +68,7 @@ describe('Screen', function()
|
{0:~ }|
{0:~ }|
- :syn match dAmpersand '[&][&]' conceal cchar=∧ |
+ |
]])
end)
@@ -84,7 +84,7 @@ describe('Screen', function()
|
{0:~ }|
{0:~ }|
- :syn match dAmpersand '[&][&]' conceal cchar=∧ |
+ |
]])
end)
@@ -100,7 +100,7 @@ describe('Screen', function()
|
{0:~ }|
{0:~ }|
- :syn match dAmpersand '[&][&]' conceal cchar=∧ |
+ |
]])
end)
@@ -116,15 +116,15 @@ describe('Screen', function()
^ |
{0:~ }|
{0:~ }|
- :syn match dAmpersand '[&][&]' conceal cchar=∧ |
+ |
]])
end)
end) -- multiple
it("keyword instances in initially in the document.", function()
feed("2ilambda<cr><ESC>")
- execute("let &conceallevel=1")
- execute("syn keyword kLambda lambda conceal cchar=λ")
+ command("let &conceallevel=1")
+ command("syn keyword kLambda lambda conceal cchar=λ")
screen:expect([[
{1:λ} |
{1:λ} |
@@ -135,7 +135,7 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :syn keyword kLambda lambda conceal cchar=λ |
+ |
]])
end) -- Keyword
@@ -144,11 +144,11 @@ describe('Screen', function()
before_each(function()
feed("2")
insert("<r> a region of text </r>\n")
- execute("let &conceallevel=1")
+ command("let &conceallevel=1")
end)
it('initially and conceal it.', function()
- execute("syn region rText start='<r>' end='</r>' conceal cchar=R")
+ command("syn region rText start='<r>' end='</r>' conceal cchar=R")
screen:expect([[
{1:R} |
{1:R} |
@@ -166,7 +166,7 @@ describe('Screen', function()
it('initially and conceal its start tag and end tag.', function()
-- concealends has a known bug (todo.txt) where the first match won't
-- be replaced with cchar.
- execute("syn region rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-")
+ command("syn region rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-")
screen:expect([[
{1: } a region of text {1:-} |
{1: } a region of text {1:-} |
@@ -182,7 +182,7 @@ describe('Screen', function()
end)
it('that are nested and conceal the nested region\'s start and end tags.', function()
- execute("syn region rText contains=rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-")
+ command("syn region rText contains=rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-")
insert("<r> A region with <r> a nested <r> nested region.</r> </r> </r>\n")
screen:expect([[
{1: } a region of text {1:-} |
@@ -201,10 +201,10 @@ describe('Screen', function()
describe("a region of text", function()
before_each(function()
- execute("syntax conceal on")
+ command("syntax conceal on")
feed("2")
insert("<r> a region of text </r>\n")
- execute("syn region rText start='<r>' end='</r>' cchar=-")
+ command("syn region rText start='<r>' end='</r>' cchar=-")
end)
it("and turn on implicit concealing", function()
@@ -218,15 +218,15 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :syn region rText start='<r>' end='</r>' cchar=- |
+ |
]])
end)
it("and then turn on, then off, and then back on implicit concealing.", function()
- execute("syntax conceal off")
+ command("syntax conceal off")
feed("2")
insert("<i> italian text </i>\n")
- execute("syn region iText start='<i>' end='</i>' cchar=*")
+ command("syn region iText start='<i>' end='</i>' cchar=*")
screen:expect([[
{1:-} |
{1:-} |
@@ -237,10 +237,10 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :syn region iText start='<i>' end='</i>' cchar=* |
+ |
]])
- execute("syntax conceal on")
- execute("syn region iText start='<i>' end='</i>' cchar=*")
+ command("syntax conceal on")
+ command("syn region iText start='<i>' end='</i>' cchar=*")
screen:expect([[
{1:-} |
{1:-} |
@@ -251,7 +251,7 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :syn region iText start='<i>' end='</i>' cchar=* |
+ |
]])
end)
end) -- a region of text (implicit concealing)
@@ -262,13 +262,13 @@ describe('Screen', function()
insert("// No Conceal\n")
insert('"Conceal without a cchar"\n')
insert("+ With cchar\n\n")
- execute("syn match noConceal '^//.*$'")
- execute("syn match concealNoCchar '\".\\{-}\"$' conceal")
- execute("syn match concealWCchar '^+.\\{-}$' conceal cchar=C")
+ command("syn match noConceal '^//.*$'")
+ command("syn match concealNoCchar '\".\\{-}\"$' conceal")
+ command("syn match concealWCchar '^+.\\{-}$' conceal cchar=C")
end)
it("0. No concealing.", function()
- execute("let &conceallevel=0")
+ command("let &conceallevel=0")
screen:expect([[
// No Conceal |
"Conceal without a cchar" |
@@ -279,12 +279,12 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :let &conceallevel=0 |
+ |
]])
end)
it("1. Conceal using cchar or reference listchars.", function()
- execute("let &conceallevel=1")
+ command("let &conceallevel=1")
screen:expect([[
// No Conceal |
{1: } |
@@ -295,12 +295,12 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :let &conceallevel=1 |
+ |
]])
end)
it("2. Hidden unless cchar is set.", function()
- execute("let &conceallevel=2")
+ command("let &conceallevel=2")
screen:expect([[
// No Conceal |
|
@@ -311,12 +311,12 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :let &conceallevel=2 |
+ |
]])
end)
it("3. Hide all concealed text.", function()
- execute("let &conceallevel=3")
+ command("let &conceallevel=3")
screen:expect([[
// No Conceal |
|
@@ -327,7 +327,7 @@ describe('Screen', function()
{0:~ }|
{0:~ }|
{0:~ }|
- :let &conceallevel=3 |
+ |
]])
end)
end) -- conceallevel
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
new file mode 100644
index 0000000000..e8271de0bf
--- /dev/null
+++ b/test/functional/ui/tabline_spec.lua
@@ -0,0 +1,54 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, command, eq = helpers.clear, helpers.command, helpers.eq
+
+describe('ui/ext_tabline', function()
+ local screen
+ local event_tabs, event_curtab
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25, 5)
+ screen:attach({rgb=true, ext_tabline=true})
+ screen:set_on_event_handler(function(name, data)
+ if name == "tabline_update" then
+ event_curtab, event_tabs = unpack(data)
+ end
+ end)
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ it('publishes UI events', function()
+ command("tabedit another-tab")
+
+ local expected_tabs = {
+ {tab = { id = 1 }, name = '[No Name]'},
+ {tab = { id = 2 }, name = 'another-tab'},
+ }
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({ id = 2 }, event_curtab)
+ eq(expected_tabs, event_tabs)
+ end)
+
+ command("tabNext")
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq({ id = 1 }, event_curtab)
+ eq(expected_tabs, event_tabs)
+ end)
+ end)
+end)
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 6a6dc99c3d..042969357e 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -1,36 +1,151 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
+local clear, feed, command = helpers.clear, helpers.feed, helpers.command
+local iswin = helpers.iswin
local funcs = helpers.funcs
+local eq = helpers.eq
+local eval = helpers.eval
+local retry = helpers.retry
-if helpers.pending_win32(pending) then return end
-
-describe("'wildmode'", function()
+describe("'wildmenu'", function()
local screen
-
before_each(function()
clear()
screen = Screen.new(25, 5)
screen:attach()
end)
-
after_each(function()
screen:detach()
end)
- describe("'wildmenu'", function()
- it(':sign <tab> shows wildmenu completions', function()
- execute('set wildmode=full')
- execute('set wildmenu')
- feed(':sign <tab>')
- screen:expect([[
- |
- ~ |
- ~ |
- define jump list > |
- :sign define^ |
- ]])
+ it(':sign <tab> shows wildmenu completions', function()
+ command('set wildmode=full')
+ command('set wildmenu')
+ feed(':sign <tab>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ define jump list > |
+ :sign define^ |
+ ]])
+ end)
+
+ it('does not crash after cycling back to original text', function()
+ command('set wildmode=full')
+ feed(':j<Tab><Tab><Tab>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ join jumps |
+ :j^ |
+ ]])
+ -- This would cause nvim to crash before #6650
+ feed('<BS><Tab>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ! # & < = > @ > |
+ :!^ |
+ ]])
+ end)
+
+ it('is preserved during :terminal activity', function()
+ -- Because this test verifies a _lack_ of activity after screen:sleep(), we
+ -- must wait the full timeout. So make it reasonable.
+ screen.timeout = 1000
+
+ command('set wildmenu wildmode=full')
+ command('set scrollback=4')
+ if iswin() then
+ if helpers.pending_win32(pending) then return end
+ -- feed([[:terminal 1,2,3,4,5 | foreach-object -process {echo $_; sleep 0.1}]])
+ else
+ feed([[:terminal for i in $(seq 1 5000); do printf 'foo\nfoo\nfoo\n'; sleep 0.1; done<cr>]])
+ end
+
+ feed([[<C-\><C-N>gg]])
+ feed([[:sign <Tab>]]) -- Invoke wildmenu.
+ screen:sleep(50) -- Allow some terminal output.
+ screen:expect([[
+ foo |
+ foo |
+ foo |
+ define jump list > |
+ :sign define^ |
+ ]])
+
+ -- cmdline CTRL-D display should also be preserved.
+ feed([[<C-\><C-N>]])
+ feed([[:sign <C-D>]]) -- Invoke cmdline CTRL-D.
+ screen:sleep(50) -- Allow some terminal output.
+ screen:expect([[
+ :sign |
+ define place |
+ jump undefine |
+ list unplace |
+ :sign ^ |
+ ]])
+
+ -- Exiting cmdline should show the buffer.
+ feed([[<C-\><C-N>]])
+ screen:expect([[
+ ^foo |
+ foo |
+ foo |
+ foo |
+ |
+ ]])
+ end)
+
+ it('ignores :redrawstatus called from a timer #7108', function()
+ -- Because this test verifies a _lack_ of activity after screen:sleep(), we
+ -- must wait the full timeout. So make it reasonable.
+ screen.timeout = 1000
+
+ command('set wildmenu wildmode=full')
+ command([[call timer_start(10, {->execute('redrawstatus')}, {'repeat':-1})]])
+ feed([[<C-\><C-N>]])
+ feed([[:sign <Tab>]]) -- Invoke wildmenu.
+ screen:sleep(30) -- Allow some timer activity.
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ define jump list > |
+ :sign define^ |
+ ]])
+ end)
+
+ it('with laststatus=0, :vsplit, :term #2255', function()
+ -- Because this test verifies a _lack_ of activity after screen:sleep(), we
+ -- must wait the full timeout. So make it reasonable.
+ screen.timeout = 1000
+
+ if not iswin() then
+ command('set shell=sh') -- Need a predictable "$" prompt.
+ end
+ command('set laststatus=0')
+ command('vsplit')
+ command('term')
+
+ -- Check for a shell prompt to verify that the terminal loaded.
+ retry(nil, nil, function()
+ if iswin() then
+ eq('Microsoft', eval("matchstr(join(getline(1, '$')), 'Microsoft')"))
+ else
+ eq('$', eval([[matchstr(getline(1), '\$')]]))
+ end
end)
+
+ feed([[<C-\><C-N>]])
+ feed([[:<Tab>]]) -- Invoke wildmenu.
+ screen:sleep(10) -- Flush
+ -- Check only the last 2 lines, because the shell output is
+ -- system-dependent.
+ screen:expect('! # & < = > @ > \n:!^', nil, nil, nil, true)
end)
end)
@@ -50,10 +165,10 @@ describe('command line completion', function()
it('lists directories with empty PATH', function()
local tmp = funcs.tempname()
- execute('e '.. tmp)
- execute('cd %:h')
- execute("call mkdir('Xtest-functional-viml-compl-dir')")
- execute('let $PATH=""')
+ command('e '.. tmp)
+ command('cd %:h')
+ command("call mkdir('Xtest-functional-viml-compl-dir')")
+ command('let $PATH=""')
feed(':!<tab><bs>')
screen:expect([[
|
@@ -64,3 +179,100 @@ describe('command line completion', function()
]])
end)
end)
+
+describe('ui/ext_wildmenu', function()
+ local screen
+ local items, selected = nil, nil
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25, 5)
+ screen:attach({rgb=true, ext_wildmenu=true})
+ screen:set_on_event_handler(function(name, data)
+ if name == "wildmenu_show" then
+ items = data[1]
+ elseif name == "wildmenu_select" then
+ selected = data[1]
+ elseif name == "wildmenu_hide" then
+ items, selected = nil, nil
+ end
+ end)
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ it('works with :sign <tab>', function()
+ local expected = {
+ 'define',
+ 'jump',
+ 'list',
+ 'place',
+ 'undefine',
+ 'unplace',
+ }
+
+ command('set wildmode=full')
+ command('set wildmenu')
+ feed(':sign <tab>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ :sign define^ |
+ ]], nil, nil, function()
+ eq(expected, items)
+ eq(0, selected)
+ end)
+
+ feed('<tab>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ :sign jump^ |
+ ]], nil, nil, function()
+ eq(expected, items)
+ eq(1, selected)
+ end)
+
+ feed('<left><left>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ :sign ^ |
+ ]], nil, nil, function()
+ eq(expected, items)
+ eq(-1, selected)
+ end)
+
+ feed('<right>')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ :sign define^ |
+ ]], nil, nil, function()
+ eq(expected, items)
+ eq(0, selected)
+ end)
+
+ feed('a')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ :sign definea^ |
+ ]], nil, nil, function()
+ eq(nil, items)
+ eq(nil, selected)
+ end)
+ end)
+end)