[commits] [Wiki] created: Doc/Dev/HordeArgv
Jan Schneider
jan at horde.org
Mon Feb 4 15:40:53 UTC 2013
jan Mon, 04 Feb 2013 16:40:53 +0100
Created page: http://wiki.horde.org/Doc/Dev/HordeArgv
+ Horde_Argv
[[toc]]
//Horde_Argv// is a library for parsing command line arguments with
various actions, providing help, grouping options, and more. It is
ported from Python's Optik (http://optik.sourceforge.net/).
++ Basic Usage
While //Horde_Argv// is quite flexible and powerful, you don't have to
jump through hoops or read reams of documentation to get started. This
document aims to demonstrate some simple usage patterns that will get
you started using //Horde_Argv// in your scripts.
To parse a command line with //Horde_Argv//, you must create an
{{Horde_Argv_Parser}} instance and define some options. You'll have to
import the {{Horde_Argv_Parser}} classes in any script that uses
//Horde_Argv//, but it is suggested that you use an autoloader instead:
<code type="php">
require_once 'Horde/Autoloader/Default.php';
</code>
Early on in the main program, create a parser:
<code type="php">
$parser = new Horde_Argv_Parser();
</code>
Then you can start defining options. The basic syntax is:
<code type="php">
$parser->addOption('opt_str', ..., array('attr' => 'value', ...));
</code>
That is, each option has one or more option strings, such as "-f" or
"--file", and several option attributes that tell //Horde_Argv// what
to expect and what to do when it encounters that option on the command
line.
Typically, each option will have one short option string and one long
option string, e.g.:
<code type="php">
$parser->addOption('-f', '--file', ...);
</code>
You're free to define as many short option strings and as many long
option strings as you like, as long as there is at least one option
string overall.
Once all of your options are defined, instruct //Horde_Argv// to parse
your program's command line:
<code type="php">
list($values, $args) = $parser->parseArgs();
</code>
(You can pass an argument list to {{parseArgs()}} if you like, but
that's rarely necessary: by default it uses $_SERVER['argv'].)
{{parseArgs()}} returns two values:
* $values is a {{Horde_Argv_Values}} object containing values for all
of your options -- e.g. if "--file" takes a single string argument,
then $values->file (or $values['file']) will be the filename supplied
by the user, or NULL if the user did not supply that option.
* $args is the list of arguments left over after parsing options.
This tutorial document only covers the four most important option
attributes: "action", "type", "dest" (destination), and "help". Of
these, "action" is the most fundamental.
+++ Option actions
Actions tell //Horde_Argv// what to do when it encounters an option on
the command line. There is a fixed set of actions hard-coded into
//Horde_Argv//; adding new actions is an advanced topic covered in
Extending //Horde_Argv//. Most actions tell //Horde_Argv// to store a
value in some variable -- for example, take a string from the command
line and store it in an attribute of options.
If you don't specify an option action, //Horde_Argv// defaults to "store".
++++ The store action
The most common option action is store, which tells //Horde_Argv// to
take the next argument (or the remainder of the current argument),
ensure that it is of the correct type, and store it to your chosen
destination.
For example:
<code type="php">
$parser->addOption(
'-f', '--file',
array('action' => 'store', 'type' => 'string', 'dest' => 'filename')
);
</code>
Now let's make up a fake command line and ask //Horde_Argv// to parse it:
<code type="php">
$args = array('-f', 'foo.txt');
list($values, $args) = $parser->parseArgs(args);
</code>
When //Horde_Argv// sees the "-f", it consumes the next argument,
"foo.txt", and stores it in $values->filename, where values is the
first return value from {{parseArgs()}}. So, after this call to
{{parseArgs()}}, $values->filename is "foo.txt".
Some other option types supported by //Horde_Argv// are "int" and
"float". Here's an option that expects an integer argument:
<code type="php">
$parser->addOption('-n', array('type' => 'int', 'dest' => 'num'));
</code>
Note that I didn't supply a long option, which is perfectly
acceptable. I also didn't specify the action, since the default is
"store".
Let's parse another fake command-line. This time, we'll jam the option
argument right up against the option -- "-n42" (one argument) is
equivalent to "-n 42" (two arguments).
<code type="php">
list($values, $args) = $parser->parseArgs(array('-n42'));
echo $values->num;
</code>
will print "42".
Trying out the "float" type is left as an exercise for the reader.
If you don't specify a type, //Horde_Argv// assumes "string". Combined
with the fact that the default action is "store", that means our first
example can be a lot shorter:
<code type="php">
$parser->addOption('-f', '--file', array('dest' => 'filename'))
</code>
If you don't supply a destination, //Horde_Argv// figures out a
sensible default from the option strings: if the first long option
string is "--foo-bar", then the default destination is "foo_bar". If
there are no long option strings, //Horde_Argv// looks at the first
short option: the default destination for "-f" is "f".
Adding types is covered in "Extending //Horde_Argv//".
++++ Handling flag (boolean) options
Flag options -- set a variable to TRUE or FALSE when a particular
option is seen -- are quite common. //Horde_Argv// supports them with
two separate actions, "store_true" and "store_false". For example, you
might have a verbose flag that is turned on with "-v" and off with "-q":
<code type="php">
$parser->addOption('-v', array('action' => 'store_true', 'dest' =>
'verbose'));
$parser->addOption('-q', array('action' => 'store_false', 'dest' =>
'verbose'));
</code>
Here we have two different options with the same destination, which is
perfectly OK. (It just means you have to be a bit careful when setting
default values -- see Default values, below.)
When //Horde_Argv// sees "-v" on the command line, it sets the verbose
attribute of the special "option values" object to a TRUE value; when
it sees "-q", it sets verbose to a FALSE value.
++++ Other actions
Some other actions supported by //Horde_Argv// are:
: "store_const" : store a constant value
: "append" : append this option's argument to a list
: "count" : increment a counter by one
: "callback" : call a specified function
These are covered in the Advanced Usage and Option Callbacks documents.
+++ Default values
All of the above examples involve setting some variable (the
"destination") when certain command-line options are seen. What
happens if those options are never seen? Since we didn't supply any
defaults, they are all set to NULL. Usually, this is just fine, but
sometimes you want more control. To address that need, //Horde_Argv//
lets you supply a default value for each destination, which is
assigned before the command-line is parsed.
First, consider the verbose/quiet example. If we want //Horde_Argv//
to set verbose to TRUE unless "-q" is seen, then we can do this:
<code type="php">
$parser->addOption('-v', array('action' => 'store_true', 'dest' =>
'verbose', $default => true));
$parser->addOption('-q', array('action' => 'store_false', 'dest' =>
'verbose'));
</code>
Oddly enough, this is exactly equivalent:
<code type="php">
$parser->addOption('-v', array('action' => 'store_true', 'dest' =>
'verbose'));
$parser->addOption('-q', array('action' => 'store_false', 'dest' =>
'verbose', $default => true));
</code>
Those are equivalent because you're supplying a default value for the
option's destination, and these two options happen to have the same
destination (the verbose variable).
Consider this:
<code type="php">
$parser->addOption('-v', array('action' => 'store_true', 'dest' =>
'verbose', $default => false));
$parser->addOption('-q', array('action' => 'store_false', 'dest' =>
'verbose', $default => true));
</code>
Again, the default value for verbose will be TRUE: the last default
value supplied for any particular destination attribute is the one
that counts.
A clearer way to specify default values is the {{setDefaults()}}
method of {{Horde_Argv_Parser}}, which you can call at any time before
calling {{parseArgs()}}:
<code type="php">
$parser->setDefaults(array('verbose' => true));
$parser->addOption(...);
list($values, $args) = $parser->parseArgs();
</code>
As before, the last value specified for a given option destination is
the one that counts. For clarity, try to use one method or the other
of setting default values, not both.
+++ Generating help
There is one more feature that you will use in every script:
//Horde_Argv//'s ability to generate help messages. All you have to do
is supply a help value for each option. Let's create a new parser and
populate it with user-friendly (documented) options:
<code type="php">
$usage = 'usage: %prog [options] arg1 arg2';
$parser = new Horde_Argv_Parser(array('usage' => $usage));
$parser->addOption(
'-v', '--verbose',
array('action' => 'store_true', 'dest' => 'verbose', $default => 1,
'help' => 'make lots of noise [default]')
);
$parser->addOption(
'-q', '--quiet',
array('action' => 'store_false', 'dest' => 'verbose',
'help' => 'be vewwy quiet (I'm hunting wabbits)')
);
$parser->addOption(
'-f', '--filename',
array('metavar' => 'FILE', 'help' => 'write output to FILE')
);
$parser->addOption(
'-m', '--mode',
array('default' => 'intermediate',
'help' => 'interaction mode: one of "novice",
"intermediate" [default], "expert"')
);
</code>
If //Horde_Argv// encounters either '-h' or '--help' on the
command-line, or if you just call {{$parser->printHelp()}}, it prints
the following to stdout:
<code>
usage: <yourscript> [options] arg1 arg2
options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-fFILE, --filename=FILE
write output to FILE
-mMODE, --mode=MODE interaction mode: one of 'novice', 'intermediate'
[default], 'expert'
</code>
There's a lot going on here to help //Horde_Argv// generate the best
possible help message:
* the script defines its own usage message:
> {{$usage = 'usage: %prog [options] arg1 arg2';}}
> //Horde_Argv// expands "%prog" in the usage string to the name of
> the current script, i.e. basename($_SERVER['argv'][0]). The expanded
> string is then printed before the detailed option help.
> If you don't supply a usage string, //Horde_Argv// uses a bland but
> sensible default: "usage: %prog [options]", which is fine if your
> script doesn't take any positional arguments.
* every option defines a help string, and doesn't worry about
line-wrapping -- //Horde_Argv// takes care of wrapping lines and
making the help output look good.
* options that take a value indicate this fact in their
automatically-generated help message, e.g. for the "mode" option:
> {{-mMODE, --mode=MODE}}
> Here, "MODE" is called the meta-variable: it stands for the argument
> that the user is expected to supply to -m/--mode. By default,
> //Horde_Argv// converts the destination variable name to uppercase
> and uses that for the meta-variable. Sometimes, that's not what you
> want -- for example, the --filename option explicitly sets $metavar
> = "FILE", resulting in this automatically-generated option
> description:
> {{-fFILE, --filename=FILE}}
> This is important for more than just saving space, though: the
> manually written help text uses the meta-variable "FILE", to clue
> the user in that there's a connection between the formal syntax
> "-fFILE" and the informal semantic description "write output to
> FILE". This is a simple but effective way to make your help text a
> lot clearer and more useful for end users.
+++ Print a version number
Similar to the brief usage string, //Horde_Argv// can also print a
version string for your program. You have to supply the string, as the
version argument to {{Horde_Argv_Parser}}:
<code type="php">
$parser = new Horde_Argv_Parser(array('usage' => '%prog [-f] [-q]',
'version' => '%prog 1.0'));
</code>
Note that "%prog" is expanded just like it is in usage. Apart from
that, version can contain anything you like. When you supply it,
//Horde_Argv// automatically adds a "--version" option to your parser.
If it encounters this option on the command line, it expands your
version string (by replacing "%prog"), prints it to stdout, and exits.
For example, if your script is called "/usr/bin/foo", a user might do:
<code type="shell">
$ /usr/bin/foo --version
foo 1.0
</code>
+++ Error-handling
The one thing you need to know for basic usage is how //Horde_Argv//
behaves when it encounters an error on the command-line -- e.g. "-n4x"
where the "-n" option takes an integer. //Horde_Argv// prints your
usage message to stderr, followed by a useful and human-readable error
message. Then it terminates with a non-zero exit status by calling
{{exit()}}.
If you don't like this, subclass {{Horde_Argv_Parser}} and override
the {{parserError()}} method. See Extending //Horde_Argv//.
+++ Putting it all together
Here's what a //Horde_Argv//-based scripts usually look like:
<code type="php">
require_once 'Horde/Autoloader/Default.php';
[...]
$usage = 'usage: %prog [options] arg';
$parser = new Horde_Argv_Parser(array('usage' => $usage));
$parser->addOption(
'-f', '--file',
array('type' => 'string', 'dest' => 'filename',
'help' => 'read data from FILENAME')
);
$parser->addOption(
'-v', '--verbose',
array('action' => 'store_true', 'dest' => 'verbose')
);
$parser->addOption(
'-q', '--quiet',
array('action' => 'store_false', 'dest' => 'verbose')
);
[... more options ...]
list($values, $args) = $parser->parseArgs();
if (count($args) != 1) {
$parser->parserError('incorrect number of arguments');
}
if ($values->verbose) {
printf('reading %s...%n', $values->filename);
}
[... go to work ...]
</code>
More information about the commits
mailing list