static int diff_busy = FALSE; /* ex_diffgetput() is busy */
/* flags obtained from the 'diffopt' option */
-#define DIFF_FILLER 1 // display filler lines
-#define DIFF_ICASE 2 // ignore case
-#define DIFF_IWHITE 4 // ignore change in white space
-#define DIFF_HORIZONTAL 8 // horizontal splits
-#define DIFF_VERTICAL 16 // vertical splits
-#define DIFF_HIDDEN_OFF 32 // diffoff when hidden
-#define DIFF_INTERNAL 64 // use internal xdiff algorithm
+#define DIFF_FILLER 0x001 // display filler lines
+#define DIFF_IBLANK 0x002 // ignore empty lines
+#define DIFF_ICASE 0x004 // ignore case
+#define DIFF_IWHITE 0x008 // ignore change in white space
+#define DIFF_IWHITEALL 0x010 // ignore all white space changes
+#define DIFF_IWHITEEOL 0x020 // ignore change in white space at EOL
+#define DIFF_HORIZONTAL 0x040 // horizontal splits
+#define DIFF_VERTICAL 0x080 // vertical splits
+#define DIFF_HIDDEN_OFF 0x100 // diffoff when hidden
+#define DIFF_INTERNAL 0x200 // use internal xdiff algorithm
+#define ALL_WHITE_DIFF (DIFF_IWHITE | DIFF_IWHITEALL | DIFF_IWHITEEOL)
static int diff_flags = DIFF_INTERNAL | DIFF_FILLER;
static long diff_algorithm = 0;
if (diff_flags & DIFF_IWHITE)
param.flags |= XDF_IGNORE_WHITESPACE_CHANGE;
+ if (diff_flags & DIFF_IWHITEALL)
+ param.flags |= XDF_IGNORE_WHITESPACE;
+ if (diff_flags & DIFF_IWHITEEOL)
+ param.flags |= XDF_IGNORE_WHITESPACE_AT_EOL;
+ if (diff_flags & DIFF_IBLANK)
+ param.flags |= XDF_IGNORE_BLANK_LINES;
emit_cfg.ctxlen = 0; // don't need any diff_context here
emit_cb.priv = &diffio->dio_diff;
// Build the diff command and execute it. Always use -a, binary
// differences are of no use. Ignore errors, diff returns
// non-zero when differences have been found.
- vim_snprintf((char *)cmd, len, "diff %s%s%s%s%s %s",
+ vim_snprintf((char *)cmd, len, "diff %s%s%s%s%s%s%s%s %s",
diff_a_works == FALSE ? "" : "-a ",
#if defined(MSWIN)
diff_bin_works == TRUE ? "--binary " : "",
"",
#endif
(diff_flags & DIFF_IWHITE) ? "-b " : "",
+ (diff_flags & DIFF_IWHITEALL) ? "-w " : "",
+ (diff_flags & DIFF_IWHITEEOL) ? "-Z " : "",
+ (diff_flags & DIFF_IBLANK) ? "-B " : "",
(diff_flags & DIFF_ICASE) ? "-i " : "",
tmp_orig, tmp_new);
append_redir(cmd, (int)len, p_srr, tmp_diff);
char_u *p1, *p2;
int l;
- if ((diff_flags & (DIFF_ICASE | DIFF_IWHITE)) == 0)
+ if ((diff_flags & DIFF_IBLANK)
+ && (*skipwhite(s1) == NUL || *skipwhite(s2) == NUL))
+ return 0;
+
+ if ((diff_flags & (DIFF_ICASE | ALL_WHITE_DIFF)) == 0)
return STRCMP(s1, s2);
- if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE))
+ if ((diff_flags & DIFF_ICASE) && !(diff_flags & ALL_WHITE_DIFF))
return MB_STRICMP(s1, s2);
- /* Ignore white space changes and possibly ignore case. */
p1 = s1;
p2 = s2;
+
+ // Ignore white space changes and possibly ignore case.
while (*p1 != NUL && *p2 != NUL)
{
- if (VIM_ISWHITE(*p1) && VIM_ISWHITE(*p2))
+ if (((diff_flags & DIFF_IWHITE)
+ && VIM_ISWHITE(*p1) && VIM_ISWHITE(*p2))
+ || ((diff_flags & DIFF_IWHITEALL)
+ && (VIM_ISWHITE(*p1) || VIM_ISWHITE(*p2))))
{
p1 = skipwhite(p1);
p2 = skipwhite(p2);
}
}
- /* Ignore trailing white space. */
+ // Ignore trailing white space.
p1 = skipwhite(p1);
p2 = skipwhite(p2);
if (*p1 != NUL || *p2 != NUL)
p += 8;
diff_context_new = getdigits(&p);
}
+ else if (STRNCMP(p, "iblank", 6) == 0)
+ {
+ p += 6;
+ diff_flags_new |= DIFF_IBLANK;
+ }
else if (STRNCMP(p, "icase", 5) == 0)
{
p += 5;
diff_flags_new |= DIFF_ICASE;
}
+ else if (STRNCMP(p, "iwhiteall", 9) == 0)
+ {
+ p += 9;
+ diff_flags_new |= DIFF_IWHITEALL;
+ }
+ else if (STRNCMP(p, "iwhiteeol", 9) == 0)
+ {
+ p += 9;
+ diff_flags_new |= DIFF_IWHITEEOL;
+ }
else if (STRNCMP(p, "iwhite", 6) == 0)
{
p += 6;
si_org = si_new = 0;
while (line_org[si_org] != NUL)
{
- if ((diff_flags & DIFF_IWHITE)
- && VIM_ISWHITE(line_org[si_org])
- && VIM_ISWHITE(line_new[si_new]))
+ if (((diff_flags & DIFF_IWHITE)
+ && VIM_ISWHITE(line_org[si_org])
+ && VIM_ISWHITE(line_new[si_new]))
+ || ((diff_flags & DIFF_IWHITEALL)
+ && (VIM_ISWHITE(line_org[si_org])
+ || VIM_ISWHITE(line_new[si_new]))))
{
si_org = (int)(skipwhite(line_org + si_org) - line_org);
si_new = (int)(skipwhite(line_new + si_new) - line_new);
while (ei_org >= *startp && ei_new >= si_new
&& ei_org >= 0 && ei_new >= 0)
{
- if ((diff_flags & DIFF_IWHITE)
- && VIM_ISWHITE(line_org[ei_org])
- && VIM_ISWHITE(line_new[ei_new]))
+ if (((diff_flags & DIFF_IWHITE)
+ && VIM_ISWHITE(line_org[ei_org])
+ && VIM_ISWHITE(line_new[ei_new]))
+ || ((diff_flags & DIFF_IWHITEALL)
+ && (VIM_ISWHITE(line_org[ei_org])
+ || VIM_ISWHITE(line_new[ei_new]))))
{
while (ei_org >= *startp
&& VIM_ISWHITE(line_org[ei_org]))
bwipe!
endfunc
-func WriteDiffFiles(list1, list2)
+func WriteDiffFiles(buf, list1, list2)
call writefile(a:list1, 'Xfile1')
call writefile(a:list2, 'Xfile2')
+ if a:buf
+ call term_sendkeys(a:buf, ":checktime\<CR>")
+ endif
endfunc
-" Verify a screendump with both the external and external diff.
+" Verify a screendump with both the internal and external diff.
func VerifyBoth(buf, dumpfile, extra)
- call term_sendkeys(a:buf, ":diffupdate!\<cr>")
" trailing : for leaving the cursor on the command line
- for cmd in [":set diffopt=filler" . a:extra . "\<cr>:", ":set diffopt+=internal\<cr>:"]
+ for cmd in [":set diffopt=filler" . a:extra . "\<CR>:", ":set diffopt+=internal\<CR>:"]
call term_sendkeys(a:buf, cmd)
if VerifyScreenDump(a:buf, a:dumpfile, {}, cmd =~ 'internal' ? 'internal' : 'external')
break " don't let the next iteration overwrite the "failed" file.
endfor
endfunc
+" Verify a screendump with the internal diff only.
+func VerifyInternal(buf, dumpfile, extra)
+ call term_sendkeys(a:buf, ":diffupdate!\<CR>")
+ " trailing : for leaving the cursor on the command line
+ call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:")
+ call VerifyScreenDump(a:buf, a:dumpfile, {})
+endfunc
+
func Test_diff_screen()
if !CanRunVimInTerminal() || !has('menu')
return
call delete('.Xfile2.swp')
" Test 1: Add a line in beginning of file 2
- call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+ call WriteDiffFiles(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
let buf = RunVimInTerminal('-d Xfile1 Xfile2', {})
" Set autoread mode, ,so that Vim won't complain once we re-write the test
" files
- call term_sendkeys(buf, ":set autoread\<cr>\<c-w>w:set autoread\<cr>\<c-w>w")
+ call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
call VerifyBoth(buf, 'Test_diff_01', '')
" Test 2: Add a line in beginning of file 1
- call WriteDiffFiles([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+ call WriteDiffFiles(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
call VerifyBoth(buf, 'Test_diff_02', '')
" Test 3: Add a line at the end of file 2
- call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
+ call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
call VerifyBoth(buf, 'Test_diff_03', '')
" Test 4: Add a line at the end of file 1
- call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+ call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
call VerifyBoth(buf, 'Test_diff_04', '')
" Test 5: Add a line in the middle of file 2, remove on at the end of file 1
- call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10])
+ 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])
call VerifyBoth(buf, 'Test_diff_05', '')
" Test 6: Add a line in the middle of file 1, remove on at the end of file 2
- call WriteDiffFiles([1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
+ 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])
call VerifyBoth(buf, 'Test_diff_06', '')
" Test 7 - 9: Test normal/patience/histogram diff algorithm
- call WriteDiffFiles(['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
+ call WriteDiffFiles(buf, ['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
\ ' int i;', ' for(i = 0; i < 10; i++)', ' {', ' printf("Your answer is: ");',
\ ' printf("%d\n", foo);', ' }', '}', '', 'int fact(int n)', '{', ' if(n > 1)', ' {',
\ ' return fact(n-1) * n;', ' }', ' return 1;', '}', '', 'int main(int argc, char **argv)',
" Test 10-11: normal/indent-heuristic
call term_sendkeys(buf, ":set diffopt&vim\<cr>")
- call WriteDiffFiles(['', ' def finalize(values)', '', ' values.each do |v|', ' v.finalize', ' end'],
+ call WriteDiffFiles(buf, ['', ' def finalize(values)', '', ' values.each do |v|', ' v.finalize', ' end'],
\ ['', ' def finalize(values)', '', ' values.each do |v|', ' v.prepare', ' end', '',
\ ' values.each do |v|', ' v.finalize', ' end'])
call term_sendkeys(buf, ":diffupdate!\<cr>")
call VerifyScreenDump(buf, 'Test_diff_11', {})
" Test 12: diff the same file
- call WriteDiffFiles([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+ call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
call VerifyBoth(buf, 'Test_diff_12', '')
" Test 13: diff an empty file
- call WriteDiffFiles([], [])
+ call WriteDiffFiles(buf, [], [])
call VerifyBoth(buf, 'Test_diff_13', '')
" Test 14: test diffopt+=icase
- call WriteDiffFiles(['a', 'b', 'cd'], ['A', 'b', 'cDe'])
+ call WriteDiffFiles(buf, ['a', 'b', 'cd'], ['A', 'b', 'cDe'])
call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase")
" Test 15-16: test diffopt+=iwhite
- call WriteDiffFiles(['int main()', '{', ' printf("Hello, World!");', ' return 0;', '}'],
+ call WriteDiffFiles(buf, ['int main()', '{', ' printf("Hello, World!");', ' return 0;', '}'],
\ ['int main()', '{', ' if (0)', ' {', ' printf("Hello, World!");', ' return 0;', ' }', '}'])
call term_sendkeys(buf, ":diffupdate!\<cr>")
call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>")
call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
call VerifyScreenDump(buf, 'Test_diff_16', {})
+ " Test 17: test diffopt+=iblank
+ call WriteDiffFiles(buf, ['a', ' ', 'cd', 'ef', 'xxx'], ['a', 'cd', '', 'ef', 'yyy'])
+ call VerifyInternal(buf, 'Test_diff_17', " diffopt+=iblank")
+
+ " Test 18: test diffopt+=iblank,iwhite / iwhiteall / iwhiteeol
+ call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhite")
+ call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteall")
+ call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteeol")
+
+ " Test 19: test diffopt+=iwhiteeol
+ call WriteDiffFiles(buf, ['a ', 'x', 'cd', 'ef', 'xx xx', 'foo', 'bar'], ['a', 'x', 'c d', ' ef', 'xx xx', 'foo', '', 'bar'])
+ call VerifyInternal(buf, 'Test_diff_19', " diffopt+=iwhiteeol")
+
+ " Test 19: test diffopt+=iwhiteall
+ call VerifyInternal(buf, 'Test_diff_20', " diffopt+=iwhiteall")
+
" clean up
call StopVimInTerminal(buf)
call delete('Xfile1')