mirror of
https://github.com/neovim/neovim.git
synced 2024-12-21 19:55:04 -07:00
5a836d4767
In vim, scrolling a window might mess up the cmdline. To keep it simple, cmdline was always cleared for any window scroll. In nvim, where safe scrolling is implemented in the TUI layer, this problem doesn't exist. Clearing the message on scrolling, when we not do it e.g when switching tabs is a bit weird, as the former is a much smaller context change. A vim patch introduced the possibility to avoid the cmdlline clear for redraws caused by async events. This case will now trivially be covered, as the redraw is always avoided. vim-patch:8.0.0592: if a job writes to a buffer screen is not updated
845 lines
37 KiB
Lua
845 lines
37 KiB
Lua
local helpers = require('test.functional.helpers')(after_each)
|
|
local clear = helpers.clear
|
|
local feed_command = helpers.feed_command
|
|
local feed = helpers.feed
|
|
local eq = helpers.eq
|
|
local expect = helpers.expect
|
|
local eval = helpers.eval
|
|
local funcs = helpers.funcs
|
|
local insert = helpers.insert
|
|
local exc_exec = helpers.exc_exec
|
|
local source = helpers.source
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
describe('mappings with <Cmd>', function()
|
|
local screen
|
|
local function cmdmap(lhs, rhs)
|
|
feed_command('noremap '..lhs..' <Cmd>'..rhs..'<cr>')
|
|
feed_command('noremap! '..lhs..' <Cmd>'..rhs..'<cr>')
|
|
end
|
|
|
|
before_each(function()
|
|
clear()
|
|
screen = Screen.new(65, 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},
|
|
[4] = {bold = true},
|
|
[5] = {background = Screen.colors.LightGrey},
|
|
[6] = {foreground = Screen.colors.Blue1},
|
|
[7] = {bold = true, reverse = true},
|
|
[8] = {background = Screen.colors.WebGray},
|
|
[9] = {background = Screen.colors.LightMagenta},
|
|
[10] = {foreground = Screen.colors.Red},
|
|
})
|
|
screen:attach()
|
|
|
|
cmdmap('<F3>', 'let m = mode(1)')
|
|
cmdmap('<F4>', 'normal! ww')
|
|
cmdmap('<F5>', 'normal! "ay')
|
|
cmdmap('<F6>', 'throw "very error"')
|
|
feed_command([[
|
|
function! TextObj()
|
|
if mode() !=# "v"
|
|
normal! v
|
|
end
|
|
call cursor(1,3)
|
|
normal! o
|
|
call cursor(2,4)
|
|
endfunction]])
|
|
cmdmap('<F7>', 'call TextObj()')
|
|
insert([[
|
|
some short lines
|
|
of test text]])
|
|
feed('gg')
|
|
cmdmap('<F8>', 'startinsert')
|
|
cmdmap('<F9>', 'stopinsert')
|
|
feed_command("abbr foo <Cmd>let g:y = 17<cr>bar")
|
|
end)
|
|
|
|
it('can be displayed', function()
|
|
feed_command('map <F3>')
|
|
screen:expect([[
|
|
^some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{6:<F3>} {6:*} {6:<Cmd>}let m = mode(1){6:<CR>} |
|
|
]])
|
|
end)
|
|
|
|
it('handles invalid mappings', function()
|
|
feed_command('let x = 0')
|
|
feed_command('noremap <F3> <Cmd><Cmd>let x = 1<cr>')
|
|
feed('<F3>')
|
|
screen:expect([[
|
|
^some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{2:E5521: <Cmd> mapping must end with <CR> before second <Cmd>} |
|
|
]])
|
|
|
|
feed_command('noremap <F3> <Cmd><F3>let x = 2<cr>')
|
|
feed('<F3>')
|
|
screen:expect([[
|
|
^some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{2:E5522: <Cmd> mapping must not include <F3> key} |
|
|
]])
|
|
|
|
feed_command('noremap <F3> <Cmd>let x = 3')
|
|
feed('<F3>')
|
|
screen:expect([[
|
|
^some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{2:E5520: <Cmd> mapping must end with <CR>} |
|
|
]])
|
|
eq(0, eval('x'))
|
|
end)
|
|
|
|
it('works in various modes and sees correct `mode()` value', function()
|
|
-- normal mode
|
|
feed('<F3>')
|
|
eq('n', eval('m'))
|
|
|
|
-- visual mode
|
|
feed('v<F3>')
|
|
eq('v', eval('m'))
|
|
-- didn't leave visual mode
|
|
eq('v', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('n', eval('mode(1)'))
|
|
|
|
-- visual mapping in select mode
|
|
feed('gh<F3>')
|
|
eq('v', eval('m'))
|
|
-- didn't leave select mode
|
|
eq('s', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('n', eval('mode(1)'))
|
|
|
|
-- select mode mapping
|
|
feed_command('snoremap <F3> <Cmd>let m = mode(1)<cr>')
|
|
feed('gh<F3>')
|
|
eq('s', eval('m'))
|
|
-- didn't leave select mode
|
|
eq('s', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('n', eval('mode(1)'))
|
|
|
|
-- operator-pending mode
|
|
feed("d<F3>")
|
|
eq('no', eval('m'))
|
|
-- did leave operator-pending mode
|
|
eq('n', eval('mode(1)'))
|
|
|
|
--insert mode
|
|
feed('i<F3>')
|
|
eq('i', eval('m'))
|
|
eq('i', eval('mode(1)'))
|
|
|
|
-- replace mode
|
|
feed("<Ins><F3>")
|
|
eq('R', eval('m'))
|
|
eq('R', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('n', eval('mode(1)'))
|
|
|
|
-- virtual replace mode
|
|
feed("gR<F3>")
|
|
eq('Rv', eval('m'))
|
|
eq('Rv', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('n', eval('mode(1)'))
|
|
|
|
-- langmap works, but is not distinguished in mode(1)
|
|
feed(":set iminsert=1<cr>i<F3>")
|
|
eq('i', eval('m'))
|
|
eq('i', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('n', eval('mode(1)'))
|
|
|
|
feed(':<F3>')
|
|
eq('c', eval('m'))
|
|
eq('c', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('n', eval('mode(1)'))
|
|
|
|
-- terminal mode
|
|
feed_command('tnoremap <F3> <Cmd>let m = mode(1)<cr>')
|
|
feed_command('split | terminal')
|
|
feed('i')
|
|
eq('t', eval('mode(1)'))
|
|
feed('<F3>')
|
|
eq('t', eval('m'))
|
|
eq('t', eval('mode(1)'))
|
|
end)
|
|
|
|
it('works in normal mode', function()
|
|
cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
|
|
|
|
-- check v:count and v:register works
|
|
feed('<F2>')
|
|
eq({'n', 0, '"'}, eval('s'))
|
|
feed('7<F2>')
|
|
eq({'n', 7, '"'}, eval('s'))
|
|
feed('"e<F2>')
|
|
eq({'n', 0, 'e'}, eval('s'))
|
|
feed('5"k<F2>')
|
|
eq({'n', 5, 'k'}, eval('s'))
|
|
feed('"+2<F2>')
|
|
eq({'n', 2, '+'}, eval('s'))
|
|
|
|
-- text object enters visual mode
|
|
feed('<F7>')
|
|
screen:expect([[
|
|
so{5:me short lines} |
|
|
{5:of }^test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- VISUAL --} |
|
|
]])
|
|
feed('<esc>')
|
|
|
|
-- startinsert
|
|
feed('<F8>')
|
|
eq('i', eval('mode(1)'))
|
|
feed('<esc>')
|
|
|
|
eq('n', eval('mode(1)'))
|
|
cmdmap(',a', 'call feedkeys("aalpha") \\| let g:a = getline(2)')
|
|
cmdmap(',b', 'call feedkeys("abeta", "x") \\| let g:b = getline(2)')
|
|
|
|
feed(',a<F3>')
|
|
screen:expect([[
|
|
some short lines |
|
|
of alpha^test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- INSERT --} |
|
|
]])
|
|
-- feedkeys were not executed immediately
|
|
eq({'n', 'of test text'}, eval('[m,a]'))
|
|
eq('i', eval('mode(1)'))
|
|
feed('<esc>')
|
|
|
|
feed(',b<F3>')
|
|
screen:expect([[
|
|
some short lines |
|
|
of alphabet^atest text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
|
|
|
]])
|
|
-- feedkeys(..., 'x') was executed immediately, but insert mode gets aborted
|
|
eq({'n', 'of alphabetatest text'}, eval('[m,b]'))
|
|
eq('n', eval('mode(1)'))
|
|
end)
|
|
|
|
it('works in :normal command', function()
|
|
feed_command('noremap ,x <Cmd>call append(1, "xx")\\| call append(1, "aa")<cr>')
|
|
feed_command('noremap ,f <Cmd>nosuchcommand<cr>')
|
|
feed_command('noremap ,e <Cmd>throw "very error"\\| call append(1, "yy")<cr>')
|
|
feed_command('noremap ,m <Cmd>echoerr "The message."\\| call append(1, "zz")<cr>')
|
|
feed_command('noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>')
|
|
|
|
feed(":normal ,x<cr>")
|
|
screen:expect([[
|
|
^some short lines |
|
|
aa |
|
|
xx |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
:normal ,x |
|
|
]])
|
|
|
|
eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec("normal ,f"))
|
|
eq('very error', exc_exec("normal ,e"))
|
|
eq('Vim(echoerr):The message.', exc_exec("normal ,m"))
|
|
feed('w')
|
|
screen:expect([[
|
|
some ^short lines |
|
|
aa |
|
|
xx |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
:normal ,x |
|
|
]])
|
|
|
|
feed_command(':%d')
|
|
eq('Vim(echoerr):Err', exc_exec("normal ,w"))
|
|
screen:expect([[
|
|
^ |
|
|
0 |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
--No lines in buffer-- |
|
|
]])
|
|
|
|
feed_command(':%d')
|
|
feed_command(':normal ,w')
|
|
screen:expect([[
|
|
^ |
|
|
4 |
|
|
3 |
|
|
2 |
|
|
1 |
|
|
0 |
|
|
{1:~ }|
|
|
{2:Err} |
|
|
]])
|
|
end)
|
|
|
|
it('works in visual mode', function()
|
|
-- can extend visual mode
|
|
feed('v<F4>')
|
|
screen:expect([[
|
|
{5:some short }^lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- VISUAL --} |
|
|
]])
|
|
eq('v', funcs.mode(1))
|
|
|
|
-- can invoke operator, ending visual mode
|
|
feed('<F5>')
|
|
eq('n', funcs.mode(1))
|
|
eq({'some short l'}, funcs.getreg('a',1,1))
|
|
|
|
-- error doesn't interrupt visual mode
|
|
feed('ggvw<F6>')
|
|
screen:expect([[
|
|
{5:some }short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{7: }|
|
|
{2:Error detected while processing :} |
|
|
{2:E605: Exception not caught: very error} |
|
|
{3:Press ENTER or type command to continue}^ |
|
|
]])
|
|
feed('<cr>')
|
|
eq('E605: Exception not caught: very error', eval('v:errmsg'))
|
|
-- still in visual mode, <cr> was consumed by the error prompt
|
|
screen:expect([[
|
|
{5:some }^short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- VISUAL --} |
|
|
]])
|
|
eq('v', funcs.mode(1))
|
|
feed('<F7>')
|
|
screen:expect([[
|
|
so{5:me short lines} |
|
|
{5:of }^test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- VISUAL --} |
|
|
]])
|
|
eq('v', funcs.mode(1))
|
|
|
|
-- startinsert gives "-- (insert) VISUAL --" mode
|
|
feed('<F8>')
|
|
screen:expect([[
|
|
so{5:me short lines} |
|
|
{5:of }^test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- (insert) VISUAL --} |
|
|
]])
|
|
eq('v', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('i', eval('mode(1)'))
|
|
end)
|
|
|
|
it('works in select mode', function()
|
|
feed_command('snoremap <F1> <cmd>throw "very error"<cr>')
|
|
feed_command('snoremap <F2> <cmd>normal! <c-g>"by<cr>')
|
|
-- can extend select mode
|
|
feed('gh<F4>')
|
|
screen:expect([[
|
|
{5:some short }^lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- SELECT --} |
|
|
]])
|
|
eq('s', funcs.mode(1))
|
|
|
|
-- visual mapping in select mode restart selct mode after operator
|
|
feed('<F5>')
|
|
eq('s', funcs.mode(1))
|
|
eq({'some short l'}, funcs.getreg('a',1,1))
|
|
|
|
-- select mode mapping works, and does not restart select mode
|
|
feed('<F2>')
|
|
eq('n', funcs.mode(1))
|
|
eq({'some short l'}, funcs.getreg('b',1,1))
|
|
|
|
-- error doesn't interrupt temporary visual mode
|
|
feed('<esc>ggvw<c-g><F6>')
|
|
screen:expect([[
|
|
{5:some }short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{7: }|
|
|
{2:Error detected while processing :} |
|
|
{2:E605: Exception not caught: very error} |
|
|
{3:Press ENTER or type command to continue}^ |
|
|
]])
|
|
feed('<cr>')
|
|
eq('E605: Exception not caught: very error', eval('v:errmsg'))
|
|
-- still in visual mode, <cr> was consumed by the error prompt
|
|
screen:expect([[
|
|
{5:some }^short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- VISUAL --} |
|
|
]])
|
|
-- quirk: restoration of select mode is not performed
|
|
eq('v', funcs.mode(1))
|
|
|
|
-- error doesn't interrupt select mode
|
|
feed('<esc>ggvw<c-g><F1>')
|
|
screen:expect([[
|
|
{5:some }short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{7: }|
|
|
{2:Error detected while processing :} |
|
|
{2:E605: Exception not caught: very error} |
|
|
{3:Press ENTER or type command to continue}^ |
|
|
]])
|
|
feed('<cr>')
|
|
eq('E605: Exception not caught: very error', eval('v:errmsg'))
|
|
-- still in select mode, <cr> was consumed by the error prompt
|
|
screen:expect([[
|
|
{5:some }^short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- SELECT --} |
|
|
]])
|
|
-- quirk: restoration of select mode is not performed
|
|
eq('s', funcs.mode(1))
|
|
|
|
feed('<F7>')
|
|
screen:expect([[
|
|
so{5:me short lines} |
|
|
{5:of }^test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- SELECT --} |
|
|
]])
|
|
eq('s', funcs.mode(1))
|
|
|
|
-- startinsert gives "-- SELECT (insert) --" mode
|
|
feed('<F8>')
|
|
screen:expect([[
|
|
so{5:me short lines} |
|
|
{5:of }^test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- (insert) SELECT --} |
|
|
]])
|
|
eq('s', eval('mode(1)'))
|
|
feed('<esc>')
|
|
eq('i', eval('mode(1)'))
|
|
end)
|
|
|
|
|
|
it('works in operator-pending mode', function()
|
|
feed('d<F4>')
|
|
expect([[
|
|
lines
|
|
of test text]])
|
|
eq({'some short '}, funcs.getreg('"',1,1))
|
|
feed('.')
|
|
expect([[
|
|
test text]])
|
|
eq({'lines', 'of '}, funcs.getreg('"',1,1))
|
|
feed('uu')
|
|
expect([[
|
|
some short lines
|
|
of test text]])
|
|
|
|
-- error aborts operator-pending, operator not performed
|
|
feed('d<F6>')
|
|
screen:expect([[
|
|
some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{7: }|
|
|
{2:Error detected while processing :} |
|
|
{2:E605: Exception not caught: very error} |
|
|
{3:Press ENTER or type command to continue}^ |
|
|
]])
|
|
feed('<cr>')
|
|
eq('E605: Exception not caught: very error', eval('v:errmsg'))
|
|
expect([[
|
|
some short lines
|
|
of test text]])
|
|
|
|
feed('"bd<F7>')
|
|
expect([[
|
|
soest text]])
|
|
eq(funcs.getreg('b',1,1), {'me short lines', 'of t'})
|
|
|
|
-- startinsert aborts operator
|
|
feed('d<F8>')
|
|
eq('i', eval('mode(1)'))
|
|
expect([[
|
|
soest text]])
|
|
end)
|
|
|
|
it('works in insert mode', function()
|
|
|
|
-- works the same as <c-o>w<c-o>w
|
|
feed('iindeed <F4>little ')
|
|
screen:expect([[
|
|
indeed some short little ^lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- INSERT --} |
|
|
]])
|
|
|
|
feed('<F6>')
|
|
screen:expect([[
|
|
indeed some short little lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{7: }|
|
|
{2:Error detected while processing :} |
|
|
{2:E605: Exception not caught: very error} |
|
|
{3:Press ENTER or type command to continue}^ |
|
|
]])
|
|
|
|
|
|
feed('<cr>')
|
|
eq('E605: Exception not caught: very error', eval('v:errmsg'))
|
|
-- still in insert
|
|
screen:expect([[
|
|
indeed some short little ^lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- INSERT --} |
|
|
]])
|
|
eq('i', eval('mode(1)'))
|
|
|
|
-- When entering visual mode from InsertEnter autocmd, an async event, or
|
|
-- a <cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode. If a
|
|
-- vim patch decides to disable this mode, this test is expected to fail.
|
|
feed('<F7>stuff ')
|
|
screen:expect([[
|
|
in{5:deed some short little lines} |
|
|
{5:of stuff }^test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- INSERT VISUAL --} |
|
|
]])
|
|
expect([[
|
|
indeed some short little lines
|
|
of stuff test text]])
|
|
|
|
feed('<F5>')
|
|
eq(funcs.getreg('a',1,1), {'deed some short little lines', 'of stuff t'})
|
|
|
|
-- still in insert
|
|
screen:expect([[
|
|
in^deed some short little lines |
|
|
of stuff test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- INSERT --} |
|
|
]])
|
|
eq('i', eval('mode(1)'))
|
|
|
|
-- also works as part of abbreviation
|
|
feed('<space>foo ')
|
|
screen:expect([[
|
|
in bar ^deed some short little lines |
|
|
of stuff test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- INSERT --} |
|
|
]])
|
|
eq(17, eval('g:y'))
|
|
|
|
-- :startinsert does nothing
|
|
feed('<F8>')
|
|
eq('i', eval('mode(1)'))
|
|
|
|
-- :stopinsert works
|
|
feed('<F9>')
|
|
eq('n', eval('mode(1)'))
|
|
end)
|
|
|
|
it('works in insert completion (Ctrl-X) mode', function()
|
|
feed('os<c-x><c-n>')
|
|
screen:expect([[
|
|
some short lines |
|
|
some^ |
|
|
{8:some } |
|
|
{9:short }{1: }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- Keyword Local completion (^N^P) }{3:match 1 of 2} |
|
|
]])
|
|
|
|
feed('<f3>')
|
|
eq('ic', eval('m'))
|
|
|
|
-- ensure a redraw, this would have moved the cursor
|
|
-- instead if CTRL-X mode was left.
|
|
feed('<up>')
|
|
screen:expect([[
|
|
some short lines |
|
|
some^ |
|
|
{9:some } |
|
|
{9:short }{1: }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- Keyword Local completion (^N^P) }{10:Back at original} |
|
|
]])
|
|
end)
|
|
|
|
it('works in cmdline mode', function()
|
|
feed(':text<F3>')
|
|
eq('c', eval('m'))
|
|
-- didn't leave cmdline mode
|
|
eq('c', eval('mode(1)'))
|
|
feed('<cr>')
|
|
eq('n', eval('mode(1)'))
|
|
screen:expect([[
|
|
^some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{2:E492: Not an editor command: text} |
|
|
]])
|
|
|
|
feed(':echo 2<F6>')
|
|
screen:expect([[
|
|
some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{7: }|
|
|
:echo 2 |
|
|
{2:Error detected while processing :} |
|
|
{2:E605: Exception not caught: very error} |
|
|
:echo 2^ |
|
|
]])
|
|
eq('E605: Exception not caught: very error', eval('v:errmsg'))
|
|
-- didn't leave cmdline mode
|
|
eq('c', eval('mode(1)'))
|
|
feed('+2<cr>')
|
|
screen:expect([[
|
|
some short lines |
|
|
of test text |
|
|
{7: }|
|
|
:echo 2 |
|
|
{2:Error detected while processing :} |
|
|
{2:E605: Exception not caught: very error} |
|
|
4 |
|
|
{3:Press ENTER or type command to continue}^ |
|
|
]])
|
|
-- however, message scrolling may cause extra CR prompt
|
|
-- This is consistent with output from async events.
|
|
feed('<cr>')
|
|
screen:expect([[
|
|
^some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
|
|
|
]])
|
|
eq('n', eval('mode(1)'))
|
|
|
|
feed(':let g:x = 3<F4>')
|
|
screen:expect([[
|
|
some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
:let g:x = 3^ |
|
|
]])
|
|
feed('+2<cr>')
|
|
-- cursor was moved in the background
|
|
screen:expect([[
|
|
some short ^lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
:let g:x = 3+2 |
|
|
]])
|
|
eq(5, eval('g:x'))
|
|
|
|
feed(':let g:y = 7<F8>')
|
|
screen:expect([[
|
|
some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
:let g:y = 7^ |
|
|
]])
|
|
eq('c', eval('mode(1)'))
|
|
feed('+2<cr>')
|
|
-- startinsert takes effect after leaving cmdline mode
|
|
screen:expect([[
|
|
some short ^lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{4:-- INSERT --} |
|
|
]])
|
|
eq('i', eval('mode(1)'))
|
|
eq(9, eval('g:y'))
|
|
|
|
end)
|
|
|
|
it("doesn't crash when invoking cmdline mode recursively #8859", function()
|
|
cmdmap('<F2>', 'norm! :foo')
|
|
feed(':bar')
|
|
screen:expect([[
|
|
some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
:bar^ |
|
|
]])
|
|
|
|
feed('<f2>x')
|
|
screen:expect([[
|
|
some short lines |
|
|
of test text |
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
{1:~ }|
|
|
:barx^ |
|
|
]])
|
|
end)
|
|
|
|
it("works with <SID> mappings", function()
|
|
source([[
|
|
map <f2> <Cmd>call <SID>do_it()<Cr>
|
|
function! s:do_it()
|
|
let g:x = 10
|
|
endfunction
|
|
]])
|
|
feed('<f2>')
|
|
eq('', eval('v:errmsg'))
|
|
eq(10, eval('g:x'))
|
|
end)
|
|
end)
|
|
|