| 288 | } |
| 289 | |
| 290 | void |
| 291 | argparse_usage(struct argparse *self) |
| 292 | { |
| 293 | if (self->usages) { |
| 294 | fprintf(stdout, "Usage: %s\n", *self->usages++); |
| 295 | while (*self->usages && **self->usages) |
| 296 | fprintf(stdout, " or: %s\n", *self->usages++); |
| 297 | } else { |
| 298 | fprintf(stdout, "Usage:\n"); |
| 299 | } |
| 300 | |
| 301 | // print description |
| 302 | if (self->description) |
| 303 | fprintf(stdout, "%s\n", self->description); |
| 304 | |
| 305 | fputc('\n', stdout); |
| 306 | |
| 307 | const struct argparse_option *options; |
| 308 | |
| 309 | // figure out best width |
| 310 | size_t usage_opts_width = 0; |
| 311 | size_t len; |
| 312 | options = self->options; |
| 313 | for (; options->type != ARGPARSE_OPT_END; options++) { |
| 314 | len = 0; |
| 315 | if ((options)->short_name) { |
| 316 | len += 2; |
| 317 | } |
| 318 | if ((options)->short_name && (options)->long_name) { |
| 319 | len += 2; // separator ", " |
| 320 | } |
| 321 | if ((options)->long_name) { |
| 322 | len += strlen((options)->long_name) + 2; |
| 323 | } |
| 324 | if (options->type == ARGPARSE_OPT_INTEGER) { |
| 325 | len += strlen("=<int>"); |
| 326 | } |
| 327 | if (options->type == ARGPARSE_OPT_FLOAT) { |
| 328 | len += strlen("=<flt>"); |
| 329 | } else if (options->type == ARGPARSE_OPT_STRING) { |
| 330 | len += strlen("=<str>"); |
| 331 | } |
| 332 | len = (len + 3) - ((len + 3) & 3); |
| 333 | if (usage_opts_width < len) { |
| 334 | usage_opts_width = len; |
| 335 | } |
| 336 | } |
| 337 | usage_opts_width += 4; // 4 spaces prefix |
| 338 | |
| 339 | options = self->options; |
| 340 | for (; options->type != ARGPARSE_OPT_END; options++) { |
| 341 | size_t pos = 0; |
| 342 | size_t pad = 0; |
| 343 | if (options->type == ARGPARSE_OPT_GROUP) { |
| 344 | fputc('\n', stdout); |
| 345 | fprintf(stdout, "%s", options->help); |
| 346 | fputc('\n', stdout); |
| 347 | continue; |
no outgoing calls
no test coverage detected