neovim

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

cmdline_spec.lua (10443B)


      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 command = n.command
      7 local eq = t.eq
      8 local expect = n.expect
      9 local eval = n.eval
     10 local next_msg = n.next_msg
     11 local feed = n.feed
     12 local api = n.api
     13 
     14 describe('cmdline autocommands', function()
     15  local channel
     16  before_each(function()
     17    clear()
     18    channel = api.nvim_get_chan_info(0).id
     19    api.nvim_set_var('channel', channel)
     20    command("autocmd CmdlineEnter * call rpcnotify(g:channel, 'CmdlineEnter', v:event)")
     21    command("autocmd CmdlineLeave * call rpcnotify(g:channel, 'CmdlineLeave', v:event)")
     22    command("autocmd CmdwinEnter * call rpcnotify(g:channel, 'CmdwinEnter', v:event)")
     23    command("autocmd CmdwinLeave * call rpcnotify(g:channel, 'CmdwinLeave', v:event)")
     24  end)
     25 
     26  it('works', function()
     27    feed(':')
     28    eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
     29    feed('redraw<cr>')
     30    eq(
     31      { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
     32      next_msg()
     33    )
     34 
     35    feed(':')
     36    eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
     37 
     38    -- note: feed('bork<c-c>') might not consume 'bork'
     39    -- due to out-of-band interrupt handling
     40    feed('bork<esc>')
     41    eq(
     42      { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = true } } },
     43      next_msg()
     44    )
     45  end)
     46 
     47  it('can abort cmdline', function()
     48    command('autocmd CmdlineLeave * let v:event.abort= len(getcmdline())>15')
     49    feed(":put! ='ok'<cr>")
     50    expect([[
     51      ok
     52      ]])
     53 
     54    feed(":put! ='blah blah'<cr>")
     55    expect([[
     56      ok
     57      ]])
     58  end)
     59 
     60  it('handles errors correctly', function()
     61    clear()
     62    local screen = Screen.new(72, 8)
     63    command("autocmd CmdlineEnter * echoerr 'FAIL'")
     64    command("autocmd CmdlineLeave * echoerr 'very error'")
     65 
     66    feed(':')
     67    screen:expect([[
     68                                                                              |
     69      {1:~                                                                       }|*3
     70      {3:                                                                        }|
     71      :                                                                       |
     72      {9:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL}                    |
     73      :^                                                                       |
     74    ]])
     75 
     76    feed("put ='lorem ipsum'<cr>")
     77    screen:expect([[
     78                                                                              |
     79      {3:                                                                        }|
     80      :                                                                       |
     81      {9:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL}                    |
     82      :put ='lorem ipsum'                                                     |
     83      {9:CmdlineLeave Autocommands for "*": Vim(echoerr):very error}              |
     84                                                                              |
     85      {6:Press ENTER or type command to continue}^                                 |
     86    ]])
     87 
     88    -- cmdline was still executed
     89    feed('<cr>')
     90    screen:expect([[
     91                                                                              |
     92      ^lorem ipsum                                                             |
     93      {1:~                                                                       }|*5
     94                                                                              |
     95    ]])
     96 
     97    command("autocmd CmdlineChanged * echoerr 'change erreor'")
     98 
     99    -- history recall still works
    100    feed(':<c-p>')
    101    screen:expect([[
    102                                                                              |
    103      lorem ipsum                                                             |
    104      {3:                                                                        }|
    105      :                                                                       |
    106      {9:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL}                    |
    107      :put ='lorem ipsum'                                                     |
    108      {9:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor}         |
    109      :put ='lorem ipsum'^                                                     |
    110    ]])
    111 
    112    feed('<left>')
    113    screen:expect([[
    114                                                                              |
    115      lorem ipsum                                                             |
    116      {3:                                                                        }|
    117      :                                                                       |
    118      {9:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL}                    |
    119      :put ='lorem ipsum'                                                     |
    120      {9:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor}         |
    121      :put ='lorem ipsum^'                                                     |
    122    ]])
    123 
    124    -- edit still works
    125    feed('.')
    126    screen:expect([[
    127      {3:                                                                        }|
    128      :                                                                       |
    129      {9:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL}                    |
    130      :put ='lorem ipsum'                                                     |
    131      {9:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor}         |
    132      :put ='lorem ipsum.'                                                    |
    133      {9:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor}         |
    134      :put ='lorem ipsum.^'                                                    |
    135    ]])
    136 
    137    feed('<cr>')
    138    screen:expect([[
    139      :put ='lorem ipsum'                                                     |
    140      {9:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor}         |
    141      :put ='lorem ipsum.'                                                    |
    142      {9:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor}         |
    143      :put ='lorem ipsum.'                                                    |
    144      {9:CmdlineLeave Autocommands for "*": Vim(echoerr):very error}              |
    145                                                                              |
    146      {6:Press ENTER or type command to continue}^                                 |
    147    ]])
    148 
    149    -- cmdline was still executed
    150    feed('<cr>')
    151    screen:expect([[
    152                                                                              |
    153      lorem ipsum                                                             |
    154      ^lorem ipsum.                                                            |
    155      {1:~                                                                       }|*4
    156                                                                              |
    157    ]])
    158  end)
    159 
    160  it('works with nested cmdline', function()
    161    feed(':')
    162    eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
    163    feed('<c-r>=')
    164    eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg())
    165    feed('<c-f>')
    166    eq({ 'notification', 'CmdwinEnter', { {} } }, next_msg())
    167    feed(':')
    168    eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 3 } } }, next_msg())
    169    feed('<c-c>')
    170    eq(
    171      { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 3, abort = true } } },
    172      next_msg()
    173    )
    174    feed('<c-c>')
    175    eq({ 'notification', 'CmdwinLeave', { {} } }, next_msg())
    176    feed('1+2<cr>')
    177    eq(
    178      { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } },
    179      next_msg()
    180    )
    181  end)
    182 
    183  it('no crash with recursive use of v:event #19484', function()
    184    command('autocmd CmdlineEnter * normal :')
    185    feed(':')
    186    eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
    187    feed('<CR>')
    188    eq(
    189      { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
    190      next_msg()
    191    )
    192  end)
    193 
    194  it('supports CmdlineChanged', function()
    195    command(
    196      "autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())"
    197    )
    198    feed(':')
    199    eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
    200    feed('l')
    201    eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'l' } }, next_msg())
    202    feed('e')
    203    eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'le' } }, next_msg())
    204    feed('t')
    205    eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let' } }, next_msg())
    206    feed('<space>')
    207    eq(
    208      { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let ' } },
    209      next_msg()
    210    )
    211    feed('x')
    212    eq(
    213      { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x' } },
    214      next_msg()
    215    )
    216    feed('<space>')
    217    eq(
    218      { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x ' } },
    219      next_msg()
    220    )
    221    feed('=')
    222    eq(
    223      { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x =' } },
    224      next_msg()
    225    )
    226    feed('<space>')
    227    eq(
    228      { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x = ' } },
    229      next_msg()
    230    )
    231    feed('<c-r>=')
    232    eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg())
    233    feed('1')
    234    eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1' } }, next_msg())
    235    feed('+')
    236    eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+' } }, next_msg())
    237    feed('1')
    238    eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+1' } }, next_msg())
    239    feed('<cr>')
    240    eq(
    241      { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } },
    242      next_msg()
    243    )
    244    eq(
    245      { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x = 2' } },
    246      next_msg()
    247    )
    248    feed('<cr>')
    249    eq(
    250      { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
    251      next_msg()
    252    )
    253    eq(2, eval('x'))
    254  end)
    255 end)