Options are used to provide extra information to tune or customize the execution of a program. In case it wasn't clear, options are usually optional. A program should be able to run just fine with no options whatsoever. Pick a random program from the Unix or GNU toolsets. Can it run without any options at all and still make sense? The main exceptions are find, tar, and dd--all of which are mutant oddballs that have been rightly criticized for their non-standard syntax and confusing interfaces.
Lots of people want their programs to have "required options". Think about it. If it's required, then it's not optional! If there is a piece of information that your program absolutely requires in order to run successfully, that's what arguments are for.
As an example of good command-line interface design, consider the humble cp utility, for copying files. It doesn't make much sense to try to copy files without supplying a destination and at least one source. Hence, cp fails if you run it with no arguments. However, it has a flexible, useful syntax that does not require any options at all:
$ cp SOURCE DEST $ cp SOURCE ... DEST-DIR
You can get pretty far with just that. Most cp implementations provide a bunch of options to tweak exactly how the files are copied: you can preserve mode and modification time, avoid following symlinks, ask before clobbering existing files, etc. But none of this distracts from the core mission of cp, which is to copy either one file to another, or several files to another directory.
To add options to your parser, just create the parser as explained in the previous section and use the Console_CommandLine::addOption() method.
The Console_CommandLine::addOption() method takes two arguments:
$result->options['foo']
;
name | type | required | description | example |
---|---|---|---|---|
short_name | string | yes, if no long_name given | the option short name | -o |
long_name | string | yes, if no short_name given | the option long name | --orientation |
description | string | no, but recommended for the help message | a description for the option | orientation of the page: ltr (default) or rtl |
action | string | no, default to "StoreString" | the option action (see next section for details) | StoreString |
default | mixed | no | the option default value | ltr |
choices | array | no, only relevant for options that expect argument(s) | list of possible values for the option | array('ltr', 'rtl') |
list | array | no, only relevant for options that use the "List" action | list of values to display | array('blue', 'green', 'yellow') |
add_list_option | boolean | no, default to FALSE | this property is only relevant when the choices property is set, if set to TRUE the parser will generate an additional option to list the choices (eg. --list-foo). | TRUE |
help_name | string | no, if not given it will default to the option name | the name to display in the option help line | page_orientation (the help ligne will be: --orientation=page_orientation) |
Adding commandline options
<?php
require_once 'Console/CommandLine.php';
$parser = new Console_CommandLine(array(
'description' => 'A useful description for your program.',
'version' => '0.0.1', // the version of your program
));
// Adding a simple option that takes no argument and that tell our program to
// turn on verbose output:
$parser->addOption(
'verbose',
array(
'short_name' => '-v',
'long_name' => '--verbose',
'description' => 'turn on verbose output',
'action' => 'StoreTrue'
)
);
// Adding an option that will store a string
$parser->addOption(
'orientation',
array(
'short_name' => '-o',
'long_name' => '--orientation',
'description' => 'orientation of the page, "ltr" (default) or "rtl"',
'action' => 'StoreString',
'default' => 'ltr',
'help_name' => 'page_orientation'
)
);
try {
$result = $parser->parse();
print_r($result->options);
} catch (Exception $exc) {
$parser->displayError($exc->getMessage());
}
?>
Now if the user type:
$ <yourprogram> -vo rtl
or (equivalent):
$ <yourprogram> --verbose --orientation=rtl
The output of the above script will be:
Array ( [verbose] => 1 [orientation] => rtl [help] => [version] => )
Actions tell the parser how to handle option values, among other things they tell the parser if the option expects a value or not and how to store this value in the result object.
This action tells the parser to store the value true in the result object if the option is present in the command line, for example:
$ <yourprogram> -v
will store TRUE in $result->options['verbose']
,
assuming the option was defined like this:
<?php
$parser->addOption('verbose', array('short_name'=>'-v', 'action'=>'StoreTrue'));
$result = $parser->parse();
?>
This action tells the parser to store the value false in the result object if the option is present in the command line, for example:
$ <yourprogram> -q
will store FALSE in $result->options['verbose']
,
assuming the option was defined like this:
<?php
$parser->addOption('verbose', array('short_name'=>'-q', 'action'=>'StoreFalse'));
$result = $parser->parse();
?>
This action tells the parser that the option expects a value and to store this value as a string in the result object, for example:
$ <yourprogram> -o out.txt
will store the string "out.txt" in
$result->options['outfile']
,
assuming the option was defined like this:
<?php
$parser->addOption('outfile', array('short_name'=>'-o', 'action'=>'StoreString'));
$result = $parser->parse();
?>
This action tells the parser that the option expects a value and to store this value as an integer in the result object, for example:
$ <yourprogram> --width=500
will store the integer 500 in $result->options['width']
,
assuming the option was defined like this:
<?php
$parser->addOption('width', array('long_name'=>'--width', 'action'=>'StoreInt'));
$result = $parser->parse();
?>
This action tells the parser that the option expects a value and to store this value as a float in the result object, for example:
$ <yourprogram> -l=0.3
will store the float 0.3 in $result->options['level']
,
assuming the option was defined like this:
<?php
$parser->addOption('level', array('short_name'=>'-l', 'action'=>'StoreFloat'));
$result = $parser->parse();
?>
This action tells the parser to increment the value in the result object each time it encounters the option in the command line, for example:
$ <yourprogram> -vvvv
or the equivalent:
$ <yourprogram> -v -v -v --verbose
will store the integer 4 in
$result->options['verbose_level']
,
assuming the option was defined like this:
<?php
$parser->addOption('verbose_level', array(
'short_name' => '-v',
'long_name' => '--verbose',
'action' => 'Counter'
));
$result = $parser->parse();
?>
This action tells the parser to display the help message if it encounters the option in the command line, most of the time you won't need this since it is handled by Console_CommandLine internally.
This action tells the parser to display the program version if it encounters the option in the command line, as for Help action, chances are that you won't need this since it is handled by Console_CommandLine internally.
This action allows the user to either type the password on the commandline or to be prompted for it (will not echo on unix systems), some examples:
<?php
$parser->addOption('password', array('short_name'=>'-p', 'action'=>'Password'));
$result = $parser->parse();
?>
$ <yourprogram> -ps3cret
will store the string "s3ecret" in
$result->options['password']
whereas:
$ <yourprogram> -p
will "prompt" the user for entering his/her password
without echoing it, and will store "s3ecret" in
$result->options['password']
This action allows to specify a PHP callback to handle user input. The callback must be a php callable and must accept five arguments:
Your callback function must return the modified (or not modified) value (the first argument).
All these arguments should give you enough flexibility to build complex callback actions.
If the callback is to a class method, then the method must be declared as a public.
Here is a simple example:
<?php
/**
* A simple encryption callback.
*
*/
function encryptCallback($value, $option, $result, $parser, $params=array())
{
if (!isset($params['salt'])) {
$params['salt'] = '';
}
return sha1($params['salt'] . $value);
}
require_once 'Console/CommandLine.php';
$parser = new Console_CommandLine();
$parser->addOption('encrypt', array(
'short_name' => '-e',
'long_name' => '--encrypt',
'action' => 'Callback',
'description' => 'encrypt the given value using sha1 + salt',
'callback' => 'encryptCallback',
'action_params' => array('salt' => 'x2897ZHKx7200j1__2')
));
try {
$result = $parser->parse();
echo $result->options['encrypt'] . "\n";
} catch (Exception $exc) {
$parser->displayError($exc->getMessage());
}
?>
Now if the user type:
$ <yourprogram> -e foobar
The output of the above script will be:
7f12da3b1c126d7a47745b09dc0040c92cee1700
a special action that simply output an array as a list.
<?php
$parser->addOption('list_colors', array(
'short_name' => '-l',
'long_name' => '--list-colors',
'action' => 'List',
'action_params' => array(
'list' => array('blue', 'green', 'yellow'),
'delimiter' => ',' //optional
)
));
$result = $parser->parse();
?>
$ <yourprogram> --list-colors
will display the list of colors separated by commas.