blob: 5cd98717089e544e3dd04963f5a15703a8220d11 [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()
55 " Set up two files with the minimal case
56 call writefile(['Paragraph 1', '', 'Paragraph 2', '', 'Paragraph 3'], 'Xfile1')
57 call writefile(['Paragraph 1', '', 'Paragraph 3'], 'Xfile2')
58
59 " Open in diff mode
60 exe 'edit Xfile1'
61 exe 'vert diffsplit Xfile2'
62
63 " Ensure both windows are in diff mode and folds are enabled
64 set foldmethod=diff
65 set foldenable
66
67 " Go to the diff and apply dp to copy Paragraph 2 to Xfile2
68 normal! ]c
69 normal! dp
70
71 " Redraw and check folds
72 redraw!
73 let win1_fold = foldclosed(1)
74 let win2_fold = foldclosed(1)
75
76 " Both windows should be fully folded (foldclosed returns 1 for top fold)
77 call assert_equal(1, win1_fold)
78 call assert_equal(1, win2_fold)
79
80 " Clean up
81 bwipe!
82 bwipe!
83 call delete('Xfile1')
84 call delete('Xfile2')
85endfunc
86
Bram Moolenaare828b762018-09-10 17:51:58 +020087func Test_vert_split_internal()
88 set diffopt=internal,filler
89 call Common_vert_split()
90 set diffopt&
91endfunc
92
93func Common_vert_split()
Bram Moolenaar42093c02016-07-30 16:16:54 +020094 " Disable the title to avoid xterm keeping the wrong one.
95 set notitle noicon
96 new
97 let l = ['1 aa', '2 bb', '3 cc', '4 dd', '5 ee']
98 call setline(1, l)
99 w! Xtest
100 normal dd
101 $
102 put
103 normal kkrXoxxx
104 w! Xtest2
105 file Nop
106 normal ggoyyyjjjozzzz
107 set foldmethod=marker foldcolumn=4
108 call assert_equal(0, &diff)
109 call assert_equal('marker', &foldmethod)
110 call assert_equal(4, &foldcolumn)
111 call assert_equal(0, &scrollbind)
112 call assert_equal(0, &cursorbind)
113 call assert_equal(1, &wrap)
114
115 vert diffsplit Xtest
116 vert diffsplit Xtest2
117 call assert_equal(1, &diff)
118 call assert_equal('diff', &foldmethod)
119 call assert_equal(2, &foldcolumn)
120 call assert_equal(1, &scrollbind)
121 call assert_equal(1, &cursorbind)
122 call assert_equal(0, &wrap)
123
124 let diff_fdm = &fdm
125 let diff_fdc = &fdc
126 " repeat entering diff mode here to see if this saves the wrong settings
127 diffthis
128 " jump to second window for a moment to have filler line appear at start of
129 " first window
130 wincmd w
131 normal gg
132 wincmd p
133 normal gg
134 call assert_equal(2, winline())
135 normal j
136 call assert_equal(4, winline())
137 normal j
138 call assert_equal(5, winline())
139 normal j
140 call assert_equal(6, winline())
141 normal j
142 call assert_equal(8, winline())
143 normal j
144 call assert_equal(9, winline())
145
146 wincmd w
147 normal gg
148 call assert_equal(1, winline())
149 normal j
150 call assert_equal(2, winline())
151 normal j
152 call assert_equal(4, winline())
153 normal j
154 call assert_equal(5, winline())
155 normal j
156 call assert_equal(8, winline())
157
158 wincmd w
159 normal gg
160 call assert_equal(2, winline())
161 normal j
162 call assert_equal(3, winline())
163 normal j
164 call assert_equal(4, winline())
165 normal j
166 call assert_equal(5, winline())
167 normal j
168 call assert_equal(6, winline())
169 normal j
170 call assert_equal(7, winline())
171 normal j
172 call assert_equal(8, winline())
173
174 " Test diffoff
175 diffoff!
zeertzjq5fd6ab82022-08-17 12:09:45 +0100176 1wincmd w
Bram Moolenaar42093c02016-07-30 16:16:54 +0200177 let &diff = 1
178 let &fdm = diff_fdm
179 let &fdc = diff_fdc
180 4wincmd w
181 diffoff!
182 1wincmd w
183 call assert_equal(0, &diff)
184 call assert_equal('marker', &foldmethod)
185 call assert_equal(4, &foldcolumn)
186 call assert_equal(0, &scrollbind)
187 call assert_equal(0, &cursorbind)
188 call assert_equal(1, &wrap)
189
190 wincmd w
191 call assert_equal(0, &diff)
192 call assert_equal('marker', &foldmethod)
193 call assert_equal(4, &foldcolumn)
194 call assert_equal(0, &scrollbind)
195 call assert_equal(0, &cursorbind)
196 call assert_equal(1, &wrap)
197
198 wincmd w
199 call assert_equal(0, &diff)
200 call assert_equal('marker', &foldmethod)
201 call assert_equal(4, &foldcolumn)
202 call assert_equal(0, &scrollbind)
203 call assert_equal(0, &cursorbind)
204 call assert_equal(1, &wrap)
205
Bram Moolenaar623cf882016-07-30 16:36:01 +0200206 call delete('Xtest')
207 call delete('Xtest2')
Bram Moolenaar42093c02016-07-30 16:16:54 +0200208 windo bw!
209endfunc
210
211func Test_filler_lines()
212 " Test that diffing shows correct filler lines
213 enew!
214 put =range(4,10)
215 1d _
216 vnew
217 put =range(1,10)
218 1d _
219 windo diffthis
220 wincmd h
221 call assert_equal(1, line('w0'))
222 unlet! diff_fdm diff_fdc
Bram Moolenaar90d121f2016-07-30 19:11:25 +0200223 windo diffoff
224 bwipe!
225 enew!
226endfunc
Bram Moolenaar42093c02016-07-30 16:16:54 +0200227
Bram Moolenaar90d121f2016-07-30 19:11:25 +0200228func Test_diffget_diffput()
229 enew!
230 let l = range(50)
231 call setline(1, l)
232 call assert_fails('diffget', 'E99:')
233 diffthis
234 call assert_fails('diffget', 'E100:')
235 new
236 let l[10] = 'one'
237 let l[20] = 'two'
238 let l[30] = 'three'
239 let l[40] = 'four'
240 call setline(1, l)
241 diffthis
242 call assert_equal('one', getline(11))
243 11diffget
244 call assert_equal('10', getline(11))
245 21diffput
246 wincmd w
247 call assert_equal('two', getline(21))
248 normal 31Gdo
249 call assert_equal('three', getline(31))
250 call assert_equal('40', getline(41))
251 normal 41Gdp
252 wincmd w
253 call assert_equal('40', getline(41))
254 new
255 diffthis
256 call assert_fails('diffget', 'E101:')
257
258 windo diffoff
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200259 %bwipe!
260endfunc
261
Bram Moolenaar5f57bdc2018-10-25 17:52:23 +0200262" Test putting two changes from one buffer to another
263func Test_diffput_two()
264 new a
265 let win_a = win_getid()
266 call setline(1, range(1, 10))
267 diffthis
268 new b
269 let win_b = win_getid()
270 call setline(1, range(1, 10))
271 8del
272 5del
273 diffthis
274 call win_gotoid(win_a)
275 %diffput
276 call win_gotoid(win_b)
277 call assert_equal(map(range(1, 10), 'string(v:val)'), getline(1, '$'))
278 bwipe! a
279 bwipe! b
280endfunc
281
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200282" Test for :diffget/:diffput with a range that is inside a diff chunk
283func Test_diffget_diffput_range()
284 call setline(1, range(1, 10))
285 new
286 call setline(1, range(11, 20))
287 windo diffthis
288 3,5diffget
289 call assert_equal(['13', '14', '15'], getline(3, 5))
290 call setline(1, range(1, 10))
291 4,8diffput
292 wincmd p
293 call assert_equal(['13', '4', '5', '6', '7', '8', '19'], getline(3, 9))
294 %bw!
295endfunc
296
297" Test for :diffget/:diffput with an empty buffer and a non-empty buffer
298func Test_diffget_diffput_empty_buffer()
299 %d _
300 new
301 call setline(1, 'one')
302 windo diffthis
303 diffget
304 call assert_equal(['one'], getline(1, '$'))
305 %d _
306 diffput
307 wincmd p
308 call assert_equal([''], getline(1, '$'))
309 %bw!
310endfunc
311
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100312" :diffput and :diffget completes names of buffers which
Dominique Pelle923dce22021-11-21 11:36:04 +0000313" are in diff mode and which are different than current buffer.
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100314" No completion when the current window is not in diff mode.
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100315func Test_diffget_diffput_completion()
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100316 e Xdiff1 | diffthis
317 botright new Xdiff2
318 botright new Xdiff3 | split | diffthis
319 botright new Xdiff4 | diffthis
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100320
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100321 wincmd t
322 call assert_equal('Xdiff1', bufname('%'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100323 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100324 call assert_equal('"diffput Xdiff3 Xdiff4', @:)
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100325 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100326 call assert_equal('"diffget Xdiff3 Xdiff4', @:)
327 call assert_equal(['Xdiff3', 'Xdiff4'], getcompletion('', 'diff_buffer'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100328
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100329 " Xdiff2 is not in diff mode, so no completion for :diffput, :diffget
330 wincmd j
331 call assert_equal('Xdiff2', bufname('%'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100332 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
333 call assert_equal('"diffput ', @:)
334 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
335 call assert_equal('"diffget ', @:)
336 call assert_equal([], getcompletion('', 'diff_buffer'))
337
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100338 " Xdiff3 is split in 2 windows, only the top one is in diff mode.
339 " So completion of :diffput :diffget only happens in the top window.
340 wincmd j
341 call assert_equal('Xdiff3', bufname('%'))
342 call assert_equal(1, &diff)
343 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
344 call assert_equal('"diffput Xdiff1 Xdiff4', @:)
345 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
346 call assert_equal('"diffget Xdiff1 Xdiff4', @:)
347 call assert_equal(['Xdiff1', 'Xdiff4'], getcompletion('', 'diff_buffer'))
348
349 wincmd j
350 call assert_equal('Xdiff3', bufname('%'))
351 call assert_equal(0, &diff)
352 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
353 call assert_equal('"diffput ', @:)
354 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
355 call assert_equal('"diffget ', @:)
356 call assert_equal([], getcompletion('', 'diff_buffer'))
357
358 wincmd j
359 call assert_equal('Xdiff4', bufname('%'))
360 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
361 call assert_equal('"diffput Xdiff1 Xdiff3', @:)
362 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
363 call assert_equal('"diffget Xdiff1 Xdiff3', @:)
364 call assert_equal(['Xdiff1', 'Xdiff3'], getcompletion('', 'diff_buffer'))
365
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100366 %bwipe
367endfunc
368
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200369func Test_dp_do_buffer()
370 e! one
371 let bn1=bufnr('%')
372 let l = range(60)
373 call setline(1, l)
374 diffthis
375
376 new two
377 let l[10] = 'one'
378 let l[20] = 'two'
379 let l[30] = 'three'
380 let l[40] = 'four'
381 let l[50] = 'five'
382 call setline(1, l)
383 diffthis
384
385 " dp and do with invalid buffer number.
386 11
387 call assert_fails('norm 99999dp', 'E102:')
388 call assert_fails('norm 99999do', 'E102:')
389 call assert_fails('diffput non_existing_buffer', 'E94:')
390 call assert_fails('diffget non_existing_buffer', 'E94:')
391
392 " dp and do with valid buffer number.
393 call assert_equal('one', getline('.'))
394 exe 'norm ' . bn1 . 'do'
395 call assert_equal('10', getline('.'))
396 21
397 call assert_equal('two', getline('.'))
Bram Moolenaar94722c52023-01-28 19:19:03 +0000398 diffget one
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200399 call assert_equal('20', getline('.'))
400
401 31
402 exe 'norm ' . bn1 . 'dp'
403 41
404 diffput one
405 wincmd w
406 31
407 call assert_equal('three', getline('.'))
408 41
409 call assert_equal('four', getline('.'))
410
411 " dp and do with buffer number which is not in diff mode.
412 new not_in_diff_mode
413 let bn3=bufnr('%')
414 wincmd w
415 51
416 call assert_fails('exe "norm" . bn3 . "dp"', 'E103:')
417 call assert_fails('exe "norm" . bn3 . "do"', 'E103:')
418 call assert_fails('diffput not_in_diff_mode', 'E94:')
419 call assert_fails('diffget not_in_diff_mode', 'E94:')
420
421 windo diffoff
422 %bwipe!
Bram Moolenaar42093c02016-07-30 16:16:54 +0200423endfunc
Bram Moolenaare67d5462016-08-27 22:40:42 +0200424
Bram Moolenaardf77cef2018-10-07 17:46:42 +0200425func Test_do_lastline()
426 e! one
427 call setline(1, ['1','2','3','4','5','6'])
428 diffthis
429
430 new two
431 call setline(1, ['2','4','5'])
432 diffthis
433
434 1
435 norm dp]c
436 norm dp]c
437 wincmd w
438 call assert_equal(4, line('$'))
439 norm G
440 norm do
441 call assert_equal(3, line('$'))
442
443 windo diffoff
444 %bwipe!
445endfunc
446
Bram Moolenaare67d5462016-08-27 22:40:42 +0200447func Test_diffoff()
448 enew!
449 call setline(1, ['Two', 'Three'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200450 redraw
Bram Moolenaare67d5462016-08-27 22:40:42 +0200451 let normattr = screenattr(1, 1)
452 diffthis
453 botright vert new
454 call setline(1, ['One', '', 'Two', 'Three'])
455 diffthis
456 redraw
Bram Moolenaar196b4662019-09-06 21:34:30 +0200457 call assert_notequal(normattr, 1->screenattr(1))
Bram Moolenaare67d5462016-08-27 22:40:42 +0200458 diffoff!
459 redraw
460 call assert_equal(normattr, screenattr(1, 1))
461 bwipe!
462 bwipe!
463endfunc
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200464
Bram Moolenaare828b762018-09-10 17:51:58 +0200465func Common_icase_test()
466 edit one
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100467 call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#vϵ', 'Si⃗x', 'Se⃗ve⃗n'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200468 redraw
469 let normattr = screenattr(1, 1)
470 diffthis
471
472 botright vert new two
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100473 call setline(1, ['one', 'TWO', 'Three ', 'Four', 'fI=VΕ', 'SI⃗x', 'SEvE⃗n'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200474 diffthis
475
476 redraw
477 call assert_equal(normattr, screenattr(1, 1))
478 call assert_equal(normattr, screenattr(2, 1))
479 call assert_notequal(normattr, screenattr(3, 1))
480 call assert_equal(normattr, screenattr(4, 1))
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100481 call assert_equal(normattr, screenattr(6, 2))
482 call assert_notequal(normattr, screenattr(7, 2))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200483
Bram Moolenaarda22b8c2017-09-02 18:01:50 +0200484 let dtextattr = screenattr(5, 3)
485 call assert_notequal(dtextattr, screenattr(5, 1))
486 call assert_notequal(dtextattr, screenattr(5, 5))
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100487 call assert_notequal(dtextattr, screenattr(7, 4))
Bram Moolenaarda22b8c2017-09-02 18:01:50 +0200488
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200489 diffoff!
490 %bwipe!
Bram Moolenaare828b762018-09-10 17:51:58 +0200491endfunc
492
493func Test_diffopt_icase()
494 set diffopt=icase,foldcolumn:0
495 call Common_icase_test()
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200496 set diffopt&
497endfunc
498
Bram Moolenaare828b762018-09-10 17:51:58 +0200499func Test_diffopt_icase_internal()
500 set diffopt=icase,foldcolumn:0,internal
501 call Common_icase_test()
502 set diffopt&
503endfunc
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200504
Bram Moolenaare828b762018-09-10 17:51:58 +0200505func Common_iwhite_test()
506 edit one
507 " Difference in trailing spaces and amount of spaces should be ignored,
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200508 " but not other space differences.
Bram Moolenaare828b762018-09-10 17:51:58 +0200509 call setline(1, ["One \t", 'Two', 'Three', 'one two', 'one two', 'Four'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200510 redraw
511 let normattr = screenattr(1, 1)
512 diffthis
513
514 botright vert new two
Bram Moolenaare828b762018-09-10 17:51:58 +0200515 call setline(1, ["One\t ", "Two\t ", 'Three', 'one two', 'onetwo', ' Four'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200516 diffthis
517
518 redraw
519 call assert_equal(normattr, screenattr(1, 1))
520 call assert_equal(normattr, screenattr(2, 1))
521 call assert_equal(normattr, screenattr(3, 1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200522 call assert_equal(normattr, screenattr(4, 1))
523 call assert_notequal(normattr, screenattr(5, 1))
524 call assert_notequal(normattr, screenattr(6, 1))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200525
526 diffoff!
527 %bwipe!
Bram Moolenaare828b762018-09-10 17:51:58 +0200528endfunc
529
530func Test_diffopt_iwhite()
531 set diffopt=iwhite,foldcolumn:0
532 call Common_iwhite_test()
533 set diffopt&
534endfunc
535
536func Test_diffopt_iwhite_internal()
537 set diffopt=internal,iwhite,foldcolumn:0
538 call Common_iwhite_test()
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200539 set diffopt&
540endfunc
541
542func Test_diffopt_context()
543 enew!
544 call setline(1, ['1', '2', '3', '4', '5', '6', '7'])
545 diffthis
546 new
547 call setline(1, ['1', '2', '3', '4', '5x', '6', '7'])
548 diffthis
549
550 set diffopt=context:2
551 call assert_equal('+-- 2 lines: 1', foldtextresult(1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200552 set diffopt=internal,context:2
553 call assert_equal('+-- 2 lines: 1', foldtextresult(1))
554
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200555 set diffopt=context:1
556 call assert_equal('+-- 3 lines: 1', foldtextresult(1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200557 set diffopt=internal,context:1
558 call assert_equal('+-- 3 lines: 1', foldtextresult(1))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200559
560 diffoff!
561 %bwipe!
562 set diffopt&
563endfunc
564
565func Test_diffopt_horizontal()
Bram Moolenaare828b762018-09-10 17:51:58 +0200566 set diffopt=internal,horizontal
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200567 diffsplit
568
569 call assert_equal(&columns, winwidth(1))
570 call assert_equal(&columns, winwidth(2))
571 call assert_equal(&lines, winheight(1) + winheight(2) + 3)
572 call assert_inrange(0, 1, winheight(1) - winheight(2))
573
574 set diffopt&
575 diffoff!
576 %bwipe
577endfunc
578
579func Test_diffopt_vertical()
Bram Moolenaare828b762018-09-10 17:51:58 +0200580 set diffopt=internal,vertical
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200581 diffsplit
582
583 call assert_equal(&lines - 2, winheight(1))
584 call assert_equal(&lines - 2, winheight(2))
585 call assert_equal(&columns, winwidth(1) + winwidth(2) + 1)
586 call assert_inrange(0, 1, winwidth(1) - winwidth(2))
587
588 set diffopt&
589 diffoff!
590 %bwipe
591endfunc
592
Bram Moolenaar97ce4192017-12-01 20:35:58 +0100593func Test_diffopt_hiddenoff()
Bram Moolenaare828b762018-09-10 17:51:58 +0200594 set diffopt=internal,filler,foldcolumn:0,hiddenoff
Bram Moolenaar97ce4192017-12-01 20:35:58 +0100595 e! one
596 call setline(1, ['Two', 'Three'])
597 redraw
598 let normattr = screenattr(1, 1)
599 diffthis
600 botright vert new two
601 call setline(1, ['One', 'Four'])
602 diffthis
603 redraw
604 call assert_notequal(normattr, screenattr(1, 1))
605 set hidden
606 close
607 redraw
608 " should not diffing with hidden buffer two while 'hiddenoff' is enabled
609 call assert_equal(normattr, screenattr(1, 1))
610
611 bwipe!
612 bwipe!
613 set hidden& diffopt&
614endfunc
615
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100616func Test_diffoff_hidden()
Bram Moolenaare828b762018-09-10 17:51:58 +0200617 set diffopt=internal,filler,foldcolumn:0
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100618 e! one
619 call setline(1, ['Two', 'Three'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200620 redraw
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100621 let normattr = screenattr(1, 1)
622 diffthis
623 botright vert new two
624 call setline(1, ['One', 'Four'])
625 diffthis
626 redraw
627 call assert_notequal(normattr, screenattr(1, 1))
628 set hidden
629 close
630 redraw
631 " diffing with hidden buffer two
632 call assert_notequal(normattr, screenattr(1, 1))
633 diffoff
634 redraw
635 call assert_equal(normattr, screenattr(1, 1))
636 diffthis
637 redraw
638 " still diffing with hidden buffer two
639 call assert_notequal(normattr, screenattr(1, 1))
640 diffoff!
641 redraw
642 call assert_equal(normattr, screenattr(1, 1))
643 diffthis
644 redraw
645 " no longer diffing with hidden buffer two
646 call assert_equal(normattr, screenattr(1, 1))
647
648 bwipe!
649 bwipe!
650 set hidden& diffopt&
651endfunc
652
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200653func Test_setting_cursor()
654 new Xtest1
655 put =range(1,90)
656 wq
657 new Xtest2
658 put =range(1,100)
659 wq
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200660
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200661 tabe Xtest2
662 $
663 diffsp Xtest1
664 tabclose
665
666 call delete('Xtest1')
667 call delete('Xtest2')
668endfunc
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100669
670func Test_diff_move_to()
671 new
672 call setline(1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
673 diffthis
674 vnew
675 call setline(1, [1, '2x', 3, 4, 4, 5, '6x', 7, '8x', 9, '10x'])
676 diffthis
677 norm ]c
678 call assert_equal(2, line('.'))
679 norm 3]c
680 call assert_equal(9, line('.'))
681 norm 10]c
682 call assert_equal(11, line('.'))
683 norm [c
684 call assert_equal(9, line('.'))
685 norm 2[c
686 call assert_equal(5, line('.'))
687 norm 10[c
688 call assert_equal(2, line('.'))
689 %bwipe!
690endfunc
691
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200692func Test_diffexpr()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +0100693 CheckExecutable diff
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200694
695 func DiffExpr()
Bram Moolenaar485b6272021-05-18 19:19:03 +0200696 " Prepend some text to check diff type detection
Bram Moolenaar3b8defd2018-09-13 13:03:11 +0200697 call writefile(['warning', ' message'], v:fname_out)
698 silent exe '!diff ' . v:fname_in . ' ' . v:fname_new . '>>' . v:fname_out
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200699 endfunc
700 set diffexpr=DiffExpr()
701 set diffopt=foldcolumn:0
702
703 enew!
704 call setline(1, ['one', 'two', 'three'])
705 redraw
706 let normattr = screenattr(1, 1)
707 diffthis
708
709 botright vert new
710 call setline(1, ['one', 'two', 'three.'])
711 diffthis
712
713 redraw
714 call assert_equal(normattr, screenattr(1, 1))
715 call assert_equal(normattr, screenattr(2, 1))
716 call assert_notequal(normattr, screenattr(3, 1))
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200717 diffoff!
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200718
Dominique Pelle923dce22021-11-21 11:36:04 +0000719 " Try using a non-existing function for 'diffexpr'.
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200720 set diffexpr=NewDiffFunc()
721 call assert_fails('windo diffthis', ['E117:', 'E97:'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200722 diffoff!
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +0000723
724 " Using a script-local function
725 func s:NewDiffExpr()
726 endfunc
727 set diffexpr=s:NewDiffExpr()
728 call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
729 set diffexpr=<SID>NewDiffExpr()
730 call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
731
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200732 %bwipe!
733 set diffexpr& diffopt&
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +0000734 delfunc DiffExpr
735 delfunc s:NewDiffExpr
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200736endfunc
737
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100738func Test_diffpatch()
739 " The patch program on MS-Windows may fail or hang.
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200740 CheckExecutable patch
741 CheckUnix
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100742 new
743 insert
744***************
745*** 1,3 ****
746 1
747! 2
748 3
749--- 1,4 ----
750 1
751! 2x
752 3
753+ 4
754.
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200755 saveas! Xpatch
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100756 bwipe!
757 new
758 call assert_fails('diffpatch Xpatch', 'E816:')
Bram Moolenaar1ef73e32017-03-09 19:21:30 +0100759
Bram Moolenaara95ab322017-03-11 19:21:53 +0100760 for name in ['Xpatch', 'Xpatch$HOME', 'Xpa''tch']
Bram Moolenaar1ef73e32017-03-09 19:21:30 +0100761 call setline(1, ['1', '2', '3'])
762 if name != 'Xpatch'
763 call rename('Xpatch', name)
764 endif
765 exe 'diffpatch ' . escape(name, '$')
766 call assert_equal(['1', '2x', '3', '4'], getline(1, '$'))
767 if name != 'Xpatch'
768 call rename(name, 'Xpatch')
769 endif
770 bwipe!
771 endfor
772
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100773 call delete('Xpatch')
774 bwipe!
775endfunc
776
Bram Moolenaar23a971d2023-04-04 22:04:53 +0100777" FIXME: test fails, the Xresult file can't be read
778func No_Test_diffpatch_restricted()
779 let lines =<< trim END
780 call assert_fails('diffpatch NoSuchDiff', 'E145:')
781
782 call writefile(v:errors, 'Xresult')
783 qa!
784 END
785 call writefile(lines, 'Xrestricted', 'D')
786 if RunVim([], [], '-Z --clean -S Xrestricted')
787 call assert_equal([], readfile('Xresult'))
788 endif
789 call delete('Xresult')
790endfunc
791
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100792func Test_diff_too_many_buffers()
793 for i in range(1, 8)
794 exe "new Xtest" . i
795 diffthis
796 endfor
797 new Xtest9
798 call assert_fails('diffthis', 'E96:')
799 %bwipe!
800endfunc
801
802func Test_diff_nomodifiable()
803 new
804 call setline(1, [1, 2, 3, 4])
805 setl nomodifiable
806 diffthis
807 vnew
808 call setline(1, ['1x', 2, 3, 3, 4])
809 diffthis
810 call assert_fails('norm dp', 'E793:')
811 setl nomodifiable
812 call assert_fails('norm do', 'E21:')
813 %bwipe!
814endfunc
Bram Moolenaarf58a8472017-03-05 18:03:04 +0100815
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200816func Test_diff_hlID()
817 new
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100818 call setline(1, [1, 2, 3, 'Yz', 'a dxxg',])
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200819 diffthis
820 vnew
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100821 call setline(1, ['1x', 2, 'x', 3, 'yx', 'abc defg'])
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200822 diffthis
823 redraw
824
Bram Moolenaara74e4942019-08-04 17:35:53 +0200825 call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("")
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200826
Bram Moolenaara74e4942019-08-04 17:35:53 +0200827 call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange")
828 call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText")
829 call diff_hlID(2, 1)->synIDattr("name")->assert_equal("")
830 call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd")
Bram Moolenaar1a3a8912019-08-23 22:31:37 +0200831 eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("")
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100832 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
833 call diff_hlID(5, 2)->synIDattr("name")->assert_equal("DiffText")
834
835 set diffopt+=icase " test that caching is invalidated by diffopt change
836 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffChange")
837 set diffopt-=icase
838 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
839
840 call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
841 call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffText")
842 call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffText")
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
846 call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
847 call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffTextAdd")
848 call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffChange")
849 call diff_hlID(6, 7)->synIDattr("name")->assert_equal("DiffText")
850 call diff_hlID(6, 8)->synIDattr("name")->assert_equal("DiffChange")
851 set diffopt-=inline:char
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200852
853 wincmd w
854 call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange")
855 call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "")
856 call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "")
857
858 %bwipe!
859endfunc
860
861func Test_diff_filler()
862 new
863 call setline(1, [1, 2, 3, 'x', 4])
864 diffthis
865 vnew
866 call setline(1, [1, 2, 'y', 'y', 3, 4])
867 diffthis
868 redraw
869
Bram Moolenaar1a3a8912019-08-23 22:31:37 +0200870 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 +0200871 wincmd w
872 call assert_equal([0, 0, 0, 0, 2, 0, 0, 0], map(range(-1, 6), 'diff_filler(v:val)'))
873
874 %bwipe!
875endfunc
876
Bram Moolenaarf58a8472017-03-05 18:03:04 +0100877func Test_diff_lastline()
878 enew!
879 only!
880 call setline(1, ['This is a ', 'line with five ', 'rows'])
881 diffthis
882 botright vert new
883 call setline(1, ['This is', 'a line with ', 'four rows'])
884 diffthis
885 1
886 call feedkeys("Je a\<CR>", 'tx')
887 call feedkeys("Je a\<CR>", 'tx')
888 let w1lines = winline()
889 wincmd w
890 $
891 let w2lines = winline()
892 call assert_equal(w2lines, w1lines)
893 bwipe!
894 bwipe!
895endfunc
Bram Moolenaare828b762018-09-10 17:51:58 +0200896
Bram Moolenaar785fc652018-09-15 19:17:38 +0200897func WriteDiffFiles(buf, list1, list2)
Bram Moolenaar61abe7d2022-08-30 21:46:08 +0100898 call writefile(a:list1, 'Xdifile1')
899 call writefile(a:list2, 'Xdifile2')
Bram Moolenaar785fc652018-09-15 19:17:38 +0200900 if a:buf
901 call term_sendkeys(a:buf, ":checktime\<CR>")
902 endif
Bram Moolenaare828b762018-09-10 17:51:58 +0200903endfunc
904
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +0200905func WriteDiffFiles3(buf, list1, list2, list3)
906 call writefile(a:list1, 'Xdifile1')
907 call writefile(a:list2, 'Xdifile2')
908 call writefile(a:list3, 'Xdifile3')
909 if a:buf
910 call term_sendkeys(a:buf, ":checktime\<CR>")
911 endif
912endfunc
913
Bram Moolenaar785fc652018-09-15 19:17:38 +0200914" Verify a screendump with both the internal and external diff.
Bram Moolenaare828b762018-09-10 17:51:58 +0200915func VerifyBoth(buf, dumpfile, extra)
Drew Vogelea67ba72025-05-07 22:05:17 +0200916 CheckScreendump
917
Bram Moolenaare828b762018-09-10 17:51:58 +0200918 " trailing : for leaving the cursor on the command line
Bram Moolenaar785fc652018-09-15 19:17:38 +0200919 for cmd in [":set diffopt=filler" . a:extra . "\<CR>:", ":set diffopt+=internal\<CR>:"]
Bram Moolenaare828b762018-09-10 17:51:58 +0200920 call term_sendkeys(a:buf, cmd)
921 if VerifyScreenDump(a:buf, a:dumpfile, {}, cmd =~ 'internal' ? 'internal' : 'external')
Bram Moolenaar485b6272021-05-18 19:19:03 +0200922 " don't let the next iteration overwrite the "failed" file.
923 return
Bram Moolenaare828b762018-09-10 17:51:58 +0200924 endif
925 endfor
Bram Moolenaar485b6272021-05-18 19:19:03 +0200926
927 " also test unified diff
928 call term_sendkeys(a:buf, ":call SetupUnified()\<CR>:")
glacambread5c1782021-05-24 14:20:53 +0200929 call term_sendkeys(a:buf, ":redraw!\<CR>:")
Bram Moolenaar485b6272021-05-18 19:19:03 +0200930 call VerifyScreenDump(a:buf, a:dumpfile, {}, 'unified')
931 call term_sendkeys(a:buf, ":call StopUnified()\<CR>:")
Bram Moolenaare828b762018-09-10 17:51:58 +0200932endfunc
933
Bram Moolenaar785fc652018-09-15 19:17:38 +0200934" Verify a screendump with the internal diff only.
935func VerifyInternal(buf, dumpfile, extra)
Drew Vogelea67ba72025-05-07 22:05:17 +0200936 CheckScreendump
937
Bram Moolenaar785fc652018-09-15 19:17:38 +0200938 call term_sendkeys(a:buf, ":diffupdate!\<CR>")
939 " trailing : for leaving the cursor on the command line
940 call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:")
941 call VerifyScreenDump(a:buf, a:dumpfile, {})
942endfunc
943
Bram Moolenaare828b762018-09-10 17:51:58 +0200944func Test_diff_screen()
Yee Cheng Chin49f2ba62024-02-14 20:34:58 +0100945 if has('osxdarwin') && system('diff --version') =~ '^Apple diff'
946 throw 'Skipped: unified diff does not work properly on this macOS version'
rhysde93d5ca2024-02-01 21:22:14 +0100947 endif
948
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100949 let g:test_is_flaky = 1
Bram Moolenaar3c8ee622019-08-03 22:55:50 +0200950 CheckScreendump
951 CheckFeature menu
952
Bram Moolenaar485b6272021-05-18 19:19:03 +0200953 let lines =<< trim END
954 func UnifiedDiffExpr()
955 " Prepend some text to check diff type detection
956 call writefile(['warning', ' message'], v:fname_out)
glacambread5c1782021-05-24 14:20:53 +0200957 silent exe '!diff -U0 ' .. v:fname_in .. ' ' .. v:fname_new .. '>>' .. v:fname_out
Bram Moolenaar485b6272021-05-18 19:19:03 +0200958 endfunc
959 func SetupUnified()
960 set diffexpr=UnifiedDiffExpr()
glacambread5c1782021-05-24 14:20:53 +0200961 diffupdate
Bram Moolenaar485b6272021-05-18 19:19:03 +0200962 endfunc
963 func StopUnified()
964 set diffexpr=
965 endfunc
966 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100967 call writefile(lines, 'XdiffSetup', 'D')
Bram Moolenaar485b6272021-05-18 19:19:03 +0200968
Bram Moolenaare828b762018-09-10 17:51:58 +0200969 " clean up already existing swap files, just in case
Bram Moolenaar61abe7d2022-08-30 21:46:08 +0100970 call delete('.Xdifile1.swp')
971 call delete('.Xdifile2.swp')
Bram Moolenaare828b762018-09-10 17:51:58 +0200972
973 " Test 1: Add a line in beginning of file 2
Bram Moolenaar785fc652018-09-15 19:17:38 +0200974 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 +0100975 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
Bram Moolenaar8ee4c012019-03-29 18:08:18 +0100976 " Set autoread mode, so that Vim won't complain once we re-write the test
Bram Moolenaare828b762018-09-10 17:51:58 +0200977 " files
Bram Moolenaar785fc652018-09-15 19:17:38 +0200978 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
Bram Moolenaare828b762018-09-10 17:51:58 +0200979
980 call VerifyBoth(buf, 'Test_diff_01', '')
981
982 " Test 2: Add a line in beginning of file 1
Bram Moolenaar785fc652018-09-15 19:17:38 +0200983 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 +0200984 call VerifyBoth(buf, 'Test_diff_02', '')
985
986 " Test 3: Add a line at the end of file 2
Bram Moolenaar785fc652018-09-15 19:17:38 +0200987 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 +0200988 call VerifyBoth(buf, 'Test_diff_03', '')
989
990 " Test 4: Add a line at the end of file 1
Bram Moolenaar785fc652018-09-15 19:17:38 +0200991 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 +0200992 call VerifyBoth(buf, 'Test_diff_04', '')
993
994 " 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 +0200995 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 +0200996 call VerifyBoth(buf, 'Test_diff_05', '')
997
998 " 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 +0200999 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 +02001000 call VerifyBoth(buf, 'Test_diff_06', '')
1001
Bram Moolenaarb9ddda62019-02-19 23:00:50 +01001002 " Variants on test 6 with different context settings
1003 call term_sendkeys(buf, ":set diffopt+=context:2\<cr>")
1004 call VerifyScreenDump(buf, 'Test_diff_06.2', {})
1005 call term_sendkeys(buf, ":set diffopt-=context:2\<cr>")
1006 call term_sendkeys(buf, ":set diffopt+=context:1\<cr>")
1007 call VerifyScreenDump(buf, 'Test_diff_06.1', {})
1008 call term_sendkeys(buf, ":set diffopt-=context:1\<cr>")
1009 call term_sendkeys(buf, ":set diffopt+=context:0\<cr>")
1010 call VerifyScreenDump(buf, 'Test_diff_06.0', {})
1011 call term_sendkeys(buf, ":set diffopt-=context:0\<cr>")
1012
Bram Moolenaare828b762018-09-10 17:51:58 +02001013 " Test 7 - 9: Test normal/patience/histogram diff algorithm
Bram Moolenaar785fc652018-09-15 19:17:38 +02001014 call WriteDiffFiles(buf, ['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
Bram Moolenaare828b762018-09-10 17:51:58 +02001015 \ ' int i;', ' for(i = 0; i < 10; i++)', ' {', ' printf("Your answer is: ");',
1016 \ ' printf("%d\n", foo);', ' }', '}', '', 'int fact(int n)', '{', ' if(n > 1)', ' {',
1017 \ ' return fact(n-1) * n;', ' }', ' return 1;', '}', '', 'int main(int argc, char **argv)',
1018 \ '{', ' frobnitz(fact(10));', '}'],
1019 \ ['#include <stdio.h>', '', 'int fib(int n)', '{', ' if(n > 2)', ' {',
1020 \ ' return fib(n-1) + fib(n-2);', ' }', ' return 1;', '}', '', '// Frobs foo heartily',
1021 \ 'int frobnitz(int foo)', '{', ' int i;', ' for(i = 0; i < 10; i++)', ' {',
1022 \ ' printf("%d\n", foo);', ' }', '}', '',
1023 \ 'int main(int argc, char **argv)', '{', ' frobnitz(fib(10));', '}'])
1024 call term_sendkeys(buf, ":diffupdate!\<cr>")
1025 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1026 call VerifyScreenDump(buf, 'Test_diff_07', {})
1027
1028 call term_sendkeys(buf, ":set diffopt+=algorithm:patience\<cr>")
1029 call VerifyScreenDump(buf, 'Test_diff_08', {})
1030
1031 call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>")
1032 call VerifyScreenDump(buf, 'Test_diff_09', {})
1033
1034 " Test 10-11: normal/indent-heuristic
1035 call term_sendkeys(buf, ":set diffopt&vim\<cr>")
Bram Moolenaar785fc652018-09-15 19:17:38 +02001036 call WriteDiffFiles(buf, ['', ' def finalize(values)', '', ' values.each do |v|', ' v.finalize', ' end'],
Bram Moolenaare828b762018-09-10 17:51:58 +02001037 \ ['', ' def finalize(values)', '', ' values.each do |v|', ' v.prepare', ' end', '',
1038 \ ' values.each do |v|', ' v.finalize', ' end'])
1039 call term_sendkeys(buf, ":diffupdate!\<cr>")
1040 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1041 call VerifyScreenDump(buf, 'Test_diff_10', {})
1042
Bram Moolenaarb6fc7282018-12-04 22:24:16 +01001043 " Leave trailing : at commandline!
1044 call term_sendkeys(buf, ":set diffopt+=indent-heuristic\<cr>:\<cr>")
1045 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'one')
1046 " shouldn't matter, if indent-algorithm comes before or after the algorithm
1047 call term_sendkeys(buf, ":set diffopt&\<cr>")
1048 call term_sendkeys(buf, ":set diffopt+=indent-heuristic,algorithm:patience\<cr>:\<cr>")
1049 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'two')
1050 call term_sendkeys(buf, ":set diffopt&\<cr>")
1051 call term_sendkeys(buf, ":set diffopt+=algorithm:patience,indent-heuristic\<cr>:\<cr>")
1052 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'three')
Bram Moolenaare828b762018-09-10 17:51:58 +02001053
1054 " Test 12: diff the same file
Bram Moolenaar785fc652018-09-15 19:17:38 +02001055 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 +02001056 call VerifyBoth(buf, 'Test_diff_12', '')
1057
1058 " Test 13: diff an empty file
Bram Moolenaar785fc652018-09-15 19:17:38 +02001059 call WriteDiffFiles(buf, [], [])
Bram Moolenaare828b762018-09-10 17:51:58 +02001060 call VerifyBoth(buf, 'Test_diff_13', '')
1061
1062 " Test 14: test diffopt+=icase
Bram Moolenaar785fc652018-09-15 19:17:38 +02001063 call WriteDiffFiles(buf, ['a', 'b', 'cd'], ['A', 'b', 'cDe'])
Bram Moolenaare828b762018-09-10 17:51:58 +02001064 call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase")
1065
1066 " Test 15-16: test diffopt+=iwhite
Bram Moolenaar785fc652018-09-15 19:17:38 +02001067 call WriteDiffFiles(buf, ['int main()', '{', ' printf("Hello, World!");', ' return 0;', '}'],
Bram Moolenaare828b762018-09-10 17:51:58 +02001068 \ ['int main()', '{', ' if (0)', ' {', ' printf("Hello, World!");', ' return 0;', ' }', '}'])
1069 call term_sendkeys(buf, ":diffupdate!\<cr>")
1070 call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>")
1071 call VerifyScreenDump(buf, 'Test_diff_15', {})
1072 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1073 call VerifyScreenDump(buf, 'Test_diff_16', {})
1074
Bram Moolenaar785fc652018-09-15 19:17:38 +02001075 " Test 17: test diffopt+=iblank
1076 call WriteDiffFiles(buf, ['a', ' ', 'cd', 'ef', 'xxx'], ['a', 'cd', '', 'ef', 'yyy'])
1077 call VerifyInternal(buf, 'Test_diff_17', " diffopt+=iblank")
1078
1079 " Test 18: test diffopt+=iblank,iwhite / iwhiteall / iwhiteeol
1080 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhite")
1081 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteall")
1082 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteeol")
1083
1084 " Test 19: test diffopt+=iwhiteeol
1085 call WriteDiffFiles(buf, ['a ', 'x', 'cd', 'ef', 'xx xx', 'foo', 'bar'], ['a', 'x', 'c d', ' ef', 'xx xx', 'foo', '', 'bar'])
1086 call VerifyInternal(buf, 'Test_diff_19', " diffopt+=iwhiteeol")
1087
Yukihiro Nakadairaf1694b42024-09-22 11:26:13 +02001088 " Test 20: test diffopt+=iwhiteall
Bram Moolenaar785fc652018-09-15 19:17:38 +02001089 call VerifyInternal(buf, 'Test_diff_20', " diffopt+=iwhiteall")
1090
Yukihiro Nakadairaf1694b42024-09-22 11:26:13 +02001091 " Test 21: Delete all lines
1092 call WriteDiffFiles(buf, [0], [])
1093 call VerifyBoth(buf, "Test_diff_21", "")
1094
1095 " Test 22: Add line to empty file
1096 call WriteDiffFiles(buf, [], [0])
1097 call VerifyBoth(buf, "Test_diff_22", "")
1098
Jonathon7c7a4e62025-01-12 09:58:00 +01001099 call WriteDiffFiles(buf, ['?a', '?b', '?c'], ['!b'])
1100 call VerifyInternal(buf, 'Test_diff_23', " diffopt+=linematch:30")
1101
1102 call WriteDiffFiles(buf, ['',
1103 \ 'common line',
1104 \ 'common line',
1105 \ '',
1106 \ 'DEFabc',
1107 \ 'xyz',
1108 \ 'xyz',
1109 \ 'xyz',
1110 \ 'DEFabc',
1111 \ 'DEFabc',
1112 \ 'DEFabc',
1113 \ 'common line',
1114 \ 'common line',
1115 \ 'DEF',
1116 \ 'common line',
1117 \ 'DEF',
1118 \ 'something' ],
1119 \ ['',
1120 \ 'common line',
1121 \ 'common line',
1122 \ '',
1123 \ 'ABCabc',
1124 \ 'ABCabc',
1125 \ 'ABCabc',
1126 \ 'ABCabc',
1127 \ 'common line',
1128 \ 'common line',
1129 \ 'common line',
1130 \ 'something'])
1131 call VerifyInternal(buf, 'Test_diff_24', " diffopt+=linematch:30")
1132
1133
Bram Moolenaare828b762018-09-10 17:51:58 +02001134 " clean up
1135 call StopVimInTerminal(buf)
Bram Moolenaar61abe7d2022-08-30 21:46:08 +01001136 call delete('Xdifile1')
1137 call delete('Xdifile2')
Bram Moolenaare828b762018-09-10 17:51:58 +02001138endfunc
1139
Bram Moolenaar04626c22021-09-01 16:02:07 +02001140func Test_diff_with_scroll_and_change()
1141 CheckScreendump
1142
1143 let lines =<< trim END
1144 call setline(1, range(1, 15))
1145 vnew
1146 call setline(1, range(9, 15))
1147 windo diffthis
1148 wincmd h
1149 exe "normal Gl5\<C-E>"
1150 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001151 call writefile(lines, 'Xtest_scroll_change', 'D')
Bram Moolenaar04626c22021-09-01 16:02:07 +02001152 let buf = RunVimInTerminal('-S Xtest_scroll_change', {})
1153
1154 call VerifyScreenDump(buf, 'Test_diff_scroll_change_01', {})
1155
1156 call term_sendkeys(buf, "ax\<Esc>")
1157 call VerifyScreenDump(buf, 'Test_diff_scroll_change_02', {})
1158
Bram Moolenaar841c2252021-10-22 20:56:55 +01001159 call term_sendkeys(buf, "\<C-W>lay\<Esc>")
1160 call VerifyScreenDump(buf, 'Test_diff_scroll_change_03', {})
1161
Bram Moolenaar04626c22021-09-01 16:02:07 +02001162 " clean up
1163 call StopVimInTerminal(buf)
Bram Moolenaar04626c22021-09-01 16:02:07 +02001164endfunc
1165
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001166func Test_diff_with_cursorline()
Bram Moolenaar3c8ee622019-08-03 22:55:50 +02001167 CheckScreendump
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001168
1169 call writefile([
1170 \ 'hi CursorLine ctermbg=red ctermfg=white',
1171 \ 'set cursorline',
1172 \ 'call setline(1, ["foo","foo","foo","bar"])',
1173 \ 'vnew',
1174 \ 'call setline(1, ["bee","foo","foo","baz"])',
1175 \ 'windo diffthis',
1176 \ '2wincmd w',
Bram Moolenaar59173412022-09-20 22:01:33 +01001177 \ ], 'Xtest_diff_cursorline', 'D')
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001178 let buf = RunVimInTerminal('-S Xtest_diff_cursorline', {})
1179
1180 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_01', {})
1181 call term_sendkeys(buf, "j")
1182 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_02', {})
1183 call term_sendkeys(buf, "j")
1184 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_03', {})
1185
1186 " clean up
1187 call StopVimInTerminal(buf)
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001188endfunc
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001189
Bram Moolenaar127969c2022-03-06 19:54:13 +00001190func Test_diff_with_cursorline_number()
1191 CheckScreendump
1192
1193 let lines =<< trim END
1194 hi CursorLine ctermbg=red ctermfg=white
1195 hi CursorLineNr ctermbg=white ctermfg=black cterm=underline
1196 set cursorline number
1197 call setline(1, ["baz", "foo", "foo", "bar"])
1198 2
1199 vnew
1200 call setline(1, ["foo", "foo", "bar"])
1201 windo diffthis
1202 1wincmd w
1203 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001204 call writefile(lines, 'Xtest_diff_cursorline_number', 'D')
Bram Moolenaar127969c2022-03-06 19:54:13 +00001205 let buf = RunVimInTerminal('-S Xtest_diff_cursorline_number', {})
1206
1207 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_01', {})
1208 call term_sendkeys(buf, ":set cursorlineopt=number\r")
1209 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_02', {})
1210
1211 " clean up
1212 call StopVimInTerminal(buf)
Bram Moolenaar127969c2022-03-06 19:54:13 +00001213endfunc
1214
zeertzjq4f33bc22021-08-05 17:57:02 +02001215func Test_diff_with_cursorline_breakindent()
1216 CheckScreendump
1217
zeertzjq588f20d2023-12-05 15:47:09 +01001218 let lines =<< trim END
1219 hi CursorLine ctermbg=red ctermfg=white
1220 set noequalalways wrap diffopt=followwrap cursorline breakindent
1221 50vnew
1222 call setline(1, [' ', ' ', ' ', ' '])
1223 exe "norm! 20Afoo\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abar\<Esc>"
1224 vnew
1225 call setline(1, [' ', ' ', ' ', ' '])
1226 exe "norm! 20Abee\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abaz\<Esc>"
1227 windo diffthis
1228 2wincmd w
1229 END
1230 call writefile(lines, 'Xtest_diff_cursorline_breakindent', 'D')
zeertzjq4f33bc22021-08-05 17:57:02 +02001231 let buf = RunVimInTerminal('-S Xtest_diff_cursorline_breakindent', {})
1232
1233 call term_sendkeys(buf, "gg0")
1234 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_01', {})
1235 call term_sendkeys(buf, "j")
1236 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_02', {})
1237 call term_sendkeys(buf, "j")
1238 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_03', {})
1239 call term_sendkeys(buf, "j")
1240 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_04', {})
1241
1242 " clean up
1243 call StopVimInTerminal(buf)
zeertzjq4f33bc22021-08-05 17:57:02 +02001244endfunc
1245
zeertzjq588f20d2023-12-05 15:47:09 +01001246func Test_diff_breakindent_after_filler()
1247 CheckScreendump
1248
1249 let lines =<< trim END
zeertzjqf0a9d652024-02-12 22:53:20 +01001250 set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0
zeertzjq588f20d2023-12-05 15:47:09 +01001251 call setline(1, ['a', ' ' .. repeat('c', 50)])
1252 vnew
1253 call setline(1, ['a', 'b', ' ' .. repeat('c', 50)])
1254 windo diffthis
1255 norm! G$
1256 END
1257 call writefile(lines, 'Xtest_diff_breakindent_after_filler', 'D')
1258 let buf = RunVimInTerminal('-S Xtest_diff_breakindent_after_filler', #{rows: 8, cols: 45})
1259 call VerifyScreenDump(buf, 'Test_diff_breakindent_after_filler', {})
1260
1261 " clean up
1262 call StopVimInTerminal(buf)
1263endfunc
1264
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001265func Test_diff_with_syntax()
1266 CheckScreendump
1267
1268 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001269 void doNothing() {
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001270 int x = 0;
1271 char *s = "hello";
1272 return 5;
1273 }
1274 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001275 call writefile(lines, 'Xprogram1.c', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001276 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001277 void doSomething() {
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001278 int x = 0;
1279 char *s = "there";
1280 return 5;
1281 }
1282 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001283 call writefile(lines, 'Xprogram2.c', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001284
1285 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001286 edit Xprogram1.c
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001287 diffsplit Xprogram2.c
1288 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001289 call writefile(lines, 'Xtest_diff_syntax', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001290 let buf = RunVimInTerminal('-S Xtest_diff_syntax', {})
1291
1292 call VerifyScreenDump(buf, 'Test_diff_syntax_1', {})
1293
1294 " clean up
1295 call StopVimInTerminal(buf)
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001296endfunc
1297
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001298func Test_diff_of_diff()
Bram Moolenaar3c8ee622019-08-03 22:55:50 +02001299 CheckScreendump
1300 CheckFeature rightleft
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001301
1302 call writefile([
1303 \ 'call setline(1, ["aa","bb","cc","@@ -3,2 +5,7 @@","dd","ee","ff"])',
1304 \ 'vnew',
1305 \ 'call setline(1, ["aa","bb","cc"])',
1306 \ 'windo diffthis',
Bram Moolenaar8ee4c012019-03-29 18:08:18 +01001307 \ '1wincmd w',
1308 \ 'setlocal number',
Bram Moolenaar59173412022-09-20 22:01:33 +01001309 \ ], 'Xtest_diff_diff', 'D')
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001310 let buf = RunVimInTerminal('-S Xtest_diff_diff', {})
1311
1312 call VerifyScreenDump(buf, 'Test_diff_of_diff_01', {})
1313
Bram Moolenaare73f9112019-03-29 18:29:54 +01001314 call term_sendkeys(buf, ":set rightleft\<cr>")
1315 call VerifyScreenDump(buf, 'Test_diff_of_diff_02', {})
1316
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001317 " clean up
1318 call StopVimInTerminal(buf)
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001319endfunc
Bram Moolenaarc8234772019-11-10 21:00:27 +01001320
1321func CloseoffSetup()
1322 enew
1323 call setline(1, ['one', 'two', 'three'])
1324 diffthis
1325 new
1326 call setline(1, ['one', 'tow', 'three'])
1327 diffthis
1328 call assert_equal(1, &diff)
Jonathonca307ef2025-01-17 13:37:35 +01001329 bw!
Bram Moolenaarc8234772019-11-10 21:00:27 +01001330endfunc
1331
1332func Test_diff_closeoff()
1333 " "closeoff" included by default: last diff win gets 'diff' reset'
1334 call CloseoffSetup()
1335 call assert_equal(0, &diff)
1336 enew!
1337
1338 " "closeoff" excluded: last diff win keeps 'diff' set'
1339 set diffopt-=closeoff
1340 call CloseoffSetup()
1341 call assert_equal(1, &diff)
1342 diffoff!
1343 enew!
1344endfunc
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001345
Bram Moolenaar4223d432021-02-10 13:18:17 +01001346func Test_diff_followwrap()
1347 new
1348 set diffopt+=followwrap
1349 set wrap
1350 diffthis
1351 call assert_equal(1, &wrap)
1352 diffoff
1353 set nowrap
1354 diffthis
1355 call assert_equal(0, &wrap)
1356 diffoff
1357 set diffopt&
1358 bwipe!
1359endfunc
1360
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001361func Test_diff_maintains_change_mark()
Sean Dewarccc16442021-12-29 16:44:48 +00001362 func DiffMaintainsChangeMark()
1363 enew!
1364 call setline(1, ['a', 'b', 'c', 'd'])
1365 diffthis
1366 new
1367 call setline(1, ['a', 'b', 'c', 'e'])
1368 " Set '[ and '] marks
1369 2,3yank
1370 call assert_equal([2, 3], [line("'["), line("']")])
1371 " Verify they aren't affected by the implicit diff
1372 diffthis
1373 call assert_equal([2, 3], [line("'["), line("']")])
1374 " Verify they aren't affected by an explicit diff
1375 diffupdate
1376 call assert_equal([2, 3], [line("'["), line("']")])
1377 bwipe!
1378 bwipe!
1379 endfunc
1380
1381 set diffopt-=internal
1382 call DiffMaintainsChangeMark()
1383 set diffopt+=internal
1384 call DiffMaintainsChangeMark()
Bram Moolenaard9b74a22022-01-16 15:00:08 +00001385
Sean Dewarccc16442021-12-29 16:44:48 +00001386 set diffopt&
Bram Moolenaard9b74a22022-01-16 15:00:08 +00001387 delfunc DiffMaintainsChangeMark
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001388endfunc
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001389
1390" Test for 'patchexpr'
1391func Test_patchexpr()
1392 let g:patch_args = []
1393 func TPatch()
1394 call add(g:patch_args, readfile(v:fname_in))
1395 call add(g:patch_args, readfile(v:fname_diff))
1396 call writefile(['output file'], v:fname_out)
1397 endfunc
1398 set patchexpr=TPatch()
1399
Bram Moolenaar59173412022-09-20 22:01:33 +01001400 call writefile(['input file'], 'Xinput', 'D')
1401 call writefile(['diff file'], 'Xdiff', 'D')
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001402 %bwipe!
1403 edit Xinput
1404 diffpatch Xdiff
1405 call assert_equal('output file', getline(1))
1406 call assert_equal('Xinput.new', bufname())
1407 call assert_equal(2, winnr('$'))
1408 call assert_true(&diff)
1409
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001410 " Using a script-local function
1411 func s:NewPatchExpr()
1412 endfunc
1413 set patchexpr=s:NewPatchExpr()
1414 call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
1415 set patchexpr=<SID>NewPatchExpr()
1416 call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
1417
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001418 set patchexpr&
1419 delfunc TPatch
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001420 delfunc s:NewPatchExpr
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001421 %bwipe!
1422endfunc
1423
Bram Moolenaar511feec2020-06-18 19:15:27 +02001424func Test_diff_rnu()
1425 CheckScreendump
1426
1427 let content =<< trim END
1428 call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
1429 vnew
1430 call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
1431 windo diffthis
1432 setlocal number rnu foldcolumn=0
1433 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001434 call writefile(content, 'Xtest_diff_rnu', 'D')
Bram Moolenaar511feec2020-06-18 19:15:27 +02001435 let buf = RunVimInTerminal('-S Xtest_diff_rnu', {})
1436
1437 call VerifyScreenDump(buf, 'Test_diff_rnu_01', {})
1438
1439 call term_sendkeys(buf, "j")
1440 call VerifyScreenDump(buf, 'Test_diff_rnu_02', {})
1441 call term_sendkeys(buf, "j")
1442 call VerifyScreenDump(buf, 'Test_diff_rnu_03', {})
1443
1444 " clean up
1445 call StopVimInTerminal(buf)
Bram Moolenaar511feec2020-06-18 19:15:27 +02001446endfunc
1447
Bram Moolenaarfc838d62020-06-25 22:23:48 +02001448func Test_diff_multilineconceal()
1449 new
1450 diffthis
1451
1452 new
1453 call matchadd('Conceal', 'a\nb', 9, -1, {'conceal': 'Y'})
1454 set cole=2 cocu=n
1455 call setline(1, ["a", "b"])
1456 diffthis
1457 redraw
1458endfunc
1459
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001460func Test_diff_and_scroll()
1461 " this was causing an ml_get error
1462 set ls=2
Bram Moolenaar94722c52023-01-28 19:19:03 +00001463 for i in range(winheight(0) * 2)
1464 call setline(i, i < winheight(0) - 10 ? i : i + 10)
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001465 endfor
1466 vnew
Bram Moolenaar94722c52023-01-28 19:19:03 +00001467 for i in range(winheight(0)*2 + 10)
1468 call setline(i, i < winheight(0) - 10 ? 0 : i)
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001469 endfor
1470 diffthis
1471 wincmd p
1472 diffthis
1473 execute 'normal ' . winheight(0) . "\<C-d>"
1474
1475 bwipe!
1476 bwipe!
1477 set ls&
1478endfunc
1479
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001480func Test_diff_filler_cursorcolumn()
1481 CheckScreendump
1482
1483 let content =<< trim END
1484 call setline(1, ['aa', 'bb', 'cc'])
1485 vnew
1486 call setline(1, ['aa', 'cc'])
1487 windo diffthis
1488 wincmd p
1489 setlocal cursorcolumn foldcolumn=0
1490 norm! gg0
1491 redraw!
1492 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001493 call writefile(content, 'Xtest_diff_cuc', 'D')
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001494 let buf = RunVimInTerminal('-S Xtest_diff_cuc', {})
1495
1496 call VerifyScreenDump(buf, 'Test_diff_cuc_01', {})
1497
1498 call term_sendkeys(buf, "l")
1499 call term_sendkeys(buf, "\<C-l>")
1500 call VerifyScreenDump(buf, 'Test_diff_cuc_02', {})
1501 call term_sendkeys(buf, "0j")
1502 call term_sendkeys(buf, "\<C-l>")
1503 call VerifyScreenDump(buf, 'Test_diff_cuc_03', {})
1504 call term_sendkeys(buf, "l")
1505 call term_sendkeys(buf, "\<C-l>")
1506 call VerifyScreenDump(buf, 'Test_diff_cuc_04', {})
1507
1508 " clean up
1509 call StopVimInTerminal(buf)
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001510endfunc
1511
Yegappan Lakshmanan30443242021-06-10 21:52:15 +02001512" Test for adding/removing lines inside diff chunks, between diff chunks
1513" and before diff chunks
1514func Test_diff_modify_chunks()
1515 enew!
1516 let w2_id = win_getid()
1517 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1518 new
1519 let w1_id = win_getid()
1520 call setline(1, ['a', '2', '3', 'd', 'e', 'f', '7', '8', 'i'])
1521 windo diffthis
1522
1523 " remove a line between two diff chunks and create a new diff chunk
1524 call win_gotoid(w2_id)
1525 5d
1526 call win_gotoid(w1_id)
1527 call diff_hlID(5, 1)->synIDattr('name')->assert_equal('DiffAdd')
1528
1529 " add a line between two diff chunks
1530 call win_gotoid(w2_id)
1531 normal! 4Goe
1532 call win_gotoid(w1_id)
1533 call diff_hlID(4, 1)->synIDattr('name')->assert_equal('')
1534 call diff_hlID(5, 1)->synIDattr('name')->assert_equal('')
1535
1536 " remove all the lines in a diff chunk.
1537 call win_gotoid(w2_id)
1538 7,8d
1539 call win_gotoid(w1_id)
1540 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1541 call assert_equal(['', 'DiffText', 'DiffText', '', '', '', 'DiffAdd',
1542 \ 'DiffAdd', ''], hl)
1543
1544 " remove lines from one diff chunk to just before the next diff chunk
1545 call win_gotoid(w2_id)
1546 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1547 2,6d
1548 call win_gotoid(w1_id)
1549 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1550 call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', 'DiffAdd',
1551 \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
1552
1553 " remove lines just before the top of a diff chunk
1554 call win_gotoid(w2_id)
1555 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1556 5,6d
1557 call win_gotoid(w1_id)
1558 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1559 call assert_equal(['', 'DiffText', 'DiffText', '', 'DiffText', 'DiffText',
1560 \ 'DiffAdd', 'DiffAdd', ''], hl)
1561
1562 " remove line after the end of a diff chunk
1563 call win_gotoid(w2_id)
1564 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1565 4d
1566 call win_gotoid(w1_id)
1567 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1568 call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', '', '', 'DiffText',
1569 \ 'DiffText', ''], hl)
1570
1571 " remove lines starting from the end of one diff chunk and ending inside
1572 " another diff chunk
1573 call win_gotoid(w2_id)
1574 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1575 4,7d
1576 call win_gotoid(w1_id)
1577 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1578 call assert_equal(['', 'DiffText', 'DiffText', 'DiffText', 'DiffAdd',
1579 \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
1580
1581 " removing the only remaining diff chunk should make the files equal
1582 call win_gotoid(w2_id)
1583 call setline(1, ['a', '2', '3', 'x', 'd', 'e', 'f', 'x', '7', '8', 'i'])
1584 8d
1585 let hl = range(1, 10)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1586 call assert_equal(['', '', '', 'DiffAdd', '', '', '', '', '', ''], hl)
1587 call win_gotoid(w2_id)
1588 4d
1589 call win_gotoid(w1_id)
1590 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1591 call assert_equal(['', '', '', '', '', '', '', '', ''], hl)
1592
1593 %bw!
1594endfunc
glacambread5c1782021-05-24 14:20:53 +02001595
Bram Moolenaar06f60952021-12-28 18:30:05 +00001596func Test_diff_binary()
1597 CheckScreendump
1598
1599 let content =<< trim END
1600 call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g'])
1601 vnew
1602 call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g'])
1603 windo diffthis
1604 wincmd p
1605 norm! gg0
1606 redraw!
1607 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001608 call writefile(content, 'Xtest_diff_bin', 'D')
Bram Moolenaar06f60952021-12-28 18:30:05 +00001609 let buf = RunVimInTerminal('-S Xtest_diff_bin', {})
1610
1611 " Test using internal diff
1612 call VerifyScreenDump(buf, 'Test_diff_bin_01', {})
1613
1614 " Test using internal diff and case folding
1615 call term_sendkeys(buf, ":set diffopt+=icase\<cr>")
1616 call term_sendkeys(buf, "\<C-l>")
1617 call VerifyScreenDump(buf, 'Test_diff_bin_02', {})
1618 " Test using external diff
1619 call term_sendkeys(buf, ":set diffopt=filler\<cr>")
1620 call term_sendkeys(buf, "\<C-l>")
1621 call VerifyScreenDump(buf, 'Test_diff_bin_03', {})
1622 " Test using external diff and case folding
1623 call term_sendkeys(buf, ":set diffopt=filler,icase\<cr>")
1624 call term_sendkeys(buf, "\<C-l>")
1625 call VerifyScreenDump(buf, 'Test_diff_bin_04', {})
1626
1627 " clean up
1628 call StopVimInTerminal(buf)
Bram Moolenaar06f60952021-12-28 18:30:05 +00001629 set diffopt&vim
1630endfunc
1631
Yegappan Lakshmananb0ad2d92022-01-27 13:16:59 +00001632" Test for using the 'zi' command to invert 'foldenable' in diff windows (test
1633" for the issue fixed by patch 6.2.317)
1634func Test_diff_foldinvert()
1635 %bw!
Bram Moolenaar61abe7d2022-08-30 21:46:08 +01001636 edit Xdoffile1
1637 new Xdoffile2
1638 new Xdoffile3
Yegappan Lakshmananb0ad2d92022-01-27 13:16:59 +00001639 windo diffthis
1640 " open a non-diff window
1641 botright new
1642 1wincmd w
1643 call assert_true(getwinvar(1, '&foldenable'))
1644 call assert_true(getwinvar(2, '&foldenable'))
1645 call assert_true(getwinvar(3, '&foldenable'))
1646 normal zi
1647 call assert_false(getwinvar(1, '&foldenable'))
1648 call assert_false(getwinvar(2, '&foldenable'))
1649 call assert_false(getwinvar(3, '&foldenable'))
1650 normal zi
1651 call assert_true(getwinvar(1, '&foldenable'))
1652 call assert_true(getwinvar(2, '&foldenable'))
1653 call assert_true(getwinvar(3, '&foldenable'))
1654
1655 " If the current window has 'noscrollbind', then 'zi' should not change
1656 " 'foldenable' in other windows.
1657 1wincmd w
1658 set noscrollbind
1659 normal zi
1660 call assert_false(getwinvar(1, '&foldenable'))
1661 call assert_true(getwinvar(2, '&foldenable'))
1662 call assert_true(getwinvar(3, '&foldenable'))
1663
1664 " 'zi' should not change the 'foldenable' for windows with 'noscrollbind'
1665 1wincmd w
1666 set scrollbind
1667 normal zi
1668 call setwinvar(2, '&scrollbind', v:false)
1669 normal zi
1670 call assert_false(getwinvar(1, '&foldenable'))
1671 call assert_true(getwinvar(2, '&foldenable'))
1672 call assert_false(getwinvar(3, '&foldenable'))
1673
1674 %bw!
1675 set scrollbind&
1676endfunc
1677
Bram Moolenaara315ce12022-06-24 12:38:57 +01001678" This was scrolling for 'cursorbind' but 'scrollbind' is more important
1679func Test_diff_scroll()
1680 CheckScreendump
1681
1682 let left =<< trim END
1683 line 1
1684 line 2
1685 line 3
1686 line 4
1687
1688 // Common block
1689 // one
1690 // containing
1691 // four lines
1692
1693 // Common block
1694 // two
1695 // containing
1696 // four lines
1697 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001698 call writefile(left, 'Xleft', 'D')
Bram Moolenaara315ce12022-06-24 12:38:57 +01001699 let right =<< trim END
1700 line 1
1701 line 2
1702 line 3
1703 line 4
1704
1705 Lorem
1706 ipsum
1707 dolor
1708 sit
1709 amet,
1710 consectetur
1711 adipiscing
1712 elit.
1713 Etiam
1714 luctus
1715 lectus
1716 sodales,
1717 dictum
1718
1719 // Common block
1720 // one
1721 // containing
1722 // four lines
1723
1724 Vestibulum
1725 tincidunt
1726 aliquet
1727 nulla.
1728
1729 // Common block
1730 // two
1731 // containing
1732 // four lines
1733 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001734 call writefile(right, 'Xright', 'D')
Bram Moolenaara315ce12022-06-24 12:38:57 +01001735 let buf = RunVimInTerminal('-d Xleft Xright', {'rows': 12})
1736 call term_sendkeys(buf, "\<C-W>\<C-W>jjjj")
1737 call VerifyScreenDump(buf, 'Test_diff_scroll_1', {})
1738 call term_sendkeys(buf, "j")
1739 call VerifyScreenDump(buf, 'Test_diff_scroll_2', {})
1740
1741 call StopVimInTerminal(buf)
Bram Moolenaara315ce12022-06-24 12:38:57 +01001742endfunc
1743
Bram Moolenaar38d867f2023-04-01 19:54:40 +01001744" This was scrolling too many lines.
1745func Test_diff_scroll_wrap_on()
1746 20new
1747 40vsplit
1748 call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
1749 setlocal number diff so=0
1750 redraw
1751 normal! jj
1752 call assert_equal(1, winsaveview().topline)
1753 normal! j
1754 call assert_equal(2, winsaveview().topline)
zeertzjq05834912023-10-04 20:12:37 +02001755
1756 bwipe!
1757 bwipe!
1758endfunc
1759
1760func Test_diff_scroll_many_filler()
1761 20new
1762 vnew
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001763 call setline(1, range(1, 40))
zeertzjq05834912023-10-04 20:12:37 +02001764 diffthis
1765 setlocal scrolloff=0
1766 wincmd p
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001767 call setline(1, range(1, 20)->reverse() + ['###']->repeat(41) + range(21, 40)->reverse())
zeertzjq05834912023-10-04 20:12:37 +02001768 diffthis
1769 setlocal scrolloff=0
1770 wincmd p
1771 redraw
1772
1773 " Note: need a redraw after each scroll, otherwise the test always passes.
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001774 for _ in range(2)
1775 normal! G
1776 redraw
1777 call assert_equal(40, winsaveview().topline)
1778 call assert_equal(19, winsaveview().topfill)
1779 exe "normal! \<C-B>"
1780 redraw
1781 call assert_equal(22, winsaveview().topline)
1782 call assert_equal(0, winsaveview().topfill)
1783 exe "normal! \<C-B>"
1784 redraw
1785 call assert_equal(4, winsaveview().topline)
1786 call assert_equal(0, winsaveview().topfill)
1787 exe "normal! \<C-B>"
1788 redraw
1789 call assert_equal(1, winsaveview().topline)
1790 call assert_equal(0, winsaveview().topfill)
1791 set smoothscroll
1792 endfor
zeertzjq05834912023-10-04 20:12:37 +02001793
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001794 set smoothscroll&
Luuk van Baalcb204e62024-04-02 20:49:45 +02001795 %bwipe!
Bram Moolenaar38d867f2023-04-01 19:54:40 +01001796endfunc
1797
Bram Moolenaarcd38bb42022-06-26 14:04:07 +01001798" This was trying to update diffs for a buffer being closed
1799func Test_diff_only()
1800 silent! lfile
1801 set diff
1802 lopen
1803 norm o
1804 silent! norm o
1805
1806 set nodiff
1807 %bwipe!
1808endfunc
1809
Bram Moolenaarc101abf2022-06-26 16:53:34 +01001810" This was causing invalid diff block values
1811" FIXME: somehow this causes a valgrind error when run directly but not when
1812" run as a test.
1813func Test_diff_manipulations()
1814 set diff
1815 split 0
1816 sil! norm R doobdeuR doobdeuR doobdeu
1817
1818 set nodiff
1819 %bwipe!
1820endfunc
1821
Bram Moolenaar4e677b92022-07-28 18:44:27 +01001822" This was causing the line number in the diff block to go below one.
1823" FIXME: somehow this causes a valgrind error when run directly but not when
1824" run as a test.
1825func Test_diff_put_and_undo()
1826 set diff
1827 next 0
1828 split 00
1829 sil! norm o0gguudpo0ggJuudp
1830
1831 bwipe!
1832 bwipe!
1833 set nodiff
1834endfunc
1835
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001836" Test for the diff() function
1837def Test_diff_func()
1838 # string is added/removed/modified at the beginning
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001839 assert_equal("@@ -0,0 +1 @@\n+abc\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001840 diff(['def'], ['abc', 'def'], {output: 'unified'}))
1841 assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 1}],
1842 diff(['def'], ['abc', 'def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001843 assert_equal("@@ -1 +0,0 @@\n-abc\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001844 diff(['abc', 'def'], ['def'], {output: 'unified'}))
1845 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 0}],
1846 diff(['abc', 'def'], ['def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001847 assert_equal("@@ -1 +1 @@\n-abc\n+abx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001848 diff(['abc', 'def'], ['abx', 'def'], {output: 'unified'}))
1849 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1850 diff(['abc', 'def'], ['abx', 'def'], {output: 'indices'}))
1851
1852 # string is added/removed/modified at the end
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001853 assert_equal("@@ -1,0 +2 @@\n+def\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001854 diff(['abc'], ['abc', 'def'], {output: 'unified'}))
1855 assert_equal([{from_idx: 1, from_count: 0, to_idx: 1, to_count: 1}],
1856 diff(['abc'], ['abc', 'def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001857 assert_equal("@@ -2 +1,0 @@\n-def\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001858 diff(['abc', 'def'], ['abc'], {output: 'unified'}))
1859 assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 0}],
1860 diff(['abc', 'def'], ['abc'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001861 assert_equal("@@ -2 +2 @@\n-def\n+xef\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001862 diff(['abc', 'def'], ['abc', 'xef'], {output: 'unified'}))
1863 assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 1}],
1864 diff(['abc', 'def'], ['abc', 'xef'], {output: 'indices'}))
1865
1866 # string is added/removed/modified in the middle
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001867 assert_equal("@@ -2,0 +3 @@\n+xxx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001868 diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'unified'}))
1869 assert_equal([{from_idx: 2, from_count: 0, to_idx: 2, to_count: 1}],
1870 diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001871 assert_equal("@@ -3 +2,0 @@\n-333\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001872 diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'unified'}))
1873 assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 0}],
1874 diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001875 assert_equal("@@ -3 +3 @@\n-333\n+xxx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001876 diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'unified'}))
1877 assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 1}],
1878 diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'indices'}))
1879
1880 # new strings are added to an empty List
1881 assert_equal("@@ -0,0 +1,2 @@\n+abc\n+def\n",
1882 diff([], ['abc', 'def'], {output: 'unified'}))
1883 assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 2}],
1884 diff([], ['abc', 'def'], {output: 'indices'}))
1885
1886 # all the strings are removed from a List
1887 assert_equal("@@ -1,2 +0,0 @@\n-abc\n-def\n",
1888 diff(['abc', 'def'], [], {output: 'unified'}))
1889 assert_equal([{from_idx: 0, from_count: 2, to_idx: 0, to_count: 0}],
1890 diff(['abc', 'def'], [], {output: 'indices'}))
1891
1892 # First character is added/removed/different
1893 assert_equal("@@ -1 +1 @@\n-abc\n+bc\n",
1894 diff(['abc'], ['bc'], {output: 'unified'}))
1895 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1896 diff(['abc'], ['bc'], {output: 'indices'}))
1897 assert_equal("@@ -1 +1 @@\n-bc\n+abc\n",
1898 diff(['bc'], ['abc'], {output: 'unified'}))
1899 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1900 diff(['bc'], ['abc'], {output: 'indices'}))
1901 assert_equal("@@ -1 +1 @@\n-abc\n+xbc\n",
1902 diff(['abc'], ['xbc'], {output: 'unified'}))
1903 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1904 diff(['abc'], ['xbc'], {output: 'indices'}))
1905
1906 # Last character is added/removed/different
1907 assert_equal("@@ -1 +1 @@\n-abc\n+abcd\n",
1908 diff(['abc'], ['abcd'], {output: 'unified'}))
1909 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1910 diff(['abc'], ['abcd'], {output: 'indices'}))
1911 assert_equal("@@ -1 +1 @@\n-abcd\n+abc\n",
1912 diff(['abcd'], ['abc'], {output: 'unified'}))
1913 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1914 diff(['abcd'], ['abc'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001915 var diff_unified: string = diff(['abc'], ['abx'], {output: 'unified'})
1916 assert_equal("@@ -1 +1 @@\n-abc\n+abx\n", diff_unified)
1917 var diff_indices: list<dict<number>> =
1918 diff(['abc'], ['abx'], {output: 'indices'})
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001919 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001920 diff_indices)
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001921
1922 # partial string modification at the start and at the end.
1923 var fromlist =<< trim END
1924 one two
1925 three four
1926 five six
1927 END
1928 var tolist =<< trim END
1929 one
1930 six
1931 END
1932 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'}))
1933 assert_equal([{from_idx: 0, from_count: 3, to_idx: 0, to_count: 2}],
1934 diff(fromlist, tolist, {output: 'indices'}))
1935
1936 # non-contiguous modifications
1937 fromlist =<< trim END
1938 one two
1939 three four
1940 five abc six
1941 END
1942 tolist =<< trim END
1943 one abc two
1944 three four
1945 five six
1946 END
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001947 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 +01001948 diff(fromlist, tolist, {output: 'unified'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001949 assert_equal([{'from_count': 1, 'to_idx': 0, 'to_count': 1, 'from_idx': 0},
1950 {'from_count': 1, 'to_idx': 2, 'to_count': 1, 'from_idx': 2}],
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001951 diff(fromlist, tolist, {output: 'indices'}))
1952
1953 # add/remove blank lines
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001954 assert_equal("@@ -2,2 +1,0 @@\n-\n-\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001955 diff(['one', '', '', 'two'], ['one', 'two'], {output: 'unified'}))
1956 assert_equal([{from_idx: 1, from_count: 2, to_idx: 1, to_count: 0}],
1957 diff(['one', '', '', 'two'], ['one', 'two'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001958 assert_equal("@@ -1,0 +2,2 @@\n+\n+\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001959 diff(['one', 'two'], ['one', '', '', 'two'], {output: 'unified'}))
1960 assert_equal([{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}],
1961 diff(['one', 'two'], ['one', '', '', 'two'], {output: 'indices'}))
1962
1963 # diff ignoring case
1964 assert_equal('', diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'unified'}))
1965 assert_equal([], diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'indices'}))
1966
1967 # diff ignoring all whitespace changes except leading whitespace changes
1968 assert_equal('', diff(['abc def'], ['abc def '], {iwhite: true}))
1969 assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:true}))
1970 assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:false}))
1971 assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:true}))
1972 assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:false}))
1973
1974 # diff ignoring all whitespace changes
1975 assert_equal('', diff(['abc def'], [' abc def '], {iwhiteall: true}))
1976 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:true}))
1977 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:false}))
1978
1979 # diff ignoring trailing whitespace changes
1980 assert_equal('', diff(['abc'], ['abc '], {iwhiteeol: true}))
1981
1982 # diff ignoring blank lines
1983 assert_equal('', diff(['one', '', '', 'two'], ['one', 'two'], {iblank: true}))
1984 assert_equal('', diff(['one', 'two'], ['one', '', '', 'two'], {iblank: true}))
1985
1986 # same string
1987 assert_equal('', diff(['abc', 'def', 'ghi'], ['abc', 'def', 'ghi']))
1988 assert_equal('', diff([''], ['']))
1989 assert_equal('', diff([], []))
1990
1991 # different xdiff algorithms
1992 for algo in ['myers', 'minimal', 'patience', 'histogram']
1993 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
1994 diff([' abc '], [' xxx '], {algorithm: algo, output: 'unified'}))
1995 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1996 diff([' abc '], [' xxx '], {algorithm: algo, output: 'indices'}))
1997 endfor
1998 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
1999 diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'unified'}))
2000 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
2001 diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'indices'}))
2002
2003 # identical strings
2004 assert_equal('', diff(['111', '222'], ['111', '222'], {output: 'unified'}))
2005 assert_equal([], diff(['111', '222'], ['111', '222'], {output: 'indices'}))
2006 assert_equal('', diff([], [], {output: 'unified'}))
2007 assert_equal([], diff([], [], {output: 'indices'}))
2008
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002009 # If 'diffexpr' is set, it should not be used for diff()
2010 def MyDiffExpr()
2011 enddef
2012 var save_diffexpr = &diffexpr
2013 :set diffexpr=MyDiffExpr()
2014 assert_equal("@@ -1 +1 @@\n-abc\n+\n",
2015 diff(['abc'], [''], {output: 'unified'}))
2016 assert_equal([{'from_idx': 0, 'from_count': 1, 'to_idx': 0, 'to_count': 1}],
2017 diff(['abc'], [''], {output: 'indices'}))
2018 assert_equal('MyDiffExpr()', &diffexpr)
2019 &diffexpr = save_diffexpr
2020
2021 # try different values for unified diff 'context'
2022 assert_equal("@@ -0,0 +1 @@\n+x\n",
2023 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c']))
2024 assert_equal("@@ -0,0 +1 @@\n+x\n",
2025 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 0}))
2026 assert_equal("@@ -1 +1,2 @@\n+x\n a\n",
2027 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 1}))
2028 assert_equal("@@ -1,2 +1,3 @@\n+x\n a\n b\n",
2029 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 2}))
2030 assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
2031 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 3}))
2032 assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
2033 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 4}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002034 assert_equal("@@ -0,0 +1 @@\n+x\n",
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002035 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: -1}))
2036
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002037 # Error cases
2038 assert_fails('call diff({}, ["a"])', 'E1211:')
2039 assert_fails('call diff(["a"], {})', 'E1211:')
2040 assert_fails('call diff(["a"], ["a"], [])', 'E1206:')
2041 assert_fails('call diff(["a"], ["a"], {output: "xyz"})', 'E106: Unsupported diff output format: xyz')
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002042 assert_fails('call diff(["a"], ["a"], {context: []})', 'E745: Using a List as a Number')
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002043enddef
Bram Moolenaara315ce12022-06-24 12:38:57 +01002044
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002045" Test for using the diff() function with 'diffexpr'
2046func Test_diffexpr_with_diff_func()
2047 CheckScreendump
2048
2049 let lines =<< trim END
2050 def DiffFuncExpr()
2051 var in: list<string> = readfile(v:fname_in)
2052 var new: list<string> = readfile(v:fname_new)
2053 var out: string = diff(in, new)
2054 writefile(split(out, "\n"), v:fname_out)
2055 enddef
2056 set diffexpr=DiffFuncExpr()
2057
2058 edit Xdifffunc1.txt
2059 diffthis
2060 vert split Xdifffunc2.txt
2061 diffthis
2062 END
2063 call writefile(lines, 'XsetupDiffFunc.vim', 'D')
2064
2065 call writefile(['zero', 'one', 'two', 'three'], 'Xdifffunc1.txt', 'D')
2066 call writefile(['one', 'twox', 'three', 'four'], 'Xdifffunc2.txt', 'D')
2067
2068 let buf = RunVimInTerminal('-S XsetupDiffFunc.vim', {'rows': 12})
2069 call VerifyScreenDump(buf, 'Test_difffunc_diffexpr_1', {})
2070 call StopVimInTerminal(buf)
2071endfunc
2072
zeertzjq9e7f1fc2024-03-16 09:40:22 +01002073func Test_diff_toggle_wrap_skipcol_leftcol()
2074 61vnew
2075 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.')
2076 30vnew
2077 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.')
2078 let win1 = win_getid()
2079 setlocal smoothscroll
2080 exe "normal! $\<C-E>"
2081 wincmd l
2082 let win2 = win_getid()
2083 setlocal smoothscroll
2084 exe "normal! $\<C-E>"
2085 call assert_equal([
2086 \ '<<<sadipscing elitr, sed diam |<<<tetur sadipscing elitr, sed|',
2087 \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
2088 \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
2089 \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
2090 \ '~ |ptua. |',
2091 \ ], ScreenLines([1, 5], 62))
2092 call assert_equal({'col': 29, 'row': 4, 'endcol': 29, 'curscol': 29},
2093 \ screenpos(win1, line('.', win1), col('.', win1)))
2094 call assert_equal({'col': 36, 'row': 5, 'endcol': 36, 'curscol': 36},
2095 \ screenpos(win2, line('.', win2), col('.', win2)))
2096
2097 wincmd h
2098 diffthis
2099 wincmd l
2100 diffthis
2101 normal! 0
2102 call assert_equal([
2103 \ ' ipsum dolor sit amet, conset| Lorem ipsum dolor sit amet, |',
2104 \ '~ |~ |',
2105 \ ], ScreenLines([1, 2], 62))
2106 call assert_equal({'col': 3, 'row': 1, 'endcol': 3, 'curscol': 3},
2107 \ screenpos(win1, line('.', win1), col('.', win1)))
2108 call assert_equal({'col': 34, 'row': 1, 'endcol': 34, 'curscol': 34},
2109 \ screenpos(win2, line('.', win2), col('.', win2)))
2110
2111 normal! $
2112 call assert_equal([
2113 \ ' voluptua. | diam voluptua. |',
2114 \ '~ |~ |',
2115 \ ], ScreenLines([1, 2], 62))
2116 call assert_equal({'col': 11, 'row': 1, 'endcol': 11, 'curscol': 11},
2117 \ screenpos(win1, line('.', win1), col('.', win1)))
2118 call assert_equal({'col': 48, 'row': 1, 'endcol': 48, 'curscol': 48},
2119 \ screenpos(win2, line('.', win2), col('.', win2)))
2120
2121 diffoff!
2122 call assert_equal([
2123 \ 'ipsum dolor sit amet, consetet|Lorem ipsum dolor sit amet, co|',
2124 \ 'ur sadipscing elitr, sed diam |nsetetur sadipscing elitr, sed|',
2125 \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
2126 \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
2127 \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
2128 \ '~ |ptua. |',
2129 \ ], ScreenLines([1, 6], 62))
2130 call assert_equal({'col': 29, 'row': 5, 'endcol': 29, 'curscol': 29},
2131 \ screenpos(win1, line('.', win1), col('.', win1)))
2132 call assert_equal({'col': 36, 'row': 6, 'endcol': 36, 'curscol': 36},
2133 \ screenpos(win2, line('.', win2), col('.', win2)))
2134
2135 bwipe!
2136 bwipe!
2137endfunc
2138
Luuk van Baal9148ba82024-04-08 22:27:41 +02002139" Ctrl-D reveals filler lines below the last line in the buffer.
2140func Test_diff_eob_halfpage()
Luuk van Baal08b0f632024-04-09 22:43:49 +02002141 new
Luuk van Baal9148ba82024-04-08 22:27:41 +02002142 call setline(1, ['']->repeat(10) + ['a'])
2143 diffthis
Luuk van Baal08b0f632024-04-09 22:43:49 +02002144 new
Luuk van Baal9148ba82024-04-08 22:27:41 +02002145 call setline(1, ['']->repeat(3) + ['a', 'b'])
2146 diffthis
Luuk van Baal08b0f632024-04-09 22:43:49 +02002147 resize 5
Luuk van Baal9148ba82024-04-08 22:27:41 +02002148 wincmd j
Luuk van Baal08b0f632024-04-09 22:43:49 +02002149 resize 5
2150 norm G
2151 call assert_equal(7, line('w0'))
2152 exe "norm! \<C-D>"
2153 call assert_equal(8, line('w0'))
Luuk van Baal9148ba82024-04-08 22:27:41 +02002154
2155 %bwipe!
2156endfunc
2157
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +02002158func Test_diff_overlapped_diff_blocks_will_be_merged()
2159 CheckScreendump
2160
2161 let lines =<< trim END
2162 func DiffExprStub()
2163 let txt_in = readfile(v:fname_in)
2164 let txt_new = readfile(v:fname_new)
2165 if txt_in == ["line1"] && txt_new == ["line2"]
2166 call writefile(["1c1"], v:fname_out)
2167 elseif txt_in == readfile("Xdiin1") && txt_new == readfile("Xdinew1")
2168 call writefile(readfile("Xdiout1"), v:fname_out)
2169 elseif txt_in == readfile("Xdiin2") && txt_new == readfile("Xdinew2")
2170 call writefile(readfile("Xdiout2"), v:fname_out)
2171 endif
2172 endfunc
2173 END
2174 call writefile(lines, 'XdiffSetup', 'D')
2175
2176 call WriteDiffFiles(0, [], [])
2177 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
2178 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2179
2180 call WriteDiffFiles(buf, ["a", "b"], ["x", "x"])
2181 call writefile(["a", "b"], "Xdiin1")
2182 call writefile(["x", "x"], "Xdinew1")
2183 call writefile(["1c1", "2c2"], "Xdiout1")
2184 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2185 call VerifyBoth(buf, "Test_diff_overlapped_2.01", "")
2186 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2187
2188 call WriteDiffFiles(buf, ["a", "b", "c"], ["x", "c"])
2189 call writefile(["a", "b", "c"], "Xdiin1")
2190 call writefile(["x", "c"], "Xdinew1")
2191 call writefile(["1c1", "2d1"], "Xdiout1")
2192 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2193 call VerifyBoth(buf, "Test_diff_overlapped_2.02", "")
2194 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2195
2196 call WriteDiffFiles(buf, ["a", "c"], ["x", "x", "c"])
2197 call writefile(["a", "c"], "Xdiin1")
2198 call writefile(["x", "x", "c"], "Xdinew1")
2199 call writefile(["1c1", "1a2"], "Xdiout1")
2200 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2201 call VerifyBoth(buf, "Test_diff_overlapped_2.03", "")
2202 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2203
2204 call StopVimInTerminal(buf)
2205 wincmd c
2206
2207 call WriteDiffFiles3(0, [], [], [])
2208 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2 Xdifile3', {})
2209 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2210
2211 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "b", "c"])
2212 call VerifyBoth(buf, "Test_diff_overlapped_3.01", "")
2213
2214 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "c"])
2215 call VerifyBoth(buf, "Test_diff_overlapped_3.02", "")
2216
2217 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y"])
2218 call VerifyBoth(buf, "Test_diff_overlapped_3.03", "")
2219
2220 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "c"])
2221 call VerifyBoth(buf, "Test_diff_overlapped_3.04", "")
2222
2223 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "y"])
2224 call VerifyBoth(buf, "Test_diff_overlapped_3.05", "")
2225
2226 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "y"])
2227 call VerifyBoth(buf, "Test_diff_overlapped_3.06", "")
2228
2229 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "x"], ["y", "y", "c"])
2230 call VerifyBoth(buf, "Test_diff_overlapped_3.07", "")
2231
2232 call WriteDiffFiles3(buf, ["a", "b", "c"], ["x", "x", "c"], ["a", "y", "y"])
2233 call VerifyBoth(buf, "Test_diff_overlapped_3.08", "")
2234
2235 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "d", "e"])
2236 call VerifyBoth(buf, "Test_diff_overlapped_3.09", "")
2237
2238 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "e"])
2239 call VerifyBoth(buf, "Test_diff_overlapped_3.10", "")
2240
2241 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "y"])
2242 call VerifyBoth(buf, "Test_diff_overlapped_3.11", "")
2243
2244 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "d", "e"])
2245 call VerifyBoth(buf, "Test_diff_overlapped_3.12", "")
2246
2247 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "e"])
2248 call VerifyBoth(buf, "Test_diff_overlapped_3.13", "")
2249
2250 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "y"])
2251 call VerifyBoth(buf, "Test_diff_overlapped_3.14", "")
2252
2253 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "d", "e"])
2254 call VerifyBoth(buf, "Test_diff_overlapped_3.15", "")
2255
2256 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "e"])
2257 call VerifyBoth(buf, "Test_diff_overlapped_3.16", "")
2258
2259 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "y"])
2260 call VerifyBoth(buf, "Test_diff_overlapped_3.17", "")
2261
2262 call WriteDiffFiles3(buf, ["a", "b"], ["x", "b"], ["y", "y"])
2263 call writefile(["a", "b"], "Xdiin1")
2264 call writefile(["x", "b"], "Xdinew1")
2265 call writefile(["1c1"], "Xdiout1")
2266 call writefile(["a", "b"], "Xdiin2")
2267 call writefile(["y", "y"], "Xdinew2")
2268 call writefile(["1c1", "2c2"], "Xdiout2")
2269 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2270 call VerifyInternal(buf, "Test_diff_overlapped_3.18", "")
2271 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2272
2273 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "c", "d"])
2274 call writefile(["a", "b", "c", "d"], "Xdiin1")
2275 call writefile(["x", "b", "x", "d"], "Xdinew1")
2276 call writefile(["1c1", "3c3"], "Xdiout1")
2277 call writefile(["a", "b", "c", "d"], "Xdiin2")
2278 call writefile(["y", "y", "c", "d"], "Xdinew2")
2279 call writefile(["1c1", "2c2"], "Xdiout2")
2280 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2281 call VerifyInternal(buf, "Test_diff_overlapped_3.19", "")
2282 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2283
2284 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "d"])
2285 call writefile(["a", "b", "c", "d"], "Xdiin1")
2286 call writefile(["x", "b", "x", "d"], "Xdinew1")
2287 call writefile(["1c1", "3c3"], "Xdiout1")
2288 call writefile(["a", "b", "c", "d"], "Xdiin2")
2289 call writefile(["y", "y", "y", "d"], "Xdinew2")
2290 call writefile(["1c1", "2,3c2,3"], "Xdiout2")
2291 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2292 call VerifyInternal(buf, "Test_diff_overlapped_3.20", "")
2293 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2294
2295 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "y"])
2296 call writefile(["a", "b", "c", "d"], "Xdiin1")
2297 call writefile(["x", "b", "x", "d"], "Xdinew1")
2298 call writefile(["1c1", "3c3"], "Xdiout1")
2299 call writefile(["a", "b", "c", "d"], "Xdiin2")
2300 call writefile(["y", "y", "y", "y"], "Xdinew2")
2301 call writefile(["1c1", "2,4c2,4"], "Xdiout2")
2302 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2303 call VerifyInternal(buf, "Test_diff_overlapped_3.21", "")
2304 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2305
2306 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b", "c"])
2307 call VerifyBoth(buf, "Test_diff_overlapped_3.22", "")
2308
2309 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["c"])
2310 call VerifyBoth(buf, "Test_diff_overlapped_3.23", "")
2311
2312 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], [])
2313 call VerifyBoth(buf, "Test_diff_overlapped_3.24", "")
2314
2315 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "c"])
2316 call VerifyBoth(buf, "Test_diff_overlapped_3.25", "")
2317
2318 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a"])
2319 call VerifyBoth(buf, "Test_diff_overlapped_3.26", "")
2320
2321 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b"])
2322 call VerifyBoth(buf, "Test_diff_overlapped_3.27", "")
2323
2324 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["d", "e"])
2325 call VerifyBoth(buf, "Test_diff_overlapped_3.28", "")
2326
2327 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["e"])
2328 call VerifyBoth(buf, "Test_diff_overlapped_3.29", "")
2329
2330 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "d", "e"])
2331 call VerifyBoth(buf, "Test_diff_overlapped_3.30", "")
2332
2333 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "e"])
2334 call VerifyBoth(buf, "Test_diff_overlapped_3.31", "")
2335
2336 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a"])
2337 call VerifyBoth(buf, "Test_diff_overlapped_3.32", "")
2338
2339 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "d", "e"])
2340 call VerifyBoth(buf, "Test_diff_overlapped_3.33", "")
2341
2342 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "e"])
2343 call VerifyBoth(buf, "Test_diff_overlapped_3.34", "")
2344
2345 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b"])
2346 call VerifyBoth(buf, "Test_diff_overlapped_3.35", "")
2347
2348 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "b", "c"])
2349 call VerifyBoth(buf, "Test_diff_overlapped_3.36", "")
2350
2351 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y", "c"])
2352 call VerifyBoth(buf, "Test_diff_overlapped_3.37", "")
2353
Yukihiro Nakadaira01f65092025-01-15 18:36:43 +01002354 call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b", "f"])
2355 call VerifyBoth(buf, "Test_diff_overlapped_3.38", "")
2356
2357 call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b"])
2358 call VerifyBoth(buf, "Test_diff_overlapped_3.39", "")
2359
Yee Cheng Chinbc08ceb2025-03-02 22:05:37 +01002360 " File 3 overlaps twice, 2nd overlap completely within the existing block.
2361 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "bar"], ["foo", "w", "x", "y", "z", "bar"], ["foo", "1", "a", "b", "2", "bar"])
2362 call VerifyBoth(buf, "Test_diff_overlapped_3.40", "")
2363
2364 " File 3 overlaps twice, 2nd overlap extends beyond existing block on new
2365 " side. Make sure we don't over-extend the range and hit 'bar'.
2366 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "2", "d", "bar"])
2367 call VerifyBoth(buf, "Test_diff_overlapped_3.41", "")
2368
2369 " Chained overlaps. File 3's 2nd overlap spans two diff blocks and is longer
2370 " than the 2nd one.
2371 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"])
2372 call VerifyBoth(buf, "Test_diff_overlapped_3.42", "")
2373
2374 " File 3 has 2 overlaps. An add and a delete. First overlap's expansion hits
2375 " the 2nd one. Make sure we adjust the diff block to have fewer lines.
2376 call WriteDiffFiles3(buf, ["foo", "a", "b", "bar"], ["foo", "x", "y", "bar"], ["foo", "1", "a", "bar"])
2377 call VerifyBoth(buf, "Test_diff_overlapped_3.43", "")
2378
2379 " File 3 has 2 overlaps. An add and another add. First overlap's expansion hits
2380 " the 2nd one. Make sure we adjust the diff block to have more lines.
2381 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "3", "4", "d", "bar"])
2382 call VerifyBoth(buf, "Test_diff_overlapped_3.44", "")
2383
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +02002384 call StopVimInTerminal(buf)
2385endfunc
2386
zeertzjq7c515282024-11-10 20:26:12 +01002387" switching windows in diff mode caused an unnecessary scroll
Christian Brabandt05a40e02024-10-29 20:29:04 +01002388func Test_diff_topline_noscroll()
2389 CheckScreendump
2390
2391 let content =<< trim END
2392 call setline(1, range(1,60))
2393 vnew
2394 call setline(1, range(1,10) + range(50,60))
2395 windo diffthis
2396 norm! G
2397 exe "norm! 30\<C-y>"
2398 END
2399 call writefile(content, 'Xcontent', 'D')
2400 let buf = RunVimInTerminal('-S Xcontent', {'rows': 20})
2401 call VerifyScreenDump(buf, 'Test_diff_topline_1', {})
2402 call term_sendkeys(buf, ":echo line('w0', 1001)\<cr>")
2403 call term_wait(buf)
2404 call VerifyScreenDump(buf, 'Test_diff_topline_2', {})
2405 call term_sendkeys(buf, "\<C-W>p")
2406 call term_wait(buf)
2407 call VerifyScreenDump(buf, 'Test_diff_topline_3', {})
2408 call term_sendkeys(buf, "\<C-W>p")
2409 call term_wait(buf)
2410 call VerifyScreenDump(buf, 'Test_diff_topline_4', {})
2411 call StopVimInTerminal(buf)
2412endfunc
2413
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002414" Test inline highlighting which shows what's different within each diff block
2415func Test_diff_inline()
2416 CheckScreendump
2417
2418 call WriteDiffFiles(0, [], [])
2419 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2420 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2421
2422 call WriteDiffFiles(buf, ["abcdef ghi jk n", "x", "y"], ["aBcef gHi lm n", "y", "z"])
2423 call VerifyInternal(buf, "Test_diff_inline_01", "")
2424 call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:none")
2425
2426 " inline:simple is the same as default
2427 call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:simple")
2428
2429 call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:char")
2430 call VerifyInternal(buf, "Test_diff_inline_04", " diffopt+=inline:word")
2431
2432 " multiple inline values will the last one
2433 call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:none,inline:char,inline:simple")
2434 call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:simple,inline:word,inline:none")
2435 call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:simple,inline:word,inline:char")
2436
2437 " DiffTextAdd highlight
2438 call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
2439 call VerifyInternal(buf, "Test_diff_inline_05", " diffopt+=inline:char")
2440
2441 " Live update in insert mode
2442 call term_sendkeys(buf, "\<Esc>isometext")
2443 call VerifyScreenDump(buf, "Test_diff_inline_06", {})
2444 call term_sendkeys(buf, "\<Esc>u")
2445
2446 " icase simple scenarios
2447 call VerifyInternal(buf, "Test_diff_inline_07", " diffopt+=inline:simple,icase")
2448 call VerifyInternal(buf, "Test_diff_inline_08", " diffopt+=inline:char,icase")
2449 call VerifyInternal(buf, "Test_diff_inline_09", " diffopt+=inline:word,icase")
2450
2451 " diff algorithms should affect highlight
2452 call WriteDiffFiles(buf, ["apples and oranges"], ["oranges and apples"])
2453 call VerifyInternal(buf, "Test_diff_inline_10", " diffopt+=inline:char")
2454 call VerifyInternal(buf, "Test_diff_inline_11", " diffopt+=inline:char,algorithm:patience")
2455
2456 " icase: composing chars and Unicode fold case edge cases
2457 call WriteDiffFiles(buf,
2458 \ ["1 - sigma in 6σ and Ὀδυσσεύς", "1 - angstrom in åå", "1 - composing: ii⃗I⃗"],
2459 \ ["2 - Sigma in 6Σ and ὈΔΥΣΣΕΎΣ", "2 - Angstrom in ÅÅ", "2 - Composing: i⃗I⃗I⃗"])
2460 call VerifyInternal(buf, "Test_diff_inline_12", " diffopt+=inline:char")
2461 call VerifyInternal(buf, "Test_diff_inline_13", " diffopt+=inline:char,icase")
2462
2463 " wide chars
2464 call WriteDiffFiles(buf, ["abc😅xde一", "f🚀g"], ["abcy😢de", "二f🚀g"])
2465 call VerifyInternal(buf, "Test_diff_inline_14", " diffopt+=inline:char,icase")
2466
2467 " NUL char (\n below is internally substituted as NUL)
2468 call WriteDiffFiles(buf, ["1\n34\n5\n6"], ["1234\n5", "6"])
2469 call VerifyInternal(buf, "Test_diff_inline_15", " diffopt+=inline:char")
2470
2471 " word diff: always use first buffer's iskeyword and ignore others' for consistency
2472 call WriteDiffFiles(buf, ["foo+bar test"], ["foo+baz test"])
2473 call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
2474
2475 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:diffupdate\<CR>")
2476 call VerifyInternal(buf, "Test_diff_inline_word_02", " diffopt+=inline:word")
2477
2478 call term_sendkeys(buf, ":set iskeyword&\<CR>:wincmd w\<CR>")
2479 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:wincmd w\<CR>:diffupdate\<CR>")
2480 " Use the previous screen dump as 2nd buffer's iskeyword does not matter
2481 call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
2482
2483 call term_sendkeys(buf, ":windo set iskeyword&\<CR>:1wincmd w\<CR>")
2484
Yee Cheng Chin9aa120f2025-04-04 19:16:21 +02002485 " word diff: test handling of multi-byte characters. Only alphanumeric chars
2486 " (e.g. Greek alphabet, but not CJK/emoji) count as words.
2487 call WriteDiffFiles(buf, ["🚀⛵️一二三ひらがなΔέλτα Δelta foobar"], ["🚀🛸一二四ひらなδέλτα δelta foobar"])
2488 call VerifyInternal(buf, "Test_diff_inline_word_03", " diffopt+=inline:word")
2489
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002490 " char diff: should slide highlight to whitespace boundary if possible for
2491 " better readability (by using forced indent-heuristics). A wrong result
2492 " would be if the highlight is "Bar, prefix". It should be "prefixBar, "
2493 " instead.
2494 call WriteDiffFiles(buf, ["prefixFoo, prefixEnd"], ["prefixFoo, prefixBar, prefixEnd"])
2495 call VerifyInternal(buf, "Test_diff_inline_char_01", " diffopt+=inline:char")
2496
2497 " char diff: small gaps between inline diff blocks will be merged during refine step
2498 " - first segment: test that we iteratively merge small gaps after we merged
2499 " adjacent blocks, but only with limited number (set to 4) of iterations.
2500 " - second and third segments: show that we need a large enough adjacent block to
2501 " trigger a merge.
2502 " - fourth segment: small gaps are not merged when adjacent large block is
2503 " on a different line.
2504 call WriteDiffFiles(buf,
2505 \ ["abcdefghijklmno", "anchor1",
2506 \ "abcdefghijklmno", "anchor2",
2507 \ "abcdefghijklmno", "anchor3",
2508 \ "test", "multiline"],
zeertzjq5a307c32025-03-28 19:01:32 +01002509 \ ["a?c?e?g?i?k???o", "anchor1",
2510 \ "a??de?????klmno", "anchor2",
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002511 \ "a??de??????lmno", "anchor3",
2512 \ "t?s?", "??????i?e"])
2513 call VerifyInternal(buf, "Test_diff_inline_char_02", " diffopt+=inline:char")
2514
2515 " Test multi-line blocks and whitespace
2516 call WriteDiffFiles(buf,
2517 \ ["this is ", "sometest text foo", "baz abc def ", "one", "word another word", "additional line"],
2518 \ ["this is some test", "texts", "foo bar abX Yef ", "oneword another word"])
2519 call VerifyInternal(buf, "Test_diff_inline_multiline_01", " diffopt+=inline:char,iwhite")
2520 call VerifyInternal(buf, "Test_diff_inline_multiline_02", " diffopt+=inline:word,iwhite")
2521 call VerifyInternal(buf, "Test_diff_inline_multiline_03", " diffopt+=inline:char,iwhiteeol")
2522 call VerifyInternal(buf, "Test_diff_inline_multiline_04", " diffopt+=inline:word,iwhiteeol")
2523 call VerifyInternal(buf, "Test_diff_inline_multiline_05", " diffopt+=inline:char,iwhiteall")
2524 call VerifyInternal(buf, "Test_diff_inline_multiline_06", " diffopt+=inline:word,iwhiteall")
2525
2526 " newline should be highlighted too when 'list' is set
2527 call term_sendkeys(buf, ":windo set list\<CR>")
2528 call VerifyInternal(buf, "Test_diff_inline_multiline_07", " diffopt+=inline:char")
2529 call VerifyInternal(buf, "Test_diff_inline_multiline_08", " diffopt+=inline:char,iwhite")
2530 call VerifyInternal(buf, "Test_diff_inline_multiline_09", " diffopt+=inline:char,iwhiteeol")
2531 call VerifyInternal(buf, "Test_diff_inline_multiline_10", " diffopt+=inline:char,iwhiteall")
2532 call term_sendkeys(buf, ":windo set nolist\<CR>")
2533
2534 call StopVimInTerminal(buf)
2535endfunc
2536
2537func Test_diff_inline_multibuffer()
2538 CheckScreendump
2539
2540 call WriteDiffFiles3(0, [], [], [])
2541 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
2542 call term_sendkeys(buf, ":windo set autoread\<CR>:1wincmd w\<CR>")
2543 call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
2544
2545 call WriteDiffFiles3(buf,
2546 \ ["That is buffer1.", "anchor", "Some random text", "anchor"],
2547 \ ["This is buffer2.", "anchor", "Some text", "anchor", "buffer2/3"],
2548 \ ["This is buffer3. Last.", "anchor", "Some more", "text here.", "anchor", "only in buffer2/3", "not in buffer1"])
2549 call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
2550
zeertzjq5a307c32025-03-28 19:01:32 +01002551 " Close one of the buffers and make sure it updates correctly
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002552 call term_sendkeys(buf, ":diffoff\<CR>")
2553 call VerifyInternal(buf, "Test_diff_inline_multibuffer_02", " diffopt+=inline:char")
2554
2555 " Update text in the non-diff buffer and nothing should be changed
2556 call term_sendkeys(buf, "\<Esc>isometext")
2557 call VerifyScreenDump(buf, "Test_diff_inline_multibuffer_03", {})
2558 call term_sendkeys(buf, "\<Esc>u")
2559
2560 call term_sendkeys(buf, ":diffthis\<CR>")
2561 call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
2562
2563 " Test that removing first buffer from diff will in turn use the next
2564 " earliest buffer's iskeyword during word diff.
2565 call WriteDiffFiles3(buf,
2566 \ ["This+is=a-setence"],
2567 \ ["This+is=another-setence"],
2568 \ ["That+is=a-setence"])
2569 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:2wincmd w\<CR>:set iskeyword+=-\<CR>:1wincmd w\<CR>")
2570 call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
2571 call term_sendkeys(buf, ":diffoff\<CR>")
2572 call VerifyInternal(buf, "Test_diff_inline_multibuffer_05", " diffopt+=inline:word")
2573 call term_sendkeys(buf, ":diffthis\<CR>")
2574 call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
2575
2576 " Test multi-buffer char diff refinement, and that removing a buffer from
2577 " diff will update the others properly.
2578 call WriteDiffFiles3(buf,
2579 \ ["abcdefghijkYmYYY"],
2580 \ ["aXXdXXghijklmnop"],
2581 \ ["abcdefghijkYmYop"])
2582 call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
2583 call term_sendkeys(buf, ":diffoff\<CR>")
2584 call VerifyInternal(buf, "Test_diff_inline_multibuffer_07", " diffopt+=inline:char")
2585 call term_sendkeys(buf, ":diffthis\<CR>")
2586 call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
2587
2588 call StopVimInTerminal(buf)
2589endfunc
2590
Jonathon7c7a4e62025-01-12 09:58:00 +01002591func Test_diffget_diffput_linematch()
2592 CheckScreendump
2593 call delete('.Xdifile1.swp')
2594 call delete('.Xdifile2.swp')
2595 call WriteDiffFiles(0, [], [])
2596 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2597 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2598
2599 " enable linematch
2600 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2601 call WriteDiffFiles(buf, ['',
2602 \ 'common line',
2603 \ 'common line',
2604 \ '',
2605 \ 'ABCabc',
2606 \ 'ABCabc',
2607 \ 'ABCabc',
2608 \ 'ABCabc',
2609 \ 'common line',
2610 \ 'common line',
2611 \ 'common line',
2612 \ 'something' ],
2613 \ ['',
2614 \ 'common line',
2615 \ 'common line',
2616 \ '',
2617 \ 'DEFabc',
2618 \ 'xyz',
2619 \ 'xyz',
2620 \ 'xyz',
2621 \ 'DEFabc',
2622 \ 'DEFabc',
2623 \ 'DEFabc',
2624 \ 'common line',
2625 \ 'common line',
2626 \ 'DEF',
2627 \ 'common line',
2628 \ 'DEF',
2629 \ 'something'])
2630 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_1', {})
2631
2632 " get from window 1 from line 5 to 9
2633 call term_sendkeys(buf, "1\<c-w>w")
2634 call term_sendkeys(buf, ":5,9diffget\<CR>")
2635 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_2', {})
2636
2637 " undo the last diffget
2638 call term_sendkeys(buf, "u")
2639
2640 " get from window 2 from line 5 to 10
2641 call term_sendkeys(buf, "2\<c-w>w")
2642 call term_sendkeys(buf, ":5,10diffget\<CR>")
2643 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_3', {})
2644
2645 " undo the last diffget
2646 call term_sendkeys(buf, "u")
2647
2648 " get all from window 2
2649 call term_sendkeys(buf, "2\<c-w>w")
2650 call term_sendkeys(buf, ":4,17diffget\<CR>")
2651 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_4', {})
2652
2653 " undo the last diffget
2654 call term_sendkeys(buf, "u")
2655
2656 " get all from window 1
2657 call term_sendkeys(buf, "1\<c-w>w")
2658 call term_sendkeys(buf, ":4,12diffget\<CR>")
2659 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_5', {})
2660
2661 " undo the last diffget
2662 call term_sendkeys(buf, "u")
2663
2664 " get from window 1 using do 1 line 5
2665 call term_sendkeys(buf, "1\<c-w>w")
2666 call term_sendkeys(buf, "5gg")
2667 call term_sendkeys(buf, ":diffget\<CR>")
2668 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_6', {})
2669
2670 " undo the last diffget
2671 call term_sendkeys(buf, "u")
2672
2673 " get from window 1 using do 2 line 6
2674 call term_sendkeys(buf, "1\<c-w>w")
2675 call term_sendkeys(buf, "6gg")
2676 call term_sendkeys(buf, ":diffget\<CR>")
2677 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_7', {})
2678
2679 " undo the last diffget
2680 call term_sendkeys(buf, "u")
2681
2682 " get from window 1 using do 2 line 7
2683 call term_sendkeys(buf, "1\<c-w>w")
2684 call term_sendkeys(buf, "7gg")
2685 call term_sendkeys(buf, ":diffget\<CR>")
2686 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_8', {})
2687
2688 " undo the last diffget
2689 call term_sendkeys(buf, "u")
2690
2691 " get from window 1 using do 2 line 11
2692 call term_sendkeys(buf, "1\<c-w>w")
2693 call term_sendkeys(buf, "11gg")
2694 call term_sendkeys(buf, ":diffget\<CR>")
2695 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_9', {})
2696
2697 " undo the last diffget
2698 call term_sendkeys(buf, "u")
2699
2700 " get from window 1 using do 2 line 12
2701 call term_sendkeys(buf, "1\<c-w>w")
2702 call term_sendkeys(buf, "12gg")
2703 call term_sendkeys(buf, ":diffget\<CR>")
2704 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_10', {})
2705
2706 " undo the last diffget
2707 call term_sendkeys(buf, "u")
2708
2709 " put from window 1 using dp 1 line 5
2710 call term_sendkeys(buf, "1\<c-w>w")
2711 call term_sendkeys(buf, "5gg")
2712 call term_sendkeys(buf, ":diffput\<CR>")
2713 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_11', {})
2714
2715 " undo the last diffput
2716 call term_sendkeys(buf, "2\<c-w>w")
2717 call term_sendkeys(buf, "u")
2718
2719 " put from window 1 using dp 2 line 6
2720 call term_sendkeys(buf, "1\<c-w>w")
2721 call term_sendkeys(buf, "6gg")
2722 call term_sendkeys(buf, ":diffput\<CR>")
2723 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_12', {})
2724
2725 " undo the last diffput
2726 call term_sendkeys(buf, "2\<c-w>w")
2727 call term_sendkeys(buf, "u")
2728
2729 " put from window 1 using dp 2 line 7
2730 call term_sendkeys(buf, "1\<c-w>w")
2731 call term_sendkeys(buf, "7gg")
2732 call term_sendkeys(buf, ":diffput\<CR>")
2733 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_13', {})
2734
2735 " undo the last diffput
2736 call term_sendkeys(buf, "2\<c-w>w")
2737 call term_sendkeys(buf, "u")
2738
2739 " put from window 1 using dp 2 line 11
2740 call term_sendkeys(buf, "1\<c-w>w")
2741 call term_sendkeys(buf, "11gg")
2742 call term_sendkeys(buf, ":diffput\<CR>")
2743 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_14', {})
2744
2745 " undo the last diffput
2746 call term_sendkeys(buf, "2\<c-w>w")
2747 call term_sendkeys(buf, "u")
2748
2749 " put from window 1 using dp 2 line 12
2750 call term_sendkeys(buf, "1\<c-w>w")
2751 call term_sendkeys(buf, "12gg")
2752 call term_sendkeys(buf, ":diffput\<CR>")
2753 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_15', {})
2754
2755 " undo the last diffput
2756 call term_sendkeys(buf, "2\<c-w>w")
2757 call term_sendkeys(buf, "u")
2758
2759 " put from window 2 using dp line 6
2760 call term_sendkeys(buf, "2\<c-w>w")
2761 call term_sendkeys(buf, "6gg")
2762 call term_sendkeys(buf, ":diffput\<CR>")
2763 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_16', {})
2764
2765 " undo the last diffput
2766 call term_sendkeys(buf, "1\<c-w>w")
2767 call term_sendkeys(buf, "u")
2768
2769 " put from window 2 using dp line 8
2770 call term_sendkeys(buf, "2\<c-w>w")
2771 call term_sendkeys(buf, "8gg")
2772 call term_sendkeys(buf, ":diffput\<CR>")
2773 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_17', {})
2774
2775 " undo the last diffput
2776 call term_sendkeys(buf, "1\<c-w>w")
2777 call term_sendkeys(buf, "u")
2778
2779 " put from window 2 using dp line 9
2780 call term_sendkeys(buf, "2\<c-w>w")
2781 call term_sendkeys(buf, "9gg")
2782 call term_sendkeys(buf, ":diffput\<CR>")
2783 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_18', {})
2784
2785 " undo the last diffput
2786 call term_sendkeys(buf, "1\<c-w>w")
2787 call term_sendkeys(buf, "u")
2788
2789 " put from window 2 using dp line 17
2790 call term_sendkeys(buf, "2\<c-w>w")
2791 call term_sendkeys(buf, "17gg")
2792 call term_sendkeys(buf, ":diffput\<CR>")
2793 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_19', {})
Jonathonca307ef2025-01-17 13:37:35 +01002794 " clean up
2795 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002796endfunc
2797
2798func Test_linematch_diff()
2799 CheckScreendump
2800 call delete('.Xdifile1.swp')
2801 call delete('.Xdifile2.swp')
2802 call WriteDiffFiles(0, [], [])
2803 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2804 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2805
2806 " enable linematch
2807 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2808 call WriteDiffFiles(buf, ['// abc d?',
2809 \ '// d?',
2810 \ '// d?' ],
2811 \ ['!',
2812 \ 'abc d!',
2813 \ 'd!'])
2814 call VerifyScreenDump(buf, 'Test_linematch_diff1', {})
Jonathonca307ef2025-01-17 13:37:35 +01002815 " clean up
2816 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002817endfunc
2818
2819func Test_linematch_diff_iwhite()
2820 CheckScreendump
2821 call delete('.Xdifile1.swp')
2822 call delete('.Xdifile2.swp')
2823 call WriteDiffFiles(0, [], [])
2824 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2825 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2826
2827 " setup a diff with 2 files and set linematch:30, with ignore white
2828 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2829 call WriteDiffFiles(buf, ['void testFunction () {',
2830 \ ' for (int i = 0; i < 10; i++) {',
2831 \ ' for (int j = 0; j < 10; j++) {',
2832 \ ' }',
2833 \ ' }',
2834 \ '}' ],
2835 \ ['void testFunction () {',
2836 \ ' // for (int j = 0; j < 10; i++) {',
2837 \ ' // }',
2838 \ '}'])
2839 call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite1', {})
2840 call term_sendkeys(buf, ":set diffopt+=iwhiteall\<CR>")
2841 call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002842 " clean up
2843 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002844endfunc
2845
2846func Test_linematch_diff_grouping()
2847 CheckScreendump
2848 call delete('.Xdifile1.swp')
2849 call delete('.Xdifile2.swp')
2850 call WriteDiffFiles(0, [], [])
2851 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2852 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2853
2854 " a diff that would result in multiple groups before grouping optimization
2855 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2856 call WriteDiffFiles(buf, ['!A',
2857 \ '!B',
2858 \ '!C' ],
2859 \ ['?Z',
2860 \ '?A',
2861 \ '?B',
2862 \ '?C',
2863 \ '?A',
2864 \ '?B',
2865 \ '?B',
2866 \ '?C'])
2867 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping1', {})
2868 call WriteDiffFiles(buf, ['!A',
2869 \ '!B',
2870 \ '!C' ],
2871 \ ['?A',
2872 \ '?Z',
2873 \ '?B',
2874 \ '?C',
2875 \ '?A',
2876 \ '?B',
2877 \ '?C',
2878 \ '?C'])
2879 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002880 " clean up
2881 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002882endfunc
2883
2884func Test_linematch_diff_scroll()
2885 CheckScreendump
2886 call delete('.Xdifile1.swp')
2887 call delete('.Xdifile2.swp')
2888 call WriteDiffFiles(0, [], [])
2889 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2890 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2891
2892 " a diff that would result in multiple groups before grouping optimization
2893 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2894 call WriteDiffFiles(buf, ['!A',
2895 \ '!B',
2896 \ '!C' ],
2897 \ ['?A',
2898 \ '?Z',
2899 \ '?B',
2900 \ '?C',
2901 \ '?A',
2902 \ '?B',
2903 \ '?C',
2904 \ '?C'])
2905 " scroll down to show calculation of top fill and scroll to correct line in
2906 " both windows
2907 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll0', {})
2908 call term_sendkeys(buf, "3\<c-e>")
2909 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll1', {})
2910 call term_sendkeys(buf, "3\<c-e>")
2911 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002912 " clean up
2913 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002914endfunc
2915
Jonathon7c7a4e62025-01-12 09:58:00 +01002916func Test_linematch_line_limit_exceeded()
2917 CheckScreendump
2918 call delete('.Xdifile1.swp')
2919 call delete('.Xdifile2.swp')
2920 call WriteDiffFiles(0, [], [])
2921 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2922 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2923
2924 call term_sendkeys(buf, ":set diffopt+=linematch:10\<CR>")
2925 " a diff block will not be aligned with linematch because it's contents
2926 " exceed 10 lines
2927 call WriteDiffFiles(buf,
2928 \ ['common line',
2929 \ 'HIL',
2930 \ '',
2931 \ 'aABCabc',
2932 \ 'aABCabc',
2933 \ 'aABCabc',
2934 \ 'aABCabc',
2935 \ 'common line',
2936 \ 'HIL',
2937 \ 'common line',
2938 \ 'something'],
2939 \ ['common line',
2940 \ 'DEF',
2941 \ 'GHI',
2942 \ 'something',
2943 \ '',
2944 \ 'aDEFabc',
2945 \ 'xyz',
2946 \ 'xyz',
2947 \ 'xyz',
2948 \ 'aDEFabc',
2949 \ 'aDEFabc',
2950 \ 'aDEFabc',
2951 \ 'common line',
2952 \ 'DEF',
2953 \ 'GHI',
2954 \ 'something else',
2955 \ 'common line',
2956 \ 'something'])
2957 call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded1', {})
2958 " after increasing the count to 30, the limit is not exceeded, and the
2959 " alignment algorithm will run on the largest diff block here
2960 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2961 call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002962 " clean up
2963 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002964endfunc
2965
2966func Test_linematch_3diffs()
2967 CheckScreendump
2968 call delete('.Xdifile1.swp')
2969 call delete('.Xdifile2.swp')
2970 call delete('.Xdifile3.swp')
2971 call WriteDiffFiles3(0, [], [], [])
2972 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
2973 call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
2974 call term_sendkeys(buf, "2\<c-w>w:set autoread\<CR>")
2975 call term_sendkeys(buf, "3\<c-w>w:set autoread\<CR>")
2976 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2977 call WriteDiffFiles3(buf,
2978 \ ["",
2979 \ " common line",
2980 \ " AAA",
2981 \ " AAA",
2982 \ " AAA"],
2983 \ ["",
2984 \ " common line",
2985 \ " <<<<<<< HEAD",
2986 \ " AAA",
2987 \ " AAA",
2988 \ " AAA",
2989 \ " =======",
2990 \ " BBB",
2991 \ " BBB",
2992 \ " BBB",
2993 \ " >>>>>>> branch1"],
2994 \ ["",
2995 \ " common line",
2996 \ " BBB",
2997 \ " BBB",
2998 \ " BBB"])
2999 call VerifyScreenDump(buf, 'Test_linematch_3diffs1', {})
Jonathonca307ef2025-01-17 13:37:35 +01003000 " clean up
3001 call StopVimInTerminal(buf)
3002endfunc
Jonathon7c7a4e62025-01-12 09:58:00 +01003003
Jonathonca307ef2025-01-17 13:37:35 +01003004" this used to access invalid memory
3005func Test_linematch_3diffs_sanity_check()
3006 CheckScreendump
3007 call delete('.Xfile_linematch1.swp')
3008 call delete('.Xfile_linematch2.swp')
3009 call delete('.Xfile_linematch3.swp')
3010 let lines =<< trim END
3011 set diffopt+=linematch:60
3012 call feedkeys("Aq\<esc>")
3013 call feedkeys("GAklm\<esc>")
3014 call feedkeys("o")
3015 END
3016 call writefile(lines, 'Xlinematch_3diffs.vim', 'D')
3017 call writefile(['abcd', 'def', 'hij'], 'Xfile_linematch1', 'D')
3018 call writefile(['defq', 'hijk', 'nopq'], 'Xfile_linematch2', 'D')
3019 call writefile(['hijklm', 'nopqr', 'stuv'], 'Xfile_linematch3', 'D')
3020 call WriteDiffFiles3(0, [], [], [])
3021 let buf = RunVimInTerminal('-d -S Xlinematch_3diffs.vim Xfile_linematch1 Xfile_linematch2 Xfile_linematch3', {})
3022 call VerifyScreenDump(buf, 'Test_linematch_3diffs2', {})
3023
3024 " clean up
3025 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01003026endfunc
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01003027" vim: shiftwidth=2 sts=2 expandtab