Fossil SCM

Add the --tcl format option to the diff commands. The plan is to use this to implement --tk (in place of --html -y) but that part is not yet implemented.

drh 2021-09-02 09:19 diff-color-enhancements
Commit e933d5d731b7369761f84cf322070b588150a737565d95f962c2fb8b2e58fe7b
2 files changed +86 +21 -1
+86
--- src/diff.c
+++ src/diff.c
@@ -47,10 +47,11 @@
4747
#define DIFF_WEBPAGE (((u64)0x00040)<<32) /* Complete webpage */
4848
#define DIFF_BROWSER (((u64)0x00080)<<32) /* The --browser option */
4949
#define DIFF_JSON (((u64)0x00100)<<32) /* JSON output */
5050
#define DIFF_DEBUG (((u64)0x00200)<<32) /* Debugging diff output */
5151
#define DIFF_RAW (((u64)0x00400)<<32) /* Raw triples - for debugging */
52
+#define DIFF_TCL (((u64)0x00800)<<32) /* For the --tk option */
5253
5354
/*
5455
** These error messages are shared in multiple locations. They are defined
5556
** here for consistency.
5657
*/
@@ -1724,10 +1725,89 @@
17241725
p->xEnd = dfdebugEnd;
17251726
p->lnLeft = p->lnRight = 0;
17261727
p->pOut = pOut;
17271728
return p;
17281729
}
1730
+
1731
+/************************* DiffBuilderTcl ********************************/
1732
+/*
1733
+** This variant outputs a description of the diff formatted as TCL, for
1734
+** use by the --tk option to "diff".
1735
+*/
1736
+
1737
+/*
1738
+** Write out a quoted TCL string
1739
+*/
1740
+void blob_append_tcl_string(Blob *pOut, const char *z, int n){
1741
+ int i;
1742
+ blob_append_char(pOut, '"');
1743
+ for(i=0; i<n; i++){
1744
+ switch( z[i] ){
1745
+ case '"':
1746
+ case '\\':
1747
+ blob_append_char(pOut, '\\');
1748
+ /* Fall thru */
1749
+ default:
1750
+ blob_append_char(pOut, z[i]);
1751
+ }
1752
+ }
1753
+ blob_append_char(pOut, '"');
1754
+}
1755
+
1756
+static void dftclSkip(DiffBuilder *p, unsigned int n, int isFinal){
1757
+ blob_appendf(p->pOut, "SKIP %u\n", n);
1758
+}
1759
+static void dftclCommon(DiffBuilder *p, const DLine *pLine){
1760
+ blob_appendf(p->pOut, "COM ");
1761
+ blob_append_tcl_string(p->pOut, pLine->z, pLine->n);
1762
+ blob_append_char(p->pOut, '\n');
1763
+}
1764
+static void dftclInsert(DiffBuilder *p, const DLine *pLine){
1765
+ blob_append(p->pOut, "INS ", -1);
1766
+ blob_append_tcl_string(p->pOut, pLine->z, pLine->n);
1767
+ blob_append_char(p->pOut, '\n');
1768
+}
1769
+static void dftclDelete(DiffBuilder *p, const DLine *pLine){
1770
+ blob_append(p->pOut, "DEL ", -1);
1771
+ blob_append_tcl_string(p->pOut, pLine->z, pLine->n);
1772
+ blob_append_char(p->pOut, '\n');
1773
+}
1774
+static void dftclEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1775
+ int i, x;
1776
+ ChangeSpan span;
1777
+ blob_append(p->pOut, "EDIT", 4);
1778
+ oneLineChange(pX, pY, &span);
1779
+ for(i=x=0; i<span.n; i++){
1780
+ blob_append_char(p->pOut, ' ');
1781
+ blob_append_tcl_string(p->pOut, pX->z + x, span.a[i].iStart1 - x);
1782
+ x = span.a[i].iStart1;
1783
+ blob_append_char(p->pOut, ' ');
1784
+ blob_append_tcl_string(p->pOut, pX->z + x, span.a[i].iLen1);
1785
+ x += span.a[i].iLen1;
1786
+ blob_append_char(p->pOut, ' ');
1787
+ blob_append_tcl_string(p->pOut, pY->z + span.a[i].iStart2,span.a[i].iLen2);
1788
+ }
1789
+ if( x<pX->n ){
1790
+ blob_append_char(p->pOut, ' ');
1791
+ blob_append_tcl_string(p->pOut, pX->z + x, pX->n - x);
1792
+ }
1793
+ blob_append_char(p->pOut, '\n');
1794
+}
1795
+static void dftclEnd(DiffBuilder *p){
1796
+ fossil_free(p);
1797
+}
1798
+static DiffBuilder *dftclNew(Blob *pOut){
1799
+ DiffBuilder *p = fossil_malloc(sizeof(*p));
1800
+ p->xSkip = dftclSkip;
1801
+ p->xCommon = dftclCommon;
1802
+ p->xInsert = dftclInsert;
1803
+ p->xDelete = dftclDelete;
1804
+ p->xEdit = dftclEdit;
1805
+ p->xEnd = dftclEnd;
1806
+ p->pOut = pOut;
1807
+ return p;
1808
+}
17291809
17301810
/************************* DiffBuilderJson ********************************/
17311811
17321812
/* Convert raw text into content suitable for a JSON string. Escape
17331813
** charaters that are special to HTML and to JSON:
@@ -2949,10 +3029,13 @@
29493029
}
29503030
}else if( diffFlags & DIFF_JSON ){
29513031
DiffBuilder *pBuilder = dfjsonNew(pOut);
29523032
formatDiff(&c, pRe, diffFlags, pBuilder);
29533033
blob_append_char(pOut, '\n');
3034
+ }else if( diffFlags & DIFF_TCL ){
3035
+ DiffBuilder *pBuilder = dftclNew(pOut);
3036
+ formatDiff(&c, pRe, diffFlags, pBuilder);
29543037
}else if( diffFlags & DIFF_SIDEBYSIDE ){
29553038
if( diffFlags & DIFF_HTML ){
29563039
DiffBuilder *pBuilder = dfsplitNew(pOut);
29573040
formatDiff(&c, pRe, diffFlags, pBuilder);
29583041
}else{
@@ -3042,10 +3125,13 @@
30423125
diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER
30433126
|DIFF_SIDEBYSIDE;
30443127
}
30453128
if( find_option("json",0,0)!=0 ){
30463129
diffFlags |= DIFF_JSON;
3130
+ }
3131
+ if( find_option("tcl",0,0)!=0 ){
3132
+ diffFlags |= DIFF_TCL;
30473133
}
30483134
30493135
/* Undocumented and unsupported flags used for development
30503136
** debugging and analysis: */
30513137
if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG;
30523138
--- src/diff.c
+++ src/diff.c
@@ -47,10 +47,11 @@
47 #define DIFF_WEBPAGE (((u64)0x00040)<<32) /* Complete webpage */
48 #define DIFF_BROWSER (((u64)0x00080)<<32) /* The --browser option */
49 #define DIFF_JSON (((u64)0x00100)<<32) /* JSON output */
50 #define DIFF_DEBUG (((u64)0x00200)<<32) /* Debugging diff output */
51 #define DIFF_RAW (((u64)0x00400)<<32) /* Raw triples - for debugging */
 
