GRASS 8 Programmer's Manual 8.6.0dev(2026)-b0a6d7703c
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 SPDX-FileCopyrightText: 2025 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9 \author Vaclav Petras
10 */
11#include <stdio.h>
12#include <string.h>
13
14#include <grass/gis.h>
15#include <grass/glocale.h>
16
17#include "parser_local_proto.h"
18
19static void print_cli_flag(FILE *file, const char *key, const char *label,
20 const char *description, const char *indent);
21static void print_cli_option(FILE *file, const struct Option *opt,
22 const char *indent);
23static void print_cli_example(FILE *file, const char *indent);
24
25void print_cli_flag(FILE *file, const char *key, const char *label,
26 const char *description, const char *indent)
27{
28 fprintf(file, "%s**", indent);
29 if (strlen(key) > 1)
30 fprintf(file, "-");
31 fprintf(file, "-%s**", key);
33 fprintf(file, "\n");
34 if (label != NULL) {
35 fprintf(file, "%s", indent);
39 fprintf(file, "\n");
40 }
41 if (description != NULL) {
42 fprintf(file, "%s", indent);
44 G__md_print_escaped(file, description, indent);
45 }
46}
47
48void print_cli_option(FILE *file, const struct Option *opt, const char *indent)
49{
50 const char *type;
51
52 if (opt->key_desc != NULL)
53 type = opt->key_desc;
54 else
55 switch (opt->type) {
56 case TYPE_INTEGER:
57 type = "integer";
58 break;
59 case TYPE_DOUBLE:
60 type = "float";
61 break;
62 case TYPE_STRING:
63 type = "string";
64 break;
65 default:
66 type = "string";
67 break;
68 }
69 fprintf(file, "%s**%s**=", indent, opt->key);
70 fprintf(file, "*%s*", type);
71 if (opt->multiple) {
72 fprintf(file, " [,");
73 fprintf(file, "*%s*,...]", type);
74 }
75 /* fprintf(file, "*"); */
76 if (opt->required) {
77 fprintf(file, " **[required]**");
78 }
80 fprintf(file, "\n");
81 if (opt->label) {
82 fprintf(file, "%s", indent);
85 }
86 if (opt->description) {
87 if (opt->label) {
89 fprintf(file, "\n");
90 }
91 fprintf(file, "%s", indent);
93 G__md_print_escaped(file, opt->description, indent);
94 }
95
96 if (opt->options) {
98 fprintf(file, "\n");
99 fprintf(file, "%s", indent);
101 fprintf(file, "%s: *", _("Allowed values"));
103 fprintf(file, "*");
104 }
105
106 if (opt->def && opt->def[0] != '\0') {
108 fprintf(file, "\n");
109 fprintf(file, "%s", indent);
111 fprintf(file, "%s:", _("Default"));
112 fprintf(file, " *");
114 fprintf(file, "*");
115 }
116
117 if (opt->descs) {
118 int i = 0;
119
120 while (opt->opts[i]) {
121 if (opt->descs[i]) {
123 fprintf(file, "\n");
124 fprintf(file, "%s", indent);
125 char *thumbnails = NULL;
126 if (opt->gisprompt) {
127 if (strcmp(opt->gisprompt, "old,colortable,colortable") ==
128 0)
129 thumbnails = "colortables";
130 else if (strcmp(opt->gisprompt, "old,barscale,barscale") ==
131 0)
132 thumbnails = "barscales";
133 else if (strcmp(opt->gisprompt,
134 "old,northarrow,northarrow") == 0)
135 thumbnails = "northarrows";
136
137 if (thumbnails) {
139 fprintf(file, "![%s](%s/%s.png) ", opt->opts[i],
140 thumbnails, opt->opts[i]);
141 }
142 else {
144 }
145 }
147 fprintf(file, "**");
149 fprintf(file, "**: ");
150 G__md_print_escaped(file, opt->descs[i], indent);
151 }
152 i++;
153 }
154 }
155}
156
157void print_cli_example(FILE *file, const char *indent)
158{
159 fprintf(file, "\n%sExample:\n", indent);
160
161 fprintf(file, "\n%s```sh\n", indent);
162 fprintf(file, "%s%s", indent, st->pgm_name);
163
164 const struct Option *first_required_rule_option =
166 const struct Option *opt = NULL;
167 const char *type;
168
169 if (st->n_opts) {
170 opt = &st->first_option;
171
172 while (opt != NULL) {
173 if (opt->key_desc != NULL)
174 type = opt->key_desc;
175 else
176 switch (opt->type) {
177 case TYPE_INTEGER:
178 type = "integer";
179 break;
180 case TYPE_DOUBLE:
181 type = "float";
182 break;
183 case TYPE_STRING:
184 type = "string";
185 break;
186 default:
187 type = "string";
188 break;
189 }
190 if (opt->required || first_required_rule_option == opt) {
191 fprintf(file, " ");
192 fprintf(file, "%s=", opt->key);
193
194 char *value = NULL;
195 if (opt->answer) {
196 value = G_store(opt->answer);
197 }
198 else if (opt->options && opt->type == TYPE_STRING) {
199 // Get example value from allowed values, but only for
200 // strings because numbers may have ranges and we don't
201 // want to print a range.
202 // Get allowed values as tokens.
203 char **tokens;
204 char delm[2];
205 delm[0] = ',';
206 delm[1] = '\0';
207 tokens = G_tokenize(opt->options, delm);
208 // We are interested in the first allowed value.
209 if (tokens[0]) {
210 G_chop(tokens[0]);
211 value = G_store(tokens[0]);
212 }
214 }
215
216 if (value) {
217 fprintf(file, "%s", value);
218 }
219 else {
220 if (opt->type == TYPE_INTEGER) {
221 fprintf(file, "0");
222 }
223 else if (opt->type == TYPE_DOUBLE) {
224 fprintf(file, "0.0");
225 }
226 else {
227 fprintf(file, "%s", type);
228 }
229 }
230 G_free(value);
231 }
232 opt = opt->next_opt;
233 }
234 }
235 fprintf(file, "\n%s```\n", indent);
236}
237
239{
240 struct Option *opt;
241 struct Flag *flag;
242 const char *type;
243 int new_prompt = 0;
244
246
247 fprintf(file, "%s**%s**", indent, st->pgm_name);
248 fprintf(file, "\n");
249
250 /* print short version first */
251 if (st->n_flags) {
252 flag = &st->first_flag;
253 fprintf(file, "%s[**-", indent);
254 while (flag != NULL) {
255 fprintf(file, "%c", flag->key);
256 flag = flag->next_flag;
257 }
258 fprintf(file, "**]");
259 fprintf(file, "\n");
260 }
261
262 if (st->n_opts) {
263 opt = &st->first_option;
264
265 while (opt != NULL) {
266 if (opt->key_desc != NULL)
267 type = opt->key_desc;
268 else
269 switch (opt->type) {
270 case TYPE_INTEGER:
271 type = "integer";
272 break;
273 case TYPE_DOUBLE:
274 type = "float";
275 break;
276 case TYPE_STRING:
277 type = "string";
278 break;
279 default:
280 type = "string";
281 break;
282 }
283 fprintf(file, "%s", indent);
284 if (!opt->required)
285 fprintf(file, "[");
286 fprintf(file, "**%s**=", opt->key);
287 fprintf(file, "*%s*", type);
288 if (opt->multiple) {
289 fprintf(file, " [,");
290 fprintf(file, "*%s*,...]", type);
291 }
292 if (!opt->required)
293 fprintf(file, "]");
294 fprintf(file, "\n");
295
296 opt = opt->next_opt;
297 }
298 }
299 if (new_prompt)
300 fprintf(file, "%s[**--overwrite**]\n", indent);
301
302 fprintf(file, "%s[**--verbose**]\n", indent);
303 fprintf(file, "%s[**--quiet**]\n", indent);
304 fprintf(file, "%s[**--qq**]\n", indent);
305 fprintf(file, "%s[**--ui**]\n", indent);
306
307 print_cli_example(file, indent);
308}
309
311{
312 struct Option *opt;
313 struct Flag *flag;
314 int new_prompt = 0;
315
317
318 // Options (key-value parameters)
319 if (st->n_opts) {
320 opt = &st->first_option;
321 while (opt != NULL) {
322 print_cli_option(file, opt, indent);
323 opt = opt->next_opt;
325 fprintf(file, "\n");
326 }
327 }
328
329 // Short (one-letter) flags and tool-specific long flags
330 if (st->n_flags || new_prompt) {
331 flag = &st->first_flag;
332 while (st->n_flags && flag != NULL) {
333 print_cli_flag(file, &flag->key, flag->label, flag->description,
334 indent);
336 fprintf(file, "\n");
337 flag = flag->next_flag;
338 }
339 if (new_prompt) {
340 print_cli_flag(file, "overwrite", NULL,
341 _("Allow output files to overwrite existing files"),
342 indent);
344 fprintf(file, "\n");
345 }
346 }
347 // Pre-defined long flags
348 print_cli_flag(file, "help", NULL, _("Print usage summary"), indent);
350 fprintf(file, "\n");
351 print_cli_flag(file, "verbose", NULL, _("Verbose module output"), indent);
353 fprintf(file, "\n");
354 print_cli_flag(file, "quiet", NULL, _("Quiet module output"), indent);
356 fprintf(file, "\n");
357 print_cli_flag(file, "qq", NULL, _("Very quiet module output"), indent);
359 fprintf(file, "\n");
360 print_cli_flag(file, "ui", NULL, _("Force launching GUI dialog"), indent);
361 fprintf(file, "\n");
362}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition gis/token.c:45
void G_free_tokens(char **)
Free memory allocated to tokens.
Definition gis/token.c:195
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition strings.c:330
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
#define TYPE_STRING
Definition gis.h:188
#define TYPE_INTEGER
Definition gis.h:186
#define TYPE_DOUBLE
Definition gis.h:187
#define _(str)
Definition glocale.h:10
#define file
int G__uses_new_gisprompt(void)
Definition parser.c:890
struct state * st
Definition parser.c:102
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:591
Structure that stores option information.
Definition gis.h:560
int type
Definition gis.h:562