Fossil SCM

Improvements to side-by-side diff alignment.

drh 2012-10-26 02:35 trunk
Commit 511405f4268502ec1266935cd8f365bfe4d4965a
+24 -3
--- src/diff.c
+++ src/diff.c
@@ -69,11 +69,11 @@
6969
struct DLine {
7070
const char *z; /* The text of the line */
7171
unsigned int h; /* Hash of the line */
7272
unsigned int iNext; /* 1+(Index of next line with same the same hash) */
7373
74
- /* an array of DLine elements services two purposes. The fields
74
+ /* an array of DLine elements serves two purposes. The fields
7575
** above are one per line of input text. But each entry is also
7676
** a bucket in a hash table, as follows: */
7777
unsigned int iHash; /* 1+(first entry in the hash chain) */
7878
};
7979
@@ -260,11 +260,11 @@
260260
if( html ) blob_append(pOut, "</span>", -1);
261261
}
262262
263263
264264
/*
265
-** Given a diff context in which the aEdit[] array has been filled
265
+** Given a raw diff p[] in which the p->aEdit[] array has been filled
266266
** in, compute a context diff into pOut.
267267
*/
268268
static void contextDiff(
269269
DContext *p, /* The difference */
270270
Blob *pOut, /* Output a context diff to here */
@@ -643,11 +643,11 @@
643643
if( nPrefix+nSuffix==nLeft ){
644644
sbsWriteLineno(p, lnLeft);
645645
p->iStart2 = p->iEnd2 = 0;
646646
p->iStart = p->iEnd = -1;
647647
sbsWriteText(p, pLeft, SBS_PAD);
648
- sbsWrite(p, " | ", 3);
648
+ sbsWrite(p, nLeft==nRight ? " " : " | ", 3);
649649
sbsWriteLineno(p, lnRight);
650650
p->iStart = nPrefix;
651651
p->iEnd = nRight - nSuffix;
652652
p->zStart = zClassAdd;
653653
sbsWriteText(p, pRight, SBS_NEWLINE);
@@ -905,10 +905,20 @@
905905
906906
/* Return the result */
907907
fossil_free(pToFree);
908908
return aM;
909909
}
910
+
911
+/*
912
+** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a
913
+** pair of adjacent differences. Return true if the gap between these
914
+** two differences is so small that they should be rendered as a single
915
+** edit.
916
+*/
917
+static int smallGap(int *R){
918
+ return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8;
919
+}
910920
911921
/*
912922
** Given a diff context in which the aEdit[] array has been filled
913923
** in, compute a side-by-side diff into pOut.
914924
*/
@@ -1012,10 +1022,21 @@
10121022
/* Show the differences */
10131023
for(i=0; i<nr; i++){
10141024
unsigned char *alignment;
10151025
ma = R[r+i*3+1]; /* Lines on left but not on right */
10161026
mb = R[r+i*3+2]; /* Lines on right but not on left */
1027
+
1028
+ /* If the gap between the current diff and then next diff within the
1029
+ ** same block is not too great, then render them as if they are a
1030
+ ** single diff. */
1031
+ while( i<nr-1 && smallGap(&R[r+i*3]) ){
1032
+ i++;
1033
+ m = R[r+i*3];
1034
+ ma += R[r+i*3+1] + m;
1035
+ mb += R[r+i*3+2] + m;
1036
+ }
1037
+
10171038
alignment = sbsAlignment(&A[a], ma, &B[b], mb);
10181039
for(j=0; ma+mb>0; j++){
10191040
if( alignment[j]==1 ){
10201041
s.n = 0;
10211042
sbsWriteLineno(&s, a);
10221043
--- src/diff.c
+++ src/diff.c
@@ -69,11 +69,11 @@
69 struct DLine {
70 const char *z; /* The text of the line */
71 unsigned int h; /* Hash of the line */
72 unsigned int iNext; /* 1+(Index of next line with same the same hash) */
73
74 /* an array of DLine elements services two purposes. The fields
75 ** above are one per line of input text. But each entry is also
76 ** a bucket in a hash table, as follows: */
77 unsigned int iHash; /* 1+(first entry in the hash chain) */
78 };
79
@@ -260,11 +260,11 @@
260 if( html ) blob_append(pOut, "</span>", -1);
261 }
262
263
264 /*
265 ** Given a diff context in which the aEdit[] array has been filled
266 ** in, compute a context diff into pOut.
267 */
268 static void contextDiff(
269 DContext *p, /* The difference */
270 Blob *pOut, /* Output a context diff to here */
@@ -643,11 +643,11 @@
643 if( nPrefix+nSuffix==nLeft ){
644 sbsWriteLineno(p, lnLeft);
645 p->iStart2 = p->iEnd2 = 0;
646 p->iStart = p->iEnd = -1;
647 sbsWriteText(p, pLeft, SBS_PAD);
648 sbsWrite(p, " | ", 3);
649 sbsWriteLineno(p, lnRight);
650 p->iStart = nPrefix;
651 p->iEnd = nRight - nSuffix;
652 p->zStart = zClassAdd;
653 sbsWriteText(p, pRight, SBS_NEWLINE);
@@ -905,10 +905,20 @@
905
906 /* Return the result */
907 fossil_free(pToFree);
908 return aM;
909 }
 
 
 
 
 
 
 
 
 
 
910
911 /*
912 ** Given a diff context in which the aEdit[] array has been filled
913 ** in, compute a side-by-side diff into pOut.
914 */
@@ -1012,10 +1022,21 @@
1012 /* Show the differences */
1013 for(i=0; i<nr; i++){
1014 unsigned char *alignment;
1015 ma = R[r+i*3+1]; /* Lines on left but not on right */
1016 mb = R[r+i*3+2]; /* Lines on right but not on left */
 
 
 
 
 
 
 
 
 
 
 
1017 alignment = sbsAlignment(&A[a], ma, &B[b], mb);
1018 for(j=0; ma+mb>0; j++){
1019 if( alignment[j]==1 ){
1020 s.n = 0;
1021 sbsWriteLineno(&s, a);
1022
--- src/diff.c
+++ src/diff.c
@@ -69,11 +69,11 @@
69 struct DLine {
70 const char *z; /* The text of the line */
71 unsigned int h; /* Hash of the line */
72 unsigned int iNext; /* 1+(Index of next line with same the same hash) */
73
74 /* an array of DLine elements serves two purposes. The fields
75 ** above are one per line of input text. But each entry is also
76 ** a bucket in a hash table, as follows: */
77 unsigned int iHash; /* 1+(first entry in the hash chain) */
78 };
79
@@ -260,11 +260,11 @@
260 if( html ) blob_append(pOut, "</span>", -1);
261 }
262
263
264 /*
265 ** Given a raw diff p[] in which the p->aEdit[] array has been filled
266 ** in, compute a context diff into pOut.
267 */
268 static void contextDiff(
269 DContext *p, /* The difference */
270 Blob *pOut, /* Output a context diff to here */
@@ -643,11 +643,11 @@
643 if( nPrefix+nSuffix==nLeft ){
644 sbsWriteLineno(p, lnLeft);
645 p->iStart2 = p->iEnd2 = 0;
646 p->iStart = p->iEnd = -1;
647 sbsWriteText(p, pLeft, SBS_PAD);
648 sbsWrite(p, nLeft==nRight ? " " : " | ", 3);
649 sbsWriteLineno(p, lnRight);
650 p->iStart = nPrefix;
651 p->iEnd = nRight - nSuffix;
652 p->zStart = zClassAdd;
653 sbsWriteText(p, pRight, SBS_NEWLINE);
@@ -905,10 +905,20 @@
905
906 /* Return the result */
907 fossil_free(pToFree);
908 return aM;
909 }
910
911 /*
912 ** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a
913 ** pair of adjacent differences. Return true if the gap between these
914 ** two differences is so small that they should be rendered as a single
915 ** edit.
916 */
917 static int smallGap(int *R){
918 return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8;
919 }
920
921 /*
922 ** Given a diff context in which the aEdit[] array has been filled
923 ** in, compute a side-by-side diff into pOut.
924 */
@@ -1012,10 +1022,21 @@
1022 /* Show the differences */
1023 for(i=0; i<nr; i++){
1024 unsigned char *alignment;
1025 ma = R[r+i*3+1]; /* Lines on left but not on right */
1026 mb = R[r+i*3+2]; /* Lines on right but not on left */
1027
1028 /* If the gap between the current diff and then next diff within the
1029 ** same block is not too great, then render them as if they are a
1030 ** single diff. */
1031 while( i<nr-1 && smallGap(&R[r+i*3]) ){
1032 i++;
1033 m = R[r+i*3];
1034 ma += R[r+i*3+1] + m;
1035 mb += R[r+i*3+2] + m;
1036 }
1037
1038 alignment = sbsAlignment(&A[a], ma, &B[b], mb);
1039 for(j=0; ma+mb>0; j++){
1040 if( alignment[j]==1 ){
1041 s.n = 0;
1042 sbsWriteLineno(&s, a);
1043
--- test/diff-test-1.wiki
+++ test/diff-test-1.wiki
@@ -21,5 +21,7 @@
2121
2222
External:
2323
2424
* <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
2525
Code indentation change.</a>
26
+ * <a href="http://www.sqlite.org/src/fdiff?v1=ab90126ee0163539&v2=a867cafae0235324#chunk1" target="testwindow">
27
+ A more difficult code indentation change.</a>
2628
--- test/diff-test-1.wiki
+++ test/diff-test-1.wiki
@@ -21,5 +21,7 @@
21
22 External:
23
24 * <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
25 Code indentation change.</a>
 
 
26
--- test/diff-test-1.wiki
+++ test/diff-test-1.wiki
@@ -21,5 +21,7 @@
21
22 External:
23
24 * <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
25 Code indentation change.</a>
26 * <a href="http://www.sqlite.org/src/fdiff?v1=ab90126ee0163539&v2=a867cafae0235324#chunk1" target="testwindow">
27 A more difficult code indentation change.</a>
28

Keyboard Shortcuts

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