Fossil SCM
Add support for side-by-side diff from the command-line "diff" command.
Commit
ac81759f65abdc4bf28062380bbb4b41a0282eea
Parent
3bbbbdfd7d032f0…
2 files changed
+179
-6
+9
-3
+179
-6
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -25,14 +25,15 @@ | ||
| 25 | 25 | |
| 26 | 26 | #if INTERFACE |
| 27 | 27 | /* |
| 28 | 28 | ** Allowed flag parameters to the text_diff() and html_sbsdiff() funtions: |
| 29 | 29 | */ |
| 30 | -#define DIFF_CONTEXT_MASK 0x00fff /* Lines of context. Default if 0 */ | |
| 31 | -#define DIFF_IGNORE_EOLWS 0x01000 /* Ignore end-of-line whitespace */ | |
| 32 | -#define DIFF_SIDEBYSIDE 0x02000 /* Generate a side-by-side diff */ | |
| 33 | -#define DIFF_NEWFILE 0x04000 /* Non-existing files are as empty files */ | |
| 30 | +#define DIFF_CONTEXT_MASK 0x0000fff /* Lines of context. Default if 0 */ | |
| 31 | +#define DIFF_WIDTH_MASK 0x00ff000 /* side-by-side column width */ | |
| 32 | +#define DIFF_IGNORE_EOLWS 0x0100000 /* Ignore end-of-line whitespace */ | |
| 33 | +#define DIFF_SIDEBYSIDE 0x0200000 /* Generate a side-by-side diff */ | |
| 34 | +#define DIFF_NEWFILE 0x0400000 /* Missing files are as empty files */ | |
| 34 | 35 | |
| 35 | 36 | #endif /* INTERFACE */ |
| 36 | 37 | |
| 37 | 38 | /* |
| 38 | 39 | ** Maximum length of a line in a text file. (8192) |
| @@ -296,10 +297,176 @@ | ||
| 296 | 297 | for(j=0; j<m; j++){ |
| 297 | 298 | appendDiffLine(pOut, " ", &B[b+j]); |
| 298 | 299 | } |
| 299 | 300 | } |
| 300 | 301 | } |
| 302 | + | |
| 303 | +/* | |
| 304 | +** Append spaces to a blob | |
| 305 | +*/ | |
| 306 | +static void appendSpace(Blob *pOut, int n){ | |
| 307 | + const char z100[101] = | |
| 308 | + " " | |
| 309 | + " "; | |
| 310 | + while( n>100 ){ | |
| 311 | + blob_append(pOut, z100, 100); n -= 100; | |
| 312 | + } | |
| 313 | + if( n>0 ){ | |
| 314 | + blob_append(pOut, z100, n); | |
| 315 | + } | |
| 316 | +} | |
| 317 | + | |
| 318 | +/* | |
| 319 | +** Append text to a sbs diff output | |
| 320 | +*/ | |
| 321 | +static void appendSbsLine(Blob *pOut, DLine *pLine, int width, int pad){ | |
| 322 | + int sz = pLine->h & LENGTH_MASK; | |
| 323 | + if( sz<width ){ | |
| 324 | + blob_append(pOut, pLine->z, sz); | |
| 325 | + if( pad ) appendSpace(pOut, width-sz); | |
| 326 | + }else{ | |
| 327 | + blob_append(pOut, pLine->z, width); | |
| 328 | + } | |
| 329 | +} | |
| 330 | + | |
| 331 | + | |
| 332 | +/* | |
| 333 | +** Given a diff context in which the aEdit[] array has been filled | |
| 334 | +** in, compute a side-by-side diff into pOut. | |
| 335 | +*/ | |
| 336 | +static void sbsDiff(DContext *p, Blob *pOut, int nContext, int width){ | |
| 337 | + DLine *A; /* Left side of the diff */ | |
| 338 | + DLine *B; /* Right side of the diff */ | |
| 339 | + int a = 0; /* Index of next line in A[] */ | |
| 340 | + int b = 0; /* Index of next line in B[] */ | |
| 341 | + int *R; /* Array of COPY/DELETE/INSERT triples */ | |
| 342 | + int r; /* Index into R[] */ | |
| 343 | + int nr; /* Number of COPY/DELETE/INSERT triples to process */ | |
| 344 | + int mxr; /* Maximum value for r */ | |
| 345 | + int na, nb; /* Number of lines shown from A and B */ | |
| 346 | + int i, j; /* Loop counters */ | |
| 347 | + int m, ma, mb;/* Number of lines to output */ | |
| 348 | + int skip; /* Number of lines to skip */ | |
| 349 | + char zFormat[50]; /* Output format */ | |
| 350 | + | |
| 351 | + sqlite3_snprintf(sizeof(zFormat), zFormat, | |
| 352 | + "%%4d %%%d.%ds %%c %%4d %%.%ds\n", | |
| 353 | + width, width, width); | |
| 354 | + A = p->aFrom; | |
| 355 | + B = p->aTo; | |
| 356 | + R = p->aEdit; | |
| 357 | + mxr = p->nEdit; | |
| 358 | + while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } | |
| 359 | + for(r=0; r<mxr; r += 3*nr){ | |
| 360 | + /* Figure out how many triples to show in a single block */ | |
| 361 | + for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} | |
| 362 | + /* printf("r=%d nr=%d\n", r, nr); */ | |
| 363 | + | |
| 364 | + /* For the current block comprising nr triples, figure out | |
| 365 | + ** how many lines of A and B are to be displayed | |
| 366 | + */ | |
| 367 | + if( R[r]>nContext ){ | |
| 368 | + na = nb = nContext; | |
| 369 | + skip = R[r] - nContext; | |
| 370 | + }else{ | |
| 371 | + na = nb = R[r]; | |
| 372 | + skip = 0; | |
| 373 | + } | |
| 374 | + for(i=0; i<nr; i++){ | |
| 375 | + na += R[r+i*3+1]; | |
| 376 | + nb += R[r+i*3+2]; | |
| 377 | + } | |
| 378 | + if( R[r+nr*3]>nContext ){ | |
| 379 | + na += nContext; | |
| 380 | + nb += nContext; | |
| 381 | + }else{ | |
| 382 | + na += R[r+nr*3]; | |
| 383 | + nb += R[r+nr*3]; | |
| 384 | + } | |
| 385 | + for(i=1; i<nr; i++){ | |
| 386 | + na += R[r+i*3]; | |
| 387 | + nb += R[r+i*3]; | |
| 388 | + } | |
| 389 | + /* | |
| 390 | + * If the patch changes an empty file or results in an empty file, | |
| 391 | + * the block header must use 0,0 as position indicator and not 1,0. | |
| 392 | + * Otherwise, patch would be confused and may reject the diff. | |
| 393 | + */ | |
| 394 | + blob_appendf(pOut,"@@ -%d,%d +%d,%d @@\n", | |
| 395 | + na ? a+skip+1 : 0, na, | |
| 396 | + nb ? b+skip+1 : 0, nb); | |
| 397 | + | |
| 398 | + /* Show the initial common area */ | |
| 399 | + a += skip; | |
| 400 | + b += skip; | |
| 401 | + m = R[r] - skip; | |
| 402 | + for(j=0; j<m; j++){ | |
| 403 | + blob_appendf(pOut, "%6d ", a+j); | |
| 404 | + appendSbsLine(pOut, &A[a+j], width, 1); | |
| 405 | + blob_appendf(pOut, " %6d ", b+j); | |
| 406 | + appendSbsLine(pOut, &B[b+j], width, 0); | |
| 407 | + blob_append(pOut, "\n", 1); | |
| 408 | + } | |
| 409 | + a += m; | |
| 410 | + b += m; | |
| 411 | + | |
| 412 | + /* Show the differences */ | |
| 413 | + for(i=0; i<nr; i++){ | |
| 414 | + ma = R[r+i*3+1]; | |
| 415 | + mb = R[r+i*3+2]; | |
| 416 | + m = ma<mb ? ma : mb; | |
| 417 | + for(j=0; j<m; j++){ | |
| 418 | + blob_appendf(pOut, "%6d ", a+j); | |
| 419 | + appendSbsLine(pOut, &A[a+j], width, 1); | |
| 420 | + blob_appendf(pOut, " | %6d ", b+j); | |
| 421 | + appendSbsLine(pOut, &B[b+j], width, 0); | |
| 422 | + blob_append(pOut, "\n", 1); | |
| 423 | + } | |
| 424 | + a += m; | |
| 425 | + b += m; | |
| 426 | + ma -= m; | |
| 427 | + mb -= m; | |
| 428 | + for(j=0; j<ma; j++){ | |
| 429 | + blob_appendf(pOut, "%6d ", a+j); | |
| 430 | + appendSbsLine(pOut, &A[a+j], width, 1); | |
| 431 | + blob_append(pOut, " <\n", 3); | |
| 432 | + } | |
| 433 | + a += ma; | |
| 434 | + for(j=0; j<mb; j++){ | |
| 435 | + appendSpace(pOut, width+7); | |
| 436 | + blob_appendf(pOut, " > %6d", b+j); | |
| 437 | + appendSbsLine(pOut, &B[b+j], width, 0); | |
| 438 | + blob_append(pOut, "\n", 1); | |
| 439 | + } | |
| 440 | + b += mb; | |
| 441 | + if( i<nr-1 ){ | |
| 442 | + m = R[r+i*3+3]; | |
| 443 | + for(j=0; j<m; j++){ | |
| 444 | + blob_appendf(pOut, "%6d ", a+j); | |
| 445 | + appendSbsLine(pOut, &A[a+j], width, 1); | |
| 446 | + blob_appendf(pOut, " %6d ", b+j); | |
| 447 | + appendSbsLine(pOut, &B[b+j], width, 0); | |
| 448 | + blob_append(pOut, "\n", 1); | |
| 449 | + } | |
| 450 | + b += m; | |
| 451 | + a += m; | |
| 452 | + } | |
| 453 | + } | |
| 454 | + | |
| 455 | + /* Show the final common area */ | |
| 456 | + assert( nr==i ); | |
| 457 | + m = R[r+nr*3]; | |
| 458 | + if( m>nContext ) m = nContext; | |
| 459 | + for(j=0; j<m; j++){ | |
| 460 | + blob_appendf(pOut, "%6d ", a+j); | |
| 461 | + appendSbsLine(pOut, &A[a+j], width, 1); | |
| 462 | + blob_appendf(pOut, " %6d ", b+j); | |
| 463 | + appendSbsLine(pOut, &B[b+j], width, 0); | |
| 464 | + blob_append(pOut, "\n", 1); | |
| 465 | + } | |
| 466 | + } | |
| 467 | +} | |
| 301 | 468 | |
| 302 | 469 | /* |
| 303 | 470 | ** Compute the optimal longest common subsequence (LCS) using an |
| 304 | 471 | ** exhaustive search. This version of the LCS is only used for |
| 305 | 472 | ** shorter input strings since runtime is O(N*N) where N is the |
| @@ -579,12 +746,18 @@ | ||
| 579 | 746 | |
| 580 | 747 | /* Compute the difference */ |
| 581 | 748 | diff_all(&c); |
| 582 | 749 | |
| 583 | 750 | if( pOut ){ |
| 584 | - /* Compute a context diff if requested */ | |
| 585 | - contextDiff(&c, pOut, nContext); | |
| 751 | + /* Compute a context or side-by-side diff into pOut */ | |
| 752 | + if( diffFlags & DIFF_SIDEBYSIDE ){ | |
| 753 | + int width = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1); | |
| 754 | + if( width==0 ) width = 80; | |
| 755 | + sbsDiff(&c, pOut, nContext, width); | |
| 756 | + }else{ | |
| 757 | + contextDiff(&c, pOut, nContext); | |
| 758 | + } | |
| 586 | 759 | free(c.aFrom); |
| 587 | 760 | free(c.aTo); |
| 588 | 761 | free(c.aEdit); |
| 589 | 762 | return 0; |
| 590 | 763 | }else{ |
| 591 | 764 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -25,14 +25,15 @@ | |
| 25 | |
| 26 | #if INTERFACE |
| 27 | /* |
| 28 | ** Allowed flag parameters to the text_diff() and html_sbsdiff() funtions: |
| 29 | */ |
| 30 | #define DIFF_CONTEXT_MASK 0x00fff /* Lines of context. Default if 0 */ |
| 31 | #define DIFF_IGNORE_EOLWS 0x01000 /* Ignore end-of-line whitespace */ |
| 32 | #define DIFF_SIDEBYSIDE 0x02000 /* Generate a side-by-side diff */ |
| 33 | #define DIFF_NEWFILE 0x04000 /* Non-existing files are as empty files */ |
| 34 | |
| 35 | #endif /* INTERFACE */ |
| 36 | |
| 37 | /* |
| 38 | ** Maximum length of a line in a text file. (8192) |
| @@ -296,10 +297,176 @@ | |
| 296 | for(j=0; j<m; j++){ |
| 297 | appendDiffLine(pOut, " ", &B[b+j]); |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | /* |
| 303 | ** Compute the optimal longest common subsequence (LCS) using an |
| 304 | ** exhaustive search. This version of the LCS is only used for |
| 305 | ** shorter input strings since runtime is O(N*N) where N is the |
| @@ -579,12 +746,18 @@ | |
| 579 | |
| 580 | /* Compute the difference */ |
| 581 | diff_all(&c); |
| 582 | |
| 583 | if( pOut ){ |
| 584 | /* Compute a context diff if requested */ |
| 585 | contextDiff(&c, pOut, nContext); |
| 586 | free(c.aFrom); |
| 587 | free(c.aTo); |
| 588 | free(c.aEdit); |
| 589 | return 0; |
| 590 | }else{ |
| 591 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -25,14 +25,15 @@ | |
| 25 | |
| 26 | #if INTERFACE |
| 27 | /* |
| 28 | ** Allowed flag parameters to the text_diff() and html_sbsdiff() funtions: |
| 29 | */ |
| 30 | #define DIFF_CONTEXT_MASK 0x0000fff /* Lines of context. Default if 0 */ |
| 31 | #define DIFF_WIDTH_MASK 0x00ff000 /* side-by-side column width */ |
| 32 | #define DIFF_IGNORE_EOLWS 0x0100000 /* Ignore end-of-line whitespace */ |
| 33 | #define DIFF_SIDEBYSIDE 0x0200000 /* Generate a side-by-side diff */ |
| 34 | #define DIFF_NEWFILE 0x0400000 /* Missing files are as empty files */ |
| 35 | |
| 36 | #endif /* INTERFACE */ |
| 37 | |
| 38 | /* |
| 39 | ** Maximum length of a line in a text file. (8192) |
| @@ -296,10 +297,176 @@ | |
| 297 | for(j=0; j<m; j++){ |
| 298 | appendDiffLine(pOut, " ", &B[b+j]); |
| 299 | } |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | /* |
| 304 | ** Append spaces to a blob |
| 305 | */ |
| 306 | static void appendSpace(Blob *pOut, int n){ |
| 307 | const char z100[101] = |
| 308 | " " |
| 309 | " "; |
| 310 | while( n>100 ){ |
| 311 | blob_append(pOut, z100, 100); n -= 100; |
| 312 | } |
| 313 | if( n>0 ){ |
| 314 | blob_append(pOut, z100, n); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | /* |
| 319 | ** Append text to a sbs diff output |
| 320 | */ |
| 321 | static void appendSbsLine(Blob *pOut, DLine *pLine, int width, int pad){ |
| 322 | int sz = pLine->h & LENGTH_MASK; |
| 323 | if( sz<width ){ |
| 324 | blob_append(pOut, pLine->z, sz); |
| 325 | if( pad ) appendSpace(pOut, width-sz); |
| 326 | }else{ |
| 327 | blob_append(pOut, pLine->z, width); |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | |
| 332 | /* |
| 333 | ** Given a diff context in which the aEdit[] array has been filled |
| 334 | ** in, compute a side-by-side diff into pOut. |
| 335 | */ |
| 336 | static void sbsDiff(DContext *p, Blob *pOut, int nContext, int width){ |
| 337 | DLine *A; /* Left side of the diff */ |
| 338 | DLine *B; /* Right side of the diff */ |
| 339 | int a = 0; /* Index of next line in A[] */ |
| 340 | int b = 0; /* Index of next line in B[] */ |
| 341 | int *R; /* Array of COPY/DELETE/INSERT triples */ |
| 342 | int r; /* Index into R[] */ |
| 343 | int nr; /* Number of COPY/DELETE/INSERT triples to process */ |
| 344 | int mxr; /* Maximum value for r */ |
| 345 | int na, nb; /* Number of lines shown from A and B */ |
| 346 | int i, j; /* Loop counters */ |
| 347 | int m, ma, mb;/* Number of lines to output */ |
| 348 | int skip; /* Number of lines to skip */ |
| 349 | char zFormat[50]; /* Output format */ |
| 350 | |
| 351 | sqlite3_snprintf(sizeof(zFormat), zFormat, |
| 352 | "%%4d %%%d.%ds %%c %%4d %%.%ds\n", |
| 353 | width, width, width); |
| 354 | A = p->aFrom; |
| 355 | B = p->aTo; |
| 356 | R = p->aEdit; |
| 357 | mxr = p->nEdit; |
| 358 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| 359 | for(r=0; r<mxr; r += 3*nr){ |
| 360 | /* Figure out how many triples to show in a single block */ |
| 361 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 362 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 363 | |
| 364 | /* For the current block comprising nr triples, figure out |
| 365 | ** how many lines of A and B are to be displayed |
| 366 | */ |
| 367 | if( R[r]>nContext ){ |
| 368 | na = nb = nContext; |
| 369 | skip = R[r] - nContext; |
| 370 | }else{ |
| 371 | na = nb = R[r]; |
| 372 | skip = 0; |
| 373 | } |
| 374 | for(i=0; i<nr; i++){ |
| 375 | na += R[r+i*3+1]; |
| 376 | nb += R[r+i*3+2]; |
| 377 | } |
| 378 | if( R[r+nr*3]>nContext ){ |
| 379 | na += nContext; |
| 380 | nb += nContext; |
| 381 | }else{ |
| 382 | na += R[r+nr*3]; |
| 383 | nb += R[r+nr*3]; |
| 384 | } |
| 385 | for(i=1; i<nr; i++){ |
| 386 | na += R[r+i*3]; |
| 387 | nb += R[r+i*3]; |
| 388 | } |
| 389 | /* |
| 390 | * If the patch changes an empty file or results in an empty file, |
| 391 | * the block header must use 0,0 as position indicator and not 1,0. |
| 392 | * Otherwise, patch would be confused and may reject the diff. |
| 393 | */ |
| 394 | blob_appendf(pOut,"@@ -%d,%d +%d,%d @@\n", |
| 395 | na ? a+skip+1 : 0, na, |
| 396 | nb ? b+skip+1 : 0, nb); |
| 397 | |
| 398 | /* Show the initial common area */ |
| 399 | a += skip; |
| 400 | b += skip; |
| 401 | m = R[r] - skip; |
| 402 | for(j=0; j<m; j++){ |
| 403 | blob_appendf(pOut, "%6d ", a+j); |
| 404 | appendSbsLine(pOut, &A[a+j], width, 1); |
| 405 | blob_appendf(pOut, " %6d ", b+j); |
| 406 | appendSbsLine(pOut, &B[b+j], width, 0); |
| 407 | blob_append(pOut, "\n", 1); |
| 408 | } |
| 409 | a += m; |
| 410 | b += m; |
| 411 | |
| 412 | /* Show the differences */ |
| 413 | for(i=0; i<nr; i++){ |
| 414 | ma = R[r+i*3+1]; |
| 415 | mb = R[r+i*3+2]; |
| 416 | m = ma<mb ? ma : mb; |
| 417 | for(j=0; j<m; j++){ |
| 418 | blob_appendf(pOut, "%6d ", a+j); |
| 419 | appendSbsLine(pOut, &A[a+j], width, 1); |
| 420 | blob_appendf(pOut, " | %6d ", b+j); |
| 421 | appendSbsLine(pOut, &B[b+j], width, 0); |
| 422 | blob_append(pOut, "\n", 1); |
| 423 | } |
| 424 | a += m; |
| 425 | b += m; |
| 426 | ma -= m; |
| 427 | mb -= m; |
| 428 | for(j=0; j<ma; j++){ |
| 429 | blob_appendf(pOut, "%6d ", a+j); |
| 430 | appendSbsLine(pOut, &A[a+j], width, 1); |
| 431 | blob_append(pOut, " <\n", 3); |
| 432 | } |
| 433 | a += ma; |
| 434 | for(j=0; j<mb; j++){ |
| 435 | appendSpace(pOut, width+7); |
| 436 | blob_appendf(pOut, " > %6d", b+j); |
| 437 | appendSbsLine(pOut, &B[b+j], width, 0); |
| 438 | blob_append(pOut, "\n", 1); |
| 439 | } |
| 440 | b += mb; |
| 441 | if( i<nr-1 ){ |
| 442 | m = R[r+i*3+3]; |
| 443 | for(j=0; j<m; j++){ |
| 444 | blob_appendf(pOut, "%6d ", a+j); |
| 445 | appendSbsLine(pOut, &A[a+j], width, 1); |
| 446 | blob_appendf(pOut, " %6d ", b+j); |
| 447 | appendSbsLine(pOut, &B[b+j], width, 0); |
| 448 | blob_append(pOut, "\n", 1); |
| 449 | } |
| 450 | b += m; |
| 451 | a += m; |
| 452 | } |
| 453 | } |
| 454 | |
| 455 | /* Show the final common area */ |
| 456 | assert( nr==i ); |
| 457 | m = R[r+nr*3]; |
| 458 | if( m>nContext ) m = nContext; |
| 459 | for(j=0; j<m; j++){ |
| 460 | blob_appendf(pOut, "%6d ", a+j); |
| 461 | appendSbsLine(pOut, &A[a+j], width, 1); |
| 462 | blob_appendf(pOut, " %6d ", b+j); |
| 463 | appendSbsLine(pOut, &B[b+j], width, 0); |
| 464 | blob_append(pOut, "\n", 1); |
| 465 | } |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | /* |
| 470 | ** Compute the optimal longest common subsequence (LCS) using an |
| 471 | ** exhaustive search. This version of the LCS is only used for |
| 472 | ** shorter input strings since runtime is O(N*N) where N is the |
| @@ -579,12 +746,18 @@ | |
| 746 | |
| 747 | /* Compute the difference */ |
| 748 | diff_all(&c); |
| 749 | |
| 750 | if( pOut ){ |
| 751 | /* Compute a context or side-by-side diff into pOut */ |
| 752 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 753 | int width = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1); |
| 754 | if( width==0 ) width = 80; |
| 755 | sbsDiff(&c, pOut, nContext, width); |
| 756 | }else{ |
| 757 | contextDiff(&c, pOut, nContext); |
| 758 | } |
| 759 | free(c.aFrom); |
| 760 | free(c.aTo); |
| 761 | free(c.aEdit); |
| 762 | return 0; |
| 763 | }else{ |
| 764 |
+9
-3
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -447,16 +447,17 @@ | ||
| 447 | 447 | ** |
| 448 | 448 | ** The "-N" or "--new-file" option causes the complete text of added or |
| 449 | 449 | ** deleted files to be displayed. |
| 450 | 450 | ** |
| 451 | 451 | ** Options: |
| 452 | +** --context|-c N Use N lines of context | |
| 452 | 453 | ** --from|-r VERSION select VERSION as source for the diff |
| 453 | 454 | ** --new-file|-N output complete text of added or deleted files |
| 454 | 455 | ** -i use internal diff logic |
| 455 | 456 | ** --to VERSION select VERSION as target for the diff |
| 456 | -** --sbs side-by-side diff | |
| 457 | -** --context|-c N Use N lines of context | |
| 457 | +** --side-by-side|-y side-by-side diff | |
| 458 | +** --width|-W N Width of lines in side-by-side diff | |
| 458 | 459 | */ |
| 459 | 460 | void diff_cmd(void){ |
| 460 | 461 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 461 | 462 | int isInternDiff; /* True for internal diff */ |
| 462 | 463 | int hasNFlag; /* True if -N or --new-file flag is used */ |
| @@ -470,14 +471,19 @@ | ||
| 470 | 471 | isGDiff = g.argv[1][0]=='g'; |
| 471 | 472 | isInternDiff = find_option("internal","i",0)!=0; |
| 472 | 473 | zFrom = find_option("from", "r", 1); |
| 473 | 474 | zTo = find_option("to", 0, 1); |
| 474 | 475 | hasNFlag = find_option("new-file","N",0)!=0; |
| 475 | - if( find_option("sbs",0,0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; | |
| 476 | + if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; | |
| 476 | 477 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){ |
| 477 | 478 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 478 | 479 | diffFlags |= f; |
| 480 | + } | |
| 481 | + if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ | |
| 482 | + f *= DIFF_CONTEXT_MASK+1; | |
| 483 | + if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; | |
| 484 | + diffFlags |= f; | |
| 479 | 485 | } |
| 480 | 486 | |
| 481 | 487 | |
| 482 | 488 | if( hasNFlag ) diffFlags |= DIFF_NEWFILE; |
| 483 | 489 | if( zTo==0 ){ |
| 484 | 490 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -447,16 +447,17 @@ | |
| 447 | ** |
| 448 | ** The "-N" or "--new-file" option causes the complete text of added or |
| 449 | ** deleted files to be displayed. |
| 450 | ** |
| 451 | ** Options: |
| 452 | ** --from|-r VERSION select VERSION as source for the diff |
| 453 | ** --new-file|-N output complete text of added or deleted files |
| 454 | ** -i use internal diff logic |
| 455 | ** --to VERSION select VERSION as target for the diff |
| 456 | ** --sbs side-by-side diff |
| 457 | ** --context|-c N Use N lines of context |
| 458 | */ |
| 459 | void diff_cmd(void){ |
| 460 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 461 | int isInternDiff; /* True for internal diff */ |
| 462 | int hasNFlag; /* True if -N or --new-file flag is used */ |
| @@ -470,14 +471,19 @@ | |
| 470 | isGDiff = g.argv[1][0]=='g'; |
| 471 | isInternDiff = find_option("internal","i",0)!=0; |
| 472 | zFrom = find_option("from", "r", 1); |
| 473 | zTo = find_option("to", 0, 1); |
| 474 | hasNFlag = find_option("new-file","N",0)!=0; |
| 475 | if( find_option("sbs",0,0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 476 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){ |
| 477 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 478 | diffFlags |= f; |
| 479 | } |
| 480 | |
| 481 | |
| 482 | if( hasNFlag ) diffFlags |= DIFF_NEWFILE; |
| 483 | if( zTo==0 ){ |
| 484 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -447,16 +447,17 @@ | |
| 447 | ** |
| 448 | ** The "-N" or "--new-file" option causes the complete text of added or |
| 449 | ** deleted files to be displayed. |
| 450 | ** |
| 451 | ** Options: |
| 452 | ** --context|-c N Use N lines of context |
| 453 | ** --from|-r VERSION select VERSION as source for the diff |
| 454 | ** --new-file|-N output complete text of added or deleted files |
| 455 | ** -i use internal diff logic |
| 456 | ** --to VERSION select VERSION as target for the diff |
| 457 | ** --side-by-side|-y side-by-side diff |
| 458 | ** --width|-W N Width of lines in side-by-side diff |
| 459 | */ |
| 460 | void diff_cmd(void){ |
| 461 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 462 | int isInternDiff; /* True for internal diff */ |
| 463 | int hasNFlag; /* True if -N or --new-file flag is used */ |
| @@ -470,14 +471,19 @@ | |
| 471 | isGDiff = g.argv[1][0]=='g'; |
| 472 | isInternDiff = find_option("internal","i",0)!=0; |
| 473 | zFrom = find_option("from", "r", 1); |
| 474 | zTo = find_option("to", 0, 1); |
| 475 | hasNFlag = find_option("new-file","N",0)!=0; |
| 476 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 477 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){ |
| 478 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 479 | diffFlags |= f; |
| 480 | } |
| 481 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 482 | f *= DIFF_CONTEXT_MASK+1; |
| 483 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 484 | diffFlags |= f; |
| 485 | } |
| 486 | |
| 487 | |
| 488 | if( hasNFlag ) diffFlags |= DIFF_NEWFILE; |
| 489 | if( zTo==0 ){ |
| 490 |