blob: 6af3fb0d83e0002fb912a8918fb47aa2844cc941 [file] [log] [blame]
Bram Moolenaar42093c02016-07-30 16:16:54 +02001" Tests for diff mode
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02002
Christian Brabandteb380b92025-07-07 20:53:55 +02003source util/screendump.vim
Bram Moolenaar42093c02016-07-30 16:16:54 +02004
5func Test_diff_fold_sync()
6 enew!
Bram Moolenaare8fa05b2018-09-16 15:48:06 +02007 let g:update_count = 0
8 au DiffUpdated * let g:update_count += 1
9
Bram Moolenaar42093c02016-07-30 16:16:54 +020010 let l = range(50)
11 call setline(1, l)
12 diffthis
13 let winone = win_getid()
14 new
15 let l[25] = 'diff'
16 call setline(1, l)
17 diffthis
18 let wintwo = win_getid()
19 " line 15 is inside the closed fold
20 call assert_equal(19, foldclosedend(10))
21 call win_gotoid(winone)
22 call assert_equal(19, foldclosedend(10))
23 " open the fold
24 normal zv
25 call assert_equal(-1, foldclosedend(10))
26 " fold in other window must have opened too
27 call win_gotoid(wintwo)
28 call assert_equal(-1, foldclosedend(10))
29
30 " cursor position is in sync
31 normal 23G
32 call win_gotoid(winone)
33 call assert_equal(23, getcurpos()[1])
34
Bram Moolenaarf65cc662022-06-26 18:17:50 +010035 " depending on how redraw is done DiffUpdated may be triggered once or twice
36 call assert_inrange(1, 2, g:update_count)
Bram Moolenaare8fa05b2018-09-16 15:48:06 +020037 au! DiffUpdated
38
Bram Moolenaar42093c02016-07-30 16:16:54 +020039 windo diffoff
40 close!
41 set nomodified
42endfunc
43
44func Test_vert_split()
Bram Moolenaare828b762018-09-10 17:51:58 +020045 set diffopt=filler
46 call Common_vert_split()
47 set diffopt&
48endfunc
49
Gary Johnson3fa0d352025-06-08 16:00:06 +020050" Test for diff folding redraw after last diff is resolved
51func Test_diff_fold_redraw()
Gary Johnson69565e32025-06-09 20:19:35 +020052 " Set up two files with a minimal case.
Gary Johnson3fa0d352025-06-08 16:00:06 +020053 call writefile(['Paragraph 1', '', 'Paragraph 2', '', 'Paragraph 3'], 'Xfile1')
54 call writefile(['Paragraph 1', '', 'Paragraph 3'], 'Xfile2')
55
Gary Johnson69565e32025-06-09 20:19:35 +020056 " Open in diff mode.
57 edit Xfile1
58 vert diffsplit Xfile2
Gary Johnson3fa0d352025-06-08 16:00:06 +020059
Gary Johnson69565e32025-06-09 20:19:35 +020060 " Go to the diff and apply :diffput to copy Paragraph 2 to Xfile2.
61 wincmd l
62 3
63 diffput
Gary Johnson3fa0d352025-06-08 16:00:06 +020064
Gary Johnson69565e32025-06-09 20:19:35 +020065 " Check that the folds in both windows are closed and extend from the first
66 " line of the buffer to the last line of the buffer.
67 call assert_equal(1, foldclosed(line("$")))
68 wincmd h
69 call assert_equal(1, foldclosed(line("$")))
Gary Johnson3fa0d352025-06-08 16:00:06 +020070
Gary Johnson69565e32025-06-09 20:19:35 +020071 " Clean up.
Gary Johnson3fa0d352025-06-08 16:00:06 +020072 bwipe!
73 bwipe!
74 call delete('Xfile1')
75 call delete('Xfile2')
76endfunc
77
Bram Moolenaare828b762018-09-10 17:51:58 +020078func Test_vert_split_internal()
79 set diffopt=internal,filler
80 call Common_vert_split()
81 set diffopt&
82endfunc
83
84func Common_vert_split()
Bram Moolenaar42093c02016-07-30 16:16:54 +020085 " Disable the title to avoid xterm keeping the wrong one.
86 set notitle noicon
87 new
88 let l = ['1 aa', '2 bb', '3 cc', '4 dd', '5 ee']
89 call setline(1, l)
90 w! Xtest
91 normal dd
92 $
93 put
94 normal kkrXoxxx
95 w! Xtest2
96 file Nop
97 normal ggoyyyjjjozzzz
98 set foldmethod=marker foldcolumn=4
99 call assert_equal(0, &diff)
100 call assert_equal('marker', &foldmethod)
101 call assert_equal(4, &foldcolumn)
102 call assert_equal(0, &scrollbind)
103 call assert_equal(0, &cursorbind)
104 call assert_equal(1, &wrap)
105
106 vert diffsplit Xtest
107 vert diffsplit Xtest2
108 call assert_equal(1, &diff)
109 call assert_equal('diff', &foldmethod)
110 call assert_equal(2, &foldcolumn)
111 call assert_equal(1, &scrollbind)
112 call assert_equal(1, &cursorbind)
113 call assert_equal(0, &wrap)
114
115 let diff_fdm = &fdm
116 let diff_fdc = &fdc
117 " repeat entering diff mode here to see if this saves the wrong settings
118 diffthis
119 " jump to second window for a moment to have filler line appear at start of
120 " first window
121 wincmd w
122 normal gg
123 wincmd p
124 normal gg
125 call assert_equal(2, winline())
126 normal j
127 call assert_equal(4, winline())
128 normal j
129 call assert_equal(5, winline())
130 normal j
131 call assert_equal(6, winline())
132 normal j
133 call assert_equal(8, winline())
134 normal j
135 call assert_equal(9, winline())
136
137 wincmd w
138 normal gg
139 call assert_equal(1, winline())
140 normal j
141 call assert_equal(2, winline())
142 normal j
143 call assert_equal(4, winline())
144 normal j
145 call assert_equal(5, winline())
146 normal j
147 call assert_equal(8, winline())
148
149 wincmd w
150 normal gg
151 call assert_equal(2, winline())
152 normal j
153 call assert_equal(3, winline())
154 normal j
155 call assert_equal(4, winline())
156 normal j
157 call assert_equal(5, winline())
158 normal j
159 call assert_equal(6, winline())
160 normal j
161 call assert_equal(7, winline())
162 normal j
163 call assert_equal(8, winline())
164
165 " Test diffoff
166 diffoff!
zeertzjq5fd6ab82022-08-17 12:09:45 +0100167 1wincmd w
Bram Moolenaar42093c02016-07-30 16:16:54 +0200168 let &diff = 1
169 let &fdm = diff_fdm
170 let &fdc = diff_fdc
171 4wincmd w
172 diffoff!
173 1wincmd w
174 call assert_equal(0, &diff)
175 call assert_equal('marker', &foldmethod)
176 call assert_equal(4, &foldcolumn)
177 call assert_equal(0, &scrollbind)
178 call assert_equal(0, &cursorbind)
179 call assert_equal(1, &wrap)
180
181 wincmd w
182 call assert_equal(0, &diff)
183 call assert_equal('marker', &foldmethod)
184 call assert_equal(4, &foldcolumn)
185 call assert_equal(0, &scrollbind)
186 call assert_equal(0, &cursorbind)
187 call assert_equal(1, &wrap)
188
189 wincmd w
190 call assert_equal(0, &diff)
191 call assert_equal('marker', &foldmethod)
192 call assert_equal(4, &foldcolumn)
193 call assert_equal(0, &scrollbind)
194 call assert_equal(0, &cursorbind)
195 call assert_equal(1, &wrap)
196
Bram Moolenaar623cf882016-07-30 16:36:01 +0200197 call delete('Xtest')
198 call delete('Xtest2')
Bram Moolenaar42093c02016-07-30 16:16:54 +0200199 windo bw!
200endfunc
201
202func Test_filler_lines()
203 " Test that diffing shows correct filler lines
204 enew!
205 put =range(4,10)
206 1d _
207 vnew
208 put =range(1,10)
209 1d _
210 windo diffthis
211 wincmd h
212 call assert_equal(1, line('w0'))
213 unlet! diff_fdm diff_fdc
Bram Moolenaar90d121f2016-07-30 19:11:25 +0200214 windo diffoff
215 bwipe!
216 enew!
217endfunc
Bram Moolenaar42093c02016-07-30 16:16:54 +0200218
Bram Moolenaar90d121f2016-07-30 19:11:25 +0200219func Test_diffget_diffput()
220 enew!
221 let l = range(50)
222 call setline(1, l)
223 call assert_fails('diffget', 'E99:')
224 diffthis
225 call assert_fails('diffget', 'E100:')
226 new
227 let l[10] = 'one'
228 let l[20] = 'two'
229 let l[30] = 'three'
230 let l[40] = 'four'
231 call setline(1, l)
232 diffthis
233 call assert_equal('one', getline(11))
234 11diffget
235 call assert_equal('10', getline(11))
236 21diffput
237 wincmd w
238 call assert_equal('two', getline(21))
239 normal 31Gdo
240 call assert_equal('three', getline(31))
241 call assert_equal('40', getline(41))
242 normal 41Gdp
243 wincmd w
244 call assert_equal('40', getline(41))
245 new
246 diffthis
247 call assert_fails('diffget', 'E101:')
248
249 windo diffoff
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200250 %bwipe!
251endfunc
252
Bram Moolenaar5f57bdc2018-10-25 17:52:23 +0200253" Test putting two changes from one buffer to another
254func Test_diffput_two()
255 new a
256 let win_a = win_getid()
257 call setline(1, range(1, 10))
258 diffthis
259 new b
260 let win_b = win_getid()
261 call setline(1, range(1, 10))
262 8del
263 5del
264 diffthis
265 call win_gotoid(win_a)
266 %diffput
267 call win_gotoid(win_b)
268 call assert_equal(map(range(1, 10), 'string(v:val)'), getline(1, '$'))
269 bwipe! a
270 bwipe! b
271endfunc
272
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200273" Test for :diffget/:diffput with a range that is inside a diff chunk
274func Test_diffget_diffput_range()
275 call setline(1, range(1, 10))
276 new
277 call setline(1, range(11, 20))
278 windo diffthis
279 3,5diffget
280 call assert_equal(['13', '14', '15'], getline(3, 5))
281 call setline(1, range(1, 10))
282 4,8diffput
283 wincmd p
284 call assert_equal(['13', '4', '5', '6', '7', '8', '19'], getline(3, 9))
285 %bw!
286endfunc
287
Yee Cheng Chind75ab0c2025-06-20 18:44:18 +0200288" Test :diffget/:diffput handling of added/deleted lines
289func Test_diffget_diffput_deleted_lines()
290 call setline(1, ['2','4','6'])
291 diffthis
292 new
293 call setline(1, range(1,7))
294 diffthis
295 wincmd w
296
297 3,3diffget " get nothing
298 call assert_equal(['2', '4', '6'], getline(1, '$'))
299 3,4diffget " get the last insertion past the end of file
300 call assert_equal(['2', '4', '6', '7'], getline(1, '$'))
301 0,1diffget " get the first insertion above first line
302 call assert_equal(['1', '2', '4', '6', '7'], getline(1, '$'))
303
304 " When using non-range diffget on the last line, it should get the
305 " change above or at the line as usual, but if the only change is below the
306 " last line, diffget should get that instead.
307 1,$delete
308 call setline(1, ['2','4','6'])
309 diffupdate
310 norm Gdo
311 call assert_equal(['2', '4', '5', '6'], getline(1, '$'))
312 norm Gdo
313 call assert_equal(['2', '4', '5', '6', '7'], getline(1, '$'))
314
315 " Test non-range diffput on last line with the same logic
316 1,$delete
317 call setline(1, ['2','4','6'])
318 diffupdate
319 norm Gdp
320 wincmd w
321 call assert_equal(['1', '2', '3', '4', '6', '7'], getline(1, '$'))
322 wincmd w
323 norm Gdp
324 wincmd w
325 call assert_equal(['1', '2', '3', '4', '6'], getline(1, '$'))
326 call setline(1, range(1,7))
327 diffupdate
328 wincmd w
329
330 " Test that 0,$+1 will get/put all changes from/to the other buffer
331 1,$delete
332 call setline(1, ['2','4','6'])
333 diffupdate
334 0,$+1diffget
335 call assert_equal(['1', '2', '3', '4', '5', '6', '7'], getline(1, '$'))
336 1,$delete
337 call setline(1, ['2','4','6'])
338 diffupdate
339 0,$+1diffput
340 wincmd w
341 call assert_equal(['2', '4', '6'], getline(1, '$'))
342 %bw!
343endfunc
344
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200345" Test for :diffget/:diffput with an empty buffer and a non-empty buffer
346func Test_diffget_diffput_empty_buffer()
347 %d _
348 new
349 call setline(1, 'one')
350 windo diffthis
351 diffget
352 call assert_equal(['one'], getline(1, '$'))
353 %d _
354 diffput
355 wincmd p
356 call assert_equal([''], getline(1, '$'))
357 %bw!
358endfunc
359
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100360" :diffput and :diffget completes names of buffers which
Dominique Pelle923dce22021-11-21 11:36:04 +0000361" are in diff mode and which are different than current buffer.
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100362" No completion when the current window is not in diff mode.
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100363func Test_diffget_diffput_completion()
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100364 e Xdiff1 | diffthis
365 botright new Xdiff2
366 botright new Xdiff3 | split | diffthis
367 botright new Xdiff4 | diffthis
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100368
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100369 wincmd t
370 call assert_equal('Xdiff1', bufname('%'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100371 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100372 call assert_equal('"diffput Xdiff3 Xdiff4', @:)
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100373 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100374 call assert_equal('"diffget Xdiff3 Xdiff4', @:)
375 call assert_equal(['Xdiff3', 'Xdiff4'], getcompletion('', 'diff_buffer'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100376
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100377 " Xdiff2 is not in diff mode, so no completion for :diffput, :diffget
378 wincmd j
379 call assert_equal('Xdiff2', bufname('%'))
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100380 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
381 call assert_equal('"diffput ', @:)
382 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
383 call assert_equal('"diffget ', @:)
384 call assert_equal([], getcompletion('', 'diff_buffer'))
385
Bram Moolenaarefcc3292019-12-30 21:59:03 +0100386 " Xdiff3 is split in 2 windows, only the top one is in diff mode.
387 " So completion of :diffput :diffget only happens in the top window.
388 wincmd j
389 call assert_equal('Xdiff3', bufname('%'))
390 call assert_equal(1, &diff)
391 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
392 call assert_equal('"diffput Xdiff1 Xdiff4', @:)
393 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
394 call assert_equal('"diffget Xdiff1 Xdiff4', @:)
395 call assert_equal(['Xdiff1', 'Xdiff4'], getcompletion('', 'diff_buffer'))
396
397 wincmd j
398 call assert_equal('Xdiff3', bufname('%'))
399 call assert_equal(0, &diff)
400 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
401 call assert_equal('"diffput ', @:)
402 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
403 call assert_equal('"diffget ', @:)
404 call assert_equal([], getcompletion('', 'diff_buffer'))
405
406 wincmd j
407 call assert_equal('Xdiff4', bufname('%'))
408 call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
409 call assert_equal('"diffput Xdiff1 Xdiff3', @:)
410 call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
411 call assert_equal('"diffget Xdiff1 Xdiff3', @:)
412 call assert_equal(['Xdiff1', 'Xdiff3'], getcompletion('', 'diff_buffer'))
413
Bram Moolenaarae7dba82019-12-29 13:56:33 +0100414 %bwipe
415endfunc
416
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200417func Test_dp_do_buffer()
418 e! one
419 let bn1=bufnr('%')
420 let l = range(60)
421 call setline(1, l)
422 diffthis
423
424 new two
425 let l[10] = 'one'
426 let l[20] = 'two'
427 let l[30] = 'three'
428 let l[40] = 'four'
429 let l[50] = 'five'
430 call setline(1, l)
431 diffthis
432
433 " dp and do with invalid buffer number.
434 11
435 call assert_fails('norm 99999dp', 'E102:')
436 call assert_fails('norm 99999do', 'E102:')
437 call assert_fails('diffput non_existing_buffer', 'E94:')
438 call assert_fails('diffget non_existing_buffer', 'E94:')
439
440 " dp and do with valid buffer number.
441 call assert_equal('one', getline('.'))
442 exe 'norm ' . bn1 . 'do'
443 call assert_equal('10', getline('.'))
444 21
445 call assert_equal('two', getline('.'))
Bram Moolenaar94722c52023-01-28 19:19:03 +0000446 diffget one
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200447 call assert_equal('20', getline('.'))
448
449 31
450 exe 'norm ' . bn1 . 'dp'
451 41
452 diffput one
453 wincmd w
454 31
455 call assert_equal('three', getline('.'))
456 41
457 call assert_equal('four', getline('.'))
458
459 " dp and do with buffer number which is not in diff mode.
460 new not_in_diff_mode
461 let bn3=bufnr('%')
462 wincmd w
463 51
464 call assert_fails('exe "norm" . bn3 . "dp"', 'E103:')
465 call assert_fails('exe "norm" . bn3 . "do"', 'E103:')
466 call assert_fails('diffput not_in_diff_mode', 'E94:')
467 call assert_fails('diffget not_in_diff_mode', 'E94:')
468
469 windo diffoff
470 %bwipe!
Bram Moolenaar42093c02016-07-30 16:16:54 +0200471endfunc
Bram Moolenaare67d5462016-08-27 22:40:42 +0200472
Bram Moolenaardf77cef2018-10-07 17:46:42 +0200473func Test_do_lastline()
474 e! one
475 call setline(1, ['1','2','3','4','5','6'])
476 diffthis
477
478 new two
479 call setline(1, ['2','4','5'])
480 diffthis
481
482 1
483 norm dp]c
484 norm dp]c
485 wincmd w
486 call assert_equal(4, line('$'))
487 norm G
488 norm do
489 call assert_equal(3, line('$'))
490
491 windo diffoff
492 %bwipe!
493endfunc
494
Bram Moolenaare67d5462016-08-27 22:40:42 +0200495func Test_diffoff()
496 enew!
497 call setline(1, ['Two', 'Three'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200498 redraw
Bram Moolenaare67d5462016-08-27 22:40:42 +0200499 let normattr = screenattr(1, 1)
500 diffthis
501 botright vert new
502 call setline(1, ['One', '', 'Two', 'Three'])
503 diffthis
504 redraw
Bram Moolenaar196b4662019-09-06 21:34:30 +0200505 call assert_notequal(normattr, 1->screenattr(1))
Bram Moolenaare67d5462016-08-27 22:40:42 +0200506 diffoff!
507 redraw
508 call assert_equal(normattr, screenattr(1, 1))
509 bwipe!
510 bwipe!
511endfunc
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200512
Bram Moolenaare828b762018-09-10 17:51:58 +0200513func Common_icase_test()
514 edit one
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100515 call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#vϵ', 'Si⃗x', 'Se⃗ve⃗n'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200516 redraw
517 let normattr = screenattr(1, 1)
518 diffthis
519
520 botright vert new two
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100521 call setline(1, ['one', 'TWO', 'Three ', 'Four', 'fI=VΕ', 'SI⃗x', 'SEvE⃗n'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200522 diffthis
523
524 redraw
525 call assert_equal(normattr, screenattr(1, 1))
526 call assert_equal(normattr, screenattr(2, 1))
527 call assert_notequal(normattr, screenattr(3, 1))
528 call assert_equal(normattr, screenattr(4, 1))
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100529 call assert_equal(normattr, screenattr(6, 2))
530 call assert_notequal(normattr, screenattr(7, 2))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200531
Bram Moolenaarda22b8c2017-09-02 18:01:50 +0200532 let dtextattr = screenattr(5, 3)
533 call assert_notequal(dtextattr, screenattr(5, 1))
534 call assert_notequal(dtextattr, screenattr(5, 5))
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100535 call assert_notequal(dtextattr, screenattr(7, 4))
Bram Moolenaarda22b8c2017-09-02 18:01:50 +0200536
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200537 diffoff!
538 %bwipe!
Bram Moolenaare828b762018-09-10 17:51:58 +0200539endfunc
540
541func Test_diffopt_icase()
542 set diffopt=icase,foldcolumn:0
543 call Common_icase_test()
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200544 set diffopt&
545endfunc
546
Bram Moolenaare828b762018-09-10 17:51:58 +0200547func Test_diffopt_icase_internal()
548 set diffopt=icase,foldcolumn:0,internal
549 call Common_icase_test()
550 set diffopt&
551endfunc
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200552
Bram Moolenaare828b762018-09-10 17:51:58 +0200553func Common_iwhite_test()
554 edit one
555 " Difference in trailing spaces and amount of spaces should be ignored,
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200556 " but not other space differences.
Bram Moolenaare828b762018-09-10 17:51:58 +0200557 call setline(1, ["One \t", 'Two', 'Three', 'one two', 'one two', 'Four'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200558 redraw
559 let normattr = screenattr(1, 1)
560 diffthis
561
562 botright vert new two
Bram Moolenaare828b762018-09-10 17:51:58 +0200563 call setline(1, ["One\t ", "Two\t ", 'Three', 'one two', 'onetwo', ' Four'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200564 diffthis
565
566 redraw
567 call assert_equal(normattr, screenattr(1, 1))
568 call assert_equal(normattr, screenattr(2, 1))
569 call assert_equal(normattr, screenattr(3, 1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200570 call assert_equal(normattr, screenattr(4, 1))
571 call assert_notequal(normattr, screenattr(5, 1))
572 call assert_notequal(normattr, screenattr(6, 1))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200573
574 diffoff!
575 %bwipe!
Bram Moolenaare828b762018-09-10 17:51:58 +0200576endfunc
577
578func Test_diffopt_iwhite()
579 set diffopt=iwhite,foldcolumn:0
580 call Common_iwhite_test()
581 set diffopt&
582endfunc
583
584func Test_diffopt_iwhite_internal()
585 set diffopt=internal,iwhite,foldcolumn:0
586 call Common_iwhite_test()
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200587 set diffopt&
588endfunc
589
590func Test_diffopt_context()
591 enew!
592 call setline(1, ['1', '2', '3', '4', '5', '6', '7'])
593 diffthis
594 new
595 call setline(1, ['1', '2', '3', '4', '5x', '6', '7'])
596 diffthis
597
598 set diffopt=context:2
599 call assert_equal('+-- 2 lines: 1', foldtextresult(1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200600 set diffopt=internal,context:2
601 call assert_equal('+-- 2 lines: 1', foldtextresult(1))
602
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200603 set diffopt=context:1
604 call assert_equal('+-- 3 lines: 1', foldtextresult(1))
Bram Moolenaare828b762018-09-10 17:51:58 +0200605 set diffopt=internal,context:1
606 call assert_equal('+-- 3 lines: 1', foldtextresult(1))
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200607
608 diffoff!
609 %bwipe!
610 set diffopt&
611endfunc
612
613func Test_diffopt_horizontal()
Bram Moolenaare828b762018-09-10 17:51:58 +0200614 set diffopt=internal,horizontal
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200615 diffsplit
616
617 call assert_equal(&columns, winwidth(1))
618 call assert_equal(&columns, winwidth(2))
619 call assert_equal(&lines, winheight(1) + winheight(2) + 3)
620 call assert_inrange(0, 1, winheight(1) - winheight(2))
621
622 set diffopt&
623 diffoff!
624 %bwipe
625endfunc
626
627func Test_diffopt_vertical()
Bram Moolenaare828b762018-09-10 17:51:58 +0200628 set diffopt=internal,vertical
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200629 diffsplit
630
631 call assert_equal(&lines - 2, winheight(1))
632 call assert_equal(&lines - 2, winheight(2))
633 call assert_equal(&columns, winwidth(1) + winwidth(2) + 1)
634 call assert_inrange(0, 1, winwidth(1) - winwidth(2))
635
636 set diffopt&
637 diffoff!
638 %bwipe
639endfunc
640
Bram Moolenaar97ce4192017-12-01 20:35:58 +0100641func Test_diffopt_hiddenoff()
Bram Moolenaare828b762018-09-10 17:51:58 +0200642 set diffopt=internal,filler,foldcolumn:0,hiddenoff
Bram Moolenaar97ce4192017-12-01 20:35:58 +0100643 e! one
644 call setline(1, ['Two', 'Three'])
645 redraw
646 let normattr = screenattr(1, 1)
647 diffthis
648 botright vert new two
649 call setline(1, ['One', 'Four'])
650 diffthis
651 redraw
652 call assert_notequal(normattr, screenattr(1, 1))
653 set hidden
654 close
655 redraw
656 " should not diffing with hidden buffer two while 'hiddenoff' is enabled
657 call assert_equal(normattr, screenattr(1, 1))
658
659 bwipe!
660 bwipe!
661 set hidden& diffopt&
662endfunc
663
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100664func Test_diffoff_hidden()
Bram Moolenaare828b762018-09-10 17:51:58 +0200665 set diffopt=internal,filler,foldcolumn:0
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100666 e! one
667 call setline(1, ['Two', 'Three'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200668 redraw
Bram Moolenaar25ea0542017-02-03 23:16:28 +0100669 let normattr = screenattr(1, 1)
670 diffthis
671 botright vert new two
672 call setline(1, ['One', 'Four'])
673 diffthis
674 redraw
675 call assert_notequal(normattr, screenattr(1, 1))
676 set hidden
677 close
678 redraw
679 " diffing with hidden buffer two
680 call assert_notequal(normattr, screenattr(1, 1))
681 diffoff
682 redraw
683 call assert_equal(normattr, screenattr(1, 1))
684 diffthis
685 redraw
686 " still diffing with hidden buffer two
687 call assert_notequal(normattr, screenattr(1, 1))
688 diffoff!
689 redraw
690 call assert_equal(normattr, screenattr(1, 1))
691 diffthis
692 redraw
693 " no longer diffing with hidden buffer two
694 call assert_equal(normattr, screenattr(1, 1))
695
696 bwipe!
697 bwipe!
698 set hidden& diffopt&
699endfunc
700
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200701func Test_setting_cursor()
702 new Xtest1
703 put =range(1,90)
704 wq
705 new Xtest2
706 put =range(1,100)
707 wq
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200708
Bram Moolenaar025e3e02016-10-18 14:50:18 +0200709 tabe Xtest2
710 $
711 diffsp Xtest1
712 tabclose
713
714 call delete('Xtest1')
715 call delete('Xtest2')
716endfunc
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100717
718func Test_diff_move_to()
719 new
720 call setline(1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
721 diffthis
722 vnew
723 call setline(1, [1, '2x', 3, 4, 4, 5, '6x', 7, '8x', 9, '10x'])
724 diffthis
725 norm ]c
726 call assert_equal(2, line('.'))
727 norm 3]c
728 call assert_equal(9, line('.'))
729 norm 10]c
730 call assert_equal(11, line('.'))
731 norm [c
732 call assert_equal(9, line('.'))
733 norm 2[c
734 call assert_equal(5, line('.'))
735 norm 10[c
736 call assert_equal(2, line('.'))
737 %bwipe!
738endfunc
739
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200740func Test_diffexpr()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +0100741 CheckExecutable diff
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200742
743 func DiffExpr()
Bram Moolenaar485b6272021-05-18 19:19:03 +0200744 " Prepend some text to check diff type detection
Bram Moolenaar3b8defd2018-09-13 13:03:11 +0200745 call writefile(['warning', ' message'], v:fname_out)
746 silent exe '!diff ' . v:fname_in . ' ' . v:fname_new . '>>' . v:fname_out
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200747 endfunc
748 set diffexpr=DiffExpr()
749 set diffopt=foldcolumn:0
750
751 enew!
752 call setline(1, ['one', 'two', 'three'])
753 redraw
754 let normattr = screenattr(1, 1)
755 diffthis
756
757 botright vert new
758 call setline(1, ['one', 'two', 'three.'])
759 diffthis
760
761 redraw
762 call assert_equal(normattr, screenattr(1, 1))
763 call assert_equal(normattr, screenattr(2, 1))
764 call assert_notequal(normattr, screenattr(3, 1))
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200765 diffoff!
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200766
Dominique Pelle923dce22021-11-21 11:36:04 +0000767 " Try using a non-existing function for 'diffexpr'.
Yegappan Lakshmanan30443242021-06-10 21:52:15 +0200768 set diffexpr=NewDiffFunc()
769 call assert_fails('windo diffthis', ['E117:', 'E97:'])
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200770 diffoff!
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +0000771
772 " Using a script-local function
773 func s:NewDiffExpr()
774 endfunc
775 set diffexpr=s:NewDiffExpr()
776 call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
777 set diffexpr=<SID>NewDiffExpr()
778 call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
779
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200780 %bwipe!
781 set diffexpr& diffopt&
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +0000782 delfunc DiffExpr
783 delfunc s:NewDiffExpr
Bram Moolenaar79a213d2017-05-16 13:15:18 +0200784endfunc
785
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100786func Test_diffpatch()
787 " The patch program on MS-Windows may fail or hang.
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200788 CheckExecutable patch
789 CheckUnix
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100790 new
791 insert
792***************
793*** 1,3 ****
794 1
795! 2
796 3
797--- 1,4 ----
798 1
799! 2x
800 3
801+ 4
802.
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200803 saveas! Xpatch
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100804 bwipe!
805 new
806 call assert_fails('diffpatch Xpatch', 'E816:')
Bram Moolenaar1ef73e32017-03-09 19:21:30 +0100807
Bram Moolenaara95ab322017-03-11 19:21:53 +0100808 for name in ['Xpatch', 'Xpatch$HOME', 'Xpa''tch']
Bram Moolenaar1ef73e32017-03-09 19:21:30 +0100809 call setline(1, ['1', '2', '3'])
810 if name != 'Xpatch'
811 call rename('Xpatch', name)
812 endif
813 exe 'diffpatch ' . escape(name, '$')
814 call assert_equal(['1', '2x', '3', '4'], getline(1, '$'))
815 if name != 'Xpatch'
816 call rename(name, 'Xpatch')
817 endif
818 bwipe!
819 endfor
820
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100821 call delete('Xpatch')
822 bwipe!
823endfunc
824
Bram Moolenaar23a971d2023-04-04 22:04:53 +0100825" FIXME: test fails, the Xresult file can't be read
826func No_Test_diffpatch_restricted()
827 let lines =<< trim END
828 call assert_fails('diffpatch NoSuchDiff', 'E145:')
829
830 call writefile(v:errors, 'Xresult')
831 qa!
832 END
833 call writefile(lines, 'Xrestricted', 'D')
834 if RunVim([], [], '-Z --clean -S Xrestricted')
835 call assert_equal([], readfile('Xresult'))
836 endif
837 call delete('Xresult')
838endfunc
839
Bram Moolenaaraeb661e2017-02-26 19:59:59 +0100840func Test_diff_too_many_buffers()
841 for i in range(1, 8)
842 exe "new Xtest" . i
843 diffthis
844 endfor
845 new Xtest9
846 call assert_fails('diffthis', 'E96:')
847 %bwipe!
848endfunc
849
850func Test_diff_nomodifiable()
851 new
852 call setline(1, [1, 2, 3, 4])
853 setl nomodifiable
854 diffthis
855 vnew
856 call setline(1, ['1x', 2, 3, 3, 4])
857 diffthis
858 call assert_fails('norm dp', 'E793:')
859 setl nomodifiable
860 call assert_fails('norm do', 'E21:')
861 %bwipe!
862endfunc
Bram Moolenaarf58a8472017-03-05 18:03:04 +0100863
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200864func Test_diff_hlID()
865 new
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100866 call setline(1, [1, 2, 3, 'Yz', 'a dxxg',])
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200867 diffthis
868 vnew
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100869 call setline(1, ['1x', 2, 'x', 3, 'yx', 'abc defg'])
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200870 diffthis
871 redraw
872
Bram Moolenaara74e4942019-08-04 17:35:53 +0200873 call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("")
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200874
Bram Moolenaara74e4942019-08-04 17:35:53 +0200875 call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange")
876 call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText")
877 call diff_hlID(2, 1)->synIDattr("name")->assert_equal("")
878 call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd")
Bram Moolenaar1a3a8912019-08-23 22:31:37 +0200879 eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("")
Yee Cheng Chin9943d472025-03-26 19:41:02 +0100880 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
881 call diff_hlID(5, 2)->synIDattr("name")->assert_equal("DiffText")
882
883 set diffopt+=icase " test that caching is invalidated by diffopt change
884 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffChange")
885 set diffopt-=icase
886 call diff_hlID(5, 1)->synIDattr("name")->assert_equal("DiffText")
887
888 call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
889 call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffText")
890 call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffText")
891 call diff_hlID(6, 7)->synIDattr("name")->assert_equal("DiffText")
892 call diff_hlID(6, 8)->synIDattr("name")->assert_equal("DiffChange")
893 set diffopt+=inline:char
894 call diff_hlID(6, 1)->synIDattr("name")->assert_equal("DiffChange")
895 call diff_hlID(6, 2)->synIDattr("name")->assert_equal("DiffTextAdd")
896 call diff_hlID(6, 4)->synIDattr("name")->assert_equal("DiffChange")
897 call diff_hlID(6, 7)->synIDattr("name")->assert_equal("DiffText")
898 call diff_hlID(6, 8)->synIDattr("name")->assert_equal("DiffChange")
899 set diffopt-=inline:char
Bram Moolenaar97fbc402017-09-26 19:41:46 +0200900
901 wincmd w
902 call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange")
903 call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "")
904 call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "")
905
906 %bwipe!
907endfunc
908
909func Test_diff_filler()
910 new
911 call setline(1, [1, 2, 3, 'x', 4])
912 diffthis
913 vnew
914 call setline(1, [1, 2, 'y', 'y', 3, 4])
915 diffthis
916 redraw
917
Bram Moolenaar1a3a8912019-08-23 22:31:37 +0200918 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 +0200919 wincmd w
920 call assert_equal([0, 0, 0, 0, 2, 0, 0, 0], map(range(-1, 6), 'diff_filler(v:val)'))
921
922 %bwipe!
923endfunc
924
Bram Moolenaarf58a8472017-03-05 18:03:04 +0100925func Test_diff_lastline()
926 enew!
927 only!
928 call setline(1, ['This is a ', 'line with five ', 'rows'])
929 diffthis
930 botright vert new
931 call setline(1, ['This is', 'a line with ', 'four rows'])
932 diffthis
933 1
934 call feedkeys("Je a\<CR>", 'tx')
935 call feedkeys("Je a\<CR>", 'tx')
936 let w1lines = winline()
937 wincmd w
938 $
939 let w2lines = winline()
940 call assert_equal(w2lines, w1lines)
941 bwipe!
942 bwipe!
943endfunc
Bram Moolenaare828b762018-09-10 17:51:58 +0200944
Bram Moolenaar785fc652018-09-15 19:17:38 +0200945func WriteDiffFiles(buf, list1, list2)
Bram Moolenaar61abe7d2022-08-30 21:46:08 +0100946 call writefile(a:list1, 'Xdifile1')
947 call writefile(a:list2, 'Xdifile2')
Bram Moolenaar785fc652018-09-15 19:17:38 +0200948 if a:buf
949 call term_sendkeys(a:buf, ":checktime\<CR>")
950 endif
Bram Moolenaare828b762018-09-10 17:51:58 +0200951endfunc
952
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +0200953func WriteDiffFiles3(buf, list1, list2, list3)
954 call writefile(a:list1, 'Xdifile1')
955 call writefile(a:list2, 'Xdifile2')
956 call writefile(a:list3, 'Xdifile3')
957 if a:buf
958 call term_sendkeys(a:buf, ":checktime\<CR>")
959 endif
960endfunc
961
Bram Moolenaar785fc652018-09-15 19:17:38 +0200962" Verify a screendump with both the internal and external diff.
Bram Moolenaare828b762018-09-10 17:51:58 +0200963func VerifyBoth(buf, dumpfile, extra)
Drew Vogelea67ba72025-05-07 22:05:17 +0200964 CheckScreendump
965
Bram Moolenaare828b762018-09-10 17:51:58 +0200966 " trailing : for leaving the cursor on the command line
Bram Moolenaar785fc652018-09-15 19:17:38 +0200967 for cmd in [":set diffopt=filler" . a:extra . "\<CR>:", ":set diffopt+=internal\<CR>:"]
Bram Moolenaare828b762018-09-10 17:51:58 +0200968 call term_sendkeys(a:buf, cmd)
969 if VerifyScreenDump(a:buf, a:dumpfile, {}, cmd =~ 'internal' ? 'internal' : 'external')
Bram Moolenaar485b6272021-05-18 19:19:03 +0200970 " don't let the next iteration overwrite the "failed" file.
971 return
Bram Moolenaare828b762018-09-10 17:51:58 +0200972 endif
973 endfor
Bram Moolenaar485b6272021-05-18 19:19:03 +0200974
975 " also test unified diff
976 call term_sendkeys(a:buf, ":call SetupUnified()\<CR>:")
glacambread5c1782021-05-24 14:20:53 +0200977 call term_sendkeys(a:buf, ":redraw!\<CR>:")
Bram Moolenaar485b6272021-05-18 19:19:03 +0200978 call VerifyScreenDump(a:buf, a:dumpfile, {}, 'unified')
979 call term_sendkeys(a:buf, ":call StopUnified()\<CR>:")
Bram Moolenaare828b762018-09-10 17:51:58 +0200980endfunc
981
Bram Moolenaar785fc652018-09-15 19:17:38 +0200982" Verify a screendump with the internal diff only.
983func VerifyInternal(buf, dumpfile, extra)
Drew Vogelea67ba72025-05-07 22:05:17 +0200984 CheckScreendump
985
Bram Moolenaar785fc652018-09-15 19:17:38 +0200986 call term_sendkeys(a:buf, ":diffupdate!\<CR>")
987 " trailing : for leaving the cursor on the command line
988 call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:")
989 call VerifyScreenDump(a:buf, a:dumpfile, {})
990endfunc
991
Bram Moolenaare828b762018-09-10 17:51:58 +0200992func Test_diff_screen()
Yee Cheng Chin49f2ba62024-02-14 20:34:58 +0100993 if has('osxdarwin') && system('diff --version') =~ '^Apple diff'
994 throw 'Skipped: unified diff does not work properly on this macOS version'
rhysde93d5ca2024-02-01 21:22:14 +0100995 endif
996
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100997 let g:test_is_flaky = 1
Bram Moolenaar3c8ee622019-08-03 22:55:50 +0200998 CheckScreendump
999 CheckFeature menu
1000
Bram Moolenaar485b6272021-05-18 19:19:03 +02001001 let lines =<< trim END
1002 func UnifiedDiffExpr()
1003 " Prepend some text to check diff type detection
1004 call writefile(['warning', ' message'], v:fname_out)
glacambread5c1782021-05-24 14:20:53 +02001005 silent exe '!diff -U0 ' .. v:fname_in .. ' ' .. v:fname_new .. '>>' .. v:fname_out
Bram Moolenaar485b6272021-05-18 19:19:03 +02001006 endfunc
1007 func SetupUnified()
1008 set diffexpr=UnifiedDiffExpr()
glacambread5c1782021-05-24 14:20:53 +02001009 diffupdate
Bram Moolenaar485b6272021-05-18 19:19:03 +02001010 endfunc
1011 func StopUnified()
1012 set diffexpr=
1013 endfunc
1014 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001015 call writefile(lines, 'XdiffSetup', 'D')
Bram Moolenaar485b6272021-05-18 19:19:03 +02001016
Bram Moolenaare828b762018-09-10 17:51:58 +02001017 " clean up already existing swap files, just in case
Bram Moolenaar61abe7d2022-08-30 21:46:08 +01001018 call delete('.Xdifile1.swp')
1019 call delete('.Xdifile2.swp')
Bram Moolenaare828b762018-09-10 17:51:58 +02001020
1021 " Test 1: Add a line in beginning of file 2
Bram Moolenaar785fc652018-09-15 19:17:38 +02001022 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 +01001023 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
Bram Moolenaar8ee4c012019-03-29 18:08:18 +01001024 " Set autoread mode, so that Vim won't complain once we re-write the test
Bram Moolenaare828b762018-09-10 17:51:58 +02001025 " files
Bram Moolenaar785fc652018-09-15 19:17:38 +02001026 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
Bram Moolenaare828b762018-09-10 17:51:58 +02001027
1028 call VerifyBoth(buf, 'Test_diff_01', '')
1029
1030 " Test 2: Add a line in beginning of file 1
Bram Moolenaar785fc652018-09-15 19:17:38 +02001031 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 +02001032 call VerifyBoth(buf, 'Test_diff_02', '')
1033
1034 " Test 3: Add a line at the end of file 2
Bram Moolenaar785fc652018-09-15 19:17:38 +02001035 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 +02001036 call VerifyBoth(buf, 'Test_diff_03', '')
1037
1038 " Test 4: Add a line at the end of file 1
Bram Moolenaar785fc652018-09-15 19:17:38 +02001039 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 +02001040 call VerifyBoth(buf, 'Test_diff_04', '')
1041
1042 " 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 +02001043 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 +02001044 call VerifyBoth(buf, 'Test_diff_05', '')
1045
1046 " 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 +02001047 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 +02001048 call VerifyBoth(buf, 'Test_diff_06', '')
1049
Bram Moolenaarb9ddda62019-02-19 23:00:50 +01001050 " Variants on test 6 with different context settings
1051 call term_sendkeys(buf, ":set diffopt+=context:2\<cr>")
1052 call VerifyScreenDump(buf, 'Test_diff_06.2', {})
1053 call term_sendkeys(buf, ":set diffopt-=context:2\<cr>")
1054 call term_sendkeys(buf, ":set diffopt+=context:1\<cr>")
1055 call VerifyScreenDump(buf, 'Test_diff_06.1', {})
1056 call term_sendkeys(buf, ":set diffopt-=context:1\<cr>")
1057 call term_sendkeys(buf, ":set diffopt+=context:0\<cr>")
1058 call VerifyScreenDump(buf, 'Test_diff_06.0', {})
1059 call term_sendkeys(buf, ":set diffopt-=context:0\<cr>")
1060
Bram Moolenaare828b762018-09-10 17:51:58 +02001061 " Test 7 - 9: Test normal/patience/histogram diff algorithm
Bram Moolenaar785fc652018-09-15 19:17:38 +02001062 call WriteDiffFiles(buf, ['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
Bram Moolenaare828b762018-09-10 17:51:58 +02001063 \ ' int i;', ' for(i = 0; i < 10; i++)', ' {', ' printf("Your answer is: ");',
1064 \ ' printf("%d\n", foo);', ' }', '}', '', 'int fact(int n)', '{', ' if(n > 1)', ' {',
1065 \ ' return fact(n-1) * n;', ' }', ' return 1;', '}', '', 'int main(int argc, char **argv)',
1066 \ '{', ' frobnitz(fact(10));', '}'],
1067 \ ['#include <stdio.h>', '', 'int fib(int n)', '{', ' if(n > 2)', ' {',
1068 \ ' return fib(n-1) + fib(n-2);', ' }', ' return 1;', '}', '', '// Frobs foo heartily',
1069 \ 'int frobnitz(int foo)', '{', ' int i;', ' for(i = 0; i < 10; i++)', ' {',
1070 \ ' printf("%d\n", foo);', ' }', '}', '',
1071 \ 'int main(int argc, char **argv)', '{', ' frobnitz(fib(10));', '}'])
1072 call term_sendkeys(buf, ":diffupdate!\<cr>")
1073 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1074 call VerifyScreenDump(buf, 'Test_diff_07', {})
1075
1076 call term_sendkeys(buf, ":set diffopt+=algorithm:patience\<cr>")
1077 call VerifyScreenDump(buf, 'Test_diff_08', {})
1078
1079 call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>")
1080 call VerifyScreenDump(buf, 'Test_diff_09', {})
1081
1082 " Test 10-11: normal/indent-heuristic
1083 call term_sendkeys(buf, ":set diffopt&vim\<cr>")
Bram Moolenaar785fc652018-09-15 19:17:38 +02001084 call WriteDiffFiles(buf, ['', ' def finalize(values)', '', ' values.each do |v|', ' v.finalize', ' end'],
Bram Moolenaare828b762018-09-10 17:51:58 +02001085 \ ['', ' def finalize(values)', '', ' values.each do |v|', ' v.prepare', ' end', '',
1086 \ ' values.each do |v|', ' v.finalize', ' end'])
1087 call term_sendkeys(buf, ":diffupdate!\<cr>")
1088 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1089 call VerifyScreenDump(buf, 'Test_diff_10', {})
1090
Bram Moolenaarb6fc7282018-12-04 22:24:16 +01001091 " Leave trailing : at commandline!
1092 call term_sendkeys(buf, ":set diffopt+=indent-heuristic\<cr>:\<cr>")
1093 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'one')
1094 " shouldn't matter, if indent-algorithm comes before or after the algorithm
1095 call term_sendkeys(buf, ":set diffopt&\<cr>")
1096 call term_sendkeys(buf, ":set diffopt+=indent-heuristic,algorithm:patience\<cr>:\<cr>")
1097 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'two')
1098 call term_sendkeys(buf, ":set diffopt&\<cr>")
1099 call term_sendkeys(buf, ":set diffopt+=algorithm:patience,indent-heuristic\<cr>:\<cr>")
1100 call VerifyScreenDump(buf, 'Test_diff_11', {}, 'three')
Bram Moolenaare828b762018-09-10 17:51:58 +02001101
1102 " Test 12: diff the same file
Bram Moolenaar785fc652018-09-15 19:17:38 +02001103 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 +02001104 call VerifyBoth(buf, 'Test_diff_12', '')
1105
1106 " Test 13: diff an empty file
Bram Moolenaar785fc652018-09-15 19:17:38 +02001107 call WriteDiffFiles(buf, [], [])
Bram Moolenaare828b762018-09-10 17:51:58 +02001108 call VerifyBoth(buf, 'Test_diff_13', '')
1109
1110 " Test 14: test diffopt+=icase
Bram Moolenaar785fc652018-09-15 19:17:38 +02001111 call WriteDiffFiles(buf, ['a', 'b', 'cd'], ['A', 'b', 'cDe'])
Bram Moolenaare828b762018-09-10 17:51:58 +02001112 call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase")
1113
1114 " Test 15-16: test diffopt+=iwhite
Bram Moolenaar785fc652018-09-15 19:17:38 +02001115 call WriteDiffFiles(buf, ['int main()', '{', ' printf("Hello, World!");', ' return 0;', '}'],
Bram Moolenaare828b762018-09-10 17:51:58 +02001116 \ ['int main()', '{', ' if (0)', ' {', ' printf("Hello, World!");', ' return 0;', ' }', '}'])
1117 call term_sendkeys(buf, ":diffupdate!\<cr>")
1118 call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>")
1119 call VerifyScreenDump(buf, 'Test_diff_15', {})
1120 call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
1121 call VerifyScreenDump(buf, 'Test_diff_16', {})
1122
Bram Moolenaar785fc652018-09-15 19:17:38 +02001123 " Test 17: test diffopt+=iblank
1124 call WriteDiffFiles(buf, ['a', ' ', 'cd', 'ef', 'xxx'], ['a', 'cd', '', 'ef', 'yyy'])
1125 call VerifyInternal(buf, 'Test_diff_17', " diffopt+=iblank")
1126
1127 " Test 18: test diffopt+=iblank,iwhite / iwhiteall / iwhiteeol
1128 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhite")
1129 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteall")
1130 call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteeol")
1131
1132 " Test 19: test diffopt+=iwhiteeol
1133 call WriteDiffFiles(buf, ['a ', 'x', 'cd', 'ef', 'xx xx', 'foo', 'bar'], ['a', 'x', 'c d', ' ef', 'xx xx', 'foo', '', 'bar'])
1134 call VerifyInternal(buf, 'Test_diff_19', " diffopt+=iwhiteeol")
1135
Yukihiro Nakadairaf1694b42024-09-22 11:26:13 +02001136 " Test 20: test diffopt+=iwhiteall
Bram Moolenaar785fc652018-09-15 19:17:38 +02001137 call VerifyInternal(buf, 'Test_diff_20', " diffopt+=iwhiteall")
1138
Yukihiro Nakadairaf1694b42024-09-22 11:26:13 +02001139 " Test 21: Delete all lines
1140 call WriteDiffFiles(buf, [0], [])
1141 call VerifyBoth(buf, "Test_diff_21", "")
1142
1143 " Test 22: Add line to empty file
1144 call WriteDiffFiles(buf, [], [0])
1145 call VerifyBoth(buf, "Test_diff_22", "")
1146
Jonathon7c7a4e62025-01-12 09:58:00 +01001147 call WriteDiffFiles(buf, ['?a', '?b', '?c'], ['!b'])
1148 call VerifyInternal(buf, 'Test_diff_23', " diffopt+=linematch:30")
1149
1150 call WriteDiffFiles(buf, ['',
1151 \ 'common line',
1152 \ 'common line',
1153 \ '',
1154 \ 'DEFabc',
1155 \ 'xyz',
1156 \ 'xyz',
1157 \ 'xyz',
1158 \ 'DEFabc',
1159 \ 'DEFabc',
1160 \ 'DEFabc',
1161 \ 'common line',
1162 \ 'common line',
1163 \ 'DEF',
1164 \ 'common line',
1165 \ 'DEF',
1166 \ 'something' ],
1167 \ ['',
1168 \ 'common line',
1169 \ 'common line',
1170 \ '',
1171 \ 'ABCabc',
1172 \ 'ABCabc',
1173 \ 'ABCabc',
1174 \ 'ABCabc',
1175 \ 'common line',
1176 \ 'common line',
1177 \ 'common line',
1178 \ 'something'])
1179 call VerifyInternal(buf, 'Test_diff_24', " diffopt+=linematch:30")
1180
1181
Bram Moolenaare828b762018-09-10 17:51:58 +02001182 " clean up
1183 call StopVimInTerminal(buf)
Bram Moolenaar61abe7d2022-08-30 21:46:08 +01001184 call delete('Xdifile1')
1185 call delete('Xdifile2')
Bram Moolenaare828b762018-09-10 17:51:58 +02001186endfunc
1187
Bram Moolenaar04626c22021-09-01 16:02:07 +02001188func Test_diff_with_scroll_and_change()
1189 CheckScreendump
1190
1191 let lines =<< trim END
1192 call setline(1, range(1, 15))
1193 vnew
1194 call setline(1, range(9, 15))
1195 windo diffthis
1196 wincmd h
1197 exe "normal Gl5\<C-E>"
1198 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001199 call writefile(lines, 'Xtest_scroll_change', 'D')
Bram Moolenaar04626c22021-09-01 16:02:07 +02001200 let buf = RunVimInTerminal('-S Xtest_scroll_change', {})
1201
1202 call VerifyScreenDump(buf, 'Test_diff_scroll_change_01', {})
1203
1204 call term_sendkeys(buf, "ax\<Esc>")
1205 call VerifyScreenDump(buf, 'Test_diff_scroll_change_02', {})
1206
Bram Moolenaar841c2252021-10-22 20:56:55 +01001207 call term_sendkeys(buf, "\<C-W>lay\<Esc>")
1208 call VerifyScreenDump(buf, 'Test_diff_scroll_change_03', {})
1209
Bram Moolenaar04626c22021-09-01 16:02:07 +02001210 " clean up
1211 call StopVimInTerminal(buf)
Bram Moolenaar04626c22021-09-01 16:02:07 +02001212endfunc
1213
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001214func Test_diff_with_cursorline()
Bram Moolenaar3c8ee622019-08-03 22:55:50 +02001215 CheckScreendump
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001216
1217 call writefile([
1218 \ 'hi CursorLine ctermbg=red ctermfg=white',
1219 \ 'set cursorline',
1220 \ 'call setline(1, ["foo","foo","foo","bar"])',
1221 \ 'vnew',
1222 \ 'call setline(1, ["bee","foo","foo","baz"])',
1223 \ 'windo diffthis',
1224 \ '2wincmd w',
Bram Moolenaar59173412022-09-20 22:01:33 +01001225 \ ], 'Xtest_diff_cursorline', 'D')
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001226 let buf = RunVimInTerminal('-S Xtest_diff_cursorline', {})
1227
1228 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_01', {})
1229 call term_sendkeys(buf, "j")
1230 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_02', {})
1231 call term_sendkeys(buf, "j")
1232 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_03', {})
1233
1234 " clean up
1235 call StopVimInTerminal(buf)
Bram Moolenaar4a5abbd2018-10-02 18:26:10 +02001236endfunc
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001237
Bram Moolenaar127969c2022-03-06 19:54:13 +00001238func Test_diff_with_cursorline_number()
1239 CheckScreendump
1240
1241 let lines =<< trim END
1242 hi CursorLine ctermbg=red ctermfg=white
1243 hi CursorLineNr ctermbg=white ctermfg=black cterm=underline
1244 set cursorline number
1245 call setline(1, ["baz", "foo", "foo", "bar"])
1246 2
1247 vnew
1248 call setline(1, ["foo", "foo", "bar"])
1249 windo diffthis
1250 1wincmd w
1251 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001252 call writefile(lines, 'Xtest_diff_cursorline_number', 'D')
Bram Moolenaar127969c2022-03-06 19:54:13 +00001253 let buf = RunVimInTerminal('-S Xtest_diff_cursorline_number', {})
1254
1255 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_01', {})
1256 call term_sendkeys(buf, ":set cursorlineopt=number\r")
1257 call VerifyScreenDump(buf, 'Test_diff_with_cursorline_number_02', {})
1258
1259 " clean up
1260 call StopVimInTerminal(buf)
Bram Moolenaar127969c2022-03-06 19:54:13 +00001261endfunc
1262
zeertzjq4f33bc22021-08-05 17:57:02 +02001263func Test_diff_with_cursorline_breakindent()
1264 CheckScreendump
1265
zeertzjq588f20d2023-12-05 15:47:09 +01001266 let lines =<< trim END
1267 hi CursorLine ctermbg=red ctermfg=white
1268 set noequalalways wrap diffopt=followwrap cursorline breakindent
1269 50vnew
1270 call setline(1, [' ', ' ', ' ', ' '])
1271 exe "norm! 20Afoo\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abar\<Esc>"
1272 vnew
1273 call setline(1, [' ', ' ', ' ', ' '])
1274 exe "norm! 20Abee\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abaz\<Esc>"
1275 windo diffthis
1276 2wincmd w
1277 END
1278 call writefile(lines, 'Xtest_diff_cursorline_breakindent', 'D')
zeertzjq4f33bc22021-08-05 17:57:02 +02001279 let buf = RunVimInTerminal('-S Xtest_diff_cursorline_breakindent', {})
1280
1281 call term_sendkeys(buf, "gg0")
1282 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_01', {})
1283 call term_sendkeys(buf, "j")
1284 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_02', {})
1285 call term_sendkeys(buf, "j")
1286 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_03', {})
1287 call term_sendkeys(buf, "j")
1288 call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_04', {})
1289
1290 " clean up
1291 call StopVimInTerminal(buf)
zeertzjq4f33bc22021-08-05 17:57:02 +02001292endfunc
1293
zeertzjq588f20d2023-12-05 15:47:09 +01001294func Test_diff_breakindent_after_filler()
1295 CheckScreendump
1296
1297 let lines =<< trim END
zeertzjqf0a9d652024-02-12 22:53:20 +01001298 set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0
zeertzjq588f20d2023-12-05 15:47:09 +01001299 call setline(1, ['a', ' ' .. repeat('c', 50)])
1300 vnew
1301 call setline(1, ['a', 'b', ' ' .. repeat('c', 50)])
1302 windo diffthis
1303 norm! G$
1304 END
1305 call writefile(lines, 'Xtest_diff_breakindent_after_filler', 'D')
1306 let buf = RunVimInTerminal('-S Xtest_diff_breakindent_after_filler', #{rows: 8, cols: 45})
1307 call VerifyScreenDump(buf, 'Test_diff_breakindent_after_filler', {})
1308
1309 " clean up
1310 call StopVimInTerminal(buf)
1311endfunc
1312
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001313func Test_diff_with_syntax()
1314 CheckScreendump
1315
1316 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001317 void doNothing() {
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001318 int x = 0;
1319 char *s = "hello";
1320 return 5;
1321 }
1322 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001323 call writefile(lines, 'Xprogram1.c', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001324 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001325 void doSomething() {
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001326 int x = 0;
1327 char *s = "there";
1328 return 5;
1329 }
1330 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001331 call writefile(lines, 'Xprogram2.c', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001332
1333 let lines =<< trim END
Bram Moolenaar94722c52023-01-28 19:19:03 +00001334 edit Xprogram1.c
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001335 diffsplit Xprogram2.c
1336 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001337 call writefile(lines, 'Xtest_diff_syntax', 'D')
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001338 let buf = RunVimInTerminal('-S Xtest_diff_syntax', {})
1339
1340 call VerifyScreenDump(buf, 'Test_diff_syntax_1', {})
1341
1342 " clean up
1343 call StopVimInTerminal(buf)
Bram Moolenaar248fdb32019-09-15 19:31:28 +02001344endfunc
1345
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001346func Test_diff_of_diff()
Bram Moolenaar3c8ee622019-08-03 22:55:50 +02001347 CheckScreendump
1348 CheckFeature rightleft
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001349
1350 call writefile([
1351 \ 'call setline(1, ["aa","bb","cc","@@ -3,2 +5,7 @@","dd","ee","ff"])',
1352 \ 'vnew',
1353 \ 'call setline(1, ["aa","bb","cc"])',
1354 \ 'windo diffthis',
Bram Moolenaar8ee4c012019-03-29 18:08:18 +01001355 \ '1wincmd w',
1356 \ 'setlocal number',
Bram Moolenaar59173412022-09-20 22:01:33 +01001357 \ ], 'Xtest_diff_diff', 'D')
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001358 let buf = RunVimInTerminal('-S Xtest_diff_diff', {})
1359
1360 call VerifyScreenDump(buf, 'Test_diff_of_diff_01', {})
1361
Bram Moolenaare73f9112019-03-29 18:29:54 +01001362 call term_sendkeys(buf, ":set rightleft\<cr>")
1363 call VerifyScreenDump(buf, 'Test_diff_of_diff_02', {})
1364
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001365 " clean up
1366 call StopVimInTerminal(buf)
Bram Moolenaarf7acf2b2018-11-01 21:14:53 +01001367endfunc
Bram Moolenaarc8234772019-11-10 21:00:27 +01001368
1369func CloseoffSetup()
1370 enew
1371 call setline(1, ['one', 'two', 'three'])
1372 diffthis
1373 new
1374 call setline(1, ['one', 'tow', 'three'])
1375 diffthis
1376 call assert_equal(1, &diff)
Jonathonca307ef2025-01-17 13:37:35 +01001377 bw!
Bram Moolenaarc8234772019-11-10 21:00:27 +01001378endfunc
1379
1380func Test_diff_closeoff()
1381 " "closeoff" included by default: last diff win gets 'diff' reset'
1382 call CloseoffSetup()
1383 call assert_equal(0, &diff)
1384 enew!
1385
1386 " "closeoff" excluded: last diff win keeps 'diff' set'
1387 set diffopt-=closeoff
1388 call CloseoffSetup()
1389 call assert_equal(1, &diff)
1390 diffoff!
1391 enew!
1392endfunc
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001393
Bram Moolenaar4223d432021-02-10 13:18:17 +01001394func Test_diff_followwrap()
1395 new
1396 set diffopt+=followwrap
1397 set wrap
1398 diffthis
1399 call assert_equal(1, &wrap)
1400 diffoff
1401 set nowrap
1402 diffthis
1403 call assert_equal(0, &wrap)
1404 diffoff
1405 set diffopt&
1406 bwipe!
1407endfunc
1408
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001409func Test_diff_maintains_change_mark()
Sean Dewarccc16442021-12-29 16:44:48 +00001410 func DiffMaintainsChangeMark()
1411 enew!
1412 call setline(1, ['a', 'b', 'c', 'd'])
1413 diffthis
1414 new
1415 call setline(1, ['a', 'b', 'c', 'e'])
1416 " Set '[ and '] marks
1417 2,3yank
1418 call assert_equal([2, 3], [line("'["), line("']")])
1419 " Verify they aren't affected by the implicit diff
1420 diffthis
1421 call assert_equal([2, 3], [line("'["), line("']")])
1422 " Verify they aren't affected by an explicit diff
1423 diffupdate
1424 call assert_equal([2, 3], [line("'["), line("']")])
1425 bwipe!
1426 bwipe!
1427 endfunc
1428
1429 set diffopt-=internal
1430 call DiffMaintainsChangeMark()
1431 set diffopt+=internal
1432 call DiffMaintainsChangeMark()
Bram Moolenaard9b74a22022-01-16 15:00:08 +00001433
Sean Dewarccc16442021-12-29 16:44:48 +00001434 set diffopt&
Bram Moolenaard9b74a22022-01-16 15:00:08 +00001435 delfunc DiffMaintainsChangeMark
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001436endfunc
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001437
1438" Test for 'patchexpr'
1439func Test_patchexpr()
1440 let g:patch_args = []
1441 func TPatch()
1442 call add(g:patch_args, readfile(v:fname_in))
1443 call add(g:patch_args, readfile(v:fname_diff))
1444 call writefile(['output file'], v:fname_out)
1445 endfunc
1446 set patchexpr=TPatch()
1447
Bram Moolenaar59173412022-09-20 22:01:33 +01001448 call writefile(['input file'], 'Xinput', 'D')
1449 call writefile(['diff file'], 'Xdiff', 'D')
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001450 %bwipe!
1451 edit Xinput
1452 diffpatch Xdiff
1453 call assert_equal('output file', getline(1))
1454 call assert_equal('Xinput.new', bufname())
1455 call assert_equal(2, winnr('$'))
1456 call assert_true(&diff)
1457
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001458 " Using a script-local function
1459 func s:NewPatchExpr()
1460 endfunc
1461 set patchexpr=s:NewPatchExpr()
1462 call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
1463 set patchexpr=<SID>NewPatchExpr()
1464 call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
1465
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001466 set patchexpr&
1467 delfunc TPatch
Yegappan Lakshmanan8bb65f22021-12-26 10:51:39 +00001468 delfunc s:NewPatchExpr
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01001469 %bwipe!
1470endfunc
1471
Bram Moolenaar511feec2020-06-18 19:15:27 +02001472func Test_diff_rnu()
1473 CheckScreendump
1474
1475 let content =<< trim END
1476 call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
1477 vnew
1478 call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
1479 windo diffthis
1480 setlocal number rnu foldcolumn=0
1481 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001482 call writefile(content, 'Xtest_diff_rnu', 'D')
Bram Moolenaar511feec2020-06-18 19:15:27 +02001483 let buf = RunVimInTerminal('-S Xtest_diff_rnu', {})
1484
1485 call VerifyScreenDump(buf, 'Test_diff_rnu_01', {})
1486
1487 call term_sendkeys(buf, "j")
1488 call VerifyScreenDump(buf, 'Test_diff_rnu_02', {})
1489 call term_sendkeys(buf, "j")
1490 call VerifyScreenDump(buf, 'Test_diff_rnu_03', {})
1491
1492 " clean up
1493 call StopVimInTerminal(buf)
Bram Moolenaar511feec2020-06-18 19:15:27 +02001494endfunc
1495
Bram Moolenaarfc838d62020-06-25 22:23:48 +02001496func Test_diff_multilineconceal()
1497 new
1498 diffthis
1499
1500 new
1501 call matchadd('Conceal', 'a\nb', 9, -1, {'conceal': 'Y'})
1502 set cole=2 cocu=n
1503 call setline(1, ["a", "b"])
1504 diffthis
1505 redraw
1506endfunc
1507
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001508func Test_diff_and_scroll()
1509 " this was causing an ml_get error
1510 set ls=2
Bram Moolenaar94722c52023-01-28 19:19:03 +00001511 for i in range(winheight(0) * 2)
1512 call setline(i, i < winheight(0) - 10 ? i : i + 10)
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001513 endfor
1514 vnew
Bram Moolenaar94722c52023-01-28 19:19:03 +00001515 for i in range(winheight(0)*2 + 10)
1516 call setline(i, i < winheight(0) - 10 ? 0 : i)
Bram Moolenaar8455c5e2020-07-14 21:22:30 +02001517 endfor
1518 diffthis
1519 wincmd p
1520 diffthis
1521 execute 'normal ' . winheight(0) . "\<C-d>"
1522
1523 bwipe!
1524 bwipe!
1525 set ls&
1526endfunc
1527
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001528func Test_diff_filler_cursorcolumn()
1529 CheckScreendump
1530
1531 let content =<< trim END
1532 call setline(1, ['aa', 'bb', 'cc'])
1533 vnew
1534 call setline(1, ['aa', 'cc'])
1535 windo diffthis
1536 wincmd p
1537 setlocal cursorcolumn foldcolumn=0
1538 norm! gg0
1539 redraw!
1540 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001541 call writefile(content, 'Xtest_diff_cuc', 'D')
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001542 let buf = RunVimInTerminal('-S Xtest_diff_cuc', {})
1543
1544 call VerifyScreenDump(buf, 'Test_diff_cuc_01', {})
1545
1546 call term_sendkeys(buf, "l")
1547 call term_sendkeys(buf, "\<C-l>")
1548 call VerifyScreenDump(buf, 'Test_diff_cuc_02', {})
1549 call term_sendkeys(buf, "0j")
1550 call term_sendkeys(buf, "\<C-l>")
1551 call VerifyScreenDump(buf, 'Test_diff_cuc_03', {})
1552 call term_sendkeys(buf, "l")
1553 call term_sendkeys(buf, "\<C-l>")
1554 call VerifyScreenDump(buf, 'Test_diff_cuc_04', {})
1555
1556 " clean up
1557 call StopVimInTerminal(buf)
Bram Moolenaarfabc3ca2020-11-05 19:07:21 +01001558endfunc
1559
Yegappan Lakshmanan30443242021-06-10 21:52:15 +02001560" Test for adding/removing lines inside diff chunks, between diff chunks
1561" and before diff chunks
1562func Test_diff_modify_chunks()
1563 enew!
1564 let w2_id = win_getid()
1565 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1566 new
1567 let w1_id = win_getid()
1568 call setline(1, ['a', '2', '3', 'd', 'e', 'f', '7', '8', 'i'])
1569 windo diffthis
1570
1571 " remove a line between two diff chunks and create a new diff chunk
1572 call win_gotoid(w2_id)
1573 5d
1574 call win_gotoid(w1_id)
1575 call diff_hlID(5, 1)->synIDattr('name')->assert_equal('DiffAdd')
1576
1577 " add a line between two diff chunks
1578 call win_gotoid(w2_id)
1579 normal! 4Goe
1580 call win_gotoid(w1_id)
1581 call diff_hlID(4, 1)->synIDattr('name')->assert_equal('')
1582 call diff_hlID(5, 1)->synIDattr('name')->assert_equal('')
1583
1584 " remove all the lines in a diff chunk.
1585 call win_gotoid(w2_id)
1586 7,8d
1587 call win_gotoid(w1_id)
1588 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1589 call assert_equal(['', 'DiffText', 'DiffText', '', '', '', 'DiffAdd',
1590 \ 'DiffAdd', ''], hl)
1591
1592 " remove lines from one diff chunk to just before the next diff chunk
1593 call win_gotoid(w2_id)
1594 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1595 2,6d
1596 call win_gotoid(w1_id)
1597 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1598 call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', 'DiffAdd',
1599 \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
1600
1601 " remove lines just before the top of a diff chunk
1602 call win_gotoid(w2_id)
1603 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1604 5,6d
1605 call win_gotoid(w1_id)
1606 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1607 call assert_equal(['', 'DiffText', 'DiffText', '', 'DiffText', 'DiffText',
1608 \ 'DiffAdd', 'DiffAdd', ''], hl)
1609
1610 " remove line after the end of a diff chunk
1611 call win_gotoid(w2_id)
1612 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1613 4d
1614 call win_gotoid(w1_id)
1615 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1616 call assert_equal(['', 'DiffText', 'DiffText', 'DiffAdd', '', '', 'DiffText',
1617 \ 'DiffText', ''], hl)
1618
1619 " remove lines starting from the end of one diff chunk and ending inside
1620 " another diff chunk
1621 call win_gotoid(w2_id)
1622 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
1623 4,7d
1624 call win_gotoid(w1_id)
1625 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1626 call assert_equal(['', 'DiffText', 'DiffText', 'DiffText', 'DiffAdd',
1627 \ 'DiffAdd', 'DiffAdd', 'DiffAdd', ''], hl)
1628
1629 " removing the only remaining diff chunk should make the files equal
1630 call win_gotoid(w2_id)
1631 call setline(1, ['a', '2', '3', 'x', 'd', 'e', 'f', 'x', '7', '8', 'i'])
1632 8d
1633 let hl = range(1, 10)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1634 call assert_equal(['', '', '', 'DiffAdd', '', '', '', '', '', ''], hl)
1635 call win_gotoid(w2_id)
1636 4d
1637 call win_gotoid(w1_id)
1638 let hl = range(1, 9)->map({_, lnum -> diff_hlID(lnum, 1)->synIDattr('name')})
1639 call assert_equal(['', '', '', '', '', '', '', '', ''], hl)
1640
1641 %bw!
1642endfunc
glacambread5c1782021-05-24 14:20:53 +02001643
Bram Moolenaar06f60952021-12-28 18:30:05 +00001644func Test_diff_binary()
1645 CheckScreendump
1646
1647 let content =<< trim END
1648 call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g'])
1649 vnew
1650 call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g'])
1651 windo diffthis
1652 wincmd p
1653 norm! gg0
1654 redraw!
1655 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001656 call writefile(content, 'Xtest_diff_bin', 'D')
Bram Moolenaar06f60952021-12-28 18:30:05 +00001657 let buf = RunVimInTerminal('-S Xtest_diff_bin', {})
1658
1659 " Test using internal diff
1660 call VerifyScreenDump(buf, 'Test_diff_bin_01', {})
1661
1662 " Test using internal diff and case folding
1663 call term_sendkeys(buf, ":set diffopt+=icase\<cr>")
1664 call term_sendkeys(buf, "\<C-l>")
1665 call VerifyScreenDump(buf, 'Test_diff_bin_02', {})
1666 " Test using external diff
1667 call term_sendkeys(buf, ":set diffopt=filler\<cr>")
1668 call term_sendkeys(buf, "\<C-l>")
1669 call VerifyScreenDump(buf, 'Test_diff_bin_03', {})
1670 " Test using external diff and case folding
1671 call term_sendkeys(buf, ":set diffopt=filler,icase\<cr>")
1672 call term_sendkeys(buf, "\<C-l>")
1673 call VerifyScreenDump(buf, 'Test_diff_bin_04', {})
1674
1675 " clean up
1676 call StopVimInTerminal(buf)
Bram Moolenaar06f60952021-12-28 18:30:05 +00001677 set diffopt&vim
1678endfunc
1679
Yegappan Lakshmananb0ad2d92022-01-27 13:16:59 +00001680" Test for using the 'zi' command to invert 'foldenable' in diff windows (test
1681" for the issue fixed by patch 6.2.317)
1682func Test_diff_foldinvert()
1683 %bw!
Bram Moolenaar61abe7d2022-08-30 21:46:08 +01001684 edit Xdoffile1
1685 new Xdoffile2
1686 new Xdoffile3
Yegappan Lakshmananb0ad2d92022-01-27 13:16:59 +00001687 windo diffthis
1688 " open a non-diff window
1689 botright new
1690 1wincmd w
1691 call assert_true(getwinvar(1, '&foldenable'))
1692 call assert_true(getwinvar(2, '&foldenable'))
1693 call assert_true(getwinvar(3, '&foldenable'))
1694 normal zi
1695 call assert_false(getwinvar(1, '&foldenable'))
1696 call assert_false(getwinvar(2, '&foldenable'))
1697 call assert_false(getwinvar(3, '&foldenable'))
1698 normal zi
1699 call assert_true(getwinvar(1, '&foldenable'))
1700 call assert_true(getwinvar(2, '&foldenable'))
1701 call assert_true(getwinvar(3, '&foldenable'))
1702
1703 " If the current window has 'noscrollbind', then 'zi' should not change
1704 " 'foldenable' in other windows.
1705 1wincmd w
1706 set noscrollbind
1707 normal zi
1708 call assert_false(getwinvar(1, '&foldenable'))
1709 call assert_true(getwinvar(2, '&foldenable'))
1710 call assert_true(getwinvar(3, '&foldenable'))
1711
1712 " 'zi' should not change the 'foldenable' for windows with 'noscrollbind'
1713 1wincmd w
1714 set scrollbind
1715 normal zi
1716 call setwinvar(2, '&scrollbind', v:false)
1717 normal zi
1718 call assert_false(getwinvar(1, '&foldenable'))
1719 call assert_true(getwinvar(2, '&foldenable'))
1720 call assert_false(getwinvar(3, '&foldenable'))
1721
1722 %bw!
1723 set scrollbind&
1724endfunc
1725
Bram Moolenaara315ce12022-06-24 12:38:57 +01001726" This was scrolling for 'cursorbind' but 'scrollbind' is more important
1727func Test_diff_scroll()
1728 CheckScreendump
1729
1730 let left =<< trim END
1731 line 1
1732 line 2
1733 line 3
1734 line 4
1735
1736 // Common block
1737 // one
1738 // containing
1739 // four lines
1740
1741 // Common block
1742 // two
1743 // containing
1744 // four lines
1745 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001746 call writefile(left, 'Xleft', 'D')
Bram Moolenaara315ce12022-06-24 12:38:57 +01001747 let right =<< trim END
1748 line 1
1749 line 2
1750 line 3
1751 line 4
1752
1753 Lorem
1754 ipsum
1755 dolor
1756 sit
1757 amet,
1758 consectetur
1759 adipiscing
1760 elit.
1761 Etiam
1762 luctus
1763 lectus
1764 sodales,
1765 dictum
1766
1767 // Common block
1768 // one
1769 // containing
1770 // four lines
1771
1772 Vestibulum
1773 tincidunt
1774 aliquet
1775 nulla.
1776
1777 // Common block
1778 // two
1779 // containing
1780 // four lines
1781 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001782 call writefile(right, 'Xright', 'D')
Bram Moolenaara315ce12022-06-24 12:38:57 +01001783 let buf = RunVimInTerminal('-d Xleft Xright', {'rows': 12})
1784 call term_sendkeys(buf, "\<C-W>\<C-W>jjjj")
1785 call VerifyScreenDump(buf, 'Test_diff_scroll_1', {})
1786 call term_sendkeys(buf, "j")
1787 call VerifyScreenDump(buf, 'Test_diff_scroll_2', {})
1788
1789 call StopVimInTerminal(buf)
Bram Moolenaara315ce12022-06-24 12:38:57 +01001790endfunc
1791
Bram Moolenaar38d867f2023-04-01 19:54:40 +01001792" This was scrolling too many lines.
1793func Test_diff_scroll_wrap_on()
1794 20new
1795 40vsplit
1796 call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
1797 setlocal number diff so=0
1798 redraw
1799 normal! jj
1800 call assert_equal(1, winsaveview().topline)
1801 normal! j
1802 call assert_equal(2, winsaveview().topline)
zeertzjq05834912023-10-04 20:12:37 +02001803
1804 bwipe!
1805 bwipe!
1806endfunc
1807
1808func Test_diff_scroll_many_filler()
1809 20new
1810 vnew
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001811 call setline(1, range(1, 40))
zeertzjq05834912023-10-04 20:12:37 +02001812 diffthis
1813 setlocal scrolloff=0
1814 wincmd p
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001815 call setline(1, range(1, 20)->reverse() + ['###']->repeat(41) + range(21, 40)->reverse())
zeertzjq05834912023-10-04 20:12:37 +02001816 diffthis
1817 setlocal scrolloff=0
1818 wincmd p
1819 redraw
1820
1821 " Note: need a redraw after each scroll, otherwise the test always passes.
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001822 for _ in range(2)
1823 normal! G
1824 redraw
1825 call assert_equal(40, winsaveview().topline)
1826 call assert_equal(19, winsaveview().topfill)
1827 exe "normal! \<C-B>"
1828 redraw
1829 call assert_equal(22, winsaveview().topline)
1830 call assert_equal(0, winsaveview().topfill)
1831 exe "normal! \<C-B>"
1832 redraw
1833 call assert_equal(4, winsaveview().topline)
1834 call assert_equal(0, winsaveview().topfill)
1835 exe "normal! \<C-B>"
1836 redraw
1837 call assert_equal(1, winsaveview().topline)
1838 call assert_equal(0, winsaveview().topfill)
1839 set smoothscroll
1840 endfor
zeertzjq05834912023-10-04 20:12:37 +02001841
Luuk van Baalb9f5b952024-03-26 18:46:45 +01001842 set smoothscroll&
Luuk van Baalcb204e62024-04-02 20:49:45 +02001843 %bwipe!
Bram Moolenaar38d867f2023-04-01 19:54:40 +01001844endfunc
1845
Bram Moolenaarcd38bb42022-06-26 14:04:07 +01001846" This was trying to update diffs for a buffer being closed
1847func Test_diff_only()
1848 silent! lfile
1849 set diff
1850 lopen
1851 norm o
1852 silent! norm o
1853
1854 set nodiff
1855 %bwipe!
1856endfunc
1857
Bram Moolenaarc101abf2022-06-26 16:53:34 +01001858" This was causing invalid diff block values
1859" FIXME: somehow this causes a valgrind error when run directly but not when
1860" run as a test.
1861func Test_diff_manipulations()
1862 set diff
1863 split 0
1864 sil! norm R doobdeuR doobdeuR doobdeu
1865
1866 set nodiff
1867 %bwipe!
1868endfunc
1869
Bram Moolenaar4e677b92022-07-28 18:44:27 +01001870" This was causing the line number in the diff block to go below one.
1871" FIXME: somehow this causes a valgrind error when run directly but not when
1872" run as a test.
1873func Test_diff_put_and_undo()
1874 set diff
1875 next 0
1876 split 00
1877 sil! norm o0gguudpo0ggJuudp
1878
1879 bwipe!
1880 bwipe!
1881 set nodiff
1882endfunc
1883
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001884" Test for the diff() function
1885def Test_diff_func()
1886 # string is added/removed/modified at the beginning
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001887 assert_equal("@@ -0,0 +1 @@\n+abc\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001888 diff(['def'], ['abc', 'def'], {output: 'unified'}))
1889 assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 1}],
1890 diff(['def'], ['abc', 'def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001891 assert_equal("@@ -1 +0,0 @@\n-abc\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001892 diff(['abc', 'def'], ['def'], {output: 'unified'}))
1893 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 0}],
1894 diff(['abc', 'def'], ['def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001895 assert_equal("@@ -1 +1 @@\n-abc\n+abx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001896 diff(['abc', 'def'], ['abx', 'def'], {output: 'unified'}))
1897 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1898 diff(['abc', 'def'], ['abx', 'def'], {output: 'indices'}))
1899
1900 # string is added/removed/modified at the end
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001901 assert_equal("@@ -1,0 +2 @@\n+def\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001902 diff(['abc'], ['abc', 'def'], {output: 'unified'}))
1903 assert_equal([{from_idx: 1, from_count: 0, to_idx: 1, to_count: 1}],
1904 diff(['abc'], ['abc', 'def'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001905 assert_equal("@@ -2 +1,0 @@\n-def\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001906 diff(['abc', 'def'], ['abc'], {output: 'unified'}))
1907 assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 0}],
1908 diff(['abc', 'def'], ['abc'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001909 assert_equal("@@ -2 +2 @@\n-def\n+xef\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001910 diff(['abc', 'def'], ['abc', 'xef'], {output: 'unified'}))
1911 assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 1}],
1912 diff(['abc', 'def'], ['abc', 'xef'], {output: 'indices'}))
1913
1914 # string is added/removed/modified in the middle
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001915 assert_equal("@@ -2,0 +3 @@\n+xxx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001916 diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'unified'}))
1917 assert_equal([{from_idx: 2, from_count: 0, to_idx: 2, to_count: 1}],
1918 diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001919 assert_equal("@@ -3 +2,0 @@\n-333\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001920 diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'unified'}))
1921 assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 0}],
1922 diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001923 assert_equal("@@ -3 +3 @@\n-333\n+xxx\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001924 diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'unified'}))
1925 assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 1}],
1926 diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'indices'}))
1927
1928 # new strings are added to an empty List
1929 assert_equal("@@ -0,0 +1,2 @@\n+abc\n+def\n",
1930 diff([], ['abc', 'def'], {output: 'unified'}))
1931 assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 2}],
1932 diff([], ['abc', 'def'], {output: 'indices'}))
1933
1934 # all the strings are removed from a List
1935 assert_equal("@@ -1,2 +0,0 @@\n-abc\n-def\n",
1936 diff(['abc', 'def'], [], {output: 'unified'}))
1937 assert_equal([{from_idx: 0, from_count: 2, to_idx: 0, to_count: 0}],
1938 diff(['abc', 'def'], [], {output: 'indices'}))
1939
1940 # First character is added/removed/different
1941 assert_equal("@@ -1 +1 @@\n-abc\n+bc\n",
1942 diff(['abc'], ['bc'], {output: 'unified'}))
1943 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1944 diff(['abc'], ['bc'], {output: 'indices'}))
1945 assert_equal("@@ -1 +1 @@\n-bc\n+abc\n",
1946 diff(['bc'], ['abc'], {output: 'unified'}))
1947 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1948 diff(['bc'], ['abc'], {output: 'indices'}))
1949 assert_equal("@@ -1 +1 @@\n-abc\n+xbc\n",
1950 diff(['abc'], ['xbc'], {output: 'unified'}))
1951 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1952 diff(['abc'], ['xbc'], {output: 'indices'}))
1953
1954 # Last character is added/removed/different
1955 assert_equal("@@ -1 +1 @@\n-abc\n+abcd\n",
1956 diff(['abc'], ['abcd'], {output: 'unified'}))
1957 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1958 diff(['abc'], ['abcd'], {output: 'indices'}))
1959 assert_equal("@@ -1 +1 @@\n-abcd\n+abc\n",
1960 diff(['abcd'], ['abc'], {output: 'unified'}))
1961 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
1962 diff(['abcd'], ['abc'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001963 var diff_unified: string = diff(['abc'], ['abx'], {output: 'unified'})
1964 assert_equal("@@ -1 +1 @@\n-abc\n+abx\n", diff_unified)
1965 var diff_indices: list<dict<number>> =
1966 diff(['abc'], ['abx'], {output: 'indices'})
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001967 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001968 diff_indices)
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001969
1970 # partial string modification at the start and at the end.
1971 var fromlist =<< trim END
1972 one two
1973 three four
1974 five six
1975 END
1976 var tolist =<< trim END
1977 one
1978 six
1979 END
1980 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'}))
1981 assert_equal([{from_idx: 0, from_count: 3, to_idx: 0, to_count: 2}],
1982 diff(fromlist, tolist, {output: 'indices'}))
1983
1984 # non-contiguous modifications
1985 fromlist =<< trim END
1986 one two
1987 three four
1988 five abc six
1989 END
1990 tolist =<< trim END
1991 one abc two
1992 three four
1993 five six
1994 END
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001995 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 +01001996 diff(fromlist, tolist, {output: 'unified'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01001997 assert_equal([{'from_count': 1, 'to_idx': 0, 'to_count': 1, 'from_idx': 0},
1998 {'from_count': 1, 'to_idx': 2, 'to_count': 1, 'from_idx': 2}],
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01001999 diff(fromlist, tolist, {output: 'indices'}))
2000
2001 # add/remove blank lines
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002002 assert_equal("@@ -2,2 +1,0 @@\n-\n-\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002003 diff(['one', '', '', 'two'], ['one', 'two'], {output: 'unified'}))
2004 assert_equal([{from_idx: 1, from_count: 2, to_idx: 1, to_count: 0}],
2005 diff(['one', '', '', 'two'], ['one', 'two'], {output: 'indices'}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002006 assert_equal("@@ -1,0 +2,2 @@\n+\n+\n",
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002007 diff(['one', 'two'], ['one', '', '', 'two'], {output: 'unified'}))
2008 assert_equal([{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}],
2009 diff(['one', 'two'], ['one', '', '', 'two'], {output: 'indices'}))
2010
2011 # diff ignoring case
2012 assert_equal('', diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'unified'}))
2013 assert_equal([], diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'indices'}))
2014
2015 # diff ignoring all whitespace changes except leading whitespace changes
2016 assert_equal('', diff(['abc def'], ['abc def '], {iwhite: true}))
2017 assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:true}))
2018 assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:false}))
2019 assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:true}))
2020 assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:false}))
2021
2022 # diff ignoring all whitespace changes
2023 assert_equal('', diff(['abc def'], [' abc def '], {iwhiteall: true}))
2024 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:true}))
2025 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:false}))
2026
2027 # diff ignoring trailing whitespace changes
2028 assert_equal('', diff(['abc'], ['abc '], {iwhiteeol: true}))
2029
2030 # diff ignoring blank lines
2031 assert_equal('', diff(['one', '', '', 'two'], ['one', 'two'], {iblank: true}))
2032 assert_equal('', diff(['one', 'two'], ['one', '', '', 'two'], {iblank: true}))
2033
2034 # same string
2035 assert_equal('', diff(['abc', 'def', 'ghi'], ['abc', 'def', 'ghi']))
2036 assert_equal('', diff([''], ['']))
2037 assert_equal('', diff([], []))
2038
2039 # different xdiff algorithms
2040 for algo in ['myers', 'minimal', 'patience', 'histogram']
2041 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
2042 diff([' abc '], [' xxx '], {algorithm: algo, output: 'unified'}))
2043 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
2044 diff([' abc '], [' xxx '], {algorithm: algo, output: 'indices'}))
2045 endfor
2046 assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
2047 diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'unified'}))
2048 assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
2049 diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'indices'}))
2050
2051 # identical strings
2052 assert_equal('', diff(['111', '222'], ['111', '222'], {output: 'unified'}))
2053 assert_equal([], diff(['111', '222'], ['111', '222'], {output: 'indices'}))
2054 assert_equal('', diff([], [], {output: 'unified'}))
2055 assert_equal([], diff([], [], {output: 'indices'}))
2056
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002057 # If 'diffexpr' is set, it should not be used for diff()
2058 def MyDiffExpr()
2059 enddef
2060 var save_diffexpr = &diffexpr
2061 :set diffexpr=MyDiffExpr()
2062 assert_equal("@@ -1 +1 @@\n-abc\n+\n",
2063 diff(['abc'], [''], {output: 'unified'}))
2064 assert_equal([{'from_idx': 0, 'from_count': 1, 'to_idx': 0, 'to_count': 1}],
2065 diff(['abc'], [''], {output: 'indices'}))
2066 assert_equal('MyDiffExpr()', &diffexpr)
2067 &diffexpr = save_diffexpr
2068
2069 # try different values for unified diff 'context'
2070 assert_equal("@@ -0,0 +1 @@\n+x\n",
2071 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c']))
2072 assert_equal("@@ -0,0 +1 @@\n+x\n",
2073 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 0}))
2074 assert_equal("@@ -1 +1,2 @@\n+x\n a\n",
2075 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 1}))
2076 assert_equal("@@ -1,2 +1,3 @@\n+x\n a\n b\n",
2077 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 2}))
2078 assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
2079 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 3}))
2080 assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
2081 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 4}))
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002082 assert_equal("@@ -0,0 +1 @@\n+x\n",
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002083 diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: -1}))
2084
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002085 # Error cases
2086 assert_fails('call diff({}, ["a"])', 'E1211:')
2087 assert_fails('call diff(["a"], {})', 'E1211:')
2088 assert_fails('call diff(["a"], ["a"], [])', 'E1206:')
2089 assert_fails('call diff(["a"], ["a"], {output: "xyz"})', 'E106: Unsupported diff output format: xyz')
Yegappan Lakshmananbe156a32024-02-11 17:08:29 +01002090 assert_fails('call diff(["a"], ["a"], {context: []})', 'E745: Using a List as a Number')
Yegappan Lakshmananfa378352024-02-01 22:05:27 +01002091enddef
Bram Moolenaara315ce12022-06-24 12:38:57 +01002092
Yegappan Lakshmanana0010a12024-02-12 20:21:26 +01002093" Test for using the diff() function with 'diffexpr'
2094func Test_diffexpr_with_diff_func()
2095 CheckScreendump
2096
2097 let lines =<< trim END
2098 def DiffFuncExpr()
2099 var in: list<string> = readfile(v:fname_in)
2100 var new: list<string> = readfile(v:fname_new)
2101 var out: string = diff(in, new)
2102 writefile(split(out, "\n"), v:fname_out)
2103 enddef
2104 set diffexpr=DiffFuncExpr()
2105
2106 edit Xdifffunc1.txt
2107 diffthis
2108 vert split Xdifffunc2.txt
2109 diffthis
2110 END
2111 call writefile(lines, 'XsetupDiffFunc.vim', 'D')
2112
2113 call writefile(['zero', 'one', 'two', 'three'], 'Xdifffunc1.txt', 'D')
2114 call writefile(['one', 'twox', 'three', 'four'], 'Xdifffunc2.txt', 'D')
2115
2116 let buf = RunVimInTerminal('-S XsetupDiffFunc.vim', {'rows': 12})
2117 call VerifyScreenDump(buf, 'Test_difffunc_diffexpr_1', {})
2118 call StopVimInTerminal(buf)
2119endfunc
2120
zeertzjq9e7f1fc2024-03-16 09:40:22 +01002121func Test_diff_toggle_wrap_skipcol_leftcol()
2122 61vnew
2123 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.')
2124 30vnew
2125 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.')
2126 let win1 = win_getid()
2127 setlocal smoothscroll
2128 exe "normal! $\<C-E>"
2129 wincmd l
2130 let win2 = win_getid()
2131 setlocal smoothscroll
2132 exe "normal! $\<C-E>"
2133 call assert_equal([
2134 \ '<<<sadipscing elitr, sed diam |<<<tetur sadipscing elitr, sed|',
2135 \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
2136 \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
2137 \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
2138 \ '~ |ptua. |',
2139 \ ], ScreenLines([1, 5], 62))
2140 call assert_equal({'col': 29, 'row': 4, 'endcol': 29, 'curscol': 29},
2141 \ screenpos(win1, line('.', win1), col('.', win1)))
2142 call assert_equal({'col': 36, 'row': 5, 'endcol': 36, 'curscol': 36},
2143 \ screenpos(win2, line('.', win2), col('.', win2)))
2144
2145 wincmd h
2146 diffthis
2147 wincmd l
2148 diffthis
2149 normal! 0
2150 call assert_equal([
2151 \ ' ipsum dolor sit amet, conset| Lorem ipsum dolor sit amet, |',
2152 \ '~ |~ |',
2153 \ ], ScreenLines([1, 2], 62))
2154 call assert_equal({'col': 3, 'row': 1, 'endcol': 3, 'curscol': 3},
2155 \ screenpos(win1, line('.', win1), col('.', win1)))
2156 call assert_equal({'col': 34, 'row': 1, 'endcol': 34, 'curscol': 34},
2157 \ screenpos(win2, line('.', win2), col('.', win2)))
2158
2159 normal! $
2160 call assert_equal([
2161 \ ' voluptua. | diam voluptua. |',
2162 \ '~ |~ |',
2163 \ ], ScreenLines([1, 2], 62))
2164 call assert_equal({'col': 11, 'row': 1, 'endcol': 11, 'curscol': 11},
2165 \ screenpos(win1, line('.', win1), col('.', win1)))
2166 call assert_equal({'col': 48, 'row': 1, 'endcol': 48, 'curscol': 48},
2167 \ screenpos(win2, line('.', win2), col('.', win2)))
2168
2169 diffoff!
2170 call assert_equal([
2171 \ 'ipsum dolor sit amet, consetet|Lorem ipsum dolor sit amet, co|',
2172 \ 'ur sadipscing elitr, sed diam |nsetetur sadipscing elitr, sed|',
2173 \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
2174 \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
2175 \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
2176 \ '~ |ptua. |',
2177 \ ], ScreenLines([1, 6], 62))
2178 call assert_equal({'col': 29, 'row': 5, 'endcol': 29, 'curscol': 29},
2179 \ screenpos(win1, line('.', win1), col('.', win1)))
2180 call assert_equal({'col': 36, 'row': 6, 'endcol': 36, 'curscol': 36},
2181 \ screenpos(win2, line('.', win2), col('.', win2)))
2182
2183 bwipe!
2184 bwipe!
2185endfunc
2186
Luuk van Baal9148ba82024-04-08 22:27:41 +02002187" Ctrl-D reveals filler lines below the last line in the buffer.
2188func Test_diff_eob_halfpage()
Luuk van Baal08b0f632024-04-09 22:43:49 +02002189 new
Luuk van Baal9148ba82024-04-08 22:27:41 +02002190 call setline(1, ['']->repeat(10) + ['a'])
2191 diffthis
Luuk van Baal08b0f632024-04-09 22:43:49 +02002192 new
Luuk van Baal9148ba82024-04-08 22:27:41 +02002193 call setline(1, ['']->repeat(3) + ['a', 'b'])
2194 diffthis
Luuk van Baal08b0f632024-04-09 22:43:49 +02002195 resize 5
Luuk van Baal9148ba82024-04-08 22:27:41 +02002196 wincmd j
Luuk van Baal08b0f632024-04-09 22:43:49 +02002197 resize 5
2198 norm G
2199 call assert_equal(7, line('w0'))
2200 exe "norm! \<C-D>"
2201 call assert_equal(8, line('w0'))
Luuk van Baal9148ba82024-04-08 22:27:41 +02002202
2203 %bwipe!
2204endfunc
2205
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +02002206func Test_diff_overlapped_diff_blocks_will_be_merged()
2207 CheckScreendump
2208
2209 let lines =<< trim END
2210 func DiffExprStub()
2211 let txt_in = readfile(v:fname_in)
2212 let txt_new = readfile(v:fname_new)
2213 if txt_in == ["line1"] && txt_new == ["line2"]
2214 call writefile(["1c1"], v:fname_out)
2215 elseif txt_in == readfile("Xdiin1") && txt_new == readfile("Xdinew1")
2216 call writefile(readfile("Xdiout1"), v:fname_out)
2217 elseif txt_in == readfile("Xdiin2") && txt_new == readfile("Xdinew2")
2218 call writefile(readfile("Xdiout2"), v:fname_out)
2219 endif
2220 endfunc
2221 END
2222 call writefile(lines, 'XdiffSetup', 'D')
2223
2224 call WriteDiffFiles(0, [], [])
2225 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2', {})
2226 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2227
2228 call WriteDiffFiles(buf, ["a", "b"], ["x", "x"])
2229 call writefile(["a", "b"], "Xdiin1")
2230 call writefile(["x", "x"], "Xdinew1")
2231 call writefile(["1c1", "2c2"], "Xdiout1")
2232 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2233 call VerifyBoth(buf, "Test_diff_overlapped_2.01", "")
2234 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2235
2236 call WriteDiffFiles(buf, ["a", "b", "c"], ["x", "c"])
2237 call writefile(["a", "b", "c"], "Xdiin1")
2238 call writefile(["x", "c"], "Xdinew1")
2239 call writefile(["1c1", "2d1"], "Xdiout1")
2240 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2241 call VerifyBoth(buf, "Test_diff_overlapped_2.02", "")
2242 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2243
2244 call WriteDiffFiles(buf, ["a", "c"], ["x", "x", "c"])
2245 call writefile(["a", "c"], "Xdiin1")
2246 call writefile(["x", "x", "c"], "Xdinew1")
2247 call writefile(["1c1", "1a2"], "Xdiout1")
2248 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2249 call VerifyBoth(buf, "Test_diff_overlapped_2.03", "")
2250 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2251
2252 call StopVimInTerminal(buf)
2253 wincmd c
2254
2255 call WriteDiffFiles3(0, [], [], [])
2256 let buf = RunVimInTerminal('-d -S XdiffSetup Xdifile1 Xdifile2 Xdifile3', {})
2257 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2258
2259 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "b", "c"])
2260 call VerifyBoth(buf, "Test_diff_overlapped_3.01", "")
2261
2262 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "c"])
2263 call VerifyBoth(buf, "Test_diff_overlapped_3.02", "")
2264
2265 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y"])
2266 call VerifyBoth(buf, "Test_diff_overlapped_3.03", "")
2267
2268 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "c"])
2269 call VerifyBoth(buf, "Test_diff_overlapped_3.04", "")
2270
2271 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "y"])
2272 call VerifyBoth(buf, "Test_diff_overlapped_3.05", "")
2273
2274 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["y", "y", "y"])
2275 call VerifyBoth(buf, "Test_diff_overlapped_3.06", "")
2276
2277 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "x"], ["y", "y", "c"])
2278 call VerifyBoth(buf, "Test_diff_overlapped_3.07", "")
2279
2280 call WriteDiffFiles3(buf, ["a", "b", "c"], ["x", "x", "c"], ["a", "y", "y"])
2281 call VerifyBoth(buf, "Test_diff_overlapped_3.08", "")
2282
2283 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "d", "e"])
2284 call VerifyBoth(buf, "Test_diff_overlapped_3.09", "")
2285
2286 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "e"])
2287 call VerifyBoth(buf, "Test_diff_overlapped_3.10", "")
2288
2289 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["y", "y", "y", "y", "y"])
2290 call VerifyBoth(buf, "Test_diff_overlapped_3.11", "")
2291
2292 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "d", "e"])
2293 call VerifyBoth(buf, "Test_diff_overlapped_3.12", "")
2294
2295 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "e"])
2296 call VerifyBoth(buf, "Test_diff_overlapped_3.13", "")
2297
2298 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "y", "y", "y", "y"])
2299 call VerifyBoth(buf, "Test_diff_overlapped_3.14", "")
2300
2301 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "d", "e"])
2302 call VerifyBoth(buf, "Test_diff_overlapped_3.15", "")
2303
2304 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "e"])
2305 call VerifyBoth(buf, "Test_diff_overlapped_3.16", "")
2306
2307 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "y", "y", "y"])
2308 call VerifyBoth(buf, "Test_diff_overlapped_3.17", "")
2309
2310 call WriteDiffFiles3(buf, ["a", "b"], ["x", "b"], ["y", "y"])
2311 call writefile(["a", "b"], "Xdiin1")
2312 call writefile(["x", "b"], "Xdinew1")
2313 call writefile(["1c1"], "Xdiout1")
2314 call writefile(["a", "b"], "Xdiin2")
2315 call writefile(["y", "y"], "Xdinew2")
2316 call writefile(["1c1", "2c2"], "Xdiout2")
2317 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2318 call VerifyInternal(buf, "Test_diff_overlapped_3.18", "")
2319 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2320
2321 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "c", "d"])
2322 call writefile(["a", "b", "c", "d"], "Xdiin1")
2323 call writefile(["x", "b", "x", "d"], "Xdinew1")
2324 call writefile(["1c1", "3c3"], "Xdiout1")
2325 call writefile(["a", "b", "c", "d"], "Xdiin2")
2326 call writefile(["y", "y", "c", "d"], "Xdinew2")
2327 call writefile(["1c1", "2c2"], "Xdiout2")
2328 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2329 call VerifyInternal(buf, "Test_diff_overlapped_3.19", "")
2330 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2331
2332 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "d"])
2333 call writefile(["a", "b", "c", "d"], "Xdiin1")
2334 call writefile(["x", "b", "x", "d"], "Xdinew1")
2335 call writefile(["1c1", "3c3"], "Xdiout1")
2336 call writefile(["a", "b", "c", "d"], "Xdiin2")
2337 call writefile(["y", "y", "y", "d"], "Xdinew2")
2338 call writefile(["1c1", "2,3c2,3"], "Xdiout2")
2339 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2340 call VerifyInternal(buf, "Test_diff_overlapped_3.20", "")
2341 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2342
2343 call WriteDiffFiles3(buf, ["a", "b", "c", "d"], ["x", "b", "x", "d"], ["y", "y", "y", "y"])
2344 call writefile(["a", "b", "c", "d"], "Xdiin1")
2345 call writefile(["x", "b", "x", "d"], "Xdinew1")
2346 call writefile(["1c1", "3c3"], "Xdiout1")
2347 call writefile(["a", "b", "c", "d"], "Xdiin2")
2348 call writefile(["y", "y", "y", "y"], "Xdinew2")
2349 call writefile(["1c1", "2,4c2,4"], "Xdiout2")
2350 call term_sendkeys(buf, ":set diffexpr=DiffExprStub()\<CR>:")
2351 call VerifyInternal(buf, "Test_diff_overlapped_3.21", "")
2352 call term_sendkeys(buf, ":set diffexpr&\<CR>:")
2353
2354 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b", "c"])
2355 call VerifyBoth(buf, "Test_diff_overlapped_3.22", "")
2356
2357 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["c"])
2358 call VerifyBoth(buf, "Test_diff_overlapped_3.23", "")
2359
2360 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], [])
2361 call VerifyBoth(buf, "Test_diff_overlapped_3.24", "")
2362
2363 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "c"])
2364 call VerifyBoth(buf, "Test_diff_overlapped_3.25", "")
2365
2366 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a"])
2367 call VerifyBoth(buf, "Test_diff_overlapped_3.26", "")
2368
2369 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["b"])
2370 call VerifyBoth(buf, "Test_diff_overlapped_3.27", "")
2371
2372 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["d", "e"])
2373 call VerifyBoth(buf, "Test_diff_overlapped_3.28", "")
2374
2375 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["e"])
2376 call VerifyBoth(buf, "Test_diff_overlapped_3.29", "")
2377
2378 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "d", "e"])
2379 call VerifyBoth(buf, "Test_diff_overlapped_3.30", "")
2380
2381 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "e"])
2382 call VerifyBoth(buf, "Test_diff_overlapped_3.31", "")
2383
2384 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a"])
2385 call VerifyBoth(buf, "Test_diff_overlapped_3.32", "")
2386
2387 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "d", "e"])
2388 call VerifyBoth(buf, "Test_diff_overlapped_3.33", "")
2389
2390 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b", "e"])
2391 call VerifyBoth(buf, "Test_diff_overlapped_3.34", "")
2392
2393 call WriteDiffFiles3(buf, ["a", "b", "c", "d", "e"], ["a", "x", "c", "x", "e"], ["a", "b"])
2394 call VerifyBoth(buf, "Test_diff_overlapped_3.35", "")
2395
2396 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "y", "b", "c"])
2397 call VerifyBoth(buf, "Test_diff_overlapped_3.36", "")
2398
2399 call WriteDiffFiles3(buf, ["a", "b", "c"], ["a", "x", "c"], ["a", "b", "y", "c"])
2400 call VerifyBoth(buf, "Test_diff_overlapped_3.37", "")
2401
Yukihiro Nakadaira01f65092025-01-15 18:36:43 +01002402 call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b", "f"])
2403 call VerifyBoth(buf, "Test_diff_overlapped_3.38", "")
2404
2405 call WriteDiffFiles3(buf, ["a", "b", "c"], ["d", "e"], ["b"])
2406 call VerifyBoth(buf, "Test_diff_overlapped_3.39", "")
2407
Yee Cheng Chinbc08ceb2025-03-02 22:05:37 +01002408 " File 3 overlaps twice, 2nd overlap completely within the existing block.
2409 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "bar"], ["foo", "w", "x", "y", "z", "bar"], ["foo", "1", "a", "b", "2", "bar"])
2410 call VerifyBoth(buf, "Test_diff_overlapped_3.40", "")
2411
2412 " File 3 overlaps twice, 2nd overlap extends beyond existing block on new
2413 " side. Make sure we don't over-extend the range and hit 'bar'.
2414 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "2", "d", "bar"])
2415 call VerifyBoth(buf, "Test_diff_overlapped_3.41", "")
2416
2417 " Chained overlaps. File 3's 2nd overlap spans two diff blocks and is longer
2418 " than the 2nd one.
2419 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"])
2420 call VerifyBoth(buf, "Test_diff_overlapped_3.42", "")
2421
2422 " File 3 has 2 overlaps. An add and a delete. First overlap's expansion hits
2423 " the 2nd one. Make sure we adjust the diff block to have fewer lines.
2424 call WriteDiffFiles3(buf, ["foo", "a", "b", "bar"], ["foo", "x", "y", "bar"], ["foo", "1", "a", "bar"])
2425 call VerifyBoth(buf, "Test_diff_overlapped_3.43", "")
2426
2427 " File 3 has 2 overlaps. An add and another add. First overlap's expansion hits
2428 " the 2nd one. Make sure we adjust the diff block to have more lines.
2429 call WriteDiffFiles3(buf, ["foo", "a", "b", "c", "d", "bar"], ["foo", "w", "x", "y", "z", "u", "bar"], ["foo", "1", "a", "b", "3", "4", "d", "bar"])
2430 call VerifyBoth(buf, "Test_diff_overlapped_3.44", "")
2431
Yukihiro Nakadaira06fe70c2024-09-26 16:19:42 +02002432 call StopVimInTerminal(buf)
2433endfunc
2434
zeertzjq7c515282024-11-10 20:26:12 +01002435" switching windows in diff mode caused an unnecessary scroll
Christian Brabandt05a40e02024-10-29 20:29:04 +01002436func Test_diff_topline_noscroll()
2437 CheckScreendump
2438
2439 let content =<< trim END
2440 call setline(1, range(1,60))
2441 vnew
2442 call setline(1, range(1,10) + range(50,60))
2443 windo diffthis
2444 norm! G
2445 exe "norm! 30\<C-y>"
2446 END
2447 call writefile(content, 'Xcontent', 'D')
2448 let buf = RunVimInTerminal('-S Xcontent', {'rows': 20})
2449 call VerifyScreenDump(buf, 'Test_diff_topline_1', {})
2450 call term_sendkeys(buf, ":echo line('w0', 1001)\<cr>")
2451 call term_wait(buf)
2452 call VerifyScreenDump(buf, 'Test_diff_topline_2', {})
2453 call term_sendkeys(buf, "\<C-W>p")
2454 call term_wait(buf)
2455 call VerifyScreenDump(buf, 'Test_diff_topline_3', {})
2456 call term_sendkeys(buf, "\<C-W>p")
2457 call term_wait(buf)
2458 call VerifyScreenDump(buf, 'Test_diff_topline_4', {})
2459 call StopVimInTerminal(buf)
2460endfunc
2461
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002462" Test inline highlighting which shows what's different within each diff block
2463func Test_diff_inline()
2464 CheckScreendump
2465
2466 call WriteDiffFiles(0, [], [])
2467 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2468 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2469
2470 call WriteDiffFiles(buf, ["abcdef ghi jk n", "x", "y"], ["aBcef gHi lm n", "y", "z"])
2471 call VerifyInternal(buf, "Test_diff_inline_01", "")
2472 call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:none")
2473
2474 " inline:simple is the same as default
2475 call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:simple")
2476
2477 call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:char")
2478 call VerifyInternal(buf, "Test_diff_inline_04", " diffopt+=inline:word")
2479
2480 " multiple inline values will the last one
2481 call VerifyInternal(buf, "Test_diff_inline_01", " diffopt+=inline:none,inline:char,inline:simple")
2482 call VerifyInternal(buf, "Test_diff_inline_02", " diffopt+=inline:simple,inline:word,inline:none")
2483 call VerifyInternal(buf, "Test_diff_inline_03", " diffopt+=inline:simple,inline:word,inline:char")
2484
2485 " DiffTextAdd highlight
2486 call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
2487 call VerifyInternal(buf, "Test_diff_inline_05", " diffopt+=inline:char")
2488
2489 " Live update in insert mode
2490 call term_sendkeys(buf, "\<Esc>isometext")
2491 call VerifyScreenDump(buf, "Test_diff_inline_06", {})
2492 call term_sendkeys(buf, "\<Esc>u")
2493
2494 " icase simple scenarios
2495 call VerifyInternal(buf, "Test_diff_inline_07", " diffopt+=inline:simple,icase")
2496 call VerifyInternal(buf, "Test_diff_inline_08", " diffopt+=inline:char,icase")
2497 call VerifyInternal(buf, "Test_diff_inline_09", " diffopt+=inline:word,icase")
2498
2499 " diff algorithms should affect highlight
2500 call WriteDiffFiles(buf, ["apples and oranges"], ["oranges and apples"])
2501 call VerifyInternal(buf, "Test_diff_inline_10", " diffopt+=inline:char")
2502 call VerifyInternal(buf, "Test_diff_inline_11", " diffopt+=inline:char,algorithm:patience")
2503
2504 " icase: composing chars and Unicode fold case edge cases
2505 call WriteDiffFiles(buf,
2506 \ ["1 - sigma in 6σ and Ὀδυσσεύς", "1 - angstrom in åå", "1 - composing: ii⃗I⃗"],
2507 \ ["2 - Sigma in 6Σ and ὈΔΥΣΣΕΎΣ", "2 - Angstrom in ÅÅ", "2 - Composing: i⃗I⃗I⃗"])
2508 call VerifyInternal(buf, "Test_diff_inline_12", " diffopt+=inline:char")
2509 call VerifyInternal(buf, "Test_diff_inline_13", " diffopt+=inline:char,icase")
2510
2511 " wide chars
2512 call WriteDiffFiles(buf, ["abc😅xde一", "f🚀g"], ["abcy😢de", "二f🚀g"])
2513 call VerifyInternal(buf, "Test_diff_inline_14", " diffopt+=inline:char,icase")
2514
2515 " NUL char (\n below is internally substituted as NUL)
2516 call WriteDiffFiles(buf, ["1\n34\n5\n6"], ["1234\n5", "6"])
2517 call VerifyInternal(buf, "Test_diff_inline_15", " diffopt+=inline:char")
2518
2519 " word diff: always use first buffer's iskeyword and ignore others' for consistency
2520 call WriteDiffFiles(buf, ["foo+bar test"], ["foo+baz test"])
2521 call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
2522
2523 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:diffupdate\<CR>")
2524 call VerifyInternal(buf, "Test_diff_inline_word_02", " diffopt+=inline:word")
2525
2526 call term_sendkeys(buf, ":set iskeyword&\<CR>:wincmd w\<CR>")
2527 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:wincmd w\<CR>:diffupdate\<CR>")
2528 " Use the previous screen dump as 2nd buffer's iskeyword does not matter
2529 call VerifyInternal(buf, "Test_diff_inline_word_01", " diffopt+=inline:word")
2530
2531 call term_sendkeys(buf, ":windo set iskeyword&\<CR>:1wincmd w\<CR>")
2532
Yee Cheng Chin9aa120f2025-04-04 19:16:21 +02002533 " word diff: test handling of multi-byte characters. Only alphanumeric chars
2534 " (e.g. Greek alphabet, but not CJK/emoji) count as words.
2535 call WriteDiffFiles(buf, ["🚀⛵️一二三ひらがなΔέλτα Δelta foobar"], ["🚀🛸一二四ひらなδέλτα δelta foobar"])
2536 call VerifyInternal(buf, "Test_diff_inline_word_03", " diffopt+=inline:word")
2537
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002538 " char diff: should slide highlight to whitespace boundary if possible for
2539 " better readability (by using forced indent-heuristics). A wrong result
2540 " would be if the highlight is "Bar, prefix". It should be "prefixBar, "
2541 " instead.
2542 call WriteDiffFiles(buf, ["prefixFoo, prefixEnd"], ["prefixFoo, prefixBar, prefixEnd"])
2543 call VerifyInternal(buf, "Test_diff_inline_char_01", " diffopt+=inline:char")
2544
2545 " char diff: small gaps between inline diff blocks will be merged during refine step
2546 " - first segment: test that we iteratively merge small gaps after we merged
2547 " adjacent blocks, but only with limited number (set to 4) of iterations.
2548 " - second and third segments: show that we need a large enough adjacent block to
2549 " trigger a merge.
2550 " - fourth segment: small gaps are not merged when adjacent large block is
2551 " on a different line.
2552 call WriteDiffFiles(buf,
2553 \ ["abcdefghijklmno", "anchor1",
2554 \ "abcdefghijklmno", "anchor2",
2555 \ "abcdefghijklmno", "anchor3",
2556 \ "test", "multiline"],
zeertzjq5a307c32025-03-28 19:01:32 +01002557 \ ["a?c?e?g?i?k???o", "anchor1",
2558 \ "a??de?????klmno", "anchor2",
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002559 \ "a??de??????lmno", "anchor3",
2560 \ "t?s?", "??????i?e"])
2561 call VerifyInternal(buf, "Test_diff_inline_char_02", " diffopt+=inline:char")
2562
2563 " Test multi-line blocks and whitespace
2564 call WriteDiffFiles(buf,
2565 \ ["this is ", "sometest text foo", "baz abc def ", "one", "word another word", "additional line"],
2566 \ ["this is some test", "texts", "foo bar abX Yef ", "oneword another word"])
2567 call VerifyInternal(buf, "Test_diff_inline_multiline_01", " diffopt+=inline:char,iwhite")
2568 call VerifyInternal(buf, "Test_diff_inline_multiline_02", " diffopt+=inline:word,iwhite")
2569 call VerifyInternal(buf, "Test_diff_inline_multiline_03", " diffopt+=inline:char,iwhiteeol")
2570 call VerifyInternal(buf, "Test_diff_inline_multiline_04", " diffopt+=inline:word,iwhiteeol")
2571 call VerifyInternal(buf, "Test_diff_inline_multiline_05", " diffopt+=inline:char,iwhiteall")
2572 call VerifyInternal(buf, "Test_diff_inline_multiline_06", " diffopt+=inline:word,iwhiteall")
2573
2574 " newline should be highlighted too when 'list' is set
2575 call term_sendkeys(buf, ":windo set list\<CR>")
2576 call VerifyInternal(buf, "Test_diff_inline_multiline_07", " diffopt+=inline:char")
2577 call VerifyInternal(buf, "Test_diff_inline_multiline_08", " diffopt+=inline:char,iwhite")
2578 call VerifyInternal(buf, "Test_diff_inline_multiline_09", " diffopt+=inline:char,iwhiteeol")
2579 call VerifyInternal(buf, "Test_diff_inline_multiline_10", " diffopt+=inline:char,iwhiteall")
2580 call term_sendkeys(buf, ":windo set nolist\<CR>")
2581
2582 call StopVimInTerminal(buf)
2583endfunc
2584
2585func Test_diff_inline_multibuffer()
2586 CheckScreendump
2587
2588 call WriteDiffFiles3(0, [], [], [])
2589 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
2590 call term_sendkeys(buf, ":windo set autoread\<CR>:1wincmd w\<CR>")
2591 call term_sendkeys(buf, ":hi DiffTextAdd ctermbg=blue\<CR>")
2592
2593 call WriteDiffFiles3(buf,
2594 \ ["That is buffer1.", "anchor", "Some random text", "anchor"],
2595 \ ["This is buffer2.", "anchor", "Some text", "anchor", "buffer2/3"],
2596 \ ["This is buffer3. Last.", "anchor", "Some more", "text here.", "anchor", "only in buffer2/3", "not in buffer1"])
2597 call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
2598
zeertzjq5a307c32025-03-28 19:01:32 +01002599 " Close one of the buffers and make sure it updates correctly
Yee Cheng Chin9943d472025-03-26 19:41:02 +01002600 call term_sendkeys(buf, ":diffoff\<CR>")
2601 call VerifyInternal(buf, "Test_diff_inline_multibuffer_02", " diffopt+=inline:char")
2602
2603 " Update text in the non-diff buffer and nothing should be changed
2604 call term_sendkeys(buf, "\<Esc>isometext")
2605 call VerifyScreenDump(buf, "Test_diff_inline_multibuffer_03", {})
2606 call term_sendkeys(buf, "\<Esc>u")
2607
2608 call term_sendkeys(buf, ":diffthis\<CR>")
2609 call VerifyInternal(buf, "Test_diff_inline_multibuffer_01", " diffopt+=inline:char")
2610
2611 " Test that removing first buffer from diff will in turn use the next
2612 " earliest buffer's iskeyword during word diff.
2613 call WriteDiffFiles3(buf,
2614 \ ["This+is=a-setence"],
2615 \ ["This+is=another-setence"],
2616 \ ["That+is=a-setence"])
2617 call term_sendkeys(buf, ":set iskeyword+=+\<CR>:2wincmd w\<CR>:set iskeyword+=-\<CR>:1wincmd w\<CR>")
2618 call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
2619 call term_sendkeys(buf, ":diffoff\<CR>")
2620 call VerifyInternal(buf, "Test_diff_inline_multibuffer_05", " diffopt+=inline:word")
2621 call term_sendkeys(buf, ":diffthis\<CR>")
2622 call VerifyInternal(buf, "Test_diff_inline_multibuffer_04", " diffopt+=inline:word")
2623
2624 " Test multi-buffer char diff refinement, and that removing a buffer from
2625 " diff will update the others properly.
2626 call WriteDiffFiles3(buf,
2627 \ ["abcdefghijkYmYYY"],
2628 \ ["aXXdXXghijklmnop"],
2629 \ ["abcdefghijkYmYop"])
2630 call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
2631 call term_sendkeys(buf, ":diffoff\<CR>")
2632 call VerifyInternal(buf, "Test_diff_inline_multibuffer_07", " diffopt+=inline:char")
2633 call term_sendkeys(buf, ":diffthis\<CR>")
2634 call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
2635
2636 call StopVimInTerminal(buf)
2637endfunc
2638
Jonathon7c7a4e62025-01-12 09:58:00 +01002639func Test_diffget_diffput_linematch()
2640 CheckScreendump
2641 call delete('.Xdifile1.swp')
2642 call delete('.Xdifile2.swp')
2643 call WriteDiffFiles(0, [], [])
2644 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2645 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2646
2647 " enable linematch
2648 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2649 call WriteDiffFiles(buf, ['',
2650 \ 'common line',
2651 \ 'common line',
2652 \ '',
2653 \ 'ABCabc',
2654 \ 'ABCabc',
2655 \ 'ABCabc',
2656 \ 'ABCabc',
2657 \ 'common line',
2658 \ 'common line',
2659 \ 'common line',
2660 \ 'something' ],
2661 \ ['',
2662 \ 'common line',
2663 \ 'common line',
2664 \ '',
2665 \ 'DEFabc',
2666 \ 'xyz',
2667 \ 'xyz',
2668 \ 'xyz',
2669 \ 'DEFabc',
2670 \ 'DEFabc',
2671 \ 'DEFabc',
2672 \ 'common line',
2673 \ 'common line',
2674 \ 'DEF',
2675 \ 'common line',
2676 \ 'DEF',
2677 \ 'something'])
2678 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_1', {})
2679
2680 " get from window 1 from line 5 to 9
2681 call term_sendkeys(buf, "1\<c-w>w")
2682 call term_sendkeys(buf, ":5,9diffget\<CR>")
2683 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_2', {})
2684
2685 " undo the last diffget
2686 call term_sendkeys(buf, "u")
2687
2688 " get from window 2 from line 5 to 10
2689 call term_sendkeys(buf, "2\<c-w>w")
2690 call term_sendkeys(buf, ":5,10diffget\<CR>")
2691 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_3', {})
2692
2693 " undo the last diffget
2694 call term_sendkeys(buf, "u")
2695
2696 " get all from window 2
2697 call term_sendkeys(buf, "2\<c-w>w")
2698 call term_sendkeys(buf, ":4,17diffget\<CR>")
2699 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_4', {})
2700
2701 " undo the last diffget
2702 call term_sendkeys(buf, "u")
2703
2704 " get all from window 1
2705 call term_sendkeys(buf, "1\<c-w>w")
2706 call term_sendkeys(buf, ":4,12diffget\<CR>")
2707 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_5', {})
2708
2709 " undo the last diffget
2710 call term_sendkeys(buf, "u")
2711
2712 " get from window 1 using do 1 line 5
2713 call term_sendkeys(buf, "1\<c-w>w")
2714 call term_sendkeys(buf, "5gg")
2715 call term_sendkeys(buf, ":diffget\<CR>")
2716 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_6', {})
2717
2718 " undo the last diffget
2719 call term_sendkeys(buf, "u")
2720
2721 " get from window 1 using do 2 line 6
2722 call term_sendkeys(buf, "1\<c-w>w")
2723 call term_sendkeys(buf, "6gg")
2724 call term_sendkeys(buf, ":diffget\<CR>")
2725 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_7', {})
2726
2727 " undo the last diffget
2728 call term_sendkeys(buf, "u")
2729
2730 " get from window 1 using do 2 line 7
2731 call term_sendkeys(buf, "1\<c-w>w")
2732 call term_sendkeys(buf, "7gg")
2733 call term_sendkeys(buf, ":diffget\<CR>")
2734 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_8', {})
2735
2736 " undo the last diffget
2737 call term_sendkeys(buf, "u")
2738
2739 " get from window 1 using do 2 line 11
2740 call term_sendkeys(buf, "1\<c-w>w")
2741 call term_sendkeys(buf, "11gg")
2742 call term_sendkeys(buf, ":diffget\<CR>")
2743 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_9', {})
2744
2745 " undo the last diffget
2746 call term_sendkeys(buf, "u")
2747
2748 " get from window 1 using do 2 line 12
2749 call term_sendkeys(buf, "1\<c-w>w")
2750 call term_sendkeys(buf, "12gg")
2751 call term_sendkeys(buf, ":diffget\<CR>")
2752 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_10', {})
2753
2754 " undo the last diffget
2755 call term_sendkeys(buf, "u")
2756
2757 " put from window 1 using dp 1 line 5
2758 call term_sendkeys(buf, "1\<c-w>w")
2759 call term_sendkeys(buf, "5gg")
2760 call term_sendkeys(buf, ":diffput\<CR>")
2761 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_11', {})
2762
2763 " undo the last diffput
2764 call term_sendkeys(buf, "2\<c-w>w")
2765 call term_sendkeys(buf, "u")
2766
2767 " put from window 1 using dp 2 line 6
2768 call term_sendkeys(buf, "1\<c-w>w")
2769 call term_sendkeys(buf, "6gg")
2770 call term_sendkeys(buf, ":diffput\<CR>")
2771 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_12', {})
2772
2773 " undo the last diffput
2774 call term_sendkeys(buf, "2\<c-w>w")
2775 call term_sendkeys(buf, "u")
2776
2777 " put from window 1 using dp 2 line 7
2778 call term_sendkeys(buf, "1\<c-w>w")
2779 call term_sendkeys(buf, "7gg")
2780 call term_sendkeys(buf, ":diffput\<CR>")
2781 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_13', {})
2782
2783 " undo the last diffput
2784 call term_sendkeys(buf, "2\<c-w>w")
2785 call term_sendkeys(buf, "u")
2786
2787 " put from window 1 using dp 2 line 11
2788 call term_sendkeys(buf, "1\<c-w>w")
2789 call term_sendkeys(buf, "11gg")
2790 call term_sendkeys(buf, ":diffput\<CR>")
2791 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_14', {})
2792
2793 " undo the last diffput
2794 call term_sendkeys(buf, "2\<c-w>w")
2795 call term_sendkeys(buf, "u")
2796
2797 " put from window 1 using dp 2 line 12
2798 call term_sendkeys(buf, "1\<c-w>w")
2799 call term_sendkeys(buf, "12gg")
2800 call term_sendkeys(buf, ":diffput\<CR>")
2801 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_15', {})
2802
2803 " undo the last diffput
2804 call term_sendkeys(buf, "2\<c-w>w")
2805 call term_sendkeys(buf, "u")
2806
2807 " put from window 2 using dp line 6
2808 call term_sendkeys(buf, "2\<c-w>w")
2809 call term_sendkeys(buf, "6gg")
2810 call term_sendkeys(buf, ":diffput\<CR>")
2811 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_16', {})
2812
2813 " undo the last diffput
2814 call term_sendkeys(buf, "1\<c-w>w")
2815 call term_sendkeys(buf, "u")
2816
2817 " put from window 2 using dp line 8
2818 call term_sendkeys(buf, "2\<c-w>w")
2819 call term_sendkeys(buf, "8gg")
2820 call term_sendkeys(buf, ":diffput\<CR>")
2821 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_17', {})
2822
2823 " undo the last diffput
2824 call term_sendkeys(buf, "1\<c-w>w")
2825 call term_sendkeys(buf, "u")
2826
2827 " put from window 2 using dp line 9
2828 call term_sendkeys(buf, "2\<c-w>w")
2829 call term_sendkeys(buf, "9gg")
2830 call term_sendkeys(buf, ":diffput\<CR>")
2831 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_18', {})
2832
2833 " undo the last diffput
2834 call term_sendkeys(buf, "1\<c-w>w")
2835 call term_sendkeys(buf, "u")
2836
2837 " put from window 2 using dp line 17
2838 call term_sendkeys(buf, "2\<c-w>w")
2839 call term_sendkeys(buf, "17gg")
2840 call term_sendkeys(buf, ":diffput\<CR>")
2841 call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_19', {})
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()
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 " enable linematch
2855 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2856 call WriteDiffFiles(buf, ['// abc d?',
2857 \ '// d?',
2858 \ '// d?' ],
2859 \ ['!',
2860 \ 'abc d!',
2861 \ 'd!'])
2862 call VerifyScreenDump(buf, 'Test_linematch_diff1', {})
Jonathonca307ef2025-01-17 13:37:35 +01002863 " clean up
2864 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002865endfunc
2866
2867func Test_linematch_diff_iwhite()
2868 CheckScreendump
2869 call delete('.Xdifile1.swp')
2870 call delete('.Xdifile2.swp')
2871 call WriteDiffFiles(0, [], [])
2872 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2873 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2874
2875 " setup a diff with 2 files and set linematch:30, with ignore white
2876 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2877 call WriteDiffFiles(buf, ['void testFunction () {',
2878 \ ' for (int i = 0; i < 10; i++) {',
2879 \ ' for (int j = 0; j < 10; j++) {',
2880 \ ' }',
2881 \ ' }',
2882 \ '}' ],
2883 \ ['void testFunction () {',
2884 \ ' // for (int j = 0; j < 10; i++) {',
2885 \ ' // }',
2886 \ '}'])
2887 call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite1', {})
2888 call term_sendkeys(buf, ":set diffopt+=iwhiteall\<CR>")
2889 call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002890 " clean up
2891 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002892endfunc
2893
2894func Test_linematch_diff_grouping()
2895 CheckScreendump
2896 call delete('.Xdifile1.swp')
2897 call delete('.Xdifile2.swp')
2898 call WriteDiffFiles(0, [], [])
2899 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2900 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2901
2902 " a diff that would result in multiple groups before grouping optimization
2903 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2904 call WriteDiffFiles(buf, ['!A',
2905 \ '!B',
2906 \ '!C' ],
2907 \ ['?Z',
2908 \ '?A',
2909 \ '?B',
2910 \ '?C',
2911 \ '?A',
2912 \ '?B',
2913 \ '?B',
2914 \ '?C'])
2915 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping1', {})
2916 call WriteDiffFiles(buf, ['!A',
2917 \ '!B',
2918 \ '!C' ],
2919 \ ['?A',
2920 \ '?Z',
2921 \ '?B',
2922 \ '?C',
2923 \ '?A',
2924 \ '?B',
2925 \ '?C',
2926 \ '?C'])
2927 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002928 " clean up
2929 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002930endfunc
2931
2932func Test_linematch_diff_scroll()
2933 CheckScreendump
2934 call delete('.Xdifile1.swp')
2935 call delete('.Xdifile2.swp')
2936 call WriteDiffFiles(0, [], [])
2937 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2938 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2939
2940 " a diff that would result in multiple groups before grouping optimization
2941 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
2942 call WriteDiffFiles(buf, ['!A',
2943 \ '!B',
2944 \ '!C' ],
2945 \ ['?A',
2946 \ '?Z',
2947 \ '?B',
2948 \ '?C',
2949 \ '?A',
2950 \ '?B',
2951 \ '?C',
2952 \ '?C'])
2953 " scroll down to show calculation of top fill and scroll to correct line in
2954 " both windows
2955 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll0', {})
2956 call term_sendkeys(buf, "3\<c-e>")
2957 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll1', {})
2958 call term_sendkeys(buf, "3\<c-e>")
2959 call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll2', {})
Jonathonca307ef2025-01-17 13:37:35 +01002960 " clean up
2961 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01002962endfunc
2963
Jonathon7c7a4e62025-01-12 09:58:00 +01002964func Test_linematch_line_limit_exceeded()
2965 CheckScreendump
2966 call delete('.Xdifile1.swp')
2967 call delete('.Xdifile2.swp')
2968 call WriteDiffFiles(0, [], [])
2969 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
2970 call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
2971
2972 call term_sendkeys(buf, ":set diffopt+=linematch:10\<CR>")
2973 " a diff block will not be aligned with linematch because it's contents
2974 " exceed 10 lines
2975 call WriteDiffFiles(buf,
2976 \ ['common line',
2977 \ 'HIL',
2978 \ '',
2979 \ 'aABCabc',
2980 \ 'aABCabc',
2981 \ 'aABCabc',
2982 \ 'aABCabc',
2983 \ 'common line',
2984 \ 'HIL',
2985 \ 'common line',
2986 \ 'something'],
2987 \ ['common line',
2988 \ 'DEF',
2989 \ 'GHI',
2990 \ 'something',
2991 \ '',
2992 \ 'aDEFabc',
2993 \ 'xyz',
2994 \ 'xyz',
2995 \ 'xyz',
2996 \ 'aDEFabc',
2997 \ 'aDEFabc',
2998 \ 'aDEFabc',
2999 \ 'common line',
3000 \ 'DEF',
3001 \ 'GHI',
3002 \ 'something else',
3003 \ 'common line',
3004 \ 'something'])
3005 call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded1', {})
3006 " after increasing the count to 30, the limit is not exceeded, and the
3007 " alignment algorithm will run on the largest diff block here
3008 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
3009 call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded2', {})
Jonathonca307ef2025-01-17 13:37:35 +01003010 " clean up
3011 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01003012endfunc
3013
3014func Test_linematch_3diffs()
3015 CheckScreendump
3016 call delete('.Xdifile1.swp')
3017 call delete('.Xdifile2.swp')
3018 call delete('.Xdifile3.swp')
3019 call WriteDiffFiles3(0, [], [], [])
3020 let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
3021 call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
3022 call term_sendkeys(buf, "2\<c-w>w:set autoread\<CR>")
3023 call term_sendkeys(buf, "3\<c-w>w:set autoread\<CR>")
3024 call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
3025 call WriteDiffFiles3(buf,
3026 \ ["",
3027 \ " common line",
3028 \ " AAA",
3029 \ " AAA",
3030 \ " AAA"],
3031 \ ["",
3032 \ " common line",
3033 \ " <<<<<<< HEAD",
3034 \ " AAA",
3035 \ " AAA",
3036 \ " AAA",
3037 \ " =======",
3038 \ " BBB",
3039 \ " BBB",
3040 \ " BBB",
3041 \ " >>>>>>> branch1"],
3042 \ ["",
3043 \ " common line",
3044 \ " BBB",
3045 \ " BBB",
3046 \ " BBB"])
3047 call VerifyScreenDump(buf, 'Test_linematch_3diffs1', {})
Jonathonca307ef2025-01-17 13:37:35 +01003048 " clean up
3049 call StopVimInTerminal(buf)
3050endfunc
Jonathon7c7a4e62025-01-12 09:58:00 +01003051
Jonathonca307ef2025-01-17 13:37:35 +01003052" this used to access invalid memory
3053func Test_linematch_3diffs_sanity_check()
3054 CheckScreendump
3055 call delete('.Xfile_linematch1.swp')
3056 call delete('.Xfile_linematch2.swp')
3057 call delete('.Xfile_linematch3.swp')
3058 let lines =<< trim END
3059 set diffopt+=linematch:60
3060 call feedkeys("Aq\<esc>")
3061 call feedkeys("GAklm\<esc>")
3062 call feedkeys("o")
3063 END
3064 call writefile(lines, 'Xlinematch_3diffs.vim', 'D')
3065 call writefile(['abcd', 'def', 'hij'], 'Xfile_linematch1', 'D')
3066 call writefile(['defq', 'hijk', 'nopq'], 'Xfile_linematch2', 'D')
3067 call writefile(['hijklm', 'nopqr', 'stuv'], 'Xfile_linematch3', 'D')
3068 call WriteDiffFiles3(0, [], [], [])
3069 let buf = RunVimInTerminal('-d -S Xlinematch_3diffs.vim Xfile_linematch1 Xfile_linematch2 Xfile_linematch3', {})
3070 call VerifyScreenDump(buf, 'Test_linematch_3diffs2', {})
3071
3072 " clean up
3073 call StopVimInTerminal(buf)
Jonathon7c7a4e62025-01-12 09:58:00 +01003074endfunc
Bram Moolenaar8dfcce32020-03-18 19:32:26 +01003075" vim: shiftwidth=2 sts=2 expandtab