neovim

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

search_spec.lua (22329B)


      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 eval = n.eval
      9 local feed = n.feed
     10 local fn = n.fn
     11 local poke_eventloop = n.poke_eventloop
     12 local exec = n.exec
     13 
     14 describe('search cmdline', function()
     15  local screen
     16 
     17  before_each(function()
     18    clear()
     19    command('set nohlsearch inccommand=')
     20    screen = Screen.new(20, 3)
     21  end)
     22 
     23  local function tenlines()
     24    fn.setline(1, {
     25      '  1',
     26      '  2 these',
     27      '  3 the',
     28      '  4 their',
     29      '  5 there',
     30      '  6 their',
     31      '  7 the',
     32      '  8 them',
     33      '  9 these',
     34      ' 10 foobar',
     35    })
     36    command('1')
     37  end
     38 
     39  it('history can be navigated with <C-N>/<C-P>', function()
     40    tenlines()
     41    command('set noincsearch')
     42    feed('/foobar<CR>')
     43    feed('/the<CR>')
     44    eq('the', eval('@/'))
     45    feed('/thes<C-P><C-P><CR>')
     46    eq('foobar', eval('@/'))
     47  end)
     48 
     49  describe('can traverse matches', function()
     50    before_each(tenlines)
     51    local function forwarditer(wrapscan)
     52      command('set incsearch ' .. wrapscan)
     53      feed('/the')
     54      screen:expect([[
     55          1                 |
     56          2 {2:the}se           |
     57        /the^                |
     58      ]])
     59      feed('<C-G>')
     60      screen:expect([[
     61          2 these           |
     62          3 {2:the}             |
     63        /the^                |
     64      ]])
     65      eq({ 0, 0, 0, 0 }, fn.getpos('"'))
     66      feed('<C-G>')
     67      screen:expect([[
     68          3 the             |
     69          4 {2:the}ir           |
     70        /the^                |
     71      ]])
     72      feed('<C-G>')
     73      screen:expect([[
     74          4 their           |
     75          5 {2:the}re           |
     76        /the^                |
     77      ]])
     78      feed('<C-G>')
     79      screen:expect([[
     80          5 there           |
     81          6 {2:the}ir           |
     82        /the^                |
     83      ]])
     84      feed('<C-G>')
     85      screen:expect([[
     86          6 their           |
     87          7 {2:the}             |
     88        /the^                |
     89      ]])
     90      feed('<C-G>')
     91      screen:expect([[
     92          7 the             |
     93          8 {2:the}m            |
     94        /the^                |
     95      ]])
     96      feed('<C-G>')
     97      screen:expect([[
     98          8 them            |
     99          9 {2:the}se           |
    100        /the^                |
    101      ]])
    102      screen.bell = false
    103      feed('<C-G>')
    104      if wrapscan == 'wrapscan' then
    105        screen:expect([[
    106            2 {2:the}se           |
    107            3 the             |
    108          /the^                |
    109        ]])
    110      else
    111        screen:expect {
    112          grid = [[
    113            8 them            |
    114            9 {2:the}se           |
    115          /the^                |
    116        ]],
    117          condition = function()
    118            eq(true, screen.bell)
    119          end,
    120        }
    121        feed('<CR>')
    122        eq({ 0, 0, 0, 0 }, fn.getpos('"'))
    123      end
    124    end
    125 
    126    local function backiter(wrapscan)
    127      command('set incsearch ' .. wrapscan)
    128      command('$')
    129 
    130      feed('?the')
    131      screen:expect([[
    132          9 {2:the}se           |
    133         10 foobar          |
    134        ?the^                |
    135      ]])
    136      screen.bell = false
    137      if wrapscan == 'wrapscan' then
    138        feed('<C-G>')
    139        screen:expect([[
    140            2 {2:the}se           |
    141            3 the             |
    142          ?the^                |
    143        ]])
    144        feed('<CR>')
    145        screen:expect([[
    146            2 ^these           |
    147            3 the             |
    148          ?the                |
    149        ]])
    150      else
    151        feed('<C-G>')
    152        screen:expect {
    153          grid = [[
    154            9 {2:the}se           |
    155           10 foobar          |
    156          ?the^                |
    157        ]],
    158          condition = function()
    159            eq(true, screen.bell)
    160          end,
    161        }
    162        feed('<CR>')
    163        screen:expect([[
    164            9 ^these           |
    165           10 foobar          |
    166          ?the                |
    167        ]])
    168      end
    169      command('$')
    170      feed('?the')
    171      screen:expect([[
    172          9 {2:the}se           |
    173         10 foobar          |
    174        ?the^                |
    175      ]])
    176      feed('<C-T>')
    177      screen:expect([[
    178          8 {2:the}m            |
    179          9 these           |
    180        ?the^                |
    181      ]])
    182      for i = 1, 6 do
    183        feed('<C-T>')
    184        -- Avoid sleep just before expect, otherwise expect will take the full
    185        -- timeout
    186        if i ~= 6 then
    187          screen:sleep(1)
    188        end
    189      end
    190      screen:expect([[
    191          2 {2:the}se           |
    192          3 the             |
    193        ?the^                |
    194      ]])
    195      screen.bell = false
    196      feed('<C-T>')
    197      if wrapscan == 'wrapscan' then
    198        screen:expect([[
    199            9 {2:the}se           |
    200           10 foobar          |
    201          ?the^                |
    202        ]])
    203      else
    204        screen:expect {
    205          grid = [[
    206            2 {2:the}se           |
    207            3 the             |
    208          ?the^                |
    209        ]],
    210          condition = function()
    211            eq(true, screen.bell)
    212          end,
    213        }
    214      end
    215    end
    216 
    217    it("using <C-G> and 'nowrapscan'", function()
    218      forwarditer('nowrapscan')
    219    end)
    220 
    221    it("using <C-G> and 'wrapscan'", function()
    222      forwarditer('wrapscan')
    223    end)
    224 
    225    it("using <C-T> and 'nowrapscan'", function()
    226      backiter('nowrapscan')
    227    end)
    228 
    229    it("using <C-T> and 'wrapscan'", function()
    230      backiter('wrapscan')
    231    end)
    232  end)
    233 
    234  it('expands pattern with <C-L>', function()
    235    tenlines()
    236    command('set incsearch wrapscan')
    237 
    238    feed('/the')
    239    screen:expect([[
    240        1                 |
    241        2 {2:the}se           |
    242      /the^                |
    243    ]])
    244    feed('<C-L>')
    245    screen:expect([[
    246        1                 |
    247        2 {2:thes}e           |
    248      /thes^               |
    249    ]])
    250    feed('<C-G>')
    251    screen:expect([[
    252        9 {2:thes}e           |
    253       10 foobar          |
    254      /thes^               |
    255    ]])
    256    feed('<C-G>')
    257    screen:expect([[
    258        2 {2:thes}e           |
    259        3 the             |
    260      /thes^               |
    261    ]])
    262    feed('<CR>')
    263    screen:expect([[
    264        2 ^these           |
    265        3 the             |
    266      /thes               |
    267    ]])
    268 
    269    command('1')
    270    command('set nowrapscan')
    271    feed('/the')
    272    screen:expect([[
    273        1                 |
    274        2 {2:the}se           |
    275      /the^                |
    276    ]])
    277    feed('<C-L>')
    278    screen:expect([[
    279        1                 |
    280        2 {2:thes}e           |
    281      /thes^               |
    282    ]])
    283    feed('<C-G>')
    284    screen:expect([[
    285        9 {2:thes}e           |
    286       10 foobar          |
    287      /thes^               |
    288    ]])
    289    feed('<C-G><CR>')
    290    screen:expect([[
    291        9 ^these           |
    292       10 foobar          |
    293      /thes               |
    294    ]])
    295  end)
    296 
    297  it('reduces pattern with <BS> and keeps cursor position', function()
    298    tenlines()
    299    command('set incsearch wrapscan')
    300 
    301    -- First match
    302    feed('/thei')
    303    screen:expect([[
    304        3 the             |
    305        4 {2:thei}r           |
    306      /thei^               |
    307    ]])
    308    -- Match from initial cursor position when modifying search
    309    feed('<BS>')
    310    screen:expect([[
    311        1                 |
    312        2 {2:the}se           |
    313      /the^                |
    314    ]])
    315    -- New text advances to next match
    316    feed('s')
    317    screen:expect([[
    318        1                 |
    319        2 {2:thes}e           |
    320      /thes^               |
    321    ]])
    322    -- Stay on this match when deleting a character
    323    feed('<BS>')
    324    screen:expect([[
    325        1                 |
    326        2 {2:the}se           |
    327      /the^                |
    328    ]])
    329    -- Advance to previous match
    330    feed('<C-T>')
    331    screen:expect([[
    332        9 {2:the}se           |
    333       10 foobar          |
    334      /the^                |
    335    ]])
    336    -- Extend search to include next character
    337    feed('<C-L>')
    338    screen:expect([[
    339        9 {2:thes}e           |
    340       10 foobar          |
    341      /thes^               |
    342    ]])
    343    -- Deleting all characters resets the cursor position
    344    feed('<BS><BS><BS><BS>')
    345    screen:expect([[
    346        1                 |
    347        2 these           |
    348      /^                   |
    349    ]])
    350    feed('the')
    351    screen:expect([[
    352        1                 |
    353        2 {2:the}se           |
    354      /the^                |
    355    ]])
    356    feed('\\>')
    357    screen:expect([[
    358        2 these           |
    359        3 {2:the}             |
    360      /the\>^              |
    361    ]])
    362  end)
    363 
    364  it('can traverse matches in the same line with <C-G>/<C-T>', function()
    365    fn.setline(1, { '  1', '  2 these', '  3 the theother' })
    366    command('1')
    367    command('set incsearch')
    368 
    369    -- First match
    370    feed('/the')
    371    screen:expect([[
    372        1                 |
    373        2 {2:the}se           |
    374      /the^                |
    375    ]])
    376 
    377    -- Next match, different line
    378    feed('<C-G>')
    379    screen:expect([[
    380        2 these           |
    381        3 {2:the} theother    |
    382      /the^                |
    383    ]])
    384 
    385    -- Next match, same line
    386    feed('<C-G>')
    387    screen:expect([[
    388        2 these           |
    389        3 the {2:the}other    |
    390      /the^                |
    391    ]])
    392    feed('<C-G>')
    393    screen:expect([[
    394        2 these           |
    395        3 the theo{2:the}r    |
    396      /the^                |
    397    ]])
    398 
    399    -- Previous match, same line
    400    feed('<C-T>')
    401    screen:expect([[
    402        2 these           |
    403        3 the {2:the}other    |
    404      /the^                |
    405    ]])
    406    feed('<C-T>')
    407    screen:expect([[
    408        2 these           |
    409        3 {2:the} theother    |
    410      /the^                |
    411    ]])
    412 
    413    -- Previous match, different line
    414    feed('<C-T>')
    415    screen:expect([[
    416        2 {2:the}se           |
    417        3 the theother    |
    418      /the^                |
    419    ]])
    420  end)
    421 
    422  it('keeps the view after deleting a char from the search', function()
    423    screen:try_resize(20, 6)
    424    tenlines()
    425 
    426    feed('/foo')
    427    screen:expect([[
    428        6 their           |
    429        7 the             |
    430        8 them            |
    431        9 these           |
    432       10 {2:foo}bar          |
    433      /foo^                |
    434    ]])
    435    feed('<BS>')
    436    screen:expect([[
    437        6 their           |
    438        7 the             |
    439        8 them            |
    440        9 these           |
    441       10 {2:fo}obar          |
    442      /fo^                 |
    443    ]])
    444    feed('<CR>')
    445    screen:expect([[
    446        6 their           |
    447        7 the             |
    448        8 them            |
    449        9 these           |
    450       10 ^foobar          |
    451      /fo                 |
    452    ]])
    453    eq({
    454      lnum = 10,
    455      leftcol = 0,
    456      col = 4,
    457      topfill = 0,
    458      topline = 6,
    459      coladd = 0,
    460      skipcol = 0,
    461      curswant = 4,
    462    }, fn.winsaveview())
    463  end)
    464 
    465  it('restores original view after failed search', function()
    466    screen:try_resize(40, 3)
    467    tenlines()
    468    feed('0')
    469    feed('/foo')
    470    screen:expect([[
    471        9 these                               |
    472       10 {2:foo}bar                              |
    473      /foo^                                    |
    474    ]])
    475    feed('<C-W>')
    476    screen:expect([[
    477        1                                     |
    478        2 these                               |
    479      /^                                       |
    480    ]])
    481    feed('<CR>')
    482    screen:expect([[
    483      /                                       |
    484      {9:E35: No previous regular expression}     |
    485      {6:Press ENTER or type command to continue}^ |
    486    ]])
    487    feed('<CR>')
    488    eq({
    489      lnum = 1,
    490      leftcol = 0,
    491      col = 0,
    492      topfill = 0,
    493      topline = 1,
    494      coladd = 0,
    495      skipcol = 0,
    496      curswant = 0,
    497    }, fn.winsaveview())
    498  end)
    499 
    500  -- oldtest: Test_search_cmdline4().
    501  it("CTRL-G with 'incsearch' and ? goes in the right direction", function()
    502    screen:try_resize(40, 4)
    503    command('enew!')
    504    fn.setline(1, { '  1 the first', '  2 the second', '  3 the third' })
    505    command('set laststatus=0 shortmess+=s')
    506    command('set incsearch')
    507    command('$')
    508    -- Send the input in chunks, so the cmdline logic regards it as
    509    -- "interactive".  This mimics Vim's test_override("char_avail").
    510    -- (See legacy test: test_search.vim)
    511    feed('?the')
    512    poke_eventloop()
    513    feed('<c-g>')
    514    poke_eventloop()
    515    feed('<cr>')
    516    screen:expect([[
    517        1 the first                           |
    518        2 the second                          |
    519        3 ^the third                           |
    520      ?the                                    |
    521    ]])
    522 
    523    command('$')
    524    feed('?the')
    525    poke_eventloop()
    526    feed('<c-g>')
    527    poke_eventloop()
    528    feed('<c-g>')
    529    poke_eventloop()
    530    feed('<cr>')
    531    screen:expect([[
    532        1 ^the first                           |
    533        2 the second                          |
    534        3 the third                           |
    535      ?the                                    |
    536    ]])
    537 
    538    command('$')
    539    feed('?the')
    540    poke_eventloop()
    541    feed('<c-g>')
    542    poke_eventloop()
    543    feed('<c-g>')
    544    poke_eventloop()
    545    feed('<c-g>')
    546    poke_eventloop()
    547    feed('<cr>')
    548    screen:expect([[
    549        1 the first                           |
    550        2 ^the second                          |
    551        3 the third                           |
    552      ?the                                    |
    553    ]])
    554 
    555    command('$')
    556    feed('?the')
    557    poke_eventloop()
    558    feed('<c-t>')
    559    poke_eventloop()
    560    feed('<cr>')
    561    screen:expect([[
    562        1 ^the first                           |
    563        2 the second                          |
    564        3 the third                           |
    565      ?the                                    |
    566    ]])
    567 
    568    command('$')
    569    feed('?the')
    570    poke_eventloop()
    571    feed('<c-t>')
    572    poke_eventloop()
    573    feed('<c-t>')
    574    poke_eventloop()
    575    feed('<cr>')
    576    screen:expect([[
    577        1 the first                           |
    578        2 the second                          |
    579        3 ^the third                           |
    580      ?the                                    |
    581    ]])
    582 
    583    command('$')
    584    feed('?the')
    585    poke_eventloop()
    586    feed('<c-t>')
    587    poke_eventloop()
    588    feed('<c-t>')
    589    poke_eventloop()
    590    feed('<c-t>')
    591    poke_eventloop()
    592    feed('<cr>')
    593    screen:expect([[
    594        1 the first                           |
    595        2 ^the second                          |
    596        3 the third                           |
    597      ?the                                    |
    598    ]])
    599  end)
    600 
    601  -- oldtest: Test_incsearch_sort_dump().
    602  it('incsearch works with :sort', function()
    603    screen:try_resize(20, 4)
    604    command('set incsearch hlsearch scrolloff=0')
    605    fn.setline(1, { 'another one 2', 'that one 3', 'the one 1' })
    606 
    607    feed(':sort ni u /on')
    608    screen:expect([[
    609      another {2:on}e 2       |
    610      that {10:on}e 3          |
    611      the {10:on}e 1           |
    612      :sort ni u /on^      |
    613    ]])
    614    feed('<esc>')
    615  end)
    616 
    617  -- oldtest: Test_incsearch_vimgrep_dump().
    618  it('incsearch works with :vimgrep family', function()
    619    screen:try_resize(30, 4)
    620    command('set incsearch hlsearch scrolloff=0')
    621    fn.setline(1, { 'another one 2', 'that one 3', 'the one 1' })
    622 
    623    feed(':vimgrep on')
    624    screen:expect([[
    625      another {2:on}e 2                 |
    626      that {10:on}e 3                    |
    627      the {10:on}e 1                     |
    628      :vimgrep on^                   |
    629    ]])
    630    feed('<esc>')
    631 
    632    feed(':vimg /on/ *.txt')
    633    screen:expect([[
    634      another {2:on}e 2                 |
    635      that {10:on}e 3                    |
    636      the {10:on}e 1                     |
    637      :vimg /on/ *.txt^              |
    638    ]])
    639    feed('<esc>')
    640 
    641    feed(':vimgrepadd "\\<LT>on')
    642    screen:expect([[
    643      another {2:on}e 2                 |
    644      that {10:on}e 3                    |
    645      the {10:on}e 1                     |
    646      :vimgrepadd "\<on^             |
    647    ]])
    648    feed('<esc>')
    649 
    650    feed(':lv "tha')
    651    screen:expect([[
    652      another one 2                 |
    653      {2:tha}t one 3                    |
    654      the one 1                     |
    655      :lv "tha^                      |
    656    ]])
    657    feed('<esc>')
    658 
    659    feed(':lvimgrepa "the" **/*.txt')
    660    screen:expect([[
    661      ano{2:the}r one 2                 |
    662      that one 3                    |
    663      {10:the} one 1                     |
    664      :lvimgrepa "the" **/*.txt^     |
    665    ]])
    666    feed('<esc>')
    667  end)
    668 
    669  -- oldtest: Test_incsearch_substitute_dump2()
    670  it('incsearch detects empty pattern properly vim-patch:8.2.2295', function()
    671    screen:try_resize(70, 6)
    672    exec([[
    673      set incsearch hlsearch scrolloff=0
    674      for n in range(1, 4)
    675        call setline(n, "foo " . n)
    676      endfor
    677      call setline(5, "abc|def")
    678      3
    679    ]])
    680 
    681    feed([[:%s/\vabc|]])
    682    screen:expect([[
    683      foo 1                                                                 |
    684      foo 2                                                                 |
    685      foo 3                                                                 |
    686      foo 4                                                                 |
    687      abc|def                                                               |
    688      :%s/\vabc|^                                                            |
    689    ]])
    690    feed('<Esc>')
    691 
    692    -- The following should not be highlighted
    693    feed([[:1,5s/\v|]])
    694    screen:expect([[
    695      foo 1                                                                 |
    696      foo 2                                                                 |
    697      foo 3                                                                 |
    698      foo 4                                                                 |
    699      abc|def                                                               |
    700      :1,5s/\v|^                                                             |
    701    ]])
    702  end)
    703 
    704  -- oldtest: Test_incsearch_restore_view()
    705  it('incsearch restores viewport', function()
    706    screen:try_resize(20, 6)
    707    exec([[
    708      set incsearch nohlsearch
    709      setlocal scrolloff=0 smoothscroll
    710      call setline(1, [join(range(25), ' '), '', '', '', '', 'xxx'])
    711      call feedkeys("2\<C-E>", 't')
    712    ]])
    713    local s = [[
    714      {1:<<<} 18 19 20 21 22 2|
    715      ^3 24                |
    716                          |*4
    717    ]]
    718    screen:expect(s)
    719    feed('/xx')
    720    screen:expect([[
    721                          |*4
    722      {2:xx}x                 |
    723      /xx^                 |
    724    ]])
    725    feed('x')
    726    screen:expect([[
    727                          |*4
    728      {2:xxx}                 |
    729      /xxx^                |
    730    ]])
    731    feed('<Esc>')
    732    screen:expect(s)
    733  end)
    734 
    735  -- oldtest: Test_incsearch_delimiter_ctrlg()
    736  it('incsearch does not include trailing delimiter', function()
    737    screen:try_resize(20, 6)
    738    exec([[
    739      set incsearch hls
    740      call setline(1, ["1 vim inc", "2 vim /", "3 vim /", "4 vim ?", "5 vim ?"])
    741      normal gg
    742      redraw
    743    ]])
    744 
    745    feed('/')
    746    poke_eventloop()
    747    feed('v')
    748    poke_eventloop()
    749    feed('i')
    750    poke_eventloop()
    751    feed('m')
    752    poke_eventloop()
    753    feed(' ')
    754    poke_eventloop()
    755    feed('/')
    756    poke_eventloop()
    757    feed('<C-G>')
    758    screen:expect([[
    759      1 {10:vim }inc           |
    760      2 {2:vim }/             |
    761      3 {10:vim }/             |
    762      4 {10:vim }?             |
    763      5 {10:vim }?             |
    764      /vim /^              |
    765    ]])
    766    feed('<Esc>')
    767 
    768    command('5')
    769    feed('?')
    770    poke_eventloop()
    771    feed('v')
    772    poke_eventloop()
    773    feed('i')
    774    poke_eventloop()
    775    feed('m')
    776    poke_eventloop()
    777    feed(' ')
    778    poke_eventloop()
    779    feed('?')
    780    poke_eventloop()
    781    feed('<C-T>')
    782    screen:expect([[
    783      1 {10:vim }inc           |
    784      2 {10:vim }/             |
    785      3 {2:vim }/             |
    786      4 {10:vim }?             |
    787      5 {10:vim }?             |
    788      ?vim ?^              |
    789    ]])
    790    feed('<Esc>')
    791 
    792    feed('/')
    793    poke_eventloop()
    794    feed('v')
    795    poke_eventloop()
    796    feed('i')
    797    poke_eventloop()
    798    feed('m')
    799    poke_eventloop()
    800    feed(' ')
    801    poke_eventloop()
    802    feed('\\/')
    803    poke_eventloop()
    804    feed('<C-G>')
    805    screen:expect([[
    806      1 vim inc           |
    807      2 {10:vim /}             |
    808      3 {2:vim /}             |
    809      4 vim ?             |
    810      5 vim ?             |
    811      /vim \/^             |
    812    ]])
    813    feed('<Esc>')
    814 
    815    command('5')
    816    feed('?')
    817    poke_eventloop()
    818    feed('v')
    819    poke_eventloop()
    820    feed('i')
    821    poke_eventloop()
    822    feed('m')
    823    poke_eventloop()
    824    feed(' ')
    825    poke_eventloop()
    826    feed('\\?')
    827    poke_eventloop()
    828    feed('<C-T>')
    829    screen:expect([[
    830      1 vim inc           |
    831      2 vim /             |
    832      3 vim /             |
    833      4 {10:vim ?}             |
    834      5 {2:vim ?}             |
    835      ?vim \?^             |
    836    ]])
    837    feed('<Esc>')
    838  end)
    839 end)
    840 
    841 describe('Search highlight', function()
    842  before_each(clear)
    843 
    844  -- oldtest: Test_hlsearch_dump()
    845  it('beyond line end vim-patch:8.2.2542', function()
    846    local screen = Screen.new(50, 6)
    847    exec([[
    848      set hlsearch noincsearch cursorline
    849      call setline(1, ["xxx", "xxx", "xxx"])
    850      /.*
    851      2
    852    ]])
    853    feed([[/\_.*<CR>]])
    854    screen:expect([[
    855      {10:xxx }                                              |*2
    856      {10:^xxx }{21:                                              }|
    857      {1:~                                                 }|*2
    858      /\_.*                                             |
    859    ]])
    860  end)
    861 
    862  -- oldtest: Test_hlsearch_and_visual()
    863  it('is combined with Visual highlight vim-patch:8.2.2797', function()
    864    local screen = Screen.new(40, 6)
    865    screen:add_extra_attr_ids {
    866      [100] = {
    867        foreground = Screen.colors.Black,
    868        bold = true,
    869        background = Screen.colors.LightGrey,
    870      },
    871      [101] = { bold = true, background = Screen.colors.Yellow },
    872    }
    873    exec([[
    874      set hlsearch noincsearch
    875      call setline(1, repeat(["xxx yyy zzz"], 3))
    876      hi Search gui=bold
    877      /yyy
    878      call cursor(1, 6)
    879    ]])
    880    feed('vjj')
    881    screen:expect([[
    882      xxx {101:y}{100:yy}{17: zzz}                             |
    883      {17:xxx }{100:yyy}{17: zzz}                             |
    884      {17:xxx }{100:y}{101:^yy} zzz                             |
    885      {1:~                                       }|*2
    886      {5:-- VISUAL --}                            |
    887    ]])
    888  end)
    889 end)