Basic usage¶
If you are new to argparse-c, the easiest mental model is this four-step flow:
- Create a parser with
ap_parser_new(...) - Define arguments with
ap_add_argument(...) - Parse the command line with
ap_parse_args(...) - Read results with
ap_ns_get_*
Optional arguments¶
ap_arg_options text = ap_arg_options_default();
text.required = true;
text.help = "text value";
ap_add_argument(parser, "-t, --text", text, &err);
- accepts both
-tand--text - becomes mandatory when
required = true
Positional arguments¶
ap_arg_options input = ap_arg_options_default();
input.help = "input file";
ap_add_argument(parser, "input", input, &err);
- positionals are declared without flags
- they appear as positional entries in usage/help
Argument groups (custom help sections)¶
Use argument groups when you want related arguments to appear under a titled section in help output.
ap_argument_group *output = ap_add_argument_group(
parser, "output", "output formatting controls", &err);
ap_arg_options color = ap_arg_options_default();
color.help = "color mode";
ap_argument_group_add_argument(output, "--color", color, &err);
ap_arg_options target = ap_arg_options_default();
target.help = "target file";
ap_argument_group_add_argument(output, "target", target, &err);
Notes:
titleis required forap_add_argument_group(...)- grouped arguments are parsed the same way as regular arguments
- grouped arguments are shown in their custom section in
ap_format_help(...)
Reusing common parser options¶
Use ap_parser_new_with_options(...) with inherit_from when multiple
commands should share a common option set (including argument groups and
mutually exclusive groups).
ap_parser *common = ap_parser_new("common", "shared options");
ap_arg_options verbose = ap_arg_options_default();
verbose.type = AP_TYPE_BOOL;
verbose.action = AP_ACTION_STORE_TRUE;
ap_add_argument(common, "--verbose", verbose, &err);
ap_parser_options child_opts = ap_parser_options_default();
child_opts.inherit_from = common;
/* default: AP_PARSER_CONFLICT_ERROR */
ap_parser *child = ap_parser_new_with_options("child", "subcommand", child_opts);
Conflict behavior for inherited definitions:
AP_PARSER_CONFLICT_ERROR(default): adding an argument that reuses an inheriteddestor flag fails.AP_PARSER_CONFLICT_KEEP_EXISTING: inherited definitions win during import.AP_PARSER_CONFLICT_REPLACE: inherited definitions can be replaced by the new parser (for overrides/customization).
ap_parser_options deep dive (prefix_chars / allow_abbrev)¶
When you need to match an existing CLI style, start from
ap_parser_options_default() and override only the behavior you need.
ap_parser_options options = ap_parser_options_default();
options.prefix_chars = "+";
options.allow_abbrev = true;
ap_parser *parser = ap_parser_new_with_options("example1", "custom prefixes", options);
Example: changing prefix_chars from - to +¶
Below is a short diff equivalent to sample/example1.c style.
- ap_parser *parser = ap_parser_new("example1", "example1 command.");
+ ap_parser_options options = ap_parser_options_default();
+ options.prefix_chars = "+";
+ ap_parser *parser =
+ ap_parser_new_with_options("example1", "example1 command.", options);
- ap_add_argument(parser, "-t, --text", text_opts, &err);
+ ap_add_argument(parser, "+t, ++text", text_opts, &err);
- ap_add_argument(parser, "-i, --integer", integer_opts, &err);
+ ap_add_argument(parser, "+i, ++integer", integer_opts, &err);
Usage/help output also changes to +/++ style:
usage: example1 [+h] +t TEXT [+i INTEGER] arg1 [arg2]
optional arguments:
+h, ++help show this help message and exit
+t TEXT, ++text TEXT text field.
+i INTEGER, ++integer INTEGER
integer field.
Example: allow_abbrev=true vs false (including collisions)¶
Assume both ++verbose and ++version exist.
allow_abbrev = false(default)++veris treated as an unknown option, because only exact matches are accepted.allow_abbrev = true++verbecomes ambiguous and parsing fails because it can match multiple long options.++verbresolves to++verbose(unique prefix).
# allow_abbrev=false
$ prog ++ver
error: unknown option '++ver'
# allow_abbrev=true, collision case
$ prog ++ver
error: ambiguous option '++ver'
Compatibility risks with existing CLIs¶
Changing ap_parser_options can break callers and scripts unexpectedly:
- Shell scripts / CI jobs: existing invocations using
-x/--longfail after switchingprefix_chars. - Documentation drift: README/help snippets become stale unless updated together.
- Abbreviation policy surprises: enabling
allow_abbrevmay introduce future breakage when new long options create a prefix collision.
Practical rollout tips:
- Keep
allow_abbrev=falseunless you need compatibility with an abbreviation-friendly CLI. - If you change
prefix_chars, consider a transition period with wrapper commands or a major-version bump. - Add parse tests for both expected success patterns and ambiguous-prefix failures.
Error handling¶
argparse-c does not call exit() inside the library. On failure, inspect ap_error and optionally render a user-facing message with ap_format_error(...).
if (ap_parse_args(parser, argc, argv, &ns, &err) != 0) {
char *message = ap_format_error(parser, &err);
fprintf(stderr, "%s", message ? message : err.message);
free(message);
}
Help output¶
-h/--help is added automatically.
You can switch help formatter mode via ap_parser_options.
ap_parser_options options = ap_parser_options_default();
options.help_formatter_mode = AP_HELP_FORMATTER_RAW_TEXT;
ap_parser *raw_parser =
ap_parser_new_with_options("demo", "raw help style", options);
options.help_formatter_mode = AP_HELP_FORMATTER_SHOW_DEFAULTS;
ap_parser *defaults_parser =
ap_parser_new_with_options("demo", "explicit defaults style", options);
Sample: example_test_runner¶
sample/example_test_runner.c is a minimal sample that verifies argument
parsing behavior in a unit-test-like style (success and failure cases in one
small program).
Build and run:
Expected output includes PASS lines for each case, for example:
PASS: success case parsed --count=3 name=alicePASS: invalid-int case failed as expectedPASS: missing-positional case failed as expectedPASS: all tests passed