Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | If the left/right alignment in side-by-side diff becomes too busy and hard for a human to read, then show it simplified: as inserting one side and then deleting the other. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
52db049b8922fae36577305a4ab8e211 |
| User & Date: | drh 2012-12-15 00:59:47.810 |
Context
|
2012-12-15
| ||
| 01:17 | More compact representation of a left/right rewrite on side-by-side diffs. ... (check-in: 233c4975a8 user: drh tags: trunk) | |
| 00:59 | If the left/right alignment in side-by-side diff becomes too busy and hard for a human to read, then show it simplified: as inserting one side and then deleting the other. ... (check-in: 52db049b89 user: drh tags: trunk) | |
|
2012-12-14
| ||
| 21:24 | Improvements to the side-by-side diff display for indentation changes with minor edits. ... (check-in: c4bbc4a9af user: drh tags: trunk) | |
Changes
Changes to src/diff.c.
| ︙ | ︙ | |||
1041 1042 1043 1044 1045 1046 1047 | ** converted into nRight lines of text on the right. This routine computes ** how the lines on the left line up with the lines on the right. ** ** The return value is a buffer of unsigned characters, obtained from ** fossil_malloc(). (The caller needs to free the return value using ** fossil_free().) Entries in the returned array have values as follows: ** | | > | < > > > > | | | | | | > | > > | > > > > > > > > > > > > > > > > | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 |
** converted into nRight lines of text on the right. This routine computes
** how the lines on the left line up with the lines on the right.
**
** The return value is a buffer of unsigned characters, obtained from
** fossil_malloc(). (The caller needs to free the return value using
** fossil_free().) Entries in the returned array have values as follows:
**
** 1. Delete the next line of pLeft.
** 2. Insert the next line of pRight.
** 3... The next line of pLeft changes into the next line of pRight.
**
** Values larger than three indicate better matches.
**
** The length of the returned array will be just large enough to cause
** all elements of pLeft and pRight to be consumed.
**
** Algorithm: Wagner's minimum edit-distance algorithm, modified by
** adding a cost to each match based on how well the two rows match
** each other. Insertion and deletion costs are 50. Match costs
** are between 0 and 100 where 0 is a perfect match 100 is a complete
** mismatch.
*/
static unsigned char *sbsAlignment(
DLine *aLeft, int nLeft, /* Text on the left */
DLine *aRight, int nRight /* Text on the right */
){
int i, j, k; /* Loop counters */
int *a; /* One row of the Wagner matrix */
int *pToFree; /* Space that needs to be freed */
unsigned char *aM; /* Wagner result matrix */
int nMatch, iMatch; /* Number of matching lines and match score */
int mnLen; /* MIN(nLeft, nRight) */
int aBuf[100]; /* Stack space for a[] if nRight not to big */
aM = fossil_malloc( (nLeft+1)*(nRight+1) );
if( nLeft==0 ){
memset(aM, 2, nRight);
return aM;
}
if( nRight==0 ){
memset(aM, 1, nLeft);
return aM;
}
/* This algorithm is O(N**2). So if N is too big, bail out with a
** simple (but stupid and ugly) result that doesn't take too long. */
if( nLeft*nRight>100000 ){
memset(aM, 2, nRight);
memset(aM+nRight, 1, nLeft);
return aM;
}
if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
pToFree = 0;
a = aBuf;
}else{
a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
}
/* Compute the best alignment */
for(i=0; i<=nRight; i++){
aM[i] = 2;
a[i] = i*50;
}
aM[0] = 0;
for(j=1; j<=nLeft; j++){
int p = a[0];
a[0] = p+50;
aM[j*(nRight+1)] = 1;
for(i=1; i<=nRight; i++){
int m = a[i-1]+50;
int d = 2;
if( m>a[i]+50 ){
m = a[i]+50;
d = 1;
}
if( m>p ){
int score = match_dline(&aLeft[j-1], &aRight[i-1]);
if( (score<=63 || (i<j+1 && i>j-1)) && m>p+score ){
m = p+score;
d = 3 | score*4;
}
}
p = a[i];
a[i] = m;
aM[j*(nRight+1)+i] = d;
}
}
/* Compute the lowest-cost path back through the matrix */
i = nRight;
j = nLeft;
k = (nRight+1)*(nLeft+1)-1;
nMatch = iMatch = 0;
while( i+j>0 ){
unsigned char c = aM[k--];
if( c>=3 ){
assert( i>0 && j>0 );
i--;
j--;
nMatch++;
iMatch += (c>>2);
}else if( c==2 ){
assert( i>0 );
i--;
}else{
assert( j>0 );
j--;
}
aM[k] = aM[j*(nRight+1)+i];
}
k++;
i = (nRight+1)*(nLeft+1) - k;
memmove(aM, &aM[k], i);
/* If:
** (1) the alignment is more than 25% longer than the longest side, and
** (2) the average match cost exceeds 15
** Then this is probably an alignment that will be difficult for humans
** to read. So instead, just show all of the right side inserted followed
** by all of the left side deleted.
**
** The coefficients for conditions (1) and (2) above are determined by
** experimentation.
*/
mnLen = nLeft>nRight ? nLeft : nRight;
if( i*4>mnLen*5 && (nMatch==0 || iMatch/nMatch>15) ){
memset(aM, 2, nRight);
memset(aM+nRight, 1, nLeft);
}
/* Return the result */
fossil_free(pToFree);
return aM;
}
/*
|
| ︙ | ︙ | |||
1292 1293 1294 1295 1296 1297 1298 |
}else{
sbsWrite(&s, " <\n", 3);
}
blob_append(pOut, s.zLine, s.n);
assert( ma>0 );
ma--;
a++;
| | | 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 |
}else{
sbsWrite(&s, " <\n", 3);
}
blob_append(pOut, s.zLine, s.n);
assert( ma>0 );
ma--;
a++;
}else if( alignment[j]>=3 ){
s.n = 0;
sbsWriteLineChange(&s, &A[a], a, &B[b], b);
blob_append(pOut, s.zLine, s.n);
assert( ma>0 && mb>0 );
ma--;
mb--;
a++;
|
| ︙ | ︙ |
Changes to test/diff-test-1.wiki.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 |
* <a href="../../../info/bda00cbada#chunk42" target="testwindow">
A difficult indentation change.
External:
* <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
Code indentation change.</a>
| > > > > > > > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
* <a href="../../../info/bda00cbada#chunk42" target="testwindow">
A difficult indentation change.
External:
* <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow">
Code indentation change.</a>
* <a href="http://www.sqlite.org/src/info/52e755943f">
A complex change (chunk 1) in which the alignment becomes so complex
that it is better for clarity to abandon it and just show the left
and right sides contiguously.</a>
* <a href="http://www.sqlite.org/src/info/3d65c70343#chunk5">
An indentation change. See especially lines 2313 and 2317 on the right,
that their green indentation addition is left-justified.</a>
|