Spaces:
Running
Running
parse-options API | |
================= | |
The parse-options API is used to parse and massage options in Git | |
and to provide a usage help with consistent look. | |
Basics | |
------ | |
The argument vector `argv[]` may usually contain mandatory or optional | |
'non-option arguments', e.g. a filename or a branch, 'options', and | |
'subcommands'. | |
Options are optional arguments that start with a dash and | |
that allow to change the behavior of a command. | |
* There are basically three types of options: | |
'boolean' options, | |
options with (mandatory) 'arguments' and | |
options with 'optional arguments' | |
(i.e. a boolean option that can be adjusted). | |
* There are basically two forms of options: | |
'Short options' consist of one dash (`-`) and one alphanumeric | |
character. | |
'Long options' begin with two dashes (`--`) and some | |
alphanumeric characters. | |
* Options are case-sensitive. | |
Please define 'lower-case long options' only. | |
The parse-options API allows: | |
* 'stuck' and 'separate form' of options with arguments. | |
`-oArg` is stuck, `-o Arg` is separate form. | |
`--option=Arg` is stuck, `--option Arg` is separate form. | |
* Long options may be 'abbreviated', as long as the abbreviation | |
is unambiguous. | |
* Short options may be bundled, e.g. `-a -b` can be specified as `-ab`. | |
* Boolean long options can be 'negated' (or 'unset') by prepending | |
`no-`, e.g. `--no-abbrev` instead of `--abbrev`. Conversely, | |
options that begin with `no-` can be 'negated' by removing it. | |
Other long options can be unset (e.g., set string to NULL, set | |
integer to 0) by prepending `no-`. | |
* Options and non-option arguments can clearly be separated using the `--` | |
option, e.g. `-a -b --option -- --this-is-a-file` indicates that | |
`--this-is-a-file` must not be processed as an option. | |
Subcommands are special in a couple of ways: | |
* Subcommands only have long form, and they have no double dash prefix, no | |
negated form, and no description, and they don't take any arguments, and | |
can't be abbreviated. | |
* There must be exactly one subcommand among the arguments, or zero if the | |
command has a default operation mode. | |
* All arguments following the subcommand are considered to be arguments of | |
the subcommand, and, conversely, arguments meant for the subcommand may | |
not precede the subcommand. | |
Therefore, if the options array contains at least one subcommand and | |
`parse_options()` encounters the first dashless argument, it will either: | |
* stop and return, if that dashless argument is a known subcommand, setting | |
`value` to the function pointer associated with that subcommand, storing | |
the name of the subcommand in argv[0], and leaving the rest of the | |
arguments unprocessed, or | |
* stop and return, if it was invoked with the `PARSE_OPT_SUBCOMMAND_OPTIONAL` | |
flag and that dashless argument doesn't match any subcommands, leaving | |
`value` unchanged and the rest of the arguments unprocessed, or | |
* show error and usage, and abort. | |
Steps to parse options | |
---------------------- | |
. `#include "parse-options.h"` | |
. define a NULL-terminated | |
`static const char * const builtin_foo_usage[]` array | |
containing alternative usage strings | |
. define `builtin_foo_options` array as described below | |
in section 'Data Structure'. | |
. in `cmd_foo(int argc, const char **argv, const char *prefix)` | |
call | |
argc = parse_options(argc, argv, prefix, builtin_foo_options, builtin_foo_usage, flags); | |
+ | |
`parse_options()` will filter out the processed options of `argv[]` and leave the | |
non-option arguments in `argv[]`. | |
`argc` is updated appropriately because of the assignment. | |
+ | |
You can also pass NULL instead of a usage array as the fifth parameter of | |
parse_options(), to avoid displaying a help screen with usage info and | |
option list. This should only be done if necessary, e.g. to implement | |
a limited parser for only a subset of the options that needs to be run | |
before the full parser, which in turn shows the full help message. | |
+ | |
Flags are the bitwise-or of: | |
`PARSE_OPT_KEEP_DASHDASH`:: | |
Keep the `--` that usually separates options from | |
non-option arguments. | |
`PARSE_OPT_STOP_AT_NON_OPTION`:: | |
Usually the whole argument vector is massaged and reordered. | |
Using this flag, processing is stopped at the first non-option | |
argument. | |
`PARSE_OPT_KEEP_ARGV0`:: | |
Keep the first argument, which contains the program name. It's | |
removed from argv[] by default. | |
`PARSE_OPT_KEEP_UNKNOWN_OPT`:: | |
Keep unknown options instead of erroring out. This doesn't | |
work for all combinations of arguments as users might expect | |
it to do. E.g. if the first argument in `--unknown --known` | |
takes a value (which we can't know), the second one is | |
mistakenly interpreted as a known option. Similarly, if | |
`PARSE_OPT_STOP_AT_NON_OPTION` is set, the second argument in | |
`--unknown value` will be mistakenly interpreted as a | |
non-option, not as a value belonging to the unknown option, | |
the parser early. That's why parse_options() errors out if | |
both options are set. | |
Note that non-option arguments are always kept, even without | |
this flag. | |
`PARSE_OPT_NO_INTERNAL_HELP`:: | |
By default, parse_options() handles `-h`, `--help` and | |
`--help-all` internally, by showing a help screen. This option | |
turns it off and allows one to add custom handlers for these | |
options, or to just leave them unknown. | |
`PARSE_OPT_SUBCOMMAND_OPTIONAL`:: | |
Don't error out when no subcommand is specified. | |
Note that `PARSE_OPT_STOP_AT_NON_OPTION` is incompatible with subcommands; | |
while `PARSE_OPT_KEEP_DASHDASH` and `PARSE_OPT_KEEP_UNKNOWN_OPT` can only be | |
used with subcommands when combined with `PARSE_OPT_SUBCOMMAND_OPTIONAL`. | |
Data Structure | |
-------------- | |
The main data structure is an array of the `option` struct, | |
say `static struct option builtin_add_options[]`. | |
There are some macros to easily define options: | |
`OPT__ABBREV(&int_var)`:: | |
Add `--abbrev[=<n>]`. | |
`OPT__COLOR(&int_var, description)`:: | |
Add `--color[=<when>]` and `--no-color`. | |
`OPT__DRY_RUN(&int_var, description)`:: | |
Add `-n, --dry-run`. | |
`OPT__FORCE(&int_var, description)`:: | |
Add `-f, --force`. | |
`OPT__QUIET(&int_var, description)`:: | |
Add `-q, --quiet`. | |
`OPT__VERBOSE(&int_var, description)`:: | |
Add `-v, --verbose`. | |
`OPT_GROUP(description)`:: | |
Start an option group. `description` is a short string that | |
describes the group or an empty string. | |
Start the description with an upper-case letter. | |
`OPT_BOOL(short, long, &int_var, description)`:: | |
Introduce a boolean option. `int_var` is set to one with | |
`--option` and set to zero with `--no-option`. | |
`OPT_COUNTUP(short, long, &int_var, description)`:: | |
Introduce a count-up option. | |
Each use of `--option` increments `int_var`, starting from zero | |
(even if initially negative), and `--no-option` resets it to | |
zero. To determine if `--option` or `--no-option` was encountered at | |
all, initialize `int_var` to a negative value, and if it is still | |
negative after parse_options(), then neither `--option` nor | |
`--no-option` was seen. | |
`OPT_BIT(short, long, &int_var, description, mask)`:: | |
Introduce a boolean option. | |
If used, `int_var` is bitwise-ored with `mask`. | |
`OPT_NEGBIT(short, long, &int_var, description, mask)`:: | |
Introduce a boolean option. | |
If used, `int_var` is bitwise-anded with the inverted `mask`. | |
`OPT_SET_INT(short, long, &int_var, description, integer)`:: | |
Introduce an integer option. | |
`int_var` is set to `integer` with `--option`, and | |
reset to zero with `--no-option`. | |
`OPT_STRING(short, long, &str_var, arg_str, description)`:: | |
Introduce an option with string argument. | |
The string argument is put into `str_var`. | |
`OPT_STRING_LIST(short, long, &struct string_list, arg_str, description)`:: | |
Introduce an option with string argument. | |
The string argument is stored as an element in `string_list`. | |
Use of `--no-option` will clear the list of preceding values. | |
`OPT_INTEGER(short, long, &int_var, description)`:: | |
Introduce an option with integer argument. | |
The integer is put into `int_var`. | |
`OPT_MAGNITUDE(short, long, &unsigned_long_var, description)`:: | |
Introduce an option with a size argument. The argument must be a | |
non-negative integer and may include a suffix of 'k', 'm' or 'g' to | |
scale the provided value by 1024, 1024^2 or 1024^3 respectively. | |
The scaled value is put into `unsigned_long_var`. | |
`OPT_EXPIRY_DATE(short, long, ×tamp_t_var, description)`:: | |
Introduce an option with expiry date argument, see `parse_expiry_date()`. | |
The timestamp is put into `timestamp_t_var`. | |
`OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`:: | |
Introduce an option with argument. | |
The argument will be fed into the function given by `func_ptr` | |
and the result will be put into `var`. | |
See 'Option Callbacks' below for a more elaborate description. | |
`OPT_FILENAME(short, long, &var, description)`:: | |
Introduce an option with a filename argument. | |
The filename will be prefixed by passing the filename along with | |
the prefix argument of `parse_options()` to `prefix_filename()`. | |
`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`:: | |
Recognize numerical options like -123 and feed the integer as | |
if it was an argument to the function given by `func_ptr`. | |
The result will be put into `var`. There can be only one such | |
option definition. It cannot be negated and it takes no | |
arguments. Short options that happen to be digits take | |
precedence over it. | |
`OPT_COLOR_FLAG(short, long, &int_var, description)`:: | |
Introduce an option that takes an optional argument that can | |
have one of three values: "always", "never", or "auto". If the | |
argument is not given, it defaults to "always". The `--no-` form | |
works like `--long=never`; it cannot take an argument. If | |
"always", set `int_var` to 1; if "never", set `int_var` to 0; if | |
"auto", set `int_var` to 1 if stdout is a tty or a pager, | |
0 otherwise. | |
`OPT_NOOP_NOARG(short, long)`:: | |
Introduce an option that has no effect and takes no arguments. | |
Use it to hide deprecated options that are still to be recognized | |
and ignored silently. | |
`OPT_PASSTHRU(short, long, &char_var, arg_str, description, flags)`:: | |
Introduce an option that will be reconstructed into a char* string, | |
which must be initialized to NULL. This is useful when you need to | |
pass the command-line option to another command. Any previous value | |
will be overwritten, so this should only be used for options where | |
the last one specified on the command line wins. | |
`OPT_PASSTHRU_ARGV(short, long, &strvec_var, arg_str, description, flags)`:: | |
Introduce an option where all instances of it on the command-line will | |
be reconstructed into a strvec. This is useful when you need to | |
pass the command-line option, which can be specified multiple times, | |
to another command. | |
`OPT_CMDMODE(short, long, &int_var, description, enum_val)`:: | |
Define an "operation mode" option, only one of which in the same | |
group of "operating mode" options that share the same `int_var` | |
can be given by the user. `int_var` is set to `enum_val` when the | |
option is used, but an error is reported if other "operating mode" | |
option has already set its value to the same `int_var`. | |
In new commands consider using subcommands instead. | |
`OPT_SUBCOMMAND(long, &fn_ptr, subcommand_fn)`:: | |
Define a subcommand. `subcommand_fn` is put into `fn_ptr` when | |
this subcommand is used. | |
The last element of the array must be `OPT_END()`. | |
If not stated otherwise, interpret the arguments as follows: | |
* `short` is a character for the short option | |
(e.g. `'e'` for `-e`, use `0` to omit), | |
* `long` is a string for the long option | |
(e.g. `"example"` for `--example`, use `NULL` to omit), | |
* `int_var` is an integer variable, | |
* `str_var` is a string variable (`char *`), | |
* `arg_str` is the string that is shown as argument | |
(e.g. `"branch"` will result in `<branch>`). | |
If set to `NULL`, three dots (`...`) will be displayed. | |
* `description` is a short string to describe the effect of the option. | |
It shall begin with a lower-case letter and a full stop (`.`) shall be | |
omitted at the end. | |
Option Callbacks | |
---------------- | |
The function must be defined in this form: | |
int func(const struct option *opt, const char *arg, int unset) | |
The callback mechanism is as follows: | |
* Inside `func`, the only interesting member of the structure | |
given by `opt` is the void pointer `opt->value`. | |
`*opt->value` will be the value that is saved into `var`, if you | |
use `OPT_CALLBACK()`. | |
For example, do `*(unsigned long *)opt->value = 42;` to get 42 | |
into an `unsigned long` variable. | |
* Return value `0` indicates success and non-zero return | |
value will invoke `usage_with_options()` and, thus, die. | |
* If the user negates the option, `arg` is `NULL` and `unset` is 1. | |
Sophisticated option parsing | |
---------------------------- | |
If you need, for example, option callbacks with optional arguments | |
or without arguments at all, or if you need other special cases, | |
that are not handled by the macros above, you need to specify the | |
members of the `option` structure manually. | |
This is not covered in this document, but well documented | |
in `parse-options.h` itself. | |
Examples | |
-------- | |
See `test-parse-options.c` and | |
`builtin/add.c`, | |
`builtin/clone.c`, | |
`builtin/commit.c`, | |
`builtin/fetch.c`, | |
`builtin/fsck.c`, | |
`builtin/rm.c` | |
for real-world examples. | |