Fossil SCM

Add the --tk option to "fossil diff" in order to launch a Tcl/Tk GUI display of colorized side-by-side diffs.

drh 2012-09-26 12:55 trunk
Commit 22e5d711e50de36f1023b0ce8c9f11617a2179ab
2 files changed +73 +1 -1
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -473,10 +473,78 @@
473473
zDefault = 0;
474474
zName = "diff-command";
475475
}
476476
return db_get(zName, zDefault);
477477
}
478
+
479
+/* A Tcl/Tk script used to render diff output.
480
+*/
481
+static const char zDiffScript[] =
482
+@ wm withdraw .
483
+@ wm title . {Fossil Diff}
484
+@ wm iconname . {Fossil Diff}
485
+@ set body {}
486
+@ set mx 80 ;# Length of the longest line of text
487
+@ set nLine 0 ;# Number of lines of text
488
+@ text .t -width 180 -yscroll {.sb set}
489
+@ if {$tcl_platform(platform)=="windows"} {.t config -font {courier 9}}
490
+@ .t tag config ln -foreground gray
491
+@ .t tag config chng -background {#d0d0ff}
492
+@ .t tag config add -background {#c0ffc0}
493
+@ .t tag config rm -background {#ffc0c0}
494
+@ proc dehtml {x} {return [string map {&amp; & &lt; < &gt; >} $x]}
495
+@ set in [open $cmd r]
496
+@ while {![eof $in]} {
497
+@ set line [gets $in]
498
+@ if {[regexp {^<a name="chunk.*"></a>} $line]} continue
499
+@ if {[regexp {^===} $line]} {
500
+@ set n [string length $line]
501
+@ if {$n>$mx} {set mx $n}
502
+@ }
503
+@ incr nLine
504
+@ while {[regexp {^(.*?)<span class="diff([a-z]+)">(.*?)</span>(.*)$} $line \
505
+@ all pre class mid tail]} {
506
+@ .t insert end [dehtml $pre] {} [dehtml $mid] $class
507
+@ set line $tail
508
+@ }
509
+@ .t insert end [dehtml $line]\n {}
510
+@ }
511
+@ close $in
512
+@ if {$mx>250} {set mx 250} ;# Limit window width to 200 lines
513
+@ if {$nLine>55} {set nLine 55} ;# Limit window height to 55 lines
514
+@ .t config -height $nLine -width $mx
515
+@ pack .t -side left -fill both -expand 1
516
+@ scrollbar .sb -command {.t yview} -orient vertical
517
+@ pack .sb -side left -fill y
518
+@ wm deiconify .
519
+;
520
+
521
+/*
522
+** Show diff output in a Tcl/Tk window, in response to the --tk option
523
+** to the diff command.
524
+**
525
+** Steps:
526
+** (1) Write the Tcl/Tk script used for rendering into a temp file.
527
+** (2) Invoke "wish" on the temp file using fossil_system().
528
+** (3) Delete the temp file.
529
+*/
530
+static void diff_tk(void){
531
+ int i;
532
+ Blob script;
533
+ char *zTempFile;
534
+ char *zCmd;
535
+ blob_zero(&script);
536
+ blob_appendf(&script, "set cmd {| \"%s\" diff --html -y", g.argv[0]);
537
+ for(i=2; i<g.argc; i++){
538
+ blob_appendf(&script, " \"%s\"", g.argv[i]);
539
+ }
540
+ blob_appendf(&script, "}\n%s", zDiffScript);
541
+ zTempFile = write_blob_to_temp_file(&script);
542
+ zCmd = mprintf("wish \"%s\"", zTempFile);
543
+ fossil_system(zCmd);
544
+ file_delete(zTempFile);
545
+}
478546
479547
/*
480548
** COMMAND: diff
481549
** COMMAND: gdiff
482550
**
@@ -509,10 +577,11 @@
509577
** --brief Show filenames only
510578
** --context|-c N Use N lines of context
511579
** --from|-r VERSION select VERSION as source for the diff
512580
** -i use internal diff logic
513581
** --new-file|-N output complete text of added or deleted files
582
+** --tk Launch a Tcl/Tk GUI for display
514583
** --to VERSION select VERSION as target for the diff
515584
** --side-by-side|-y side-by-side diff
516585
** --width|-W N Width of lines in side-by-side diff
517586
*/
518587
void diff_cmd(void){
@@ -524,10 +593,14 @@
524593
const char *zBranch; /* Branch to diff */
525594
const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */
526595
u64 diffFlags = 0; /* Flags to control the DIFF */
527596
int f;
528597
598
+ if( find_option("tk",0,0)!=0 ){
599
+ diff_tk();
600
+ return;
601
+ }
529602
isGDiff = g.argv[1][0]=='g';
530603
isInternDiff = find_option("internal","i",0)!=0;
531604
zFrom = find_option("from", "r", 1);
532605
zTo = find_option("to", 0, 1);
533606
zBranch = find_option("branch", 0, 1);
534607
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -473,10 +473,78 @@
473 zDefault = 0;
474 zName = "diff-command";
475 }
476 return db_get(zName, zDefault);
477 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
479 /*
480 ** COMMAND: diff
481 ** COMMAND: gdiff
482 **
@@ -509,10 +577,11 @@
509 ** --brief Show filenames only
510 ** --context|-c N Use N lines of context
511 ** --from|-r VERSION select VERSION as source for the diff
512 ** -i use internal diff logic
513 ** --new-file|-N output complete text of added or deleted files
 
514 ** --to VERSION select VERSION as target for the diff
515 ** --side-by-side|-y side-by-side diff
516 ** --width|-W N Width of lines in side-by-side diff
517 */
518 void diff_cmd(void){
@@ -524,10 +593,14 @@
524 const char *zBranch; /* Branch to diff */
525 const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */
526 u64 diffFlags = 0; /* Flags to control the DIFF */
527 int f;
528
 
 
 
 
529 isGDiff = g.argv[1][0]=='g';
530 isInternDiff = find_option("internal","i",0)!=0;
531 zFrom = find_option("from", "r", 1);
532 zTo = find_option("to", 0, 1);
533 zBranch = find_option("branch", 0, 1);
534
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -473,10 +473,78 @@
473 zDefault = 0;
474 zName = "diff-command";
475 }
476 return db_get(zName, zDefault);
477 }
478
479 /* A Tcl/Tk script used to render diff output.
480 */
481 static const char zDiffScript[] =
482 @ wm withdraw .
483 @ wm title . {Fossil Diff}
484 @ wm iconname . {Fossil Diff}
485 @ set body {}
486 @ set mx 80 ;# Length of the longest line of text
487 @ set nLine 0 ;# Number of lines of text
488 @ text .t -width 180 -yscroll {.sb set}
489 @ if {$tcl_platform(platform)=="windows"} {.t config -font {courier 9}}
490 @ .t tag config ln -foreground gray
491 @ .t tag config chng -background {#d0d0ff}
492 @ .t tag config add -background {#c0ffc0}
493 @ .t tag config rm -background {#ffc0c0}
494 @ proc dehtml {x} {return [string map {&amp; & &lt; < &gt; >} $x]}
495 @ set in [open $cmd r]
496 @ while {![eof $in]} {
497 @ set line [gets $in]
498 @ if {[regexp {^<a name="chunk.*"></a>} $line]} continue
499 @ if {[regexp {^===} $line]} {
500 @ set n [string length $line]
501 @ if {$n>$mx} {set mx $n}
502 @ }
503 @ incr nLine
504 @ while {[regexp {^(.*?)<span class="diff([a-z]+)">(.*?)</span>(.*)$} $line \
505 @ all pre class mid tail]} {
506 @ .t insert end [dehtml $pre] {} [dehtml $mid] $class
507 @ set line $tail
508 @ }
509 @ .t insert end [dehtml $line]\n {}
510 @ }
511 @ close $in
512 @ if {$mx>250} {set mx 250} ;# Limit window width to 200 lines
513 @ if {$nLine>55} {set nLine 55} ;# Limit window height to 55 lines
514 @ .t config -height $nLine -width $mx
515 @ pack .t -side left -fill both -expand 1
516 @ scrollbar .sb -command {.t yview} -orient vertical
517 @ pack .sb -side left -fill y
518 @ wm deiconify .
519 ;
520
521 /*
522 ** Show diff output in a Tcl/Tk window, in response to the --tk option
523 ** to the diff command.
524 **
525 ** Steps:
526 ** (1) Write the Tcl/Tk script used for rendering into a temp file.
527 ** (2) Invoke "wish" on the temp file using fossil_system().
528 ** (3) Delete the temp file.
529 */
530 static void diff_tk(void){
531 int i;
532 Blob script;
533 char *zTempFile;
534 char *zCmd;
535 blob_zero(&script);
536 blob_appendf(&script, "set cmd {| \"%s\" diff --html -y", g.argv[0]);
537 for(i=2; i<g.argc; i++){
538 blob_appendf(&script, " \"%s\"", g.argv[i]);
539 }
540 blob_appendf(&script, "}\n%s", zDiffScript);
541 zTempFile = write_blob_to_temp_file(&script);
542 zCmd = mprintf("wish \"%s\"", zTempFile);
543 fossil_system(zCmd);
544 file_delete(zTempFile);
545 }
546
547 /*
548 ** COMMAND: diff
549 ** COMMAND: gdiff
550 **
@@ -509,10 +577,11 @@
577 ** --brief Show filenames only
578 ** --context|-c N Use N lines of context
579 ** --from|-r VERSION select VERSION as source for the diff
580 ** -i use internal diff logic
581 ** --new-file|-N output complete text of added or deleted files
582 ** --tk Launch a Tcl/Tk GUI for display
583 ** --to VERSION select VERSION as target for the diff
584 ** --side-by-side|-y side-by-side diff
585 ** --width|-W N Width of lines in side-by-side diff
586 */
587 void diff_cmd(void){
@@ -524,10 +593,14 @@
593 const char *zBranch; /* Branch to diff */
594 const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */
595 u64 diffFlags = 0; /* Flags to control the DIFF */
596 int f;
597
598 if( find_option("tk",0,0)!=0 ){
599 diff_tk();
600 return;
601 }
602 isGDiff = g.argv[1][0]=='g';
603 isInternDiff = find_option("internal","i",0)!=0;
604 zFrom = find_option("from", "r", 1);
605 zTo = find_option("to", 0, 1);
606 zBranch = find_option("branch", 0, 1);
607
+1 -1
--- src/vfile.c
+++ src/vfile.c
@@ -535,11 +535,11 @@
535535
}
536536
537537
/*
538538
** Write a BLOB into a random filename. Return the name of the file.
539539
*/
540
-static char *write_blob_to_temp_file(Blob *pBlob){
540
+char *write_blob_to_temp_file(Blob *pBlob){
541541
sqlite3_uint64 r;
542542
char *zOut = 0;
543543
do{
544544
sqlite3_free(zOut);
545545
sqlite3_randomness(8, &r);
546546
--- src/vfile.c
+++ src/vfile.c
@@ -535,11 +535,11 @@
535 }
536
537 /*
538 ** Write a BLOB into a random filename. Return the name of the file.
539 */
540 static char *write_blob_to_temp_file(Blob *pBlob){
541 sqlite3_uint64 r;
542 char *zOut = 0;
543 do{
544 sqlite3_free(zOut);
545 sqlite3_randomness(8, &r);
546
--- src/vfile.c
+++ src/vfile.c
@@ -535,11 +535,11 @@
535 }
536
537 /*
538 ** Write a BLOB into a random filename. Return the name of the file.
539 */
540 char *write_blob_to_temp_file(Blob *pBlob){
541 sqlite3_uint64 r;
542 char *zOut = 0;
543 do{
544 sqlite3_free(zOut);
545 sqlite3_randomness(8, &r);
546

Keyboard Shortcuts

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