GRASS GIS 8 Programmer's Manual 8.4.2(2025)-exported
Loading...
Searching...
No Matches
parser_rest_md.c
Go to the documentation of this file.
1/*!
2 \file lib/gis/parser_rest_md.c
3
4 \brief GIS Library - Argument parsing functions (reStructuredText and
5 Markdown output)
6
7 (C) 2012-2023 by the GRASS Development Team
8
9 This program is free software under the GNU General Public License
10 (>=v2). Read the file COPYING that comes with GRASS for details.
11
12 \author Luca Delucchi
13 \author Martin Landa (Markdown added)
14 */
15#include <stdbool.h>
16#include <stdio.h>
17#include <string.h>
18
19#include <grass/gis.h>
20#include <grass/glocale.h>
21
22#include "parser_local_proto.h"
23
24static void usage_rest_md(bool rest);
25static void print_flag(const char *key, const char *label,
26 const char *description, bool rest);
27void print_option(const struct Option *opt, bool rest, char *);
28static void print_escaped(FILE *f, const char *str, bool rest);
29static void print_escaped_for_rest(FILE *f, const char *str);
30static void print_escaped_for_md(FILE *f, const char *str);
31static void print_escaped_for_rest_options(FILE *f, const char *str);
32static void print_escaped_for_md_keywords(FILE *f, const char *str);
33
34/*!
35 \brief Print module usage description in reStructuredText or in Markdown
36 format.
37
38 \param bool rest TRUE for reStructuredText otherwise Markdown
39 */
40void usage_rest_md(bool rest)
41{
42 struct Option *opt;
43 struct Flag *flag;
44 const char *type;
45 char *header = NULL;
46 int new_prompt = 0;
47
48 new_prompt = G__uses_new_gisprompt();
49
50 if (!st->pgm_name)
51 st->pgm_name = G_program_name();
52 if (!st->pgm_name)
53 st->pgm_name = "??";
54
55 /* main header */
56 G_asprintf(&header, "%s - GRASS GIS manual", st->pgm_name);
57 if (rest) {
58 size_t s;
59 fprintf(stdout, "%s\n", header);
60 for (s = 0; s < strlen(header); s++) {
61 fprintf(stdout, "=");
62 }
63 fprintf(stdout, "\n");
64 }
65 else {
66 fprintf(stdout, "# %s\n", header);
67 }
68 fprintf(stdout, "\n");
69
70 /* GRASS GIS logo */
71 if (rest) {
72 fprintf(stdout, ".. image:: grass_logo.png\n");
73 fprintf(stdout, " :align: center\n");
74 fprintf(stdout, " :alt: GRASS logo\n");
75 }
76 else {
77 fprintf(stdout, "![GRASS logo](./grass_logo.png)\n");
78 }
79 /* horizontal line */
80 fprintf(stdout, "\n---");
81 if (rest)
82 fprintf(stdout, "-");
83 fprintf(stdout, "\n\n");
84
85 /* header - GRASS module */
86 if (!rest)
87 fprintf(stdout, "## ");
88 fprintf(stdout, "%s\n", _("NAME"));
89 if (rest)
90 fprintf(stdout, "----");
91 fprintf(stdout, "\n");
92 fprintf(stdout, "**%s**", st->pgm_name);
93
94 if (st->module_info.label || st->module_info.description)
95 fprintf(stdout, " - ");
96
97 if (st->module_info.label)
98 fprintf(stdout, "%s\n", st->module_info.label);
99
100 if (st->module_info.description) {
101 if (st->module_info.label)
102 fprintf(stdout, "\n");
103 fprintf(stdout, "%s\n", st->module_info.description);
104 }
105 fprintf(stdout, "\n");
106 if (!rest)
107 fprintf(stdout, "### ");
108 fprintf(stdout, "%s\n", _("KEYWORDS"));
109 if (rest)
110 fprintf(stdout, "--------\n");
111 fprintf(stdout, "\n");
112 if (st->module_info.keywords) {
113 if (rest) {
114 G__print_keywords(stdout, NULL, FALSE);
115 fprintf(stdout, "\n");
116 }
117 else {
118 G__print_keywords(stdout, print_escaped_for_md_keywords, TRUE);
119 }
120 }
121 fprintf(stdout, "\n");
122 if (!rest)
123 fprintf(stdout, "### ");
124 fprintf(stdout, "%s\n", _("SYNOPSIS"));
125 if (rest) {
126 fprintf(stdout, "--------\n\n");
127 fprintf(stdout, "| ");
128 }
129 else {
130 fprintf(stdout, "\n");
131 }
132 fprintf(stdout, "**%s**", st->pgm_name);
133 if (!rest)
134 fprintf(stdout, "\\");
135 fprintf(stdout, "\n");
136 if (rest)
137 fprintf(stdout, "| ");
138 fprintf(stdout, "**%s --help**", st->pgm_name);
139 if (!rest)
140 fprintf(stdout, "\\");
141 fprintf(stdout, "\n");
142 if (rest)
143 fprintf(stdout, "| ");
144 fprintf(stdout, "**%s**", st->pgm_name);
145
146 /* print short version first */
147 if (st->n_flags) {
148 flag = &st->first_flag;
149 fprintf(stdout, " [**-");
150 while (flag != NULL) {
151 fprintf(stdout, "%c", flag->key);
152 flag = flag->next_flag;
153 }
154 fprintf(stdout, "**] ");
155 }
156 else
157 fprintf(stdout, " ");
158
159 if (st->n_opts) {
160 opt = &st->first_option;
161
162 while (opt != NULL) {
163 if (opt->key_desc != NULL)
164 type = opt->key_desc;
165 else
166 switch (opt->type) {
167 case TYPE_INTEGER:
168 type = "integer";
169 break;
170 case TYPE_DOUBLE:
171 type = "float";
172 break;
173 case TYPE_STRING:
174 type = "string";
175 break;
176 default:
177 type = "string";
178 break;
179 }
180 fprintf(stdout, " ");
181 if (!opt->required)
182 fprintf(stdout, "[");
183 fprintf(stdout, "**%s**=", opt->key);
184 if (rest)
185 fprintf(stdout, "\\ ");
186 fprintf(stdout, "*%s*", type);
187 if (opt->multiple) {
188 fprintf(stdout, " [,");
189 if (rest)
190 fprintf(stdout, "\\ ");
191 fprintf(stdout, "*%s*,...]", type);
192 }
193 if (!opt->required)
194 fprintf(stdout, "]");
195 if (rest)
196 fprintf(stdout, " ");
197 else
198 fprintf(stdout, "\n");
199
200 opt = opt->next_opt;
201 }
202 }
203 if (new_prompt)
204 fprintf(stdout, " [**--overwrite**] ");
205
206 fprintf(stdout, " [**--verbose**] ");
207 fprintf(stdout, " [**--quiet**] ");
208 fprintf(stdout, " [**--ui**]\n");
209
210 /* now long version */
211 fprintf(stdout, "\n");
212 if (st->n_flags || new_prompt) {
213 flag = &st->first_flag;
214 if (!rest)
215 fprintf(stdout, "#### ");
216 fprintf(stdout, "%s\n", _("Flags"));
217 if (rest)
218 fprintf(stdout, "~~~~~~\n");
219 fprintf(stdout, "\n");
220 while (st->n_flags && flag != NULL) {
221 print_flag(&flag->key, flag->label, flag->description, rest);
222 if (!rest)
223 fprintf(stdout, "\\");
224 fprintf(stdout, "\n");
225 flag = flag->next_flag;
226 }
227 if (new_prompt) {
228 print_flag("overwrite", NULL,
229 _("Allow output files to overwrite existing files"),
230 rest);
231 if (!rest)
232 fprintf(stdout, "\\");
233 fprintf(stdout, "\n");
234 }
235 }
236 print_flag("help", NULL, _("Print usage summary"), rest);
237 if (!rest)
238 fprintf(stdout, "\\");
239 fprintf(stdout, "\n");
240 print_flag("verbose", NULL, _("Verbose module output"), rest);
241 if (!rest)
242 fprintf(stdout, "\\");
243 fprintf(stdout, "\n");
244 print_flag("quiet", NULL, _("Quiet module output"), rest);
245 if (!rest)
246 fprintf(stdout, "\\");
247 fprintf(stdout, "\n");
248 print_flag("ui", NULL, _("Force launching GUI dialog"), rest);
249 fprintf(stdout, "\n");
250
251 if (st->n_opts) {
252 fprintf(stdout, "\n");
253 opt = &st->first_option;
254 if (!rest)
255 fprintf(stdout, "#### ");
256 fprintf(stdout, "%s\n", _("Parameters"));
257 if (rest)
258 fprintf(stdout, "~~~~~~~~~~~\n");
259 fprintf(stdout, "\n");
260 char image_spec_rest[GPATH_MAX];
261 image_spec_rest[0] = '\0';
262 while (opt != NULL) {
263 print_option(opt, rest, image_spec_rest);
264 opt = opt->next_opt;
265 if (opt != NULL) {
266 if (!rest)
267 fprintf(stdout, "\\");
268 }
269 fprintf(stdout, "\n");
270 }
271 if (strlen(image_spec_rest) > 0) {
272 fprintf(stdout, "\n");
273 fprintf(stdout, "%s", image_spec_rest);
274 }
275 }
276}
277
278void print_flag(const char *key, const char *label, const char *description,
279 bool rest)
280{
281 if (rest)
282 fprintf(stdout, "| ");
283 fprintf(stdout, "**");
284 if (strlen(key) > 1)
285 fprintf(stdout, "-");
286 fprintf(stdout, "-%s**", key);
287 if (!rest)
288 fprintf(stdout, "\\");
289 fprintf(stdout, "\n");
290 if (label != NULL) {
291 if (rest)
292 fprintf(stdout, "| ");
293 print_escaped(stdout, "\t", rest);
294 print_escaped(stdout, label, rest);
295 if (!rest)
296 fprintf(stdout, "\\");
297 fprintf(stdout, "\n");
298 }
299 if (rest)
300 fprintf(stdout, "| ");
301 print_escaped(stdout, "\t", rest);
302 print_escaped(stdout, description, rest);
303}
304
305void print_option(const struct Option *opt, bool rest, char *image_spec_rest)
306{
307 const char *type;
308
309 /* TODO: make this a enumeration type? */
310 if (opt->key_desc != NULL)
311 type = opt->key_desc;
312 else
313 switch (opt->type) {
314 case TYPE_INTEGER:
315 type = "integer";
316 break;
317 case TYPE_DOUBLE:
318 type = "float";
319 break;
320 case TYPE_STRING:
321 type = "string";
322 break;
323 default:
324 type = "string";
325 break;
326 }
327
328 if (rest)
329 fprintf(stdout, "| ");
330 fprintf(stdout, "**%s**=", opt->key);
331 if (rest)
332 fprintf(stdout, "\\ ");
333 fprintf(stdout, "*%s*", type);
334 if (opt->multiple) {
335 fprintf(stdout, " [,");
336 if (rest)
337 fprintf(stdout, "\\ ");
338 fprintf(stdout, "*%s*,...]", type);
339 }
340 /* fprintf(stdout, "*"); */
341 if (opt->required) {
342 fprintf(stdout, " **[required]**");
343 }
344 if (!rest)
345 fprintf(stdout, "\\");
346 fprintf(stdout, "\n");
347 if (opt->label) {
348 if (rest)
349 fprintf(stdout, "| ");
350 print_escaped(stdout, "\t", rest);
351 print_escaped(stdout, opt->label, rest);
352 }
353 if (opt->description) {
354 if (opt->label) {
355 if (!rest)
356 fprintf(stdout, "\\");
357 fprintf(stdout, "\n");
358 }
359 if (rest)
360 fprintf(stdout, "| ");
361 print_escaped(stdout, "\t", rest);
362 print_escaped(stdout, opt->description, rest);
363 }
364
365 if (opt->options) {
366 if (!rest)
367 fprintf(stdout, "\\");
368 fprintf(stdout, "\n");
369 if (rest)
370 fprintf(stdout, "| ");
371 print_escaped(stdout, "\t", rest);
372 fprintf(stdout, "%s: *", _("Options"));
373 print_escaped_for_rest_options(stdout, opt->options);
374 fprintf(stdout, "*");
375 }
376
377 if (opt->def) {
378 if (!rest)
379 fprintf(stdout, "\\");
380 fprintf(stdout, "\n");
381 if (rest)
382 fprintf(stdout, "| ");
383 print_escaped(stdout, "\t", rest);
384 fprintf(stdout, "%s:", _("Default"));
385 /* TODO check if value is empty
386 if (!opt->def.empty()){ */
387 fprintf(stdout, " *");
388 print_escaped(stdout, opt->def, rest);
389 fprintf(stdout, "*");
390 }
391
392 if (opt->descs) {
393 int i = 0;
394
395 while (opt->opts[i]) {
396 if (opt->descs[i]) {
397 if (!rest)
398 fprintf(stdout, "\\");
399 fprintf(stdout, "\n");
400 char *thumbnails = NULL;
401 if (opt->gisprompt) {
402 if (strcmp(opt->gisprompt, "old,colortable,colortable") ==
403 0)
404 thumbnails = "colortables";
405 else if (strcmp(opt->gisprompt, "old,barscale,barscale") ==
406 0)
407 thumbnails = "barscales";
408 else if (strcmp(opt->gisprompt,
409 "old,northarrow,northarrow") == 0)
410 thumbnails = "northarrows";
411
412 if (thumbnails) {
413 if (rest) {
414 char *image_spec;
415 G_asprintf(&image_spec,
416 ".. |%s| image:: %s/%s.png\n",
417 opt->opts[i], thumbnails, opt->opts[i]);
418 strcat(image_spec_rest, image_spec);
419 }
420 else {
421 print_escaped(stdout, "\t\t", rest);
422 fprintf(stdout, "![%s](%s/%s.png) ", opt->opts[i],
423 thumbnails, opt->opts[i]);
424 }
425 }
426 else {
427 if (rest)
428 fprintf(stdout, "| ");
429 print_escaped(stdout, "\t\t", rest);
430 if (rest)
431 fprintf(stdout, "\\ ");
432 }
433 }
434
435 if (rest && thumbnails) {
436 fprintf(stdout, "| ");
437 print_escaped(stdout, "\t\t", rest);
438 fprintf(stdout, "|%s| ", opt->opts[i]);
439 }
440 if (!rest)
441 print_escaped(stdout, "\t", rest);
442 fprintf(stdout, "**");
443 print_escaped(stdout, opt->opts[i], rest);
444 fprintf(stdout, "**: ");
445 print_escaped(stdout, opt->descs[i], rest);
446 }
447 i++;
448 }
449 }
450}
451
452/*!
453 * \brief Format text for reStructuredText output
454 */
455#define do_escape(c, escaped) \
456 case c: \
457 fputs(escaped, f); \
458 break
459
460void print_escaped(FILE *f, const char *str, bool rest)
461{
462 if (rest)
463 print_escaped_for_rest(f, str);
464 else
465 print_escaped_for_md(f, str);
466}
467
468void print_escaped_for_rest(FILE *f, const char *str)
469{
470 const char *s;
471
472 for (s = str; *s; s++) {
473 switch (*s) {
474 do_escape('\n', "\n\n");
475 do_escape('\t', " ");
476 default:
477 fputc(*s, f);
478 }
479 }
480}
481
482void print_escaped_for_md(FILE *f, const char *str)
483{
484 const char *s;
485
486 for (s = str; *s; s++) {
487 switch (*s) {
488 do_escape('\n', "\\\n");
489 do_escape('\t', "&nbsp;&nbsp;&nbsp;&nbsp;");
490 do_escape('<', "&lt;");
491 do_escape('>', "&gt;");
492 do_escape('*', "\\*");
493 default:
494 fputc(*s, f);
495 }
496 }
497}
498
499void print_escaped_for_rest_options(FILE *f, const char *str)
500{
501 const char *s;
502
503 for (s = str; *s; s++) {
504 switch (*s) {
505 do_escape('\n', "\n\n");
506 do_escape(',', ", ");
507 default:
508 fputc(*s, f);
509 }
510 }
511}
512
513/* generate HTML links */
514void print_escaped_for_md_keywords(FILE *f, const char *str)
515{
516 /* removes all leading and trailing white space from keyword
517 string, as spotted in Japanese and other locales. */
518 char *str_s;
519 str_s = G_store(str);
520 G_strip(str_s);
521
522 /* HTML link only for second keyword */
523 if (st->n_keys > 1 && strcmp(st->module_info.keywords[1], str) == 0) {
524
525 const char *s;
526
527 /* TODO: fprintf(f, _("topic: ")); */
528 fprintf(f, "[%s](topic_", str_s);
529 for (s = str_s; *s; s++) {
530 switch (*s) {
531 do_escape(' ', "_");
532 default:
533 fputc(*s, f);
534 }
535 }
536 fprintf(f, ".html)");
537 }
538 else { /* first and other than second keyword */
539 if (st->n_keys > 0 && strcmp(st->module_info.keywords[0], str) == 0) {
540 /* command family */
541 const char *s;
542
543 fprintf(f, "[%s](", str_s);
544 for (s = str_s; *s; s++) {
545 switch (*s) {
546 do_escape(' ', "_");
547 default:
548 fputc(*s, f);
549 }
550 }
551 fprintf(f, ".html)");
552 }
553 else {
554 /* keyword index */
555 char *str_link;
556 str_link = G_str_replace(str_s, " ", "%20");
557 fprintf(f, "[%s](keywords.html#%s)", str_s, str_link);
558 G_free(str_link);
559 }
560 }
561
562 G_free(str_s);
563}
564
565#undef do_escape
566
567/*!
568 \brief Print module usage description in reStructuredText format.
569*/
571{
572 usage_rest_md(TRUE);
573}
574
575/*!
576 \brief Print module usage description in Markdown format.
577*/
579{
580 usage_rest_md(FALSE);
581}
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
int G_asprintf(char **out, const char *fmt,...)
Definition asprintf.c:69
#define NULL
Definition ccmath.h:32
#define TRUE
Definition dbfopen.c:75
#define FALSE
Definition dbfopen.c:74
void G__print_keywords(FILE *fd, void(*format)(FILE *, const char *), int newline)
Print list of keywords (internal use only)
Definition parser.c:927
int G__uses_new_gisprompt(void)
Definition parser.c:890
struct state * st
Definition parser.c:104
#define do_escape(c, escaped)
Format text for reStructuredText output.
void G__usage_markdown(void)
Print module usage description in Markdown format.
void G__usage_rest(void)
Print module usage description in reStructuredText format.
void print_option(const struct Option *opt, bool rest, char *)
const char * G_program_name(void)
Return module name.
Definition progrm_nme.c:28
char * G_str_replace(const char *buffer, const char *old_str, const char *new_str)
Replace all occurrences of old_str in buffer with new_str.
Definition strings.c:189
char * G_store(const char *s)
Copy string to allocated memory.
Definition strings.c:87
void G_strip(char *buf)
Removes all leading and trailing white space from string.
Definition strings.c:300