neovim

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

test_diffmode.vim (107415B)


      1 " Tests for diff mode
      2 
      3 source shared.vim
      4 source screendump.vim
      5 source check.vim
      6 source view_util.vim
      7 
      8 func Test_diff_fold_sync()
      9  enew!
     10  let g:update_count = 0
     11  au DiffUpdated * let g:update_count += 1
     12 
     13  let l = range(50)
     14  call setline(1, l)
     15  diffthis
     16  let winone = win_getid()
     17  new
     18  let l[25] = 'diff'
     19  call setline(1, l)
     20  diffthis
     21  let wintwo = win_getid()
     22  " line 15 is inside the closed fold
     23  call assert_equal(19, foldclosedend(10))
     24  call win_gotoid(winone)
     25  call assert_equal(19, foldclosedend(10))
     26  " open the fold
     27  normal zv
     28  call assert_equal(-1, foldclosedend(10))
     29  " fold in other window must have opened too
     30  call win_gotoid(wintwo)
     31  call assert_equal(-1, foldclosedend(10))
     32 
     33  " cursor position is in sync
     34  normal 23G
     35  call win_gotoid(winone)
     36  call assert_equal(23, getcurpos()[1])
     37 
     38  " depending on how redraw is done DiffUpdated may be triggered once or twice
     39  call assert_inrange(1, 2, g:update_count)
     40  au! DiffUpdated
     41 
     42  windo diffoff
     43  close!
     44  set nomodified
     45 endfunc
     46 
     47 func Test_vert_split()
     48  set diffopt=filler
     49  call Common_vert_split()
     50  set diffopt&
     51 endfunc
     52 
     53 " Test for diff folding redraw after last diff is resolved
     54 func Test_diff_fold_redraw()
     55  " Set up two files with a minimal case.
     56  call writefile(['Paragraph 1', '', 'Paragraph 2', '', 'Paragraph 3'], 'Xfile1')
     57  call writefile(['Paragraph 1', '', 'Paragraph 3'], 'Xfile2')
     58 
     59  " Open in diff mode.
     60  edit Xfile1
     61  vert diffsplit Xfile2
     62 
     63  " Go to the diff and apply :diffput to copy Paragraph 2 to Xfile2.
     64  wincmd l
     65  3
     66  diffput
     67 
     68  " Check that the folds in both windows are closed and extend from the first
     69  " line of the buffer to the last line of the buffer.
     70  call assert_equal(1, foldclosed(line("$")))
     71  wincmd h
     72  call assert_equal(1, foldclosed(line("$")))
     73 
     74  " Clean up.
     75  bwipe!
     76  bwipe!
     77  call delete('Xfile1')
     78  call delete('Xfile2')
     79 endfunc
     80 
     81 func Test_vert_split_internal()
     82  set diffopt=internal,filler
     83  call Common_vert_split()
     84  set diffopt&
     85 endfunc
     86 
     87 func Common_vert_split()
     88  " Disable the title to avoid xterm keeping the wrong one.
     89  set notitle noicon
     90  new
     91  let l = ['1 aa', '2 bb', '3 cc', '4 dd', '5 ee']
     92  call setline(1, l)
     93  w! Xtest
     94  normal dd
     95  $
     96  put
     97  normal kkrXoxxx
     98  w! Xtest2
     99  file Nop
    100  normal ggoyyyjjjozzzz
    101  set foldmethod=marker foldcolumn=4
    102  call assert_equal(0, &diff)
    103  call assert_equal('marker', &foldmethod)
    104  call assert_equal('4', &foldcolumn)
    105  call assert_equal(0, &scrollbind)
    106  call assert_equal(0, &cursorbind)
    107  call assert_equal(1, &wrap)
    108 
    109  vert diffsplit Xtest
    110  vert diffsplit Xtest2
    111  call assert_equal(1, &diff)
    112  call assert_equal('diff', &foldmethod)
    113  call assert_equal('2', &foldcolumn)
    114  call assert_equal(1, &scrollbind)
    115  call assert_equal(1, &cursorbind)
    116  call assert_equal(0, &wrap)
    117 
    118  let diff_fdm = &fdm
    119  let diff_fdc = &fdc
    120  " repeat entering diff mode here to see if this saves the wrong settings
    121  diffthis
    122  " jump to second window for a moment to have filler line appear at start of
    123  " first window
    124  wincmd w
    125  normal gg
    126  wincmd p
    127  normal gg
    128  call assert_equal(2, winline())
    129  normal j
    130  call assert_equal(4, winline())
    131  normal j
    132  call assert_equal(5, winline())
    133  normal j
    134  call assert_equal(6, winline())
    135  normal j
    136  call assert_equal(8, winline())
    137  normal j
    138  call assert_equal(9, winline())
    139 
    140  wincmd w
    141  normal gg
    142  call assert_equal(1, winline())
    143  normal j
    144  call assert_equal(2, winline())
    145  normal j
    146  call assert_equal(4, winline())
    147  normal j
    148  call assert_equal(5, winline())
    149  normal j
    150  call assert_equal(8, winline())
    151 
    152  wincmd w
    153  normal gg
    154  call assert_equal(2, winline())
    155  normal j
    156  call assert_equal(3, winline())
    157  normal j
    158  call assert_equal(4, winline())
    159  normal j
    160  call assert_equal(5, winline())
    161  normal j
    162  call assert_equal(6, winline())
    163  normal j
    164  call assert_equal(7, winline())
    165  normal j
    166  call assert_equal(8, winline())
    167 
    168  " Test diffoff
    169  diffoff!
    170  1wincmd w
    171  let &diff = 1
    172  let &fdm = diff_fdm
    173  let &fdc = diff_fdc
    174  4wincmd w
    175  diffoff!
    176  1wincmd w
    177  call assert_equal(0, &diff)
    178  call assert_equal('marker', &foldmethod)
    179  call assert_equal('4', &foldcolumn)
    180  call assert_equal(0, &scrollbind)
    181  call assert_equal(0, &cursorbind)
    182  call assert_equal(1, &wrap)
    183 
    184  wincmd w
    185  call assert_equal(0, &diff)
    186  call assert_equal('marker', &foldmethod)
    187  call assert_equal('4', &foldcolumn)
    188  call assert_equal(0, &scrollbind)
    189  call assert_equal(0, &cursorbind)
    190  call assert_equal(1, &wrap)
    191 
    192  wincmd w
    193  call assert_equal(0, &diff)
    194  call assert_equal('marker', &foldmethod)
    195  call assert_equal('4', &foldcolumn)
    196  call assert_equal(0, &scrollbind)
    197  call assert_equal(0, &cursorbind)
    198  call assert_equal(1, &wrap)
    199 
    200  call delete('Xtest')
    201  call delete('Xtest2')
    202  windo bw!
    203 endfunc
    204 
    205 func Test_filler_lines()
    206  " Test that diffing shows correct filler lines
    207  enew!
    208  put =range(4,10)
    209  1d _
    210  vnew
    211  put =range(1,10)
    212  1d _
    213  windo diffthis
    214  wincmd h
    215  call assert_equal(1, line('w0'))
    216  unlet! diff_fdm diff_fdc
    217  windo diffoff
    218  bwipe!
    219  enew!
    220 endfunc
    221 
    222 func Test_diffget_diffput()
    223  enew!
    224  let l = range(50)
    225  call setline(1, l)
    226  call assert_fails('diffget', 'E99:')
    227  diffthis
    228  call assert_fails('diffget', 'E100:')
    229  new
    230  let l[10] = 'one'
    231  let l[20] = 'two'
    232  let l[30] = 'three'
    233  let l[40] = 'four'
    234  call setline(1, l)
    235  diffthis
    236  call assert_equal('one', getline(11))
    237  11diffget
    238  call assert_equal('10', getline(11))
    239  21diffput
    240  wincmd w
    241  call assert_equal('two', getline(21))
    242  normal 31Gdo
    243  call assert_equal('three', getline(31))
    244  call assert_equal('40', getline(41))
    245  normal 41Gdp
    246  wincmd w
    247  call assert_equal('40', getline(41))
    248  new
    249  diffthis
    250  call assert_fails('diffget', 'E101:')
    251 
    252  windo diffoff
    253  %bwipe!
    254 endfunc
    255 
    256 " Test putting two changes from one buffer to another
    257 func Test_diffput_two()
    258  new a
    259  let win_a = win_getid()
    260  call setline(1, range(1, 10))
    261  diffthis
    262  new b
    263  let win_b = win_getid()
    264  call setline(1, range(1, 10))
    265  8del
    266  5del
    267  diffthis
    268  call win_gotoid(win_a)
    269  %diffput
    270  call win_gotoid(win_b)
    271  call assert_equal(map(range(1, 10), 'string(v:val)'), getline(1, '$'))
    272  bwipe! a
    273  bwipe! b
    274 endfunc
    275 
    276 " Test for :diffget/:diffput with a range that is inside a diff chunk
    277 func Test_diffget_diffput_range()
    278  call setline(1, range(1, 10))
    279  new
    280  call setline(1, range(11, 20))
    281  windo diffthis
    282  3,5diffget
    283  call assert_equal(['13', '14', '15'], getline(3, 5))
    284  call setline(1, range(1, 10))
    285  4,8diffput
    286  wincmd p
    287  call assert_equal(['13', '4', '5', '6', '7', '8', '19'], getline(3, 9))
    288  %bw!
    289 endfunc
    290 
    291 " Test :diffget/:diffput handling of added/deleted lines
    292 func Test_diffget_diffput_deleted_lines()
    293  call setline(1, ['2','4','6'])
    294  diffthis
    295  new
    296  call setline(1, range(1,7))
    297  diffthis
    298  wincmd w
    299 
    300  3,3diffget " get nothing
    301  call assert_equal(['2', '4', '6'], getline(1, '$'))
    302  3,4diffget " get the last insertion past the end of file
    303  call assert_equal(['2', '4', '6', '7'], getline(1, '$'))
    304  0,1diffget " get the first insertion above first line
    305  call assert_equal(['1', '2', '4', '6', '7'], getline(1, '$'))
    306 
    307  " When using non-range diffget on the last line, it should get the
    308  " change above or at the line as usual, but if the only change is below the
    309  " last line, diffget should get that instead.
    310  1,$delete
    311  call setline(1, ['2','4','6'])
    312  diffupdate
    313  norm Gdo
    314  call assert_equal(['2', '4', '5', '6'], getline(1, '$'))
    315  norm Gdo
    316  call assert_equal(['2', '4', '5', '6', '7'], getline(1, '$'))
    317 
    318  " Test non-range diffput on last line with the same logic
    319  1,$delete
    320  call setline(1, ['2','4','6'])
    321  diffupdate
    322  norm Gdp
    323  wincmd w
    324  call assert_equal(['1', '2', '3', '4', '6', '7'], getline(1, '$'))
    325  wincmd w
    326  norm Gdp
    327  wincmd w
    328  call assert_equal(['1', '2', '3', '4', '6'], getline(1, '$'))
    329  call setline(1, range(1,7))
    330  diffupdate
    331  wincmd w
    332 
    333  " Test that 0,$+1 will get/put all changes from/to the other buffer
    334  1,$delete
    335  call setline(1, ['2','4','6'])
    336  diffupdate
    337  0,$+1diffget
    338  call assert_equal(['1', '2', '3', '4', '5', '6', '7'], getline(1, '$'))
    339  1,$delete
    340  call setline(1, ['2','4','6'])
    341  diffupdate
    342  0,$+1diffput
    343  wincmd w
    344  call assert_equal(['2', '4', '6'], getline(1, '$'))
    345  %bw!
    346 endfunc
    347 
    348 " Test for :diffget/:diffput with an empty buffer and a non-empty buffer
    349 func Test_diffget_diffput_empty_buffer()
    350  %d _
    351  new
    352  call setline(1, 'one')
    353  windo diffthis
    354  diffget
    355  call assert_equal(['one'], getline(1, '$'))
    356  %d _
    357  diffput
    358  wincmd p
    359  call assert_equal([''], getline(1, '$'))
    360  %bw!
    361 endfunc
    362 
    363 " :diffput and :diffget completes names of buffers which
    364 " are in diff mode and which are different than current buffer.
    365 " No completion when the current window is not in diff mode.
    366 func Test_diffget_diffput_completion()
    367  e            Xdiff1 | diffthis
    368  botright new Xdiff2
    369  botright new Xdiff3 | split | diffthis
    370  botright new Xdiff4 | diffthis
    371 
    372  wincmd t
    373  call assert_equal('Xdiff1', bufname('%'))
    374  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
    375  call assert_equal('"diffput Xdiff3 Xdiff4', @:)
    376  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
    377  call assert_equal('"diffget Xdiff3 Xdiff4', @:)
    378  call assert_equal(['Xdiff3', 'Xdiff4'], getcompletion('', 'diff_buffer'))
    379 
    380  " Xdiff2 is not in diff mode, so no completion for :diffput, :diffget
    381  wincmd j
    382  call assert_equal('Xdiff2', bufname('%'))
    383  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
    384  call assert_equal('"diffput ', @:)
    385  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
    386  call assert_equal('"diffget ', @:)
    387  call assert_equal([], getcompletion('', 'diff_buffer'))
    388 
    389  " Xdiff3 is split in 2 windows, only the top one is in diff mode.
    390  " So completion of :diffput :diffget only happens in the top window.
    391  wincmd j
    392  call assert_equal('Xdiff3', bufname('%'))
    393  call assert_equal(1, &diff)
    394  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
    395  call assert_equal('"diffput Xdiff1 Xdiff4', @:)
    396  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
    397  call assert_equal('"diffget Xdiff1 Xdiff4', @:)
    398  call assert_equal(['Xdiff1', 'Xdiff4'], getcompletion('', 'diff_buffer'))
    399 
    400  wincmd j
    401  call assert_equal('Xdiff3', bufname('%'))
    402  call assert_equal(0, &diff)
    403  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
    404  call assert_equal('"diffput ', @:)
    405  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
    406  call assert_equal('"diffget ', @:)
    407  call assert_equal([], getcompletion('', 'diff_buffer'))
    408 
    409  wincmd j
    410  call assert_equal('Xdiff4', bufname('%'))
    411  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
    412  call assert_equal('"diffput Xdiff1 Xdiff3', @:)
    413  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
    414  call assert_equal('"diffget Xdiff1 Xdiff3', @:)
    415  call assert_equal(['Xdiff1', 'Xdiff3'], getcompletion('', 'diff_buffer'))
    416 
    417  %bwipe
    418 endfunc
    419 
    420 func Test_dp_do_buffer()
    421  e! one
    422  let bn1=bufnr('%')
    423  let l = range(60)
    424  call setline(1, l)
    425  diffthis
    426 
    427  new two
    428  let l[10] = 'one'
    429  let l[20] = 'two'
    430  let l[30] = 'three'
    431  let l[40] = 'four'
    432  let l[50] = 'five'
    433  call setline(1, l)
    434  diffthis
    435 
    436  " dp and do with invalid buffer number.
    437  11
    438  call assert_fails('norm 99999dp', 'E102:')
    439  call assert_fails('norm 99999do', 'E102:')
    440  call assert_fails('diffput non_existing_buffer', 'E94:')
    441  call assert_fails('diffget non_existing_buffer', 'E94:')
    442 
    443  " dp and do with valid buffer number.
    444  call assert_equal('one', getline('.'))
    445  exe 'norm ' . bn1 . 'do'
    446  call assert_equal('10', getline('.'))
    447  21
    448  call assert_equal('two', getline('.'))
    449  diffget one
    450  call assert_equal('20', getline('.'))
    451 
    452  31
    453  exe 'norm ' . bn1 . 'dp'
    454  41
    455  diffput one
    456  wincmd w
    457  31
    458  call assert_equal('three', getline('.'))
    459  41
    460  call assert_equal('four', getline('.'))
    461 
    462  " dp and do with buffer number which is not in diff mode.
    463  new not_in_diff_mode
    464  let bn3=bufnr('%')
    465  wincmd w
    466  51
    467  call assert_fails('exe "norm" . bn3 . "dp"', 'E103:')
    468  call assert_fails('exe "norm" . bn3 . "do"', 'E103:')
    469  call assert_fails('diffput not_in_diff_mode', 'E94:')
    470  call assert_fails('diffget not_in_diff_mode', 'E94:')
    471 
    472  windo diffoff
    473  %bwipe!
    474 endfunc
    475 
    476 func Test_do_lastline()
    477  e! one
    478  call setline(1, ['1','2','3','4','5','6'])
    479  diffthis
    480 
    481  new two
    482  call setline(1, ['2','4','5'])
    483  diffthis
    484 
    485  1
    486  norm dp]c
    487  norm dp]c
    488  wincmd w
    489  call assert_equal(4, line('$'))
    490  norm G
    491  norm do
    492  call assert_equal(3, line('$'))
    493 
    494  windo diffoff
    495  %bwipe!
    496 endfunc
    497 
    498 func Test_diffoff()
    499  enew!
    500  call setline(1, ['Two', 'Three'])
    501  redraw
    502  let normattr = screenattr(1, 1)
    503  diffthis
    504  botright vert new
    505  call setline(1, ['One', '', 'Two', 'Three'])
    506  diffthis
    507  redraw
    508  call assert_notequal(normattr, 1->screenattr(1))
    509  diffoff!
    510  redraw
    511  call assert_equal(normattr, screenattr(1, 1))
    512  bwipe!
    513  bwipe!
    514 endfunc
    515 
    516 func Common_icase_test()
    517  edit one
    518  call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#vϵ', 'Si⃗x', 'Se⃗ve⃗n'])
    519  redraw
    520  let normattr = screenattr(1, 1)
    521  diffthis
    522 
    523  botright vert new two
    524  call setline(1, ['one', 'TWO', 'Three ', 'Four', 'fI=VΕ', 'SI⃗x', 'SEvE⃗n'])
    525  diffthis
    526 
    527  redraw
    528  call assert_equal(normattr, screenattr(1, 1))
    529  call assert_equal(normattr, screenattr(2, 1))
    530  call assert_notequal(normattr, screenattr(3, 1))
    531  call assert_equal(normattr, screenattr(4, 1))
    532  call assert_equal(normattr, screenattr(6, 2))
    533  call assert_notequal(normattr, screenattr(7, 2))
    534 
    535  let dtextattr = screenattr(5, 3)
    536  call assert_notequal(dtextattr, screenattr(5, 1))
    537  call assert_notequal(dtextattr, screenattr(5, 5))
    538  call assert_notequal(dtextattr, screenattr(7, 4))
    539 
    540  diffoff!
    541  %bwipe!
    542 endfunc
    543 
    544 func Test_diffopt_icase()
    545  set diffopt=icase,foldcolumn:0
    546  call Common_icase_test()
    547  set diffopt&
    548 endfunc
    549 
    550 func Test_diffopt_icase_internal()
    551  set diffopt=icase,foldcolumn:0,internal
    552  call Common_icase_test()
    553  set diffopt&
    554 endfunc
    555 
    556 func Common_iwhite_test()
    557  edit one
    558  " Difference in trailing spaces and amount of spaces should be ignored,
    559  " but not other space differences.
    560  call setline(1, ["One \t", 'Two', 'Three', 'one two', 'one two', 'Four'])
    561  redraw
    562  let normattr = screenattr(1, 1)
    563  diffthis
    564 
    565  botright vert new two
    566  call setline(1, ["One\t ", "Two\t ", 'Three', 'one   two', 'onetwo', ' Four'])
    567  diffthis
    568 
    569  redraw
    570  call assert_equal(normattr, screenattr(1, 1))
    571  call assert_equal(normattr, screenattr(2, 1))
    572  call assert_equal(normattr, screenattr(3, 1))
    573  call assert_equal(normattr, screenattr(4, 1))
    574  call assert_notequal(normattr, screenattr(5, 1))
    575  call assert_notequal(normattr, screenattr(6, 1))
    576 
    577  diffoff!
    578  %bwipe!
    579 endfunc
    580 
    581 func Test_diffopt_iwhite()
    582  set diffopt=iwhite,foldcolumn:0
    583  call Common_iwhite_test()
    584  set diffopt&
    585 endfunc
    586 
    587 func Test_diffopt_iwhite_internal()
    588  set diffopt=internal,iwhite,foldcolumn:0
    589  call Common_iwhite_test()
    590  set diffopt&
    591 endfunc
    592 
    593 func Test_diffopt_context()
    594  enew!
    595  call setline(1, ['1', '2', '3', '4', '5', '6', '7'])
    596  diffthis
    597  new
    598  call setline(1, ['1', '2', '3', '4', '5x', '6', '7'])
    599  diffthis
    600 
    601  set diffopt=context:2
    602  call assert_equal('+--  2 lines: 1', foldtextresult(1))
    603  set diffopt=internal,context:2
    604  call assert_equal('+--  2 lines: 1', foldtextresult(1))
    605 
    606  set diffopt=context:1
    607  call assert_equal('+--  3 lines: 1', foldtextresult(1))
    608  set diffopt=internal,context:1
    609  call assert_equal('+--  3 lines: 1', foldtextresult(1))
    610 
    611  diffoff!
    612  %bwipe!
    613  set diffopt&
    614 endfunc
    615 
    616 func Test_diffopt_horizontal()
    617  set diffopt=internal,horizontal
    618  diffsplit
    619 
    620  call assert_equal(&columns, winwidth(1))
    621  call assert_equal(&columns, winwidth(2))
    622  call assert_equal(&lines, winheight(1) + winheight(2) + 3)
    623  call assert_inrange(0, 1, winheight(1) - winheight(2))
    624 
    625  set diffopt&
    626  diffoff!
    627  %bwipe
    628 endfunc
    629 
    630 func Test_diffopt_vertical()
    631  set diffopt=internal,vertical
    632  diffsplit
    633 
    634  call assert_equal(&lines - 2, winheight(1))
    635  call assert_equal(&lines - 2, winheight(2))
    636  call assert_equal(&columns, winwidth(1) + winwidth(2) + 1)
    637  call assert_inrange(0, 1, winwidth(1) - winwidth(2))
    638 
    639  set diffopt&
    640  diffoff!
    641  %bwipe
    642 endfunc
    643 
    644 func Test_diffopt_hiddenoff()
    645  set diffopt=internal,filler,foldcolumn:0,hiddenoff
    646  e! one
    647  call setline(1, ['Two', 'Three'])
    648  redraw
    649  let normattr = screenattr(1, 1)
    650  diffthis
    651  botright vert new two
    652  call setline(1, ['One', 'Four'])
    653  diffthis
    654  redraw
    655  call assert_notequal(normattr, screenattr(1, 1))
    656  set hidden
    657  close
    658  redraw
    659  " should not diffing with hidden buffer two while 'hiddenoff' is enabled
    660  call assert_equal(normattr, screenattr(1, 1))
    661 
    662  bwipe!
    663  bwipe!
    664  set hidden& diffopt&
    665 endfunc
    666 
    667 func Test_diffoff_hidden()
    668  set diffopt=internal,filler,foldcolumn:0
    669  e! one
    670  call setline(1, ['Two', 'Three'])
    671  redraw
    672  let normattr = screenattr(1, 1)
    673  diffthis
    674  botright vert new two
    675  call setline(1, ['One', 'Four'])
    676  diffthis
    677  redraw
    678  call assert_notequal(normattr, screenattr(1, 1))
    679  set hidden
    680  close
    681  redraw
    682  " diffing with hidden buffer two
    683  call assert_notequal(normattr, screenattr(1, 1))
    684  diffoff
    685  redraw
    686  call assert_equal(normattr, screenattr(1, 1))
    687  diffthis
    688  redraw
    689  " still diffing with hidden buffer two
    690  call assert_notequal(normattr, screenattr(1, 1))
    691  diffoff!
    692  redraw
    693  call assert_equal(normattr, screenattr(1, 1))
    694  diffthis
    695  redraw
    696  " no longer diffing with hidden buffer two
    697  call assert_equal(normattr, screenattr(1, 1))
    698 
    699  bwipe!
    700  bwipe!
    701  set hidden& diffopt&
    702 endfunc
    703 
    704 func Test_setting_cursor()
    705  new Xtest1
    706  put =range(1,90)
    707  wq
    708  new Xtest2
    709  put =range(1,100)
    710  wq
    711 
    712  tabe Xtest2
    713  $
    714  diffsp Xtest1
    715  tabclose
    716 
    717  call delete('Xtest1')
    718  call delete('Xtest2')
    719 endfunc
    720 
    721 func Test_diff_move_to()
    722  new
    723  call setline(1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    724  diffthis
    725  vnew
    726  call setline(1, [1, '2x', 3, 4, 4, 5, '6x', 7, '8x', 9, '10x'])
    727  diffthis
    728  norm ]c
    729  call assert_equal(2, line('.'))
    730  norm 3]c
    731  call assert_equal(9, line('.'))
    732  norm 10]c
    733  call assert_equal(11, line('.'))
    734  norm [c
    735  call assert_equal(9, line('.'))
    736  norm 2[c
    737  call assert_equal(5, line('.'))
    738  norm 10[c
    739  call assert_equal(2, line('.'))
    740  %bwipe!
    741 endfunc
    742 
    743 func Test_diffexpr()
    744  CheckExecutable diff
    745 
    746  func DiffExpr()
    747    " Prepend some text to check diff type detection
    748    call writefile(['warning', '  message'], v:fname_out)
    749    silent exe '!diff ' . v:fname_in . ' ' . v:fname_new . '>>' . v:fname_out
    750  endfunc
    751  set diffexpr=DiffExpr()
    752  set diffopt=foldcolumn:0
    753 
    754  enew!
    755  call setline(1, ['one', 'two', 'three'])
    756  redraw
    757  let normattr = screenattr(1, 1)
    758  diffthis
    759 
    760  botright vert new
    761  call setline(1, ['one', 'two', 'three.'])
    762  diffthis
    763 
    764  redraw
    765  call assert_equal(normattr, screenattr(1, 1))
    766  call assert_equal(normattr, screenattr(2, 1))
    767  call assert_notequal(normattr, screenattr(3, 1))
    768  diffoff!
    769 
    770  " Try using a non-existing function for 'diffexpr'.
    771  set diffexpr=NewDiffFunc()
    772  call assert_fails('windo diffthis', ['E117:', 'E97:'])
    773  diffoff!
    774 
    775  " Using a script-local function
    776  func s:NewDiffExpr()
    777  endfunc
    778  set diffexpr=s:NewDiffExpr()
    779  call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
    780  set diffexpr=<SID>NewDiffExpr()
    781  call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
    782 
    783  %bwipe!
    784  set diffexpr& diffopt&
    785  delfunc DiffExpr
    786  delfunc s:NewDiffExpr
    787 endfunc
    788 
    789 func Test_diffpatch()
    790  " The patch program on MS-Windows may fail or hang.
    791  CheckExecutable patch
    792  CheckUnix
    793  new
    794  insert
    795 ***************
    796 *** 1,3 ****
    797  1
    798 ! 2
    799  3
    800 --- 1,4 ----
    801  1
    802 ! 2x
    803  3
    804 + 4
    805 .
    806  saveas! Xpatch
    807  bwipe!
    808  new
    809  call assert_fails('diffpatch Xpatch', 'E816:')
    810 
    811  for name in ['Xpatch', 'Xpatch$HOME', 'Xpa''tch']
    812    call setline(1, ['1', '2', '3'])
    813    if name != 'Xpatch'
    814      call rename('Xpatch', name)
    815    endif
    816    exe 'diffpatch ' . escape(name, '$')
    817    call assert_equal(['1', '2x', '3', '4'], getline(1, '$'))
    818    if name != 'Xpatch'
    819      call rename(name, 'Xpatch')
    820    endif
    821    bwipe!
    822  endfor
    823 
    824  call delete('Xpatch')
    825  bwipe!
    826 endfunc
    827 
    828 func Test_diff_too_many_buffers()
    829  for i in range(1, 8)
    830    exe "new Xtest" . i
    831    diffthis
    832  endfor
    833  new Xtest9
    834  call assert_fails('diffthis', 'E96:')
    835  %bwipe!
    836 endfunc
    837 
    838 func Test_diff_nomodifiable()
    839  new
    840  call setline(1, [1, 2, 3, 4])
    841  setl nomodifiable
    842  diffthis
    843  vnew
    844  call setline(1, ['1x', 2, 3, 3, 4])
    845  diffthis
    846  call assert_fails('norm dp', 'E793:')
    847  setl nomodifiable
    848  call assert_fails('norm do', 'E21:')
    849  %bwipe!
    850 endfunc
    851 
    852 func Test_diff_hlID()
    853  set diffopt=internal,filler
    854  new
    855  call setline(1, [1, 2, 3, 'Yz', 'a dxxg',])
    856  diffthis
    857  vnew
    858  call setline(1, ['1x', 2, 'x', 3, 'yx', 'abc defg'])
    859  diffthis
    860  redraw
    861 
    862  call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("")
    863 
    864  call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange")
    865  call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText")
    866  call diff_hlID(2, 1)->synIDattr("name")->assert_equal("")
    867  call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd")
    868  eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("")
    869  call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
    870  call diff_hlID(5, 2)->synIDattr("name")->assert_equal("DiffText")
    871 
    872  set diffopt+=icase " test that caching is invalidated by diffopt change
    873  call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffChange")
    874  set diffopt-=icase
    875  call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
    876 
    877  call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
    878  call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffText")
    879  call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffText")
    880  call diff_hlID(6, 7)->synIDattr("name")->assert_equal("DiffText")
    881  call diff_hlID(6, 8)->synIDattr("name")->assert_equal("DiffChange")
    882  set diffopt+=inline:char
    883  call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
    884  call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffTextAdd")
    885  call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffChange")
    886  call diff_hlID(6, 7)->synIDattr("name")->assert_equal("DiffText")
    887  call diff_hlID(6, 8)->synIDattr("name")->assert_equal("DiffChange")
    888  set diffopt-=inline:char
    889 
    890  wincmd w
    891  call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange")
    892  call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "")
    893  call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "")
    894 
    895  %bwipe!
    896  set diffopt&
    897 endfunc
    898 
    899 func Test_diff_filler()
    900  new
    901  call setline(1, [1, 2, 3, 'x', 4])
    902  diffthis
    903  vnew
    904  call setline(1, [1, 2, 'y', 'y', 3, 4])
    905  diffthis
    906  redraw
    907 
    908  call assert_equal([0, 0, 0, 0, 0, 0, 0, 1, 0], map(range(-1, 7), 'v:val->diff_filler()'))
    909  wincmd w
    910  call assert_equal([0, 0, 0, 0, 2, 0, 0, 0], map(range(-1, 6), 'diff_filler(v:val)'))
    911 
    912  %bwipe!
    913 endfunc
    914 
    915 func Test_diff_lastline()
    916  enew!
    917  only!
    918  call setline(1, ['This is a ', 'line with five ', 'rows'])
    919  diffthis
    920  botright vert new
    921  call setline(1, ['This is', 'a line with ', 'four rows'])
    922  diffthis
    923  1
    924  call feedkeys("Je a\<CR>", 'tx')
    925  call feedkeys("Je a\<CR>", 'tx')
    926  let w1lines = winline()
    927  wincmd w
    928  $
    929  let w2lines = winline()
    930  call assert_equal(w2lines, w1lines)
    931  bwipe!
    932  bwipe!
    933 endfunc
    934 
    935 func WriteDiffFiles(buf, list1, list2)
    936  call writefile(a:list1, 'Xdifile1')
    937  call writefile(a:list2, 'Xdifile2')
    938  if a:buf
    939    call term_sendkeys(a:buf, ":checktime\<CR>")
    940  endif
    941 endfunc
    942 
    943 func WriteDiffFiles3(buf, list1, list2, list3)
    944  call writefile(a:list1, 'Xdifile1')
    945  call writefile(a:list2, 'Xdifile2')
    946  call writefile(a:list3, 'Xdifile3')
    947  if a:buf
    948    call term_sendkeys(a:buf, ":checktime\<CR>")
    949  endif
    950 endfunc
    951 
    952 " Verify a screendump with both the internal and external diff.
    953 func VerifyBoth(buf, dumpfile, extra)
    954  CheckScreendump
    955 
    956  " trailing : for leaving the cursor on the command line
    957  for cmd in [":set diffopt=filler" . a:extra . "\<CR>:", ":set diffopt+=internal\<CR>:"]
    958    call term_sendkeys(a:buf, cmd)
    959    if VerifyScreenDump(a:buf, a:dumpfile, {}, cmd =~ 'internal' ? 'internal' : 'external')
    960      break " don't let the next iteration overwrite the "failed" file.
    961      " don't let the next iteration overwrite the "failed" file.
    962      return
    963    endif
    964  endfor
    965 
    966  " also test unified diff
    967  call term_sendkeys(a:buf, ":call SetupUnified()\<CR>:")
    968  call term_sendkeys(a:buf, ":redraw!\<CR>:")
    969  call VerifyScreenDump(a:buf, a:dumpfile, {}, 'unified')
    970  call term_sendkeys(a:buf, ":call StopUnified()\<CR>:")
    971 endfunc
    972 
    973 " Verify a screendump with the internal diff only.
    974 func VerifyInternal(buf, dumpfile, extra)
    975  CheckScreendump
    976 
    977  call term_sendkeys(a:buf, ":diffupdate!\<CR>")
    978  " trailing : for leaving the cursor on the command line
    979  call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:")
    980  call VerifyScreenDump(a:buf, a:dumpfile, {})
    981 endfunc
    982 
    983 func Test_diff_screen()
    984  let g:test_is_flaky = 1
    985  CheckScreendump
    986  CheckFeature menu
    987 
    988  let lines =<< trim END
    989      func UnifiedDiffExpr()
    990        " Prepend some text to check diff type detection
    991        call writefile(['warning', '  message'], v:fname_out)
    992        silent exe '!diff -U0 ' .. v:fname_in .. ' ' .. v:fname_new .. '>>' .. v:fname_out
    993      endfunc
    994      func SetupUnified()
    995        set diffexpr=UnifiedDiffExpr()
    996        diffupdate
    997      endfunc
    998      func StopUnified()
    999        set diffexpr=
   1000      endfunc
   1001  END
   1002  call writefile(lines, 'XdiffSetup', 'D')
   1003 
   1004  " clean up already existing swap files, just in case
   1005  call delete('.Xdifile1.swp')
   1006  call delete('.Xdifile2.swp')
   1007 
   1008  " Test 1: Add a line in beginning of file 2
   1009  call WriteDiffFiles(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
   1010  let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
   1011  " Set autoread mode, so that Vim won't complain once we re-write the test
   1012  " files
   1013  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   1014 
   1015  call VerifyBoth(buf, 'Test_diff_01', '')
   1016 
   1017  " Test 2: Add a line in beginning of file 1
   1018  call WriteDiffFiles(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
   1019  call VerifyBoth(buf, 'Test_diff_02', '')
   1020 
   1021  " Test 3: Add a line at the end of file 2
   1022  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
   1023  call VerifyBoth(buf, 'Test_diff_03', '')
   1024 
   1025  " Test 4: Add a line at the end of file 1
   1026  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
   1027  call VerifyBoth(buf, 'Test_diff_04', '')
   1028 
   1029  " Test 5: Add a line in the middle of file 2, remove on at the end of file 1
   1030  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10])
   1031  call VerifyBoth(buf, 'Test_diff_05', '')
   1032 
   1033  " Test 6: Add a line in the middle of file 1, remove on at the end of file 2
   1034  call WriteDiffFiles(buf, [1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
   1035  call VerifyBoth(buf, 'Test_diff_06', '')
   1036 
   1037  " Variants on test 6 with different context settings
   1038  call term_sendkeys(buf, ":set diffopt+=context:2\<cr>")
   1039  call VerifyScreenDump(buf, 'Test_diff_06.2', {})
   1040  call term_sendkeys(buf, ":set diffopt-=context:2\<cr>")
   1041  call term_sendkeys(buf, ":set diffopt+=context:1\<cr>")
   1042  call VerifyScreenDump(buf, 'Test_diff_06.1', {})
   1043  call term_sendkeys(buf, ":set diffopt-=context:1\<cr>")
   1044  call term_sendkeys(buf, ":set diffopt+=context:0\<cr>")
   1045  call VerifyScreenDump(buf, 'Test_diff_06.0', {})
   1046  call term_sendkeys(buf, ":set diffopt-=context:0\<cr>")
   1047 
   1048  " Test 7 - 9: Test normal/patience/histogram diff algorithm
   1049  call WriteDiffFiles(buf, ['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
   1050      \ '    int i;', '    for(i = 0; i < 10; i++)', '    {', '        printf("Your answer is: ");',
   1051      \ '        printf("%d\n", foo);', '    }', '}', '', 'int fact(int n)', '{', '    if(n > 1)', '    {',
   1052      \ '        return fact(n-1) * n;', '    }', '    return 1;', '}', '', 'int main(int argc, char **argv)',
   1053      \ '{', '    frobnitz(fact(10));', '}'],
   1054      \ ['#include <stdio.h>', '', 'int fib(int n)', '{', '    if(n > 2)', '    {',
   1055      \ '        return fib(n-1) + fib(n-2);', '    }', '    return 1;', '}', '', '// Frobs foo heartily',
   1056      \ 'int frobnitz(int foo)', '{', '    int i;', '    for(i = 0; i < 10; i++)', '    {',
   1057      \ '        printf("%d\n", foo);', '    }', '}', '',
   1058      \ 'int main(int argc, char **argv)', '{', '    frobnitz(fib(10));', '}'])
   1059  call term_sendkeys(buf, ":diffupdate!\<cr>")
   1060  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
   1061  call VerifyScreenDump(buf, 'Test_diff_07', {})
   1062 
   1063  call term_sendkeys(buf, ":set diffopt+=algorithm:patience\<cr>")
   1064  call VerifyScreenDump(buf, 'Test_diff_08', {})
   1065 
   1066  call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>")
   1067  call VerifyScreenDump(buf, 'Test_diff_09', {})
   1068 
   1069  " Test 10-11: with/without indent-heuristic
   1070  call term_sendkeys(buf, ":set diffopt&vim\<cr>")
   1071  call WriteDiffFiles(buf, ['', '  def finalize(values)', '', '    values.each do |v|', '      v.finalize', '    end'],
   1072      \ ['', '  def finalize(values)', '', '    values.each do |v|', '      v.prepare', '    end', '',
   1073      \ '    values.each do |v|', '      v.finalize', '    end'])
   1074  call term_sendkeys(buf, ":diffupdate!\<cr>")
   1075  call term_sendkeys(buf, ":set diffopt+=internal\<cr>:\<cr>")
   1076  call VerifyScreenDump(buf, 'Test_diff_11', {})
   1077 
   1078  " Leave trailing : at commandline!
   1079  call term_sendkeys(buf, ":set diffopt-=indent-heuristic\<cr>:\<cr>")
   1080  call VerifyScreenDump(buf, 'Test_diff_10', {}, 'one')
   1081  " shouldn't matter, if indent-algorithm comes before or after the algorithm
   1082  call term_sendkeys(buf, ":set diffopt&\<cr>")
   1083  call term_sendkeys(buf, ":set diffopt+=indent-heuristic,algorithm:patience\<cr>:\<cr>")
   1084  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'two')
   1085  call term_sendkeys(buf, ":set diffopt&\<cr>")
   1086  call term_sendkeys(buf, ":set diffopt+=algorithm:patience,indent-heuristic\<cr>:\<cr>")
   1087  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'three')
   1088 
   1089  " Test 12: diff the same file
   1090  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
   1091  call VerifyBoth(buf, 'Test_diff_12', '')
   1092 
   1093  " Test 13: diff an empty file
   1094  call WriteDiffFiles(buf, [], [])
   1095  call VerifyBoth(buf, 'Test_diff_13', '')
   1096 
   1097  " Test 14: test diffopt+=icase
   1098  call WriteDiffFiles(buf, ['a', 'b', 'cd'], ['A', 'b', 'cDe'])
   1099  call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase")
   1100 
   1101  " Test 15-16: test diffopt+=iwhite
   1102  call WriteDiffFiles(buf, ['int main()', '{', '   printf("Hello, World!");', '   return 0;', '}'],
   1103      \ ['int main()', '{', '   if (0)', '   {', '      printf("Hello, World!");', '      return 0;', '   }', '}'])
   1104  call term_sendkeys(buf, ":diffupdate!\<cr>")
   1105  call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>")
   1106  call VerifyScreenDump(buf, 'Test_diff_15', {})
   1107  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
   1108  call VerifyScreenDump(buf, 'Test_diff_16', {})
   1109 
   1110  " Test 17: test diffopt+=iblank
   1111  call WriteDiffFiles(buf, ['a', ' ', 'cd', 'ef', 'xxx'], ['a', 'cd', '', 'ef', 'yyy'])
   1112  call VerifyInternal(buf, 'Test_diff_17', " diffopt+=iblank")
   1113 
   1114  " Test 18: test diffopt+=iblank,iwhite / iwhiteall / iwhiteeol
   1115  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhite")
   1116  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteall")
   1117  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteeol")
   1118 
   1119  " Test 19: test diffopt+=iwhiteeol
   1120  call WriteDiffFiles(buf, ['a ', 'x', 'cd', 'ef', 'xx  xx', 'foo', 'bar'], ['a', 'x', 'c d', ' ef', 'xx xx', 'foo', '', 'bar'])
   1121  call VerifyInternal(buf, 'Test_diff_19', " diffopt+=iwhiteeol")
   1122 
   1123  " Test 20: test diffopt+=iwhiteall
   1124  call VerifyInternal(buf, 'Test_diff_20', " diffopt+=iwhiteall")
   1125 
   1126  " Test 21: Delete all lines
   1127  call WriteDiffFiles(buf, [0], [])
   1128  call VerifyBoth(buf, "Test_diff_21", "")
   1129 
   1130  " Test 22: Add line to empty file
   1131  call WriteDiffFiles(buf, [], [0])
   1132  call VerifyBoth(buf, "Test_diff_22", "")
   1133 
   1134  call WriteDiffFiles(buf, ['?a', '?b', '?c'], ['!b'])
   1135  call VerifyInternal(buf, 'Test_diff_23', " diffopt+=linematch:30")
   1136 
   1137  call WriteDiffFiles(buf, ['',
   1138      \ 'common line',
   1139      \ 'common line',
   1140      \ '',
   1141      \ 'DEFabc',
   1142      \ 'xyz',
   1143      \ 'xyz',
   1144      \ 'xyz',
   1145      \ 'DEFabc',
   1146      \ 'DEFabc',
   1147      \ 'DEFabc',
   1148      \ 'common line',
   1149      \ 'common line',
   1150      \ 'DEF',
   1151      \ 'common line',
   1152      \ 'DEF',
   1153      \ 'something' ],
   1154      \ ['',
   1155      \ 'common line',
   1156      \ 'common line',
   1157      \ '',
   1158      \ 'ABCabc',
   1159      \ 'ABCabc',
   1160      \ 'ABCabc',
   1161      \ 'ABCabc',
   1162      \ 'common line',
   1163      \ 'common line',
   1164      \ 'common line',
   1165      \ 'something'])
   1166  call VerifyInternal(buf, 'Test_diff_24', " diffopt+=linematch:30")
   1167 
   1168 
   1169  " clean up
   1170  call StopVimInTerminal(buf)
   1171  call delete('Xdifile1')
   1172  call delete('Xdifile2')
   1173 endfunc
   1174 
   1175 func Test_diff_with_scroll_and_change()
   1176  CheckScreendump
   1177 
   1178  let lines =<< trim END
   1179 call setline(1, range(1, 15))
   1180 vnew
   1181 call setline(1, range(9, 15))
   1182 windo diffthis
   1183 wincmd h
   1184 exe "normal Gl5\<C-E>"
   1185  END
   1186  call writefile(lines, 'Xtest_scroll_change', 'D')
   1187  let buf = RunVimInTerminal('-S Xtest_scroll_change', {})
   1188 
   1189  call VerifyScreenDump(buf, 'Test_diff_scroll_change_01', {})
   1190 
   1191  call term_sendkeys(buf, "ax\<Esc>")
   1192  call VerifyScreenDump(buf, 'Test_diff_scroll_change_02', {})
   1193 
   1194  call term_sendkeys(buf, "\<C-W>lay\<Esc>")
   1195  call VerifyScreenDump(buf, 'Test_diff_scroll_change_03', {})
   1196 
   1197  " clean up
   1198  call StopVimInTerminal(buf)
   1199 endfunc
   1200 
   1201 func Test_diff_with_cursorline()
   1202  CheckScreendump
   1203 
   1204  call writefile([
   1205 \ 'hi CursorLine ctermbg=red ctermfg=white',
   1206 \ 'set cursorline',
   1207 \ 'call setline(1, ["foo","foo","foo","bar"])',
   1208 \ 'vnew',
   1209 \ 'call setline(1, ["bee","foo","foo","baz"])',
   1210 \ 'windo diffthis',
   1211 \ '2wincmd w',
   1212 \ ], 'Xtest_diff_cursorline', 'D')
   1213  let buf = RunVimInTerminal('-S Xtest_diff_cursorline', {})
   1214 
   1215  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_01', {})
   1216  call term_sendkeys(buf, "j")
   1217  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_02', {})
   1218  call term_sendkeys(buf, "j")
   1219  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_03', {})
   1220 
   1221  " clean up
   1222  call StopVimInTerminal(buf)
   1223 endfunc
   1224 
   1225 func Test_diff_with_cursorline_number()
   1226  CheckScreendump
   1227 
   1228  let lines =<< trim END
   1229      hi CursorLine ctermbg=red ctermfg=white
   1230      hi CursorLineNr ctermbg=white ctermfg=black cterm=underline
   1231      set cursorline number
   1232      call setline(1, ["baz", "foo", "foo", "bar"])
   1233      2
   1234      vnew
   1235      call setline(1, ["foo", "foo", "bar"])
   1236      windo diffthis
   1237      1wincmd w
   1238  END
   1239  call writefile(lines, 'Xtest_diff_cursorline_number', 'D')
   1240  let buf = RunVimInTerminal('-S Xtest_diff_cursorline_number', {})
   1241 
   1242  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_01', {})
   1243  call term_sendkeys(buf, ":set cursorlineopt=number\r")
   1244  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_02', {})
   1245 
   1246  " clean up
   1247  call StopVimInTerminal(buf)
   1248 endfunc
   1249 
   1250 func Test_diff_with_cursorline_breakindent()
   1251  CheckScreendump
   1252 
   1253  let lines =<< trim END
   1254    hi CursorLine ctermbg=red ctermfg=white
   1255    set noequalalways wrap diffopt=followwrap cursorline breakindent
   1256    50vnew
   1257    call setline(1, ['  ', '  ', '  ', '  '])
   1258    exe "norm! 20Afoo\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abar\<Esc>"
   1259    vnew
   1260    call setline(1, ['  ', '  ', '  ', '  '])
   1261    exe "norm! 20Abee\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abaz\<Esc>"
   1262    windo diffthis
   1263    2wincmd w
   1264  END
   1265  call writefile(lines, 'Xtest_diff_cursorline_breakindent', 'D')
   1266  let buf = RunVimInTerminal('-S Xtest_diff_cursorline_breakindent', {})
   1267 
   1268  call term_sendkeys(buf, "gg0")
   1269  call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_01', {})
   1270  call term_sendkeys(buf, "j")
   1271  call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_02', {})
   1272  call term_sendkeys(buf, "j")
   1273  call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_03', {})
   1274  call term_sendkeys(buf, "j")
   1275  call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_04', {})
   1276 
   1277  " clean up
   1278  call StopVimInTerminal(buf)
   1279 endfunc
   1280 
   1281 func Test_diff_breakindent_after_filler()
   1282  CheckScreendump
   1283 
   1284  let lines =<< trim END
   1285    set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0
   1286    call setline(1, ['a', '  ' .. repeat('c', 50)])
   1287    vnew
   1288    call setline(1, ['a', 'b', '  ' .. repeat('c', 50)])
   1289    windo diffthis
   1290    norm! G$
   1291  END
   1292  call writefile(lines, 'Xtest_diff_breakindent_after_filler', 'D')
   1293  let buf = RunVimInTerminal('-S Xtest_diff_breakindent_after_filler', #{rows: 8, cols: 45})
   1294  call VerifyScreenDump(buf, 'Test_diff_breakindent_after_filler', {})
   1295 
   1296  " clean up
   1297  call StopVimInTerminal(buf)
   1298 endfunc
   1299 
   1300 func Test_diff_with_syntax()
   1301  CheckScreendump
   1302 
   1303  let lines =<< trim END
   1304 void doNothing() {
   1305    int x = 0;
   1306    char *s = "hello";
   1307    return 5;
   1308 }
   1309  END
   1310  call writefile(lines, 'Xprogram1.c', 'D')
   1311  let lines =<< trim END
   1312 void doSomething() {
   1313    int x = 0;
   1314    char *s = "there";
   1315    return 5;
   1316 }
   1317  END
   1318  call writefile(lines, 'Xprogram2.c', 'D')
   1319 
   1320  let lines =<< trim END
   1321    set diffopt=internal,filler
   1322 edit Xprogram1.c
   1323 diffsplit Xprogram2.c
   1324  END
   1325  call writefile(lines, 'Xtest_diff_syntax', 'D')
   1326  let buf = RunVimInTerminal('-S Xtest_diff_syntax', {})
   1327 
   1328  call VerifyScreenDump(buf, 'Test_diff_syntax_1', {})
   1329 
   1330  " clean up
   1331  call StopVimInTerminal(buf)
   1332 endfunc
   1333 
   1334 func Test_diff_of_diff()
   1335  CheckScreendump
   1336  CheckFeature rightleft
   1337 
   1338  call writefile([
   1339 \ 'call setline(1, ["aa","bb","cc","@@ -3,2 +5,7 @@","dd","ee","ff"])',
   1340 \ 'vnew',
   1341 \ 'call setline(1, ["aa","bb","cc"])',
   1342 \ 'windo diffthis',
   1343 \ '1wincmd w',
   1344 \ 'setlocal number',
   1345 \ ], 'Xtest_diff_diff', 'D')
   1346  let buf = RunVimInTerminal('-S Xtest_diff_diff', {})
   1347 
   1348  call VerifyScreenDump(buf, 'Test_diff_of_diff_01', {})
   1349 
   1350  call term_sendkeys(buf, ":set rightleft\<cr>")
   1351  call VerifyScreenDump(buf, 'Test_diff_of_diff_02', {})
   1352 
   1353  " clean up
   1354  call StopVimInTerminal(buf)
   1355 endfunc
   1356 
   1357 func CloseoffSetup()
   1358  enew
   1359  call setline(1, ['one', 'two', 'three'])
   1360  diffthis
   1361  new
   1362  call setline(1, ['one', 'tow', 'three'])
   1363  diffthis
   1364  call assert_equal(1, &diff)
   1365  bw!
   1366 endfunc
   1367 
   1368 func Test_diff_closeoff()
   1369  " "closeoff" included by default: last diff win gets 'diff' reset'
   1370  call CloseoffSetup()
   1371  call assert_equal(0, &diff)
   1372  enew!
   1373 
   1374  " "closeoff" excluded: last diff win keeps 'diff' set'
   1375  set diffopt-=closeoff
   1376  call CloseoffSetup()
   1377  call assert_equal(1, &diff)
   1378  diffoff!
   1379  enew!
   1380 endfunc
   1381 
   1382 func Test_diff_followwrap()
   1383  new
   1384  set diffopt+=followwrap
   1385  set wrap
   1386  diffthis
   1387  call assert_equal(1, &wrap)
   1388  diffoff
   1389  set nowrap
   1390  diffthis
   1391  call assert_equal(0, &wrap)
   1392  diffoff
   1393  set diffopt&
   1394  bwipe!
   1395 endfunc
   1396 
   1397 func Test_diff_maintains_change_mark()
   1398  func DiffMaintainsChangeMark()
   1399    enew!
   1400    call setline(1, ['a', 'b', 'c', 'd'])
   1401    diffthis
   1402    new
   1403    call setline(1, ['a', 'b', 'c', 'e'])
   1404    " Set '[ and '] marks
   1405    2,3yank
   1406    call assert_equal([2, 3], [line("'["), line("']")])
   1407    " Verify they aren't affected by the implicit diff
   1408    diffthis
   1409    call assert_equal([2, 3], [line("'["), line("']")])
   1410    " Verify they aren't affected by an explicit diff
   1411    diffupdate
   1412    call assert_equal([2, 3], [line("'["), line("']")])
   1413    bwipe!
   1414    bwipe!
   1415  endfunc
   1416 
   1417  set diffopt-=internal
   1418  call DiffMaintainsChangeMark()
   1419  set diffopt+=internal
   1420  call DiffMaintainsChangeMark()
   1421 
   1422  set diffopt&
   1423  delfunc DiffMaintainsChangeMark
   1424 endfunc
   1425 
   1426 " Test for 'patchexpr'
   1427 func Test_patchexpr()
   1428  let g:patch_args = []
   1429  func TPatch()
   1430    call add(g:patch_args, readfile(v:fname_in))
   1431    call add(g:patch_args, readfile(v:fname_diff))
   1432    call writefile(['output file'], v:fname_out)
   1433  endfunc
   1434  set patchexpr=TPatch()
   1435 
   1436  call writefile(['input file'], 'Xinput', 'D')
   1437  call writefile(['diff file'], 'Xdiff', 'D')
   1438  %bwipe!
   1439  edit Xinput
   1440  diffpatch Xdiff
   1441  call assert_equal('output file', getline(1))
   1442  call assert_equal('Xinput.new', bufname())
   1443  call assert_equal(2, winnr('$'))
   1444  call assert_true(&diff)
   1445 
   1446  " Using a script-local function
   1447  func s:NewPatchExpr()
   1448  endfunc
   1449  set patchexpr=s:NewPatchExpr()
   1450  call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
   1451  set patchexpr=<SID>NewPatchExpr()
   1452  call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
   1453 
   1454  set patchexpr&
   1455  delfunc TPatch
   1456  delfunc s:NewPatchExpr
   1457  %bwipe!
   1458 endfunc
   1459 
   1460 func Test_diff_rnu()
   1461  CheckScreendump
   1462 
   1463  let content =<< trim END
   1464    set diffopt=internal,filler
   1465    call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
   1466    vnew
   1467    call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
   1468    windo diffthis
   1469    setlocal number rnu foldcolumn=0
   1470  END
   1471  call writefile(content, 'Xtest_diff_rnu', 'D')
   1472  let buf = RunVimInTerminal('-S Xtest_diff_rnu', {})
   1473 
   1474  call VerifyScreenDump(buf, 'Test_diff_rnu_01', {})
   1475 
   1476  call term_sendkeys(buf, "j")
   1477  call VerifyScreenDump(buf, 'Test_diff_rnu_02', {})
   1478  call term_sendkeys(buf, "j")
   1479  call VerifyScreenDump(buf, 'Test_diff_rnu_03', {})
   1480 
   1481  " clean up
   1482  call StopVimInTerminal(buf)
   1483 endfunc
   1484 
   1485 func Test_diff_multilineconceal()
   1486  new
   1487  diffthis
   1488 
   1489  new
   1490  call matchadd('Conceal', 'a\nb', 9, -1, {'conceal': 'Y'})
   1491  set cole=2 cocu=n
   1492  call setline(1, ["a", "b"])
   1493  diffthis
   1494  redraw
   1495 endfunc
   1496 
   1497 func Test_diff_and_scroll()
   1498  " this was causing an ml_get error
   1499  set ls=2
   1500  for i in range(winheight(0) * 2)
   1501    call setline(i, i < winheight(0) - 10 ? i : i + 10)
   1502  endfor
   1503  vnew
   1504  for i in range(winheight(0)*2 + 10)
   1505    call setline(i, i < winheight(0) - 10 ? 0 : i)
   1506  endfor
   1507  diffthis
   1508  wincmd p
   1509  diffthis
   1510  execute 'normal ' . winheight(0) . "\<C-d>"
   1511 
   1512  bwipe!
   1513  bwipe!
   1514  set ls&
   1515 endfunc
   1516 
   1517 func Test_diff_filler_cursorcolumn()
   1518  CheckScreendump
   1519 
   1520  let content =<< trim END
   1521    call setline(1, ['aa', 'bb', 'cc'])
   1522    vnew
   1523    call setline(1, ['aa', 'cc'])
   1524    windo diffthis
   1525    wincmd p
   1526    setlocal cursorcolumn foldcolumn=0
   1527    norm! gg0
   1528    redraw!
   1529  END
   1530  call writefile(content, 'Xtest_diff_cuc', 'D')
   1531  let buf = RunVimInTerminal('-S Xtest_diff_cuc', {})
   1532 
   1533  call VerifyScreenDump(buf, 'Test_diff_cuc_01', {})
   1534 
   1535  call term_sendkeys(buf, "l")
   1536  call term_sendkeys(buf, "\<C-l>")
   1537  call VerifyScreenDump(buf, 'Test_diff_cuc_02', {})
   1538  call term_sendkeys(buf, "0j")
   1539  call term_sendkeys(buf, "\<C-l>")
   1540  call VerifyScreenDump(buf, 'Test_diff_cuc_03', {})
   1541  call term_sendkeys(buf, "l")
   1542  call term_sendkeys(buf, "\<C-l>")
   1543  call VerifyScreenDump(buf, 'Test_diff_cuc_04', {})
   1544 
   1545  " clean up
   1546  call StopVimInTerminal(buf)
   1547 endfunc
   1548 
   1549 " Test for adding/removing lines inside diff chunks, between diff chunks
   1550 " and before diff chunks
   1551 func Test_diff_modify_chunks()
   1552  set diffopt=internal,filler
   1553  enew!
   1554  let w2_id = win_getid()
   1555  call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
   1556  new
   1557  let w1_id = win_getid()
   1558  call setline(1, ['a', '2', '3', 'd', 'e', 'f', '7', '8', 'i'])
   1559  windo diffthis
   1560 
   1561  " remove a line between two diff chunks and create a new diff chunk
   1562  call win_gotoid(w2_id)
   1563  5d
   1564  call win_gotoid(w1_id)
   1565  call diff_hlID(5, 1)->synIDattr('name')->assert_equal('DiffAdd')
   1566 
   1567  " add a line between two diff chunks
   1568  call win_gotoid(w2_id)
   1569  normal! 4Goe
   1570  call win_gotoid(w1_id)
   1571  call diff_hlID(4, 1)->synIDattr('name')->assert_equal('')
   1572  call diff_hlID(5, 1)->synIDattr('name')->assert_equal('')
   1573 
   1574  " remove all the lines in a diff chunk.
   1575  call win_gotoid(w2_id)
   1576  7,8d
   1577  call win_gotoid(w1_id)
   1578  let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
   1579  call assert_equal(['', 'DiffText', 'DiffText', '', '', '', 'DiffAdd',
   1580        \ 'DiffAdd', ''], hl)
   1581 
   1582  " remove lines from one diff chunk to just before the next diff chunk
   1583  call win_gotoid(w2_id)
   1584  call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
   1585  2,6d
   1586  call win_gotoid(w1_id)
   1587  let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
   1588  call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', 'DiffAdd',
   1589        \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
   1590 
   1591  " remove lines just before the top of a diff chunk
   1592  call win_gotoid(w2_id)
   1593  call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
   1594  5,6d
   1595  call win_gotoid(w1_id)
   1596  let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
   1597  call assert_equal(['', 'DiffText', 'DiffText', '', 'DiffText', 'DiffText',
   1598        \ 'DiffAdd', 'DiffAdd', ''], hl)
   1599 
   1600  " remove line after the end of a diff chunk
   1601  call win_gotoid(w2_id)
   1602  call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
   1603  4d
   1604  call win_gotoid(w1_id)
   1605  let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
   1606  call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', '', '', 'DiffText',
   1607        \ 'DiffText', ''], hl)
   1608 
   1609  " remove lines starting from the end of one diff chunk and ending inside
   1610  " another diff chunk
   1611  call win_gotoid(w2_id)
   1612  call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
   1613  4,7d
   1614  call win_gotoid(w1_id)
   1615  let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
   1616  call assert_equal(['', 'DiffText', 'DiffText', 'DiffText', 'DiffAdd',
   1617        \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
   1618 
   1619  " removing the only remaining diff chunk should make the files equal
   1620  call win_gotoid(w2_id)
   1621  call setline(1, ['a', '2', '3', 'x', 'd', 'e', 'f', 'x', '7', '8', 'i'])
   1622  8d
   1623  let hl = range(1, 10)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
   1624  call assert_equal(['', '', '', 'DiffAdd', '', '', '', '', '', ''], hl)
   1625  call win_gotoid(w2_id)
   1626  4d
   1627  call win_gotoid(w1_id)
   1628  let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
   1629  call assert_equal(['', '', '', '', '', '', '', '', ''], hl)
   1630 
   1631  %bw!
   1632  set diffopt&
   1633 endfunc
   1634 
   1635 func Test_diff_binary()
   1636  CheckScreendump
   1637 
   1638  let content =<< trim END
   1639    call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g'])
   1640    vnew
   1641    call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g'])
   1642    windo diffthis
   1643    wincmd p
   1644    norm! gg0
   1645    redraw!
   1646  END
   1647  call writefile(content, 'Xtest_diff_bin', 'D')
   1648  let buf = RunVimInTerminal('-S Xtest_diff_bin', {})
   1649 
   1650  " Test using internal diff
   1651  call VerifyScreenDump(buf, 'Test_diff_bin_01', {})
   1652 
   1653  " Test using internal diff and case folding
   1654  call term_sendkeys(buf, ":set diffopt+=icase\<cr>")
   1655  call term_sendkeys(buf, "\<C-l>")
   1656  call VerifyScreenDump(buf, 'Test_diff_bin_02', {})
   1657  " Test using external diff
   1658  call term_sendkeys(buf, ":set diffopt=filler\<cr>")
   1659  call term_sendkeys(buf, "\<C-l>")
   1660  call VerifyScreenDump(buf, 'Test_diff_bin_03', {})
   1661  " Test using external diff and case folding
   1662  call term_sendkeys(buf, ":set diffopt=filler,icase\<cr>")
   1663  call term_sendkeys(buf, "\<C-l>")
   1664  call VerifyScreenDump(buf, 'Test_diff_bin_04', {})
   1665 
   1666  " clean up
   1667  call StopVimInTerminal(buf)
   1668  set diffopt&vim
   1669 endfunc
   1670 
   1671 " Test for using the 'zi' command to invert 'foldenable' in diff windows (test
   1672 " for the issue fixed by patch 6.2.317)
   1673 func Test_diff_foldinvert()
   1674  %bw!
   1675  edit Xdoffile1
   1676  new Xdoffile2
   1677  new Xdoffile3
   1678  windo diffthis
   1679  " open a non-diff window
   1680  botright new
   1681  1wincmd w
   1682  call assert_true(getwinvar(1, '&foldenable'))
   1683  call assert_true(getwinvar(2, '&foldenable'))
   1684  call assert_true(getwinvar(3, '&foldenable'))
   1685  normal zi
   1686  call assert_false(getwinvar(1, '&foldenable'))
   1687  call assert_false(getwinvar(2, '&foldenable'))
   1688  call assert_false(getwinvar(3, '&foldenable'))
   1689  normal zi
   1690  call assert_true(getwinvar(1, '&foldenable'))
   1691  call assert_true(getwinvar(2, '&foldenable'))
   1692  call assert_true(getwinvar(3, '&foldenable'))
   1693 
   1694  " If the current window has 'noscrollbind', then 'zi' should not change
   1695  " 'foldenable' in other windows.
   1696  1wincmd w
   1697  set noscrollbind
   1698  normal zi
   1699  call assert_false(getwinvar(1, '&foldenable'))
   1700  call assert_true(getwinvar(2, '&foldenable'))
   1701  call assert_true(getwinvar(3, '&foldenable'))
   1702 
   1703  " 'zi' should not change the 'foldenable' for windows with 'noscrollbind'
   1704  1wincmd w
   1705  set scrollbind
   1706  normal zi
   1707  call setwinvar(2, '&scrollbind', v:false)
   1708  normal zi
   1709  call assert_false(getwinvar(1, '&foldenable'))
   1710  call assert_true(getwinvar(2, '&foldenable'))
   1711  call assert_false(getwinvar(3, '&foldenable'))
   1712 
   1713  %bw!
   1714  set scrollbind&
   1715 endfunc
   1716 
   1717 " This was scrolling for 'cursorbind' but 'scrollbind' is more important
   1718 func Test_diff_scroll()
   1719  CheckScreendump
   1720 
   1721  let left =<< trim END
   1722      line 1
   1723      line 2
   1724      line 3
   1725      line 4
   1726 
   1727      // Common block
   1728      // one
   1729      // containing
   1730      // four lines
   1731 
   1732      // Common block
   1733      // two
   1734      // containing
   1735      // four lines
   1736  END
   1737  call writefile(left, 'Xleft', 'D')
   1738  let right =<< trim END
   1739      line 1
   1740      line 2
   1741      line 3
   1742      line 4
   1743 
   1744      Lorem
   1745      ipsum
   1746      dolor
   1747      sit
   1748      amet,
   1749      consectetur
   1750      adipiscing
   1751      elit.
   1752      Etiam
   1753      luctus
   1754      lectus
   1755      sodales,
   1756      dictum
   1757 
   1758      // Common block
   1759      // one
   1760      // containing
   1761      // four lines
   1762 
   1763      Vestibulum
   1764      tincidunt
   1765      aliquet
   1766      nulla.
   1767 
   1768      // Common block
   1769      // two
   1770      // containing
   1771      // four lines
   1772  END
   1773  call writefile(right, 'Xright', 'D')
   1774  let buf = RunVimInTerminal('-d Xleft Xright', {'rows': 12})
   1775  call term_sendkeys(buf, "\<C-W>\<C-W>jjjj")
   1776  call VerifyScreenDump(buf, 'Test_diff_scroll_1', {})
   1777  call term_sendkeys(buf, "j")
   1778  call VerifyScreenDump(buf, 'Test_diff_scroll_2', {})
   1779 
   1780  call StopVimInTerminal(buf)
   1781 endfunc
   1782 
   1783 " This was scrolling too many lines.
   1784 func Test_diff_scroll_wrap_on()
   1785  20new
   1786  40vsplit
   1787  call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
   1788  setlocal number diff so=0
   1789  redraw
   1790  normal! jj
   1791  call assert_equal(1, winsaveview().topline)
   1792  normal! j
   1793  call assert_equal(2, winsaveview().topline)
   1794 
   1795  bwipe!
   1796  bwipe!
   1797 endfunc
   1798 
   1799 func Test_diff_scroll_many_filler()
   1800  20new
   1801  vnew
   1802  call setline(1, range(1, 40))
   1803  diffthis
   1804  setlocal scrolloff=0
   1805  wincmd p
   1806  call setline(1, range(1, 20)->reverse() + ['###']->repeat(41) + range(21, 40)->reverse())
   1807  diffthis
   1808  setlocal scrolloff=0
   1809  wincmd p
   1810  redraw
   1811 
   1812  " Note: need a redraw after each scroll, otherwise the test always passes.
   1813  for _ in range(2)
   1814    normal! G
   1815    redraw
   1816    call assert_equal(40, winsaveview().topline)
   1817    call assert_equal(19, winsaveview().topfill)
   1818    exe "normal! \<C-B>"
   1819    redraw
   1820    call assert_equal(22, winsaveview().topline)
   1821    call assert_equal(0, winsaveview().topfill)
   1822    exe "normal! \<C-B>"
   1823    redraw
   1824    call assert_equal(4, winsaveview().topline)
   1825    call assert_equal(0, winsaveview().topfill)
   1826    exe "normal! \<C-B>"
   1827    redraw
   1828    call assert_equal(1, winsaveview().topline)
   1829    call assert_equal(0, winsaveview().topfill)
   1830    set smoothscroll
   1831  endfor
   1832 
   1833  set smoothscroll&
   1834  %bwipe!
   1835 endfunc
   1836 
   1837 " This was trying to update diffs for a buffer being closed
   1838 func Test_diff_only()
   1839  silent! lfile
   1840  set diff
   1841  lopen
   1842  norm o
   1843  silent! norm o
   1844 
   1845  set nodiff
   1846  %bwipe!
   1847 endfunc
   1848 
   1849 " This was causing invalid diff block values
   1850 " FIXME: somehow this causes a valgrind error when run directly but not when
   1851 " run as a test.
   1852 func Test_diff_manipulations()
   1853  set diff
   1854  split 0
   1855  sil! norm RdoobdeuRdoobdeuRdoobdeu
   1856 
   1857  set nodiff
   1858  %bwipe!
   1859 endfunc
   1860 
   1861 " This was causing the line number in the diff block to go below one.
   1862 " FIXME: somehow this causes a valgrind error when run directly but not when
   1863 " run as a test.
   1864 func Test_diff_put_and_undo()
   1865  set diff
   1866  next 0
   1867  split 00
   1868  sil! norm o0gguudpo0ggJuudp
   1869 
   1870  bwipe!
   1871  bwipe!
   1872  set nodiff
   1873 endfunc
   1874 
   1875 
   1876 func Test_diff_toggle_wrap_skipcol_leftcol()
   1877  61vnew
   1878  call setline(1, 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.')
   1879  30vnew
   1880  call setline(1, 'ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.')
   1881  let win1 = win_getid()
   1882  setlocal smoothscroll
   1883  exe "normal! $\<C-E>"
   1884  wincmd l
   1885  let win2 = win_getid()
   1886  setlocal smoothscroll
   1887  exe "normal! $\<C-E>"
   1888  call assert_equal([
   1889        \ '<<<sadipscing elitr, sed diam |<<<tetur sadipscing elitr, sed|',
   1890        \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
   1891        \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
   1892        \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
   1893        \ '~                             |ptua.                         |',
   1894        \ ], ScreenLines([1, 5], 62))
   1895  call assert_equal({'col': 29, 'row': 4, 'endcol': 29, 'curscol': 29},
   1896        \ screenpos(win1, line('.', win1), col('.', win1)))
   1897  call assert_equal({'col': 36, 'row': 5, 'endcol': 36, 'curscol': 36},
   1898        \ screenpos(win2, line('.', win2), col('.', win2)))
   1899 
   1900  wincmd h
   1901  diffthis
   1902  wincmd l
   1903  diffthis
   1904  normal! 0
   1905  call assert_equal([
   1906        \ '  ipsum dolor sit amet, conset|  Lorem ipsum dolor sit amet, |',
   1907        \ '~                             |~                             |',
   1908        \ ], ScreenLines([1, 2], 62))
   1909  call assert_equal({'col': 3, 'row': 1, 'endcol': 3, 'curscol': 3},
   1910        \ screenpos(win1, line('.', win1), col('.', win1)))
   1911  call assert_equal({'col': 34, 'row': 1, 'endcol': 34, 'curscol': 34},
   1912        \ screenpos(win2, line('.', win2), col('.', win2)))
   1913 
   1914  normal! $
   1915  call assert_equal([
   1916        \ '  voluptua.                   |   diam voluptua.             |',
   1917        \ '~                             |~                             |',
   1918        \ ], ScreenLines([1, 2], 62))
   1919  call assert_equal({'col': 11, 'row': 1, 'endcol': 11, 'curscol': 11},
   1920        \ screenpos(win1, line('.', win1), col('.', win1)))
   1921  call assert_equal({'col': 48, 'row': 1, 'endcol': 48, 'curscol': 48},
   1922        \ screenpos(win2, line('.', win2), col('.', win2)))
   1923 
   1924  diffoff!
   1925  call assert_equal([
   1926        \ 'ipsum dolor sit amet, consetet|Lorem ipsum dolor sit amet, co|',
   1927        \ 'ur sadipscing elitr, sed diam |nsetetur sadipscing elitr, sed|',
   1928        \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
   1929        \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
   1930        \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
   1931        \ '~                             |ptua.                         |',
   1932        \ ], ScreenLines([1, 6], 62))
   1933  call assert_equal({'col': 29, 'row': 5, 'endcol': 29, 'curscol': 29},
   1934        \ screenpos(win1, line('.', win1), col('.', win1)))
   1935  call assert_equal({'col': 36, 'row': 6, 'endcol': 36, 'curscol': 36},
   1936        \ screenpos(win2, line('.', win2), col('.', win2)))
   1937 
   1938  bwipe!
   1939  bwipe!
   1940 endfunc
   1941 
   1942 " Ctrl-D reveals filler lines below the last line in the buffer.
   1943 func Test_diff_eob_halfpage()
   1944  new
   1945  call setline(1, ['']->repeat(10) + ['a'])
   1946  diffthis
   1947  new
   1948  call setline(1, ['']->repeat(3) + ['a', 'b'])
   1949  diffthis
   1950  resize 5
   1951  wincmd j
   1952  resize 5
   1953  norm G
   1954  call assert_equal(7, line('w0'))
   1955  exe "norm! \<C-D>"
   1956  call assert_equal(8, line('w0'))
   1957 
   1958  %bwipe!
   1959 endfunc
   1960 
   1961 func Test_diff_overlapped_diff_blocks_will_be_merged()
   1962  CheckScreendump
   1963 
   1964  let lines =<< trim END
   1965    func DiffExprStub()
   1966      let txt_in = readfile(v:fname_in)
   1967      let txt_new = readfile(v:fname_new)
   1968      if txt_in == ["line1"] && txt_new == ["line2"]
   1969        call writefile(["1c1"], v:fname_out)
   1970      elseif txt_in == readfile("Xdiin1") && txt_new == readfile("Xdinew1")
   1971        call writefile(readfile("Xdiout1"), v:fname_out)
   1972      elseif txt_in == readfile("Xdiin2") && txt_new == readfile("Xdinew2")
   1973        call writefile(readfile("Xdiout2"), v:fname_out)
   1974      endif
   1975    endfunc
   1976  END
   1977  call writefile(lines, 'XdiffSetup', 'D')
   1978 
   1979  call WriteDiffFiles(0, [], [])
   1980  let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
   1981  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   1982 
   1983  call WriteDiffFiles(buf, ["a", "b"], ["x", "x"])
   1984  call writefile(["a", "b"], "Xdiin1")
   1985  call writefile(["x", "x"], "Xdinew1")
   1986  call writefile(["1c1", "2c2"], "Xdiout1")
   1987  call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
   1988  call VerifyBoth(buf, "Test_diff_overlapped_2.01", "")
   1989  call term_sendkeys(buf, ":set diffexpr&\<CR>:")
   1990 
   1991  call WriteDiffFiles(buf, ["a", "b", "c"], ["x", "c"])
   1992  call writefile(["a", "b", "c"], "Xdiin1")
   1993  call writefile(["x", "c"], "Xdinew1")
   1994  call writefile(["1c1", "2d1"], "Xdiout1")
   1995  call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
   1996  call VerifyBoth(buf, "Test_diff_overlapped_2.02", "")
   1997  call term_sendkeys(buf, ":set diffexpr&\<CR>:")
   1998 
   1999  call WriteDiffFiles(buf, ["a", "c"], ["x", "x", "c"])
   2000  call writefile(["a", "c"], "Xdiin1")
   2001  call writefile(["x", "x", "c"], "Xdinew1")
   2002  call writefile(["1c1", "1a2"], "Xdiout1")
   2003  call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
   2004  call VerifyBoth(buf, "Test_diff_overlapped_2.03", "")
   2005  call term_sendkeys(buf, ":set diffexpr&\<CR>:")
   2006 
   2007  call StopVimInTerminal(buf)
   2008  wincmd c
   2009 
   2010  call WriteDiffFiles3(0, [], [], [])
   2011  let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2 Xdifile3', {})
   2012  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2013 
   2014  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "b", "c"])
   2015  call VerifyBoth(buf, "Test_diff_overlapped_3.01", "")
   2016 
   2017  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "c"])
   2018  call VerifyBoth(buf, "Test_diff_overlapped_3.02", "")
   2019 
   2020  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y"])
   2021  call VerifyBoth(buf, "Test_diff_overlapped_3.03", "")
   2022 
   2023  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "c"])
   2024  call VerifyBoth(buf, "Test_diff_overlapped_3.04", "")
   2025 
   2026  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "y"])
   2027  call VerifyBoth(buf, "Test_diff_overlapped_3.05", "")
   2028 
   2029  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "y"])
   2030  call VerifyBoth(buf, "Test_diff_overlapped_3.06", "")
   2031 
   2032  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "x"], ["y", "y", "c"])
   2033  call VerifyBoth(buf, "Test_diff_overlapped_3.07", "")
   2034 
   2035  call WriteDiffFiles3(buf, ["a", "b", "c"], ["x", "x", "c"], ["a", "y", "y"])
   2036  call VerifyBoth(buf, "Test_diff_overlapped_3.08", "")
   2037 
   2038  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "d", "e"])
   2039  call VerifyBoth(buf, "Test_diff_overlapped_3.09", "")
   2040 
   2041  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "e"])
   2042  call VerifyBoth(buf, "Test_diff_overlapped_3.10", "")
   2043 
   2044  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "y"])
   2045  call VerifyBoth(buf, "Test_diff_overlapped_3.11", "")
   2046 
   2047  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "d", "e"])
   2048  call VerifyBoth(buf, "Test_diff_overlapped_3.12", "")
   2049 
   2050  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "e"])
   2051  call VerifyBoth(buf, "Test_diff_overlapped_3.13", "")
   2052 
   2053  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "y"])
   2054  call VerifyBoth(buf, "Test_diff_overlapped_3.14", "")
   2055 
   2056  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "d", "e"])
   2057  call VerifyBoth(buf, "Test_diff_overlapped_3.15", "")
   2058 
   2059  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "e"])
   2060  call VerifyBoth(buf, "Test_diff_overlapped_3.16", "")
   2061 
   2062  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "y"])
   2063  call VerifyBoth(buf, "Test_diff_overlapped_3.17", "")
   2064 
   2065  call WriteDiffFiles3(buf, ["a", "b"], ["x", "b"], ["y", "y"])
   2066  call writefile(["a", "b"], "Xdiin1")
   2067  call writefile(["x", "b"], "Xdinew1")
   2068  call writefile(["1c1"], "Xdiout1")
   2069  call writefile(["a", "b"], "Xdiin2")
   2070  call writefile(["y", "y"], "Xdinew2")
   2071  call writefile(["1c1", "2c2"], "Xdiout2")
   2072  call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
   2073  call VerifyInternal(buf, "Test_diff_overlapped_3.18", "")
   2074  call term_sendkeys(buf, ":set diffexpr&\<CR>:")
   2075 
   2076  call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "c", "d"])
   2077  call writefile(["a", "b", "c", "d"], "Xdiin1")
   2078  call writefile(["x", "b", "x", "d"], "Xdinew1")
   2079  call writefile(["1c1", "3c3"], "Xdiout1")
   2080  call writefile(["a", "b", "c", "d"], "Xdiin2")
   2081  call writefile(["y", "y", "c", "d"], "Xdinew2")
   2082  call writefile(["1c1", "2c2"], "Xdiout2")
   2083  call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
   2084  call VerifyInternal(buf, "Test_diff_overlapped_3.19", "")
   2085  call term_sendkeys(buf, ":set diffexpr&\<CR>:")
   2086 
   2087  call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "d"])
   2088  call writefile(["a", "b", "c", "d"], "Xdiin1")
   2089  call writefile(["x", "b", "x", "d"], "Xdinew1")
   2090  call writefile(["1c1", "3c3"], "Xdiout1")
   2091  call writefile(["a", "b", "c", "d"], "Xdiin2")
   2092  call writefile(["y", "y", "y", "d"], "Xdinew2")
   2093  call writefile(["1c1", "2,3c2,3"], "Xdiout2")
   2094  call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
   2095  call VerifyInternal(buf, "Test_diff_overlapped_3.20", "")
   2096  call term_sendkeys(buf, ":set diffexpr&\<CR>:")
   2097 
   2098  call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "y"])
   2099  call writefile(["a", "b", "c", "d"], "Xdiin1")
   2100  call writefile(["x", "b", "x", "d"], "Xdinew1")
   2101  call writefile(["1c1", "3c3"], "Xdiout1")
   2102  call writefile(["a", "b", "c", "d"], "Xdiin2")
   2103  call writefile(["y", "y", "y", "y"], "Xdinew2")
   2104  call writefile(["1c1", "2,4c2,4"], "Xdiout2")
   2105  call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
   2106  call VerifyInternal(buf, "Test_diff_overlapped_3.21", "")
   2107  call term_sendkeys(buf, ":set diffexpr&\<CR>:")
   2108 
   2109  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b", "c"])
   2110  call VerifyBoth(buf, "Test_diff_overlapped_3.22", "")
   2111 
   2112  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["c"])
   2113  call VerifyBoth(buf, "Test_diff_overlapped_3.23", "")
   2114 
   2115  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], [])
   2116  call VerifyBoth(buf, "Test_diff_overlapped_3.24", "")
   2117 
   2118  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "c"])
   2119  call VerifyBoth(buf, "Test_diff_overlapped_3.25", "")
   2120 
   2121  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a"])
   2122  call VerifyBoth(buf, "Test_diff_overlapped_3.26", "")
   2123 
   2124  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b"])
   2125  call VerifyBoth(buf, "Test_diff_overlapped_3.27", "")
   2126 
   2127  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["d", "e"])
   2128  call VerifyBoth(buf, "Test_diff_overlapped_3.28", "")
   2129 
   2130  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["e"])
   2131  call VerifyBoth(buf, "Test_diff_overlapped_3.29", "")
   2132 
   2133  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "d", "e"])
   2134  call VerifyBoth(buf, "Test_diff_overlapped_3.30", "")
   2135 
   2136  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "e"])
   2137  call VerifyBoth(buf, "Test_diff_overlapped_3.31", "")
   2138 
   2139  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a"])
   2140  call VerifyBoth(buf, "Test_diff_overlapped_3.32", "")
   2141 
   2142  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "d", "e"])
   2143  call VerifyBoth(buf, "Test_diff_overlapped_3.33", "")
   2144 
   2145  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "e"])
   2146  call VerifyBoth(buf, "Test_diff_overlapped_3.34", "")
   2147 
   2148  call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b"])
   2149  call VerifyBoth(buf, "Test_diff_overlapped_3.35", "")
   2150 
   2151  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "b", "c"])
   2152  call VerifyBoth(buf, "Test_diff_overlapped_3.36", "")
   2153 
   2154  call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y", "c"])
   2155  call VerifyBoth(buf, "Test_diff_overlapped_3.37", "")
   2156 
   2157  call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b", "f"])
   2158  call VerifyBoth(buf, "Test_diff_overlapped_3.38", "")
   2159 
   2160  call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b"])
   2161  call VerifyBoth(buf, "Test_diff_overlapped_3.39", "")
   2162 
   2163  " File 3 overlaps twice, 2nd overlap completely within the existing block.
   2164  call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "bar"], ["foo", "w", "x", "y", "z", "bar"], ["foo", "1", "a", "b", "2", "bar"])
   2165  call VerifyBoth(buf, "Test_diff_overlapped_3.40", "")
   2166 
   2167  " File 3 overlaps twice, 2nd overlap extends beyond existing block on new
   2168  " side. Make sure we don't over-extend the range and hit 'bar'.
   2169  call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "2", "d", "bar"])
   2170  call VerifyBoth(buf, "Test_diff_overlapped_3.41", "")
   2171 
   2172  " Chained overlaps. File 3's 2nd overlap spans two diff blocks and is longer
   2173  " than the 2nd one.
   2174  call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "e", "f", "bar"], ["foo", "w", "x", "y", "z", "e", "u", "bar"], ["foo", "1", "b", "2", "3", "d", "4", "f", "bar"])
   2175  call VerifyBoth(buf, "Test_diff_overlapped_3.42", "")
   2176 
   2177  " File 3 has 2 overlaps. An add and a delete. First overlap's expansion hits
   2178  " the 2nd one. Make sure we adjust the diff block to have fewer lines.
   2179  call WriteDiffFiles3(buf, ["foo", "a", "b", "bar"], ["foo", "x", "y", "bar"], ["foo", "1", "a", "bar"])
   2180  call VerifyBoth(buf, "Test_diff_overlapped_3.43", "")
   2181 
   2182  " File 3 has 2 overlaps. An add and another add. First overlap's expansion hits
   2183  " the 2nd one. Make sure we adjust the diff block to have more lines.
   2184  call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "3", "4", "d", "bar"])
   2185  call VerifyBoth(buf, "Test_diff_overlapped_3.44", "")
   2186 
   2187  call StopVimInTerminal(buf)
   2188 endfunc
   2189 
   2190 " switching windows in diff mode caused an unnecessary scroll
   2191 func Test_diff_topline_noscroll()
   2192  CheckScreendump
   2193 
   2194  let content =<< trim END
   2195    call setline(1, range(1,60))
   2196    vnew
   2197    call setline(1, range(1,10) + range(50,60))
   2198    windo diffthis
   2199    norm! G
   2200    exe "norm! 30\<C-y>"
   2201  END
   2202  call writefile(content, 'Xcontent', 'D')
   2203  let buf = RunVimInTerminal('-S Xcontent', {'rows': 20})
   2204  call VerifyScreenDump(buf, 'Test_diff_topline_1', {})
   2205  call term_sendkeys(buf, ":echo line('w0', 1001)\<cr>")
   2206  call term_wait(buf)
   2207  call VerifyScreenDump(buf, 'Test_diff_topline_2', {})
   2208  call term_sendkeys(buf, "\<C-W>p")
   2209  call term_wait(buf)
   2210  call VerifyScreenDump(buf, 'Test_diff_topline_3', {})
   2211  call term_sendkeys(buf, "\<C-W>p")
   2212  call term_wait(buf)
   2213  call VerifyScreenDump(buf, 'Test_diff_topline_4', {})
   2214  call StopVimInTerminal(buf)
   2215 endfunc
   2216 
   2217 " Test inline highlighting which shows what's different within each diff block
   2218 func Test_diff_inline()
   2219  CheckScreendump
   2220 
   2221  call WriteDiffFiles(0, [], [])
   2222  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2223  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2224 
   2225  call WriteDiffFiles(buf, ["abcdef ghi jk n", "x", "y"], ["aBcef gHi lm n", "y", "z"])
   2226  call VerifyInternal(buf, "Test_diff_inline_01", "")
   2227  call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:none")
   2228 
   2229  " inline:simple is the same as default
   2230  call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:simple")
   2231 
   2232  call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:char")
   2233  call VerifyInternal(buf, "Test_diff_inline_04", " diffopt+=inline:word")
   2234 
   2235  " multiple inline values will the last one
   2236  call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:none,inline:char,inline:simple")
   2237  call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:simple,inline:word,inline:none")
   2238  call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:simple,inline:word,inline:char")
   2239 
   2240  " DiffTextAdd highlight
   2241  call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
   2242  call VerifyInternal(buf, "Test_diff_inline_05", " diffopt+=inline:char")
   2243 
   2244  " Live update in insert mode
   2245  call term_sendkeys(buf, "\<Esc>isometext")
   2246  call VerifyScreenDump(buf, "Test_diff_inline_06", {})
   2247  call term_sendkeys(buf, "\<Esc>u")
   2248 
   2249  " icase simple scenarios
   2250  call VerifyInternal(buf, "Test_diff_inline_07", " diffopt+=inline:simple,icase")
   2251  call VerifyInternal(buf, "Test_diff_inline_08", " diffopt+=inline:char,icase")
   2252  call VerifyInternal(buf, "Test_diff_inline_09", " diffopt+=inline:word,icase")
   2253 
   2254  " diff algorithms should affect highlight
   2255  call WriteDiffFiles(buf, ["apples and oranges"], ["oranges and apples"])
   2256  call VerifyInternal(buf, "Test_diff_inline_10", " diffopt+=inline:char")
   2257  call VerifyInternal(buf, "Test_diff_inline_11", " diffopt+=inline:char,algorithm:patience")
   2258 
   2259  " icase: composing chars and Unicode fold case edge cases
   2260  call WriteDiffFiles(buf,
   2261        \ ["1 - sigma in 6σ and Ὀδυσσεύς", "1 - angstrom in åå", "1 - composing: ii⃗I⃗"],
   2262        \ ["2 - Sigma in 6Σ and ὈΔΥΣΣΕΎΣ", "2 - Angstrom in ÅÅ", "2 - Composing: i⃗I⃗I⃗"])
   2263  call VerifyInternal(buf, "Test_diff_inline_12", " diffopt+=inline:char")
   2264  call VerifyInternal(buf, "Test_diff_inline_13", " diffopt+=inline:char,icase")
   2265 
   2266  " wide chars
   2267  call WriteDiffFiles(buf, ["abc😅xde一", "f🚀g"], ["abcy😢de", "二f🚀g"])
   2268  call VerifyInternal(buf, "Test_diff_inline_14", " diffopt+=inline:char,icase")
   2269 
   2270  " NUL char (\n below is internally substituted as NUL)
   2271  call WriteDiffFiles(buf, ["1\n34\n5\n6"], ["1234\n5", "6"])
   2272  call VerifyInternal(buf, "Test_diff_inline_15", " diffopt+=inline:char")
   2273 
   2274  " word diff: always use first buffer's iskeyword and ignore others' for consistency
   2275  call WriteDiffFiles(buf, ["foo+bar test"], ["foo+baz test"])
   2276  call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
   2277 
   2278  call term_sendkeys(buf, ":set iskeyword+=+\<CR>:diffupdate\<CR>")
   2279  call VerifyInternal(buf, "Test_diff_inline_word_02", " diffopt+=inline:word")
   2280 
   2281  call term_sendkeys(buf, ":set iskeyword&\<CR>:wincmd w\<CR>")
   2282  call term_sendkeys(buf, ":set iskeyword+=+\<CR>:wincmd w\<CR>:diffupdate\<CR>")
   2283  " Use the previous screen dump as 2nd buffer's iskeyword does not matter
   2284  call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
   2285 
   2286  call term_sendkeys(buf, ":windo set iskeyword&\<CR>:1wincmd w\<CR>")
   2287 
   2288  " word diff: test handling of multi-byte characters. Only alphanumeric chars
   2289  " (e.g. Greek alphabet, but not CJK/emoji) count as words.
   2290  call WriteDiffFiles(buf, ["🚀⛵️一二三ひらがなΔέλτα Δelta foobar"], ["🚀🛸一二四ひらなδέλτα δelta foobar"])
   2291  call VerifyInternal(buf, "Test_diff_inline_word_03", " diffopt+=inline:word")
   2292 
   2293  " char diff: should slide highlight to whitespace boundary if possible for
   2294  " better readability (by using forced indent-heuristics). A wrong result
   2295  " would be if the highlight is "Bar, prefix". It should be "prefixBar, "
   2296  " instead.
   2297  call WriteDiffFiles(buf, ["prefixFoo, prefixEnd"], ["prefixFoo, prefixBar, prefixEnd"])
   2298  call VerifyInternal(buf, "Test_diff_inline_char_01", " diffopt+=inline:char")
   2299 
   2300  " char diff: small gaps between inline diff blocks will be merged during refine step
   2301  " - first segment: test that we iteratively merge small gaps after we merged
   2302  "   adjacent blocks, but only with limited number (set to 4) of iterations.
   2303  " - second and third segments: show that we need a large enough adjacent block to
   2304  "   trigger a merge.
   2305  " - fourth segment: small gaps are not merged when adjacent large block is
   2306  "   on a different line.
   2307  call WriteDiffFiles(buf,
   2308        \ ["abcdefghijklmno", "anchor1",
   2309        \  "abcdefghijklmno", "anchor2",
   2310        \  "abcdefghijklmno", "anchor3",
   2311        \  "test", "multiline"],
   2312        \ ["a?c?e?g?i?k???o", "anchor1",
   2313        \  "a??de?????klmno", "anchor2",
   2314        \  "a??de??????lmno", "anchor3",
   2315        \  "t?s?", "??????i?e"])
   2316  call VerifyInternal(buf, "Test_diff_inline_char_02", " diffopt+=inline:char")
   2317 
   2318  " Test multi-line blocks and whitespace
   2319  call WriteDiffFiles(buf,
   2320        \ ["this   is   ", "sometest text foo", "baz abc def ", "one", "word another word", "additional line"],
   2321        \ ["this is some test", "texts", "foo bar abX Yef     ", "oneword another word"])
   2322  call VerifyInternal(buf, "Test_diff_inline_multiline_01", " diffopt+=inline:char,iwhite")
   2323  call VerifyInternal(buf, "Test_diff_inline_multiline_02", " diffopt+=inline:word,iwhite")
   2324  call VerifyInternal(buf, "Test_diff_inline_multiline_03", " diffopt+=inline:char,iwhiteeol")
   2325  call VerifyInternal(buf, "Test_diff_inline_multiline_04", " diffopt+=inline:word,iwhiteeol")
   2326  call VerifyInternal(buf, "Test_diff_inline_multiline_05", " diffopt+=inline:char,iwhiteall")
   2327  call VerifyInternal(buf, "Test_diff_inline_multiline_06", " diffopt+=inline:word,iwhiteall")
   2328 
   2329  " newline should be highlighted too when 'list' is set
   2330  call term_sendkeys(buf, ":windo set list\<CR>")
   2331  call VerifyInternal(buf, "Test_diff_inline_multiline_07", " diffopt+=inline:char")
   2332  call VerifyInternal(buf, "Test_diff_inline_multiline_08", " diffopt+=inline:char,iwhite")
   2333  call VerifyInternal(buf, "Test_diff_inline_multiline_09", " diffopt+=inline:char,iwhiteeol")
   2334  call VerifyInternal(buf, "Test_diff_inline_multiline_10", " diffopt+=inline:char,iwhiteall")
   2335  call term_sendkeys(buf, ":windo set nolist\<CR>")
   2336 
   2337  call StopVimInTerminal(buf)
   2338 endfunc
   2339 
   2340 func Test_diff_inline_multibuffer()
   2341  CheckScreendump
   2342 
   2343  call WriteDiffFiles3(0, [], [], [])
   2344  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
   2345  call term_sendkeys(buf, ":windo set autoread\<CR>:1wincmd w\<CR>")
   2346  call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
   2347 
   2348  call WriteDiffFiles3(buf,
   2349        \ ["That is buffer1.", "anchor", "Some random text", "anchor"],
   2350        \ ["This is buffer2.", "anchor", "Some text", "anchor", "buffer2/3"],
   2351        \ ["This is buffer3. Last.", "anchor", "Some more", "text here.", "anchor", "only in buffer2/3", "not in buffer1"])
   2352  call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
   2353 
   2354  " Close one of the buffers and make sure it updates correctly
   2355  call term_sendkeys(buf, ":diffoff\<CR>")
   2356  call VerifyInternal(buf, "Test_diff_inline_multibuffer_02", " diffopt+=inline:char")
   2357 
   2358  " Update text in the non-diff buffer and nothing should be changed
   2359  call term_sendkeys(buf, "\<Esc>isometext")
   2360  call VerifyScreenDump(buf, "Test_diff_inline_multibuffer_03", {})
   2361  call term_sendkeys(buf, "\<Esc>u")
   2362 
   2363  call term_sendkeys(buf, ":diffthis\<CR>")
   2364  call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
   2365 
   2366  " Test that removing first buffer from diff will in turn use the next
   2367  " earliest buffer's iskeyword during word diff.
   2368  call WriteDiffFiles3(buf,
   2369        \ ["This+is=a-setence"],
   2370        \ ["This+is=another-setence"],
   2371        \ ["That+is=a-setence"])
   2372  call term_sendkeys(buf, ":set iskeyword+=+\<CR>:2wincmd w\<CR>:set iskeyword+=-\<CR>:1wincmd w\<CR>")
   2373  call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
   2374  call term_sendkeys(buf, ":diffoff\<CR>")
   2375  call VerifyInternal(buf, "Test_diff_inline_multibuffer_05", " diffopt+=inline:word")
   2376  call term_sendkeys(buf, ":diffthis\<CR>")
   2377  call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
   2378 
   2379  " Test multi-buffer char diff refinement, and that removing a buffer from
   2380  " diff will update the others properly.
   2381  call WriteDiffFiles3(buf,
   2382        \ ["abcdefghijkYmYYY"],
   2383        \ ["aXXdXXghijklmnop"],
   2384        \ ["abcdefghijkYmYop"])
   2385  call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
   2386  call term_sendkeys(buf, ":diffoff\<CR>")
   2387  call VerifyInternal(buf, "Test_diff_inline_multibuffer_07", " diffopt+=inline:char")
   2388  call term_sendkeys(buf, ":diffthis\<CR>")
   2389  call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
   2390 
   2391  call StopVimInTerminal(buf)
   2392 endfunc
   2393 
   2394 " Test that when using multi-buffer diff, an empty block would be correctly
   2395 " skipped in the result, without resulting in invalid states or crashes.
   2396 func Test_diff_inline_multibuffer_empty_block()
   2397  CheckScreendump
   2398 
   2399  call writefile(['anchor1', '1234567890abcde', 'anchor2'], 'Xdifile1')
   2400  call writefile(['anchor1', '1234567--0abc-e', 'anchor2'], 'Xdifile2')
   2401  call writefile(['anchor1', 'anchor2'], 'Xdifile3')
   2402  call writefile(['anchor1', '1???????90abcd?', 'anchor2'], 'Xdifile4')
   2403 
   2404  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3 Xdifile4', {})
   2405  call VerifyInternal(buf, "Test_diff_inline_multibuffer_empty_block_01", " diffopt+=inline:char")
   2406 
   2407  call StopVimInTerminal(buf)
   2408 endfunc
   2409 
   2410 func Test_diffget_diffput_linematch()
   2411  CheckScreendump
   2412  call delete('.Xdifile1.swp')
   2413  call delete('.Xdifile2.swp')
   2414  call WriteDiffFiles(0, [], [])
   2415  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2416  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2417 
   2418  " enable linematch
   2419  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
   2420  call WriteDiffFiles(buf, ['',
   2421      \ 'common line',
   2422      \ 'common line',
   2423      \ '',
   2424      \ 'ABCabc',
   2425      \ 'ABCabc',
   2426      \ 'ABCabc',
   2427      \ 'ABCabc',
   2428      \ 'common line',
   2429      \ 'common line',
   2430      \ 'common line',
   2431      \ 'something' ],
   2432      \ ['',
   2433      \ 'common line',
   2434      \ 'common line',
   2435      \ '',
   2436      \ 'DEFabc',
   2437      \ 'xyz',
   2438      \ 'xyz',
   2439      \ 'xyz',
   2440      \ 'DEFabc',
   2441      \ 'DEFabc',
   2442      \ 'DEFabc',
   2443      \ 'common line',
   2444      \ 'common line',
   2445      \ 'DEF',
   2446      \ 'common line',
   2447      \ 'DEF',
   2448      \ 'something'])
   2449  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_1', {})
   2450 
   2451  " get from window 1 from line 5 to 9
   2452  call term_sendkeys(buf, "1\<c-w>w")
   2453  call term_sendkeys(buf, ":5,9diffget\<CR>")
   2454  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_2', {})
   2455 
   2456  " undo the last diffget
   2457  call term_sendkeys(buf, "u")
   2458 
   2459  " get from window 2 from line 5 to 10
   2460  call term_sendkeys(buf, "2\<c-w>w")
   2461  call term_sendkeys(buf, ":5,10diffget\<CR>")
   2462  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_3', {})
   2463 
   2464  " undo the last diffget
   2465  call term_sendkeys(buf, "u")
   2466 
   2467  " get all from window 2
   2468  call term_sendkeys(buf, "2\<c-w>w")
   2469  call term_sendkeys(buf, ":4,17diffget\<CR>")
   2470  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_4', {})
   2471 
   2472  " undo the last diffget
   2473  call term_sendkeys(buf, "u")
   2474 
   2475  " get all from window 1
   2476  call term_sendkeys(buf, "1\<c-w>w")
   2477  call term_sendkeys(buf, ":4,12diffget\<CR>")
   2478  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_5', {})
   2479 
   2480  " undo the last diffget
   2481  call term_sendkeys(buf, "u")
   2482 
   2483  " get from window 1 using do 1 line 5
   2484  call term_sendkeys(buf, "1\<c-w>w")
   2485  call term_sendkeys(buf, "5gg")
   2486  call term_sendkeys(buf, ":diffget\<CR>")
   2487  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_6', {})
   2488 
   2489  " undo the last diffget
   2490  call term_sendkeys(buf, "u")
   2491 
   2492  " get from window 1 using do 2 line 6
   2493  call term_sendkeys(buf, "1\<c-w>w")
   2494  call term_sendkeys(buf, "6gg")
   2495  call term_sendkeys(buf, ":diffget\<CR>")
   2496  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_7', {})
   2497 
   2498  " undo the last diffget
   2499  call term_sendkeys(buf, "u")
   2500 
   2501  " get from window 1 using do 2 line 7
   2502  call term_sendkeys(buf, "1\<c-w>w")
   2503  call term_sendkeys(buf, "7gg")
   2504  call term_sendkeys(buf, ":diffget\<CR>")
   2505  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_8', {})
   2506 
   2507  " undo the last diffget
   2508  call term_sendkeys(buf, "u")
   2509 
   2510  " get from window 1 using do 2 line 11
   2511  call term_sendkeys(buf, "1\<c-w>w")
   2512  call term_sendkeys(buf, "11gg")
   2513  call term_sendkeys(buf, ":diffget\<CR>")
   2514  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_9', {})
   2515 
   2516  " undo the last diffget
   2517  call term_sendkeys(buf, "u")
   2518 
   2519  " get from window 1 using do 2 line 12
   2520  call term_sendkeys(buf, "1\<c-w>w")
   2521  call term_sendkeys(buf, "12gg")
   2522  call term_sendkeys(buf, ":diffget\<CR>")
   2523  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_10', {})
   2524 
   2525  " undo the last diffget
   2526  call term_sendkeys(buf, "u")
   2527 
   2528  " put from window 1 using dp 1 line 5
   2529  call term_sendkeys(buf, "1\<c-w>w")
   2530  call term_sendkeys(buf, "5gg")
   2531  call term_sendkeys(buf, ":diffput\<CR>")
   2532  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_11', {})
   2533 
   2534  " undo the last diffput
   2535  call term_sendkeys(buf, "2\<c-w>w")
   2536  call term_sendkeys(buf, "u")
   2537 
   2538  " put from window 1 using dp 2 line 6
   2539  call term_sendkeys(buf, "1\<c-w>w")
   2540  call term_sendkeys(buf, "6gg")
   2541  call term_sendkeys(buf, ":diffput\<CR>")
   2542  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_12', {})
   2543 
   2544  " undo the last diffput
   2545  call term_sendkeys(buf, "2\<c-w>w")
   2546  call term_sendkeys(buf, "u")
   2547 
   2548  " put from window 1 using dp 2 line 7
   2549  call term_sendkeys(buf, "1\<c-w>w")
   2550  call term_sendkeys(buf, "7gg")
   2551  call term_sendkeys(buf, ":diffput\<CR>")
   2552  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_13', {})
   2553 
   2554  " undo the last diffput
   2555  call term_sendkeys(buf, "2\<c-w>w")
   2556  call term_sendkeys(buf, "u")
   2557 
   2558  " put from window 1 using dp 2 line 11
   2559  call term_sendkeys(buf, "1\<c-w>w")
   2560  call term_sendkeys(buf, "11gg")
   2561  call term_sendkeys(buf, ":diffput\<CR>")
   2562  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_14', {})
   2563 
   2564  " undo the last diffput
   2565  call term_sendkeys(buf, "2\<c-w>w")
   2566  call term_sendkeys(buf, "u")
   2567 
   2568  " put from window 1 using dp 2 line 12
   2569  call term_sendkeys(buf, "1\<c-w>w")
   2570  call term_sendkeys(buf, "12gg")
   2571  call term_sendkeys(buf, ":diffput\<CR>")
   2572  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_15', {})
   2573 
   2574  " undo the last diffput
   2575  call term_sendkeys(buf, "2\<c-w>w")
   2576  call term_sendkeys(buf, "u")
   2577 
   2578  " put from window 2 using dp line 6
   2579  call term_sendkeys(buf, "2\<c-w>w")
   2580  call term_sendkeys(buf, "6gg")
   2581  call term_sendkeys(buf, ":diffput\<CR>")
   2582  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_16', {})
   2583 
   2584  " undo the last diffput
   2585  call term_sendkeys(buf, "1\<c-w>w")
   2586  call term_sendkeys(buf, "u")
   2587 
   2588  " put from window 2 using dp line 8
   2589  call term_sendkeys(buf, "2\<c-w>w")
   2590  call term_sendkeys(buf, "8gg")
   2591  call term_sendkeys(buf, ":diffput\<CR>")
   2592  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_17', {})
   2593 
   2594  " undo the last diffput
   2595  call term_sendkeys(buf, "1\<c-w>w")
   2596  call term_sendkeys(buf, "u")
   2597 
   2598  " put from window 2 using dp line 9
   2599  call term_sendkeys(buf, "2\<c-w>w")
   2600  call term_sendkeys(buf, "9gg")
   2601  call term_sendkeys(buf, ":diffput\<CR>")
   2602  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_18', {})
   2603 
   2604  " undo the last diffput
   2605  call term_sendkeys(buf, "1\<c-w>w")
   2606  call term_sendkeys(buf, "u")
   2607 
   2608  " put from window 2 using dp line 17
   2609  call term_sendkeys(buf, "2\<c-w>w")
   2610  call term_sendkeys(buf, "17gg")
   2611  call term_sendkeys(buf, ":diffput\<CR>")
   2612  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_19', {})
   2613  " clean up
   2614  call StopVimInTerminal(buf)
   2615 endfunc
   2616 
   2617 func Test_linematch_diff()
   2618  CheckScreendump
   2619  call delete('.Xdifile1.swp')
   2620  call delete('.Xdifile2.swp')
   2621  call WriteDiffFiles(0, [], [])
   2622  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2623  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2624 
   2625  " enable linematch
   2626  call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
   2627  call WriteDiffFiles(buf, ['// abc d?',
   2628      \ '// d?',
   2629      \ '// d?' ],
   2630      \ ['!',
   2631      \ 'abc d!',
   2632      \ 'd!'])
   2633  call term_sendkeys(buf, ":\<CR>") " clear cmdline
   2634  call VerifyScreenDump(buf, 'Test_linematch_diff1', {})
   2635 
   2636  " test that filler is always implicitly set by linematch
   2637  call term_sendkeys(buf, ":set diffopt-=filler\<CR>")
   2638  call term_sendkeys(buf, ":\<CR>") " clear cmdline
   2639  call VerifyScreenDump(buf, 'Test_linematch_diff1', {})
   2640 
   2641  " clean up
   2642  call StopVimInTerminal(buf)
   2643 endfunc
   2644 
   2645 func Test_linematch_diff_iwhite()
   2646  CheckScreendump
   2647  call delete('.Xdifile1.swp')
   2648  call delete('.Xdifile2.swp')
   2649  call WriteDiffFiles(0, [], [])
   2650  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2651  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2652 
   2653  " setup a diff with 2 files and set linematch:30, with ignore white
   2654  call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
   2655  call WriteDiffFiles(buf, ['void testFunction () {',
   2656      \ '  for (int i = 0; i < 10; i++) {',
   2657      \ '    for (int j = 0; j < 10; j++) {',
   2658      \ '    }',
   2659      \ '  }',
   2660      \ '}' ],
   2661      \ ['void testFunction () {',
   2662      \ '  // for (int j = 0; j < 10; i++) {',
   2663      \ '  // }',
   2664      \ '}'])
   2665  call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite1', {})
   2666  call term_sendkeys(buf, ":set diffopt+=iwhiteall\<CR>")
   2667  call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite2', {})
   2668  " clean up
   2669  call StopVimInTerminal(buf)
   2670 endfunc
   2671 
   2672 func Test_linematch_diff_grouping()
   2673  CheckScreendump
   2674  call delete('.Xdifile1.swp')
   2675  call delete('.Xdifile2.swp')
   2676  call WriteDiffFiles(0, [], [])
   2677  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2678  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2679 
   2680  " a diff that would result in multiple groups before grouping optimization
   2681  call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
   2682  call WriteDiffFiles(buf, ['!A',
   2683      \ '!B',
   2684      \ '!C' ],
   2685      \ ['?Z',
   2686      \ '?A',
   2687      \ '?B',
   2688      \ '?C',
   2689      \ '?A',
   2690      \ '?B',
   2691      \ '?B',
   2692      \ '?C'])
   2693  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping1', {})
   2694  call WriteDiffFiles(buf, ['!A',
   2695      \ '!B',
   2696      \ '!C' ],
   2697      \ ['?A',
   2698      \ '?Z',
   2699      \ '?B',
   2700      \ '?C',
   2701      \ '?A',
   2702      \ '?B',
   2703      \ '?C',
   2704      \ '?C'])
   2705  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping2', {})
   2706  " clean up
   2707  call StopVimInTerminal(buf)
   2708 endfunc
   2709 
   2710 func Test_linematch_diff_scroll()
   2711  CheckScreendump
   2712  call delete('.Xdifile1.swp')
   2713  call delete('.Xdifile2.swp')
   2714  call WriteDiffFiles(0, [], [])
   2715  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2716  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2717 
   2718  " a diff that would result in multiple groups before grouping optimization
   2719  call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
   2720  call WriteDiffFiles(buf, ['!A',
   2721      \ '!B',
   2722      \ '!C' ],
   2723      \ ['?A',
   2724      \ '?Z',
   2725      \ '?B',
   2726      \ '?C',
   2727      \ '?A',
   2728      \ '?B',
   2729      \ '?C',
   2730      \ '?C'])
   2731  " scroll down to show calculation of top fill and scroll to correct line in
   2732  " both windows
   2733  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll0', {})
   2734  call term_sendkeys(buf, "3\<c-e>")
   2735  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll1', {})
   2736  call term_sendkeys(buf, "3\<c-e>")
   2737  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll2', {})
   2738  " clean up
   2739  call StopVimInTerminal(buf)
   2740 endfunc
   2741 
   2742 func Test_linematch_line_limit_exceeded()
   2743  CheckScreendump
   2744  call delete('.Xdifile1.swp')
   2745  call delete('.Xdifile2.swp')
   2746  call WriteDiffFiles(0, [], [])
   2747  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2748  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
   2749 
   2750  call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:10\<CR>")
   2751  " a diff block will not be aligned with linematch because it's contents
   2752  " exceed 10 lines
   2753  call WriteDiffFiles(buf,
   2754        \ ['common line',
   2755        \ 'HIL',
   2756        \ '',
   2757        \ 'aABCabc',
   2758        \ 'aABCabc',
   2759        \ 'aABCabc',
   2760        \ 'aABCabc',
   2761        \ 'common line',
   2762        \ 'HIL',
   2763        \ 'common line',
   2764        \ 'something'],
   2765        \ ['common line',
   2766        \ 'DEF',
   2767        \ 'GHI',
   2768        \ 'something',
   2769        \ '',
   2770        \ 'aDEFabc',
   2771        \ 'xyz',
   2772        \ 'xyz',
   2773        \ 'xyz',
   2774        \ 'aDEFabc',
   2775        \ 'aDEFabc',
   2776        \ 'aDEFabc',
   2777        \ 'common line',
   2778        \ 'DEF',
   2779        \ 'GHI',
   2780        \ 'something else',
   2781        \ 'common line',
   2782        \ 'something'])
   2783  call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded1', {})
   2784  " after increasing the count to 30, the limit is not exceeded, and the
   2785  " alignment algorithm will run on the largest diff block here
   2786  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
   2787  call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded2', {})
   2788  " clean up
   2789  call StopVimInTerminal(buf)
   2790 endfunc
   2791 
   2792 func Test_linematch_3diffs()
   2793  CheckScreendump
   2794  call delete('.Xdifile1.swp')
   2795  call delete('.Xdifile2.swp')
   2796  call delete('.Xdifile3.swp')
   2797  call WriteDiffFiles3(0, [], [], [])
   2798  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
   2799  call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
   2800  call term_sendkeys(buf, "2\<c-w>w:set autoread\<CR>")
   2801  call term_sendkeys(buf, "3\<c-w>w:set autoread\<CR>")
   2802  call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
   2803  call WriteDiffFiles3(buf,
   2804        \ ["",
   2805        \ "  common line",
   2806        \ "      AAA",
   2807        \ "      AAA",
   2808        \ "      AAA"],
   2809        \ ["",
   2810        \ "  common line",
   2811        \ "  <<<<<<< HEAD",
   2812        \ "      AAA",
   2813        \ "      AAA",
   2814        \ "      AAA",
   2815        \ "  =======",
   2816        \ "      BBB",
   2817        \ "      BBB",
   2818        \ "      BBB",
   2819        \ "  >>>>>>> branch1"],
   2820        \ ["",
   2821        \ "  common line",
   2822        \ "      BBB",
   2823        \ "      BBB",
   2824        \ "      BBB"])
   2825  call VerifyScreenDump(buf, 'Test_linematch_3diffs1', {})
   2826  " clean up
   2827  call StopVimInTerminal(buf)
   2828 endfunc
   2829 
   2830 " this used to access invalid memory
   2831 func Test_linematch_3diffs_sanity_check()
   2832  CheckScreendump
   2833  call delete('.Xfile_linematch1.swp')
   2834  call delete('.Xfile_linematch2.swp')
   2835  call delete('.Xfile_linematch3.swp')
   2836  let lines =<< trim END
   2837    set diffopt=internal,filler,linematch:60
   2838    call feedkeys("Aq\<esc>")
   2839    call feedkeys("GAklm\<esc>")
   2840    call feedkeys("o")
   2841  END
   2842  call writefile(lines, 'Xlinematch_3diffs.vim', 'D')
   2843  call writefile(['abcd', 'def', 'hij'], 'Xfile_linematch1', 'D')
   2844  call writefile(['defq', 'hijk', 'nopq'], 'Xfile_linematch2', 'D')
   2845  call writefile(['hijklm', 'nopqr', 'stuv'], 'Xfile_linematch3', 'D')
   2846  call WriteDiffFiles3(0, [], [], [])
   2847  let buf = RunVimInTerminal('-d -S Xlinematch_3diffs.vim Xfile_linematch1 Xfile_linematch2 Xfile_linematch3', {})
   2848  call VerifyScreenDump(buf, 'Test_linematch_3diffs2', {})
   2849 
   2850  " clean up
   2851  call StopVimInTerminal(buf)
   2852 endfunc
   2853 
   2854 func Test_diffanchors()
   2855  CheckScreendump
   2856  call WriteDiffFiles3(0,
   2857      \ ["anchorA1", "1", "2", "3",
   2858      \  "100", "101", "102", "anchorB", "103", "104", "105"],
   2859      \ ["100", "101", "102", "anchorB", "103", "104", "105",
   2860      \  "anchorA2", "1", "2", "3"],
   2861      \ ["100", "anchorB", "103",
   2862      \  "anchorA3", "1", "2", "3"])
   2863  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
   2864 
   2865  " Simple diff without any anchors
   2866  call VerifyInternal(buf, "Test_diff_anchors_00", "")
   2867 
   2868  " Setting diffopt+=anchor or diffanchors without the other won't do anything
   2869  call VerifyInternal(buf, "Test_diff_anchors_00", " diffopt+=anchor")
   2870  call VerifyInternal(buf, "Test_diff_anchors_00", " dia=1/anchorA/")
   2871 
   2872  " Use a single anchor by specifying a pattern. Test both internal and
   2873  " external diff to make sure both paths work.
   2874  call VerifyBoth(buf, "Test_diff_anchors_01", " dia=1/anchorA/ diffopt+=anchor")
   2875 
   2876  " Use 2 anchors. They should be sorted by line number, so in file 2/3
   2877  " anchorB is used before anchorA.
   2878  call VerifyBoth(buf, "Test_diff_anchors_02", " dia=1/anchorA/,1/anchorB/ diffopt+=anchor")
   2879 
   2880  " Set marks and specify addresses using marks and repeat the test
   2881  call term_sendkeys(buf, ":2wincmd w\<CR>:1/anchorA/mark a\<CR>")
   2882  call term_sendkeys(buf, ":1/anchorB/mark b\<CR>")
   2883  call term_sendkeys(buf, ":3wincmd w\<CR>:1/anchorA/mark a\<CR>")
   2884  call term_sendkeys(buf, ":1/anchorB/mark b\<CR>")
   2885  call term_sendkeys(buf, ":1wincmd w\<CR>:1/anchorA/mark a\<CR>")
   2886  call term_sendkeys(buf, ":1/anchorB/mark b\<CR>")
   2887 
   2888  call VerifyInternal(buf, "Test_diff_anchors_01", " dia='a diffopt+=anchor")
   2889  call VerifyInternal(buf, "Test_diff_anchors_02", " dia='a,'b diffopt+=anchor")
   2890 
   2891  " Update marks to point somewhere else. When we first set the mark the diff
   2892  " won't be updated until we manually invoke :diffupdate.
   2893  call VerifyInternal(buf, "Test_diff_anchors_01", " dia='a diffopt+=anchor")
   2894  call term_sendkeys(buf, ":1wincmd w\<CR>:1/anchorB/mark a\<CR>:")
   2895  call term_wait(buf)
   2896  call VerifyScreenDump(buf, "Test_diff_anchors_01", {})
   2897  call term_sendkeys(buf, ":diffupdate\<CR>:")
   2898  call term_wait(buf)
   2899  call VerifyScreenDump(buf, "Test_diff_anchors_03", {})
   2900 
   2901  " Use local diff anchors with line numbers, and repeat the same test
   2902  call term_sendkeys(buf, ":2wincmd w\<CR>:setlocal dia=8\<CR>")
   2903  call term_sendkeys(buf, ":3wincmd w\<CR>:setlocal dia=4\<CR>")
   2904  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=1\<CR>")
   2905  call VerifyInternal(buf, "Test_diff_anchors_01", " diffopt+=anchor")
   2906  call term_sendkeys(buf, ":2wincmd w\<CR>:setlocal dia=8,4\<CR>")
   2907  call term_sendkeys(buf, ":3wincmd w\<CR>:setlocal dia=4,2\<CR>")
   2908  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=1,8\<CR>")
   2909  call VerifyInternal(buf, "Test_diff_anchors_02", " diffopt+=anchor")
   2910 
   2911  " Test multiple diff anchors on the same line in file 1.
   2912  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=1,1\<CR>")
   2913  call VerifyInternal(buf, "Test_diff_anchors_04", " diffopt+=anchor")
   2914 
   2915  " Test that if one file has fewer diff anchors than others. Vim should only
   2916  " use the minimum in this case.
   2917  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=8\<CR>")
   2918  call VerifyInternal(buf, "Test_diff_anchors_05", " diffopt+=anchor")
   2919 
   2920  " $+1 should anchor everything past the last line
   2921  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=$+1\<CR>")
   2922  call VerifyInternal(buf, "Test_diff_anchors_06", " diffopt+=anchor")
   2923 
   2924  " Sorting of diff anchors should work with multiple anchors
   2925  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=1,10,8,2\<CR>")
   2926  call term_sendkeys(buf, ":2wincmd w\<CR>:setlocal dia=1,2,3,4\<CR>")
   2927  call term_sendkeys(buf, ":3wincmd w\<CR>:setlocal dia=4,3,2,1\<CR>")
   2928  call VerifyInternal(buf, "Test_diff_anchors_07", " diffopt+=anchor")
   2929 
   2930  " Intentionally set an invalid anchor with wrong line number. Should fall
   2931  " back to treat it as if no anchors are used at all.
   2932  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=1,10,8,2,1000 | silent! diffupdate\<CR>:")
   2933  call VerifyScreenDump(buf, "Test_diff_anchors_00", {})
   2934 
   2935  call StopVimInTerminal(buf)
   2936 endfunc
   2937 
   2938 " Test that scrollbind and topline calculations work correctly, even when diff
   2939 " anchors create adjacent diff blocks which complicates the calculations.
   2940 func Test_diffanchors_scrollbind_topline()
   2941  CheckScreendump
   2942 
   2943  " Simple overlapped line anchored to be adjacent to each other
   2944  call WriteDiffFiles(0,
   2945      \ ["anchor1", "diff1a", "anchor2"],
   2946      \ ["anchor1", "diff2a", "anchor2"])
   2947  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
   2948 
   2949  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=2\<CR>")
   2950  call term_sendkeys(buf, ":2wincmd w\<CR>:setlocal dia=3\<CR>")
   2951 
   2952  call VerifyInternal(buf, "Test_diff_anchors_scrollbind_topline_01", " diffopt+=anchor")
   2953  call term_sendkeys(buf, "\<Esc>\<C-E>")
   2954  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_02", {})
   2955  call term_sendkeys(buf, "\<C-E>")
   2956  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_03", {})
   2957  call term_sendkeys(buf, "\<C-E>")
   2958  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_04", {})
   2959 
   2960  " Also test no-filler
   2961  call term_sendkeys(buf, "gg")
   2962  call VerifyInternal(buf, "Test_diff_anchors_scrollbind_topline_05", " diffopt+=anchor diffopt-=filler")
   2963  call term_sendkeys(buf, "\<Esc>\<C-E>")
   2964  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_06", {})
   2965  call term_sendkeys(buf, "\<C-E>")
   2966  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_07", {})
   2967 
   2968  call StopVimInTerminal(buf)
   2969 endfunc
   2970 
   2971 func Test_diffanchors_scrollbind_topline2()
   2972  CheckScreendump
   2973 
   2974  " More-complicated case with 3 files and multiple overlapping diff blocks
   2975  call WriteDiffFiles3(0,
   2976      \ ["anchor1"],
   2977      \ ["diff2a", "diff2b", "diff2c", "diff2d", "anchor2"],
   2978      \ ["diff3a", "diff3c", "diff3d", "anchor3", "diff3e"])
   2979  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
   2980 
   2981  call term_sendkeys(buf, ":1wincmd w\<CR>:setlocal dia=1,1,2\<CR>")
   2982  call term_sendkeys(buf, ":2wincmd w\<CR>:setlocal dia=3,5,6\<CR>")
   2983  call term_sendkeys(buf, ":3wincmd w\<CR>:setlocal dia=2,4,5\<CR>")
   2984 
   2985  call VerifyInternal(buf, "Test_diff_anchors_scrollbind_topline_08", " diffopt+=anchor")
   2986  call term_sendkeys(buf, ":1wincmd w\<CR>")
   2987  call term_sendkeys(buf, "\<C-E>")
   2988  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_09", {})
   2989  call term_sendkeys(buf, "\<C-E>")
   2990  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_10", {})
   2991  call term_sendkeys(buf, "\<C-E>")
   2992  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_11", {})
   2993  call term_sendkeys(buf, "\<C-E>")
   2994  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_12", {})
   2995 
   2996  " Also test no-filler
   2997  call term_sendkeys(buf, ":3wincmd w\<CR>gg")
   2998  call VerifyInternal(buf, "Test_diff_anchors_scrollbind_topline_13", " diffopt+=anchor diffopt-=filler")
   2999  call term_sendkeys(buf, "\<Esc>\<C-E>")
   3000  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_14", {})
   3001  call term_sendkeys(buf, "\<C-E>")
   3002  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_15", {})
   3003  call term_sendkeys(buf, "\<C-E>")
   3004  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_16", {})
   3005  call term_sendkeys(buf, "\<C-E>")
   3006  call VerifyScreenDump(buf, "Test_diff_anchors_scrollbind_topline_17", {})
   3007 
   3008  call StopVimInTerminal(buf)
   3009 endfunc
   3010 
   3011 " Test that setting 'diffanchors' will update the diff.
   3012 func Test_diffanchors_option_set_update()
   3013  set diffanchors='a diffopt=internal,filler,anchor
   3014 
   3015  " Set up 3 tabs that share some buffers, and set up marks on each of them.
   3016  " We want to make sure only relevant tabs are updated if buffer-local diff
   3017  " anchors are updated, but all tabs should refresh if global diff anchors
   3018  " are updated (see diffanchors_changed() in code).
   3019 
   3020  " Tab 1. A buffer here will be reused.
   3021  call setline(1, range(1, 10))
   3022  3mark a
   3023  4mark b
   3024  diffthis
   3025  new
   3026  call setline(1, range(21, 25))
   3027  let buf = bufnr()
   3028  1mark a
   3029  2mark b
   3030  diffthis
   3031  call assert_equal(2, diff_filler(1))
   3032  call assert_equal(0, diff_filler(2))
   3033 
   3034  " Tab 2. "buf" is here but intentionally not participating in diff.
   3035  tabnew
   3036  exec 'buf ' .. buf
   3037  diffoff
   3038  new
   3039  call setline(1, range(31, 40))
   3040  8mark a
   3041  9mark b
   3042  diffthis
   3043  new
   3044  call setline(1, range(41, 50))
   3045  5mark a
   3046  6mark b
   3047  diffthis
   3048 
   3049  call assert_equal(3, diff_filler(5))
   3050  call assert_equal(0, diff_filler(6))
   3051  call assert_equal(0, diff_filler(7))
   3052 
   3053  " Update mark a location, and check that the diff has *not* updated. When
   3054  " updating marks diff's won't automatically update.
   3055  7mark a
   3056  call assert_equal(3, diff_filler(5))
   3057  call assert_equal(0, diff_filler(6))
   3058  call assert_equal(0, diff_filler(7))
   3059 
   3060  " Tab 3. "buf" is used here and also in a diff.
   3061  tabnew
   3062  call setline(1, range(51, 65))
   3063  10mark a
   3064  11mark b
   3065  diffthis
   3066  exec 'sbuffer ' .. buf
   3067  diffthis
   3068 
   3069  " Change local diff anchor of "buf" to mark b
   3070  setlocal diffanchors='b
   3071 
   3072  " Tab 1 should immediately update the diff to use mark b because the buf
   3073  " local diff anchor has been changed in "buf".
   3074  1tabnext
   3075  call assert_equal(0, diff_filler(1))
   3076  call assert_equal(1, diff_filler(2))
   3077 
   3078  " Tab 2 should not immediately update because "buf" is not a diff buffer
   3079  " here.
   3080  2tabnext
   3081  call assert_equal(3, diff_filler(5))
   3082  call assert_equal(0, diff_filler(6))
   3083  call assert_equal(0, diff_filler(7))
   3084 
   3085  " Manual diff update would refresh the diff since we previously changed mark
   3086  " a's location above.
   3087  diffupdate
   3088  call assert_equal(0, diff_filler(5))
   3089  call assert_equal(0, diff_filler(6))
   3090  call assert_equal(1, diff_filler(7))
   3091 
   3092  " Go back to tab 1. Reset diff anchor to global value and make sure it uses
   3093  " mark a again.
   3094  1tabnext
   3095  set diffanchors<
   3096  call assert_equal(2, diff_filler(1))
   3097  call assert_equal(0, diff_filler(2))
   3098 
   3099  " Now, change the global diff anchor to mark b. This should affect all tabs
   3100  " including tab 2 which should update automatically.
   3101  set diffanchors='b
   3102  call assert_equal(0, diff_filler(1))
   3103  call assert_equal(2, diff_filler(2))
   3104 
   3105  2tabnext
   3106  call assert_equal(0, diff_filler(5))
   3107  call assert_equal(3, diff_filler(6))
   3108  call assert_equal(0, diff_filler(7))
   3109 
   3110  %bw!
   3111  set diffopt&
   3112  set diffanchors&
   3113 endfunc
   3114 
   3115 " Test that using diff anchors with window/buffer-local addresses will work as
   3116 " expected and use the relevant window/buffer instead of curbuf/curwin.
   3117 func Test_diffanchors_buf_win_local_addresses()
   3118  " Win 1-3 point to buffer 1. Set up different window-specific jump history
   3119  " Win 2 is the one we activate diff mode on.
   3120  call setline(1, range(1, 15))
   3121  norm 2gg
   3122  norm 3gg
   3123 
   3124  split
   3125  norm 4gg
   3126  norm 5gg
   3127 
   3128  split
   3129  norm 11gg
   3130  norm 12gg
   3131  call setline(10, 'new text 1') " update the '. mark to line 10
   3132 
   3133  " Win 4 points to buffer 2
   3134  botright vert new
   3135  call setline(1, range(101, 110))
   3136  norm 8gg
   3137  norm 9gg
   3138  call setline(3, 'new text 2') " update the '. mark to line 3
   3139 
   3140  2wincmd w
   3141  diffthis
   3142  4wincmd w
   3143  diffthis
   3144 
   3145  " Test buffer-local marks using '. Should be anchored to lines 10 / 3.
   3146  set diffopt=internal,filler,anchor
   3147  set diffanchors='.
   3148  4wincmd w
   3149  call assert_equal(7, diff_filler(3))
   3150 
   3151  " Test window-local marks using '' Should be anchored to lines 4 / 8.
   3152  " Note that windows 1 & 3 point to the buffer being diff'ed but are not used
   3153  " for diffing themselves and therefore should not be used. Windows 2 & 4
   3154  " should be used.
   3155  set diffanchors=''
   3156  2wincmd w
   3157  call assert_equal(4, diff_filler(4))
   3158 
   3159  " Also test "." for the current cursor position, which is also
   3160  " window-specific. Make sure the cursor position at the longer file doesn't
   3161  " result in the other file using out of bounds line number.
   3162  4wincmd w
   3163  norm G
   3164  2wincmd w
   3165  norm G
   3166  set diffanchors=.
   3167  diffupdate
   3168  4wincmd w
   3169  call assert_equal(5, diff_filler(10))
   3170 
   3171  %bw!
   3172  set diffopt&
   3173  set diffanchors&
   3174 endfunc
   3175 
   3176 " Test diff anchors error handling for anchors that fail to resolve to a line.
   3177 " These are not handled during option parsing because they depend on the
   3178 " specifics of the buffer at diff time.
   3179 func Test_diffanchors_invalid()
   3180  call setline(1, range(1, 5))
   3181  new
   3182  call setline(1, range(11, 20))
   3183  set diffopt=internal,filler,anchor
   3184  windo diffthis
   3185  1wincmd w
   3186 
   3187  " Line numbers that are out of bounds should be an error
   3188  set diffanchors=0
   3189  call assert_fails('diffupdate', 'E16:')
   3190  set diffanchors=1
   3191  diffupdate
   3192  set diffanchors=$
   3193  diffupdate
   3194  set diffanchors=$+1
   3195  diffupdate
   3196  set diffanchors=$+2
   3197  call assert_fails('diffupdate', 'E16:')
   3198 
   3199  " Test that non-existent marks in any one buffer will be detected
   3200  set diffanchors='a
   3201  call assert_fails('diffupdate', 'E20:')
   3202  2mark a
   3203  call assert_fails('diffupdate', 'E20:')
   3204 
   3205  set diffanchors=1
   3206  setlocal diffanchors='a
   3207  diffupdate
   3208 
   3209  set diffanchors<
   3210  windo 2mark a
   3211  set diffanchors='b
   3212  call assert_fails('diffupdate', 'E20:')
   3213  set diffanchors='a
   3214  diffupdate
   3215 
   3216  " File marks are ok to use for anchors only if it is in the same file
   3217  1wincmd w
   3218  3mark C
   3219  setlocal diffanchors='C
   3220  diffupdate
   3221  set diffanchors='C
   3222  call assert_fails('diffupdate', 'E20:')
   3223 
   3224  " Buffer-local marks also can only be used in buffers that have them.
   3225  set diffanchors=1
   3226  exec "norm 1ggVj\<Esc>"
   3227  setlocal diffanchors='<
   3228  diffupdate
   3229  set diffanchors='<
   3230  call assert_fails('diffupdate', 'E20:')
   3231 
   3232  " Pattern search that failed will be an error too
   3233  let @/='orig_search_pat'
   3234  set diffanchors=1/5/
   3235  diffupdate
   3236  call assert_equal('orig_search_pat', @/) " also check we don't pollute the search register
   3237  set diffanchors=1/does_not_exist/
   3238  call assert_fails('diffupdate', 'E1550:')
   3239  call assert_equal('orig_search_pat', @/)
   3240 
   3241  " Hidden buffers are not supported right now
   3242  hide
   3243  call assert_fails('diffupdate', 'E1562:')
   3244 
   3245  %bw!
   3246  set diffopt&
   3247  set diffanchors&
   3248 endfunc
   3249 
   3250 " Test diffget/diffput behaviors when using diff anchors which could create
   3251 " adjacent diff blocks.
   3252 func Test_diffget_diffput_diffanchors()
   3253  set diffanchors=1/anchor/
   3254  set diffopt=internal,filler,anchor
   3255 
   3256  call setline(1, ['1', 'anchor1', '4'])
   3257  diffthis
   3258  new
   3259  call setline(1, ['2', '3', 'anchor2', '4', '5'])
   3260  diffthis
   3261  wincmd w
   3262 
   3263  " Test using no-range diffget. It should grab the closest diff block only,
   3264  " even if there are multiple adjacent blocks.
   3265  2
   3266  diffget
   3267  call assert_equal(['1', 'anchor2', '4'], getline(1, '$'))
   3268  diffget
   3269  call assert_equal(['2', '3', 'anchor2', '4'], getline(1, '$'))
   3270 
   3271  " Test using a range to get/put all the adjacent diff blocks.
   3272  1,$delete
   3273  call setline(1, ['anchor1', '4'])
   3274  0,1 diffget
   3275  call assert_equal(['2', '3', 'anchor2', '4'], getline(1, '$'))
   3276 
   3277  1,$delete
   3278  call setline(1, ['anchor1', '4'])
   3279  0,$+1 diffget
   3280  call assert_equal(['2', '3', 'anchor2', '4', '5'], getline(1, '$'))
   3281 
   3282  1,$delete
   3283  call setline(1, ['anchor1', '4'])
   3284  0,1 diffput
   3285  wincmd w
   3286  call assert_equal(['anchor1', '4', '5'], getline(1,'$'))
   3287 
   3288  %bw!
   3289  set diffopt&
   3290  set diffanchors&
   3291 endfunc
   3292 
   3293 func Test_diff_add_prop_in_autocmd()
   3294  CheckScreendump
   3295 
   3296  let lines =<< trim END
   3297    func MyDiff() abort
   3298      let f1 = readfile(v:fname_in)
   3299      let f2 = readfile(v:fname_new)
   3300      let f0 = diff(f1, f2)
   3301      call writefile(split(f0, "\n"), v:fname_out)
   3302    endfunc
   3303 
   3304    call prop_type_add('myprop', #{highlight: 'Search', override: 1})
   3305    autocmd OptionSet diff call prop_add(1, 1, #{type: 'myprop', length: 100})
   3306    set diffexpr=MyDiff()
   3307  END
   3308  call writefile(lines, 'Xtest_diff_add_prop_in_autocmd', 'D')
   3309  call writefile(['foo', 'bar', 'baz'], 'Xdiffsplit_file', 'D')
   3310 
   3311  let buf = RunVimInTerminal('-S Xtest_diff_add_prop_in_autocmd', {})
   3312  call term_sendkeys(buf, ":diffsplit Xdiffsplit_file\<CR>")
   3313  call VerifyScreenDump(buf, 'Test_diff_add_prop_in_autocmd_01', {})
   3314 
   3315  call StopVimInTerminal(buf)
   3316 endfunc
   3317 
   3318 " this was causing a use-after-free by calling winframe_remove() recursively
   3319 func Test_diffexpr_wipe_buffers()
   3320  CheckRunVimInTerminal
   3321 
   3322  let lines =<< trim END
   3323    def DiffFuncExpr()
   3324      var in: list<string> = readfile(v:fname_in)
   3325      var new = readfile(v:fname_new)
   3326      var out: string = diff(in, new)
   3327      writefile(split(out, "n"), v:fname_out)
   3328    enddef
   3329 
   3330    new
   3331    vnew
   3332    set diffexpr=DiffFuncExpr()
   3333    wincmd l
   3334    new
   3335    cal setline(1,range(20))
   3336    wind difft
   3337    wincm w
   3338    hid
   3339    %bw!
   3340  END
   3341  call writefile(lines, 'Xtest_diffexpr_wipe', 'D')
   3342 
   3343  let buf = RunVimInTerminal('Xtest_diffexpr_wipe', {})
   3344  call term_sendkeys(buf, ":so\<CR>")
   3345  call WaitForAssert({-> assert_match('4 buffers wiped out', term_getline(buf, 20))})
   3346 
   3347  call StopVimInTerminal(buf)
   3348 endfunc
   3349 
   3350 func Test_diffput_to_empty_buf()
   3351  CheckScreendump
   3352 
   3353  let lines =<< trim END
   3354    call setline(1, ['foo', 'bar', 'baz'])
   3355    rightbelow vnew
   3356    windo diffthis
   3357    windo set cursorline nofoldenable
   3358    wincmd t
   3359  END
   3360  call writefile(lines, 'Xtest_diffput_to_empty_buf', 'D')
   3361 
   3362  let buf = RunVimInTerminal('-S Xtest_diffput_to_empty_buf', {})
   3363  call VerifyScreenDump(buf, 'Test_diffput_to_empty_buf_01', {})
   3364  call term_sendkeys(buf, '0')  " Trigger an initial 'cursorbind' check.
   3365  call VerifyScreenDump(buf, 'Test_diffput_to_empty_buf_01', {})
   3366  call term_sendkeys(buf, ":diffput | echo\<CR>")
   3367  call VerifyScreenDump(buf, 'Test_diffput_to_empty_buf_02', {})
   3368  call term_sendkeys(buf, ":redraw!\<CR>")
   3369  call VerifyScreenDump(buf, 'Test_diffput_to_empty_buf_02', {})
   3370  call term_sendkeys(buf, 'j')
   3371  call VerifyScreenDump(buf, 'Test_diffput_to_empty_buf_03', {})
   3372 
   3373  call StopVimInTerminal(buf)
   3374 endfunc
   3375 
   3376 " vim: shiftwidth=2 sts=2 expandtab