GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
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
21static void print_cli_flag(FILE *file, const char *key, const char *label,
22 const char *description, const char *indent);
23static void print_cli_option(FILE *file, const struct Option *opt,
24 const char *indent);
25static void print_cli_example(FILE *file, const char *indent);
26
27void 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);
35 fprintf(file, "\n");
36 if (label != NULL) {
37 fprintf(file, "%s", indent);
41 fprintf(file, "\n");
42 }
43 if (description != NULL) {
44 fprintf(file, "%s", indent);
46 G__md_print_escaped(file, description, indent);
47 }
48}
49
50void 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 }
82 fprintf(file, "\n");
83 if (opt->label) {
84 fprintf(file, "%s", indent);
87 }
88 if (opt->description) {
89 if (opt->label) {
91 fprintf(file, "\n");
92 }
93 fprintf(file, "%s", indent);
95 G__md_print_escaped(file, opt->description, indent);
96 }
97
98 if (opt->options) {
100 fprintf(file, "\n");
101 fprintf(file, "%s", indent);
103 fprintf(file, "%s: *", _("Allowed values"));
105 fprintf(file, "*");
106 }
107
108 if (opt->def && opt->def[0] != '\0') {
110 fprintf(file, "\n");
111 fprintf(file, "%s", indent);
113 fprintf(file, "%s:", _("Default"));
114 fprintf(file, " *");
116 fprintf(file, "*");
117 }
118
119 if (opt->descs) {
120 int i = 0;
121
122 while (opt->opts[i]) {
123 if (opt->descs[i]) {
125 fprintf(file, "\n");
126 fprintf(file, "%s", indent);
127 char *thumbnails = NULL;
128 if (opt->gisprompt) {
129 if (strcmp(opt->gisprompt, "old,colortable,colortable") ==
130 0)
131 thumbnails = "colortables";
132 else if (strcmp(opt->gisprompt, "old,barscale,barscale") ==
133 0)
134 thumbnails = "barscales";
135 else if (strcmp(opt->gisprompt,
136 "old,northarrow,northarrow") == 0)
137 thumbnails = "northarrows";
138
139 if (thumbnails) {
141 fprintf(file, "![%s](%s/%s.png) ", opt->opts[i],
142 thumbnails, opt->opts[i]);
143 }
144 else {
146 }
147 }
149 fprintf(file, "**");
151 fprintf(file, "**: ");
152 G__md_print_escaped(file, opt->descs[i], indent);
153 }
154 i++;
155 }
156 }
157}
158
159void print_cli_example(FILE *file, const char *indent)
160{
161 fprintf(file, "\n%sExample:\n", indent);
162
163 fprintf(file, "\n%s```sh\n", indent);
164 fprintf(file, "%s%s", indent, st->pgm_name);
165
166 const struct Option *first_required_rule_option =
168 const struct Option *opt = NULL;
169 const char *type;
170
171 if (st->n_opts) {
172 opt = &st->first_option;
173
174 while (opt != NULL) {
175 if (opt->key_desc != NULL)
176 type = opt->key_desc;
177 else
178 switch (opt->type) {
179 case TYPE_INTEGER:
180 type = "integer";
181 break;
182 case TYPE_DOUBLE:
183 type = "float";
184 break;
185 case TYPE_STRING:
186 type = "string";
187 break;
188 default:
189 type = "string";
190 break;
191 }
192 if (opt->required || first_required_rule_option == opt) {
193 fprintf(file, " ");
194 fprintf(file, "%s=", opt->key);
195
196 char *value = NULL;
197 if (opt->answer) {
198 value = G_store(opt->answer);
199 }
200 else if (opt->options && opt->type == TYPE_STRING) {
201 // Get example value from allowed values, but only for
202 // strings because numbers may have ranges and we don't
203 // want to print a range.
204 // Get allowed values as tokens.
205 char **tokens;
206 char delm[2];
207 delm[0] = ',';
208 delm[1] = '\0';
209 tokens = G_tokenize(opt->options, delm);
210 // We are interested in the first allowed value.
211 if (tokens[0]) {
212 G_chop(tokens[0]);
213 value = G_store(tokens[0]);
214 }
216 }
217
218 if (value) {
219 fprintf(file, "%s", value);
220 }
221 else {
222 if (opt->type == TYPE_INTEGER) {
223 fprintf(file, "0");
224 }
225 else if (opt->type == TYPE_DOUBLE) {
226 fprintf(file, "0.0");
227 }
228 else {
229 fprintf(file, "%s", type);
230 }
231 }
232 G_free(value);
233 }
234 opt = opt->next_opt;
235 }
236 }
237 fprintf(file, "\n%s```\n", indent);
238}
239
241{
242 struct Option *opt;
243 struct Flag *flag;
244 const char *type;
245 int new_prompt = 0;
246
248
249 fprintf(file, "%s**%s**", indent, st->pgm_name);
250 fprintf(file, "\n");
251
252 /* print short version first */
253 if (st->n_flags) {
254 flag = &st->first_flag;
255 fprintf(file, "%s[**-", indent);
256 while (flag != NULL) {
257 fprintf(file, "%c", flag->key);
258 flag = flag->next_flag;
259 }
260 fprintf(file, "**]");
261 fprintf(file, "\n");
262 }
263
264 if (st->n_opts) {
265 opt = &st->first_option;
266
267 while (opt != NULL) {
268 if (opt->key_desc != NULL)
269 type = opt->key_desc;
270 else
271 switch (opt->type) {
272 case TYPE_INTEGER:
273 type = "integer";
274 break;
275 case TYPE_DOUBLE:
276 type = "float";
277 break;
278 case TYPE_STRING:
279 type = "string";
280 break;
281 default:
282 type = "string";
283 break;
284 }
285 fprintf(file, "%s", indent);
286 if (!opt->required)
287 fprintf(file, "[");
288 fprintf(file, "**%s**=", opt->key);
289 fprintf(file, "*%s*", type);
290 if (opt->multiple) {
291 fprintf(file, " [,");
292 fprintf(file, "*%s*,...]", type);
293 }
294 if (!opt->required)
295 fprintf(file, "]");
296 fprintf(file, "\n");
297
298 opt = opt->next_opt;
299 }
300 }
301 if (new_prompt)
302 fprintf(file, "%s[**--overwrite**]\n", indent);
303
304 fprintf(file, "%s[**--verbose**]\n", indent);
305 fprintf(file, "%s[**--quiet**]\n", indent);
306 fprintf(file, "%s[**--qq**]\n", indent);
307 fprintf(file, "%s[**--ui**]\n", indent);
308
309 print_cli_example(file, indent);
310}
311
313{
314 struct Option *opt;
315 struct Flag *flag;
316 int new_prompt = 0;
317
319
320 // Options (key-value parameters)
321 if (st->n_opts) {
322 opt = &st->first_option;
323 while (opt != NULL) {
324 print_cli_option(file, opt, indent);
325 opt = opt->next_opt;
327 fprintf(file, "\n");
328 }
329 }
330
331 // Short (one-letter) flags and tool-specific long flags
332 if (st->n_flags || new_prompt) {
333 flag = &st->first_flag;
334 while (st->n_flags && flag != NULL) {
335 print_cli_flag(file, &flag->key, flag->label, flag->description,
336 indent);
338 fprintf(file, "\n");
339 flag = flag->next_flag;
340 }
341 if (new_prompt) {
342 print_cli_flag(file, "overwrite", NULL,
343 _("Allow output files to overwrite existing files"),
344 indent);
346 fprintf(file, "\n");
347 }
348 }
349 // Pre-defined long flags
350 print_cli_flag(file, "help", NULL, _("Print usage summary"), indent);
352 fprintf(file, "\n");
353 print_cli_flag(file, "verbose", NULL, _("Verbose module output"), indent);
355 fprintf(file, "\n");
356 print_cli_flag(file, "quiet", NULL, _("Quiet module output"), indent);
358 fprintf(file, "\n");
359 print_cli_flag(file, "qq", NULL, _("Very quiet module output"), indent);
361 fprintf(file, "\n");
362 print_cli_flag(file, "ui", NULL, _("Force launching GUI dialog"), indent);
363 fprintf(file, "\n");
364}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition gis/token.c:47
void G_free_tokens(char **)
Free memory allocated to tokens.
Definition gis/token.c:197
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition strings.c:332
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:87
#define TYPE_STRING
Definition gis.h:191
#define TYPE_INTEGER
Definition gis.h:189
#define TYPE_DOUBLE
Definition gis.h:190
#define _(str)
Definition glocale.h:10
#define file
int G__uses_new_gisprompt(void)
Definition parser.c:892
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, const char *indent)
void G__md_print_escaped_for_options(FILE *f, const char *str)
Structure that stores flag info.
Definition gis.h:594
Structure that stores option information.
Definition gis.h:563
int type
Definition gis.h:565