neovim

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

cmdline_spec.lua (47418B)


      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, feed = n.clear, n.feed
      6 local source = n.source
      7 local command = n.command
      8 local assert_alive = n.assert_alive
      9 local poke_eventloop = n.poke_eventloop
     10 local exec = n.exec
     11 local eval = n.eval
     12 local eq = t.eq
     13 local is_os = t.is_os
     14 local api = n.api
     15 
     16 local function test_cmdline(linegrid)
     17  local screen
     18 
     19  before_each(function()
     20    clear()
     21    screen = Screen.new(25, 5, { rgb = true, ext_cmdline = true, ext_linegrid = linegrid })
     22  end)
     23 
     24  it('works', function()
     25    feed(':')
     26    screen:expect {
     27      grid = [[
     28        ^                         |
     29        {1:~                        }|*3
     30                                 |
     31      ]],
     32      cmdline = { { firstc = ':', content = { { '' } }, pos = 0 } },
     33    }
     34 
     35    feed('sign')
     36    screen:expect {
     37      grid = [[
     38        ^                         |
     39        {1:~                        }|*3
     40                                 |
     41      ]],
     42      cmdline = { { firstc = ':', content = { { 'sign' } }, pos = 4 } },
     43    }
     44 
     45    feed('<Left>')
     46    screen:expect {
     47      grid = [[
     48        ^                         |
     49        {1:~                        }|*3
     50                                 |
     51      ]],
     52      cmdline = { { firstc = ':', content = { { 'sign' } }, pos = 3 } },
     53    }
     54 
     55    feed('<bs>')
     56    screen:expect {
     57      grid = [[
     58        ^                         |
     59        {1:~                        }|*3
     60                                 |
     61      ]],
     62      cmdline = { { firstc = ':', content = { { 'sin' } }, pos = 2 } },
     63    }
     64 
     65    feed('<Esc>')
     66    screen:expect {
     67      grid = [[
     68        ^                         |
     69        {1:~                        }|*3
     70                                 |
     71      ]],
     72      cmdline = { { abort = true } },
     73    }
     74  end)
     75 
     76  it('works with input()', function()
     77    feed(':call input("input", "default")<cr>')
     78    screen:expect({
     79      grid = [[
     80        ^                         |
     81        {1:~                        }|*3
     82                                 |
     83      ]],
     84      cmdline = { { content = { { 'default' } }, pos = 7, prompt = 'input' } },
     85    })
     86 
     87    feed('<cr>')
     88    screen:expect_unchanged()
     89  end)
     90 
     91  it('works with special chars and nested cmdline', function()
     92    feed(':xx<c-r>')
     93    screen:expect {
     94      grid = [[
     95        ^                         |
     96        {1:~                        }|*3
     97                                 |
     98      ]],
     99      cmdline = { { firstc = ':', content = { { 'xx' } }, pos = 2, special = { '"', true } } },
    100    }
    101 
    102    feed('=')
    103    screen:expect {
    104      grid = [[
    105        ^                         |
    106        {1:~                        }|*3
    107                                 |
    108      ]],
    109      cmdline = {
    110        { firstc = ':', content = { { 'xx' } }, pos = 2, special = { '"', true } },
    111        { firstc = '=', content = { { '' } }, pos = 0 },
    112      },
    113    }
    114 
    115    feed('1+2')
    116 
    117    screen:expect {
    118      grid = [[
    119        ^                         |
    120        {1:~                        }|*3
    121                                 |
    122      ]],
    123      cmdline = {
    124        { firstc = ':', content = { { 'xx' } }, pos = 2, special = { '"', true } },
    125        {
    126          firstc = '=',
    127          content = {
    128            { '1', 26, linegrid and 'NvimNumber' or nil },
    129            { '+', 15, linegrid and 'NvimBinaryPlus' or nil },
    130            { '2', 26, linegrid and 'NvimNumber' or nil },
    131          },
    132          pos = 3,
    133        },
    134      },
    135    }
    136 
    137    -- erase information, so we check if it is retransmitted
    138    command('mode')
    139    screen:expect {
    140      grid = [[
    141        ^                         |
    142        {1:~                        }|*3
    143                                 |
    144      ]],
    145      cmdline = {
    146        { firstc = ':', content = { { 'xx' } }, pos = 2, special = { '"', true } },
    147        {
    148          firstc = '=',
    149          content = {
    150            { '1', 26, linegrid and 'NvimNumber' or nil },
    151            { '+', 15, linegrid and 'NvimBinaryPlus' or nil },
    152            { '2', 26, linegrid and 'NvimNumber' or nil },
    153          },
    154          pos = 3,
    155        },
    156      },
    157      reset = true,
    158    }
    159 
    160    feed('<cr>')
    161    screen:expect {
    162      grid = [[
    163        ^                         |
    164        {1:~                        }|*3
    165                                 |
    166      ]],
    167      cmdline = { { firstc = ':', content = { { 'xx3' } }, pos = 3 } },
    168    }
    169 
    170    feed('<esc>')
    171    screen:expect {
    172      grid = [[
    173        ^                         |
    174        {1:~                        }|*3
    175                                 |
    176      ]],
    177      cmdline = { { abort = true } },
    178    }
    179  end)
    180 
    181  it('works with function definitions', function()
    182    feed(':function Foo()<cr>')
    183    screen:expect {
    184      grid = [[
    185        ^                         |
    186        {1:~                        }|*3
    187                                 |
    188      ]],
    189      cmdline = { { indent = 2, firstc = ':', content = { { '' } }, pos = 0 } },
    190      cmdline_block = { { { 'function Foo()' } } },
    191    }
    192 
    193    feed('line1<cr>')
    194    screen:expect {
    195      grid = [[
    196        ^                         |
    197        {1:~                        }|*3
    198                                 |
    199      ]],
    200      cmdline = { { indent = 2, firstc = ':', content = { { '' } }, pos = 0 } },
    201      cmdline_block = { { { 'function Foo()' } }, { { '  line1' } } },
    202    }
    203 
    204    command('mode')
    205    screen:expect {
    206      grid = [[
    207        ^                         |
    208        {1:~                        }|*3
    209                                 |
    210      ]],
    211      cmdline = { { indent = 2, firstc = ':', content = { { '' } }, pos = 0 } },
    212      cmdline_block = { { { 'function Foo()' } }, { { '  line1' } } },
    213      reset = true,
    214    }
    215 
    216    feed('endfunction<cr>')
    217    screen:expect([[
    218      ^                         |
    219      {1:~                        }|*3
    220                               |
    221    ]])
    222 
    223    -- Try once more, to check buffer is reinitialized. #8007
    224    feed(':function Bar()<cr>')
    225    screen:expect {
    226      grid = [[
    227        ^                         |
    228        {1:~                        }|*3
    229                                 |
    230      ]],
    231      cmdline = { { indent = 2, firstc = ':', content = { { '' } }, pos = 0 } },
    232      cmdline_block = { { { 'function Bar()' } } },
    233    }
    234 
    235    feed('endfunction<cr>')
    236    screen:expect([[
    237      ^                         |
    238      {1:~                        }|*3
    239                               |
    240    ]])
    241  end)
    242 
    243  it('works with cmdline window', function()
    244    feed(':make')
    245    screen:expect {
    246      grid = [[
    247        ^                         |
    248        {1:~                        }|*3
    249                                 |
    250      ]],
    251      cmdline = { { firstc = ':', content = { { 'make' } }, pos = 4 } },
    252    }
    253 
    254    feed('<c-f>')
    255    screen:expect([[
    256                               |
    257      {2:[No Name]                }|
    258      {1::}make^                    |
    259      {3:[Command Line]           }|
    260                               |
    261    ]])
    262 
    263    -- nested cmdline
    264    feed(':yank')
    265    screen:expect {
    266      grid = [[
    267                                 |
    268        {2:[No Name]                }|
    269        {1::}make^                    |
    270        {3:[Command Line]           }|
    271                                 |
    272      ]],
    273      cmdline = {
    274        nil,
    275        { firstc = ':', content = { { 'yank' } }, pos = 4 },
    276      },
    277    }
    278 
    279    command('mode')
    280    screen:expect {
    281      grid = [[
    282                                 |
    283        {2:[No Name]                }|
    284        {1::}make^                    |
    285        {3:[Command Line]           }|
    286                                 |
    287      ]],
    288      cmdline = {
    289        nil,
    290        { firstc = ':', content = { { 'yank' } }, pos = 4 },
    291      },
    292      reset = true,
    293    }
    294 
    295    feed('<c-c>')
    296    screen:expect {
    297      grid = [[
    298                                 |
    299        {2:[No Name]                }|
    300        {1::}make^                    |
    301        {3:[Command Line]           }|
    302                                 |
    303      ]],
    304      cmdline = { [2] = { abort = true } },
    305    }
    306 
    307    feed('<c-c>')
    308    screen:expect {
    309      grid = [[
    310        ^                         |
    311        {2:[No Name]                }|
    312        {1::}make                    |
    313        {3:[Command Line]           }|
    314                                 |
    315      ]],
    316      cmdline = { { firstc = ':', content = { { 'make' } }, pos = 4 } },
    317    }
    318 
    319    command('redraw!')
    320    screen:expect {
    321      grid = [[
    322        ^                         |
    323        {1:~                        }|*3
    324                                 |
    325      ]],
    326      cmdline = { { firstc = ':', content = { { 'make' } }, pos = 4 } },
    327    }
    328  end)
    329 
    330  it('works with inputsecret()', function()
    331    feed(":call inputsecret('secret:')<cr>abc123")
    332    screen:expect {
    333      grid = [[
    334        ^                         |
    335        {1:~                        }|*3
    336                                 |
    337      ]],
    338      cmdline = { { prompt = 'secret:', content = { { '******' } }, pos = 6 } },
    339    }
    340  end)
    341 
    342  it('works with highlighted cmdline', function()
    343    source([[
    344      highlight RBP1 guibg=Red
    345      highlight RBP2 guibg=Yellow
    346      highlight RBP3 guibg=Green
    347      highlight RBP4 guibg=Blue
    348      let g:NUM_LVLS = 4
    349      function RainBowParens(cmdline)
    350        let ret = []
    351        let i = 0
    352        let lvl = 0
    353        while i < len(a:cmdline)
    354          if a:cmdline[i] is# '('
    355            call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)])
    356            let lvl += 1
    357          elseif a:cmdline[i] is# ')'
    358            let lvl -= 1
    359            call add(ret, [i, i + 1, 'RBP' . ((lvl % g:NUM_LVLS) + 1)])
    360          endif
    361          let i += 1
    362        endwhile
    363        return ret
    364      endfunction
    365      map <f5>  :let x = input({'prompt':'>','highlight':'RainBowParens'})<cr>
    366      "map <f5>  :let x = input({'prompt':'>'})<cr>
    367    ]])
    368    feed('<f5>(a(b)a)')
    369    screen:expect {
    370      grid = [[
    371        ^                         |
    372        {1:~                        }|*3
    373                                 |
    374      ]],
    375      cmdline = {
    376        {
    377          prompt = '>',
    378          content = {
    379            { '(', 30, linegrid and 'RBP1' or nil },
    380            { 'a' },
    381            { '(', 10, linegrid and 'RBP2' or nil },
    382            { 'b' },
    383            { ')', 10, linegrid and 'RBP2' or nil },
    384            { 'a' },
    385            { ')', 30, linegrid and 'RBP1' or nil },
    386          },
    387          pos = 7,
    388        },
    389      },
    390    }
    391  end)
    392 
    393  it('works together with ext_wildmenu', function()
    394    command('set wildmode=full')
    395    command('set wildmenu')
    396    screen:set_option('ext_wildmenu', true)
    397    feed(':sign <tab>')
    398 
    399    screen:expect {
    400      grid = [[
    401        ^                         |
    402        {1:~                        }|*3
    403                                 |
    404      ]],
    405      cmdline = { { firstc = ':', content = { { 'sign define' } }, pos = 11 } },
    406      wildmenu_items = { 'define', 'jump', 'list', 'place', 'undefine', 'unplace' },
    407      wildmenu_pos = 0,
    408    }
    409 
    410    feed('<tab>')
    411    screen:expect {
    412      grid = [[
    413        ^                         |
    414        {1:~                        }|*3
    415                                 |
    416      ]],
    417      cmdline = { { firstc = ':', content = { { 'sign jump' } }, pos = 9 } },
    418      wildmenu_items = { 'define', 'jump', 'list', 'place', 'undefine', 'unplace' },
    419      wildmenu_pos = 1,
    420    }
    421 
    422    feed('<left><left>')
    423    screen:expect {
    424      grid = [[
    425        ^                         |
    426        {1:~                        }|*3
    427                                 |
    428      ]],
    429      cmdline = { { firstc = ':', content = { { 'sign ' } }, pos = 5 } },
    430      wildmenu_items = { 'define', 'jump', 'list', 'place', 'undefine', 'unplace' },
    431      wildmenu_pos = -1,
    432    }
    433 
    434    feed('<right>')
    435    screen:expect {
    436      grid = [[
    437        ^                         |
    438        {1:~                        }|*3
    439                                 |
    440      ]],
    441      cmdline = { { firstc = ':', content = { { 'sign define' } }, pos = 11 } },
    442      wildmenu_items = { 'define', 'jump', 'list', 'place', 'undefine', 'unplace' },
    443      wildmenu_pos = 0,
    444    }
    445 
    446    feed('a')
    447    screen:expect {
    448      grid = [[
    449        ^                         |
    450        {1:~                        }|*3
    451                                 |
    452      ]],
    453      cmdline = { { firstc = ':', content = { { 'sign definea' } }, pos = 12 } },
    454    }
    455  end)
    456 
    457  local function test_ext_cmdline_popupmenu()
    458    local expected = {
    459      { 'define', '', '', '' },
    460      { 'jump', '', '', '' },
    461      { 'list', '', '', '' },
    462      { 'place', '', '', '' },
    463      { 'undefine', '', '', '' },
    464      { 'unplace', '', '', '' },
    465    }
    466 
    467    command('set wildmode=full')
    468    command('set wildmenu')
    469    screen:set_option('ext_popupmenu', true)
    470    feed(':sign <tab>')
    471 
    472    screen:expect {
    473      grid = [[
    474        ^                         |
    475        {1:~                        }|*3
    476                                 |
    477      ]],
    478      cmdline = { { firstc = ':', content = { { 'sign define' } }, pos = 11 } },
    479      popupmenu = { items = expected, pos = 0, anchor = { -1, 0, 5 } },
    480    }
    481 
    482    feed('<tab>')
    483    screen:expect {
    484      grid = [[
    485        ^                         |
    486        {1:~                        }|*3
    487                                 |
    488      ]],
    489      cmdline = { { firstc = ':', content = { { 'sign jump' } }, pos = 9 } },
    490      popupmenu = { items = expected, pos = 1, anchor = { -1, 0, 5 } },
    491    }
    492 
    493    feed('<left><left>')
    494    screen:expect {
    495      grid = [[
    496        ^                         |
    497        {1:~                        }|*3
    498                                 |
    499      ]],
    500      cmdline = { { firstc = ':', content = { { 'sign ' } }, pos = 5 } },
    501      popupmenu = { items = expected, pos = -1, anchor = { -1, 0, 5 } },
    502    }
    503 
    504    feed('<right>')
    505    screen:expect {
    506      grid = [[
    507        ^                         |
    508        {1:~                        }|*3
    509                                 |
    510      ]],
    511      cmdline = { { firstc = ':', content = { { 'sign define' } }, pos = 11 } },
    512      popupmenu = { items = expected, pos = 0, anchor = { -1, 0, 5 } },
    513    }
    514 
    515    feed('a')
    516    screen:expect {
    517      grid = [[
    518        ^                         |
    519        {1:~                        }|*3
    520                                 |
    521      ]],
    522      cmdline = { { firstc = ':', content = { { 'sign definea' } }, pos = 12 } },
    523    }
    524    feed('<esc>')
    525 
    526    -- check positioning with multibyte char in pattern
    527    command('e långfile1')
    528    command('sp långfile2')
    529    feed(':b lå<tab>')
    530    screen:expect {
    531      grid = [[
    532        ^                         |
    533        {3:långfile2                }|
    534                                 |
    535        {2:långfile1                }|
    536                                 |
    537      ]],
    538      cmdline = { { content = { { 'b långfile1' } }, firstc = ':', pos = 12 } },
    539      popupmenu = {
    540        anchor = { -1, 0, 2 },
    541        items = { { 'långfile1', '', '', '' }, { 'långfile2', '', '', '' } },
    542        pos = 0,
    543      },
    544    }
    545 
    546    feed('<Esc>')
    547    command('silent %bwipe')
    548 
    549    command('set shellslash')
    550    -- position is correct when expanding environment variable #20348
    551    command('silent cd test/functional/fixtures')
    552    n.fn.setenv('XNDIR', 'wildpum/Xnamedir')
    553    feed(':e $XNDIR/<Tab>')
    554    screen:expect {
    555      grid = [[
    556        ^                         |
    557        {1:~                        }|*3
    558                                 |
    559      ]],
    560      cmdline = { { content = { { 'e wildpum/Xnamedir/XdirA/' } }, firstc = ':', pos = 25 } },
    561      popupmenu = {
    562        anchor = { -1, 0, 19 },
    563        items = { { 'XdirA/', '', '', '' }, { 'XfileA', '', '', '' } },
    564        pos = 0,
    565      },
    566    }
    567 
    568    feed('<Esc>')
    569    command('set wildmode=longest,full')
    570    feed(':sign u<tab>')
    571    screen:expect {
    572      grid = [[
    573        ^                         |
    574        {1:~                        }|*3
    575                                 |
    576      ]],
    577      cmdline = { { content = { { 'sign un' } }, firstc = ':', pos = 7 } },
    578    }
    579 
    580    feed('<tab>')
    581    local s_undefine_unplace_0 = {
    582      grid = [[
    583        ^                         |
    584        {1:~                        }|*3
    585                                 |
    586      ]],
    587      cmdline = { { content = { { 'sign undefine' } }, firstc = ':', pos = 13 } },
    588      popupmenu = {
    589        anchor = { -1, 0, 5 },
    590        items = { { 'undefine', '', '', '' }, { 'unplace', '', '', '' } },
    591        pos = 0,
    592      },
    593    }
    594    screen:expect(s_undefine_unplace_0)
    595 
    596    feed('<Esc>')
    597    screen:expect([[
    598      ^                         |
    599      {1:~                        }|*3
    600                               |
    601    ]])
    602 
    603    feed(':sign un<tab>')
    604    screen:expect(s_undefine_unplace_0)
    605  end
    606 
    607  describe('works together with ext_popupmenu', function()
    608    it('with wildoptions=pum', function()
    609      command('set wildoptions=pum')
    610      test_ext_cmdline_popupmenu()
    611    end)
    612 
    613    it('with wildoptions=', function()
    614      command('set wildoptions=')
    615      test_ext_cmdline_popupmenu()
    616    end)
    617  end)
    618 
    619  it('ext_wildmenu takes precedence over ext_popupmenu', function()
    620    local expected = {
    621      'define',
    622      'jump',
    623      'list',
    624      'place',
    625      'undefine',
    626      'unplace',
    627    }
    628 
    629    command('set wildmode=full')
    630    command('set wildmenu')
    631    screen:set_option('ext_wildmenu', true)
    632    screen:set_option('ext_popupmenu', true)
    633    feed(':sign <tab>')
    634 
    635    screen:expect {
    636      grid = [[
    637        ^                         |
    638        {1:~                        }|*3
    639                                 |
    640      ]],
    641      cmdline = { { firstc = ':', content = { { 'sign define' } }, pos = 11 } },
    642      wildmenu_items = expected,
    643      wildmenu_pos = 0,
    644    }
    645  end)
    646 
    647  it("doesn't send invalid events when aborting mapping #10000", function()
    648    command('set notimeout')
    649    command('cnoremap ab c')
    650 
    651    feed(':xa')
    652    screen:expect {
    653      grid = [[
    654        ^                         |
    655        {1:~                        }|*3
    656                                 |
    657      ]],
    658      cmdline = { { content = { { 'x' } }, firstc = ':', pos = 1, special = { 'a', false } } },
    659    }
    660 
    661    -- This used to send an invalid event where pos where larger than the total
    662    -- length of content. Checked in _handle_cmdline_show.
    663    feed('<esc>')
    664    screen:expect({
    665      grid = [[
    666        ^                         |
    667        {1:~                        }|*3
    668                                 |
    669      ]],
    670      cmdline = { { abort = true } },
    671    })
    672  end)
    673 
    674  it('does not move cursor to curwin #20309', function()
    675    local win = api.nvim_get_current_win()
    676    command('norm icmdlinewin')
    677    command('new')
    678    command('norm icurwin')
    679    feed(':')
    680    api.nvim_win_set_cursor(win, { 1, 7 })
    681    api.nvim__redraw({ win = win, cursor = true })
    682    screen:expect {
    683      grid = [[
    684        curwin                   |
    685        {3:[No Name] [+]            }|
    686        cmdline^win               |
    687        {2:[No Name] [+]            }|
    688                                 |
    689      ]],
    690      cmdline = { { content = { { '' } }, firstc = ':', pos = 0 } },
    691    }
    692  end)
    693 
    694  it('show prompt hl_id', function()
    695    screen:expect([[
    696      ^                         |
    697      {1:~                        }|*3
    698                               |
    699    ]])
    700    feed(':echohl Error | call input("Prompt:")<CR>')
    701    screen:expect({
    702      grid = [[
    703        ^                         |
    704        {1:~                        }|*3
    705                                 |
    706      ]],
    707      cmdline = { { content = { { '' } }, hl = 'Error', pos = 0, prompt = 'Prompt:' } },
    708    })
    709  end)
    710 
    711  it('works with conditionals', function()
    712    screen:expect([[
    713      ^                         |
    714      {1:~                        }|*3
    715                               |
    716    ]])
    717    feed(':if 1<CR>')
    718    screen:expect({
    719      grid = [[
    720        ^                         |
    721        {1:~                        }|*3
    722                                 |
    723      ]],
    724      cmdline = { { content = { { '' } }, firstc = ':', indent = 2, pos = 0 } },
    725      cmdline_block = { { { 'if 1' } } },
    726    })
    727    feed('let x = 1<CR>')
    728    screen:expect({
    729      grid = [[
    730        ^                         |
    731        {1:~                        }|*3
    732                                 |
    733      ]],
    734      cmdline = { { content = { { '' } }, firstc = ':', indent = 2, pos = 0 } },
    735      cmdline_block = { { { 'if 1' } }, { { '  let x = 1' } } },
    736    })
    737    feed('<CR>')
    738    eq('let x = 1', eval('@:'))
    739    screen:expect({
    740      grid = [[
    741        ^                         |
    742        {1:~                        }|*3
    743                                 |
    744      ]],
    745      cmdline = { { content = { { '' } }, firstc = ':', indent = 2, pos = 0 } },
    746      cmdline_block = { { { 'if 1' } }, { { '  let x = 1' } }, { { '  ' } } },
    747    })
    748    feed('call input("foo:")<CR>')
    749    screen:expect({
    750      grid = [[
    751        ^                         |
    752        {1:~                        }|*3
    753                                 |
    754      ]],
    755      cmdline = { { content = { { '' } }, pos = 0, prompt = 'foo:' } },
    756      cmdline_block = {
    757        { { 'if 1' } },
    758        { { '  let x = 1' } },
    759        { { '  ' } },
    760        { { '  call input("foo:")' } },
    761      },
    762    })
    763    feed('bar<CR>')
    764    screen:expect({
    765      grid = [[
    766        ^                         |
    767        {1:~                        }|*3
    768                                 |
    769      ]],
    770      cmdline = { { content = { { '' } }, firstc = ':', indent = 2, pos = 0 } },
    771      cmdline_block = {
    772        { { 'if 1' } },
    773        { { '  let x = 1' } },
    774        { { '  ' } },
    775        { { '  call input("foo:")' } },
    776      },
    777    })
    778    feed('endif')
    779    screen:expect({
    780      grid = [[
    781        ^                         |
    782        {1:~                        }|*3
    783                                 |
    784      ]],
    785      cmdline = { { content = { { 'endif' } }, firstc = ':', indent = 2, pos = 5 } },
    786      cmdline_block = {
    787        { { 'if 1' } },
    788        { { '  let x = 1' } },
    789        { { '  ' } },
    790        { { '  call input("foo:")' } },
    791      },
    792    })
    793    feed('<CR>')
    794    screen:expect([[
    795      ^                         |
    796      {1:~                        }|*3
    797                               |
    798    ]])
    799  end)
    800 
    801  it('works with exmode', function()
    802    feed('gQ')
    803    screen:expect({
    804      grid = [[
    805                                 |
    806        {3:                         }|
    807        Entering Ex mode.  Type "|
    808        visual" to go to Normal m|
    809        ode.^                     |
    810      ]],
    811      cmdline = { { content = { { '' } }, firstc = ':', pos = 0 } },
    812    })
    813    feed('echo "foo"<CR>')
    814    screen:expect({
    815      grid = [[
    816        {3:                         }|
    817        Entering Ex mode.  Type "|
    818        visual" to go to Normal m|
    819        ode.                     |
    820        foo^                      |
    821      ]],
    822      cmdline = { { content = { { '' } }, firstc = ':', pos = 0 } },
    823      cmdline_block = { { { 'echo "foo"' } } },
    824    })
    825    feed('vis<CR>')
    826    screen:expect([[
    827      ^                         |
    828      {1:~                        }|*3
    829                               |
    830    ]])
    831  end)
    832 end
    833 
    834 -- the representation of cmdline and cmdline_block contents changed with ext_linegrid
    835 -- (which uses indexed highlights) so make sure to test both
    836 describe('ui/ext_cmdline', function()
    837  test_cmdline(true)
    838 end)
    839 describe('ui/ext_cmdline (legacy highlights)', function()
    840  test_cmdline(false)
    841 end)
    842 
    843 describe('cmdline redraw', function()
    844  local screen
    845  before_each(function()
    846    clear()
    847    screen = Screen.new(25, 5, { rgb = true })
    848  end)
    849 
    850  it('with timer', function()
    851    feed(':012345678901234567890123456789')
    852    screen:expect([[
    853                               |
    854      {1:~                        }|
    855      {3:                         }|
    856      :012345678901234567890123|
    857      456789^                   |
    858    ]])
    859    command('call timer_start(0, {-> 1})')
    860    screen:expect_unchanged()
    861  end)
    862 
    863  it('with <Cmd>', function()
    864    if is_os('bsd') then
    865      pending('FIXME #10804')
    866    end
    867    command('cmap a <Cmd>call sin(0)<CR>') -- no-op
    868    feed(':012345678901234567890123456789')
    869    screen:expect([[
    870                               |
    871      {1:~                        }|
    872      {3:                         }|
    873      :012345678901234567890123|
    874      456789^                   |
    875    ]])
    876    feed('a')
    877    screen:expect_unchanged()
    878  end)
    879 
    880  it('after pressing Ctrl-C in cmdwin in Visual mode #18967', function()
    881    screen:try_resize(40, 10)
    882    command('set cmdwinheight=3')
    883    feed('q:iabc<Esc>vhh')
    884    screen:expect([[
    885                                              |
    886      {1:~                                       }|*3
    887      {2:[No Name]                               }|
    888      {1::}^a{17:bc}                                    |
    889      {1:~                                       }|*2
    890      {3:[Command Line]                          }|
    891      {5:-- VISUAL --}                            |
    892    ]])
    893    feed('<C-C>')
    894    screen:expect([[
    895                                              |
    896      {1:~                                       }|*3
    897      {2:[No Name]                               }|
    898      {1::}a{17:bc}                                    |
    899      {1:~                                       }|*2
    900      {3:[Command Line]                          }|
    901      :^abc                                    |
    902    ]])
    903  end)
    904 
    905  it('with rightleftcmd', function()
    906    command('set rightleft rightleftcmd=search shortmess+=s')
    907    api.nvim_buf_set_lines(0, 0, -1, true, { "let's rock!" })
    908    screen:expect([[
    909                    !kcor s'te^l|
    910      {1:                        ~}|*3
    911                               |
    912    ]])
    913 
    914    feed '/'
    915    screen:expect([[
    916                    !kcor s'tel|
    917      {1:                        ~}|*3
    918                             ^ /|
    919    ]])
    920 
    921    feed "let's"
    922    -- note: cursor looks off but looks alright in real use
    923    -- when rendered as a block so it touches the end of the text
    924    screen:expect([[
    925                    !kcor {2:s'tel}|
    926      {1:                        ~}|*3
    927                        ^ s'tel/|
    928    ]])
    929 
    930    -- cursor movement
    931    feed '<space>'
    932    screen:expect([[
    933                    !kcor{2: s'tel}|
    934      {1:                        ~}|*3
    935                       ^  s'tel/|
    936    ]])
    937 
    938    feed 'rock'
    939    screen:expect([[
    940                    !{2:kcor s'tel}|
    941      {1:                        ~}|*3
    942                   ^ kcor s'tel/|
    943    ]])
    944 
    945    feed '<right>'
    946    screen:expect([[
    947                    !{2:kcor s'tel}|
    948      {1:                        ~}|*3
    949                    ^kcor s'tel/|
    950    ]])
    951 
    952    feed '<left>'
    953    screen:expect([[
    954                    !{2:kcor s'tel}|
    955      {1:                        ~}|*3
    956                   ^ kcor s'tel/|
    957    ]])
    958 
    959    feed '<cr>'
    960    screen:expect([[
    961                    !{10:kcor s'te^l}|
    962      {1:                        ~}|*3
    963      kcor s'tel/              |
    964    ]])
    965  end)
    966 
    967  it('prompt with silent mapping and screen update', function()
    968    command([[nmap <silent> T :call confirm("Save changes?", "&Yes\n&No\n&Cancel")<CR>]])
    969    feed('T')
    970    screen:expect([[
    971                               |
    972      {3:                         }|
    973                               |
    974      {6:Save changes?}            |
    975      {6:[Y]es, (N)o, (C)ancel: }^  |
    976    ]])
    977    command('call setline(1, "foo") | redraw')
    978    screen:expect([[
    979      foo                      |
    980      {3:                         }|
    981                               |
    982      {6:Save changes?}            |
    983      {6:[Y]es, (N)o, (C)ancel: }^  |
    984    ]])
    985    feed('Y')
    986    screen:expect([[
    987      ^foo                      |
    988      {1:~                        }|*3
    989                               |
    990    ]])
    991    screen:try_resize(75, screen._height)
    992    feed(':call inputlist(["foo", "bar"])<CR>')
    993    screen:expect([[
    994      foo                                                                        |
    995      {3:                                                                           }|
    996      foo                                                                        |
    997      bar                                                                        |
    998      Type number and <Enter> or click with the mouse (q or empty cancels): ^     |
    999    ]])
   1000    command('redraw')
   1001    screen:expect_unchanged()
   1002 
   1003    command('set keymap=dvorak')
   1004    feed('<C-^>')
   1005    command('redraw')
   1006    screen:expect_unchanged()
   1007 
   1008    feed('<C-^>')
   1009    command('set keymap&')
   1010    command('redraw')
   1011    screen:expect_unchanged()
   1012  end)
   1013 
   1014  it('substitute confirm prompt does not scroll', function()
   1015    screen:try_resize(75, screen._height)
   1016    command('call setline(1, "foo")')
   1017    command('set report=0')
   1018    feed(':%s/foo/bar/c<CR>')
   1019    screen:expect([[
   1020      {2:foo}                                                                        |
   1021      {1:~                                                                          }|*3
   1022      {6:replace with bar? (y)es/(n)o/(a)ll/(q)uit/(l)ast/scroll up(^E)/down(^Y)}^    |
   1023    ]])
   1024    feed('y')
   1025    screen:expect([[
   1026      ^bar                                                                        |
   1027      {1:~                                                                          }|*3
   1028      1 substitution on 1 line                                                   |
   1029    ]])
   1030  end)
   1031 end)
   1032 
   1033 describe('statusline is redrawn on entering cmdline', function()
   1034  local screen
   1035 
   1036  before_each(function()
   1037    clear()
   1038    screen = Screen.new(25, 5)
   1039    command('set laststatus=2')
   1040  end)
   1041 
   1042  it('from normal mode', function()
   1043    command('set statusline=%{mode()}')
   1044    screen:expect([[
   1045      ^                         |
   1046      {1:~                        }|*2
   1047      {3:n                        }|
   1048                               |
   1049    ]])
   1050 
   1051    feed(':')
   1052    screen:expect([[
   1053                               |
   1054      {1:~                        }|*2
   1055      {3:c                        }|
   1056      :^                        |
   1057    ]])
   1058  end)
   1059 
   1060  it('from normal mode when : is mapped', function()
   1061    command('set statusline=%{mode()}')
   1062    command('nnoremap ; :')
   1063 
   1064    screen:expect([[
   1065      ^                         |
   1066      {1:~                        }|*2
   1067      {3:n                        }|
   1068                               |
   1069    ]])
   1070 
   1071    feed(';')
   1072    screen:expect([[
   1073                               |
   1074      {1:~                        }|*2
   1075      {3:c                        }|
   1076      :^                        |
   1077    ]])
   1078  end)
   1079 
   1080  it('with scrolled messages', function()
   1081    screen:try_resize(35, 14)
   1082    exec([[
   1083      let g:count = 0
   1084      autocmd CmdlineEnter * let g:count += 1
   1085      split
   1086      resize 1
   1087      setlocal statusline=%{mode()}%{g:count}
   1088      setlocal winbar=%{mode()}%{g:count}
   1089    ]])
   1090    feed(':echoerr doesnotexist<cr>')
   1091    screen:expect([[
   1092      {5:c1                                 }|
   1093                                         |
   1094      {3:c1                                 }|
   1095                                         |
   1096      {1:~                                  }|*5
   1097      {3:                                   }|
   1098      {9:E121: Undefined variable: doesnotex}|
   1099      {9:ist}                                |
   1100      {6:Press ENTER or type command to cont}|
   1101      {6:inue}^                               |
   1102    ]])
   1103    feed(':echoerr doesnotexist<cr>')
   1104    screen:expect([[
   1105      {5:c2                                 }|
   1106                                         |
   1107      {3:c2                                 }|
   1108                                         |
   1109      {1:~                                  }|*2
   1110      {3:                                   }|
   1111      {9:E121: Undefined variable: doesnotex}|
   1112      {9:ist}                                |
   1113      {6:Press ENTER or type command to cont}|
   1114      {9:E121: Undefined variable: doesnotex}|
   1115      {9:ist}                                |
   1116      {6:Press ENTER or type command to cont}|
   1117      {6:inue}^                               |
   1118    ]])
   1119 
   1120    feed(':echoerr doesnotexist<cr>')
   1121    screen:expect([[
   1122      {5:c3                                 }|
   1123                                         |
   1124      {3:c3                                 }|
   1125      {3:                                   }|
   1126      {9:E121: Undefined variable: doesnotex}|
   1127      {9:ist}                                |
   1128      {6:Press ENTER or type command to cont}|
   1129      {9:E121: Undefined variable: doesnotex}|
   1130      {9:ist}                                |
   1131      {6:Press ENTER or type command to cont}|
   1132      {9:E121: Undefined variable: doesnotex}|
   1133      {9:ist}                                |
   1134      {6:Press ENTER or type command to cont}|
   1135      {6:inue}^                               |
   1136    ]])
   1137 
   1138    feed('<cr>')
   1139    screen:expect([[
   1140      {5:n3                                 }|
   1141      ^                                   |
   1142      {3:n3                                 }|
   1143                                         |
   1144      {1:~                                  }|*8
   1145      {2:[No Name]                          }|
   1146                                         |
   1147    ]])
   1148  end)
   1149 
   1150  describe('if custom statusline is set by', function()
   1151    before_each(function()
   1152      command('set statusline=')
   1153      screen:expect([[
   1154        ^                         |
   1155        {1:~                        }|*2
   1156        {3:[No Name]                }|
   1157                                 |
   1158      ]])
   1159    end)
   1160 
   1161    it('CmdlineEnter autocommand', function()
   1162      command('autocmd CmdlineEnter * set statusline=command')
   1163      feed(':')
   1164      screen:expect([[
   1165                                 |
   1166        {1:~                        }|*2
   1167        {3:command                  }|
   1168        :^                        |
   1169      ]])
   1170    end)
   1171 
   1172    it('ModeChanged autocommand', function()
   1173      command('autocmd ModeChanged *:c set statusline=command')
   1174      feed(':')
   1175      screen:expect([[
   1176                                 |
   1177        {1:~                        }|*2
   1178        {3:command                  }|
   1179        :^                        |
   1180      ]])
   1181    end)
   1182  end)
   1183 end)
   1184 
   1185 it('tabline is not redrawn in Ex mode #24122', function()
   1186  clear()
   1187  local screen = Screen.new(60, 5)
   1188 
   1189  exec([[
   1190    set showtabline=2
   1191    set tabline=%!MyTabLine()
   1192 
   1193    function! MyTabLine()
   1194 
   1195      return "foo"
   1196    endfunction
   1197  ]])
   1198 
   1199  feed('gQ')
   1200  screen:expect([[
   1201    {2:foo                                                         }|
   1202                                                                |
   1203    {3:                                                            }|
   1204    Entering Ex mode.  Type "visual" to go to Normal mode.      |
   1205    :^                                                           |
   1206  ]])
   1207 
   1208  feed('echo 1<CR>')
   1209  screen:expect([[
   1210    {3:                                                            }|
   1211    Entering Ex mode.  Type "visual" to go to Normal mode.      |
   1212    :echo 1                                                     |
   1213    1                                                           |
   1214    :^                                                           |
   1215  ]])
   1216 end)
   1217 
   1218 describe('cmdline height', function()
   1219  before_each(clear)
   1220 
   1221  it('does not crash resized screen #14263', function()
   1222    local screen = Screen.new(25, 10)
   1223    command('set cmdheight=9999')
   1224    screen:try_resize(25, 5)
   1225    assert_alive()
   1226  end)
   1227 
   1228  it('unchanged when restoring window sizes with global statusline', function()
   1229    command('set cmdheight=2 laststatus=2')
   1230    feed('q:')
   1231    command('set cmdheight=1 laststatus=3 | quit')
   1232    -- Available lines changed, so closing cmdwin should skip restoring window sizes, leaving the
   1233    -- cmdheight unchanged.
   1234    eq(1, eval('&cmdheight'))
   1235  end)
   1236 
   1237  it('not increased to 0 from 1 with wincmd _', function()
   1238    command('set cmdheight=0 laststatus=0')
   1239    command('wincmd _')
   1240    eq(0, eval('&cmdheight'))
   1241  end)
   1242 end)
   1243 
   1244 describe('cmdheight=0', function()
   1245  local screen
   1246  before_each(function()
   1247    clear()
   1248    screen = Screen.new(25, 5)
   1249  end)
   1250 
   1251  it('with redrawdebug=invalid resize -1', function()
   1252    command('set redrawdebug=invalid cmdheight=0 noruler laststatus=0')
   1253    screen:expect([[
   1254      ^                         |
   1255      {1:~                        }|*4
   1256    ]])
   1257    feed(':resize -1<CR>')
   1258    screen:expect([[
   1259      ^                         |
   1260      {1:~                        }|*3
   1261                               |
   1262    ]])
   1263    assert_alive()
   1264  end)
   1265 
   1266  it('with cmdheight=1 noruler laststatus=2', function()
   1267    command('set cmdheight=1 noruler laststatus=2')
   1268    screen:expect([[
   1269      ^                         |
   1270      {1:~                        }|*2
   1271      {3:[No Name]                }|
   1272                               |
   1273    ]])
   1274  end)
   1275 
   1276  it('with cmdheight=0 noruler laststatus=2', function()
   1277    command('set cmdheight=0 noruler laststatus=2')
   1278    screen:expect([[
   1279      ^                         |
   1280      {1:~                        }|*3
   1281      {3:[No Name]                }|
   1282    ]])
   1283  end)
   1284 
   1285  it('with cmdheight=0 ruler laststatus=0', function()
   1286    command('set cmdheight=0 ruler laststatus=0')
   1287    screen:expect([[
   1288      ^                         |
   1289      {1:~                        }|*4
   1290    ]])
   1291  end)
   1292 
   1293  it('with cmdheight=0 ruler laststatus=0', function()
   1294    command('set cmdheight=0 noruler laststatus=0 showmode')
   1295    feed('i')
   1296    screen:expect {
   1297      grid = [[
   1298        ^                         |
   1299        {1:~                        }|*4
   1300      ]],
   1301      showmode = {},
   1302    }
   1303    feed('<Esc>')
   1304    eq(0, eval('&cmdheight'))
   1305  end)
   1306 
   1307  it('with cmdheight=0 ruler rulerformat laststatus=0', function()
   1308    command('set cmdheight=0 noruler laststatus=0 rulerformat=%l,%c%= showmode')
   1309    feed('i')
   1310    screen:expect {
   1311      grid = [[
   1312        ^                         |
   1313        {1:~                        }|*4
   1314      ]],
   1315      showmode = {},
   1316    }
   1317    feed('<Esc>')
   1318    eq(0, eval('&cmdheight'))
   1319  end)
   1320 
   1321  it('with showmode', function()
   1322    command('set cmdheight=1 noruler laststatus=0 showmode')
   1323    feed('i')
   1324    screen:expect([[
   1325      ^                         |
   1326      {1:~                        }|*3
   1327      {5:-- INSERT --}             |
   1328    ]])
   1329    feed('<Esc>')
   1330    eq(1, eval('&cmdheight'))
   1331  end)
   1332 
   1333  it('when using command line', function()
   1334    command('set cmdheight=0 noruler laststatus=0')
   1335    feed(':')
   1336    screen:expect([[
   1337                               |
   1338      {1:~                        }|*3
   1339      :^                        |
   1340    ]])
   1341    eq(0, eval('&cmdheight'))
   1342    feed('<cr>')
   1343    screen:expect {
   1344      grid = [[
   1345        ^                         |
   1346        {1:~                        }|*4
   1347      ]],
   1348      showmode = {},
   1349    }
   1350    eq(0, eval('&cmdheight'))
   1351  end)
   1352 
   1353  it('when using input()', function()
   1354    command('set cmdheight=0 noruler laststatus=0')
   1355    feed(':call input("foo >")<cr>')
   1356    screen:expect([[
   1357                               |
   1358      {1:~                        }|
   1359      {3:                         }|
   1360      :call input("foo >")     |
   1361      foo >^                    |
   1362    ]])
   1363    eq(0, eval('&cmdheight'))
   1364    feed('<cr>')
   1365    screen:expect {
   1366      grid = [[
   1367        ^                         |
   1368        {1:~                        }|*4
   1369      ]],
   1370      showmode = {},
   1371    }
   1372    eq(0, eval('&cmdheight'))
   1373  end)
   1374 
   1375  it('with winbar and splits', function()
   1376    command('set cmdheight=0 noruler laststatus=3 winbar=foo')
   1377    feed(':split<CR>')
   1378    screen:expect([[
   1379      {3:                         }|
   1380      :split                   |
   1381      {9:E36: Not enough room}     |
   1382      {6:Press ENTER or type comma}|
   1383      {6:nd to continue}^           |
   1384    ]])
   1385    feed('<CR>')
   1386    screen:expect([[
   1387      {5:foo                      }|
   1388      ^                         |
   1389      {1:~                        }|*2
   1390      {3:[No Name]                }|
   1391    ]])
   1392    feed(':')
   1393    screen:expect([[
   1394      {5:foo                      }|
   1395                               |
   1396      {1:~                        }|*2
   1397      :^                        |
   1398    ]])
   1399    feed('<Esc>')
   1400    screen:expect {
   1401      grid = [[
   1402        {5:foo                      }|
   1403        ^                         |
   1404        {1:~                        }|*2
   1405        {3:[No Name]                }|
   1406      ]],
   1407      showmode = {},
   1408    }
   1409    eq(0, eval('&cmdheight'))
   1410 
   1411    assert_alive()
   1412  end)
   1413 
   1414  it('when macro with lastline', function()
   1415    command('set cmdheight=0 display=lastline')
   1416    feed('qq')
   1417    screen:expect([[
   1418      ^                         |
   1419      {1:~                        }|*4
   1420    ]])
   1421    feed('q')
   1422    screen:expect {
   1423      grid = [[
   1424        ^                         |
   1425        {1:~                        }|*4
   1426      ]],
   1427      unchanged = true,
   1428    }
   1429  end)
   1430 
   1431  it('when substitute text', function()
   1432    command('set cmdheight=0 noruler laststatus=3')
   1433    feed('ifoo<ESC>')
   1434    screen:try_resize(screen._width, 7)
   1435    screen:expect([[
   1436      fo^o                      |
   1437      {1:~                        }|*5
   1438      {3:[No Name] [+]            }|
   1439    ]])
   1440 
   1441    feed(':%s/foo/bar/gc<CR>')
   1442    screen:expect([[
   1443      {2:foo}                      |
   1444      {3:                         }|
   1445                               |*2
   1446      {6:replace with bar? (y)es/(}|
   1447      {6:n)o/(a)ll/(q)uit/(l)ast/s}|
   1448      {6:croll up(^E)/down(^Y)}^    |
   1449    ]])
   1450 
   1451    feed('y')
   1452    screen:expect([[
   1453      ^bar                      |
   1454      {1:~                        }|*5
   1455      {3:[No Name] [+]            }|
   1456    ]])
   1457 
   1458    assert_alive()
   1459  end)
   1460 
   1461  it('when window resize', function()
   1462    command('set cmdheight=0')
   1463    feed('<C-w>+')
   1464    eq(0, eval('&cmdheight'))
   1465  end)
   1466 
   1467  it('with non-silent mappings with cmdline', function()
   1468    command('set cmdheight=0')
   1469    command('map <f3> :nohlsearch<cr>')
   1470    feed('iaabbaa<esc>/aa<cr>')
   1471    screen:expect([[
   1472      {10:^aa}bb{10:aa}                   |
   1473      {1:~                        }|*4
   1474    ]])
   1475 
   1476    feed('<f3>')
   1477    screen:expect([[
   1478      ^aabbaa                   |
   1479      {1:~                        }|*4
   1480    ]])
   1481  end)
   1482 
   1483  it('with silent! at startup', function()
   1484    clear { args = { '-c', 'set cmdheight=0', '-c', 'autocmd VimEnter * silent! call Foo()' } }
   1485    screen = Screen.new(25, 5)
   1486    -- doesn't crash while not displaying silent! error message
   1487    screen:expect([[
   1488      ^                         |
   1489      {1:~                        }|*4
   1490    ]])
   1491  end)
   1492 
   1493  it('with multigrid', function()
   1494    clear { args = { '--cmd', 'set cmdheight=0' } }
   1495    screen = Screen.new(25, 5, { ext_multigrid = true })
   1496    api.nvim_buf_set_lines(0, 0, -1, true, { 'p' })
   1497    screen:expect {
   1498      grid = [[
   1499      ## grid 1
   1500        [2:-------------------------]|*5
   1501      ## grid 2
   1502        ^p                        |
   1503        {1:~                        }|*4
   1504      ## grid 3
   1505      ]],
   1506      win_viewport = {
   1507        [2] = {
   1508          win = 1000,
   1509          topline = 0,
   1510          botline = 2,
   1511          curline = 0,
   1512          curcol = 0,
   1513          linecount = 1,
   1514          sum_scroll_delta = 0,
   1515        },
   1516      },
   1517    }
   1518 
   1519    feed '/p'
   1520    screen:expect {
   1521      grid = [[
   1522      ## grid 1
   1523        [2:-------------------------]|*4
   1524        [3:-------------------------]|
   1525      ## grid 2
   1526        {2:p}                        |
   1527        {1:~                        }|*4
   1528      ## grid 3
   1529        /p^                       |
   1530      ]],
   1531      win_viewport = {
   1532        [2] = {
   1533          win = 1000,
   1534          topline = 0,
   1535          botline = 2,
   1536          curline = 0,
   1537          curcol = 1,
   1538          linecount = 1,
   1539          sum_scroll_delta = 0,
   1540        },
   1541      },
   1542    }
   1543  end)
   1544 
   1545  it('winbar is redrawn on entering cmdline and :redrawstatus #20336', function()
   1546    exec([[
   1547      set cmdheight=0
   1548      set winbar=%{mode()}%=:%{getcmdline()}
   1549    ]])
   1550    feed(':')
   1551    screen:expect([[
   1552      {5:c                       :}|
   1553                               |
   1554      {1:~                        }|*2
   1555      :^                        |
   1556    ]])
   1557    feed('echo')
   1558    -- not redrawn yet
   1559    screen:expect([[
   1560      {5:c                       :}|
   1561                               |
   1562      {1:~                        }|*2
   1563      :echo^                    |
   1564    ]])
   1565    command('redrawstatus')
   1566    screen:expect([[
   1567      {5:c                   :echo}|
   1568                               |
   1569      {1:~                        }|*2
   1570      :echo^                    |
   1571    ]])
   1572  end)
   1573 
   1574  it('window equalization with laststatus=0 #20367', function()
   1575    screen:try_resize(60, 9)
   1576    command('set cmdheight=0 laststatus=0')
   1577    command('vsplit')
   1578    screen:expect([[
   1579      ^                                                           |
   1580      {1:~                             }{1:~                            }|*8
   1581    ]])
   1582    feed(':')
   1583    command('split')
   1584    feed('<Esc>')
   1585    screen:expect([[
   1586      ^                                                           |
   1587      {1:~                             }{1:~                            }|*3
   1588      {3:[No Name]                     }{1:~                            }|
   1589                                    {1:~                            }|
   1590      {1:~                             }{1:~                            }|*3
   1591    ]])
   1592    command('resize 2')
   1593    screen:expect([[
   1594      ^                                                           |
   1595      {1:~                             }{1:~                            }|
   1596      {3:[No Name]                     }{1:~                            }|
   1597                                    {1:~                            }|
   1598      {1:~                             }{1:~                            }|*5
   1599    ]])
   1600    feed(':')
   1601    command('wincmd =')
   1602    feed('<Esc>')
   1603    screen:expect([[
   1604      ^                                                           |
   1605      {1:~                             }{1:~                            }|*3
   1606      {3:[No Name]                     }{1:~                            }|
   1607                                    {1:~                            }|
   1608      {1:~                             }{1:~                            }|*3
   1609    ]])
   1610  end)
   1611 
   1612  it('no assert failure with showcmd', function()
   1613    command('set showcmd cmdheight=0')
   1614    feed('d')
   1615    screen:expect([[
   1616      ^                         |
   1617      {1:~                        }|*4
   1618    ]])
   1619    assert_alive()
   1620  end)
   1621 
   1622  it('can only be resized to 0 if set explicitly', function()
   1623    command('set laststatus=2')
   1624    command('resize +1')
   1625    screen:expect([[
   1626      ^                         |
   1627      {1:~                        }|*2
   1628      {3:[No Name]                }|
   1629                               |
   1630    ]])
   1631    command('set cmdheight=0')
   1632    screen:expect([[
   1633      ^                         |
   1634      {1:~                        }|*3
   1635      {3:[No Name]                }|
   1636    ]])
   1637    command('resize -1')
   1638    screen:expect([[
   1639      ^                         |
   1640      {1:~                        }|*2
   1641      {3:[No Name]                }|
   1642                               |
   1643    ]])
   1644    command('resize +1')
   1645    screen:expect([[
   1646      ^                         |
   1647      {1:~                        }|*3
   1648      {3:[No Name]                }|
   1649    ]])
   1650  end)
   1651 
   1652  it('can be resized with external messages', function()
   1653    clear()
   1654    screen = Screen.new(25, 5, { rgb = true, ext_messages = true })
   1655    command('set laststatus=2 mouse=a')
   1656    command('resize -1')
   1657    screen:expect([[
   1658      ^                         |
   1659      {1:~                        }|*2
   1660      {3:[No Name]                }|
   1661                               |
   1662    ]])
   1663    api.nvim_input_mouse('left', 'press', '', 0, 3, 10)
   1664    poke_eventloop()
   1665    api.nvim_input_mouse('left', 'drag', '', 0, 4, 10)
   1666    screen:expect([[
   1667      ^                         |
   1668      {1:~                        }|*3
   1669      {3:[No Name]                }|
   1670    ]])
   1671  end)
   1672 end)