Argument parameters are assigned to the last known target, such
that multiple parameters accumulate:
1
2
|
args.parse ("-a=1 -a=2 foo", true);
assert (args('a').assigned().length is 3);
|
That example results in argument 'a' assigned three parameters.
Two parameters are explicitly assigned using '=', while a third
is implicitly assigned(). Implicit parameters are often useful for
collecting filenames or other parameters without specifying the
associated argument:
1
2
|
args.parse ("thisfile.txt thatfile.doc -v", true);
assert (args(null).assigned().length is 2);
|
The 'null' argument is always defined and acts as an accumulator
for parameters left uncaptured by other arguments. In the above
instance it was assigned both parameters.
Examples thus far have used 'sloppy' argument declaration, via
the second argument of parse() being set true. This allows the
parser to create argument declaration on-the-fly, which can be
handy for trivial usage. However, most features require the a-
priori declaration of arguments:
1
2
3
4
|
args = new Arguments;
args('x').required;
if (! args.parse("-x"))
// x not supplied!
|
Sloppy arguments are disabled in that example, and a required
argument 'x' is declared. The parse() method will fail if the
pre-conditions are not fully met. Additional qualifiers include
specifying how many parameters are allowed for each individual
argument, default parameters, whether an argument requires the
presence or exclusion of another, etc. Qualifiers are typically
chained together and the following example shows argument "foo"
being made required, with one parameter, aliased to 'f', and
dependent upon the presence of another argument "bar":
1
2
|
args("foo").required.params(1).aliased('f').requires("bar");
args("help").aliased('?').aliased('h');
|
Parameters can be constrained to a set of matching text values,
and the parser will fail on mismatched input:
1
2
|
args("greeting").restrict("hello", "yo", "gday");
args("enabled").restrict("true", "false", "t", "f", "y", "n");
|
A set of declared arguments may be configured in this manner
and the parser will return true only where all conditions are
met. Where a error condition occurs you may traverse the set
of arguments to find out which argument has what error. This
can be handled like so, where arg.error holds a defined code:
1
2
3
4
|
if (! args.parse (...))
foreach (arg; args)
if (arg.error)
...
|
Error codes are as follows:
1
2
3
4
5
6
7
8
|
None: ok (zero)
ParamLo: too few params for an argument
ParamHi: too many params for an argument
Required: missing argument is required
Requires: depends on a missing argument
Conflict: conflicting argument is present
Extra: unexpected argument (see sloppy)
Option: parameter does not match options
|
A simpler way to handle errors is to invoke an internal format
routine, which constructs error messages on your behalf:
1
2
|
if (! args.parse (...))
stderr (args.errors(&stderr.layout.sprint));
|
Note that messages are constructed via a layout handler and
the messages themselves may be customized (for i18n purposes).
See the two errors() methods for more information on this.
The parser make a distinction between a short and long prefix,
in that a long prefix argument is always distinct while short
prefix arguments may be combined as a shortcut:
1
2
3
4
5
6
|
args.parse ("--foo --bar -abc", true);
assert (args("foo").set);
assert (args("bar").set);
assert (args("a").set);
assert (args("b").set);
assert (args("c").set);
|
In addition, short-prefix arguments may be "smushed" with an
associated parameter when configured to do so:
1
2
3
|
args('o').params(1).smush;
if (args.parse ("-ofile"))
assert (args('o').assigned()[0] == "file");
|
There are two callback varieties supports, where one is invoked
when an associated argument is parsed and the other is invoked
as parameters are assigned(). See the bind() methods for delegate
signature details.
You may change the argument prefix to be something other than
"-" and "--" via the constructor. You might, for example, need
to specify a "/" indicator instead, and use ':' for explicitly
assigning parameters:
1
2
3
4
5
6
7
8
|
auto args = new Args ("/", "-", ':');
args.parse ("-foo:param -bar /abc");
assert (args("foo").set);
assert (args("bar").set);
assert (args("a").set);
assert (args("b").set);
assert (args("c").set);
assert (args("foo").assigned().length is 1);
|
Returning to an earlier example we can declare some specifics:
1
2
3
|
args('v').params(0);
assert (args.parse (`-v thisfile.txt thatfile.doc`));
assert (args(null).assigned().length is 2);
|
Note that the -v flag is now in front of the implicit parameters
but ignores them because it is declared to consume none. That is,
implicit parameters are assigned to arguments from right to left,
according to how many parameters said arguments may consume. Each
sloppy argument consumes parameters by default, so those implicit
parameters would have been assigned to -v without the declaration
shown. On the other hand, an explicit assignment (via '=') always
associates the parameter with that argument even when an overflow
would occur (though will cause an error to be raised).
Certain parameters are used for capturing comments or other plain
text from the user, including whitespace and other special chars.
Such parameter values should be quoted on the commandline, and be
assigned explicitly rather than implicitly:
1
|
args.parse (`--comment="-- a comment --"`);
|
Without the explicit assignment, the text content might otherwise
be considered the start of another argument (due to how argv/argc
values are stripped of original quotes).
Lastly, all subsequent text is treated as paramter-values after a
"--" token is encountered. This notion is applied by unix systems
to terminate argument processing in a similar manner. Such values
are considered to be implicit, and are assigned to preceding args
in the usual right to left fashion (or to the null argument):
1
2
|
args.parse (`-- -thisfile --thatfile`);
assert (args(null).assigned().length is 2);
|