Fossil SCM

Side-by-side diff coloration now appears to be technically correct, though further improves are needed to optimize for human perception, and for performance.

drh 2021-08-28 00:13 diff-color-enhancements
Commit 6ed7541472c4052c5df6894f51e1fc00825fd9cea2368224b6935e9e95386a1f
1 file changed +9 -24
+9 -24
--- src/diff.c
+++ src/diff.c
@@ -596,11 +596,11 @@
596596
int i; /* Number of input characters consumed */
597597
int k; /* Cursor position */
598598
int needEndSpan = 0;
599599
const char *zIn = pLine->z;
600600
int w = p->width;
601
- int colorize = p->escHtml;
601
+ int colorize = p->escHtml && p->n>0;
602602
if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
603603
colorize = 0;
604604
}
605605
for(i=k=0; (p->escHtml || k<w) && i<n; i++, k++){
606606
char c = zIn[i];
@@ -614,12 +614,11 @@
614614
needEndSpan = 0;
615615
if( p->n>1 ){
616616
p->n--;
617617
memmove(p->a, p->a+1, sizeof(p->a[0])*p->n);
618618
}else{
619
- p->a[0].iStart = -1;
620
- p->a[0].iEnd = -1;
619
+ colorize = 0;
621620
}
622621
}
623622
}
624623
if( c=='\t' && !p->escHtml ){
625624
blob_append(pCol, " ", 1);
@@ -721,20 +720,15 @@
721720
const unsigned char *zA = (const unsigned char*)zLeft; /* left string */
722721
const unsigned char *zB = (const unsigned char*)zRight; /* right string */
723722
int i, j, k; /* Loop counters */
724723
int lenBest = 0; /* Match length to beat */
725724
726
-#if 0
727
- printf("testLCS(\"%.*s\",\"%.*s\") = ",
728
- nA, zLeft, nB, zRight);
729
-#endif
730
-
731725
for(i=0; i<nA-lenBest; i++){
732726
unsigned char cA = zA[i];
733727
for(j=0; j<nB-lenBest; j++ ){
734728
if( zB[j]==cA ){
735
- for(k=1; j+k<nB && zB[j+k]==zA[i+k]; k++){}
729
+ for(k=1; j+k<nB && i+k<nA && zB[j+k]==zA[i+k]; k++){}
736730
if( k>lenBest ){
737731
lenBest = k;
738732
aLCS[0] = i;
739733
aLCS[1] = i+k;
740734
aLCS[2] = j;
@@ -741,23 +735,10 @@
741735
aLCS[3] = j+k;
742736
}
743737
}
744738
}
745739
}
746
-#if 0
747
- if( lenBest<=0 ){
748
- printf("no-match\n");
749
- }else{
750
- printf(" %d,%d,%d,%d\n", aLCS[0], aLCS[1], aLCS[2], aLCS[3]);
751
- printf("%*s%.*s", 9+aLCS[0], "", aLCS[1]-aLCS[0],
752
- "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
753
- printf("%*s%.*s\n", nA-aLCS[1]+3+aLCS[2], "", aLCS[3]-aLCS[2],
754
- "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
755
- }
756
- fflush(stdout);
757
-#endif
758
-
759740
return lenBest>0;
760741
}
761742
762743
/*
763744
** Find the smallest spans that different between two text strings that
@@ -985,11 +966,11 @@
985966
int i, j;
986967
sbsWriteLineno(p, lnLeft, SBS_LNA);
987968
for(i=j=0; i<CSpan.n; i++){
988969
if( CSpan.a[i].iLen1==0 ) continue;
989970
p->a[j].iStart = nPrefix + CSpan.a[i].iStart1;
990
- p->a[j].iEnd = p->a[i].iStart + CSpan.a[i].iLen1;
971
+ p->a[j].iEnd = p->a[j].iStart + CSpan.a[i].iLen1;
991972
if( CSpan.a[i].iLen2==0 ){
992973
if( i==0 ) sbsShiftLeft(p, zLeft);
993974
p->a[j].zTag = zClassRm;
994975
}else{
995976
p->a[j].zTag = zClassChng;
@@ -1002,11 +983,11 @@
1002983
sbsWriteMarker(p, " | ", "|");
1003984
sbsWriteLineno(p, lnRight, SBS_LNB);
1004985
for(i=j=0; i<CSpan.n; i++){
1005986
if( CSpan.a[i].iLen2==0 ) continue;
1006987
p->a[j].iStart = nPrefix + CSpan.a[i].iStart2;
1007
- p->a[j].iEnd = p->a[i].iStart + CSpan.a[i].iLen2;
988
+ p->a[j].iEnd = p->a[j].iStart + CSpan.a[i].iLen2;
1008989
if( CSpan.a[i].iLen1==0 ){
1009990
if( i==0 ) sbsShiftLeft(p, zRight);
1010991
p->a[j].zTag = zClassAdd;
1011992
}else{
1012993
p->a[j].zTag = zClassChng;
@@ -1026,11 +1007,14 @@
10261007
p->a[0].zTag = zClassChng;
10271008
p->n = 1;
10281009
sbsWriteText(p, pLeft, SBS_TXTA);
10291010
sbsWriteMarker(p, " | ", "|");
10301011
sbsWriteLineno(p, lnRight, SBS_LNB);
1012
+ p->a[0].iStart = nPrefix;
10311013
p->a[0].iEnd = nRight - nSuffix;
1014
+ p->a[0].zTag = zClassChng;
1015
+ p->n = 1;
10321016
sbsWriteText(p, pRight, SBS_TXTB);
10331017
}
10341018
10351019
/*
10361020
** Minimum of two values
@@ -1302,10 +1286,11 @@
13021286
}
13031287
s.pRe = pRe;
13041288
s.a[0].iStart = -1;
13051289
s.a[1].iStart = 0;
13061290
s.a[0].iEnd = -1;
1291
+ s.n = 0;
13071292
A = p->aFrom;
13081293
B = p->aTo;
13091294
R = p->aEdit;
13101295
mxr = p->nEdit;
13111296
while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
13121297
--- src/diff.c
+++ src/diff.c
@@ -596,11 +596,11 @@
596 int i; /* Number of input characters consumed */
597 int k; /* Cursor position */
598 int needEndSpan = 0;
599 const char *zIn = pLine->z;
600 int w = p->width;
601 int colorize = p->escHtml;
602 if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
603 colorize = 0;
604 }
605 for(i=k=0; (p->escHtml || k<w) && i<n; i++, k++){
606 char c = zIn[i];
@@ -614,12 +614,11 @@
614 needEndSpan = 0;
615 if( p->n>1 ){
616 p->n--;
617 memmove(p->a, p->a+1, sizeof(p->a[0])*p->n);
618 }else{
619 p->a[0].iStart = -1;
620 p->a[0].iEnd = -1;
621 }
622 }
623 }
624 if( c=='\t' && !p->escHtml ){
625 blob_append(pCol, " ", 1);
@@ -721,20 +720,15 @@
721 const unsigned char *zA = (const unsigned char*)zLeft; /* left string */
722 const unsigned char *zB = (const unsigned char*)zRight; /* right string */
723 int i, j, k; /* Loop counters */
724 int lenBest = 0; /* Match length to beat */
725
726 #if 0
727 printf("testLCS(\"%.*s\",\"%.*s\") = ",
728 nA, zLeft, nB, zRight);
729 #endif
730
731 for(i=0; i<nA-lenBest; i++){
732 unsigned char cA = zA[i];
733 for(j=0; j<nB-lenBest; j++ ){
734 if( zB[j]==cA ){
735 for(k=1; j+k<nB && zB[j+k]==zA[i+k]; k++){}
736 if( k>lenBest ){
737 lenBest = k;
738 aLCS[0] = i;
739 aLCS[1] = i+k;
740 aLCS[2] = j;
@@ -741,23 +735,10 @@
741 aLCS[3] = j+k;
742 }
743 }
744 }
745 }
746 #if 0
747 if( lenBest<=0 ){
748 printf("no-match\n");
749 }else{
750 printf(" %d,%d,%d,%d\n", aLCS[0], aLCS[1], aLCS[2], aLCS[3]);
751 printf("%*s%.*s", 9+aLCS[0], "", aLCS[1]-aLCS[0],
752 "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
753 printf("%*s%.*s\n", nA-aLCS[1]+3+aLCS[2], "", aLCS[3]-aLCS[2],
754 "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
755 }
756 fflush(stdout);
757 #endif
758
759 return lenBest>0;
760 }
761
762 /*
763 ** Find the smallest spans that different between two text strings that
@@ -985,11 +966,11 @@
985 int i, j;
986 sbsWriteLineno(p, lnLeft, SBS_LNA);
987 for(i=j=0; i<CSpan.n; i++){
988 if( CSpan.a[i].iLen1==0 ) continue;
989 p->a[j].iStart = nPrefix + CSpan.a[i].iStart1;
990 p->a[j].iEnd = p->a[i].iStart + CSpan.a[i].iLen1;
991 if( CSpan.a[i].iLen2==0 ){
992 if( i==0 ) sbsShiftLeft(p, zLeft);
993 p->a[j].zTag = zClassRm;
994 }else{
995 p->a[j].zTag = zClassChng;
@@ -1002,11 +983,11 @@
1002 sbsWriteMarker(p, " | ", "|");
1003 sbsWriteLineno(p, lnRight, SBS_LNB);
1004 for(i=j=0; i<CSpan.n; i++){
1005 if( CSpan.a[i].iLen2==0 ) continue;
1006 p->a[j].iStart = nPrefix + CSpan.a[i].iStart2;
1007 p->a[j].iEnd = p->a[i].iStart + CSpan.a[i].iLen2;
1008 if( CSpan.a[i].iLen1==0 ){
1009 if( i==0 ) sbsShiftLeft(p, zRight);
1010 p->a[j].zTag = zClassAdd;
1011 }else{
1012 p->a[j].zTag = zClassChng;
@@ -1026,11 +1007,14 @@
1026 p->a[0].zTag = zClassChng;
1027 p->n = 1;
1028 sbsWriteText(p, pLeft, SBS_TXTA);
1029 sbsWriteMarker(p, " | ", "|");
1030 sbsWriteLineno(p, lnRight, SBS_LNB);
 
1031 p->a[0].iEnd = nRight - nSuffix;
 
 
1032 sbsWriteText(p, pRight, SBS_TXTB);
1033 }
1034
1035 /*
1036 ** Minimum of two values
@@ -1302,10 +1286,11 @@
1302 }
1303 s.pRe = pRe;
1304 s.a[0].iStart = -1;
1305 s.a[1].iStart = 0;
1306 s.a[0].iEnd = -1;
 
1307 A = p->aFrom;
1308 B = p->aTo;
1309 R = p->aEdit;
1310 mxr = p->nEdit;
1311 while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
1312
--- src/diff.c
+++ src/diff.c
@@ -596,11 +596,11 @@
596 int i; /* Number of input characters consumed */
597 int k; /* Cursor position */
598 int needEndSpan = 0;
599 const char *zIn = pLine->z;
600 int w = p->width;
601 int colorize = p->escHtml && p->n>0;
602 if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
603 colorize = 0;
604 }
605 for(i=k=0; (p->escHtml || k<w) && i<n; i++, k++){
606 char c = zIn[i];
@@ -614,12 +614,11 @@
614 needEndSpan = 0;
615 if( p->n>1 ){
616 p->n--;
617 memmove(p->a, p->a+1, sizeof(p->a[0])*p->n);
618 }else{
619 colorize = 0;
 
620 }
621 }
622 }
623 if( c=='\t' && !p->escHtml ){
624 blob_append(pCol, " ", 1);
@@ -721,20 +720,15 @@
720 const unsigned char *zA = (const unsigned char*)zLeft; /* left string */
721 const unsigned char *zB = (const unsigned char*)zRight; /* right string */
722 int i, j, k; /* Loop counters */
723 int lenBest = 0; /* Match length to beat */
724
 
 
 
 
 
725 for(i=0; i<nA-lenBest; i++){
726 unsigned char cA = zA[i];
727 for(j=0; j<nB-lenBest; j++ ){
728 if( zB[j]==cA ){
729 for(k=1; j+k<nB && i+k<nA && zB[j+k]==zA[i+k]; k++){}
730 if( k>lenBest ){
731 lenBest = k;
732 aLCS[0] = i;
733 aLCS[1] = i+k;
734 aLCS[2] = j;
@@ -741,23 +735,10 @@
735 aLCS[3] = j+k;
736 }
737 }
738 }
739 }
 
 
 
 
 
 
 
 
 
 
 
 
 
740 return lenBest>0;
741 }
742
743 /*
744 ** Find the smallest spans that different between two text strings that
@@ -985,11 +966,11 @@
966 int i, j;
967 sbsWriteLineno(p, lnLeft, SBS_LNA);
968 for(i=j=0; i<CSpan.n; i++){
969 if( CSpan.a[i].iLen1==0 ) continue;
970 p->a[j].iStart = nPrefix + CSpan.a[i].iStart1;
971 p->a[j].iEnd = p->a[j].iStart + CSpan.a[i].iLen1;
972 if( CSpan.a[i].iLen2==0 ){
973 if( i==0 ) sbsShiftLeft(p, zLeft);
974 p->a[j].zTag = zClassRm;
975 }else{
976 p->a[j].zTag = zClassChng;
@@ -1002,11 +983,11 @@
983 sbsWriteMarker(p, " | ", "|");
984 sbsWriteLineno(p, lnRight, SBS_LNB);
985 for(i=j=0; i<CSpan.n; i++){
986 if( CSpan.a[i].iLen2==0 ) continue;
987 p->a[j].iStart = nPrefix + CSpan.a[i].iStart2;
988 p->a[j].iEnd = p->a[j].iStart + CSpan.a[i].iLen2;
989 if( CSpan.a[i].iLen1==0 ){
990 if( i==0 ) sbsShiftLeft(p, zRight);
991 p->a[j].zTag = zClassAdd;
992 }else{
993 p->a[j].zTag = zClassChng;
@@ -1026,11 +1007,14 @@
1007 p->a[0].zTag = zClassChng;
1008 p->n = 1;
1009 sbsWriteText(p, pLeft, SBS_TXTA);
1010 sbsWriteMarker(p, " | ", "|");
1011 sbsWriteLineno(p, lnRight, SBS_LNB);
1012 p->a[0].iStart = nPrefix;
1013 p->a[0].iEnd = nRight - nSuffix;
1014 p->a[0].zTag = zClassChng;
1015 p->n = 1;
1016 sbsWriteText(p, pRight, SBS_TXTB);
1017 }
1018
1019 /*
1020 ** Minimum of two values
@@ -1302,10 +1286,11 @@
1286 }
1287 s.pRe = pRe;
1288 s.a[0].iStart = -1;
1289 s.a[1].iStart = 0;
1290 s.a[0].iEnd = -1;
1291 s.n = 0;
1292 A = p->aFrom;
1293 B = p->aTo;
1294 R = p->aEdit;
1295 mxr = p->nEdit;
1296 while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
1297

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button