52
53 /*
54 ** These error messages are shared in multiple locations. They are defined
55 ** here for consistency.
56 */
@@ -1724,10 +1725,89 @@
1724 p->xEnd = dfdebugEnd;
1725 p->lnLeft = p->lnRight = 0;
1726 p->pOut = pOut;
1727 return p;
1728 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1729
1730 /************************* DiffBuilderJson ********************************/
1731
1732 /* Convert raw text into content suitable for a JSON string. Escape
1733 ** charaters that are special to HTML and to JSON:
@@ -2949,10 +3029,13 @@
2949 }
2950 }else if( diffFlags & DIFF_JSON ){
2951 DiffBuilder *pBuilder = dfjsonNew(pOut);
2952 formatDiff(&c, pRe, diffFlags, pBuilder);
2953 blob_append_char(pOut, '\n');
 
 
 
2954 }else if( diffFlags & DIFF_SIDEBYSIDE ){
2955 if( diffFlags & DIFF_HTML ){
2956 DiffBuilder *pBuilder = dfsplitNew(pOut);
2957 formatDiff(&c, pRe, diffFlags, pBuilder);
2958 }else{
@@ -3042,10 +3125,13 @@
3042 diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER
3043 |DIFF_SIDEBYSIDE;
3044 }
3045 if( find_option("json",0,0)!=0 ){
3046 diffFlags |= DIFF_JSON;
 
 
 
3047 }
3048
3049 /* Undocumented and unsupported flags used for development
3050 ** debugging and analysis: */
3051 if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG;
3052
--- src/diff.c
+++ src/diff.c
@@ -47,10 +47,11 @@
47 #define DIFF_WEBPAGE (((u64)0x00040)<<32) /* Complete webpage */
48 #define DIFF_BROWSER (((u64)0x00080)<<32) /* The --browser option */
49 #define DIFF_JSON (((u64)0x00100)<<32) /* JSON output */
50 #define DIFF_DEBUG (((u64)0x00200)<<32) /* Debugging diff output */
51 #define DIFF_RAW (((u64)0x00400)<<32) /* Raw triples - for debugging */
52 #define DIFF_TCL (((u64)0x00800)<<32) /* For the --tk option */
53
54 /*
55 ** These error messages are shared in multiple locations. They are defined
56 ** here for consistency.
57 */
@@ -1724,10 +1725,89 @@
1725 p->xEnd = dfdebugEnd;
1726 p->lnLeft = p->lnRight = 0;
1727 p->pOut = pOut;
1728 return p;
1729 }
1730
1731 /************************* DiffBuilderTcl ********************************/
1732 /*
1733 ** This variant outputs a description of the diff formatted as TCL, for
1734 ** use by the --tk option to "diff".
1735 */
1736
1737 /*
1738 ** Write out a quoted TCL string
1739 */
1740 void blob_append_tcl_string(Blob *pOut, const char *z, int n){
1741 int i;
1742 blob_append_char(pOut, '"');
1743 for(i=0; i<n; i++){
1744 switch( z[i] ){
1745 case '"':
1746 case '\\':
1747 blob_append_char(pOut, '\\');
1748 /* Fall thru */
1749 default:
1750 blob_append_char(pOut, z[i]);
1751 }
1752 }
1753 blob_append_char(pOut, '"');
1754 }
1755
1756 static void dftclSkip(DiffBuilder *p, unsigned int n, int isFinal){
1757 blob_appendf(p->pOut, "SKIP %u\n", n);
1758 }
1759 static void dftclCommon(DiffBuilder *p, const DLine *pLine){
1760 blob_appendf(p->pOut, "COM ");
1761 blob_append_tcl_string(p->pOut, pLine->z, pLine->n);
1762 blob_append_char(p->pOut, '\n');
1763 }
1764 static void dftclInsert(DiffBuilder *p, const DLine *pLine){
1765 blob_append(p->pOut, "INS ", -1);
1766 blob_append_tcl_string(p->pOut, pLine->z, pLine->n);
1767 blob_append_char(p->pOut, '\n');
1768 }
1769 static void dftclDelete(DiffBuilder *p, const DLine *pLine){
1770 blob_append(p->pOut, "DEL ", -1);
1771 blob_append_tcl_string(p->pOut, pLine->z, pLine->n);
1772 blob_append_char(p->pOut, '\n');
1773 }
1774 static void dftclEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
1775 int i, x;
1776 ChangeSpan span;
1777 blob_append(p->pOut, "EDIT", 4);
1778 oneLineChange(pX, pY, &span);
1779 for(i=x=0; i<span.n; i++){
1780 blob_append_char(p->pOut, ' ');
1781 blob_append_tcl_string(p->pOut, pX->z + x, span.a[i].iStart1 - x);
1782 x = span.a[i].iStart1;
1783 blob_append_char(p->pOut, ' ');
1784 blob_append_tcl_string(p->pOut, pX->z + x, span.a[i].iLen1);
1785 x += span.a[i].iLen1;
1786 blob_append_char(p->pOut, ' ');
1787 blob_append_tcl_string(p->pOut, pY->z + span.a[i].iStart2,span.a[i].iLen2);
1788 }
1789 if( x<pX->n ){
1790 blob_append_char(p->pOut, ' ');
1791 blob_append_tcl_string(p->pOut, pX->z + x, pX->n - x);
1792 }
1793 blob_append_char(p->pOut, '\n');
1794 }
1795 static void dftclEnd(DiffBuilder *p){
1796 fossil_free(p);
1797 }
1798 static DiffBuilder *dftclNew(Blob *pOut){
1799 DiffBuilder *p = fossil_malloc(sizeof(*p));
1800 p->xSkip = dftclSkip;
1801 p->xCommon = dftclCommon;
1802 p->xInsert = dftclInsert;
1803 p->xDelete = dftclDelete;
1804 p->xEdit = dftclEdit;
1805 p->xEnd = dftclEnd;
1806 p->pOut = pOut;
1807 return p;
1808 }
1809
1810 /************************* DiffBuilderJson ********************************/
1811
1812 /* Convert raw text into content suitable for a JSON string. Escape
1813 ** charaters that are special to HTML and to JSON:
@@ -2949,10 +3029,13 @@
3029 }
3030 }else if( diffFlags & DIFF_JSON ){
3031 DiffBuilder *pBuilder = dfjsonNew(pOut);
3032 formatDiff(&c, pRe, diffFlags, pBuilder);
3033 blob_append_char(pOut, '\n');
3034 }else if( diffFlags & DIFF_TCL ){
3035 DiffBuilder *pBuilder = dftclNew(pOut);
3036 formatDiff(&c, pRe, diffFlags, pBuilder);
3037 }else if( diffFlags & DIFF_SIDEBYSIDE ){
3038 if( diffFlags & DIFF_HTML ){
3039 DiffBuilder *pBuilder = dfsplitNew(pOut);
3040 formatDiff(&c, pRe, diffFlags, pBuilder);
3041 }else{
@@ -3042,10 +3125,13 @@
3125 diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER
3126 |DIFF_SIDEBYSIDE;
3127 }
3128 if( find_option("json",0,0)!=0 ){
3129 diffFlags |= DIFF_JSON;
3130 }
3131 if( find_option("tcl",0,0)!=0 ){
3132 diffFlags |= DIFF_TCL;
3133 }
3134
3135 /* Undocumented and unsupported flags used for development
3136 ** debugging and analysis: */
3137 if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG;
3138
+21 -1
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -114,11 +114,12 @@
114114
115115
/*
116116
** Print the "Index:" message that patches wants to see at the top of a diff.
117117
*/
118118
void diff_print_index(const char *zFile, u64 diffFlags, Blob *diffBlob){
119
- if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF|DIFF_NUMSTAT|DIFF_WEBPAGE))==0 ){
119
+ if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF|DIFF_NUMSTAT|
120
+ DIFF_WEBPAGE|DIFF_TCL))==0 ){
120121
char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
121122
if( !diffBlob ){
122123
fossil_print("%s", z);
123124
}else{
124125
blob_appendf(diffBlob, "%s", z);
@@ -146,10 +147,29 @@
146147
if( fossil_strcmp(zLeft,zRight)==0 ){
147148
z = mprintf("<h1>%h</h1>\n", zLeft);
148149
}else{
149150
z = mprintf("<h1>%h &lrarr; %h</h1>\n", zLeft, zRight);
150151
}
152
+ }else if( diffFlags & DIFF_TCL ){
153
+ Blob *pOut;
154
+ Blob x;
155
+ if( diffBlob ){
156
+ pOut = diffBlob;
157
+ }else{
158
+ blob_init(&x, 0, 0);
159
+ pOut = &x;
160
+ }
161
+ blob_append(pOut, "FILE ", 5);
162
+ blob_append_tcl_string(pOut, zLeft, (int)strlen(zLeft));
163
+ blob_append_char(pOut, ' ');
164
+ blob_append_tcl_string(pOut, zRight, (int)strlen(zRight));
165
+ blob_append_char(pOut, '\n');
166
+ if( !diffBlob ){
167
+ fossil_print("%s", blob_str(pOut));
168
+ blob_reset(&x);
169
+ }
170
+ return;
151171
}else if( diffFlags & DIFF_SIDEBYSIDE ){
152172
int w = diff_width(diffFlags);
153173
int n1 = strlen(zLeft);
154174
int n2 = strlen(zRight);
155175
int x;
156176
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -114,11 +114,12 @@
114
115 /*
116 ** Print the "Index:" message that patches wants to see at the top of a diff.
117 */
118 void diff_print_index(const char *zFile, u64 diffFlags, Blob *diffBlob){
119 if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF|DIFF_NUMSTAT|DIFF_WEBPAGE))==0 ){
 
120 char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
121 if( !diffBlob ){
122 fossil_print("%s", z);
123 }else{
124 blob_appendf(diffBlob, "%s", z);
@@ -146,10 +147,29 @@
146 if( fossil_strcmp(zLeft,zRight)==0 ){
147 z = mprintf("<h1>%h</h1>\n", zLeft);
148 }else{
149 z = mprintf("<h1>%h &lrarr; %h</h1>\n", zLeft, zRight);
150 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151 }else if( diffFlags & DIFF_SIDEBYSIDE ){
152 int w = diff_width(diffFlags);
153 int n1 = strlen(zLeft);
154 int n2 = strlen(zRight);
155 int x;
156
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -114,11 +114,12 @@
114
115 /*
116 ** Print the "Index:" message that patches wants to see at the top of a diff.
117 */
118 void diff_print_index(const char *zFile, u64 diffFlags, Blob *diffBlob){
119 if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF|DIFF_NUMSTAT|
120 DIFF_WEBPAGE|DIFF_TCL))==0 ){
121 char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
122 if( !diffBlob ){
123 fossil_print("%s", z);
124 }else{
125 blob_appendf(diffBlob, "%s", z);
@@ -146,10 +147,29 @@
147 if( fossil_strcmp(zLeft,zRight)==0 ){
148 z = mprintf("<h1>%h</h1>\n", zLeft);
149 }else{
150 z = mprintf("<h1>%h &lrarr; %h</h1>\n", zLeft, zRight);
151 }
152 }else if( diffFlags & DIFF_TCL ){
153 Blob *pOut;
154 Blob x;
155 if( diffBlob ){
156 pOut = diffBlob;
157 }else{
158 blob_init(&x, 0, 0);
159 pOut = &x;
160 }
161 blob_append(pOut, "FILE ", 5);
162 blob_append_tcl_string(pOut, zLeft, (int)strlen(zLeft));
163 blob_append_char(pOut, ' ');
164 blob_append_tcl_string(pOut, zRight, (int)strlen(zRight));
165 blob_append_char(pOut, '\n');
166 if( !diffBlob ){
167 fossil_print("%s", blob_str(pOut));
168 blob_reset(&x);
169 }
170 return;
171 }else if( diffFlags & DIFF_SIDEBYSIDE ){
172 int w = diff_width(diffFlags);
173 int n1 = strlen(zLeft);
174 int n2 = strlen(zRight);
175 int x;
176

Keyboard Shortcuts

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