Managing command line options

Managing command line options – how to add options to the parser and use them.

Some background

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.

Adding options with Console_CommandLine

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:

  • the option name: a string that will be used to access the option in the result object. For example if you name your option foo, you will access to the result object like this: $result->options['foo'];
  • the options parameters: an array of various informations, as explained below.
Available option parameters
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] =>
)

Options actions

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.

StoreTrue

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();
?>

StoreFalse

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();
?>

StoreString

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();
?>

StoreInt

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();
?>

StoreFloat

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();
?>

Counter

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();
?>

Help

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.

Version

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.

Password

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']

Callback

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

List

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.