aboutsummaryrefslogtreecommitdiff
path: root/test/functional/ui
diff options
context:
space:
mode:
authorJames McCoy <jamessan@jamessan.com>2018-03-28 21:52:06 -0400
committerJames McCoy <jamessan@jamessan.com>2018-03-28 21:54:39 -0400
commit79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1 (patch)
tree4e0589d75801f3ff6a9678f84f5009102766661e /test/functional/ui
parent4403864da3c48412595d439f36458d1e6ccfc49f (diff)
parent3f3de9b1a95d273463a87516365510dbffcaf3d2 (diff)
downloadrneovim-79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1.tar.gz
rneovim-79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1.tar.bz2
rneovim-79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1.zip
Merge branch 'master' into yagebu/option-fixes
Diffstat (limited to 'test/functional/ui')
-rw-r--r--test/functional/ui/bufhl_spec.lua48
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua1000
-rw-r--r--test/functional/ui/cmdline_spec.lua681
-rw-r--r--test/functional/ui/highlight_spec.lua93
-rw-r--r--test/functional/ui/inccommand_spec.lua1052
-rw-r--r--test/functional/ui/input_spec.lua96
-rw-r--r--test/functional/ui/mouse_spec.lua495
-rw-r--r--test/functional/ui/options_spec.lua110
-rw-r--r--test/functional/ui/output_spec.lua179
-rw-r--r--test/functional/ui/screen.lua14
-rw-r--r--test/functional/ui/screen_basic_spec.lua150
-rw-r--r--test/functional/ui/searchhl_spec.lua131
-rw-r--r--test/functional/ui/sign_spec.lua2
-rw-r--r--test/functional/ui/spell_spec.lua49
-rw-r--r--test/functional/ui/syntax_conceal_spec.lua2
-rw-r--r--test/functional/ui/tabline_spec.lua57
-rw-r--r--test/functional/ui/wildmode_spec.lua264
17 files changed, 3935 insertions, 488 deletions
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index e1e11203e0..5b38921e50 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -2,13 +2,11 @@ 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, request, neq = helpers.command, helpers.request, helpers.neq
-
-if helpers.pending_win32(pending) then return end
+local command, neq = helpers.command, helpers.neq
+local curbufmeths = helpers.curbufmeths
describe('Buffer highlighting', function()
local screen
- local curbuf
before_each(function()
clear()
@@ -24,23 +22,17 @@ 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)
after_each(function()
screen:detach()
end)
- local function add_hl(...)
- return request('nvim_buf_add_highlight', curbuf, ...)
- end
-
- local function clear_hl(...)
- return request('nvim_buf_clear_highlight', curbuf, ...)
- end
-
+ local add_hl = curbufmeths.add_highlight
+ local clear_hl = curbufmeths.clear_highlight
it('works', function()
insert([[
@@ -255,4 +247,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..f9cec903a0
--- /dev/null
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -0,0 +1,1000 @@
+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},
+ NUM={foreground = Screen.colors.Blue2},
+ NPAR={foreground = Screen.colors.Yellow},
+ SQ={foreground = Screen.colors.Blue3},
+ SB={foreground = Screen.colors.Blue4},
+ E={foreground = Screen.colors.Red, background = Screen.colors.Blue},
+ M={bold = true},
+ })
+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)
+ it('does not crash when callback has caught not-a-editor-command exception',
+ function()
+ source([[
+ function CaughtExc(cmdline) abort
+ try
+ gibberish
+ catch
+ " Do nothing
+ endtry
+ return []
+ endfunction
+ ]])
+ set_color_cb('CaughtExc')
+ start_prompt('1')
+ eq(1, meths.eval('1'))
+ end)
+end)
+describe('Ex commands coloring 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('Error 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.command('hi clear NvimNumber')
+ meths.command('hi clear NvimNestingParenthesis')
+ meths.command('hi NvimNumber guifg=Blue2')
+ meths.command('hi NvimNestingParenthesis guifg=Yellow')
+ feed(':echo <C-r>=(((1)))')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ={NPAR:(((}{NUM:1}{NPAR:)))}^ |
+ ]])
+ end)
+ it('does not use Nvim_color_expr', function()
+ meths.set_var('Nvim_color_expr', 42)
+ -- Used to error out due to failing to get callback.
+ meths.command('hi clear NvimNumber')
+ meths.command('hi NvimNumber guifg=Blue2')
+ feed(':<C-r>=1')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ={NUM:1}^ |
+ ]])
+ end)
+ it('works correctly with non-ASCII and control characters', function()
+ meths.command('hi clear NvimStringBody')
+ meths.command('hi clear NvimStringQuote')
+ meths.command('hi clear NvimInvalid')
+ meths.command('hi NvimStringQuote guifg=Blue3')
+ meths.command('hi NvimStringBody guifg=Blue4')
+ meths.command('hi NvimInvalid guifg=Red guibg=Blue')
+ feed('i<C-r>="«»"«»')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ={SQ:"}{SB:«»}{SQ:"}{E:«»}^ |
+ ]])
+ feed('<C-c>')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {M:-- INSERT --} |
+ ]])
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ |
+ ]])
+ feed(':<C-\\>e"<C-v><C-x>"<C-v><C-x>')
+ -- TODO(ZyX-I): Parser highlighting should not override special character
+ -- highlighting.
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ={SQ:"}{SB:^X}{SQ:"}{ERR:^X}^ |
+ ]])
+ feed('<C-c>')
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ :^ |
+ ]])
+ funcs.setreg('a', {'\192'})
+ feed('<C-r>="<C-r><C-r>a"<C-r><C-r>a"foo"')
+ -- TODO(ZyX-I): Parser highlighting should not override special character
+ -- highlighting.
+ screen:expect([[
+ |
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ {EOB:~ }|
+ ={SQ:"}{SB:<c0>}{SQ:"}{E:<c0>"}{SB:foo}{E:"}^ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
new file mode 100644
index 0000000000..f8680678ef
--- /dev/null
+++ b/test/functional/ui/cmdline_spec.lua
@@ -0,0 +1,681 @@
+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
+ local wild_items = nil
+ local wild_selected = nil
+
+ before_each(function()
+ clear()
+ cmdline, block = {}, nil
+ screen = Screen.new(25, 5)
+ screen:attach({rgb=true, ext_cmdline=true})
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {reverse = true},
+ [3] = {bold = true, reverse = 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
+ elseif name == "wildmenu_show" then
+ wild_items = data[1]
+ elseif name == "wildmenu_select" then
+ wild_selected = data[1]
+ elseif name == "wildmenu_hide" then
+ wild_items, wild_selected = nil, 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([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq(1, last_level)
+ eq({{
+ content = { { {}, "" } },
+ firstc = ":",
+ indent = 0,
+ pos = 0,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('sign')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<Left>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign" } },
+ firstc = ":",
+ indent = 0,
+ pos = 3,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<bs>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sin" } },
+ firstc = ":",
+ indent = 0,
+ pos = 2,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+ end)
+
+ it("works with input()", function()
+ feed(':call input("input", "default")<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "default" } },
+ firstc = "",
+ indent = 0,
+ pos = 7,
+ prompt = "input"
+ }}, cmdline)
+ end)
+ feed('<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+
+ end)
+
+ it("works with special chars and nested cmdline", function()
+ feed(':xx<c-r>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "xx" } },
+ firstc = ":",
+ indent = 0,
+ pos = 2,
+ prompt = "",
+ special = {'"', true},
+ }}, cmdline)
+ end)
+
+ feed('=')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], 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([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], 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([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^ |
+ ]], nil, nil, function()
+ eq(expectation, cmdline)
+ end)
+
+
+ feed('<cr>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "xx3" } },
+ firstc = ":",
+ indent = 0,
+ pos = 3,
+ prompt = "",
+ }}, cmdline)
+ end)
+
+ feed('<esc>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+ end)
+
+ it("works with function definitions", function()
+ feed(':function Foo()<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "" } },
+ firstc = ":",
+ indent = 2,
+ pos = 0,
+ prompt = "",
+ }}, cmdline)
+ eq({ { { {}, 'function Foo()'} } }, block)
+ end)
+
+ feed('line1<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({ { { {}, 'function Foo()'} },
+ { { {}, ' line1'} } }, block)
+ end)
+
+ block = {}
+ command("redraw!")
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^ |
+ ]], nil, nil, function()
+ eq({ { { {}, 'function Foo()'} },
+ { { {}, ' line1'} } }, block)
+ end)
+
+ feed('endfunction<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq(nil, block)
+ end)
+
+ -- Try once more, to check buffer is reinitialized. #8007
+ feed(':function Bar()<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "" } },
+ firstc = ":",
+ indent = 2,
+ pos = 0,
+ prompt = "",
+ }}, cmdline)
+ eq({ { { {}, 'function Bar()'} } }, block)
+ end)
+
+ feed('endfunction<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq(nil, block)
+ end)
+ end)
+
+ it("works with cmdline window", function()
+ feed(':make')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "make" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed('<c-f>')
+ screen:expect([[
+ |
+ {2:[No Name] }|
+ {1::}make^ |
+ {3:[Command Line] }|
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+
+ -- nested cmdline
+ feed(':yank')
+ screen:expect([[
+ |
+ {2:[No Name] }|
+ {1::}make^ |
+ {3:[Command Line] }|
+ |
+ ]], nil, nil, function()
+ eq({nil, {
+ content = { { {}, "yank" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ cmdline = {}
+ command("redraw!")
+ screen:expect([[
+ |
+ {2:[No Name] }|
+ {1::}make |
+ {3:[Command Line] }|
+ ^ |
+ ]], nil, nil, function()
+ eq({nil, {
+ content = { { {}, "yank" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ feed("<c-c>")
+ screen:expect([[
+ |
+ {2:[No Name] }|
+ {1::}make^ |
+ {3:[Command Line] }|
+ |
+ ]], nil, nil, function()
+ eq({}, cmdline)
+ end)
+
+ feed("<c-c>")
+ screen:expect([[
+ |
+ {2:[No Name] }|
+ {1::}make^ |
+ {3:[Command Line] }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "make" } },
+ firstc = ":",
+ indent = 0,
+ pos = 4,
+ prompt = ""
+ }}, cmdline)
+ end)
+
+ cmdline = {}
+ command("redraw!")
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^ |
+ ]], 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([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], 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)
+
+ it('works together with ext_wildmenu', function()
+ local expected = {
+ 'define',
+ 'jump',
+ 'list',
+ 'place',
+ 'undefine',
+ 'unplace',
+ }
+
+ command('set wildmode=full')
+ command('set wildmenu')
+ screen:set_option('ext_wildmenu', true)
+ feed(':sign <tab>')
+
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign define"} },
+ firstc = ":",
+ indent = 0,
+ pos = 11,
+ prompt = ""
+ }}, cmdline)
+ eq(expected, wild_items)
+ eq(0, wild_selected)
+ end)
+
+ feed('<tab>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign jump"} },
+ firstc = ":",
+ indent = 0,
+ pos = 9,
+ prompt = ""
+ }}, cmdline)
+ eq(expected, wild_items)
+ eq(1, wild_selected)
+ end)
+
+ feed('<left><left>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign "} },
+ firstc = ":",
+ indent = 0,
+ pos = 5,
+ prompt = ""
+ }}, cmdline)
+ eq(expected, wild_items)
+ eq(-1, wild_selected)
+ end)
+
+ feed('<right>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign define"} },
+ firstc = ":",
+ indent = 0,
+ pos = 11,
+ prompt = ""
+ }}, cmdline)
+ eq(expected, wild_items)
+ eq(0, wild_selected)
+ end)
+
+ feed('a')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], nil, nil, function()
+ eq({{
+ content = { { {}, "sign definea"} },
+ firstc = ":",
+ indent = 0,
+ pos = 12,
+ prompt = ""
+ }}, cmdline)
+ eq(nil, wild_items)
+ eq(nil, wild_selected)
+ end)
+ end)
+end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index d1357ea525..e874c45272 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -4,7 +4,7 @@ local os = require('os')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command = helpers.command
local eval, exc_exec = helpers.eval, helpers.exc_exec
-local feed_command, request, eq = helpers.feed_command, helpers.request, helpers.eq
+local feed_command, eq = helpers.feed_command, helpers.eq
local curbufmeths = helpers.curbufmeths
describe('colorscheme compatibility', function()
@@ -14,8 +14,6 @@ describe('colorscheme compatibility', function()
it('t_Co is set to 256 by default', function()
eq('256', eval('&t_Co'))
- request('nvim_set_option', 't_Co', '88')
- eq('88', eval('&t_Co'))
end)
end)
@@ -110,12 +108,12 @@ describe('highlight defaults', function()
})
feed_command('sp', 'vsp', 'vsp')
screen:expect([[
- ^ {2:|} {2:|} |
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
+ ^ {2:│} {2:│} |
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
{1:[No Name] }{2:[No Name] [No Name] }|
|
{0:~ }|
@@ -128,12 +126,12 @@ describe('highlight defaults', function()
-- navigate to verify that the attributes are properly moved
feed('<c-w>j')
screen:expect([[
- {2:|} {2:|} |
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
+ {2:│} {2:│} |
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
{2:[No Name] [No Name] [No Name] }|
^ |
{0:~ }|
@@ -148,12 +146,12 @@ describe('highlight defaults', function()
-- (upstream vim has the same behavior)
feed('<c-w>k<c-w>l')
screen:expect([[
- {2:|}^ {2:|} |
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
+ {2:│}^ {2:│} |
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
{2:[No Name] }{1:[No Name] }{2:[No Name] }|
|
{0:~ }|
@@ -165,12 +163,12 @@ describe('highlight defaults', function()
]])
feed('<c-w>l')
screen:expect([[
- {2:|} {2:|}^ |
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
+ {2:│} {2:│}^ |
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
{2:[No Name] [No Name] }{1:[No Name] }|
|
{0:~ }|
@@ -182,12 +180,12 @@ describe('highlight defaults', function()
]])
feed('<c-w>h<c-w>h')
screen:expect([[
- ^ {2:|} {2:|} |
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
- {0:~ }{2:|}{0:~ }{2:|}{0:~ }|
+ ^ {2:│} {2:│} |
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
+ {0:~ }{2:│}{0:~ }{2:│}{0:~ }|
{1:[No Name] }{2:[No Name] [No Name] }|
|
{0:~ }|
@@ -314,7 +312,7 @@ describe('highlight defaults', function()
end)
end)
-describe('guisp (special/undercurl)', function()
+describe('highlight', function()
local screen
before_each(function()
@@ -323,7 +321,31 @@ describe('guisp (special/undercurl)', function()
screen:attach()
end)
- it('can be set and is applied like foreground or background', function()
+ it('cterm=standout gui=standout', function()
+ screen:detach()
+ screen = Screen.new(20,5)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {standout = true, bold = true, underline = true,
+ background = Screen.colors.Gray90, foreground = Screen.colors.Blue1},
+ [3] = {standout = true, underline = true,
+ background = Screen.colors.Gray90}
+ })
+ feed_command('hi CursorLine cterm=standout,underline gui=standout,underline')
+ feed_command('set cursorline')
+ feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
+ feed('i\t abcd <cr>\t abcd <cr><esc>k')
+ screen:expect([[
+ {1:>-------.}abcd{1:*¬} |
+ {2:^>-------.}{3:abcd}{2:*¬}{3: }|
+ {1:¬} |
+ {1:~ }|
+ |
+ ]])
+ end)
+
+ it('guisp (special/undercurl)', function()
feed_command('syntax on')
feed_command('syn keyword TmpKeyword neovim')
feed_command('syn keyword TmpKeyword1 special')
@@ -907,6 +929,7 @@ describe("'winhighlight' highlight", function()
end)
it('background applies also to non-text', function()
+ command('set sidescroll=0')
insert('Lorem ipsum dolor sit amet ')
command('set shiftwidth=2')
feed('>>')
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 8bdc4601c0..8b0cb82365 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -12,14 +12,52 @@ local insert = helpers.insert
local meths = helpers.meths
local neq = helpers.neq
local ok = helpers.ok
+local retry = helpers.retry
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
command("syntax on")
@@ -54,22 +92,30 @@ local function common_setup(screen, inccommand, text)
end
end
-describe(":substitute, inccommand=split does not trigger preview", function()
+describe(":substitute, inccommand=split", function()
before_each(function()
clear()
common_setup(nil, "split", default_text)
end)
- it("if invoked by a script ", function()
+ -- Test the tests: verify that the `1==bufnr('$')` assertion
+ -- in the "no preview" tests (below) actually means something.
+ it("previews interactive cmdline", function()
+ feed(':%s/tw/MO/g')
+ retry(nil, 1000, function()
+ eq(2, eval("bufnr('$')"))
+ end)
+ end)
+
+ it("no preview if invoked by a script", function()
source('%s/tw/MO/g')
wait()
eq(1, eval("bufnr('$')"))
-
-- sanity check: assert the buffer state
expect(default_text:gsub("tw", "MO"))
end)
- it("if invoked by feedkeys()", function()
+ it("no preview if invoked by feedkeys()", function()
-- in a script...
source([[:call feedkeys(":%s/tw/MO/g\<CR>")]])
wait()
@@ -77,15 +123,12 @@ describe(":substitute, inccommand=split does not trigger preview", function()
feed([[:call feedkeys(":%s/tw/MO/g\<CR>")<CR>]])
wait()
eq(1, eval("bufnr('$')"))
-
-- sanity check: assert the buffer state
expect(default_text:gsub("tw", "MO"))
end)
end)
describe(":substitute, 'inccommand' preserves", function()
- if helpers.pending_win32(pending) then return end
-
before_each(clear)
it('listed buffers (:ls)', function()
@@ -248,8 +291,6 @@ describe(":substitute, 'inccommand' preserves", function()
end)
describe(":substitute, 'inccommand' preserves undo", function()
- if helpers.pending_win32(pending) then return end
-
local cases = { "", "split", "nosplit" }
local substrings = {
@@ -663,8 +704,6 @@ describe(":substitute, 'inccommand' preserves undo", function()
end)
describe(":substitute, inccommand=split", function()
- if helpers.pending_win32(pending) then return end
-
local screen = Screen.new(30,15)
before_each(function()
@@ -681,14 +720,14 @@ describe(":substitute, inccommand=split", 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:~ }|
@@ -700,18 +739,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:~ }|
@@ -732,7 +790,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -744,14 +802,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:~ }|
@@ -770,7 +828,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -785,14 +843,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:~ }|
@@ -808,7 +866,7 @@ describe(":substitute, inccommand=split", function()
screen:sleep(1)
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
Inc substitution on |
two lines |
|
@@ -852,14 +910,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:~ }|
@@ -874,14 +932,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:~ }|
@@ -892,6 +950,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>")
@@ -924,9 +1029,9 @@ describe(":substitute, inccommand=split", function()
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 |
@@ -986,7 +1091,7 @@ describe(":substitute, inccommand=split", function()
-- Set 'redrawtime' to minimal value, to ensure timeout is triggered.
feed_command("set redrawtime=1 nowrap")
-- Load a big file.
- feed_command("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()
@@ -996,19 +1101,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^ |
]])
@@ -1024,15 +1129,15 @@ describe(":substitute, inccommand=split", function()
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:~ }|
@@ -1066,8 +1171,6 @@ describe(":substitute, inccommand=split", function()
end)
describe("inccommand=nosplit", function()
- if helpers.pending_win32(pending) then return end
-
local screen = Screen.new(20,10)
before_each(function()
@@ -1089,7 +1192,7 @@ describe("inccommand=nosplit", function()
two lines |
Inc substitution on |
two lines |
- Line *.X |
+ Line *.{12:X} |
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1097,7 +1200,6 @@ describe("inccommand=nosplit", function()
:%smagic/3.*/X^ |
]])
-
feed([[<C-\><C-N>]]) -- cancel
feed(":%snomagic/3.*/X") -- start :snomagic command
screen:expect([[
@@ -1105,7 +1207,7 @@ describe("inccommand=nosplit", function()
two lines |
Inc substitution on |
two lines |
- Line *.X here |
+ Line *.{12:X} here |
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1114,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()
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:~ }|
@@ -1134,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:~ }|
@@ -1148,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:~ }|
@@ -1181,8 +1325,8 @@ describe("inccommand=nosplit", function()
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 |
|
@@ -1212,8 +1356,6 @@ describe("inccommand=nosplit", function()
end)
describe(":substitute, 'inccommand' with a failing expression", function()
- if helpers.pending_win32(pending) then return end
-
local screen = Screen.new(20,10)
local cases = { "", "split", "nosplit" }
@@ -1477,8 +1619,6 @@ describe("'inccommand' autocommands", function()
end)
describe("'inccommand' split windows", function()
- if helpers.pending_win32(pending) then return end
-
local screen
local function refresh()
clear()
@@ -1498,29 +1638,29 @@ describe("'inccommand' split windows", function()
feed_command("split")
feed(":%s/tw")
screen:expect([[
- Inc substitution on {10:|}Inc substitution on|
- two lines {10:|}two lines |
- {10:|} |
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {11:[No Name] [+] }{10:|}{15:~ }|
- Inc substitution on {10:|}{15:~ }|
- two lines {10:|}{15:~ }|
- {10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
+ Inc substitution on {10:│}Inc substitution on|
+ {12:tw}o lines {10:│}{12:tw}o lines |
+ {10:│} |
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {11:[No Name] [+] }{10:│}{15:~ }|
+ Inc substitution on {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:~ }|
@@ -1537,29 +1677,29 @@ describe("'inccommand' split windows", function()
feed(":%s/tw")
screen:expect([[
- Inc substitution on {10:|}Inc substitution on|
- two lines {10:|}two lines |
- {10:|} |
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
- {15:~ }{10:|}{15:~ }|
+ Inc substitution on {10:│}Inc substitution on|
+ {12:tw}o lines {10:│}{12:tw}o lines |
+ {10:│} |
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {15:~ }{10:│}{15:~ }|
+ {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:~ }|
@@ -1588,7 +1728,7 @@ describe("'inccommand' split windows", function()
screen:expect([[
Inc substitution on |
- two lines |
+ {12:tw}o lines |
|
{15:~ }|
{15:~ }|
@@ -1608,8 +1748,8 @@ describe("'inccommand' split windows", function()
{15:~ }|
{15:~ }|
{11:[No Name] [+] }|
- |2| two lines |
- |
+ |2| {12:tw}o lines |
+ {15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
@@ -1622,3 +1762,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 29d974b709..8e62a37ef1 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -1,11 +1,10 @@
local helpers = require('test.functional.helpers')(after_each)
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 feed, next_msg, eq = helpers.feed, helpers.next_msg, helpers.eq
local expect = helpers.expect
+local write_file = helpers.write_file
local Screen = require('test.functional.ui.screen')
-if helpers.pending_win32(pending) then return end
-
describe('mappings', function()
local cid
@@ -17,7 +16,7 @@ describe('mappings', function()
local check_mapping = function(mapping, expected)
feed(mapping)
- eq({'notification', 'mapped', {expected}}, next_message())
+ eq({'notification', 'mapped', {expected}}, next_msg())
end
before_each(function()
@@ -126,3 +125,92 @@ describe('input utf sequences that contain CSI/K_SPECIAL', function()
expect('…')
end)
end)
+
+describe('input non-printable chars', function()
+ it("doesn't crash when echoing them back", function()
+ write_file("Xtest-overwrite", [[foobar]])
+ clear()
+ local screen = Screen.new(60,8)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [3] = {bold = true, foreground = Screen.colors.SeaGreen4}
+ })
+ screen:attach()
+
+ feed_command("e Xtest-overwrite")
+ screen:expect([[
+ ^foobar |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ "Xtest-overwrite" [noeol] 1L, 6C |
+ ]])
+
+ -- The timestamp is in second resolution, wait two seconds to be sure.
+ screen:sleep(2000)
+ write_file("Xtest-overwrite", [[smurf]])
+ feed_command("w")
+ screen:expect([[
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ "Xtest-overwrite" |
+ {2:WARNING: The file has been changed since reading it!!!} |
+ {3:Do you really want to write to it (y/n)?}^ |
+ ]])
+
+ feed("u")
+ screen:expect([[
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ "Xtest-overwrite" |
+ {2:WARNING: The file has been changed since reading it!!!} |
+ {3:Do you really want to write to it (y/n)?}u |
+ {3:Do you really want to write to it (y/n)?}^ |
+ ]])
+
+ feed("\005")
+ screen:expect([[
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ "Xtest-overwrite" |
+ {2:WARNING: The file has been changed since reading it!!!} |
+ {3:Do you really want to write to it (y/n)?}u |
+ {3:Do you really want to write to it (y/n)?} |
+ {3:Do you really want to write to it (y/n)?}^ |
+ ]])
+
+ feed("n")
+ screen:expect([[
+ {1:~ }|
+ {1:~ }|
+ "Xtest-overwrite" |
+ {2:WARNING: The file has been changed since reading it!!!} |
+ {3:Do you really want to write to it (y/n)?}u |
+ {3:Do you really want to write to it (y/n)?} |
+ {3:Do you really want to write to it (y/n)?}n |
+ {3:Press ENTER or type command to continue}^ |
+ ]])
+
+ feed("<cr>")
+ screen:expect([[
+ ^foobar |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index 35af34015d..05d5a6409a 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -3,8 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
local insert, feed_command = helpers.insert, helpers.feed_command
local eq, funcs = helpers.eq, helpers.funcs
-
-if helpers.pending_win32(pending) then return end
+local command = helpers.command
describe('ui/mouse/input', function()
local screen
@@ -13,9 +12,6 @@ describe('ui/mouse/input', 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,7 +115,6 @@ describe('ui/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()
@@ -643,12 +638,12 @@ describe('ui/mouse/input', function()
screen:try_resize(53, 14)
feed_command('sp', 'vsp')
screen:expect([[
- lines {4:|}lines |
- to {4:|}to |
- test {4:|}test |
- mouse scrolling {4:|}mouse scrolling |
- ^ {4:|} |
- {0:~ }{4:|}{0:~ }|
+ lines {4:│}lines |
+ to {4:│}to |
+ test {4:│}test |
+ mouse scrolling {4:│}mouse scrolling |
+ ^ {4:│} |
+ {0:~ }{4:│}{0:~ }|
{5:[No Name] [+] }{4:[No Name] [+] }|
to |
test |
@@ -660,12 +655,12 @@ describe('ui/mouse/input', function()
]])
feed('<ScrollWheelDown><0,0>')
screen:expect([[
- mouse scrolling {4:|}lines |
- ^ {4:|}to |
- {0:~ }{4:|}test |
- {0:~ }{4:|}mouse scrolling |
- {0:~ }{4:|} |
- {0:~ }{4:|}{0:~ }|
+ mouse scrolling {4:│}lines |
+ ^ {4:│}to |
+ {0:~ }{4:│}test |
+ {0:~ }{4:│}mouse scrolling |
+ {0:~ }{4:│} |
+ {0:~ }{4:│}{0:~ }|
{5:[No Name] [+] }{4:[No Name] [+] }|
to |
test |
@@ -677,12 +672,12 @@ describe('ui/mouse/input', function()
]])
feed('<ScrollWheelUp><27,0>')
screen:expect([[
- mouse scrolling {4:|}text |
- ^ {4:|}with |
- {0:~ }{4:|}many |
- {0:~ }{4:|}lines |
- {0:~ }{4:|}to |
- {0:~ }{4:|}test |
+ mouse scrolling {4:│}text |
+ ^ {4:│}with |
+ {0:~ }{4:│}many |
+ {0:~ }{4:│}lines |
+ {0:~ }{4:│}to |
+ {0:~ }{4:│}test |
{5:[No Name] [+] }{4:[No Name] [+] }|
to |
test |
@@ -694,12 +689,12 @@ describe('ui/mouse/input', function()
]])
feed('<ScrollWheelUp><27,7><ScrollWheelUp>')
screen:expect([[
- mouse scrolling {4:|}text |
- ^ {4:|}with |
- {0:~ }{4:|}many |
- {0:~ }{4:|}lines |
- {0:~ }{4:|}to |
- {0:~ }{4:|}test |
+ mouse scrolling {4:│}text |
+ ^ {4:│}with |
+ {0:~ }{4:│}many |
+ {0:~ }{4:│}lines |
+ {0:~ }{4:│}to |
+ {0:~ }{4:│}test |
{5:[No Name] [+] }{4:[No Name] [+] }|
Inserting |
text |
@@ -712,6 +707,7 @@ describe('ui/mouse/input', function()
end)
it('horizontal scrolling', function()
+ command('set sidescroll=0')
feed("<esc>:set nowrap<cr>")
feed("a <esc>20Ab<esc>")
@@ -756,17 +752,19 @@ describe('ui/mouse/input', function()
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')
+ feed_command('set shiftwidth=2 tabstop=4 list listchars=tab:>-')
+ feed_command('syntax match NonText "\\*" conceal')
+ feed_command('syntax match NonText "cats" conceal cchar=X')
+ feed_command('syntax match NonText "x" conceal cchar=>')
+ -- First column is there to retain the tabs.
insert([[
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr.
- Stet clita kasd gubergren, no sea takimata sanctus est.
+ |Section *t1*
+ | *t2* *t3* *t4*
+ |x 私は猫が大好き *cats* ✨🐈✨
]])
- feed('gg')
+ feed('gg<c-v>Gxgg')
end)
it('(level 1) click on non-wrapped lines', function()
@@ -774,93 +772,138 @@ describe('ui/mouse/input', function()
feed('<esc><LeftMouse><0,0>')
screen:expect([[
- {c:^Y}rem ip{c:X}um do{c: } {c:X}it {c: }, con|
- {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en, no|
+ ^Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ {c:>} 私は猫が大好き{0:>---}{c: X } {0:>}|
|
{0:~ }|
{0:~ }|
- {0:~ }|
|
]])
feed('<esc><LeftMouse><1,0>')
screen:expect([[
- {c:Y}^rem ip{c:X}um do{c: } {c:X}it {c: }, con|
- {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en, no|
+ S^ection{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ {c:>} 私は猫が大好き{0:>---}{c: X } {0:>}|
|
{0:~ }|
{0:~ }|
+ |
+ ]])
+
+ feed('<esc><LeftMouse><21,0>')
+ screen:expect([[
+ Section{0:>>--->--->---}{c: }^t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ {c:>} 私は猫が大好き{0:>---}{c: X } {0:>}|
+ |
+ {0:~ }|
{0:~ }|
|
]])
- feed('<esc><LeftMouse><15,0>')
+ feed('<esc><LeftMouse><21,1>')
screen:expect([[
- {c:Y}rem ip{c:X}um do{c: } {c:^X}it {c: }, con|
- {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en, no|
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t^3{c: } {c: }|
+ {c:>} 私は猫が大好き{0:>---}{c: X } {0:>}|
|
{0:~ }|
{0:~ }|
+ |
+ ]])
+
+ feed('<esc><LeftMouse><0,2>')
+ screen:expect([[
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ {c:^>} 私は猫が大好き{0:>---}{c: X } {0:>}|
+ |
+ {0:~ }|
{0:~ }|
|
]])
- feed('<esc><LeftMouse><15,1>')
+ feed('<esc><LeftMouse><7,2>')
screen:expect([[
- {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: }, con|
- {c:X}tet {c: }ta ka{c:X}d {c:X}^ber{c:X}en, no|
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ {c:>} 私は^猫が大好き{0:>---}{c: X } {0:>}|
|
{0:~ }|
{0:~ }|
+ |
+ ]])
+
+ feed('<esc><LeftMouse><21,2>')
+ screen:expect([[
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ {c:>} 私は猫が大好き{0:>---}{c: ^X } {0:>}|
+ |
+ {0:~ }|
{0:~ }|
|
]])
+
end) -- level 1 - non wrapped
it('(level 1) click on wrapped lines', function()
feed_command('let &conceallevel=1', 'let &wrap=1', 'echo')
- feed('<esc><LeftMouse><0,0>')
+ feed('<esc><LeftMouse><24,1>')
screen:expect([[
- {c:^Y}rem ip{c:X}um do{c: } {c:X}it {c: } |
- , con{c:X}etetur {c:X}adip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c:^ }|
+ t4{c: } |
+ {c:>} 私は猫が大好き{0:>---}{c: X} |
+ {c: } ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><6,1>')
+ feed('<esc><LeftMouse><0,2>')
screen:expect([[
- {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: } |
- , con{c:X}^etetur {c:X}adip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ ^t4{c: } |
+ {c:>} 私は猫が大好き{0:>---}{c: X} |
+ {c: } ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><15,1>')
+ feed('<esc><LeftMouse><8,3>')
screen:expect([[
- {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: } |
- , con{c:X}etetur {c:X}a^dip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ t4{c: } |
+ {c:>} 私は猫^が大好き{0:>---}{c: X} |
+ {c: } ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><15,3>')
+ feed('<esc><LeftMouse><21,3>')
screen:expect([[
- {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: } |
- , con{c:X}etetur {c:X}adip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet {c: }ta ka{c:X}d {c:X}^ber{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ t4{c: } |
+ {c:>} 私は猫が大好き{0:>---}{c: ^X} |
+ {c: } ✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><4,4>')
+ screen:expect([[
+ Section{0:>>--->--->---}{c: }t1{c: } |
+ {0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
+ t4{c: } |
+ {c:>} 私は猫が大好き{0:>---}{c: X} |
+ {c: } ✨^🐈✨ |
+ |
|
]])
end) -- level 1 - wrapped
@@ -869,46 +912,68 @@ describe('ui/mouse/input', function()
it('(level 2) click on non-wrapped lines', function()
feed_command('let &conceallevel=2', 'echo')
- feed('<esc><LeftMouse><0,0>')
+ feed('<esc><LeftMouse><20,0>')
screen:expect([[
- {c:^Y}rem ip{c:X}um do {c:X}it , con{c:X}e|
- {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en, no |
+ Section{0:>>--->--->---}^t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} ✨{0:>}|
|
{0:~ }|
{0:~ }|
- {0:~ }|
|
]])
- feed('<esc><LeftMouse><1,0>')
+ feed('<esc><LeftMouse><14,1>')
screen:expect([[
- {c:Y}^rem ip{c:X}um do {c:X}it , con{c:X}e|
- {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en, no |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} ^t2 t3 t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} ✨{0:>}|
|
{0:~ }|
{0:~ }|
- {0:~ }|
|
]])
- feed('<esc><LeftMouse><15,0>')
+ feed('<esc><LeftMouse><18,1>')
screen:expect([[
- {c:Y}rem ip{c:X}um do {c:X}^it , con{c:X}e|
- {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en, no |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t^3 t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} ✨{0:>}|
|
{0:~ }|
{0:~ }|
+ |
+ ]])
+
+ feed('<esc><LeftMouse><0,2>') -- Weirdness
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ {c:^>} 私は猫が大好き{0:>---}{c:X} ✨{0:>}|
+ |
+ {0:~ }|
{0:~ }|
|
]])
- feed('<esc><LeftMouse><15,1>')
+ feed('<esc><LeftMouse><8,2>')
screen:expect([[
- {c:Y}rem ip{c:X}um do {c:X}it , con{c:X}e|
- {c:X}tet ta ka{c:X}d {c:X}b^er{c:X}en, no |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ {c:>} 私は猫^が大好き{0:>---}{c:X} ✨{0:>}|
|
{0:~ }|
{0:~ }|
+ |
+ ]])
+
+ feed('<esc><LeftMouse><20,2>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:^X} ✨{0:>}|
+ |
+ {0:~ }|
{0:~ }|
|
]])
@@ -917,47 +982,108 @@ describe('ui/mouse/input', function()
it('(level 2) click on wrapped lines', function()
feed_command('let &conceallevel=2', 'let &wrap=1', 'echo')
- feed('<esc><LeftMouse><0,0>')
+ feed('<esc><LeftMouse><20,0>')
screen:expect([[
- {c:^Y}rem ip{c:X}um do {c:X}it |
- , con{c:X}etetur {c:X}adip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}^t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} |
+ ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><6,1>')
+ feed('<esc><LeftMouse><14,1>')
screen:expect([[
- {c:Y}rem ip{c:X}um do {c:X}it |
- , con{c:X}^etetur {c:X}adip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} ^t2 t3 |
+ t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} |
+ ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><15,1>')
+ feed('<esc><LeftMouse><18,1>')
screen:expect([[
- {c:Y}rem ip{c:X}um do {c:X}it |
- , con{c:X}etetur {c:X}a^dip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t^3 |
+ t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} |
+ ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><15,3>')
+ -- NOTE: The click would ideally be on the 't' in 't4', but wrapping
+ -- caused the invisible '*' right before 't4' to remain on the previous
+ -- screen line. This is being treated as expected because fixing this is
+ -- out of scope for mouse clicks. Should the wrapping behavior of
+ -- concealed characters change in the future, this case should be
+ -- reevaluated.
+ feed('<esc><LeftMouse><0,2>')
screen:expect([[
- {c:Y}rem ip{c:X}um do {c:X}it |
- , con{c:X}etetur {c:X}adip{c:X}cin{c:X} |
- elitr. |
- {c:X}tet ta ka{c:X}d {c:X}b^er{c:X}en |
- , no {c:X}ea takimata {c:X}anctu{c:X}|
- e{c:X}t. |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 ^ |
+ t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} |
+ ✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><1,2>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t^4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} |
+ ✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><0,3>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ {c:^>} 私は猫が大好き{0:>---}{c:X} |
+ ✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><20,3>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:^X} |
+ ✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><1,4>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} |
+ ^✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><5,4>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ {c:>} 私は猫が大好き{0:>---}{c:X} |
+ ✨🐈^✨ |
+ |
|
]])
end) -- level 2 - wrapped
@@ -966,47 +1092,47 @@ describe('ui/mouse/input', function()
it('(level 3) click on non-wrapped lines', function()
feed_command('let &conceallevel=3', 'echo')
- feed('<esc><LeftMouse><0,0>')
+ feed('<esc><LeftMouse><0,2>')
screen:expect([[
- ^rem ipum do it , conetetu|
- tet ta kad beren, no ea t|
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ ^ 私は猫が大好き{0:>----} ✨🐈|
|
{0:~ }|
{0:~ }|
- {0:~ }|
|
]])
- feed('<esc><LeftMouse><1,0>')
+ feed('<esc><LeftMouse><1,2>')
screen:expect([[
- r^em ipum do it , conetetu|
- tet ta kad beren, no ea t|
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ ^私は猫が大好き{0:>----} ✨🐈|
|
{0:~ }|
{0:~ }|
- {0:~ }|
|
]])
- feed('<esc><LeftMouse><15,0>')
+ feed('<esc><LeftMouse><13,2>')
screen:expect([[
- rem ipum do it ^, conetetu|
- tet ta kad beren, no ea t|
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ 私は猫が大好^き{0:>----} ✨🐈|
|
{0:~ }|
{0:~ }|
- {0:~ }|
|
]])
- feed('<esc><LeftMouse><15,1>')
+ feed('<esc><LeftMouse><20,2>')
screen:expect([[
- rem ipum do it , conetetu|
- tet ta kad bere^n, no ea t|
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 t4 |
+ 私は猫が大好き{0:>----}^ ✨🐈|
|
{0:~ }|
{0:~ }|
- {0:~ }|
|
]])
end) -- level 3 - non wrapped
@@ -1014,49 +1140,94 @@ describe('ui/mouse/input', function()
it('(level 3) click on wrapped lines', function()
feed_command('let &conceallevel=3', 'let &wrap=1', 'echo')
- feed('<esc><LeftMouse><0,0>')
+ feed('<esc><LeftMouse><14,1>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} ^t2 t3 |
+ t4 |
+ 私は猫が大好き{0:>----} |
+ ✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><18,1>')
screen:expect([[
- ^rem ipum do it |
- , conetetur adipcin |
- elitr. |
- tet ta kad beren |
- , no ea takimata anctu |
- et. |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t^3 |
+ t4 |
+ 私は猫が大好き{0:>----} |
+ ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><6,1>')
+ feed('<esc><LeftMouse><1,2>')
screen:expect([[
- rem ipum do it |
- , cone^tetur adipcin |
- elitr. |
- tet ta kad beren |
- , no ea takimata anctu |
- et. |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t^4 |
+ 私は猫が大好き{0:>----} |
+ ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><15,1>')
+ feed('<esc><LeftMouse><0,3>')
screen:expect([[
- rem ipum do it |
- , conetetur adi^pcin |
- elitr. |
- tet ta kad beren |
- , no ea takimata anctu |
- et. |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ ^ 私は猫が大好き{0:>----} |
+ ✨🐈✨ |
+ |
|
]])
- feed('<esc><LeftMouse><15,3>')
+ feed('<esc><LeftMouse><20,3>')
screen:expect([[
- rem ipum do it |
- , conetetur adipcin |
- elitr. |
- tet ta kad bere^n |
- , no ea takimata anctu |
- et. |
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ 私は猫が大好き{0:>----}^ |
+ ✨🐈✨ |
+ |
|
]])
+
+ feed('<esc><LeftMouse><1,4>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ 私は猫が大好き{0:>----} |
+ ^✨🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><3,4>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ 私は猫が大好き{0:>----} |
+ ✨^🐈✨ |
+ |
+ |
+ ]])
+
+ feed('<esc><LeftMouse><5,4>')
+ screen:expect([[
+ Section{0:>>--->--->---}t1 |
+ {0:>--->--->---} t2 t3 |
+ t4 |
+ 私は猫が大好き{0:>----} |
+ ✨🐈^✨ |
+ |
+ |
+ ]])
+
end) -- level 3 - wrapped
end)
end)
diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua
new file mode 100644
index 0000000000..62b08c0967
--- /dev/null
+++ b/test/functional/ui/options_spec.lua
@@ -0,0 +1,110 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local command = helpers.command
+local eq = helpers.eq
+
+describe('ui receives option updates', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(20,5)
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ local defaults = {
+ ambiwidth='single',
+ arabicshape=true,
+ emoji=true,
+ guifont='',
+ guifontset='',
+ guifontwide='',
+ linespace=0,
+ showtabline=1,
+ termguicolors=false,
+ ext_cmdline=false,
+ ext_popupmenu=false,
+ ext_tabline=false,
+ ext_wildmenu=false,
+ }
+
+ it("for defaults", function()
+ screen:attach()
+ screen:expect(function()
+ eq(defaults, screen.options)
+ end)
+ end)
+
+ it("when setting options", function()
+ screen:attach()
+ local changed = {}
+ for k,v in pairs(defaults) do
+ changed[k] = v
+ end
+
+ command("set termguicolors")
+ changed.termguicolors = true
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+
+ command("set guifont=Comic\\ Sans")
+ changed.guifont = "Comic Sans"
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+
+ command("set showtabline=0")
+ changed.showtabline = 0
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+
+ command("set linespace=13")
+ changed.linespace = 13
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+
+ command("set linespace=-11")
+ changed.linespace = -11
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+
+ command("set all&")
+ screen:expect(function()
+ eq(defaults, screen.options)
+ end)
+ end)
+
+ it('with UI extensions', function()
+ local changed = {}
+ for k,v in pairs(defaults) do
+ changed[k] = v
+ end
+
+ screen:attach({ext_cmdline=true, ext_wildmenu=true})
+ changed.ext_cmdline = true
+ changed.ext_wildmenu = true
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+
+ screen:set_option('ext_popupmenu', true)
+ changed.ext_popupmenu = true
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+
+ screen:set_option('ext_wildmenu', false)
+ changed.ext_wildmenu = false
+ screen:expect(function()
+ eq(changed, screen.options)
+ end)
+ end)
+end)
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index c6d564e8dc..4246020fab 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -1,14 +1,24 @@
-local session = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local helpers = require('test.functional.helpers')(after_each)
local child_session = require('test.functional.terminal.helpers')
-
-if session.pending_win32(pending) then return end
+local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir
+local eq = helpers.eq
+local eval = helpers.eval
+local feed = helpers.feed
+local feed_command = helpers.feed_command
+local iswin = helpers.iswin
+local clear = helpers.clear
+local command = helpers.command
+local nvim_dir = helpers.nvim_dir
describe("shell command :!", function()
+ if helpers.pending_win32(pending) then return end
+
local screen
before_each(function()
- session.clear()
- screen = child_session.screen_setup(0, '["'..session.nvim_prog..
- '", "-u", "NONE", "-i", "NONE", "--cmd", "'..session.nvim_set..'"]')
+ clear()
+ screen = child_session.screen_setup(0, '["'..helpers.nvim_prog..
+ '", "-u", "NONE", "-i", "NONE", "--cmd", "'..helpers.nvim_set..'"]')
screen:expect([[
{1: } |
{4:~ }|
@@ -33,15 +43,15 @@ describe("shell command :!", function()
{4:~ }|
{4:~ }|
{4:~ }|
+ {4:~ }|
:!printf foo; sleep 200 |
- |
foo |
{3:-- TERMINAL --} |
]])
end)
it("throttles shell-command output greater than ~10KB", function()
- if os.getenv("TRAVIS") and session.os_name() == "osx" then
+ if os.getenv("TRAVIS") and helpers.os_name() == "osx" then
pending("[Unreliable on Travis macOS.]", function() end)
return
end
@@ -56,13 +66,164 @@ describe("shell command :!", function()
-- Final chunk of output should always be displayed, never skipped.
-- (Throttling is non-deterministic, this test is merely a sanity check.)
screen:expect([[
- XXXXXXXXXX 2996 |
XXXXXXXXXX 2997 |
XXXXXXXXXX 2998 |
XXXXXXXXXX 2999 |
XXXXXXXXXX 3000 |
+ |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
]])
end)
end)
+
+describe("shell command :!", function()
+ before_each(function()
+ clear()
+ end)
+
+ it("cat a binary file #4142", function()
+ feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>")
+ eq(2, eval('1+1')) -- Still alive?
+ end)
+
+ it([[display \x08 char #4142]], function()
+ feed(":silent !echo \08<CR>")
+ eq(2, eval('1+1')) -- Still alive?
+ end)
+
+ it([[handles control codes]], function()
+ if iswin() then
+ pending('missing printf', function() end)
+ return
+ end
+ local screen = Screen.new(50, 4)
+ screen:attach()
+ -- Print TAB chars. #2958
+ feed([[:!printf '1\t2\t3'<CR>]])
+ screen:expect([[
+ ~ |
+ :!printf '1\t2\t3' |
+ 1 2 3 |
+ Press ENTER or type command to continue^ |
+ ]])
+ feed([[<CR>]])
+ -- Print BELL control code. #4338
+ screen.bell = false
+ feed([[:!printf '\x07\x07\x07\x07text'<CR>]])
+ screen:expect([[
+ ~ |
+ :!printf '\x07\x07\x07\x07text' |
+ text |
+ Press ENTER or type command to continue^ |
+ ]], nil, nil, function()
+ eq(true, screen.bell)
+ end)
+ feed([[<CR>]])
+ -- Print BS control code.
+ feed([[:echo system('printf ''\x08\n''')<CR>]])
+ screen:expect([[
+ ~ |
+ ^H |
+ |
+ Press ENTER or type command to continue^ |
+ ]])
+ feed([[<CR>]])
+ -- Print LF control code.
+ feed([[:!printf '\n'<CR>]])
+ screen:expect([[
+ :!printf '\n' |
+ |
+ |
+ Press ENTER or type command to continue^ |
+ ]])
+ feed([[<CR>]])
+ end)
+
+ describe('', function()
+ local screen
+ before_each(function()
+ rmdir('bang_filter_spec')
+ mkdir('bang_filter_spec')
+ write_file('bang_filter_spec/f1', 'f1')
+ write_file('bang_filter_spec/f2', 'f2')
+ write_file('bang_filter_spec/f3', 'f3')
+ screen = Screen.new(53,10)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {foreground = Screen.colors.Blue1},
+ [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ })
+ screen:attach()
+ end)
+
+ after_each(function()
+ rmdir('bang_filter_spec')
+ end)
+
+ it("doesn't truncate Last line of shell output #3269", function()
+ command(helpers.iswin()
+ and [[nnoremap <silent>\l :!dir /b bang_filter_spec<cr>]]
+ or [[nnoremap <silent>\l :!ls bang_filter_spec<cr>]])
+ local result = (helpers.iswin()
+ and [[:!dir /b bang_filter_spec]]
+ or [[:!ls bang_filter_spec ]])
+ feed([[\l]])
+ screen:expect([[
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]]..result..[[ |
+ f1 |
+ f2 |
+ f3 |
+ |
+ {3:Press ENTER or type command to continue}^ |
+ ]])
+ end)
+
+ it('handles binary and multibyte data', function()
+ feed_command('!cat test/functional/fixtures/shell_data.txt')
+ screen.bell = false
+ screen:expect([[
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :!cat test/functional/fixtures/shell_data.txt |
+ {2:^@^A^B^C^D^E^F^H} |
+ {2:^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_} |
+ ö 한글 {2:<a5><c3>} |
+ t {2:<ff>} |
+ |
+ {3:Press ENTER or type command to continue}^ |
+ ]], nil, nil, function()
+ eq(true, screen.bell)
+ end)
+ end)
+
+ it('handles multibyte sequences split over buffer boundaries', function()
+ command('cd '..nvim_dir)
+ local cmd
+ if iswin() then
+ cmd = '!shell-test UTF-8 '
+ else
+ cmd = '!./shell-test UTF-8'
+ end
+ feed_command(cmd)
+ -- Note: only the first example of split composed char works
+ screen:expect([[
+ {1:~ }|
+ {1:~ }|
+ :]]..cmd..[[ |
+ å |
+ ref: å̲ |
+ 1: å̲ |
+ 2: å ̲ |
+ 3: å ̲ |
+ |
+ {3:Press ENTER or type command to continue}^ |
+ ]])
+ end)
+ end)
+end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 5408e1e195..52e108f389 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -137,6 +137,7 @@ function Screen.new(width, height)
visual_bell = false,
suspended = false,
mode = 'normal',
+ options = {},
_default_attr_ids = nil,
_default_attr_ignore = nil,
_mouse_enabled = true,
@@ -176,6 +177,10 @@ function Screen:try_resize(columns, rows)
self:sleep(0.1)
end
+function Screen:set_option(option, value)
+ uimeths.set_option(option, value)
+end
+
-- Asserts that `expected` eventually matches the screen state.
--
-- expected: Expected screen state (string). Each line represents a screen
@@ -251,7 +256,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
@@ -450,6 +455,9 @@ function Screen:_handle_visual_bell()
self.visual_bell = true
end
+function Screen:_handle_default_colors_set()
+end
+
function Screen:_handle_update_fg(fg)
self._fg = fg
end
@@ -478,6 +486,10 @@ function Screen:_handle_set_icon(icon)
self.icon = icon
end
+function Screen:_handle_option_set(name, value)
+ self.options[name] = value
+end
+
function Screen:_clear_block(top, bot, left, right)
for i = top, bot do
self:_clear_row_section(i, left, right)
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index bfcdc7f652..bbdf576641 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -5,6 +5,7 @@ local feed, command = helpers.feed, helpers.command
local insert = helpers.insert
local eq = helpers.eq
local eval = helpers.eval
+local iswin = helpers.iswin
describe('screen', function()
local screen
@@ -119,9 +120,10 @@ describe('Screen', function()
end)
it('has correct default title with named file', function()
- local expected = 'myfile (/mydir) - NVIM'
+ local expected = (iswin() and 'myfile (C:\\mydir) - NVIM'
+ or 'myfile (/mydir) - NVIM')
command('set title')
- command('file /mydir/myfile')
+ command(iswin() and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
screen:expect(function()
eq(expected, screen.title)
end)
@@ -187,12 +189,12 @@ describe('Screen', function()
command('vsp')
command('vsp')
screen:expect([[
- ^ {3:|} {3:|} |
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
+ ^ {3:│} {3:│} |
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
{1:[No Name] }{3:[No Name] [No Name] }|
|
{0:~ }|
@@ -204,12 +206,12 @@ describe('Screen', function()
]])
insert('hello')
screen:expect([[
- hell^o {3:|}hello {3:|}hello |
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
+ hell^o {3:│}hello {3:│}hello |
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
hello |
{0:~ }|
@@ -230,12 +232,12 @@ describe('Screen', function()
command('vsp')
insert('hello')
screen:expect([[
- hell^o {3:|}hello {3:|}hello |
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
+ hell^o {3:│}hello {3:│}hello |
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
hello |
{0:~ }|
@@ -267,12 +269,12 @@ describe('Screen', function()
command('tabprevious')
screen:expect([[
{2: }{6:4}{2:+ [No Name] }{4: + [No Name] }{3: }{4:X}|
- hell^o {3:|}hello {3:|}hello |
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
- {0:~ }{3:|}{0:~ }{3:|}{0:~ }|
+ hell^o {3:│}hello {3:│}hello |
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
+ {0:~ }{3:│}{0:~ }{3:│}{0:~ }|
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
hello |
{0:~ }|
@@ -396,12 +398,12 @@ describe('Screen', function()
command('vsp')
command('vsp')
screen:expect([[
- and {3:|}and {3:|}and |
- clearing {3:|}clearing {3:|}clearing |
- in {3:|}in {3:|}in |
- split {3:|}split {3:|}split |
- windows {3:|}windows {3:|}windows |
- ^ {3:|} {3:|} |
+ and {3:│}and {3:│}and |
+ clearing {3:│}clearing {3:│}clearing |
+ in {3:│}in {3:│}in |
+ split {3:│}split {3:│}split |
+ windows {3:│}windows {3:│}windows |
+ ^ {3:│} {3:│} |
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
clearing |
in |
@@ -416,12 +418,12 @@ describe('Screen', function()
it('only affects the current scroll region', function()
feed('6k')
screen:expect([[
- ^scrolling {3:|}and {3:|}and |
- and {3:|}clearing {3:|}clearing |
- clearing {3:|}in {3:|}in |
- in {3:|}split {3:|}split |
- split {3:|}windows {3:|}windows |
- windows {3:|} {3:|} |
+ ^scrolling {3:│}and {3:│}and |
+ and {3:│}clearing {3:│}clearing |
+ clearing {3:│}in {3:│}in |
+ in {3:│}split {3:│}split |
+ split {3:│}windows {3:│}windows |
+ windows {3:│} {3:│} |
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
clearing |
in |
@@ -433,12 +435,12 @@ describe('Screen', function()
]])
feed('<c-w>l')
screen:expect([[
- scrolling {3:|}and {3:|}and |
- and {3:|}clearing {3:|}clearing |
- clearing {3:|}in {3:|}in |
- in {3:|}split {3:|}split |
- split {3:|}windows {3:|}windows |
- windows {3:|}^ {3:|} |
+ scrolling {3:│}and {3:│}and |
+ and {3:│}clearing {3:│}clearing |
+ clearing {3:│}in {3:│}in |
+ in {3:│}split {3:│}split |
+ split {3:│}windows {3:│}windows |
+ windows {3:│}^ {3:│} |
{3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }|
clearing |
in |
@@ -450,12 +452,12 @@ describe('Screen', function()
]])
feed('gg')
screen:expect([[
- scrolling {3:|}^Inserting {3:|}and |
- and {3:|}text {3:|}clearing |
- clearing {3:|}with {3:|}in |
- in {3:|}many {3:|}split |
- split {3:|}lines {3:|}windows |
- windows {3:|}to {3:|} |
+ scrolling {3:│}^Inserting {3:│}and |
+ and {3:│}text {3:│}clearing |
+ clearing {3:│}with {3:│}in |
+ in {3:│}many {3:│}split |
+ split {3:│}lines {3:│}windows |
+ windows {3:│}to {3:│} |
{3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }|
clearing |
in |
@@ -467,12 +469,12 @@ describe('Screen', function()
]])
feed('7j')
screen:expect([[
- scrolling {3:|}with {3:|}and |
- and {3:|}many {3:|}clearing |
- clearing {3:|}lines {3:|}in |
- in {3:|}to {3:|}split |
- split {3:|}test {3:|}windows |
- windows {3:|}^scrolling {3:|} |
+ scrolling {3:│}with {3:│}and |
+ and {3:│}many {3:│}clearing |
+ clearing {3:│}lines {3:│}in |
+ in {3:│}to {3:│}split |
+ split {3:│}test {3:│}windows |
+ windows {3:│}^scrolling {3:│} |
{3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }|
clearing |
in |
@@ -484,12 +486,12 @@ describe('Screen', function()
]])
feed('2j')
screen:expect([[
- scrolling {3:|}lines {3:|}and |
- and {3:|}to {3:|}clearing |
- clearing {3:|}test {3:|}in |
- in {3:|}scrolling {3:|}split |
- split {3:|}and {3:|}windows |
- windows {3:|}^clearing {3:|} |
+ scrolling {3:│}lines {3:│}and |
+ and {3:│}to {3:│}clearing |
+ clearing {3:│}test {3:│}in |
+ in {3:│}scrolling {3:│}split |
+ split {3:│}and {3:│}windows |
+ windows {3:│}^clearing {3:│} |
{3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }|
clearing |
in |
@@ -501,12 +503,12 @@ describe('Screen', function()
]])
feed('5k')
screen:expect([[
- scrolling {3:|}^lines {3:|}and |
- and {3:|}to {3:|}clearing |
- clearing {3:|}test {3:|}in |
- in {3:|}scrolling {3:|}split |
- split {3:|}and {3:|}windows |
- windows {3:|}clearing {3:|} |
+ scrolling {3:│}^lines {3:│}and |
+ and {3:│}to {3:│}clearing |
+ clearing {3:│}test {3:│}in |
+ in {3:│}scrolling {3:│}split |
+ split {3:│}and {3:│}windows |
+ windows {3:│}clearing {3:│} |
{3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }|
clearing |
in |
@@ -518,12 +520,12 @@ describe('Screen', function()
]])
feed('k')
screen:expect([[
- scrolling {3:|}^many {3:|}and |
- and {3:|}lines {3:|}clearing |
- clearing {3:|}to {3:|}in |
- in {3:|}test {3:|}split |
- split {3:|}scrolling {3:|}windows |
- windows {3:|}and {3:|} |
+ scrolling {3:│}^many {3:│}and |
+ and {3:│}lines {3:│}clearing |
+ clearing {3:│}to {3:│}in |
+ in {3:│}test {3:│}split |
+ split {3:│}scrolling {3:│}windows |
+ windows {3:│}and {3:│} |
{3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }|
clearing |
in |
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index 11b18d015f..9f273e8dc9 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -2,8 +2,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 feed_command = helpers.feed_command
-
-if helpers.pending_win32(pending) then return end
+local eq = helpers.eq
+local eval = helpers.eval
describe('search highlighting', function()
local screen
@@ -101,7 +101,30 @@ describe('search highlighting', function()
feed("gg/li")
screen:expect([[
the first {3:li}ne |
- in a little file |
+ in a {2:li}ttle file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /li^ |
+ ]])
+
+ -- check that consecutive matches are caught by C-g/C-t
+ feed("<C-g>")
+ screen:expect([[
+ the first {2:li}ne |
+ in a {3:li}ttle file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /li^ |
+ ]])
+
+ feed("<C-t>")
+ screen:expect([[
+ the first {3:li}ne |
+ in a {2:li}ttle file |
|
{1:~ }|
{1:~ }|
@@ -134,7 +157,7 @@ describe('search highlighting', function()
feed("/fir")
screen:expect([[
the {3:fir}st line |
- in a {2:lit}tle file |
+ in a little file |
|
{1:~ }|
{1:~ }|
@@ -146,13 +169,107 @@ describe('search highlighting', function()
feed("<esc>/ttle")
screen:expect([[
the first line |
- in a {2:li}{3:ttle} file |
+ in a li{3:ttle} file |
|
{1:~ }|
{1:~ }|
{1:~ }|
/ttle^ |
]])
+
+ -- cancelling search resets to the old search term
+ feed('<esc>')
+ screen:expect([[
+ the first line |
+ in a {2:^lit}tle file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ eq('lit', eval('@/'))
+
+ -- cancelling inc search restores the hl state
+ feed(':noh<cr>')
+ screen:expect([[
+ the first line |
+ in a ^little file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :noh |
+ ]])
+
+ feed('/first')
+ screen:expect([[
+ the {3:first} line |
+ in a little file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /first^ |
+ ]])
+ feed('<esc>')
+ screen:expect([[
+ the first line |
+ in a ^little file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+
+ -- test that pressing C-g in an empty command line does not move the cursor
+ feed('/<C-g>')
+ screen:expect([[
+ the first line |
+ in a little file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /^ |
+ ]])
+
+ -- same, for C-t
+ feed('<ESC>/<C-t>')
+ screen:expect([[
+ the first line |
+ in a little file |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /^ |
+ ]])
+
+ -- 8.0.1304, test that C-g and C-t works with incsearch and empty pattern
+ feed('<esc>/fi<CR>')
+ feed('//')
+ screen:expect([[
+ the {3:fi}rst line |
+ in a little {2:fi}le |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ //^ |
+ ]])
+
+ feed('<C-g>')
+ screen:expect([[
+ the {2:fi}rst line |
+ in a little {3:fi}le |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ //^ |
+ ]])
end)
it('works with incsearch and offset', function()
@@ -165,7 +282,7 @@ describe('search highlighting', function()
feed("gg/mat/e")
screen:expect([[
not the {3:mat}ch you're looking for |
- the match is here |
+ the {2:mat}ch is here |
{1:~ }|
{1:~ }|
{1:~ }|
@@ -176,7 +293,7 @@ describe('search highlighting', function()
-- Search with count and /e offset fixed in Vim patch 7.4.532.
feed("<esc>2/mat/e")
screen:expect([[
- not the match you're looking for |
+ not the {2:mat}ch you're looking for |
the {3:mat}ch is here |
{1:~ }|
{1:~ }|
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index e5c96f2ec0..c00d99cf90 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -2,8 +2,6 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, command = helpers.clear, helpers.feed, helpers.command
-if helpers.pending_win32(pending) then return end
-
describe('Signs', function()
local screen
diff --git a/test/functional/ui/spell_spec.lua b/test/functional/ui/spell_spec.lua
new file mode 100644
index 0000000000..913f1b9bed
--- /dev/null
+++ b/test/functional/ui/spell_spec.lua
@@ -0,0 +1,49 @@
+-- Test for scenarios involving 'spell'
+
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local feed = helpers.feed
+local feed_command = helpers.feed_command
+local insert = helpers.insert
+
+describe("'spell'", function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(80, 8)
+ screen:attach()
+ screen:set_default_attr_ids( {
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = {special = Screen.colors.Red, undercurl = true}
+ })
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ it('joins long lines #7937', function()
+ feed_command('set spell')
+ insert([[
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
+ cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
+ non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+ ]])
+ feed('ggJJJJJJ0')
+ screen:expect([[
+ {1:^Lorem} {1:ipsum} dolor sit {1:amet}, {1:consectetur} {1:adipiscing} {1:elit}, {1:sed} do {1:eiusmod} {1:tempor} {1:i}|
+ {1:ncididunt} {1:ut} {1:labore} {1:et} {1:dolore} {1:magna} {1:aliqua}. {1:Ut} {1:enim} ad minim {1:veniam}, {1:quis} {1:nostru}|
+ {1:d} {1:exercitation} {1:ullamco} {1:laboris} {1:nisi} {1:ut} {1:aliquip} ex ea {1:commodo} {1:consequat}. {1:Duis} {1:aut}|
+ {1:e} {1:irure} dolor in {1:reprehenderit} in {1:voluptate} {1:velit} {1:esse} {1:cillum} {1:dolore} {1:eu} {1:fugiat} {1:n}|
+ {1:ulla} {1:pariatur}. {1:Excepteur} {1:sint} {1:occaecat} {1:cupidatat} non {1:proident}, {1:sunt} in culpa {1:qui}|
+ {1:officia} {1:deserunt} {1:mollit} {1:anim} id est {1:laborum}. |
+ {0:~ }|
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua
index 28a104360d..e7a7004c1e 100644
--- a/test/functional/ui/syntax_conceal_spec.lua
+++ b/test/functional/ui/syntax_conceal_spec.lua
@@ -3,8 +3,6 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, command = helpers.clear, helpers.feed, helpers.command
local insert = helpers.insert
-if helpers.pending_win32(pending) then return end
-
describe('Screen', function()
local screen
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
index 56331a33b5..e8271de0bf 100644
--- a/test/functional/ui/tabline_spec.lua
+++ b/test/functional/ui/tabline_spec.lua
@@ -2,7 +2,7 @@ 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/tabline', function()
+describe('ui/ext_tabline', function()
local screen
local event_tabs, event_curtab
@@ -21,37 +21,34 @@ describe('ui/tabline', function()
screen:detach()
end)
- describe('externalized', function()
- it('publishes UI events', function()
- command("tabedit another-tab")
+ 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)
+ 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 052cdd55a1..c6ddc78618 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -1,57 +1,150 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
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()
- command('set wildmode=full')
- command('set wildmenu')
- feed(':sign <tab>')
- screen:expect([[
- |
- ~ |
- ~ |
- define jump list > |
- :sign define^ |
- ]])
- end)
+ 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
+ feed([[:terminal for /L \%I in (1,1,5000) do @(echo foo & echo foo & echo foo)<cr>]])
+ 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')
- 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([[
- |
- ~ |
- ~ |
- ! # & < = > @ > |
- :!^ |
- ]])
+ -- 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)
@@ -85,3 +178,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)