blob: 1ab194568b2ff4be75ea3e2850ebcc50cb581815 [file] [log] [blame]
Bram Moolenaar42093c02016-07-30 16:16:54 +02001" Tests for diff mode
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02002
Bram Moolenaare828b762018-09-10 17:51:58 +02003source shared.vim
4source screendump.vim
Bram Moolenaar3c8ee622019-08-03 22:55:50 +02005source check.vim
zeertzjq9e7f1fc2024-03-16 09:40:22 +01006source view_util.vim
Bram Moolenaar42093c02016-07-30 16:16:54 +02007
8func Test_diff_fold_sync()
9 enew!
Bram Moolenaare8fa05b2018-09-16 15:48:06 +020010 let g:update_count = 0
11 au DiffUpdated * let g:update_count += 1
12
Bram Moolenaar42093c02016-07-30 16:16:54 +020013 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
Bram Moolenaarf65cc662022-06-26 18:17:50 +010038 " depending on how redraw is done DiffUpdated may be triggered once or twice
39 call assert_inrange(1, 2, g:update_count)
Bram Moolenaare8fa05b2018-09-16 15:48:06 +020040 au! DiffUpdated
41
Bram Moolenaar42093c02016-07-30 16:16:54 +020042 windo diffoff
43 close!
44 set nomodified
45endfunc
46
47func Test_vert_split()
Bram Moolenaare828b762018-09-10 17:51:58 +020048 set diffopt=filler
49 call Common_vert_split()
50 set diffopt&
51endfunc
52
Gary Johnson3fa0d352025-06-08 16:00:06 +020053" Test for diff folding redraw after last diff is resolved
54func Test_diff_fold_redraw()
Gary Johnson69565e32025-06-09 20:19:35 +020055 " Set up two files with a minimal case.
Gary Johnson3fa0d352025-06-08 16:00:06 +020056 call writefile(['Paragraph 1', '', 'Paragraph 2', '', 'Paragraph 3'], 'Xfile1')
57 call writefile(['Paragraph 1', '', 'Paragraph 3'], 'Xfile2')
58
Gary Johnson69565e32025-06-09 20:19:35 +020059 " Open in diff mode.
60 edit Xfile1
61 vert diffsplit Xfile2
Gary Johnson3fa0d352025-06-08 16:00:06 +020062
Gary Johnson69565e32025-06-09 20:19:35 +020063 " Go to the diff and apply :diffput to copy Paragraph 2 to Xfile2.
64 wincmd l
65 3
66 diffput
Gary Johnson3fa0d352025-06-08 16:00:06 +020067
Gary Johnson69565e32025-06-09 20:19:35 +020068 " 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("$")))
Gary Johnson3fa0d352025-06-08 16:00:06 +020073
Gary Johnson69565e32025-06-09 20:19:35 +020074 " Clean up.
Gary Johnson3fa0d352025-06-08 16:00:06 +020075 bwipe!
76 bwipe!
77 call delete('Xfile1')
78 call delete('Xfile2')
79endfunc
80
Bram Moolenaare828b762018-09-10 17:51:58 +020081func Test_vert_split_internal()
82 set diffopt=internal,filler
83 call Common_vert_split()
84 set diffopt&
85endfunc
86
87func Common_vert_split()
Bram Moolenaar42093c02016-07-30 16:16:54 +020088 " 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!
zeertzjq5fd6ab82022-08-17 12:09:45 +0100170 1wincmd w
Bram Moolenaar42093c02016-07-30 16:16:54 +0200171 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
Bram Moolenaar623cf882016-07-30 16:36:01 +0200200 call delete('Xtest')
201 call delete('Xtest2')
Bram Moolenaar42093c02016-07-30 16:16:54 +0200202 windo bw!
203endfunc
204
205func 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
Bram Moolenaar90d121f2016-07-30 19:11:25 +0200217 windo diffoff
218 bwipe!
219 enew!
220endfunc
Bram Moolenaar42093c02016-07-30 16:16:54 +0200221
Bram Moolenaar90d121f2016-07-30 19:11:25 +0200222func 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
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200253 %bwipe!
254endfunc
255
Bram Moolenaar5f57bdc2018-10-25 17:52:23 +0200256" Test putting two changes from one buffer to another
257func 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
274endfunc
275
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200276" Test for :diffget/:diffput with a range that is inside a diff chunk
277func 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!
289endfunc
290
291" Test for :diffget/:diffput with an empty buffer and a non-empty buffer
292func Test_diffget_diffput_empty_buffer()
293 %d _
294 new
295 call setline(1, 'one')
296 windo diffthis
297 diffget
298 call assert_equal(['one'], getline(1, '$'))
299 %d _
300 diffput
301 wincmd p
302 call assert_equal([''], getline(1, '$'))
303 %bw!
304endfunc
305
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100306" :diffput and :diffget completes names of buffers which
Dominique Pelle923dce22021-11-21 11:36:04 +0000307" are in diff mode and which are different than current buffer.
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100308" No completion when the current window is not in diff mode.
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100309func Test_diffget_diffput_completion()
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100310 e Xdiff1 | diffthis
311 botright new Xdiff2
312 botright new Xdiff3 | split | diffthis
313 botright new Xdiff4 | diffthis
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100314
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100315 wincmd t
316 call assert_equal('Xdiff1', bufname('%'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100317 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100318 call assert_equal('"diffput Xdiff3 Xdiff4', @:)
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100319 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100320 call assert_equal('"diffget Xdiff3 Xdiff4', @:)
321 call assert_equal(['Xdiff3', 'Xdiff4'], getcompletion('', 'diff_buffer'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100322
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100323 " Xdiff2 is not in diff mode, so no completion for :diffput, :diffget
324 wincmd j
325 call assert_equal('Xdiff2', bufname('%'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100326 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
327 call assert_equal('"diffput ', @:)
328 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
329 call assert_equal('"diffget ', @:)
330 call assert_equal([], getcompletion('', 'diff_buffer'))
331
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100332 " Xdiff3 is split in 2 windows, only the top one is in diff mode.
333 " So completion of :diffput :diffget only happens in the top window.
334 wincmd j
335 call assert_equal('Xdiff3', bufname('%'))
336 call assert_equal(1, &diff)
337 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
338 call assert_equal('"diffput Xdiff1 Xdiff4', @:)
339 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
340 call assert_equal('"diffget Xdiff1 Xdiff4', @:)
341 call assert_equal(['Xdiff1', 'Xdiff4'], getcompletion('', 'diff_buffer'))
342
343 wincmd j
344 call assert_equal('Xdiff3', bufname('%'))
345 call assert_equal(0, &diff)
346 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
347 call assert_equal('"diffput ', @:)
348 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
349 call assert_equal('"diffget ', @:)
350 call assert_equal([], getcompletion('', 'diff_buffer'))
351
352 wincmd j
353 call assert_equal('Xdiff4', bufname('%'))
354 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
355 call assert_equal('"diffput Xdiff1 Xdiff3', @:)
356 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
357 call assert_equal('"diffget Xdiff1 Xdiff3', @:)
358 call assert_equal(['Xdiff1', 'Xdiff3'], getcompletion('', 'diff_buffer'))
359
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100360 %bwipe
361endfunc
362
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200363func Test_dp_do_buffer()
364 e! one
365 let bn1=bufnr('%')
366 let l = range(60)
367 call setline(1, l)
368 diffthis
369
370 new two
371 let l[10] = 'one'
372 let l[20] = 'two'
373 let l[30] = 'three'
374 let l[40] = 'four'
375 let l[50] = 'five'
376 call setline(1, l)
377 diffthis
378
379 " dp and do with invalid buffer number.
380 11
381 call assert_fails('norm 99999dp', 'E102:')
382 call assert_fails('norm 99999do', 'E102:')
383 call assert_fails('diffput non_existing_buffer', 'E94:')
384 call assert_fails('diffget non_existing_buffer', 'E94:')
385
386 " dp and do with valid buffer number.
387 call assert_equal('one', getline('.'))
388 exe 'norm ' . bn1 . 'do'
389 call assert_equal('10', getline('.'))
390 21
391 call assert_equal('two', getline('.'))
Bram Moolenaar94722c52023-01-28 19:19:03 +0000392 diffget one
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200393 call assert_equal('20', getline('.'))
394
395 31
396 exe 'norm ' . bn1 . 'dp'
397 41
398 diffput one
399 wincmd w
400 31
401 call assert_equal('three', getline('.'))
402 41
403 call assert_equal('four', getline('.'))
404
405 " dp and do with buffer number which is not in diff mode.
406 new not_in_diff_mode
407 let bn3=bufnr('%')
408 wincmd w
409 51
410 call assert_fails('exe "norm" . bn3 . "dp"', 'E103:')
411 call assert_fails('exe "norm" . bn3 . "do"', 'E103:')
412 call assert_fails('diffput not_in_diff_mode', 'E94:')
413 call assert_fails('diffget not_in_diff_mode', 'E94:')
414
415 windo diffoff
416 %bwipe!
Bram Moolenaar42093c02016-07-30 16:16:54 +0200417endfunc
Bram Moolenaare67d5462016-08-27 22:40:42 +0200418
Bram Moolenaardf77cef2018-10-07 17:46:42 +0200419func Test_do_lastline()
420 e! one
421 call setline(1, ['1','2','3','4','5','6'])
422 diffthis
423
424 new two
425 call setline(1, ['2','4','5'])
426 diffthis
427
428 1
429 norm dp]c
430 norm dp]c
431 wincmd w
432 call assert_equal(4, line('$'))
433 norm G
434 norm do
435 call assert_equal(3, line('$'))
436
437 windo diffoff
438 %bwipe!
439endfunc
440
Bram Moolenaare67d5462016-08-27 22:40:42 +0200441func Test_diffoff()
442 enew!
443 call setline(1, ['Two', 'Three'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200444 redraw
Bram Moolenaare67d5462016-08-27 22:40:42 +0200445 let normattr = screenattr(1, 1)
446 diffthis
447 botright vert new
448 call setline(1, ['One', '', 'Two', 'Three'])
449 diffthis
450 redraw
Bram Moolenaar196b4662019-09-06 21:34:30 +0200451 call assert_notequal(normattr, 1->screenattr(1))
Bram Moolenaare67d5462016-08-27 22:40:42 +0200452 diffoff!
453 redraw
454 call assert_equal(normattr, screenattr(1, 1))
455 bwipe!
456 bwipe!
457endfunc
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200458
Bram Moolenaare828b762018-09-10 17:51:58 +0200459func Common_icase_test()
460 edit one
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100461 call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#vϵ', 'Si⃗x', 'Se⃗ve⃗n'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200462 redraw
463 let normattr = screenattr(1, 1)
464 diffthis
465
466 botright vert new two
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100467 call setline(1, ['one', 'TWO', 'Three ', 'Four', 'fI=VΕ', 'SI⃗x', 'SEvE⃗n'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200468 diffthis
469
470 redraw
471 call assert_equal(normattr, screenattr(1, 1))
472 call assert_equal(normattr, screenattr(2, 1))
473 call assert_notequal(normattr, screenattr(3, 1))
474 call assert_equal(normattr, screenattr(4, 1))
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100475 call assert_equal(normattr, screenattr(6, 2))
476 call assert_notequal(normattr, screenattr(7, 2))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200477
Bram Moolenaarda22b8c2017-09-02 18:01:50 +0200478 let dtextattr = screenattr(5, 3)
479 call assert_notequal(dtextattr, screenattr(5, 1))
480 call assert_notequal(dtextattr, screenattr(5, 5))
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100481 call assert_notequal(dtextattr, screenattr(7, 4))
Bram Moolenaarda22b8c2017-09-02 18:01:50 +0200482
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200483 diffoff!
484 %bwipe!
Bram Moolenaare828b762018-09-10 17:51:58 +0200485endfunc
486
487func Test_diffopt_icase()
488 set diffopt=icase,foldcolumn:0
489 call Common_icase_test()
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200490 set diffopt&
491endfunc
492
Bram Moolenaare828b762018-09-10 17:51:58 +0200493func Test_diffopt_icase_internal()
494 set diffopt=icase,foldcolumn:0,internal
495 call Common_icase_test()
496 set diffopt&
497endfunc
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200498
Bram Moolenaare828b762018-09-10 17:51:58 +0200499func Common_iwhite_test()
500 edit one
501 " Difference in trailing spaces and amount of spaces should be ignored,
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200502 " but not other space differences.
Bram Moolenaare828b762018-09-10 17:51:58 +0200503 call setline(1, ["One \t", 'Two', 'Three', 'one two', 'one two', 'Four'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200504 redraw
505 let normattr = screenattr(1, 1)
506 diffthis
507
508 botright vert new two
Bram Moolenaare828b762018-09-10 17:51:58 +0200509 call setline(1, ["One\t ", "Two\t ", 'Three', 'one two', 'onetwo', ' Four'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200510 diffthis
511
512 redraw
513 call assert_equal(normattr, screenattr(1, 1))
514 call assert_equal(normattr, screenattr(2, 1))
515 call assert_equal(normattr, screenattr(3, 1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200516 call assert_equal(normattr, screenattr(4, 1))
517 call assert_notequal(normattr, screenattr(5, 1))
518 call assert_notequal(normattr, screenattr(6, 1))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200519
520 diffoff!
521 %bwipe!
Bram Moolenaare828b762018-09-10 17:51:58 +0200522endfunc
523
524func Test_diffopt_iwhite()
525 set diffopt=iwhite,foldcolumn:0
526 call Common_iwhite_test()
527 set diffopt&
528endfunc
529
530func Test_diffopt_iwhite_internal()
531 set diffopt=internal,iwhite,foldcolumn:0
532 call Common_iwhite_test()
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200533 set diffopt&
534endfunc
535
536func Test_diffopt_context()
537 enew!
538 call setline(1, ['1', '2', '3', '4', '5', '6', '7'])
539 diffthis
540 new
541 call setline(1, ['1', '2', '3', '4', '5x', '6', '7'])
542 diffthis
543
544 set diffopt=context:2
545 call assert_equal('+-- 2 lines: 1', foldtextresult(1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200546 set diffopt=internal,context:2
547 call assert_equal('+-- 2 lines: 1', foldtextresult(1))
548
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200549 set diffopt=context:1
550 call assert_equal('+-- 3 lines: 1', foldtextresult(1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200551 set diffopt=internal,context:1
552 call assert_equal('+-- 3 lines: 1', foldtextresult(1))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200553
554 diffoff!
555 %bwipe!
556 set diffopt&
557endfunc
558
559func Test_diffopt_horizontal()
Bram Moolenaare828b762018-09-10 17:51:58 +0200560 set diffopt=internal,horizontal
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200561 diffsplit
562
563 call assert_equal(&columns, winwidth(1))
564 call assert_equal(&columns, winwidth(2))
565 call assert_equal(&lines, winheight(1) + winheight(2) + 3)
566 call assert_inrange(0, 1, winheight(1) - winheight(2))
567
568 set diffopt&
569 diffoff!
570 %bwipe
571endfunc
572
573func Test_diffopt_vertical()
Bram Moolenaare828b762018-09-10 17:51:58 +0200574 set diffopt=internal,vertical
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200575 diffsplit
576
577 call assert_equal(&lines - 2, winheight(1))
578 call assert_equal(&lines - 2, winheight(2))
579 call assert_equal(&columns, winwidth(1) + winwidth(2) + 1)
580 call assert_inrange(0, 1, winwidth(1) - winwidth(2))
581
582 set diffopt&
583 diffoff!
584 %bwipe
585endfunc
586
Bram Moolenaar97ce4192017-12-01 20:35:58 +0100587func Test_diffopt_hiddenoff()
Bram Moolenaare828b762018-09-10 17:51:58 +0200588 set diffopt=internal,filler,foldcolumn:0,hiddenoff
Bram Moolenaar97ce4192017-12-01 20:35:58 +0100589 e! one
590 call setline(1, ['Two', 'Three'])
591 redraw
592 let normattr = screenattr(1, 1)
593 diffthis
594 botright vert new two
595 call setline(1, ['One', 'Four'])
596 diffthis
597 redraw
598 call assert_notequal(normattr, screenattr(1, 1))
599 set hidden
600 close
601 redraw
602 " should not diffing with hidden buffer two while 'hiddenoff' is enabled
603 call assert_equal(normattr, screenattr(1, 1))
604
605 bwipe!
606 bwipe!
607 set hidden& diffopt&
608endfunc
609
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100610func Test_diffoff_hidden()
Bram Moolenaare828b762018-09-10 17:51:58 +0200611 set diffopt=internal,filler,foldcolumn:0
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100612 e! one
613 call setline(1, ['Two', 'Three'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200614 redraw
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100615 let normattr = screenattr(1, 1)
616 diffthis
617 botright vert new two
618 call setline(1, ['One', 'Four'])
619 diffthis
620 redraw
621 call assert_notequal(normattr, screenattr(1, 1))
622 set hidden
623 close
624 redraw
625 " diffing with hidden buffer two
626 call assert_notequal(normattr, screenattr(1, 1))
627 diffoff
628 redraw
629 call assert_equal(normattr, screenattr(1, 1))
630 diffthis
631 redraw
632 " still diffing with hidden buffer two
633 call assert_notequal(normattr, screenattr(1, 1))
634 diffoff!
635 redraw
636 call assert_equal(normattr, screenattr(1, 1))
637 diffthis
638 redraw
639 " no longer diffing with hidden buffer two
640 call assert_equal(normattr, screenattr(1, 1))
641
642 bwipe!
643 bwipe!
644 set hidden& diffopt&
645endfunc
646
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200647func Test_setting_cursor()
648 new Xtest1
649 put =range(1,90)
650 wq
651 new Xtest2
652 put =range(1,100)
653 wq
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200654
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200655 tabe Xtest2
656 $
657 diffsp Xtest1
658 tabclose
659
660 call delete('Xtest1')
661 call delete('Xtest2')
662endfunc
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100663
664func Test_diff_move_to()
665 new
666 call setline(1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
667 diffthis
668 vnew
669 call setline(1, [1, '2x', 3, 4, 4, 5, '6x', 7, '8x', 9, '10x'])
670 diffthis
671 norm ]c
672 call assert_equal(2, line('.'))
673 norm 3]c
674 call assert_equal(9, line('.'))
675 norm 10]c
676 call assert_equal(11, line('.'))
677 norm [c
678 call assert_equal(9, line('.'))
679 norm 2[c
680 call assert_equal(5, line('.'))
681 norm 10[c
682 call assert_equal(2, line('.'))
683 %bwipe!
684endfunc
685
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200686func Test_diffexpr()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +0100687 CheckExecutable diff
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200688
689 func DiffExpr()
Bram Moolenaar485b6272021-05-18 19:19:03 +0200690 " Prepend some text to check diff type detection
Bram Moolenaar3b8defd2018-09-13 13:03:11 +0200691 call writefile(['warning', ' message'], v:fname_out)
692 silent exe '!diff ' . v:fname_in . ' ' . v:fname_new . '>>' . v:fname_out
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200693 endfunc
694 set diffexpr=DiffExpr()
695 set diffopt=foldcolumn:0
696
697 enew!
698 call setline(1, ['one', 'two', 'three'])
699 redraw
700 let normattr = screenattr(1, 1)
701 diffthis
702
703 botright vert new
704 call setline(1, ['one', 'two', 'three.'])
705 diffthis
706
707 redraw
708 call assert_equal(normattr, screenattr(1, 1))
709 call assert_equal(normattr, screenattr(2, 1))
710 call assert_notequal(normattr, screenattr(3, 1))
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200711 diffoff!
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200712
Dominique Pelle923dce22021-11-21 11:36:04 +0000713 " Try using a non-existing function for 'diffexpr'.
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200714 set diffexpr=NewDiffFunc()
715 call assert_fails('windo diffthis', ['E117:', 'E97:'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200716 diffoff!
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +0000717
718 " Using a script-local function
719 func s:NewDiffExpr()
720 endfunc
721 set diffexpr=s:NewDiffExpr()
722 call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
723 set diffexpr=<SID>NewDiffExpr()
724 call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
725
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200726 %bwipe!
727 set diffexpr& diffopt&
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +0000728 delfunc DiffExpr
729 delfunc s:NewDiffExpr
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200730endfunc
731
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100732func Test_diffpatch()
733 " The patch program on MS-Windows may fail or hang.
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200734 CheckExecutable patch
735 CheckUnix
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100736 new
737 insert
738***************
739*** 1,3 ****
740 1
741! 2
742 3
743--- 1,4 ----
744 1
745! 2x
746 3
747+ 4
748.
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200749 saveas! Xpatch
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100750 bwipe!
751 new
752 call assert_fails('diffpatch Xpatch', 'E816:')
Bram Moolenaar1ef73e32017-03-09 19:21:30 +0100753
Bram Moolenaara95ab322017-03-11 19:21:53 +0100754 for name in ['Xpatch', 'Xpatch$HOME', 'Xpa''tch']
Bram Moolenaar1ef73e32017-03-09 19:21:30 +0100755 call setline(1, ['1', '2', '3'])
756 if name != 'Xpatch'
757 call rename('Xpatch', name)
758 endif
759 exe 'diffpatch ' . escape(name, '$')
760 call assert_equal(['1', '2x', '3', '4'], getline(1, '$'))
761 if name != 'Xpatch'
762 call rename(name, 'Xpatch')
763 endif
764 bwipe!
765 endfor
766
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100767 call delete('Xpatch')
768 bwipe!
769endfunc
770
Bram Moolenaar23a971d2023-04-04 22:04:53 +0100771" FIXME: test fails, the Xresult file can't be read
772func No_Test_diffpatch_restricted()
773 let lines =<< trim END
774 call assert_fails('diffpatch NoSuchDiff', 'E145:')
775
776 call writefile(v:errors, 'Xresult')
777 qa!
778 END
779 call writefile(lines, 'Xrestricted', 'D')
780 if RunVim([], [], '-Z --clean -S Xrestricted')
781 call assert_equal([], readfile('Xresult'))
782 endif
783 call delete('Xresult')
784endfunc
785
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100786func Test_diff_too_many_buffers()
787 for i in range(1, 8)
788 exe "new Xtest" . i
789 diffthis
790 endfor
791 new Xtest9
792 call assert_fails('diffthis', 'E96:')
793 %bwipe!
794endfunc
795
796func Test_diff_nomodifiable()
797 new
798 call setline(1, [1, 2, 3, 4])
799 setl nomodifiable
800 diffthis
801 vnew
802 call setline(1, ['1x', 2, 3, 3, 4])
803 diffthis
804 call assert_fails('norm dp', 'E793:')
805 setl nomodifiable
806 call assert_fails('norm do', 'E21:')
807 %bwipe!
808endfunc
Bram Moolenaarf58a8472017-03-05 18:03:04 +0100809
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200810func Test_diff_hlID()
811 new
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100812 call setline(1, [1, 2, 3, 'Yz', 'a dxxg',])
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200813 diffthis
814 vnew
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100815 call setline(1, ['1x', 2, 'x', 3, 'yx', 'abc defg'])
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200816 diffthis
817 redraw
818
Bram Moolenaara74e4942019-08-04 17:35:53 +0200819 call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("")
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200820
Bram Moolenaara74e4942019-08-04 17:35:53 +0200821 call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange")
822 call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText")
823 call diff_hlID(2, 1)->synIDattr("name")->assert_equal("")
824 call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd")
Bram Moolenaar1a3a8912019-08-23 22:31:37 +0200825 eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("")
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100826 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
827 call diff_hlID(5, 2)->synIDattr("name")->assert_equal("DiffText")
828
829 set diffopt+=icase " test that caching is invalidated by diffopt change
830 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffChange")
831 set diffopt-=icase
832 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
833
834 call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
835 call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffText")
836 call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffText")
837 call diff_hlID(6, 7)->synIDattr("name")->assert_equal("DiffText")
838 call diff_hlID(6, 8)->synIDattr("name")->assert_equal("DiffChange")
839 set diffopt+=inline:char
840 call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
841 call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffTextAdd")
842 call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffChange")
843 call diff_hlID(6, 7)->synIDattr("name")->assert_equal("DiffText")
844 call diff_hlID(6, 8)->synIDattr("name")->assert_equal("DiffChange")
845 set diffopt-=inline:char
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200846
847 wincmd w
848 call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange")
849 call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "")
850 call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "")
851
852 %bwipe!
853endfunc
854
855func Test_diff_filler()
856 new
857 call setline(1, [1, 2, 3, 'x', 4])
858 diffthis
859 vnew
860 call setline(1, [1, 2, 'y', 'y', 3, 4])
861 diffthis
862 redraw
863
Bram Moolenaar1a3a8912019-08-23 22:31:37 +0200864 call assert_equal([0, 0, 0, 0, 0, 0, 0, 1, 0], map(range(-1, 7), 'v:val->diff_filler()'))
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200865 wincmd w
866 call assert_equal([0, 0, 0, 0, 2, 0, 0, 0], map(range(-1, 6), 'diff_filler(v:val)'))
867
868 %bwipe!
869endfunc
870
Bram Moolenaarf58a8472017-03-05 18:03:04 +0100871func Test_diff_lastline()
872 enew!
873 only!
874 call setline(1, ['This is a ', 'line with five ', 'rows'])
875 diffthis
876 botright vert new
877 call setline(1, ['This is', 'a line with ', 'four rows'])
878 diffthis
879 1
880 call feedkeys("Je a\<CR>", 'tx')
881 call feedkeys("Je a\<CR>", 'tx')
882 let w1lines = winline()
883 wincmd w
884 $
885 let w2lines = winline()
886 call assert_equal(w2lines, w1lines)
887 bwipe!
888 bwipe!
889endfunc
Bram Moolenaare828b762018-09-10 17:51:58 +0200890
Bram Moolenaar785fc652018-09-15 19:17:38 +0200891func WriteDiffFiles(buf, list1, list2)
Bram Moolenaar61abe7d2022-08-30 21:46:08 +0100892 call writefile(a:list1, 'Xdifile1')
893 call writefile(a:list2, 'Xdifile2')
Bram Moolenaar785fc652018-09-15 19:17:38 +0200894 if a:buf
895 call term_sendkeys(a:buf, ":checktime\<CR>")
896 endif
Bram Moolenaare828b762018-09-10 17:51:58 +0200897endfunc
898
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +0200899func WriteDiffFiles3(buf, list1, list2, list3)
900 call writefile(a:list1, 'Xdifile1')
901 call writefile(a:list2, 'Xdifile2')
902 call writefile(a:list3, 'Xdifile3')
903 if a:buf
904 call term_sendkeys(a:buf, ":checktime\<CR>")
905 endif
906endfunc
907
Bram Moolenaar785fc652018-09-15 19:17:38 +0200908" Verify a screendump with both the internal and external diff.
Bram Moolenaare828b762018-09-10 17:51:58 +0200909func VerifyBoth(buf, dumpfile, extra)
Drew Vogelea67ba72025-05-07 22:05:17 +0200910 CheckScreendump
911
Bram Moolenaare828b762018-09-10 17:51:58 +0200912 " trailing : for leaving the cursor on the command line
Bram Moolenaar785fc652018-09-15 19:17:38 +0200913 for cmd in [":set diffopt=filler" . a:extra . "\<CR>:", ":set diffopt+=internal\<CR>:"]
Bram Moolenaare828b762018-09-10 17:51:58 +0200914 call term_sendkeys(a:buf, cmd)
915 if VerifyScreenDump(a:buf, a:dumpfile, {}, cmd =~ 'internal' ? 'internal' : 'external')
Bram Moolenaar485b6272021-05-18 19:19:03 +0200916 " don't let the next iteration overwrite the "failed" file.
917 return
Bram Moolenaare828b762018-09-10 17:51:58 +0200918 endif
919 endfor
Bram Moolenaar485b6272021-05-18 19:19:03 +0200920
921 " also test unified diff
922 call term_sendkeys(a:buf, ":call SetupUnified()\<CR>:")
glacambread5c1782021-05-24 14:20:53 +0200923 call term_sendkeys(a:buf, ":redraw!\<CR>:")
Bram Moolenaar485b6272021-05-18 19:19:03 +0200924 call VerifyScreenDump(a:buf, a:dumpfile, {}, 'unified')
925 call term_sendkeys(a:buf, ":call StopUnified()\<CR>:")
Bram Moolenaare828b762018-09-10 17:51:58 +0200926endfunc
927
Bram Moolenaar785fc652018-09-15 19:17:38 +0200928" Verify a screendump with the internal diff only.
929func VerifyInternal(buf, dumpfile, extra)
Drew Vogelea67ba72025-05-07 22:05:17 +0200930 CheckScreendump
931
Bram Moolenaar785fc652018-09-15 19:17:38 +0200932 call term_sendkeys(a:buf, ":diffupdate!\<CR>")
933 " trailing : for leaving the cursor on the command line
934 call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:")
935 call VerifyScreenDump(a:buf, a:dumpfile, {})
936endfunc
937
Bram Moolenaare828b762018-09-10 17:51:58 +0200938func Test_diff_screen()
Yee Cheng Chin49f2ba62024-02-14 20:34:58 +0100939 if has('osxdarwin') && system('diff --version') =~ '^Apple diff'
940 throw 'Skipped: unified diff does not work properly on this macOS version'
rhysde93d5ca2024-02-01 21:22:14 +0100941 endif
942
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100943 let g:test_is_flaky = 1
Bram Moolenaar3c8ee622019-08-03 22:55:50 +0200944 CheckScreendump
945 CheckFeature menu
946
Bram Moolenaar485b6272021-05-18 19:19:03 +0200947 let lines =<< trim END
948 func UnifiedDiffExpr()
949 " Prepend some text to check diff type detection
950 call writefile(['warning', ' message'], v:fname_out)
glacambread5c1782021-05-24 14:20:53 +0200951 silent exe '!diff -U0 ' .. v:fname_in .. ' ' .. v:fname_new .. '>>' .. v:fname_out
Bram Moolenaar485b6272021-05-18 19:19:03 +0200952 endfunc
953 func SetupUnified()
954 set diffexpr=UnifiedDiffExpr()
glacambread5c1782021-05-24 14:20:53 +0200955 diffupdate
Bram Moolenaar485b6272021-05-18 19:19:03 +0200956 endfunc
957 func StopUnified()
958 set diffexpr=
959 endfunc
960 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100961 call writefile(lines, 'XdiffSetup', 'D')
Bram Moolenaar485b6272021-05-18 19:19:03 +0200962
Bram Moolenaare828b762018-09-10 17:51:58 +0200963 " clean up already existing swap files, just in case
Bram Moolenaar61abe7d2022-08-30 21:46:08 +0100964 call delete('.Xdifile1.swp')
965 call delete('.Xdifile2.swp')
Bram Moolenaare828b762018-09-10 17:51:58 +0200966
967 " Test 1: Add a line in beginning of file 2
Bram Moolenaar785fc652018-09-15 19:17:38 +0200968 call WriteDiffFiles(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Bram Moolenaar61abe7d2022-08-30 21:46:08 +0100969 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
Bram Moolenaar8ee4c012019-03-29 18:08:18 +0100970 " Set autoread mode, so that Vim won't complain once we re-write the test
Bram Moolenaare828b762018-09-10 17:51:58 +0200971 " files
Bram Moolenaar785fc652018-09-15 19:17:38 +0200972 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
Bram Moolenaare828b762018-09-10 17:51:58 +0200973
974 call VerifyBoth(buf, 'Test_diff_01', '')
975
976 " Test 2: Add a line in beginning of file 1
Bram Moolenaar785fc652018-09-15 19:17:38 +0200977 call WriteDiffFiles(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Bram Moolenaare828b762018-09-10 17:51:58 +0200978 call VerifyBoth(buf, 'Test_diff_02', '')
979
980 " Test 3: Add a line at the end of file 2
Bram Moolenaar785fc652018-09-15 19:17:38 +0200981 call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
Bram Moolenaare828b762018-09-10 17:51:58 +0200982 call VerifyBoth(buf, 'Test_diff_03', '')
983
984 " Test 4: Add a line at the end of file 1
Bram Moolenaar785fc652018-09-15 19:17:38 +0200985 call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Bram Moolenaare828b762018-09-10 17:51:58 +0200986 call VerifyBoth(buf, 'Test_diff_04', '')
987
988 " Test 5: Add a line in the middle of file 2, remove on at the end of file 1
Bram Moolenaar785fc652018-09-15 19:17:38 +0200989 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])
Bram Moolenaare828b762018-09-10 17:51:58 +0200990 call VerifyBoth(buf, 'Test_diff_05', '')
991
992 " Test 6: Add a line in the middle of file 1, remove on at the end of file 2
Bram Moolenaar785fc652018-09-15 19:17:38 +0200993 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])
Bram Moolenaare828b762018-09-10 17:51:58 +0200994 call VerifyBoth(buf, 'Test_diff_06', '')
995
Bram Moolenaarb9ddda62019-02-19 23:00:50 +0100996 " Variants on test 6 with different context settings
997 call term_sendkeys(buf, ":set diffopt+=context:2\<cr>")
998 call VerifyScreenDump(buf, 'Test_diff_06.2', {})
999 call term_sendkeys(buf, ":set diffopt-=context:2\<cr>")
1000 call term_sendkeys(buf, ":set diffopt+=context:1\<cr>")
1001 call VerifyScreenDump(buf, 'Test_diff_06.1', {})
1002 call term_sendkeys(buf, ":set diffopt-=context:1\<cr>")
1003 call term_sendkeys(buf, ":set diffopt+=context:0\<cr>")
1004 call VerifyScreenDump(buf, 'Test_diff_06.0', {})
1005 call term_sendkeys(buf, ":set diffopt-=context:0\<cr>")
1006
Bram Moolenaare828b762018-09-10 17:51:58 +02001007 " Test 7 - 9: Test normal/patience/histogram diff algorithm
Bram Moolenaar785fc652018-09-15 19:17:38 +02001008 call WriteDiffFiles(buf, ['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
Bram Moolenaare828b762018-09-10 17:51:58 +02001009 \ ' int i;', ' for(i = 0; i < 10; i++)', ' {', ' printf("Your answer is: ");',
1010 \ ' printf("%d\n", foo);', ' }', '}', '', 'int fact(int n)', '{', ' if(n > 1)', ' {',
1011 \ ' return fact(n-1) * n;', ' }', ' return 1;', '}', '', 'int main(int argc, char **argv)',
1012 \ '{', ' frobnitz(fact(10));', '}'],
1013 \ ['#include <stdio.h>', '', 'int fib(int n)', '{', ' if(n > 2)', ' {',
1014 \ ' return fib(n-1) + fib(n-2);', ' }', ' return 1;', '}', '', '// Frobs foo heartily',
1015 \ 'int frobnitz(int foo)', '{', ' int i;', ' for(i = 0; i < 10; i++)', ' {',
1016 \ ' printf("%d\n", foo);', ' }', '}', '',
1017 \ 'int main(int argc, char **argv)', '{', ' frobnitz(fib(10));', '}'])
1018 call term_sendkeys(buf, ":diffupdate!\<cr>")
1019 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1020 call VerifyScreenDump(buf, 'Test_diff_07', {})
1021
1022 call term_sendkeys(buf, ":set diffopt+=algorithm:patience\<cr>")
1023 call VerifyScreenDump(buf, 'Test_diff_08', {})
1024
1025 call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>")
1026 call VerifyScreenDump(buf, 'Test_diff_09', {})
1027
1028 " Test 10-11: normal/indent-heuristic
1029 call term_sendkeys(buf, ":set diffopt&vim\<cr>")
Bram Moolenaar785fc652018-09-15 19:17:38 +02001030 call WriteDiffFiles(buf, ['', ' def finalize(values)', '', ' values.each do |v|', ' v.finalize', ' end'],
Bram Moolenaare828b762018-09-10 17:51:58 +02001031 \ ['', ' def finalize(values)', '', ' values.each do |v|', ' v.prepare', ' end', '',
1032 \ ' values.each do |v|', ' v.finalize', ' end'])
1033 call term_sendkeys(buf, ":diffupdate!\<cr>")
1034 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1035 call VerifyScreenDump(buf, 'Test_diff_10', {})
1036
Bram Moolenaarb6fc7282018-12-04 22:24:16 +01001037 " Leave trailing : at commandline!
1038 call term_sendkeys(buf, ":set diffopt+=indent-heuristic\<cr>:\<cr>")
1039 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'one')
1040 " shouldn't matter, if indent-algorithm comes before or after the algorithm
1041 call term_sendkeys(buf, ":set diffopt&\<cr>")
1042 call term_sendkeys(buf, ":set diffopt+=indent-heuristic,algorithm:patience\<cr>:\<cr>")
1043 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'two')
1044 call term_sendkeys(buf, ":set diffopt&\<cr>")
1045 call term_sendkeys(buf, ":set diffopt+=algorithm:patience,indent-heuristic\<cr>:\<cr>")
1046 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'three')
Bram Moolenaare828b762018-09-10 17:51:58 +02001047
1048 " Test 12: diff the same file
Bram Moolenaar785fc652018-09-15 19:17:38 +02001049 call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Bram Moolenaare828b762018-09-10 17:51:58 +02001050 call VerifyBoth(buf, 'Test_diff_12', '')
1051
1052 " Test 13: diff an empty file
Bram Moolenaar785fc652018-09-15 19:17:38 +02001053 call WriteDiffFiles(buf, [], [])
Bram Moolenaare828b762018-09-10 17:51:58 +02001054 call VerifyBoth(buf, 'Test_diff_13', '')
1055
1056 " Test 14: test diffopt+=icase
Bram Moolenaar785fc652018-09-15 19:17:38 +02001057 call WriteDiffFiles(buf, ['a', 'b', 'cd'], ['A', 'b', 'cDe'])
Bram Moolenaare828b762018-09-10 17:51:58 +02001058 call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase")
1059
1060 " Test 15-16: test diffopt+=iwhite
Bram Moolenaar785fc652018-09-15 19:17:38 +02001061 call WriteDiffFiles(buf, ['int main()', '{', ' printf("Hello, World!");', ' return 0;', '}'],
Bram Moolenaare828b762018-09-10 17:51:58 +02001062 \ ['int main()', '{', ' if (0)', ' {', ' printf("Hello, World!");', ' return 0;', ' }', '}'])
1063 call term_sendkeys(buf, ":diffupdate!\<cr>")
1064 call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>")
1065 call VerifyScreenDump(buf, 'Test_diff_15', {})
1066 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1067 call VerifyScreenDump(buf, 'Test_diff_16', {})
1068
Bram Moolenaar785fc652018-09-15 19:17:38 +02001069 " Test 17: test diffopt+=iblank
1070 call WriteDiffFiles(buf, ['a', ' ', 'cd', 'ef', 'xxx'], ['a', 'cd', '', 'ef', 'yyy'])
1071 call VerifyInternal(buf, 'Test_diff_17', " diffopt+=iblank")
1072
1073 " Test 18: test diffopt+=iblank,iwhite / iwhiteall / iwhiteeol
1074 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhite")
1075 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteall")
1076 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteeol")
1077
1078 " Test 19: test diffopt+=iwhiteeol
1079 call WriteDiffFiles(buf, ['a ', 'x', 'cd', 'ef', 'xx xx', 'foo', 'bar'], ['a', 'x', 'c d', ' ef', 'xx xx', 'foo', '', 'bar'])
1080 call VerifyInternal(buf, 'Test_diff_19', " diffopt+=iwhiteeol")
1081
Yukihiro Nakadairaf1694b42024-09-22 11:26:13 +02001082 " Test 20: test diffopt+=iwhiteall
Bram Moolenaar785fc652018-09-15 19:17:38 +02001083 call VerifyInternal(buf, 'Test_diff_20', " diffopt+=iwhiteall")
1084
Yukihiro Nakadairaf1694b42024-09-22 11:26:13 +02001085 " Test 21: Delete all lines
1086 call WriteDiffFiles(buf, [0], [])
1087 call VerifyBoth(buf, "Test_diff_21", "")
1088
1089 " Test 22: Add line to empty file
1090 call WriteDiffFiles(buf, [], [0])
1091 call VerifyBoth(buf, "Test_diff_22", "")
1092
Jonathon7c7a4e62025-01-12 09:58:00 +01001093 call WriteDiffFiles(buf, ['?a', '?b', '?c'], ['!b'])
1094 call VerifyInternal(buf, 'Test_diff_23', " diffopt+=linematch:30")
1095
1096 call WriteDiffFiles(buf, ['',
1097 \ 'common line',
1098 \ 'common line',
1099 \ '',
1100 \ 'DEFabc',
1101 \ 'xyz',
1102 \ 'xyz',
1103 \ 'xyz',
1104 \ 'DEFabc',
1105 \ 'DEFabc',
1106 \ 'DEFabc',
1107 \ 'common line',
1108 \ 'common line',
1109 \ 'DEF',
1110 \ 'common line',
1111 \ 'DEF',
1112 \ 'something' ],
1113 \ ['',
1114 \ 'common line',
1115 \ 'common line',
1116 \ '',
1117 \ 'ABCabc',
1118 \ 'ABCabc',
1119 \ 'ABCabc',
1120 \ 'ABCabc',
1121 \ 'common line',
1122 \ 'common line',
1123 \ 'common line',
1124 \ 'something'])
1125 call VerifyInternal(buf, 'Test_diff_24', " diffopt+=linematch:30")
1126
1127
Bram Moolenaare828b762018-09-10 17:51:58 +02001128 " clean up
1129 call StopVimInTerminal(buf)
Bram Moolenaar61abe7d2022-08-30 21:46:08 +01001130 call delete('Xdifile1')
1131 call delete('Xdifile2')
Bram Moolenaare828b762018-09-10 17:51:58 +02001132endfunc
1133
Bram Moolenaar04626c22021-09-01 16:02:07 +02001134func Test_diff_with_scroll_and_change()
1135 CheckScreendump
1136
1137 let lines =<< trim END
1138 call setline(1, range(1, 15))
1139 vnew
1140 call setline(1, range(9, 15))
1141 windo diffthis
1142 wincmd h
1143 exe "normal Gl5\<C-E>"
1144 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001145 call writefile(lines, 'Xtest_scroll_change', 'D')
Bram Moolenaar04626c22021-09-01 16:02:07 +02001146 let buf = RunVimInTerminal('-S Xtest_scroll_change', {})
1147
1148 call VerifyScreenDump(buf, 'Test_diff_scroll_change_01', {})
1149
1150 call term_sendkeys(buf, "ax\<Esc>")
1151 call VerifyScreenDump(buf, 'Test_diff_scroll_change_02', {})
1152
Bram Moolenaar841c2252021-10-22 20:56:55 +01001153 call term_sendkeys(buf, "\<C-W>lay\<Esc>")
1154 call VerifyScreenDump(buf, 'Test_diff_scroll_change_03', {})
1155
Bram Moolenaar04626c22021-09-01 16:02:07 +02001156 " clean up
1157 call StopVimInTerminal(buf)
Bram Moolenaar04626c22021-09-01 16:02:07 +02001158endfunc
1159
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001160func Test_diff_with_cursorline()
Bram Moolenaar3c8ee622019-08-03 22:55:50 +02001161 CheckScreendump
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001162
1163 call writefile([
1164 \ 'hi CursorLine ctermbg=red ctermfg=white',
1165 \ 'set cursorline',
1166 \ 'call setline(1, ["foo","foo","foo","bar"])',
1167 \ 'vnew',
1168 \ 'call setline(1, ["bee","foo","foo","baz"])',
1169 \ 'windo diffthis',
1170 \ '2wincmd w',
Bram Moolenaar59173412022-09-20 22:01:33 +01001171 \ ], 'Xtest_diff_cursorline', 'D')
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001172 let buf = RunVimInTerminal('-S Xtest_diff_cursorline', {})
1173
1174 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_01', {})
1175 call term_sendkeys(buf, "j")
1176 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_02', {})
1177 call term_sendkeys(buf, "j")
1178 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_03', {})
1179
1180 " clean up
1181 call StopVimInTerminal(buf)
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001182endfunc
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001183
Bram Moolenaar127969c2022-03-06 19:54:13 +00001184func Test_diff_with_cursorline_number()
1185 CheckScreendump
1186
1187 let lines =<< trim END
1188 hi CursorLine ctermbg=red ctermfg=white
1189 hi CursorLineNr ctermbg=white ctermfg=black cterm=underline
1190 set cursorline number
1191 call setline(1, ["baz", "foo", "foo", "bar"])
1192 2
1193 vnew
1194 call setline(1, ["foo", "foo", "bar"])
1195 windo diffthis
1196 1wincmd w
1197 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001198 call writefile(lines, 'Xtest_diff_cursorline_number', 'D')
Bram Moolenaar127969c2022-03-06 19:54:13 +00001199 let buf = RunVimInTerminal('-S Xtest_diff_cursorline_number', {})
1200
1201 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_01', {})
1202 call term_sendkeys(buf, ":set cursorlineopt=number\r")
1203 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_02', {})
1204
1205 " clean up
1206 call StopVimInTerminal(buf)
Bram Moolenaar127969c2022-03-06 19:54:13 +00001207endfunc
1208
zeertzjq4f33bc22021-08-05 17:57:02 +02001209func Test_diff_with_cursorline_breakindent()
1210 CheckScreendump
1211
zeertzjq588f20d2023-12-05 15:47:09 +01001212 let lines =<< trim END
1213 hi CursorLine ctermbg=red ctermfg=white
1214 set noequalalways wrap diffopt=followwrap cursorline breakindent
1215 50vnew
1216 call setline(1, [' ', ' ', ' ', ' '])
1217 exe "norm! 20Afoo\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abar\<Esc>"
1218 vnew
1219 call setline(1, [' ', ' ', ' ', ' '])
1220 exe "norm! 20Abee\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abaz\<Esc>"
1221 windo diffthis
1222 2wincmd w
1223 END
1224 call writefile(lines, 'Xtest_diff_cursorline_breakindent', 'D')
zeertzjq4f33bc22021-08-05 17:57:02 +02001225 let buf = RunVimInTerminal('-S Xtest_diff_cursorline_breakindent', {})
1226
1227 call term_sendkeys(buf, "gg0")
1228 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_01', {})
1229 call term_sendkeys(buf, "j")
1230 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_02', {})
1231 call term_sendkeys(buf, "j")
1232 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_03', {})
1233 call term_sendkeys(buf, "j")
1234 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_04', {})
1235
1236 " clean up
1237 call StopVimInTerminal(buf)
zeertzjq4f33bc22021-08-05 17:57:02 +02001238endfunc
1239
zeertzjq588f20d2023-12-05 15:47:09 +01001240func Test_diff_breakindent_after_filler()
1241 CheckScreendump
1242
1243 let lines =<< trim END
zeertzjqf0a9d652024-02-12 22:53:20 +01001244 set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0
zeertzjq588f20d2023-12-05 15:47:09 +01001245 call setline(1, ['a', ' ' .. repeat('c', 50)])
1246 vnew
1247 call setline(1, ['a', 'b', ' ' .. repeat('c', 50)])
1248 windo diffthis
1249 norm! G$
1250 END
1251 call writefile(lines, 'Xtest_diff_breakindent_after_filler', 'D')
1252 let buf = RunVimInTerminal('-S Xtest_diff_breakindent_after_filler', #{rows: 8, cols: 45})
1253 call VerifyScreenDump(buf, 'Test_diff_breakindent_after_filler', {})
1254
1255 " clean up
1256 call StopVimInTerminal(buf)
1257endfunc
1258
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001259func Test_diff_with_syntax()
1260 CheckScreendump
1261
1262 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001263 void doNothing() {
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001264 int x = 0;
1265 char *s = "hello";
1266 return 5;
1267 }
1268 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001269 call writefile(lines, 'Xprogram1.c', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001270 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001271 void doSomething() {
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001272 int x = 0;
1273 char *s = "there";
1274 return 5;
1275 }
1276 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001277 call writefile(lines, 'Xprogram2.c', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001278
1279 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001280 edit Xprogram1.c
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001281 diffsplit Xprogram2.c
1282 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001283 call writefile(lines, 'Xtest_diff_syntax', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001284 let buf = RunVimInTerminal('-S Xtest_diff_syntax', {})
1285
1286 call VerifyScreenDump(buf, 'Test_diff_syntax_1', {})
1287
1288 " clean up
1289 call StopVimInTerminal(buf)
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001290endfunc
1291
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001292func Test_diff_of_diff()
Bram Moolenaar3c8ee622019-08-03 22:55:50 +02001293 CheckScreendump
1294 CheckFeature rightleft
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001295
1296 call writefile([
1297 \ 'call setline(1, ["aa","bb","cc","@@ -3,2 +5,7 @@","dd","ee","ff"])',
1298 \ 'vnew',
1299 \ 'call setline(1, ["aa","bb","cc"])',
1300 \ 'windo diffthis',
Bram Moolenaar8ee4c012019-03-29 18:08:18 +01001301 \ '1wincmd w',
1302 \ 'setlocal number',
Bram Moolenaar59173412022-09-20 22:01:33 +01001303 \ ], 'Xtest_diff_diff', 'D')
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001304 let buf = RunVimInTerminal('-S Xtest_diff_diff', {})
1305
1306 call VerifyScreenDump(buf, 'Test_diff_of_diff_01', {})
1307
Bram Moolenaare73f9112019-03-29 18:29:54 +01001308 call term_sendkeys(buf, ":set rightleft\<cr>")
1309 call VerifyScreenDump(buf, 'Test_diff_of_diff_02', {})
1310
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001311 " clean up
1312 call StopVimInTerminal(buf)
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001313endfunc
Bram Moolenaarc8234772019-11-10 21:00:27 +01001314
1315func CloseoffSetup()
1316 enew
1317 call setline(1, ['one', 'two', 'three'])
1318 diffthis
1319 new
1320 call setline(1, ['one', 'tow', 'three'])
1321 diffthis
1322 call assert_equal(1, &diff)
Jonathonca307ef2025-01-17 13:37:35 +01001323 bw!
Bram Moolenaarc8234772019-11-10 21:00:27 +01001324endfunc
1325
1326func Test_diff_closeoff()
1327 " "closeoff" included by default: last diff win gets 'diff' reset'
1328 call CloseoffSetup()
1329 call assert_equal(0, &diff)
1330 enew!
1331
1332 " "closeoff" excluded: last diff win keeps 'diff' set'
1333 set diffopt-=closeoff
1334 call CloseoffSetup()
1335 call assert_equal(1, &diff)
1336 diffoff!
1337 enew!
1338endfunc
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001339
Bram Moolenaar4223d432021-02-10 13:18:17 +01001340func Test_diff_followwrap()
1341 new
1342 set diffopt+=followwrap
1343 set wrap
1344 diffthis
1345 call assert_equal(1, &wrap)
1346 diffoff
1347 set nowrap
1348 diffthis
1349 call assert_equal(0, &wrap)
1350 diffoff
1351 set diffopt&
1352 bwipe!
1353endfunc
1354
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001355func Test_diff_maintains_change_mark()
Sean Dewarccc16442021-12-29 16:44:48 +00001356 func DiffMaintainsChangeMark()
1357 enew!
1358 call setline(1, ['a', 'b', 'c', 'd'])
1359 diffthis
1360 new
1361 call setline(1, ['a', 'b', 'c', 'e'])
1362 " Set '[ and '] marks
1363 2,3yank
1364 call assert_equal([2, 3], [line("'["), line("']")])
1365 " Verify they aren't affected by the implicit diff
1366 diffthis
1367 call assert_equal([2, 3], [line("'["), line("']")])
1368 " Verify they aren't affected by an explicit diff
1369 diffupdate
1370 call assert_equal([2, 3], [line("'["), line("']")])
1371 bwipe!
1372 bwipe!
1373 endfunc
1374
1375 set diffopt-=internal
1376 call DiffMaintainsChangeMark()
1377 set diffopt+=internal
1378 call DiffMaintainsChangeMark()
Bram Moolenaard9b74a22022-01-16 15:00:08 +00001379
Sean Dewarccc16442021-12-29 16:44:48 +00001380 set diffopt&
Bram Moolenaard9b74a22022-01-16 15:00:08 +00001381 delfunc DiffMaintainsChangeMark
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001382endfunc
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001383
1384" Test for 'patchexpr'
1385func Test_patchexpr()
1386 let g:patch_args = []
1387 func TPatch()
1388 call add(g:patch_args, readfile(v:fname_in))
1389 call add(g:patch_args, readfile(v:fname_diff))
1390 call writefile(['output file'], v:fname_out)
1391 endfunc
1392 set patchexpr=TPatch()
1393
Bram Moolenaar59173412022-09-20 22:01:33 +01001394 call writefile(['input file'], 'Xinput', 'D')
1395 call writefile(['diff file'], 'Xdiff', 'D')
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001396 %bwipe!
1397 edit Xinput
1398 diffpatch Xdiff
1399 call assert_equal('output file', getline(1))
1400 call assert_equal('Xinput.new', bufname())
1401 call assert_equal(2, winnr('$'))
1402 call assert_true(&diff)
1403
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001404 " Using a script-local function
1405 func s:NewPatchExpr()
1406 endfunc
1407 set patchexpr=s:NewPatchExpr()
1408 call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
1409 set patchexpr=<SID>NewPatchExpr()
1410 call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
1411
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001412 set patchexpr&
1413 delfunc TPatch
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001414 delfunc s:NewPatchExpr
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001415 %bwipe!
1416endfunc
1417
Bram Moolenaar511feec2020-06-18 19:15:27 +02001418func Test_diff_rnu()
1419 CheckScreendump
1420
1421 let content =<< trim END
1422 call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
1423 vnew
1424 call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
1425 windo diffthis
1426 setlocal number rnu foldcolumn=0
1427 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001428 call writefile(content, 'Xtest_diff_rnu', 'D')
Bram Moolenaar511feec2020-06-18 19:15:27 +02001429 let buf = RunVimInTerminal('-S Xtest_diff_rnu', {})
1430
1431 call VerifyScreenDump(buf, 'Test_diff_rnu_01', {})
1432
1433 call term_sendkeys(buf, "j")
1434 call VerifyScreenDump(buf, 'Test_diff_rnu_02', {})
1435 call term_sendkeys(buf, "j")
1436 call VerifyScreenDump(buf, 'Test_diff_rnu_03', {})
1437
1438 " clean up
1439 call StopVimInTerminal(buf)
Bram Moolenaar511feec2020-06-18 19:15:27 +02001440endfunc
1441
Bram Moolenaarfc838d62020-06-25 22:23:48 +02001442func Test_diff_multilineconceal()
1443 new
1444 diffthis
1445
1446 new
1447 call matchadd('Conceal', 'a\nb', 9, -1, {'conceal': 'Y'})
1448 set cole=2 cocu=n
1449 call setline(1, ["a", "b"])
1450 diffthis
1451 redraw
1452endfunc
1453
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001454func Test_diff_and_scroll()
1455 " this was causing an ml_get error
1456 set ls=2
Bram Moolenaar94722c52023-01-28 19:19:03 +00001457 for i in range(winheight(0) * 2)
1458 call setline(i, i < winheight(0) - 10 ? i : i + 10)
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001459 endfor
1460 vnew
Bram Moolenaar94722c52023-01-28 19:19:03 +00001461 for i in range(winheight(0)*2 + 10)
1462 call setline(i, i < winheight(0) - 10 ? 0 : i)
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001463 endfor
1464 diffthis
1465 wincmd p
1466 diffthis
1467 execute 'normal ' . winheight(0) . "\<C-d>"
1468
1469 bwipe!
1470 bwipe!
1471 set ls&
1472endfunc
1473
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001474func Test_diff_filler_cursorcolumn()
1475 CheckScreendump
1476
1477 let content =<< trim END
1478 call setline(1, ['aa', 'bb', 'cc'])
1479 vnew
1480 call setline(1, ['aa', 'cc'])
1481 windo diffthis
1482 wincmd p
1483 setlocal cursorcolumn foldcolumn=0
1484 norm! gg0
1485 redraw!
1486 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001487 call writefile(content, 'Xtest_diff_cuc', 'D')
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001488 let buf = RunVimInTerminal('-S Xtest_diff_cuc', {})
1489
1490 call VerifyScreenDump(buf, 'Test_diff_cuc_01', {})
1491
1492 call term_sendkeys(buf, "l")
1493 call term_sendkeys(buf, "\<C-l>")
1494 call VerifyScreenDump(buf, 'Test_diff_cuc_02', {})
1495 call term_sendkeys(buf, "0j")
1496 call term_sendkeys(buf, "\<C-l>")
1497 call VerifyScreenDump(buf, 'Test_diff_cuc_03', {})
1498 call term_sendkeys(buf, "l")
1499 call term_sendkeys(buf, "\<C-l>")
1500 call VerifyScreenDump(buf, 'Test_diff_cuc_04', {})
1501
1502 " clean up
1503 call StopVimInTerminal(buf)
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001504endfunc
1505
Yegappan Lakshmanan30443242021-06-10 21:52:15 +02001506" Test for adding/removing lines inside diff chunks, between diff chunks
1507" and before diff chunks
1508func Test_diff_modify_chunks()
1509 enew!
1510 let w2_id = win_getid()
1511 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1512 new
1513 let w1_id = win_getid()
1514 call setline(1, ['a', '2', '3', 'd', 'e', 'f', '7', '8', 'i'])
1515 windo diffthis
1516
1517 " remove a line between two diff chunks and create a new diff chunk
1518 call win_gotoid(w2_id)
1519 5d
1520 call win_gotoid(w1_id)
1521 call diff_hlID(5, 1)->synIDattr('name')->assert_equal('DiffAdd')
1522
1523 " add a line between two diff chunks
1524 call win_gotoid(w2_id)
1525 normal! 4Goe
1526 call win_gotoid(w1_id)
1527 call diff_hlID(4, 1)->synIDattr('name')->assert_equal('')
1528 call diff_hlID(5, 1)->synIDattr('name')->assert_equal('')
1529
1530 " remove all the lines in a diff chunk.
1531 call win_gotoid(w2_id)
1532 7,8d
1533 call win_gotoid(w1_id)
1534 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1535 call assert_equal(['', 'DiffText', 'DiffText', '', '', '', 'DiffAdd',
1536 \ 'DiffAdd', ''], hl)
1537
1538 " remove lines from one diff chunk to just before the next diff chunk
1539 call win_gotoid(w2_id)
1540 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1541 2,6d
1542 call win_gotoid(w1_id)
1543 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1544 call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', 'DiffAdd',
1545 \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
1546
1547 " remove lines just before the top of a diff chunk
1548 call win_gotoid(w2_id)
1549 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1550 5,6d
1551 call win_gotoid(w1_id)
1552 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1553 call assert_equal(['', 'DiffText', 'DiffText', '', 'DiffText', 'DiffText',
1554 \ 'DiffAdd', 'DiffAdd', ''], hl)
1555
1556 " remove line after the end of a diff chunk
1557 call win_gotoid(w2_id)
1558 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1559 4d
1560 call win_gotoid(w1_id)
1561 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1562 call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', '', '', 'DiffText',
1563 \ 'DiffText', ''], hl)
1564
1565 " remove lines starting from the end of one diff chunk and ending inside
1566 " another diff chunk
1567 call win_gotoid(w2_id)
1568 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1569 4,7d
1570 call win_gotoid(w1_id)
1571 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1572 call assert_equal(['', 'DiffText', 'DiffText', 'DiffText', 'DiffAdd',
1573 \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
1574
1575 " removing the only remaining diff chunk should make the files equal
1576 call win_gotoid(w2_id)
1577 call setline(1, ['a', '2', '3', 'x', 'd', 'e', 'f', 'x', '7', '8', 'i'])
1578 8d
1579 let hl = range(1, 10)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1580 call assert_equal(['', '', '', 'DiffAdd', '', '', '', '', '', ''], hl)
1581 call win_gotoid(w2_id)
1582 4d
1583 call win_gotoid(w1_id)
1584 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1585 call assert_equal(['', '', '', '', '', '', '', '', ''], hl)
1586
1587 %bw!
1588endfunc
glacambread5c1782021-05-24 14:20:53 +02001589
Bram Moolenaar06f60952021-12-28 18:30:05 +00001590func Test_diff_binary()
1591 CheckScreendump
1592
1593 let content =<< trim END
1594 call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g'])
1595 vnew
1596 call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g'])
1597 windo diffthis
1598 wincmd p
1599 norm! gg0
1600 redraw!
1601 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001602 call writefile(content, 'Xtest_diff_bin', 'D')
Bram Moolenaar06f60952021-12-28 18:30:05 +00001603 let buf = RunVimInTerminal('-S Xtest_diff_bin', {})
1604
1605 " Test using internal diff
1606 call VerifyScreenDump(buf, 'Test_diff_bin_01', {})
1607
1608 " Test using internal diff and case folding
1609 call term_sendkeys(buf, ":set diffopt+=icase\<cr>")
1610 call term_sendkeys(buf, "\<C-l>")
1611 call VerifyScreenDump(buf, 'Test_diff_bin_02', {})
1612 " Test using external diff
1613 call term_sendkeys(buf, ":set diffopt=filler\<cr>")
1614 call term_sendkeys(buf, "\<C-l>")
1615 call VerifyScreenDump(buf, 'Test_diff_bin_03', {})
1616 " Test using external diff and case folding
1617 call term_sendkeys(buf, ":set diffopt=filler,icase\<cr>")
1618 call term_sendkeys(buf, "\<C-l>")
1619 call VerifyScreenDump(buf, 'Test_diff_bin_04', {})
1620
1621 " clean up
1622 call StopVimInTerminal(buf)
Bram Moolenaar06f60952021-12-28 18:30:05 +00001623 set diffopt&vim
1624endfunc
1625
Yegappan Lakshmananb0ad2d92022-01-27 13:16:59 +00001626" Test for using the 'zi' command to invert 'foldenable' in diff windows (test
1627" for the issue fixed by patch 6.2.317)
1628func Test_diff_foldinvert()
1629 %bw!
Bram Moolenaar61abe7d2022-08-30 21:46:08 +01001630 edit Xdoffile1
1631 new Xdoffile2
1632 new Xdoffile3
Yegappan Lakshmananb0ad2d92022-01-27 13:16:59 +00001633 windo diffthis
1634 " open a non-diff window
1635 botright new
1636 1wincmd w
1637 call assert_true(getwinvar(1, '&foldenable'))
1638 call assert_true(getwinvar(2, '&foldenable'))
1639 call assert_true(getwinvar(3, '&foldenable'))
1640 normal zi
1641 call assert_false(getwinvar(1, '&foldenable'))
1642 call assert_false(getwinvar(2, '&foldenable'))
1643 call assert_false(getwinvar(3, '&foldenable'))
1644 normal zi
1645 call assert_true(getwinvar(1, '&foldenable'))
1646 call assert_true(getwinvar(2, '&foldenable'))
1647 call assert_true(getwinvar(3, '&foldenable'))
1648
1649 " If the current window has 'noscrollbind', then 'zi' should not change
1650 " 'foldenable' in other windows.
1651 1wincmd w
1652 set noscrollbind
1653 normal zi
1654 call assert_false(getwinvar(1, '&foldenable'))
1655 call assert_true(getwinvar(2, '&foldenable'))
1656 call assert_true(getwinvar(3, '&foldenable'))
1657
1658 " 'zi' should not change the 'foldenable' for windows with 'noscrollbind'
1659 1wincmd w
1660 set scrollbind
1661 normal zi
1662 call setwinvar(2, '&scrollbind', v:false)
1663 normal zi
1664 call assert_false(getwinvar(1, '&foldenable'))
1665 call assert_true(getwinvar(2, '&foldenable'))
1666 call assert_false(getwinvar(3, '&foldenable'))
1667
1668 %bw!
1669 set scrollbind&
1670endfunc
1671
Bram Moolenaara315ce12022-06-24 12:38:57 +01001672" This was scrolling for 'cursorbind' but 'scrollbind' is more important
1673func Test_diff_scroll()
1674 CheckScreendump
1675
1676 let left =<< trim END
1677 line 1
1678 line 2
1679 line 3
1680 line 4
1681
1682 // Common block
1683 // one
1684 // containing
1685 // four lines
1686
1687 // Common block
1688 // two
1689 // containing
1690 // four lines
1691 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001692 call writefile(left, 'Xleft', 'D')
Bram Moolenaara315ce12022-06-24 12:38:57 +01001693 let right =<< trim END
1694 line 1
1695 line 2
1696 line 3
1697 line 4
1698
1699 Lorem
1700 ipsum
1701 dolor
1702 sit
1703 amet,
1704 consectetur
1705 adipiscing
1706 elit.
1707 Etiam
1708 luctus
1709 lectus
1710 sodales,
1711 dictum
1712
1713 // Common block
1714 // one
1715 // containing
1716 // four lines
1717
1718 Vestibulum
1719 tincidunt
1720 aliquet
1721 nulla.
1722
1723 // Common block
1724 // two
1725 // containing
1726 // four lines
1727 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001728 call writefile(right, 'Xright', 'D')
Bram Moolenaara315ce12022-06-24 12:38:57 +01001729 let buf = RunVimInTerminal('-d Xleft Xright', {'rows': 12})
1730 call term_sendkeys(buf, "\<C-W>\<C-W>jjjj")
1731 call VerifyScreenDump(buf, 'Test_diff_scroll_1', {})
1732 call term_sendkeys(buf, "j")
1733 call VerifyScreenDump(buf, 'Test_diff_scroll_2', {})
1734
1735 call StopVimInTerminal(buf)
Bram Moolenaara315ce12022-06-24 12:38:57 +01001736endfunc
1737
Bram Moolenaar38d867f2023-04-01 19:54:40 +01001738" This was scrolling too many lines.
1739func Test_diff_scroll_wrap_on()
1740 20new
1741 40vsplit
1742 call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
1743 setlocal number diff so=0
1744 redraw
1745 normal! jj
1746 call assert_equal(1, winsaveview().topline)
1747 normal! j
1748 call assert_equal(2, winsaveview().topline)
zeertzjq05834912023-10-04 20:12:37 +02001749
1750 bwipe!
1751 bwipe!
1752endfunc
1753
1754func Test_diff_scroll_many_filler()
1755 20new
1756 vnew
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001757 call setline(1, range(1, 40))
zeertzjq05834912023-10-04 20:12:37 +02001758 diffthis
1759 setlocal scrolloff=0
1760 wincmd p
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001761 call setline(1, range(1, 20)->reverse() + ['###']->repeat(41) + range(21, 40)->reverse())
zeertzjq05834912023-10-04 20:12:37 +02001762 diffthis
1763 setlocal scrolloff=0
1764 wincmd p
1765 redraw
1766
1767 " Note: need a redraw after each scroll, otherwise the test always passes.
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001768 for _ in range(2)
1769 normal! G
1770 redraw
1771 call assert_equal(40, winsaveview().topline)
1772 call assert_equal(19, winsaveview().topfill)
1773 exe "normal! \<C-B>"
1774 redraw
1775 call assert_equal(22, winsaveview().topline)
1776 call assert_equal(0, winsaveview().topfill)
1777 exe "normal! \<C-B>"
1778 redraw
1779 call assert_equal(4, winsaveview().topline)
1780 call assert_equal(0, winsaveview().topfill)
1781 exe "normal! \<C-B>"
1782 redraw
1783 call assert_equal(1, winsaveview().topline)
1784 call assert_equal(0, winsaveview().topfill)
1785 set smoothscroll
1786 endfor
zeertzjq05834912023-10-04 20:12:37 +02001787
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001788 set smoothscroll&
Luuk van Baalcb204e62024-04-02 20:49:45 +02001789 %bwipe!
Bram Moolenaar38d867f2023-04-01 19:54:40 +01001790endfunc
1791
Bram Moolenaarcd38bb42022-06-26 14:04:07 +01001792" This was trying to update diffs for a buffer being closed
1793func Test_diff_only()
1794 silent! lfile
1795 set diff
1796 lopen
1797 norm o
1798 silent! norm o
1799
1800 set nodiff
1801 %bwipe!
1802endfunc
1803
Bram Moolenaarc101abf2022-06-26 16:53:34 +01001804" This was causing invalid diff block values
1805" FIXME: somehow this causes a valgrind error when run directly but not when
1806" run as a test.
1807func Test_diff_manipulations()
1808 set diff
1809 split 0
1810 sil! norm R doobdeuR doobdeuR doobdeu
1811
1812 set nodiff
1813 %bwipe!
1814endfunc
1815
Bram Moolenaar4e677b92022-07-28 18:44:27 +01001816" This was causing the line number in the diff block to go below one.
1817" FIXME: somehow this causes a valgrind error when run directly but not when
1818" run as a test.
1819func Test_diff_put_and_undo()
1820 set diff
1821 next 0
1822 split 00
1823 sil! norm o0gguudpo0ggJuudp
1824
1825 bwipe!
1826 bwipe!
1827 set nodiff
1828endfunc
1829
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001830" Test for the diff() function
1831def Test_diff_func()
1832 # string is added/removed/modified at the beginning
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001833 assert_equal("@@ -0,0 +1 @@\n+abc\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001834 diff(['def'], ['abc', 'def'], {output: 'unified'}))
1835 assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 1}],
1836 diff(['def'], ['abc', 'def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001837 assert_equal("@@ -1 +0,0 @@\n-abc\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001838 diff(['abc', 'def'], ['def'], {output: 'unified'}))
1839 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 0}],
1840 diff(['abc', 'def'], ['def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001841 assert_equal("@@ -1 +1 @@\n-abc\n+abx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001842 diff(['abc', 'def'], ['abx', 'def'], {output: 'unified'}))
1843 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1844 diff(['abc', 'def'], ['abx', 'def'], {output: 'indices'}))
1845
1846 # string is added/removed/modified at the end
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001847 assert_equal("@@ -1,0 +2 @@\n+def\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001848 diff(['abc'], ['abc', 'def'], {output: 'unified'}))
1849 assert_equal([{from_idx: 1, from_count: 0, to_idx: 1, to_count: 1}],
1850 diff(['abc'], ['abc', 'def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001851 assert_equal("@@ -2 +1,0 @@\n-def\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001852 diff(['abc', 'def'], ['abc'], {output: 'unified'}))
1853 assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 0}],
1854 diff(['abc', 'def'], ['abc'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001855 assert_equal("@@ -2 +2 @@\n-def\n+xef\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001856 diff(['abc', 'def'], ['abc', 'xef'], {output: 'unified'}))
1857 assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 1}],
1858 diff(['abc', 'def'], ['abc', 'xef'], {output: 'indices'}))
1859
1860 # string is added/removed/modified in the middle
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001861 assert_equal("@@ -2,0 +3 @@\n+xxx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001862 diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'unified'}))
1863 assert_equal([{from_idx: 2, from_count: 0, to_idx: 2, to_count: 1}],
1864 diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001865 assert_equal("@@ -3 +2,0 @@\n-333\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001866 diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'unified'}))
1867 assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 0}],
1868 diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001869 assert_equal("@@ -3 +3 @@\n-333\n+xxx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001870 diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'unified'}))
1871 assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 1}],
1872 diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'indices'}))
1873
1874 # new strings are added to an empty List
1875 assert_equal("@@ -0,0 +1,2 @@\n+abc\n+def\n",
1876 diff([], ['abc', 'def'], {output: 'unified'}))
1877 assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 2}],
1878 diff([], ['abc', 'def'], {output: 'indices'}))
1879
1880 # all the strings are removed from a List
1881 assert_equal("@@ -1,2 +0,0 @@\n-abc\n-def\n",
1882 diff(['abc', 'def'], [], {output: 'unified'}))
1883 assert_equal([{from_idx: 0, from_count: 2, to_idx: 0, to_count: 0}],
1884 diff(['abc', 'def'], [], {output: 'indices'}))
1885
1886 # First character is added/removed/different
1887 assert_equal("@@ -1 +1 @@\n-abc\n+bc\n",
1888 diff(['abc'], ['bc'], {output: 'unified'}))
1889 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1890 diff(['abc'], ['bc'], {output: 'indices'}))
1891 assert_equal("@@ -1 +1 @@\n-bc\n+abc\n",
1892 diff(['bc'], ['abc'], {output: 'unified'}))
1893 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1894 diff(['bc'], ['abc'], {output: 'indices'}))
1895 assert_equal("@@ -1 +1 @@\n-abc\n+xbc\n",
1896 diff(['abc'], ['xbc'], {output: 'unified'}))
1897 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1898 diff(['abc'], ['xbc'], {output: 'indices'}))
1899
1900 # Last character is added/removed/different
1901 assert_equal("@@ -1 +1 @@\n-abc\n+abcd\n",
1902 diff(['abc'], ['abcd'], {output: 'unified'}))
1903 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1904 diff(['abc'], ['abcd'], {output: 'indices'}))
1905 assert_equal("@@ -1 +1 @@\n-abcd\n+abc\n",
1906 diff(['abcd'], ['abc'], {output: 'unified'}))
1907 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1908 diff(['abcd'], ['abc'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001909 var diff_unified: string = diff(['abc'], ['abx'], {output: 'unified'})
1910 assert_equal("@@ -1 +1 @@\n-abc\n+abx\n", diff_unified)
1911 var diff_indices: list<dict<number>> =
1912 diff(['abc'], ['abx'], {output: 'indices'})
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001913 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001914 diff_indices)
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001915
1916 # partial string modification at the start and at the end.
1917 var fromlist =<< trim END
1918 one two
1919 three four
1920 five six
1921 END
1922 var tolist =<< trim END
1923 one
1924 six
1925 END
1926 assert_equal("@@ -1,3 +1,2 @@\n-one two\n-three four\n-five six\n+one\n+six\n", diff(fromlist, tolist, {output: 'unified'}))
1927 assert_equal([{from_idx: 0, from_count: 3, to_idx: 0, to_count: 2}],
1928 diff(fromlist, tolist, {output: 'indices'}))
1929
1930 # non-contiguous modifications
1931 fromlist =<< trim END
1932 one two
1933 three four
1934 five abc six
1935 END
1936 tolist =<< trim END
1937 one abc two
1938 three four
1939 five six
1940 END
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001941 assert_equal("@@ -1 +1 @@\n-one two\n+one abc two\n@@ -3 +3 @@\n-five abc six\n+five six\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001942 diff(fromlist, tolist, {output: 'unified'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001943 assert_equal([{'from_count': 1, 'to_idx': 0, 'to_count': 1, 'from_idx': 0},
1944 {'from_count': 1, 'to_idx': 2, 'to_count': 1, 'from_idx': 2}],
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001945 diff(fromlist, tolist, {output: 'indices'}))
1946
1947 # add/remove blank lines
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001948 assert_equal("@@ -2,2 +1,0 @@\n-\n-\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001949 diff(['one', '', '', 'two'], ['one', 'two'], {output: 'unified'}))
1950 assert_equal([{from_idx: 1, from_count: 2, to_idx: 1, to_count: 0}],
1951 diff(['one', '', '', 'two'], ['one', 'two'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001952 assert_equal("@@ -1,0 +2,2 @@\n+\n+\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001953 diff(['one', 'two'], ['one', '', '', 'two'], {output: 'unified'}))
1954 assert_equal([{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}],
1955 diff(['one', 'two'], ['one', '', '', 'two'], {output: 'indices'}))
1956
1957 # diff ignoring case
1958 assert_equal('', diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'unified'}))
1959 assert_equal([], diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'indices'}))
1960
1961 # diff ignoring all whitespace changes except leading whitespace changes
1962 assert_equal('', diff(['abc def'], ['abc def '], {iwhite: true}))
1963 assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:true}))
1964 assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:false}))
1965 assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:true}))
1966 assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:false}))
1967
1968 # diff ignoring all whitespace changes
1969 assert_equal('', diff(['abc def'], [' abc def '], {iwhiteall: true}))
1970 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:true}))
1971 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:false}))
1972
1973 # diff ignoring trailing whitespace changes
1974 assert_equal('', diff(['abc'], ['abc '], {iwhiteeol: true}))
1975
1976 # diff ignoring blank lines
1977 assert_equal('', diff(['one', '', '', 'two'], ['one', 'two'], {iblank: true}))
1978 assert_equal('', diff(['one', 'two'], ['one', '', '', 'two'], {iblank: true}))
1979
1980 # same string
1981 assert_equal('', diff(['abc', 'def', 'ghi'], ['abc', 'def', 'ghi']))
1982 assert_equal('', diff([''], ['']))
1983 assert_equal('', diff([], []))
1984
1985 # different xdiff algorithms
1986 for algo in ['myers', 'minimal', 'patience', 'histogram']
1987 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
1988 diff([' abc '], [' xxx '], {algorithm: algo, output: 'unified'}))
1989 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1990 diff([' abc '], [' xxx '], {algorithm: algo, output: 'indices'}))
1991 endfor
1992 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
1993 diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'unified'}))
1994 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1995 diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'indices'}))
1996
1997 # identical strings
1998 assert_equal('', diff(['111', '222'], ['111', '222'], {output: 'unified'}))
1999 assert_equal([], diff(['111', '222'], ['111', '222'], {output: 'indices'}))
2000 assert_equal('', diff([], [], {output: 'unified'}))
2001 assert_equal([], diff([], [], {output: 'indices'}))
2002
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002003 # If 'diffexpr' is set, it should not be used for diff()
2004 def MyDiffExpr()
2005 enddef
2006 var save_diffexpr = &diffexpr
2007 :set diffexpr=MyDiffExpr()
2008 assert_equal("@@ -1 +1 @@\n-abc\n+\n",
2009 diff(['abc'], [''], {output: 'unified'}))
2010 assert_equal([{'from_idx': 0, 'from_count': 1, 'to_idx': 0, 'to_count': 1}],
2011 diff(['abc'], [''], {output: 'indices'}))
2012 assert_equal('MyDiffExpr()', &diffexpr)
2013 &diffexpr = save_diffexpr
2014
2015 # try different values for unified diff 'context'
2016 assert_equal("@@ -0,0 +1 @@\n+x\n",
2017 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c']))
2018 assert_equal("@@ -0,0 +1 @@\n+x\n",
2019 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 0}))
2020 assert_equal("@@ -1 +1,2 @@\n+x\n a\n",
2021 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 1}))
2022 assert_equal("@@ -1,2 +1,3 @@\n+x\n a\n b\n",
2023 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 2}))
2024 assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
2025 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 3}))
2026 assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
2027 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 4}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002028 assert_equal("@@ -0,0 +1 @@\n+x\n",
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002029 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: -1}))
2030
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002031 # Error cases
2032 assert_fails('call diff({}, ["a"])', 'E1211:')
2033 assert_fails('call diff(["a"], {})', 'E1211:')
2034 assert_fails('call diff(["a"], ["a"], [])', 'E1206:')
2035 assert_fails('call diff(["a"], ["a"], {output: "xyz"})', 'E106: Unsupported diff output format: xyz')
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002036 assert_fails('call diff(["a"], ["a"], {context: []})', 'E745: Using a List as a Number')
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002037enddef
Bram Moolenaara315ce12022-06-24 12:38:57 +01002038
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002039" Test for using the diff() function with 'diffexpr'
2040func Test_diffexpr_with_diff_func()
2041 CheckScreendump
2042
2043 let lines =<< trim END
2044 def DiffFuncExpr()
2045 var in: list<string> = readfile(v:fname_in)
2046 var new: list<string> = readfile(v:fname_new)
2047 var out: string = diff(in, new)
2048 writefile(split(out, "\n"), v:fname_out)
2049 enddef
2050 set diffexpr=DiffFuncExpr()
2051
2052 edit Xdifffunc1.txt
2053 diffthis
2054 vert split Xdifffunc2.txt
2055 diffthis
2056 END
2057 call writefile(lines, 'XsetupDiffFunc.vim', 'D')
2058
2059 call writefile(['zero', 'one', 'two', 'three'], 'Xdifffunc1.txt', 'D')
2060 call writefile(['one', 'twox', 'three', 'four'], 'Xdifffunc2.txt', 'D')
2061
2062 let buf = RunVimInTerminal('-S XsetupDiffFunc.vim', {'rows': 12})
2063 call VerifyScreenDump(buf, 'Test_difffunc_diffexpr_1', {})
2064 call StopVimInTerminal(buf)
2065endfunc
2066
zeertzjq9e7f1fc2024-03-16 09:40:22 +01002067func Test_diff_toggle_wrap_skipcol_leftcol()
2068 61vnew
2069 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.')
2070 30vnew
2071 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.')
2072 let win1 = win_getid()
2073 setlocal smoothscroll
2074 exe "normal! $\<C-E>"
2075 wincmd l
2076 let win2 = win_getid()
2077 setlocal smoothscroll
2078 exe "normal! $\<C-E>"
2079 call assert_equal([
2080 \ '<<<sadipscing elitr, sed diam |<<<tetur sadipscing elitr, sed|',
2081 \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
2082 \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
2083 \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
2084 \ '~ |ptua. |',
2085 \ ], ScreenLines([1, 5], 62))
2086 call assert_equal({'col': 29, 'row': 4, 'endcol': 29, 'curscol': 29},
2087 \ screenpos(win1, line('.', win1), col('.', win1)))
2088 call assert_equal({'col': 36, 'row': 5, 'endcol': 36, 'curscol': 36},
2089 \ screenpos(win2, line('.', win2), col('.', win2)))
2090
2091 wincmd h
2092 diffthis
2093 wincmd l
2094 diffthis
2095 normal! 0
2096 call assert_equal([
2097 \ ' ipsum dolor sit amet, conset| Lorem ipsum dolor sit amet, |',
2098 \ '~ |~ |',
2099 \ ], ScreenLines([1, 2], 62))
2100 call assert_equal({'col': 3, 'row': 1, 'endcol': 3, 'curscol': 3},
2101 \ screenpos(win1, line('.', win1), col('.', win1)))
2102 call assert_equal({'col': 34, 'row': 1, 'endcol': 34, 'curscol': 34},
2103 \ screenpos(win2, line('.', win2), col('.', win2)))
2104
2105 normal! $
2106 call assert_equal([
2107 \ ' voluptua. | diam voluptua. |',
2108 \ '~ |~ |',
2109 \ ], ScreenLines([1, 2], 62))
2110 call assert_equal({'col': 11, 'row': 1, 'endcol': 11, 'curscol': 11},
2111 \ screenpos(win1, line('.', win1), col('.', win1)))
2112 call assert_equal({'col': 48, 'row': 1, 'endcol': 48, 'curscol': 48},
2113 \ screenpos(win2, line('.', win2), col('.', win2)))
2114
2115 diffoff!
2116 call assert_equal([
2117 \ 'ipsum dolor sit amet, consetet|Lorem ipsum dolor sit amet, co|',
2118 \ 'ur sadipscing elitr, sed diam |nsetetur sadipscing elitr, sed|',
2119 \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
2120 \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
2121 \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
2122 \ '~ |ptua. |',
2123 \ ], ScreenLines([1, 6], 62))
2124 call assert_equal({'col': 29, 'row': 5, 'endcol': 29, 'curscol': 29},
2125 \ screenpos(win1, line('.', win1), col('.', win1)))
2126 call assert_equal({'col': 36, 'row': 6, 'endcol': 36, 'curscol': 36},
2127 \ screenpos(win2, line('.', win2), col('.', win2)))
2128
2129 bwipe!
2130 bwipe!
2131endfunc
2132
Luuk van Baal9148ba82024-04-08 22:27:41 +02002133" Ctrl-D reveals filler lines below the last line in the buffer.
2134func Test_diff_eob_halfpage()
Luuk van Baal08b0f632024-04-09 22:43:49 +02002135 new
Luuk van Baal9148ba82024-04-08 22:27:41 +02002136 call setline(1, ['']->repeat(10) + ['a'])
2137 diffthis
Luuk van Baal08b0f632024-04-09 22:43:49 +02002138 new
Luuk van Baal9148ba82024-04-08 22:27:41 +02002139 call setline(1, ['']->repeat(3) + ['a', 'b'])
2140 diffthis
Luuk van Baal08b0f632024-04-09 22:43:49 +02002141 resize 5
Luuk van Baal9148ba82024-04-08 22:27:41 +02002142 wincmd j
Luuk van Baal08b0f632024-04-09 22:43:49 +02002143 resize 5
2144 norm G
2145 call assert_equal(7, line('w0'))
2146 exe "norm! \<C-D>"
2147 call assert_equal(8, line('w0'))
Luuk van Baal9148ba82024-04-08 22:27:41 +02002148
2149 %bwipe!
2150endfunc
2151
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +02002152func Test_diff_overlapped_diff_blocks_will_be_merged()
2153 CheckScreendump
2154
2155 let lines =<< trim END
2156 func DiffExprStub()
2157 let txt_in = readfile(v:fname_in)
2158 let txt_new = readfile(v:fname_new)
2159 if txt_in == ["line1"] && txt_new == ["line2"]
2160 call writefile(["1c1"], v:fname_out)
2161 elseif txt_in == readfile("Xdiin1") && txt_new == readfile("Xdinew1")
2162 call writefile(readfile("Xdiout1"), v:fname_out)
2163 elseif txt_in == readfile("Xdiin2") && txt_new == readfile("Xdinew2")
2164 call writefile(readfile("Xdiout2"), v:fname_out)
2165 endif
2166 endfunc
2167 END
2168 call writefile(lines, 'XdiffSetup', 'D')
2169
2170 call WriteDiffFiles(0, [], [])
2171 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
2172 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2173
2174 call WriteDiffFiles(buf, ["a", "b"], ["x", "x"])
2175 call writefile(["a", "b"], "Xdiin1")
2176 call writefile(["x", "x"], "Xdinew1")
2177 call writefile(["1c1", "2c2"], "Xdiout1")
2178 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2179 call VerifyBoth(buf, "Test_diff_overlapped_2.01", "")
2180 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2181
2182 call WriteDiffFiles(buf, ["a", "b", "c"], ["x", "c"])
2183 call writefile(["a", "b", "c"], "Xdiin1")
2184 call writefile(["x", "c"], "Xdinew1")
2185 call writefile(["1c1", "2d1"], "Xdiout1")
2186 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2187 call VerifyBoth(buf, "Test_diff_overlapped_2.02", "")
2188 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2189
2190 call WriteDiffFiles(buf, ["a", "c"], ["x", "x", "c"])
2191 call writefile(["a", "c"], "Xdiin1")
2192 call writefile(["x", "x", "c"], "Xdinew1")
2193 call writefile(["1c1", "1a2"], "Xdiout1")
2194 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2195 call VerifyBoth(buf, "Test_diff_overlapped_2.03", "")
2196 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2197
2198 call StopVimInTerminal(buf)
2199 wincmd c
2200
2201 call WriteDiffFiles3(0, [], [], [])
2202 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2 Xdifile3', {})
2203 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2204
2205 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "b", "c"])
2206 call VerifyBoth(buf, "Test_diff_overlapped_3.01", "")
2207
2208 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "c"])
2209 call VerifyBoth(buf, "Test_diff_overlapped_3.02", "")
2210
2211 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y"])
2212 call VerifyBoth(buf, "Test_diff_overlapped_3.03", "")
2213
2214 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "c"])
2215 call VerifyBoth(buf, "Test_diff_overlapped_3.04", "")
2216
2217 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "y"])
2218 call VerifyBoth(buf, "Test_diff_overlapped_3.05", "")
2219
2220 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "y"])
2221 call VerifyBoth(buf, "Test_diff_overlapped_3.06", "")
2222
2223 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "x"], ["y", "y", "c"])
2224 call VerifyBoth(buf, "Test_diff_overlapped_3.07", "")
2225
2226 call WriteDiffFiles3(buf, ["a", "b", "c"], ["x", "x", "c"], ["a", "y", "y"])
2227 call VerifyBoth(buf, "Test_diff_overlapped_3.08", "")
2228
2229 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "d", "e"])
2230 call VerifyBoth(buf, "Test_diff_overlapped_3.09", "")
2231
2232 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "e"])
2233 call VerifyBoth(buf, "Test_diff_overlapped_3.10", "")
2234
2235 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "y"])
2236 call VerifyBoth(buf, "Test_diff_overlapped_3.11", "")
2237
2238 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "d", "e"])
2239 call VerifyBoth(buf, "Test_diff_overlapped_3.12", "")
2240
2241 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "e"])
2242 call VerifyBoth(buf, "Test_diff_overlapped_3.13", "")
2243
2244 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "y"])
2245 call VerifyBoth(buf, "Test_diff_overlapped_3.14", "")
2246
2247 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "d", "e"])
2248 call VerifyBoth(buf, "Test_diff_overlapped_3.15", "")
2249
2250 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "e"])
2251 call VerifyBoth(buf, "Test_diff_overlapped_3.16", "")
2252
2253 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "y"])
2254 call VerifyBoth(buf, "Test_diff_overlapped_3.17", "")
2255
2256 call WriteDiffFiles3(buf, ["a", "b"], ["x", "b"], ["y", "y"])
2257 call writefile(["a", "b"], "Xdiin1")
2258 call writefile(["x", "b"], "Xdinew1")
2259 call writefile(["1c1"], "Xdiout1")
2260 call writefile(["a", "b"], "Xdiin2")
2261 call writefile(["y", "y"], "Xdinew2")
2262 call writefile(["1c1", "2c2"], "Xdiout2")
2263 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2264 call VerifyInternal(buf, "Test_diff_overlapped_3.18", "")
2265 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2266
2267 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "c", "d"])
2268 call writefile(["a", "b", "c", "d"], "Xdiin1")
2269 call writefile(["x", "b", "x", "d"], "Xdinew1")
2270 call writefile(["1c1", "3c3"], "Xdiout1")
2271 call writefile(["a", "b", "c", "d"], "Xdiin2")
2272 call writefile(["y", "y", "c", "d"], "Xdinew2")
2273 call writefile(["1c1", "2c2"], "Xdiout2")
2274 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2275 call VerifyInternal(buf, "Test_diff_overlapped_3.19", "")
2276 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2277
2278 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "d"])
2279 call writefile(["a", "b", "c", "d"], "Xdiin1")
2280 call writefile(["x", "b", "x", "d"], "Xdinew1")
2281 call writefile(["1c1", "3c3"], "Xdiout1")
2282 call writefile(["a", "b", "c", "d"], "Xdiin2")
2283 call writefile(["y", "y", "y", "d"], "Xdinew2")
2284 call writefile(["1c1", "2,3c2,3"], "Xdiout2")
2285 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2286 call VerifyInternal(buf, "Test_diff_overlapped_3.20", "")
2287 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2288
2289 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "y"])
2290 call writefile(["a", "b", "c", "d"], "Xdiin1")
2291 call writefile(["x", "b", "x", "d"], "Xdinew1")
2292 call writefile(["1c1", "3c3"], "Xdiout1")
2293 call writefile(["a", "b", "c", "d"], "Xdiin2")
2294 call writefile(["y", "y", "y", "y"], "Xdinew2")
2295 call writefile(["1c1", "2,4c2,4"], "Xdiout2")
2296 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2297 call VerifyInternal(buf, "Test_diff_overlapped_3.21", "")
2298 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2299
2300 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b", "c"])
2301 call VerifyBoth(buf, "Test_diff_overlapped_3.22", "")
2302
2303 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["c"])
2304 call VerifyBoth(buf, "Test_diff_overlapped_3.23", "")
2305
2306 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], [])
2307 call VerifyBoth(buf, "Test_diff_overlapped_3.24", "")
2308
2309 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "c"])
2310 call VerifyBoth(buf, "Test_diff_overlapped_3.25", "")
2311
2312 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a"])
2313 call VerifyBoth(buf, "Test_diff_overlapped_3.26", "")
2314
2315 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b"])
2316 call VerifyBoth(buf, "Test_diff_overlapped_3.27", "")
2317
2318 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["d", "e"])
2319 call VerifyBoth(buf, "Test_diff_overlapped_3.28", "")
2320
2321 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["e"])
2322 call VerifyBoth(buf, "Test_diff_overlapped_3.29", "")
2323
2324 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "d", "e"])
2325 call VerifyBoth(buf, "Test_diff_overlapped_3.30", "")
2326
2327 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "e"])
2328 call VerifyBoth(buf, "Test_diff_overlapped_3.31", "")
2329
2330 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a"])
2331 call VerifyBoth(buf, "Test_diff_overlapped_3.32", "")
2332
2333 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "d", "e"])
2334 call VerifyBoth(buf, "Test_diff_overlapped_3.33", "")
2335
2336 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "e"])
2337 call VerifyBoth(buf, "Test_diff_overlapped_3.34", "")
2338
2339 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b"])
2340 call VerifyBoth(buf, "Test_diff_overlapped_3.35", "")
2341
2342 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "b", "c"])
2343 call VerifyBoth(buf, "Test_diff_overlapped_3.36", "")
2344
2345 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y", "c"])
2346 call VerifyBoth(buf, "Test_diff_overlapped_3.37", "")
2347
Yukihiro Nakadaira01f65092025-01-15 18:36:43 +01002348 call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b", "f"])
2349 call VerifyBoth(buf, "Test_diff_overlapped_3.38", "")
2350
2351 call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b"])
2352 call VerifyBoth(buf, "Test_diff_overlapped_3.39", "")
2353
Yee Cheng Chinbc08ceb2025-03-02 22:05:37 +01002354 " File 3 overlaps twice, 2nd overlap completely within the existing block.
2355 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "bar"], ["foo", "w", "x", "y", "z", "bar"], ["foo", "1", "a", "b", "2", "bar"])
2356 call VerifyBoth(buf, "Test_diff_overlapped_3.40", "")
2357
2358 " File 3 overlaps twice, 2nd overlap extends beyond existing block on new
2359 " side. Make sure we don't over-extend the range and hit 'bar'.
2360 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "2", "d", "bar"])
2361 call VerifyBoth(buf, "Test_diff_overlapped_3.41", "")
2362
2363 " Chained overlaps. File 3's 2nd overlap spans two diff blocks and is longer
2364 " than the 2nd one.
2365 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"])
2366 call VerifyBoth(buf, "Test_diff_overlapped_3.42", "")
2367
2368 " File 3 has 2 overlaps. An add and a delete. First overlap's expansion hits
2369 " the 2nd one. Make sure we adjust the diff block to have fewer lines.
2370 call WriteDiffFiles3(buf, ["foo", "a", "b", "bar"], ["foo", "x", "y", "bar"], ["foo", "1", "a", "bar"])
2371 call VerifyBoth(buf, "Test_diff_overlapped_3.43", "")
2372
2373 " File 3 has 2 overlaps. An add and another add. First overlap's expansion hits
2374 " the 2nd one. Make sure we adjust the diff block to have more lines.
2375 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "3", "4", "d", "bar"])
2376 call VerifyBoth(buf, "Test_diff_overlapped_3.44", "")
2377
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +02002378 call StopVimInTerminal(buf)
2379endfunc
2380
zeertzjq7c515282024-11-10 20:26:12 +01002381" switching windows in diff mode caused an unnecessary scroll
Christian Brabandt05a40e02024-10-29 20:29:04 +01002382func Test_diff_topline_noscroll()
2383 CheckScreendump
2384
2385 let content =<< trim END
2386 call setline(1, range(1,60))
2387 vnew
2388 call setline(1, range(1,10) + range(50,60))
2389 windo diffthis
2390 norm! G
2391 exe "norm! 30\<C-y>"
2392 END
2393 call writefile(content, 'Xcontent', 'D')
2394 let buf = RunVimInTerminal('-S Xcontent', {'rows': 20})
2395 call VerifyScreenDump(buf, 'Test_diff_topline_1', {})
2396 call term_sendkeys(buf, ":echo line('w0', 1001)\<cr>")
2397 call term_wait(buf)
2398 call VerifyScreenDump(buf, 'Test_diff_topline_2', {})
2399 call term_sendkeys(buf, "\<C-W>p")
2400 call term_wait(buf)
2401 call VerifyScreenDump(buf, 'Test_diff_topline_3', {})
2402 call term_sendkeys(buf, "\<C-W>p")
2403 call term_wait(buf)
2404 call VerifyScreenDump(buf, 'Test_diff_topline_4', {})
2405 call StopVimInTerminal(buf)
2406endfunc
2407
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002408" Test inline highlighting which shows what's different within each diff block
2409func Test_diff_inline()
2410 CheckScreendump
2411
2412 call WriteDiffFiles(0, [], [])
2413 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2414 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2415
2416 call WriteDiffFiles(buf, ["abcdef ghi jk n", "x", "y"], ["aBcef gHi lm n", "y", "z"])
2417 call VerifyInternal(buf, "Test_diff_inline_01", "")
2418 call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:none")
2419
2420 " inline:simple is the same as default
2421 call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:simple")
2422
2423 call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:char")
2424 call VerifyInternal(buf, "Test_diff_inline_04", " diffopt+=inline:word")
2425
2426 " multiple inline values will the last one
2427 call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:none,inline:char,inline:simple")
2428 call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:simple,inline:word,inline:none")
2429 call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:simple,inline:word,inline:char")
2430
2431 " DiffTextAdd highlight
2432 call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
2433 call VerifyInternal(buf, "Test_diff_inline_05", " diffopt+=inline:char")
2434
2435 " Live update in insert mode
2436 call term_sendkeys(buf, "\<Esc>isometext")
2437 call VerifyScreenDump(buf, "Test_diff_inline_06", {})
2438 call term_sendkeys(buf, "\<Esc>u")
2439
2440 " icase simple scenarios
2441 call VerifyInternal(buf, "Test_diff_inline_07", " diffopt+=inline:simple,icase")
2442 call VerifyInternal(buf, "Test_diff_inline_08", " diffopt+=inline:char,icase")
2443 call VerifyInternal(buf, "Test_diff_inline_09", " diffopt+=inline:word,icase")
2444
2445 " diff algorithms should affect highlight
2446 call WriteDiffFiles(buf, ["apples and oranges"], ["oranges and apples"])
2447 call VerifyInternal(buf, "Test_diff_inline_10", " diffopt+=inline:char")
2448 call VerifyInternal(buf, "Test_diff_inline_11", " diffopt+=inline:char,algorithm:patience")
2449
2450 " icase: composing chars and Unicode fold case edge cases
2451 call WriteDiffFiles(buf,
2452 \ ["1 - sigma in 6σ and Ὀδυσσεύς", "1 - angstrom in åå", "1 - composing: ii⃗I⃗"],
2453 \ ["2 - Sigma in 6Σ and ὈΔΥΣΣΕΎΣ", "2 - Angstrom in ÅÅ", "2 - Composing: i⃗I⃗I⃗"])
2454 call VerifyInternal(buf, "Test_diff_inline_12", " diffopt+=inline:char")
2455 call VerifyInternal(buf, "Test_diff_inline_13", " diffopt+=inline:char,icase")
2456
2457 " wide chars
2458 call WriteDiffFiles(buf, ["abc😅xde一", "f🚀g"], ["abcy😢de", "二f🚀g"])
2459 call VerifyInternal(buf, "Test_diff_inline_14", " diffopt+=inline:char,icase")
2460
2461 " NUL char (\n below is internally substituted as NUL)
2462 call WriteDiffFiles(buf, ["1\n34\n5\n6"], ["1234\n5", "6"])
2463 call VerifyInternal(buf, "Test_diff_inline_15", " diffopt+=inline:char")
2464
2465 " word diff: always use first buffer's iskeyword and ignore others' for consistency
2466 call WriteDiffFiles(buf, ["foo+bar test"], ["foo+baz test"])
2467 call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
2468
2469 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:diffupdate\<CR>")
2470 call VerifyInternal(buf, "Test_diff_inline_word_02", " diffopt+=inline:word")
2471
2472 call term_sendkeys(buf, ":set iskeyword&\<CR>:wincmd w\<CR>")
2473 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:wincmd w\<CR>:diffupdate\<CR>")
2474 " Use the previous screen dump as 2nd buffer's iskeyword does not matter
2475 call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
2476
2477 call term_sendkeys(buf, ":windo set iskeyword&\<CR>:1wincmd w\<CR>")
2478
Yee Cheng Chin9aa120f2025-04-04 19:16:21 +02002479 " word diff: test handling of multi-byte characters. Only alphanumeric chars
2480 " (e.g. Greek alphabet, but not CJK/emoji) count as words.
2481 call WriteDiffFiles(buf, ["🚀⛵️一二三ひらがなΔέλτα Δelta foobar"], ["🚀🛸一二四ひらなδέλτα δelta foobar"])
2482 call VerifyInternal(buf, "Test_diff_inline_word_03", " diffopt+=inline:word")
2483
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002484 " char diff: should slide highlight to whitespace boundary if possible for
2485 " better readability (by using forced indent-heuristics). A wrong result
2486 " would be if the highlight is "Bar, prefix". It should be "prefixBar, "
2487 " instead.
2488 call WriteDiffFiles(buf, ["prefixFoo, prefixEnd"], ["prefixFoo, prefixBar, prefixEnd"])
2489 call VerifyInternal(buf, "Test_diff_inline_char_01", " diffopt+=inline:char")
2490
2491 " char diff: small gaps between inline diff blocks will be merged during refine step
2492 " - first segment: test that we iteratively merge small gaps after we merged
2493 " adjacent blocks, but only with limited number (set to 4) of iterations.
2494 " - second and third segments: show that we need a large enough adjacent block to
2495 " trigger a merge.
2496 " - fourth segment: small gaps are not merged when adjacent large block is
2497 " on a different line.
2498 call WriteDiffFiles(buf,
2499 \ ["abcdefghijklmno", "anchor1",
2500 \ "abcdefghijklmno", "anchor2",
2501 \ "abcdefghijklmno", "anchor3",
2502 \ "test", "multiline"],
zeertzjq5a307c32025-03-28 19:01:32 +01002503 \ ["a?c?e?g?i?k???o", "anchor1",
2504 \ "a??de?????klmno", "anchor2",
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002505 \ "a??de??????lmno", "anchor3",
2506 \ "t?s?", "??????i?e"])
2507 call VerifyInternal(buf, "Test_diff_inline_char_02", " diffopt+=inline:char")
2508
2509 " Test multi-line blocks and whitespace
2510 call WriteDiffFiles(buf,
2511 \ ["this is ", "sometest text foo", "baz abc def ", "one", "word another word", "additional line"],
2512 \ ["this is some test", "texts", "foo bar abX Yef ", "oneword another word"])
2513 call VerifyInternal(buf, "Test_diff_inline_multiline_01", " diffopt+=inline:char,iwhite")
2514 call VerifyInternal(buf, "Test_diff_inline_multiline_02", " diffopt+=inline:word,iwhite")
2515 call VerifyInternal(buf, "Test_diff_inline_multiline_03", " diffopt+=inline:char,iwhiteeol")
2516 call VerifyInternal(buf, "Test_diff_inline_multiline_04", " diffopt+=inline:word,iwhiteeol")
2517 call VerifyInternal(buf, "Test_diff_inline_multiline_05", " diffopt+=inline:char,iwhiteall")
2518 call VerifyInternal(buf, "Test_diff_inline_multiline_06", " diffopt+=inline:word,iwhiteall")
2519
2520 " newline should be highlighted too when 'list' is set
2521 call term_sendkeys(buf, ":windo set list\<CR>")
2522 call VerifyInternal(buf, "Test_diff_inline_multiline_07", " diffopt+=inline:char")
2523 call VerifyInternal(buf, "Test_diff_inline_multiline_08", " diffopt+=inline:char,iwhite")
2524 call VerifyInternal(buf, "Test_diff_inline_multiline_09", " diffopt+=inline:char,iwhiteeol")
2525 call VerifyInternal(buf, "Test_diff_inline_multiline_10", " diffopt+=inline:char,iwhiteall")
2526 call term_sendkeys(buf, ":windo set nolist\<CR>")
2527
2528 call StopVimInTerminal(buf)
2529endfunc
2530
2531func Test_diff_inline_multibuffer()
2532 CheckScreendump
2533
2534 call WriteDiffFiles3(0, [], [], [])
2535 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
2536 call term_sendkeys(buf, ":windo set autoread\<CR>:1wincmd w\<CR>")
2537 call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
2538
2539 call WriteDiffFiles3(buf,
2540 \ ["That is buffer1.", "anchor", "Some random text", "anchor"],
2541 \ ["This is buffer2.", "anchor", "Some text", "anchor", "buffer2/3"],
2542 \ ["This is buffer3. Last.", "anchor", "Some more", "text here.", "anchor", "only in buffer2/3", "not in buffer1"])
2543 call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
2544
zeertzjq5a307c32025-03-28 19:01:32 +01002545 " Close one of the buffers and make sure it updates correctly
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002546 call term_sendkeys(buf, ":diffoff\<CR>")
2547 call VerifyInternal(buf, "Test_diff_inline_multibuffer_02", " diffopt+=inline:char")
2548
2549 " Update text in the non-diff buffer and nothing should be changed
2550 call term_sendkeys(buf, "\<Esc>isometext")
2551 call VerifyScreenDump(buf, "Test_diff_inline_multibuffer_03", {})
2552 call term_sendkeys(buf, "\<Esc>u")
2553
2554 call term_sendkeys(buf, ":diffthis\<CR>")
2555 call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
2556
2557 " Test that removing first buffer from diff will in turn use the next
2558 " earliest buffer's iskeyword during word diff.
2559 call WriteDiffFiles3(buf,
2560 \ ["This+is=a-setence"],
2561 \ ["This+is=another-setence"],
2562 \ ["That+is=a-setence"])
2563 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:2wincmd w\<CR>:set iskeyword+=-\<CR>:1wincmd w\<CR>")
2564 call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
2565 call term_sendkeys(buf, ":diffoff\<CR>")
2566 call VerifyInternal(buf, "Test_diff_inline_multibuffer_05", " diffopt+=inline:word")
2567 call term_sendkeys(buf, ":diffthis\<CR>")
2568 call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
2569
2570 " Test multi-buffer char diff refinement, and that removing a buffer from
2571 " diff will update the others properly.
2572 call WriteDiffFiles3(buf,
2573 \ ["abcdefghijkYmYYY"],
2574 \ ["aXXdXXghijklmnop"],
2575 \ ["abcdefghijkYmYop"])
2576 call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
2577 call term_sendkeys(buf, ":diffoff\<CR>")
2578 call VerifyInternal(buf, "Test_diff_inline_multibuffer_07", " diffopt+=inline:char")
2579 call term_sendkeys(buf, ":diffthis\<CR>")
2580 call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
2581
2582 call StopVimInTerminal(buf)
2583endfunc
2584
Jonathon7c7a4e62025-01-12 09:58:00 +01002585func Test_diffget_diffput_linematch()
2586 CheckScreendump
2587 call delete('.Xdifile1.swp')
2588 call delete('.Xdifile2.swp')
2589 call WriteDiffFiles(0, [], [])
2590 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2591 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2592
2593 " enable linematch
2594 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2595 call WriteDiffFiles(buf, ['',
2596 \ 'common line',
2597 \ 'common line',
2598 \ '',
2599 \ 'ABCabc',
2600 \ 'ABCabc',
2601 \ 'ABCabc',
2602 \ 'ABCabc',
2603 \ 'common line',
2604 \ 'common line',
2605 \ 'common line',
2606 \ 'something' ],
2607 \ ['',
2608 \ 'common line',
2609 \ 'common line',
2610 \ '',
2611 \ 'DEFabc',
2612 \ 'xyz',
2613 \ 'xyz',
2614 \ 'xyz',
2615 \ 'DEFabc',
2616 \ 'DEFabc',
2617 \ 'DEFabc',
2618 \ 'common line',
2619 \ 'common line',
2620 \ 'DEF',
2621 \ 'common line',
2622 \ 'DEF',
2623 \ 'something'])
2624 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_1', {})
2625
2626 " get from window 1 from line 5 to 9
2627 call term_sendkeys(buf, "1\<c-w>w")
2628 call term_sendkeys(buf, ":5,9diffget\<CR>")
2629 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_2', {})
2630
2631 " undo the last diffget
2632 call term_sendkeys(buf, "u")
2633
2634 " get from window 2 from line 5 to 10
2635 call term_sendkeys(buf, "2\<c-w>w")
2636 call term_sendkeys(buf, ":5,10diffget\<CR>")
2637 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_3', {})
2638
2639 " undo the last diffget
2640 call term_sendkeys(buf, "u")
2641
2642 " get all from window 2
2643 call term_sendkeys(buf, "2\<c-w>w")
2644 call term_sendkeys(buf, ":4,17diffget\<CR>")
2645 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_4', {})
2646
2647 " undo the last diffget
2648 call term_sendkeys(buf, "u")
2649
2650 " get all from window 1
2651 call term_sendkeys(buf, "1\<c-w>w")
2652 call term_sendkeys(buf, ":4,12diffget\<CR>")
2653 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_5', {})
2654
2655 " undo the last diffget
2656 call term_sendkeys(buf, "u")
2657
2658 " get from window 1 using do 1 line 5
2659 call term_sendkeys(buf, "1\<c-w>w")
2660 call term_sendkeys(buf, "5gg")
2661 call term_sendkeys(buf, ":diffget\<CR>")
2662 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_6', {})
2663
2664 " undo the last diffget
2665 call term_sendkeys(buf, "u")
2666
2667 " get from window 1 using do 2 line 6
2668 call term_sendkeys(buf, "1\<c-w>w")
2669 call term_sendkeys(buf, "6gg")
2670 call term_sendkeys(buf, ":diffget\<CR>")
2671 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_7', {})
2672
2673 " undo the last diffget
2674 call term_sendkeys(buf, "u")
2675
2676 " get from window 1 using do 2 line 7
2677 call term_sendkeys(buf, "1\<c-w>w")
2678 call term_sendkeys(buf, "7gg")
2679 call term_sendkeys(buf, ":diffget\<CR>")
2680 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_8', {})
2681
2682 " undo the last diffget
2683 call term_sendkeys(buf, "u")
2684
2685 " get from window 1 using do 2 line 11
2686 call term_sendkeys(buf, "1\<c-w>w")
2687 call term_sendkeys(buf, "11gg")
2688 call term_sendkeys(buf, ":diffget\<CR>")
2689 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_9', {})
2690
2691 " undo the last diffget
2692 call term_sendkeys(buf, "u")
2693
2694 " get from window 1 using do 2 line 12
2695 call term_sendkeys(buf, "1\<c-w>w")
2696 call term_sendkeys(buf, "12gg")
2697 call term_sendkeys(buf, ":diffget\<CR>")
2698 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_10', {})
2699
2700 " undo the last diffget
2701 call term_sendkeys(buf, "u")
2702
2703 " put from window 1 using dp 1 line 5
2704 call term_sendkeys(buf, "1\<c-w>w")
2705 call term_sendkeys(buf, "5gg")
2706 call term_sendkeys(buf, ":diffput\<CR>")
2707 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_11', {})
2708
2709 " undo the last diffput
2710 call term_sendkeys(buf, "2\<c-w>w")
2711 call term_sendkeys(buf, "u")
2712
2713 " put from window 1 using dp 2 line 6
2714 call term_sendkeys(buf, "1\<c-w>w")
2715 call term_sendkeys(buf, "6gg")
2716 call term_sendkeys(buf, ":diffput\<CR>")
2717 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_12', {})
2718
2719 " undo the last diffput
2720 call term_sendkeys(buf, "2\<c-w>w")
2721 call term_sendkeys(buf, "u")
2722
2723 " put from window 1 using dp 2 line 7
2724 call term_sendkeys(buf, "1\<c-w>w")
2725 call term_sendkeys(buf, "7gg")
2726 call term_sendkeys(buf, ":diffput\<CR>")
2727 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_13', {})
2728
2729 " undo the last diffput
2730 call term_sendkeys(buf, "2\<c-w>w")
2731 call term_sendkeys(buf, "u")
2732
2733 " put from window 1 using dp 2 line 11
2734 call term_sendkeys(buf, "1\<c-w>w")
2735 call term_sendkeys(buf, "11gg")
2736 call term_sendkeys(buf, ":diffput\<CR>")
2737 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_14', {})
2738
2739 " undo the last diffput
2740 call term_sendkeys(buf, "2\<c-w>w")
2741 call term_sendkeys(buf, "u")
2742
2743 " put from window 1 using dp 2 line 12
2744 call term_sendkeys(buf, "1\<c-w>w")
2745 call term_sendkeys(buf, "12gg")
2746 call term_sendkeys(buf, ":diffput\<CR>")
2747 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_15', {})
2748
2749 " undo the last diffput
2750 call term_sendkeys(buf, "2\<c-w>w")
2751 call term_sendkeys(buf, "u")
2752
2753 " put from window 2 using dp line 6
2754 call term_sendkeys(buf, "2\<c-w>w")
2755 call term_sendkeys(buf, "6gg")
2756 call term_sendkeys(buf, ":diffput\<CR>")
2757 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_16', {})
2758
2759 " undo the last diffput
2760 call term_sendkeys(buf, "1\<c-w>w")
2761 call term_sendkeys(buf, "u")
2762
2763 " put from window 2 using dp line 8
2764 call term_sendkeys(buf, "2\<c-w>w")
2765 call term_sendkeys(buf, "8gg")
2766 call term_sendkeys(buf, ":diffput\<CR>")
2767 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_17', {})
2768
2769 " undo the last diffput
2770 call term_sendkeys(buf, "1\<c-w>w")
2771 call term_sendkeys(buf, "u")
2772
2773 " put from window 2 using dp line 9
2774 call term_sendkeys(buf, "2\<c-w>w")
2775 call term_sendkeys(buf, "9gg")
2776 call term_sendkeys(buf, ":diffput\<CR>")
2777 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_18', {})
2778
2779 " undo the last diffput
2780 call term_sendkeys(buf, "1\<c-w>w")
2781 call term_sendkeys(buf, "u")
2782
2783 " put from window 2 using dp line 17
2784 call term_sendkeys(buf, "2\<c-w>w")
2785 call term_sendkeys(buf, "17gg")
2786 call term_sendkeys(buf, ":diffput\<CR>")
2787 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_19', {})
Jonathonca307ef2025-01-17 13:37:35 +01002788 " clean up
2789 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002790endfunc
2791
2792func Test_linematch_diff()
2793 CheckScreendump
2794 call delete('.Xdifile1.swp')
2795 call delete('.Xdifile2.swp')
2796 call WriteDiffFiles(0, [], [])
2797 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2798 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2799
2800 " enable linematch
2801 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2802 call WriteDiffFiles(buf, ['// abc d?',
2803 \ '// d?',
2804 \ '// d?' ],
2805 \ ['!',
2806 \ 'abc d!',
2807 \ 'd!'])
2808 call VerifyScreenDump(buf, 'Test_linematch_diff1', {})
Jonathonca307ef2025-01-17 13:37:35 +01002809 " clean up
2810 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002811endfunc
2812
2813func Test_linematch_diff_iwhite()
2814 CheckScreendump
2815 call delete('.Xdifile1.swp')
2816 call delete('.Xdifile2.swp')
2817 call WriteDiffFiles(0, [], [])
2818 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2819 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2820
2821 " setup a diff with 2 files and set linematch:30, with ignore white
2822 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2823 call WriteDiffFiles(buf, ['void testFunction () {',
2824 \ ' for (int i = 0; i < 10; i++) {',
2825 \ ' for (int j = 0; j < 10; j++) {',
2826 \ ' }',
2827 \ ' }',
2828 \ '}' ],
2829 \ ['void testFunction () {',
2830 \ ' // for (int j = 0; j < 10; i++) {',
2831 \ ' // }',
2832 \ '}'])
2833 call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite1', {})
2834 call term_sendkeys(buf, ":set diffopt+=iwhiteall\<CR>")
2835 call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002836 " clean up
2837 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002838endfunc
2839
2840func Test_linematch_diff_grouping()
2841 CheckScreendump
2842 call delete('.Xdifile1.swp')
2843 call delete('.Xdifile2.swp')
2844 call WriteDiffFiles(0, [], [])
2845 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2846 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2847
2848 " a diff that would result in multiple groups before grouping optimization
2849 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2850 call WriteDiffFiles(buf, ['!A',
2851 \ '!B',
2852 \ '!C' ],
2853 \ ['?Z',
2854 \ '?A',
2855 \ '?B',
2856 \ '?C',
2857 \ '?A',
2858 \ '?B',
2859 \ '?B',
2860 \ '?C'])
2861 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping1', {})
2862 call WriteDiffFiles(buf, ['!A',
2863 \ '!B',
2864 \ '!C' ],
2865 \ ['?A',
2866 \ '?Z',
2867 \ '?B',
2868 \ '?C',
2869 \ '?A',
2870 \ '?B',
2871 \ '?C',
2872 \ '?C'])
2873 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002874 " clean up
2875 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002876endfunc
2877
2878func Test_linematch_diff_scroll()
2879 CheckScreendump
2880 call delete('.Xdifile1.swp')
2881 call delete('.Xdifile2.swp')
2882 call WriteDiffFiles(0, [], [])
2883 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2884 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2885
2886 " a diff that would result in multiple groups before grouping optimization
2887 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2888 call WriteDiffFiles(buf, ['!A',
2889 \ '!B',
2890 \ '!C' ],
2891 \ ['?A',
2892 \ '?Z',
2893 \ '?B',
2894 \ '?C',
2895 \ '?A',
2896 \ '?B',
2897 \ '?C',
2898 \ '?C'])
2899 " scroll down to show calculation of top fill and scroll to correct line in
2900 " both windows
2901 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll0', {})
2902 call term_sendkeys(buf, "3\<c-e>")
2903 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll1', {})
2904 call term_sendkeys(buf, "3\<c-e>")
2905 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002906 " clean up
2907 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002908endfunc
2909
Jonathon7c7a4e62025-01-12 09:58:00 +01002910func Test_linematch_line_limit_exceeded()
2911 CheckScreendump
2912 call delete('.Xdifile1.swp')
2913 call delete('.Xdifile2.swp')
2914 call WriteDiffFiles(0, [], [])
2915 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2916 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2917
2918 call term_sendkeys(buf, ":set diffopt+=linematch:10\<CR>")
2919 " a diff block will not be aligned with linematch because it's contents
2920 " exceed 10 lines
2921 call WriteDiffFiles(buf,
2922 \ ['common line',
2923 \ 'HIL',
2924 \ '',
2925 \ 'aABCabc',
2926 \ 'aABCabc',
2927 \ 'aABCabc',
2928 \ 'aABCabc',
2929 \ 'common line',
2930 \ 'HIL',
2931 \ 'common line',
2932 \ 'something'],
2933 \ ['common line',
2934 \ 'DEF',
2935 \ 'GHI',
2936 \ 'something',
2937 \ '',
2938 \ 'aDEFabc',
2939 \ 'xyz',
2940 \ 'xyz',
2941 \ 'xyz',
2942 \ 'aDEFabc',
2943 \ 'aDEFabc',
2944 \ 'aDEFabc',
2945 \ 'common line',
2946 \ 'DEF',
2947 \ 'GHI',
2948 \ 'something else',
2949 \ 'common line',
2950 \ 'something'])
2951 call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded1', {})
2952 " after increasing the count to 30, the limit is not exceeded, and the
2953 " alignment algorithm will run on the largest diff block here
2954 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2955 call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002956 " clean up
2957 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002958endfunc
2959
2960func Test_linematch_3diffs()
2961 CheckScreendump
2962 call delete('.Xdifile1.swp')
2963 call delete('.Xdifile2.swp')
2964 call delete('.Xdifile3.swp')
2965 call WriteDiffFiles3(0, [], [], [])
2966 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
2967 call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
2968 call term_sendkeys(buf, "2\<c-w>w:set autoread\<CR>")
2969 call term_sendkeys(buf, "3\<c-w>w:set autoread\<CR>")
2970 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2971 call WriteDiffFiles3(buf,
2972 \ ["",
2973 \ " common line",
2974 \ " AAA",
2975 \ " AAA",
2976 \ " AAA"],
2977 \ ["",
2978 \ " common line",
2979 \ " <<<<<<< HEAD",
2980 \ " AAA",
2981 \ " AAA",
2982 \ " AAA",
2983 \ " =======",
2984 \ " BBB",
2985 \ " BBB",
2986 \ " BBB",
2987 \ " >>>>>>> branch1"],
2988 \ ["",
2989 \ " common line",
2990 \ " BBB",
2991 \ " BBB",
2992 \ " BBB"])
2993 call VerifyScreenDump(buf, 'Test_linematch_3diffs1', {})
Jonathonca307ef2025-01-17 13:37:35 +01002994 " clean up
2995 call StopVimInTerminal(buf)
2996endfunc
Jonathon7c7a4e62025-01-12 09:58:00 +01002997
Jonathonca307ef2025-01-17 13:37:35 +01002998" this used to access invalid memory
2999func Test_linematch_3diffs_sanity_check()
3000 CheckScreendump
3001 call delete('.Xfile_linematch1.swp')
3002 call delete('.Xfile_linematch2.swp')
3003 call delete('.Xfile_linematch3.swp')
3004 let lines =<< trim END
3005 set diffopt+=linematch:60
3006 call feedkeys("Aq\<esc>")
3007 call feedkeys("GAklm\<esc>")
3008 call feedkeys("o")
3009 END
3010 call writefile(lines, 'Xlinematch_3diffs.vim', 'D')
3011 call writefile(['abcd', 'def', 'hij'], 'Xfile_linematch1', 'D')
3012 call writefile(['defq', 'hijk', 'nopq'], 'Xfile_linematch2', 'D')
3013 call writefile(['hijklm', 'nopqr', 'stuv'], 'Xfile_linematch3', 'D')
3014 call WriteDiffFiles3(0, [], [], [])
3015 let buf = RunVimInTerminal('-d -S Xlinematch_3diffs.vim Xfile_linematch1 Xfile_linematch2 Xfile_linematch3', {})
3016 call VerifyScreenDump(buf, 'Test_linematch_3diffs2', {})
3017
3018 " clean up
3019 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01003020endfunc
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01003021" vim: shiftwidth=2 sts=2 expandtab