GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-a277d8547c
parser_md_cli.c
Go to the documentation of this file.
1 /*!
2  \file lib/gis/parser_md_cli.c
3 
4  \brief GIS Library - Argument parsing functions (Markdown output - CLI)
5 
6  (C) 2025 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Vaclav Petras
12  */
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include <grass/gis.h>
17 #include <grass/glocale.h>
18 
19 #include "parser_local_proto.h"
20 
21 static void print_cli_flag(FILE *file, const char *key, const char *label,
22  const char *description, const char *indent);
23 static void print_cli_option(FILE *file, const struct Option *opt,
24  const char *indent);
25 static void print_cli_example(FILE *file, const char *indent);
26 
27 void print_cli_flag(FILE *file, const char *key, const char *label,
28  const char *description, const char *indent)
29 {
30  fprintf(file, "%s**", indent);
31  if (strlen(key) > 1)
32  fprintf(file, "-");
33  fprintf(file, "-%s**", key);
34  fprintf(file, MD_NEWLINE);
35  fprintf(file, "\n");
36  if (label != NULL) {
37  fprintf(file, "%s", indent);
39  G__md_print_escaped(file, label);
40  fprintf(file, MD_NEWLINE);
41  fprintf(file, "\n");
42  }
43  if (description != NULL) {
44  fprintf(file, "%s", indent);
46  G__md_print_escaped(file, description);
47  }
48 }
49 
50 void print_cli_option(FILE *file, const struct Option *opt, const char *indent)
51 {
52  const char *type;
53 
54  if (opt->key_desc != NULL)
55  type = opt->key_desc;
56  else
57  switch (opt->type) {
58  case TYPE_INTEGER:
59  type = "integer";
60  break;
61  case TYPE_DOUBLE:
62  type = "float";
63  break;
64  case TYPE_STRING:
65  type = "string";
66  break;
67  default:
68  type = "string";
69  break;
70  }
71  fprintf(file, "%s**%s**=", indent, opt->key);
72  fprintf(file, "*%s*", type);
73  if (opt->multiple) {
74  fprintf(file, " [,");
75  fprintf(file, "*%s*,...]", type);
76  }
77  /* fprintf(file, "*"); */
78  if (opt->required) {
79  fprintf(file, " **[required]**");
80  }
81  fprintf(file, MD_NEWLINE);
82  fprintf(file, "\n");
83  if (opt->label) {
84  fprintf(file, "%s", indent);
87  }
88  if (opt->description) {
89  if (opt->label) {
90  fprintf(file, MD_NEWLINE);
91  fprintf(file, "\n");
92  }
93  fprintf(file, "%s", indent);
96  }
97 
98  if (opt->options) {
99  fprintf(file, MD_NEWLINE);
100  fprintf(file, "\n");
101  fprintf(file, "%s", indent);
102  G__md_print_escaped(file, "\t");
103  fprintf(file, "%s: *", _("Allowed values"));
105  fprintf(file, "*");
106  }
107 
108  if (opt->def) {
109  fprintf(file, MD_NEWLINE);
110  fprintf(file, "\n");
111  fprintf(file, "%s", indent);
112  G__md_print_escaped(file, "\t");
113  fprintf(file, "%s:", _("Default"));
114  /* TODO check if value is empty
115  if (!opt->def.empty()){ */
116  fprintf(file, " *");
118  fprintf(file, "*");
119  }
120 
121  if (opt->descs) {
122  int i = 0;
123 
124  while (opt->opts[i]) {
125  if (opt->descs[i]) {
126  fprintf(file, MD_NEWLINE);
127  fprintf(file, "\n");
128  fprintf(file, "%s", indent);
129  char *thumbnails = NULL;
130  if (opt->gisprompt) {
131  if (strcmp(opt->gisprompt, "old,colortable,colortable") ==
132  0)
133  thumbnails = "colortables";
134  else if (strcmp(opt->gisprompt, "old,barscale,barscale") ==
135  0)
136  thumbnails = "barscales";
137  else if (strcmp(opt->gisprompt,
138  "old,northarrow,northarrow") == 0)
139  thumbnails = "northarrows";
140 
141  if (thumbnails) {
142  G__md_print_escaped(file, "\t\t");
143  fprintf(file, "![%s](%s/%s.png) ", opt->opts[i],
144  thumbnails, opt->opts[i]);
145  }
146  else {
147  G__md_print_escaped(file, "\t\t");
148  }
149  }
150  G__md_print_escaped(file, "\t");
151  fprintf(file, "**");
152  G__md_print_escaped(file, opt->opts[i]);
153  fprintf(file, "**: ");
154  G__md_print_escaped(file, opt->descs[i]);
155  }
156  i++;
157  }
158  }
159 }
160 
161 void print_cli_example(FILE *file, const char *indent)
162 {
163  fprintf(file, "\n%sExample:\n", indent);
164 
165  fprintf(file, "\n%s```sh\n", indent);
166  fprintf(file, "%s%s", indent, st->pgm_name);
167 
168  const struct Option *first_required_rule_option =
170  const struct Option *opt = NULL;
171  const char *type;
172 
173  if (st->n_opts) {
174  opt = &st->first_option;
175 
176  while (opt != NULL) {
177  if (opt->key_desc != NULL)
178  type = opt->key_desc;
179  else
180  switch (opt->type) {
181  case TYPE_INTEGER:
182  type = "integer";
183  break;
184  case TYPE_DOUBLE:
185  type = "float";
186  break;
187  case TYPE_STRING:
188  type = "string";
189  break;
190  default:
191  type = "string";
192  break;
193  }
194  if (opt->required || first_required_rule_option == opt) {
195  fprintf(file, " ");
196  fprintf(file, "%s=", opt->key);
197  if (opt->answer) {
198  fprintf(file, "%s", opt->answer);
199  }
200  else {
201  fprintf(file, "%s", type);
202  }
203  }
204  opt = opt->next_opt;
205  }
206  }
207  fprintf(file, "\n%s```\n", indent);
208 }
209 
210 void G__md_print_cli_short_version(FILE *file, const char *indent)
211 {
212  struct Option *opt;
213  struct Flag *flag;
214  const char *type;
215  int new_prompt = 0;
216 
217  new_prompt = G__uses_new_gisprompt();
218 
219  fprintf(file, "%s**%s**", indent, st->pgm_name);
220  fprintf(file, "\n");
221 
222  /* print short version first */
223  if (st->n_flags) {
224  flag = &st->first_flag;
225  fprintf(file, "%s[**-", indent);
226  while (flag != NULL) {
227  fprintf(file, "%c", flag->key);
228  flag = flag->next_flag;
229  }
230  fprintf(file, "**]");
231  fprintf(file, "\n");
232  }
233 
234  if (st->n_opts) {
235  opt = &st->first_option;
236 
237  while (opt != NULL) {
238  if (opt->key_desc != NULL)
239  type = opt->key_desc;
240  else
241  switch (opt->type) {
242  case TYPE_INTEGER:
243  type = "integer";
244  break;
245  case TYPE_DOUBLE:
246  type = "float";
247  break;
248  case TYPE_STRING:
249  type = "string";
250  break;
251  default:
252  type = "string";
253  break;
254  }
255  fprintf(file, "%s", indent);
256  if (!opt->required)
257  fprintf(file, "[");
258  fprintf(file, "**%s**=", opt->key);
259  fprintf(file, "*%s*", type);
260  if (opt->multiple) {
261  fprintf(file, " [,");
262  fprintf(file, "*%s*,...]", type);
263  }
264  if (!opt->required)
265  fprintf(file, "]");
266  fprintf(file, "\n");
267 
268  opt = opt->next_opt;
269  }
270  }
271  if (new_prompt)
272  fprintf(file, "%s[**--overwrite**]\n", indent);
273 
274  fprintf(file, "%s[**--verbose**]\n", indent);
275  fprintf(file, "%s[**--quiet**]\n", indent);
276  fprintf(file, "%s[**--qq**]\n", indent);
277  fprintf(file, "%s[**--ui**]\n", indent);
278 
279  print_cli_example(file, indent);
280 }
281 
282 void G__md_print_cli_long_version(FILE *file, const char *indent)
283 {
284  struct Option *opt;
285  struct Flag *flag;
286  int new_prompt = 0;
287 
288  new_prompt = G__uses_new_gisprompt();
289 
290  // Options (key-value parameters)
291  if (st->n_opts) {
292  opt = &st->first_option;
293  while (opt != NULL) {
294  print_cli_option(file, opt, indent);
295  opt = opt->next_opt;
296  fprintf(file, MD_NEWLINE);
297  fprintf(file, "\n");
298  }
299  }
300 
301  // Short (one-letter) flags and tool-specific long flags
302  if (st->n_flags || new_prompt) {
303  flag = &st->first_flag;
304  while (st->n_flags && flag != NULL) {
305  print_cli_flag(file, &flag->key, flag->label, flag->description,
306  indent);
307  fprintf(file, MD_NEWLINE);
308  fprintf(file, "\n");
309  flag = flag->next_flag;
310  }
311  if (new_prompt) {
312  print_cli_flag(file, "overwrite", NULL,
313  _("Allow output files to overwrite existing files"),
314  indent);
315  fprintf(file, MD_NEWLINE);
316  fprintf(file, "\n");
317  }
318  }
319  // Pre-defined long flags
320  print_cli_flag(file, "help", NULL, _("Print usage summary"), indent);
321  fprintf(file, MD_NEWLINE);
322  fprintf(file, "\n");
323  print_cli_flag(file, "verbose", NULL, _("Verbose module output"), indent);
324  fprintf(file, MD_NEWLINE);
325  fprintf(file, "\n");
326  print_cli_flag(file, "quiet", NULL, _("Quiet module output"), indent);
327  fprintf(file, MD_NEWLINE);
328  fprintf(file, "\n");
329  print_cli_flag(file, "qq", NULL, _("Very quiet module output"), indent);
330  fprintf(file, MD_NEWLINE);
331  fprintf(file, "\n");
332  print_cli_flag(file, "ui", NULL, _("Force launching GUI dialog"), indent);
333  fprintf(file, "\n");
334 }
#define NULL
Definition: ccmath.h:32
#define TYPE_STRING
Definition: gis.h:185
#define TYPE_INTEGER
Definition: gis.h:183
#define TYPE_DOUBLE
Definition: gis.h:184
#define _(str)
Definition: glocale.h:10
#define file
int G__uses_new_gisprompt(void)
Definition: parser.c:893
struct state * st
Definition: parser.c:104
const struct Option * G__first_required_option_from_rules(void)
void G__md_print_cli_long_version(FILE *file, const char *indent)
void G__md_print_cli_short_version(FILE *file, const char *indent)
void G__md_print_escaped(FILE *f, const char *str)
void G__md_print_escaped_for_options(FILE *f, const char *str)
Structure that stores flag info.
Definition: gis.h:588
struct Flag * next_flag
Definition: gis.h:597
const char * description
Definition: gis.h:594
char key
Definition: gis.h:589
const char * label
Definition: gis.h:593
Structure that stores option information.
Definition: gis.h:557
const char * key
Definition: gis.h:558
struct Option * next_opt
Definition: gis.h:574
const char * key_desc
Definition: gis.h:564
const char ** opts
Definition: gis.h:563
const char * gisprompt
Definition: gis.h:575
const char * label
Definition: gis.h:565
int type
Definition: gis.h:559
const char * def
Definition: gis.h:572
const char * description
Definition: gis.h:566
char * answer
Definition: gis.h:571
int required
Definition: gis.h:560
const char ** descs
Definition: gis.h:569
const char * options
Definition: gis.h:562
int multiple
Definition: gis.h:561