Fossil SCM

Automatically add HTML formatting to the on-line help when displaying in a web-page. (This is a work-in-progress. No everything displays correctly, yet.)

drh 2020-06-24 21:50 trunk
Commit f1230cb3f3ace07b43e261c47a15441d86f0b1cb9ad69d5f62eeac2caeac289d
1 file changed +227 -42
+227 -42
--- src/dispatch.c
+++ src/dispatch.c
@@ -216,35 +216,210 @@
216216
if( strncmp(zPrefix, aCommand[i].zName, nPrefix)==0 ){
217217
blob_appendf(pList, " %s", aCommand[i].zName);
218218
}
219219
}
220220
}
221
+
222
+/*
223
+** Return the index of the first non-space character that follows
224
+** a span of two or more spaces. Return 0 if there is not gap.
225
+*/
226
+static int hasGap(const char *z, int n){
227
+ int i;
228
+ for(i=3; i<n-1; i++){
229
+ if( z[i]==' ' && z[i+1]!=' ' && z[i-1]==' ' ) return i+1;
230
+ }
231
+ return 0 ;
232
+}
233
+
234
+/*
235
+** Append text to pOut, adding formatting markup. Terms that
236
+** have all lower-case letters are within <tt>..</tt>. Terms
237
+** that have all upper-case letters are within <i>..</i>.
238
+*/
239
+static void appendMixedFont(Blob *pOut, const char *z, int n){
240
+ const char *zEnd = "";
241
+ int i = 0;
242
+ int j;
243
+ while( i<n ){
244
+ if( z[i]==' ' ){
245
+ for(j=i+1; j<n && z[j]==' '; j++){}
246
+ blob_append(pOut, z+i, j-i);
247
+ i = j;
248
+ }else{
249
+ for(j=i; j<n && z[j]!=' ' && !fossil_isalpha(z[j]); j++){}
250
+ if( j>=n || z[j]==' ' ){
251
+ zEnd = "";
252
+ }else{
253
+ if( fossil_isupper(z[j]) ){
254
+ blob_append(pOut, "<i>",3);
255
+ zEnd = "</i>";
256
+ }else{
257
+ blob_append(pOut, "<tt>", 4);
258
+ zEnd = "</tt>";
259
+ }
260
+ }
261
+ while( j<n && z[j]!=' ' ){ j++; }
262
+ blob_appendf(pOut, "%#h", j-i, z+i);
263
+ if( zEnd[0] ) blob_append(pOut, zEnd, -1);
264
+ i = j;
265
+ }
266
+ }
267
+}
221268
222269
/*
223270
** Attempt to reformat plain-text help into HTML for display on a webpage.
224271
**
225272
** The HTML output is appended to Blob pHtml, which should already be
226273
** initialized.
274
+**
275
+** Formatting rules:
276
+**
277
+** * Bullet lists are indented from the surrounding text by
278
+** at least one space. Each bullet begins with " * ".
279
+**
280
+** * Display lists are indented from the surrounding text.
281
+** Each tag begins with "-" or occur on a line that is
282
+** followed by two spaces and a non-space. <dd> elements can begin
283
+** on the same line as long as they are separated by at least
284
+** two spaces.
285
+**
286
+** * Indented text is show verbatim (<pre>...</pre>)
227287
*/
228288
static void help_to_html(const char *zHelp, Blob *pHtml){
229
- char *s;
230
- char *d;
231
- char *z;
232
-
233
- /* Transform "%fossil" into just "fossil" */
234
- z = s = d = mprintf("%s", zHelp);
235
- while( *s ){
236
- if( *s=='%' && strncmp(s, "%fossil", 7)==0 ){
237
- s++;
238
- }else{
239
- *d++ = *s++;
240
- }
241
- }
242
- *d = 0;
243
-
244
- blob_appendf(pHtml, "<pre>\n%h\n</pre>\n", z);
245
- fossil_free(z);
289
+ int i;
290
+ char c;
291
+ int nIndent = 0;
292
+ int wantP = 0;
293
+ int wantBR = 0;
294
+ int aIndent[10];
295
+ const char *azEnd[10];
296
+ int iLevel = 0;
297
+ int isLI = 0;
298
+ static const char *zEndDL = "</dl></blockquote>";
299
+ static const char *zEndPRE = "</pre></blockquote>";
300
+ static const char *zEndUL = "</ul>";
301
+ static const char *zEndDD = "</dd>";
302
+
303
+ aIndent[0] = 0;
304
+ azEnd[0] = "";
305
+ while( zHelp[0] ){
306
+ i = 0;
307
+ while( (c = zHelp[i])!=0
308
+ && c!='\n'
309
+ && (c!='%' || strncmp(zHelp+i,"%fossil",7)!=0)
310
+ ){ i++; }
311
+ if( c=='%' ){
312
+ if( i ) blob_appendf(pHtml, "%#h", i, zHelp);
313
+ zHelp += i + 1;
314
+ i = 0;
315
+ wantBR = 1;
316
+ continue;
317
+ }
318
+ for(nIndent=0; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
319
+ if( nIndent==i ){
320
+ if( c==0 ) break;
321
+ blob_append(pHtml, "\n", 1);
322
+ wantP = 1;
323
+ wantBR = 0;
324
+ zHelp += i+1;
325
+ continue;
326
+ }
327
+ if( nIndent+2<i && zHelp[nIndent]=='*' && zHelp[nIndent+1]==' ' ){
328
+ nIndent += 2;
329
+ while( nIndent<i && zHelp[nIndent]==' '){ nIndent++; }
330
+ isLI = 1;
331
+ }else{
332
+ isLI = 0;
333
+ }
334
+ while( iLevel>0 && aIndent[iLevel]>nIndent ){
335
+ blob_append(pHtml, azEnd[iLevel--], -1);
336
+ }
337
+ if( nIndent>aIndent[iLevel] ){
338
+ assert( iLevel<ArraySize(aIndent)-2 );
339
+ if( isLI ){
340
+ iLevel++;
341
+ aIndent[iLevel] = nIndent;
342
+ azEnd[iLevel] = zEndUL;
343
+ blob_append(pHtml, "<ul>\n", 5);
344
+ }else if( zHelp[nIndent]=='-' || hasGap(zHelp+nIndent,i-nIndent) ){
345
+ iLevel++;
346
+ aIndent[iLevel] = nIndent;
347
+ azEnd[iLevel] = zEndDL;
348
+ blob_append(pHtml, "<blockquote><dl>\n", -1);
349
+ }else if( wantP && azEnd[iLevel]!=zEndDL ){
350
+ iLevel++;
351
+ aIndent[iLevel] = nIndent;
352
+ azEnd[iLevel] = zEndPRE;
353
+ blob_append(pHtml, "<blockquote><pre>", -1);
354
+ wantP = 0;
355
+ }
356
+ }
357
+ if( isLI ){
358
+ blob_append(pHtml, "<li> ", 5);
359
+ }
360
+ if( wantP ){
361
+ blob_append(pHtml, "<p> ", 4);
362
+ wantP = 0;
363
+ }
364
+ if( azEnd[iLevel]==zEndDL ){
365
+ int iDD;
366
+ blob_append(pHtml, "<dt> ", 5);
367
+ iDD = hasGap(zHelp+nIndent, i-nIndent);
368
+ if( iDD ){
369
+ int x;
370
+ assert( iLevel<ArraySize(aIndent)-1 );
371
+ iLevel++;
372
+ aIndent[iLevel] = x = nIndent+iDD;
373
+ azEnd[iLevel] = zEndDD;
374
+ appendMixedFont(pHtml, zHelp+nIndent, iDD-2);
375
+ blob_appendf(pHtml, "</dt><dd>%#h\n", x, zHelp+x);
376
+ }else{
377
+ appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
378
+ blob_append(pHtml, "</dt>\n", 6);
379
+ }
380
+ }else if( wantBR ){
381
+ appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
382
+ blob_append(pHtml, "<br>\n", 5);
383
+ wantBR = 0;
384
+ }else{
385
+ blob_appendf(pHtml, "%#h\n", i-nIndent, zHelp+nIndent);
386
+ }
387
+ zHelp += i+1;
388
+ i = 0;
389
+ if( c==0 ) break;
390
+ }
391
+ while( iLevel>0 ){
392
+ blob_appendf(pHtml, "%s\n", azEnd[iLevel--]);
393
+ }
394
+}
395
+
396
+/*
397
+** Format help text for TTY display.
398
+*/
399
+static void help_to_text(const char *zHelp, Blob *pText){
400
+ int i;
401
+ char c;
402
+ for(i=0; (c = zHelp[i])!=0; i++){
403
+ if( c=='%' && strncmp(zHelp+i,"%fossil",7)==0 ){
404
+ if( i>0 ) blob_append(pText, zHelp, i);
405
+ blob_append(pText, "fossil", 6);
406
+ zHelp += i+7;
407
+ i = -1;
408
+ continue;
409
+ }
410
+ if( c=='\n' && strncmp(zHelp+i+1,"> ",3)==0 ){
411
+ if( i>0 ) blob_append(pText, zHelp, i-1);
412
+ blob_append(pText, " ", 6);
413
+ zHelp += i+3;
414
+ i = -1;
415
+ continue;
416
+ }
417
+ }
418
+ if( i>0 ){
419
+ blob_append(pText, zHelp, i);
420
+ }
246421
}
247422
248423
/*
249424
** COMMAND: test-all-help
250425
**
@@ -292,19 +467,24 @@
292467
}else{
293468
fossil_print("---\n");
294469
}
295470
for(i=0; i<MX_COMMAND; i++){
296471
if( (aCommand[i].eCmdFlags & mask)==0 ) continue;
297
- fossil_print("# %s\n", aCommand[i].zName);
298472
if( useHtml ){
299473
Blob html;
300
- blob_zero(&html);
474
+ blob_init(&html, 0, 0);
301475
help_to_html(aCommand[i].zHelp, &html);
302
- fossil_print("%s\n\n", blob_str(&html));
476
+ fossil_print("<h1>%h</h1>\n", aCommand[i].zName);
477
+ fossil_print("%s\n<hr>\n", blob_str(&html));
303478
blob_reset(&html);
304479
}else{
305
- fossil_print("%s\n\n", aCommand[i].zHelp);
480
+ Blob txt;
481
+ blob_init(&txt, 0, 0);
482
+ help_to_text(aCommand[i].zHelp, &txt);
483
+ fossil_print("# %s\n", aCommand[i].zName);
484
+ fossil_print("%s\n\n", blob_str(&txt));
485
+ blob_reset(&txt);
306486
}
307487
}
308488
if( useHtml ){
309489
fossil_print("<!-- end_all_help -->\n");
310490
}else{
@@ -689,31 +869,37 @@
689869
;
690870
691871
/*
692872
** COMMAND: help
693873
**
694
-** Usage: %fossil help TOPIC
695
-** or: %fossil TOPIC --help
874
+** Usage: %fossil help [OPTIONS] [TOPIC]
696875
**
697876
** Display information on how to use TOPIC, which may be a command, webpage, or
698
-** setting. Webpage names begin with "/". To display a list of available
699
-** topics, use one of:
877
+** setting. Webpage names begin with "/". If TOPIC is omitted, a list of
878
+** topics is returned.
879
+**
880
+** The following options can be used when TOPIC is omitted:
881
+**
882
+** -a|--all List both command and auxiliary commands
883
+** -o|--options List command-line options common to all commands
884
+** -s|--setting List setting names
885
+** -t|--test List unsupported "test" commands
886
+** -x|--aux List only auxiliary commands
887
+** -w|--www List all web pages
888
+**
889
+** These options can be used when TOPIC is present:
700890
**
701
-** %fossil help Show common commands
702
-** %fossil help -a|--all Show both common and auxiliary commands
703
-** %fossil help -o|--options Show command-line options common to all cmds
704
-** %fossil help -s|--setting Show setting names
705
-** %fossil help -t|--test Show test commands only
706
-** %fossil help -x|--aux Show auxiliary commands only
707
-** %fossil help -w|--www Show list of webpages
891
+** -h|--html Format output as HTML rather than plain text
708892
*/
709893
void help_cmd(void){
710894
int rc;
711895
int isPage = 0;
712896
const char *z;
713897
const char *zCmdOrPage;
714898
const CmdOrPage *pCmd = 0;
899
+ int useHtml = 0;
900
+ Blob txt;
715901
if( g.argc<3 ){
716902
z = g.argv[0];
717903
fossil_print(
718904
"Usage: %s help TOPIC\n"
719905
"Common commands: (use \"%s help help\" for more options)\n",
@@ -744,10 +930,11 @@
744930
}
745931
else if( find_option("setting","s",0) ){
746932
command_list(0, CMDFLAG_SETTING);
747933
return;
748934
}
935
+ useHtml = find_option("html","h",0)!=0;
749936
isPage = ('/' == *g.argv[2]) ? 1 : 0;
750937
if(isPage){
751938
zCmdOrPage = "page";
752939
}else{
753940
zCmdOrPage = "command or setting";
@@ -782,20 +969,18 @@
782969
fossil_print("Setting: \"%s\"%s\n\n",
783970
pCmd->zName,
784971
(pCmd->eCmdFlags & CMDFLAG_VERSIONABLE)!=0 ? " (versionable)" : ""
785972
);
786973
}
787
- while( *z ){
788
- if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
789
- fossil_print("%s", g.argv[0]);
790
- z += 7;
791
- }else{
792
- putchar(*z);
793
- z++;
794
- }
795
- }
796
- putchar('\n');
974
+ blob_init(&txt, 0, 0);
975
+ if( useHtml ){
976
+ help_to_html(z, &txt);
977
+ }else{
978
+ help_to_text(z, &txt);
979
+ }
980
+ fossil_print("%s\n", blob_str(&txt));
981
+ blob_reset(&txt);
797982
}
798983
799984
/*
800985
** Return a pointer to the setting information array.
801986
**
802987
--- src/dispatch.c
+++ src/dispatch.c
@@ -216,35 +216,210 @@
216 if( strncmp(zPrefix, aCommand[i].zName, nPrefix)==0 ){
217 blob_appendf(pList, " %s", aCommand[i].zName);
218 }
219 }
220 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
222 /*
223 ** Attempt to reformat plain-text help into HTML for display on a webpage.
224 **
225 ** The HTML output is appended to Blob pHtml, which should already be
226 ** initialized.
 
 
 
 
 
 
 
 
 
 
 
 
 
227 */
228 static void help_to_html(const char *zHelp, Blob *pHtml){
229 char *s;
230 char *d;
231 char *z;
232
233 /* Transform "%fossil" into just "fossil" */
234 z = s = d = mprintf("%s", zHelp);
235 while( *s ){
236 if( *s=='%' && strncmp(s, "%fossil", 7)==0 ){
237 s++;
238 }else{
239 *d++ = *s++;
240 }
241 }
242 *d = 0;
243
244 blob_appendf(pHtml, "<pre>\n%h\n</pre>\n", z);
245 fossil_free(z);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246 }
247
248 /*
249 ** COMMAND: test-all-help
250 **
@@ -292,19 +467,24 @@
292 }else{
293 fossil_print("---\n");
294 }
295 for(i=0; i<MX_COMMAND; i++){
296 if( (aCommand[i].eCmdFlags & mask)==0 ) continue;
297 fossil_print("# %s\n", aCommand[i].zName);
298 if( useHtml ){
299 Blob html;
300 blob_zero(&html);
301 help_to_html(aCommand[i].zHelp, &html);
302 fossil_print("%s\n\n", blob_str(&html));
 
303 blob_reset(&html);
304 }else{
305 fossil_print("%s\n\n", aCommand[i].zHelp);
 
 
 
 
 
306 }
307 }
308 if( useHtml ){
309 fossil_print("<!-- end_all_help -->\n");
310 }else{
@@ -689,31 +869,37 @@
689 ;
690
691 /*
692 ** COMMAND: help
693 **
694 ** Usage: %fossil help TOPIC
695 ** or: %fossil TOPIC --help
696 **
697 ** Display information on how to use TOPIC, which may be a command, webpage, or
698 ** setting. Webpage names begin with "/". To display a list of available
699 ** topics, use one of:
 
 
 
 
 
 
 
 
 
 
 
700 **
701 ** %fossil help Show common commands
702 ** %fossil help -a|--all Show both common and auxiliary commands
703 ** %fossil help -o|--options Show command-line options common to all cmds
704 ** %fossil help -s|--setting Show setting names
705 ** %fossil help -t|--test Show test commands only
706 ** %fossil help -x|--aux Show auxiliary commands only
707 ** %fossil help -w|--www Show list of webpages
708 */
709 void help_cmd(void){
710 int rc;
711 int isPage = 0;
712 const char *z;
713 const char *zCmdOrPage;
714 const CmdOrPage *pCmd = 0;
 
 
715 if( g.argc<3 ){
716 z = g.argv[0];
717 fossil_print(
718 "Usage: %s help TOPIC\n"
719 "Common commands: (use \"%s help help\" for more options)\n",
@@ -744,10 +930,11 @@
744 }
745 else if( find_option("setting","s",0) ){
746 command_list(0, CMDFLAG_SETTING);
747 return;
748 }
 
749 isPage = ('/' == *g.argv[2]) ? 1 : 0;
750 if(isPage){
751 zCmdOrPage = "page";
752 }else{
753 zCmdOrPage = "command or setting";
@@ -782,20 +969,18 @@
782 fossil_print("Setting: \"%s\"%s\n\n",
783 pCmd->zName,
784 (pCmd->eCmdFlags & CMDFLAG_VERSIONABLE)!=0 ? " (versionable)" : ""
785 );
786 }
787 while( *z ){
788 if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
789 fossil_print("%s", g.argv[0]);
790 z += 7;
791 }else{
792 putchar(*z);
793 z++;
794 }
795 }
796 putchar('\n');
797 }
798
799 /*
800 ** Return a pointer to the setting information array.
801 **
802
--- src/dispatch.c
+++ src/dispatch.c
@@ -216,35 +216,210 @@
216 if( strncmp(zPrefix, aCommand[i].zName, nPrefix)==0 ){
217 blob_appendf(pList, " %s", aCommand[i].zName);
218 }
219 }
220 }
221
222 /*
223 ** Return the index of the first non-space character that follows
224 ** a span of two or more spaces. Return 0 if there is not gap.
225 */
226 static int hasGap(const char *z, int n){
227 int i;
228 for(i=3; i<n-1; i++){
229 if( z[i]==' ' && z[i+1]!=' ' && z[i-1]==' ' ) return i+1;
230 }
231 return 0 ;
232 }
233
234 /*
235 ** Append text to pOut, adding formatting markup. Terms that
236 ** have all lower-case letters are within <tt>..</tt>. Terms
237 ** that have all upper-case letters are within <i>..</i>.
238 */
239 static void appendMixedFont(Blob *pOut, const char *z, int n){
240 const char *zEnd = "";
241 int i = 0;
242 int j;
243 while( i<n ){
244 if( z[i]==' ' ){
245 for(j=i+1; j<n && z[j]==' '; j++){}
246 blob_append(pOut, z+i, j-i);
247 i = j;
248 }else{
249 for(j=i; j<n && z[j]!=' ' && !fossil_isalpha(z[j]); j++){}
250 if( j>=n || z[j]==' ' ){
251 zEnd = "";
252 }else{
253 if( fossil_isupper(z[j]) ){
254 blob_append(pOut, "<i>",3);
255 zEnd = "</i>";
256 }else{
257 blob_append(pOut, "<tt>", 4);
258 zEnd = "</tt>";
259 }
260 }
261 while( j<n && z[j]!=' ' ){ j++; }
262 blob_appendf(pOut, "%#h", j-i, z+i);
263 if( zEnd[0] ) blob_append(pOut, zEnd, -1);
264 i = j;
265 }
266 }
267 }
268
269 /*
270 ** Attempt to reformat plain-text help into HTML for display on a webpage.
271 **
272 ** The HTML output is appended to Blob pHtml, which should already be
273 ** initialized.
274 **
275 ** Formatting rules:
276 **
277 ** * Bullet lists are indented from the surrounding text by
278 ** at least one space. Each bullet begins with " * ".
279 **
280 ** * Display lists are indented from the surrounding text.
281 ** Each tag begins with "-" or occur on a line that is
282 ** followed by two spaces and a non-space. <dd> elements can begin
283 ** on the same line as long as they are separated by at least
284 ** two spaces.
285 **
286 ** * Indented text is show verbatim (<pre>...</pre>)
287 */
288 static void help_to_html(const char *zHelp, Blob *pHtml){
289 int i;
290 char c;
291 int nIndent = 0;
292 int wantP = 0;
293 int wantBR = 0;
294 int aIndent[10];
295 const char *azEnd[10];
296 int iLevel = 0;
297 int isLI = 0;
298 static const char *zEndDL = "</dl></blockquote>";
299 static const char *zEndPRE = "</pre></blockquote>";
300 static const char *zEndUL = "</ul>";
301 static const char *zEndDD = "</dd>";
302
303 aIndent[0] = 0;
304 azEnd[0] = "";
305 while( zHelp[0] ){
306 i = 0;
307 while( (c = zHelp[i])!=0
308 && c!='\n'
309 && (c!='%' || strncmp(zHelp+i,"%fossil",7)!=0)
310 ){ i++; }
311 if( c=='%' ){
312 if( i ) blob_appendf(pHtml, "%#h", i, zHelp);
313 zHelp += i + 1;
314 i = 0;
315 wantBR = 1;
316 continue;
317 }
318 for(nIndent=0; nIndent<i && zHelp[nIndent]==' '; nIndent++){}
319 if( nIndent==i ){
320 if( c==0 ) break;
321 blob_append(pHtml, "\n", 1);
322 wantP = 1;
323 wantBR = 0;
324 zHelp += i+1;
325 continue;
326 }
327 if( nIndent+2<i && zHelp[nIndent]=='*' && zHelp[nIndent+1]==' ' ){
328 nIndent += 2;
329 while( nIndent<i && zHelp[nIndent]==' '){ nIndent++; }
330 isLI = 1;
331 }else{
332 isLI = 0;
333 }
334 while( iLevel>0 && aIndent[iLevel]>nIndent ){
335 blob_append(pHtml, azEnd[iLevel--], -1);
336 }
337 if( nIndent>aIndent[iLevel] ){
338 assert( iLevel<ArraySize(aIndent)-2 );
339 if( isLI ){
340 iLevel++;
341 aIndent[iLevel] = nIndent;
342 azEnd[iLevel] = zEndUL;
343 blob_append(pHtml, "<ul>\n", 5);
344 }else if( zHelp[nIndent]=='-' || hasGap(zHelp+nIndent,i-nIndent) ){
345 iLevel++;
346 aIndent[iLevel] = nIndent;
347 azEnd[iLevel] = zEndDL;
348 blob_append(pHtml, "<blockquote><dl>\n", -1);
349 }else if( wantP && azEnd[iLevel]!=zEndDL ){
350 iLevel++;
351 aIndent[iLevel] = nIndent;
352 azEnd[iLevel] = zEndPRE;
353 blob_append(pHtml, "<blockquote><pre>", -1);
354 wantP = 0;
355 }
356 }
357 if( isLI ){
358 blob_append(pHtml, "<li> ", 5);
359 }
360 if( wantP ){
361 blob_append(pHtml, "<p> ", 4);
362 wantP = 0;
363 }
364 if( azEnd[iLevel]==zEndDL ){
365 int iDD;
366 blob_append(pHtml, "<dt> ", 5);
367 iDD = hasGap(zHelp+nIndent, i-nIndent);
368 if( iDD ){
369 int x;
370 assert( iLevel<ArraySize(aIndent)-1 );
371 iLevel++;
372 aIndent[iLevel] = x = nIndent+iDD;
373 azEnd[iLevel] = zEndDD;
374 appendMixedFont(pHtml, zHelp+nIndent, iDD-2);
375 blob_appendf(pHtml, "</dt><dd>%#h\n", x, zHelp+x);
376 }else{
377 appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
378 blob_append(pHtml, "</dt>\n", 6);
379 }
380 }else if( wantBR ){
381 appendMixedFont(pHtml, zHelp+nIndent, i-nIndent);
382 blob_append(pHtml, "<br>\n", 5);
383 wantBR = 0;
384 }else{
385 blob_appendf(pHtml, "%#h\n", i-nIndent, zHelp+nIndent);
386 }
387 zHelp += i+1;
388 i = 0;
389 if( c==0 ) break;
390 }
391 while( iLevel>0 ){
392 blob_appendf(pHtml, "%s\n", azEnd[iLevel--]);
393 }
394 }
395
396 /*
397 ** Format help text for TTY display.
398 */
399 static void help_to_text(const char *zHelp, Blob *pText){
400 int i;
401 char c;
402 for(i=0; (c = zHelp[i])!=0; i++){
403 if( c=='%' && strncmp(zHelp+i,"%fossil",7)==0 ){
404 if( i>0 ) blob_append(pText, zHelp, i);
405 blob_append(pText, "fossil", 6);
406 zHelp += i+7;
407 i = -1;
408 continue;
409 }
410 if( c=='\n' && strncmp(zHelp+i+1,"> ",3)==0 ){
411 if( i>0 ) blob_append(pText, zHelp, i-1);
412 blob_append(pText, " ", 6);
413 zHelp += i+3;
414 i = -1;
415 continue;
416 }
417 }
418 if( i>0 ){
419 blob_append(pText, zHelp, i);
420 }
421 }
422
423 /*
424 ** COMMAND: test-all-help
425 **
@@ -292,19 +467,24 @@
467 }else{
468 fossil_print("---\n");
469 }
470 for(i=0; i<MX_COMMAND; i++){
471 if( (aCommand[i].eCmdFlags & mask)==0 ) continue;
 
472 if( useHtml ){
473 Blob html;
474 blob_init(&html, 0, 0);
475 help_to_html(aCommand[i].zHelp, &html);
476 fossil_print("<h1>%h</h1>\n", aCommand[i].zName);
477 fossil_print("%s\n<hr>\n", blob_str(&html));
478 blob_reset(&html);
479 }else{
480 Blob txt;
481 blob_init(&txt, 0, 0);
482 help_to_text(aCommand[i].zHelp, &txt);
483 fossil_print("# %s\n", aCommand[i].zName);
484 fossil_print("%s\n\n", blob_str(&txt));
485 blob_reset(&txt);
486 }
487 }
488 if( useHtml ){
489 fossil_print("<!-- end_all_help -->\n");
490 }else{
@@ -689,31 +869,37 @@
869 ;
870
871 /*
872 ** COMMAND: help
873 **
874 ** Usage: %fossil help [OPTIONS] [TOPIC]
 
875 **
876 ** Display information on how to use TOPIC, which may be a command, webpage, or
877 ** setting. Webpage names begin with "/". If TOPIC is omitted, a list of
878 ** topics is returned.
879 **
880 ** The following options can be used when TOPIC is omitted:
881 **
882 ** -a|--all List both command and auxiliary commands
883 ** -o|--options List command-line options common to all commands
884 ** -s|--setting List setting names
885 ** -t|--test List unsupported "test" commands
886 ** -x|--aux List only auxiliary commands
887 ** -w|--www List all web pages
888 **
889 ** These options can be used when TOPIC is present:
890 **
891 ** -h|--html Format output as HTML rather than plain text
 
 
 
 
 
 
892 */
893 void help_cmd(void){
894 int rc;
895 int isPage = 0;
896 const char *z;
897 const char *zCmdOrPage;
898 const CmdOrPage *pCmd = 0;
899 int useHtml = 0;
900 Blob txt;
901 if( g.argc<3 ){
902 z = g.argv[0];
903 fossil_print(
904 "Usage: %s help TOPIC\n"
905 "Common commands: (use \"%s help help\" for more options)\n",
@@ -744,10 +930,11 @@
930 }
931 else if( find_option("setting","s",0) ){
932 command_list(0, CMDFLAG_SETTING);
933 return;
934 }
935 useHtml = find_option("html","h",0)!=0;
936 isPage = ('/' == *g.argv[2]) ? 1 : 0;
937 if(isPage){
938 zCmdOrPage = "page";
939 }else{
940 zCmdOrPage = "command or setting";
@@ -782,20 +969,18 @@
969 fossil_print("Setting: \"%s\"%s\n\n",
970 pCmd->zName,
971 (pCmd->eCmdFlags & CMDFLAG_VERSIONABLE)!=0 ? " (versionable)" : ""
972 );
973 }
974 blob_init(&txt, 0, 0);
975 if( useHtml ){
976 help_to_html(z, &txt);
977 }else{
978 help_to_text(z, &txt);
979 }
980 fossil_print("%s\n", blob_str(&txt));
981 blob_reset(&txt);
 
 
982 }
983
984 /*
985 ** Return a pointer to the setting information array.
986 **
987

Keyboard Shortcuts

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