Fossil SCM

If unable to get good alignment between two diff block, try merging the current diff block with the subsequent diff block, if it is nearby.

drh 2021-09-04 16:51 diff-color-enhancements
Commit 45c91a66701d5fc8d864e75211e8d4f69ec7e88fc07b939c156c2c14a1b4f6d8
1 file changed +28
+28
--- src/diff.c
+++ src/diff.c
@@ -913,10 +913,14 @@
913913
**
914914
** 1. Delete the next line of pLeft.
915915
** 2. Insert the next line of pRight.
916916
** 3. The next line of pLeft changes into the next line of pRight.
917917
** 4. Delete one line from pLeft and add one line to pRight.
918
+**
919
+** The (4) case only happens when we cannot get a reasonable alignment between
920
+** the two blocks. If any return value is (4), then all return values will
921
+** be (4).
918922
**
919923
** Algorithm: Wagner's minimum edit-distance algorithm, modified by
920924
** adding a cost to each match based on how well the two rows match
921925
** each other. Insertion and deletion costs are 50. Match costs
922926
** are between 0 and 100 where 0 is a perfect match 100 is a complete
@@ -1855,10 +1859,20 @@
18551859
p->width = diff_width(diffFlags);
18561860
p->pOut = pOut;
18571861
return p;
18581862
}
18591863
/****************************************************************************/
1864
+
1865
+/*
1866
+** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a
1867
+** pair of adjacent differences. Return true if the gap between these
1868
+** two differences is so small that they should be rendered as a single
1869
+** edit.
1870
+*/
1871
+static int smallGap(const int *R){
1872
+ return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8;
1873
+}
18601874
18611875
/*
18621876
** Format a diff using a DiffBuilder object
18631877
*/
18641878
static void formatDiff(
@@ -1961,11 +1975,25 @@
19611975
for(i=0; i<nr; i++){
19621976
unsigned char *alignment;
19631977
ma = R[r+i*3+1]; /* Lines on left but not on right */
19641978
mb = R[r+i*3+2]; /* Lines on right but not on left */
19651979
1980
+ /* Try to find an alignment for the lines within this one block */
19661981
alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags);
1982
+
1983
+ /* If we could not get a good alignment, try merging the current
1984
+ ** block with subsequent blocks, if the subsequent blocks are
1985
+ ** nearby */
1986
+ while( alignment[0]==4 && i<nr-1 && smallGap(&R[r+i*3]) ){
1987
+ i++;
1988
+ m = R[r+i*3];
1989
+ ma += R[r+i*3+1] + m;
1990
+ mb += R[r+i*3+2] + m;
1991
+ fossil_free(alignment);
1992
+ alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags);
1993
+ }
1994
+
19671995
for(j=0; ma+mb>0; j++){
19681996
switch( alignment[j] ){
19691997
case 1: {
19701998
/* Delete one line from the left */
19711999
pBuilder->xDelete(pBuilder, &A[a]);
19722000
--- src/diff.c
+++ src/diff.c
@@ -913,10 +913,14 @@
913 **
914 ** 1. Delete the next line of pLeft.
915 ** 2. Insert the next line of pRight.
916 ** 3. The next line of pLeft changes into the next line of pRight.
917 ** 4. Delete one line from pLeft and add one line to pRight.
 
 
 
 
918 **
919 ** Algorithm: Wagner's minimum edit-distance algorithm, modified by
920 ** adding a cost to each match based on how well the two rows match
921 ** each other. Insertion and deletion costs are 50. Match costs
922 ** are between 0 and 100 where 0 is a perfect match 100 is a complete
@@ -1855,10 +1859,20 @@
1855 p->width = diff_width(diffFlags);
1856 p->pOut = pOut;
1857 return p;
1858 }
1859 /****************************************************************************/
 
 
 
 
 
 
 
 
 
 
1860
1861 /*
1862 ** Format a diff using a DiffBuilder object
1863 */
1864 static void formatDiff(
@@ -1961,11 +1975,25 @@
1961 for(i=0; i<nr; i++){
1962 unsigned char *alignment;
1963 ma = R[r+i*3+1]; /* Lines on left but not on right */
1964 mb = R[r+i*3+2]; /* Lines on right but not on left */
1965
 
1966 alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags);
 
 
 
 
 
 
 
 
 
 
 
 
 
1967 for(j=0; ma+mb>0; j++){
1968 switch( alignment[j] ){
1969 case 1: {
1970 /* Delete one line from the left */
1971 pBuilder->xDelete(pBuilder, &A[a]);
1972
--- src/diff.c
+++ src/diff.c
@@ -913,10 +913,14 @@
913 **
914 ** 1. Delete the next line of pLeft.
915 ** 2. Insert the next line of pRight.
916 ** 3. The next line of pLeft changes into the next line of pRight.
917 ** 4. Delete one line from pLeft and add one line to pRight.
918 **
919 ** The (4) case only happens when we cannot get a reasonable alignment between
920 ** the two blocks. If any return value is (4), then all return values will
921 ** be (4).
922 **
923 ** Algorithm: Wagner's minimum edit-distance algorithm, modified by
924 ** adding a cost to each match based on how well the two rows match
925 ** each other. Insertion and deletion costs are 50. Match costs
926 ** are between 0 and 100 where 0 is a perfect match 100 is a complete
@@ -1855,10 +1859,20 @@
1859 p->width = diff_width(diffFlags);
1860 p->pOut = pOut;
1861 return p;
1862 }
1863 /****************************************************************************/
1864
1865 /*
1866 ** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a
1867 ** pair of adjacent differences. Return true if the gap between these
1868 ** two differences is so small that they should be rendered as a single
1869 ** edit.
1870 */
1871 static int smallGap(const int *R){
1872 return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8;
1873 }
1874
1875 /*
1876 ** Format a diff using a DiffBuilder object
1877 */
1878 static void formatDiff(
@@ -1961,11 +1975,25 @@
1975 for(i=0; i<nr; i++){
1976 unsigned char *alignment;
1977 ma = R[r+i*3+1]; /* Lines on left but not on right */
1978 mb = R[r+i*3+2]; /* Lines on right but not on left */
1979
1980 /* Try to find an alignment for the lines within this one block */
1981 alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags);
1982
1983 /* If we could not get a good alignment, try merging the current
1984 ** block with subsequent blocks, if the subsequent blocks are
1985 ** nearby */
1986 while( alignment[0]==4 && i<nr-1 && smallGap(&R[r+i*3]) ){
1987 i++;
1988 m = R[r+i*3];
1989 ma += R[r+i*3+1] + m;
1990 mb += R[r+i*3+2] + m;
1991 fossil_free(alignment);
1992 alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags);
1993 }
1994
1995 for(j=0; ma+mb>0; j++){
1996 switch( alignment[j] ){
1997 case 1: {
1998 /* Delete one line from the left */
1999 pBuilder->xDelete(pBuilder, &A[a]);
2000

Keyboard Shortcuts

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