You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
278 lines
9.4 KiB
278 lines
9.4 KiB
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, and 'options'. |
|
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: |
|
|
|
* 'sticked' and 'separate form' of options with arguments. |
|
`-oArg` is sticked, `-o Arg` is separate form. |
|
`--option=Arg` is sticked, `--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. |
|
|
|
* 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. |
|
|
|
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`:: |
|
Keep unknown arguments 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. |
|
|
|
`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. |
|
|
|
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. |
|
`int_var` is incremented on each use of `--option`, and |
|
reset to zero with `--no-option`. |
|
|
|
`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_SET_PTR(short, long, &ptr_var, description, ptr)`:: |
|
Introduce a boolean option. |
|
If used, set `ptr_var` to `ptr`. |
|
|
|
`OPT_STRING(short, long, &str_var, arg_str, description)`:: |
|
Introduce an option with string argument. |
|
The string argument is put into `str_var`. |
|
|
|
`OPT_INTEGER(short, long, &int_var, description)`:: |
|
Introduce an option with integer argument. |
|
The integer is put into `int_var`. |
|
|
|
`OPT_DATE(short, long, &int_var, description)`:: |
|
Introduce an option with date argument, see `approxidate()`. |
|
The timestamp is put into `int_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_ARGUMENT(long, description)`:: |
|
Introduce a long-option argument that will be kept in `argv[]`. |
|
|
|
`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. |
|
|
|
|
|
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.
|
|
|