neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

cmd_map_spec.lua (29069B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 local Screen = require('test.functional.ui.screen')
      4 
      5 local clear = n.clear
      6 local feed = n.feed
      7 local eq = t.eq
      8 local expect = n.expect
      9 local eval = n.eval
     10 local fn = n.fn
     11 local insert = n.insert
     12 local write_file = t.write_file
     13 local exc_exec = n.exc_exec
     14 local command = n.command
     15 
     16 describe('mappings with <Cmd>', function()
     17  local screen
     18  local tmpfile = 'X_ex_cmds_cmd_map'
     19 
     20  local function cmdmap(lhs, rhs)
     21    command('noremap ' .. lhs .. ' <Cmd>' .. rhs .. '<cr>')
     22    command('noremap! ' .. lhs .. ' <Cmd>' .. rhs .. '<cr>')
     23  end
     24 
     25  before_each(function()
     26    clear()
     27    screen = Screen.new(65, 8)
     28    screen:set_default_attr_ids({
     29      [1] = { bold = true, foreground = Screen.colors.Blue1 },
     30      [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
     31      [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
     32      [4] = { bold = true },
     33      [5] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
     34      [6] = { foreground = Screen.colors.Blue1 },
     35      [7] = { bold = true, reverse = true },
     36      [8] = { background = Screen.colors.WebGray },
     37      [9] = { background = Screen.colors.LightMagenta },
     38      [10] = { foreground = Screen.colors.Red },
     39    })
     40 
     41    cmdmap('<F3>', 'let m = mode(1)')
     42    cmdmap('<F4>', 'normal! ww')
     43    cmdmap('<F5>', 'normal! "ay')
     44    cmdmap('<F6>', 'throw "very error"')
     45    command([[
     46        function! TextObj()
     47            if mode() !=# "v"
     48                normal! v
     49            end
     50            call cursor(1,3)
     51            normal! o
     52            call cursor(2,4)
     53        endfunction]])
     54    cmdmap('<F7>', 'call TextObj()')
     55    insert([[
     56        some short lines
     57        of test text]])
     58    feed('gg')
     59    cmdmap('<F8>', 'startinsert')
     60    cmdmap('<F9>', 'stopinsert')
     61    command('abbr foo <Cmd>let g:y = 17<cr>bar')
     62  end)
     63 
     64  after_each(function()
     65    os.remove(tmpfile)
     66  end)
     67 
     68  it('can be displayed', function()
     69    command('map <F3>')
     70    screen:expect([[
     71      ^some short lines                                                 |
     72      of test text                                                     |
     73      {1:~                                                                }|*5
     74         {6:<F3>}        {6:*} {6:<Cmd>}let m = mode(1){6:<CR>}                        |
     75    ]])
     76  end)
     77 
     78  it('handles invalid mappings', function()
     79    command('let x = 0')
     80    command('noremap <F3> <Cmd><Cmd>let x = 1<cr>')
     81    feed('<F3>')
     82    screen:expect([[
     83      ^some short lines                                                 |
     84      of test text                                                     |
     85      {1:~                                                                }|*5
     86      {2:E1136: <Cmd> mapping must end with <CR> before second <Cmd>}      |
     87    ]])
     88 
     89    command('noremap <F3> <Cmd>let x = 3')
     90    feed('<F3>')
     91    screen:expect([[
     92      ^some short lines                                                 |
     93      of test text                                                     |
     94      {1:~                                                                }|*5
     95      {2:E1255: <Cmd> mapping must end with <CR>}                          |
     96    ]])
     97    eq(0, eval('x'))
     98  end)
     99 
    100  it('allows special keys and modifiers', function()
    101    command('noremap <F3> <Cmd>normal! <Down><CR>')
    102    feed('<F3>')
    103    screen:expect([[
    104      some short lines                                                 |
    105      ^of test text                                                     |
    106      {1:~                                                                }|*5
    107                                                                       |
    108    ]])
    109 
    110    command('noremap <F3> <Cmd>normal! <C-Right><CR>')
    111    feed('<F3>')
    112    screen:expect([[
    113      some short lines                                                 |
    114      of ^test text                                                     |
    115      {1:~                                                                }|*5
    116                                                                       |
    117    ]])
    118  end)
    119 
    120  it('handles string containing K_SPECIAL (0x80) bytes correctly', function()
    121    command([[noremap <F3> <Cmd>let g:str = 'foo…bar'<CR>]])
    122    feed('<F3>')
    123    eq('foo…bar', eval('g:str'))
    124    local str = eval([["foo\<D-…>bar"]])
    125    command([[noremap <F3> <Cmd>let g:str = ']] .. str .. [['<CR>]])
    126    feed('<F3>')
    127    eq(str, eval('g:str'))
    128    command([[noremap <F3> <Cmd>let g:str = 'foo<D-…>bar'<CR>]])
    129    feed('<F3>')
    130    eq(str, eval('g:str'))
    131  end)
    132 
    133  it('works in various modes and sees correct `mode()` value', function()
    134    -- normal mode
    135    feed('<F3>')
    136    eq('n', eval('m'))
    137 
    138    -- visual mode
    139    feed('v<F3>')
    140    eq('v', eval('m'))
    141    -- didn't leave visual mode
    142    eq('v', eval('mode(1)'))
    143    feed('<esc>')
    144    eq('n', eval('mode(1)'))
    145 
    146    -- visual mapping in select mode
    147    feed('gh<F3>')
    148    eq('v', eval('m'))
    149    -- didn't leave select mode
    150    eq('s', eval('mode(1)'))
    151    feed('<esc>')
    152    eq('n', eval('mode(1)'))
    153 
    154    -- select mode mapping
    155    command('snoremap <F3> <Cmd>let m = mode(1)<cr>')
    156    feed('gh<F3>')
    157    eq('s', eval('m'))
    158    -- didn't leave select mode
    159    eq('s', eval('mode(1)'))
    160    feed('<esc>')
    161    eq('n', eval('mode(1)'))
    162 
    163    -- operator-pending mode
    164    feed('d<F3>')
    165    eq('no', eval('m'))
    166    -- did leave operator-pending mode
    167    eq('n', eval('mode(1)'))
    168 
    169    --insert mode
    170    feed('i<F3>')
    171    eq('i', eval('m'))
    172    eq('i', eval('mode(1)'))
    173 
    174    -- replace mode
    175    feed('<Ins><F3>')
    176    eq('R', eval('m'))
    177    eq('R', eval('mode(1)'))
    178    feed('<esc>')
    179    eq('n', eval('mode(1)'))
    180 
    181    -- virtual replace mode
    182    feed('gR<F3>')
    183    eq('Rv', eval('m'))
    184    eq('Rv', eval('mode(1)'))
    185    feed('<esc>')
    186    eq('n', eval('mode(1)'))
    187 
    188    -- langmap works, but is not distinguished in mode(1)
    189    feed(':set iminsert=1<cr>i<F3>')
    190    eq('i', eval('m'))
    191    eq('i', eval('mode(1)'))
    192    feed('<esc>')
    193    eq('n', eval('mode(1)'))
    194 
    195    feed(':<F3>')
    196    eq('c', eval('m'))
    197    eq('c', eval('mode(1)'))
    198    feed('<esc>')
    199    eq('n', eval('mode(1)'))
    200 
    201    -- terminal mode
    202    command('tnoremap <F3> <Cmd>let m = mode(1)<cr>')
    203    command('split | terminal')
    204    feed('i')
    205    eq('t', eval('mode(1)'))
    206    feed('<F3>')
    207    eq('t', eval('m'))
    208    eq('t', eval('mode(1)'))
    209  end)
    210 
    211  it('works in normal mode', function()
    212    cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
    213 
    214    -- check v:count and v:register works
    215    feed('<F2>')
    216    eq({ 'n', 0, '"' }, eval('s'))
    217    feed('7<F2>')
    218    eq({ 'n', 7, '"' }, eval('s'))
    219    feed('"e<F2>')
    220    eq({ 'n', 0, 'e' }, eval('s'))
    221    feed('5"k<F2>')
    222    eq({ 'n', 5, 'k' }, eval('s'))
    223    feed('"+2<F2>')
    224    eq({ 'n', 2, '+' }, eval('s'))
    225 
    226    -- text object enters visual mode
    227    feed('<F7>')
    228    screen:expect([[
    229      so{5:me short lines}                                                 |
    230      {5:of }^test text                                                     |
    231      {1:~                                                                }|*5
    232      {4:-- VISUAL --}                                                     |
    233    ]])
    234    feed('<esc>')
    235 
    236    -- startinsert
    237    feed('<F8>')
    238    eq('i', eval('mode(1)'))
    239    feed('<esc>')
    240 
    241    eq('n', eval('mode(1)'))
    242    cmdmap(',a', 'call feedkeys("aalpha") \\| let g:a = getline(2)')
    243    cmdmap(',b', 'call feedkeys("abeta", "x") \\| let g:b = getline(2)')
    244 
    245    feed(',a<F3>')
    246    screen:expect([[
    247      some short lines                                                 |
    248      of alpha^test text                                                |
    249      {1:~                                                                }|*5
    250      {4:-- INSERT --}                                                     |
    251    ]])
    252    -- feedkeys were not executed immediately
    253    eq({ 'n', 'of test text' }, eval('[m,a]'))
    254    eq('i', eval('mode(1)'))
    255    feed('<esc>')
    256 
    257    feed(',b<F3>')
    258    screen:expect([[
    259      some short lines                                                 |
    260      of alphabet^atest text                                            |
    261      {1:~                                                                }|*5
    262                                                                       |
    263    ]])
    264    -- feedkeys(..., 'x') was executed immediately, but insert mode gets aborted
    265    eq({ 'n', 'of alphabetatest text' }, eval('[m,b]'))
    266    eq('n', eval('mode(1)'))
    267  end)
    268 
    269  it('works in :normal command', function()
    270    command('noremap ,x <Cmd>call append(1, "xx")\\| call append(1, "aa")<cr>')
    271    command('noremap ,f <Cmd>nosuchcommand<cr>')
    272    command('noremap ,e <Cmd>throw "very error"\\| call append(1, "yy")<cr>')
    273    command('noremap ,m <Cmd>echoerr "The message."\\| call append(1, "zz")<cr>')
    274    command(
    275      'noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>'
    276    )
    277 
    278    feed(':normal ,x<cr>')
    279    screen:expect([[
    280      ^some short lines                                                 |
    281      aa                                                               |
    282      xx                                                               |
    283      of test text                                                     |
    284      {1:~                                                                }|*3
    285      :normal ,x                                                       |
    286    ]])
    287 
    288    eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec('normal ,f'))
    289    eq('very error', exc_exec('normal ,e'))
    290    eq('Vim(echoerr):The message.', exc_exec('normal ,m'))
    291    feed('w')
    292    screen:expect([[
    293      some ^short lines                                                 |
    294      aa                                                               |
    295      xx                                                               |
    296      of test text                                                     |
    297      {1:~                                                                }|*3
    298      :normal ,x                                                       |
    299    ]])
    300 
    301    command(':%d')
    302    eq('Vim(echoerr):Err', exc_exec('normal ,w'))
    303    screen:expect([[
    304      ^                                                                 |
    305      0                                                                |
    306      {1:~                                                                }|*5
    307      --No lines in buffer--                                           |
    308    ]])
    309 
    310    command(':%d')
    311    feed(':normal ,w<cr>')
    312    screen:expect([[
    313      ^                                                                 |
    314      4                                                                |
    315      3                                                                |
    316      2                                                                |
    317      1                                                                |
    318      0                                                                |
    319      {1:~                                                                }|
    320      {2:Err}                                                              |
    321    ]])
    322  end)
    323 
    324  it('works in visual mode', function()
    325    -- can extend visual mode
    326    feed('v<F4>')
    327    screen:expect([[
    328      {5:some short }^lines                                                 |
    329      of test text                                                     |
    330      {1:~                                                                }|*5
    331      {4:-- VISUAL --}                                                     |
    332    ]])
    333    eq('v', fn.mode(1))
    334 
    335    -- can invoke operator, ending visual mode
    336    feed('<F5>')
    337    eq('n', fn.mode(1))
    338    eq({ 'some short l' }, fn.getreg('a', 1, 1))
    339 
    340    -- error doesn't interrupt visual mode
    341    feed('ggvw<F6>')
    342    screen:expect([[
    343      {5:some }short lines                                                 |
    344      of test text                                                     |
    345      {1:~                                                                }|*2
    346      {7:                                                                 }|
    347      {2:Error in :}                                                       |
    348      {2:E605: Exception not caught: very error}                           |
    349      {3:Press ENTER or type command to continue}^                          |
    350    ]])
    351    feed('<cr>')
    352    eq('E605: Exception not caught: very error', eval('v:errmsg'))
    353    -- still in visual mode, <cr> was consumed by the error prompt
    354    screen:expect([[
    355      {5:some }^short lines                                                 |
    356      of test text                                                     |
    357      {1:~                                                                }|*5
    358      {4:-- VISUAL --}                                                     |
    359    ]])
    360    eq('v', fn.mode(1))
    361    feed('<F7>')
    362    screen:expect([[
    363      so{5:me short lines}                                                 |
    364      {5:of }^test text                                                     |
    365      {1:~                                                                }|*5
    366      {4:-- VISUAL --}                                                     |
    367    ]])
    368    eq('v', fn.mode(1))
    369 
    370    -- startinsert gives "-- (insert) VISUAL --" mode
    371    feed('<F8>')
    372    screen:expect([[
    373      so{5:me short lines}                                                 |
    374      {5:of }^test text                                                     |
    375      {1:~                                                                }|*5
    376      {4:-- (insert) VISUAL --}                                            |
    377    ]])
    378    eq('v', eval('mode(1)'))
    379    feed('<esc>')
    380    eq('i', eval('mode(1)'))
    381  end)
    382 
    383  it('works in select mode', function()
    384    command('snoremap <F1> <cmd>throw "very error"<cr>')
    385    command('snoremap <F2> <cmd>normal! <c-g>"by<cr>')
    386    -- can extend select mode
    387    feed('gh<F4>')
    388    screen:expect([[
    389      {5:some short }^lines                                                 |
    390      of test text                                                     |
    391      {1:~                                                                }|*5
    392      {4:-- SELECT --}                                                     |
    393    ]])
    394    eq('s', fn.mode(1))
    395 
    396    -- visual mapping in select mode restart select mode after operator
    397    feed('<F5>')
    398    eq('s', fn.mode(1))
    399    eq({ 'some short l' }, fn.getreg('a', 1, 1))
    400 
    401    -- select mode mapping works, and does not restart select mode
    402    feed('<F2>')
    403    eq('n', fn.mode(1))
    404    eq({ 'some short l' }, fn.getreg('b', 1, 1))
    405 
    406    -- error doesn't interrupt temporary visual mode
    407    feed('<esc>ggvw<c-g><F6>')
    408    screen:expect([[
    409      {5:some }short lines                                                 |
    410      of test text                                                     |
    411      {1:~                                                                }|*2
    412      {7:                                                                 }|
    413      {2:Error in :}                                                       |
    414      {2:E605: Exception not caught: very error}                           |
    415      {3:Press ENTER or type command to continue}^                          |
    416    ]])
    417    feed('<cr>')
    418    eq('E605: Exception not caught: very error', eval('v:errmsg'))
    419    -- still in visual mode, <cr> was consumed by the error prompt
    420    screen:expect([[
    421      {5:some }^short lines                                                 |
    422      of test text                                                     |
    423      {1:~                                                                }|*5
    424      {4:-- VISUAL --}                                                     |
    425    ]])
    426    -- quirk: restoration of select mode is not performed
    427    eq('v', fn.mode(1))
    428 
    429    -- error doesn't interrupt select mode
    430    feed('<esc>ggvw<c-g><F1>')
    431    screen:expect([[
    432      {5:some }short lines                                                 |
    433      of test text                                                     |
    434      {1:~                                                                }|*2
    435      {7:                                                                 }|
    436      {2:Error in :}                                                       |
    437      {2:E605: Exception not caught: very error}                           |
    438      {3:Press ENTER or type command to continue}^                          |
    439    ]])
    440    feed('<cr>')
    441    eq('E605: Exception not caught: very error', eval('v:errmsg'))
    442    -- still in select mode, <cr> was consumed by the error prompt
    443    screen:expect([[
    444      {5:some }^short lines                                                 |
    445      of test text                                                     |
    446      {1:~                                                                }|*5
    447      {4:-- SELECT --}                                                     |
    448    ]])
    449    -- quirk: restoration of select mode is not performed
    450    eq('s', fn.mode(1))
    451 
    452    feed('<F7>')
    453    screen:expect([[
    454      so{5:me short lines}                                                 |
    455      {5:of }^test text                                                     |
    456      {1:~                                                                }|*5
    457      {4:-- SELECT --}                                                     |
    458    ]])
    459    eq('s', fn.mode(1))
    460 
    461    -- startinsert gives "-- SELECT (insert) --" mode
    462    feed('<F8>')
    463    screen:expect([[
    464      so{5:me short lines}                                                 |
    465      {5:of }^test text                                                     |
    466      {1:~                                                                }|*5
    467      {4:-- (insert) SELECT --}                                            |
    468    ]])
    469    eq('s', eval('mode(1)'))
    470    feed('<esc>')
    471    eq('i', eval('mode(1)'))
    472  end)
    473 
    474  it('works in operator-pending mode', function()
    475    feed('d<F4>')
    476    expect([[
    477        lines
    478        of test text]])
    479    eq({ 'some short ' }, fn.getreg('"', 1, 1))
    480    feed('.')
    481    expect([[
    482        test text]])
    483    eq({ 'lines', 'of ' }, fn.getreg('"', 1, 1))
    484    feed('uu')
    485    expect([[
    486        some short lines
    487        of test text]])
    488 
    489    -- error aborts operator-pending, operator not performed
    490    feed('d<F6>')
    491    screen:expect([[
    492      some short lines                                                 |
    493      of test text                                                     |
    494      {1:~                                                                }|*2
    495      {7:                                                                 }|
    496      {2:Error in :}                                                       |
    497      {2:E605: Exception not caught: very error}                           |
    498      {3:Press ENTER or type command to continue}^                          |
    499    ]])
    500    feed('<cr>')
    501    eq('E605: Exception not caught: very error', eval('v:errmsg'))
    502    expect([[
    503        some short lines
    504        of test text]])
    505 
    506    feed('"bd<F7>')
    507    expect([[
    508        soest text]])
    509    eq({ 'me short lines', 'of t' }, fn.getreg('b', 1, 1))
    510 
    511    -- startinsert aborts operator
    512    feed('d<F8>')
    513    eq('i', eval('mode(1)'))
    514    expect([[
    515        soest text]])
    516  end)
    517 
    518  it('works in insert mode', function()
    519    -- works the same as <c-o>w<c-o>w
    520    feed('iindeed <F4>little ')
    521    screen:expect([[
    522      indeed some short little ^lines                                   |
    523      of test text                                                     |
    524      {1:~                                                                }|*5
    525      {4:-- INSERT --}                                                     |
    526    ]])
    527 
    528    feed('<F6>')
    529    screen:expect([[
    530      indeed some short little lines                                   |
    531      of test text                                                     |
    532      {1:~                                                                }|*2
    533      {7:                                                                 }|
    534      {2:Error in :}                                                       |
    535      {2:E605: Exception not caught: very error}                           |
    536      {3:Press ENTER or type command to continue}^                          |
    537    ]])
    538 
    539    feed('<cr>')
    540    eq('E605: Exception not caught: very error', eval('v:errmsg'))
    541    -- still in insert
    542    screen:expect([[
    543      indeed some short little ^lines                                   |
    544      of test text                                                     |
    545      {1:~                                                                }|*5
    546      {4:-- INSERT --}                                                     |
    547    ]])
    548    eq('i', eval('mode(1)'))
    549 
    550    -- When entering visual mode from InsertEnter autocmd, an async event, or
    551    -- a <cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode. If a
    552    -- vim patch decides to disable this mode, this test is expected to fail.
    553    feed('<F7>stuff ')
    554    screen:expect([[
    555      in{5:deed some short little lines}                                   |
    556      {5:of stuff }^test text                                               |
    557      {1:~                                                                }|*5
    558      {4:-- INSERT VISUAL --}                                              |
    559    ]])
    560    expect([[
    561      indeed some short little lines
    562      of stuff test text]])
    563 
    564    feed('<F5>')
    565    eq({ 'deed some short little lines', 'of stuff t' }, fn.getreg('a', 1, 1))
    566 
    567    -- still in insert
    568    screen:expect([[
    569      in^deed some short little lines                                   |
    570      of stuff test text                                               |
    571      {1:~                                                                }|*5
    572      {4:-- INSERT --}                                                     |
    573    ]])
    574    eq('i', eval('mode(1)'))
    575 
    576    -- also works as part of abbreviation
    577    feed(' foo ')
    578    screen:expect([[
    579      in bar ^deed some short little lines                              |
    580      of stuff test text                                               |
    581      {1:~                                                                }|*5
    582      {4:-- INSERT --}                                                     |
    583    ]])
    584    eq(17, eval('g:y'))
    585 
    586    -- :startinsert does nothing
    587    feed('<F8>')
    588    eq('i', eval('mode(1)'))
    589 
    590    -- :stopinsert works
    591    feed('<F9>')
    592    eq('n', eval('mode(1)'))
    593  end)
    594 
    595  it('works in insert completion (Ctrl-X) mode', function()
    596    feed('os<c-x><c-n>')
    597    screen:expect([[
    598      some short lines                                                 |
    599      some^                                                             |
    600      {8:some           }                                                  |
    601      {9:short          }{1:                                                  }|
    602      {1:~                                                                }|*3
    603      {4:-- Keyword Local completion (^N^P) }{3:match 1 of 2}                  |
    604    ]])
    605 
    606    feed('<f3>')
    607    eq('ic', eval('m'))
    608 
    609    -- ensure a redraw, this would have moved the cursor
    610    -- instead if CTRL-X mode was left.
    611    feed('<up>')
    612    screen:expect([[
    613      some short lines                                                 |
    614      some^                                                             |
    615      {9:some           }                                                  |
    616      {9:short          }{1:                                                  }|
    617      {1:~                                                                }|*3
    618      {4:-- Keyword Local completion (^N^P) }{10:Back at original}              |
    619    ]])
    620  end)
    621 
    622  it('works in cmdline mode', function()
    623    feed(':text<F3>')
    624    eq('c', eval('m'))
    625    -- didn't leave cmdline mode
    626    eq('c', eval('mode(1)'))
    627    feed('<cr>')
    628    eq('n', eval('mode(1)'))
    629    screen:expect([[
    630      ^some short lines                                                 |
    631      of test text                                                     |
    632      {1:~                                                                }|*5
    633      {2:E492: Not an editor command: text}                                |
    634    ]])
    635 
    636    feed(':echo 2<F6>')
    637    screen:expect([[
    638      some short lines                                                 |
    639      of test text                                                     |
    640      {1:~                                                                }|
    641      {7:                                                                 }|
    642      :echo 2                                                          |
    643      {2:Error in :}                                                       |
    644      {2:E605: Exception not caught: very error}                           |
    645      :echo 2^                                                          |
    646    ]])
    647    eq('E605: Exception not caught: very error', eval('v:errmsg'))
    648    -- didn't leave cmdline mode
    649    eq('c', eval('mode(1)'))
    650    feed('+2<cr>')
    651    screen:expect([[
    652      some short lines                                                 |
    653      of test text                                                     |
    654      {7:                                                                 }|
    655      :echo 2                                                          |
    656      {2:Error in :}                                                       |
    657      {2:E605: Exception not caught: very error}                           |
    658      4                                                                |
    659      {3:Press ENTER or type command to continue}^                          |
    660    ]])
    661    -- however, message scrolling may cause extra CR prompt
    662    -- This is consistent with output from async events.
    663    feed('<cr>')
    664    screen:expect([[
    665      ^some short lines                                                 |
    666      of test text                                                     |
    667      {1:~                                                                }|*5
    668                                                                       |
    669    ]])
    670    eq('n', eval('mode(1)'))
    671 
    672    feed(':let g:x = 3<F4>')
    673    screen:expect([[
    674      some short lines                                                 |
    675      of test text                                                     |
    676      {1:~                                                                }|*5
    677      :let g:x = 3^                                                     |
    678    ]])
    679    feed('+2<cr>')
    680    -- cursor was moved in the background
    681    screen:expect([[
    682      some short ^lines                                                 |
    683      of test text                                                     |
    684      {1:~                                                                }|*5
    685      :let g:x = 3+2                                                   |
    686    ]])
    687    eq(5, eval('g:x'))
    688 
    689    feed(':let g:y = 7<F8>')
    690    screen:expect([[
    691      some short lines                                                 |
    692      of test text                                                     |
    693      {1:~                                                                }|*5
    694      :let g:y = 7^                                                     |
    695    ]])
    696    eq('c', eval('mode(1)'))
    697    feed('+2<cr>')
    698    -- startinsert takes effect after leaving cmdline mode
    699    screen:expect([[
    700      some short ^lines                                                 |
    701      of test text                                                     |
    702      {1:~                                                                }|*5
    703      {4:-- INSERT --}                                                     |
    704    ]])
    705    eq('i', eval('mode(1)'))
    706    eq(9, eval('g:y'))
    707  end)
    708 
    709  it("doesn't crash when invoking cmdline mode recursively #8859", function()
    710    cmdmap('<F2>', 'norm! :foo')
    711    feed(':bar')
    712    screen:expect([[
    713      some short lines                                                 |
    714      of test text                                                     |
    715      {1:~                                                                }|*5
    716      :bar^                                                             |
    717    ]])
    718 
    719    feed('<f2>x')
    720    screen:expect([[
    721      some short lines                                                 |
    722      of test text                                                     |
    723      {1:~                                                                }|*5
    724      :barx^                                                            |
    725    ]])
    726  end)
    727 
    728  it('works with <SID> mappings', function()
    729    command('new!')
    730    write_file(
    731      tmpfile,
    732      [[
    733      map <f2> <Cmd>call <SID>do_it()<Cr>
    734      function! s:do_it()
    735        let g:x = 10
    736      endfunction
    737    ]]
    738    )
    739    command('source ' .. tmpfile)
    740    feed('<f2>')
    741    eq('', eval('v:errmsg'))
    742    eq(10, eval('g:x'))
    743  end)
    744 end)