The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

PTools::Options - A simple OO interface to Getopt::Long

VERSION

This document describes version 0.15, released August, 2005.

SYNOPSIS

 use PTools::Options;

 $usage   = "Usage: $0 [-h] [-v[v...]]";   # define usage "help text"
 @optArgs = qw( help|h verbose|v+ );       # define valid options

 $opts = new PTools::Options( $usage, @optArgs );  # parse @ARGV list
 $opts = new PTools::Options();                    # delay parsing @ARGV

 $opts->configure( @getopt_configs );      # configure Getopt::Long 
 $opts->config   ( @getopt_configs );      # configure Getopt::Long 

 $opts->parse( $usage, @optArgs );         # parse @ARGV after 'configure'

 $opts->set('attribute', $newValue);       # set attribute to a new value
 $opts->attribute($newValue);              # "automatic accessor" method

 $value = $opts->get('attribute');         # get current value for attribute
 $value = $opts->attribute;                # "automatic accessor" method

 $opts->reset('attribute');                # remove/undefine the attribute

 $usage   = $opts->usage;                  # get value passed to 'new' method
 $optArgs = $opts->optArgs;                # get args passed to 'new' method

 $optRef  = $opts->opts;                   # get user entered cmd-line options 

 $argRef  = $opts->args;                   # get user entered cmd-line arguments
 (@args)  = $opts->args;                   # 'ref' or list, depending on context
 $arg0    = $opts->args->[0];              # 0th command line argument
 $arg1    = $opts->args->[1];              # 1st command line argument, etc...

 $opts->resetArgs( $argRef );              # reset list of user entered args
 $opts->resetArgs( \@args  );              # reset list of user entered args

 $opts->abortOnError;                      # abort with "$usage" if parse err(s)

 $opts->abortWithHelp   if ( ... );        # abort with "$usage" if (whatever)
 $opts->abortWithUsage  if ( ... );        # abort with "$usage" if (whatever)

 $opts->exitWithHelp    if $opts->help;    # exit gracefully w/ '-h' (--help)
 $opts->exitWithUsage   if $opts->help;    # exit gracefully w/ '-h' (--help)

 print $opts->dump;                        # useful when testing/debugging

DESCRIPTION

This is a generic class that can be used by any application module or script to define and then validate command-line options. It is a simple wrapper for Perl's Getopt::Long class (the GetOptions function).

Judging from the above Synopsis it may not seem that this is a simple interface to the Getopt::Long class. However, the following complete example is pretty simple.

 use PTools::Options;

 $usage = "Usage: $0 [-h] [-D [n]] [-v[...]] filename";

 @optArgs = qw( Debug|D:i help|h verbose|v+ );

 $opts = new PTools::Options( $usage, @optArgs );

 $opts->abortOnError;
 $opts->exitWithUsage  if $opts->help;

 $filename = $opts->args->[0];

 $opts->abortWithUsage  unless $filename;

Constructor

new ( [ Usage, OptArgs ] )

The new method is used to both define and validate user entered command line options.

Usage

A text string describing the usage of a given module or script.

OptArgs

A list of Getopt::Long options that is used to validate any command line options entered by a user.

See the Synopsis and Description sections, above, and the Examples section, below, for examples. See Getopt::Long for a complete description of the option definitions that can be passed in the OptArgs list.

To delay option parsing, for example when configuration is needed prior to invoking the parse, pass an empty parameter list.

Methods

config ( Arg [, Arg ... ] )
configure ( Arg [, Arg ... ] )

The configure (or config) method is used to configure the underlying Getopt::Long class prior to actually parsing command-line options.

See the Examples section, below, for an example. See Getopt::Long for a full discussion of the available configuration directives.

parse ( Usage, OptArgs )

The parse method is available when configuration is needed prior to actually parsing command line optoins. Arguments for this method are the same as for the 'new' method, above

See the Examples section, below, for an example.

resetArgs ( ListRef )
setArgs ( ListRef )

It is sometimes handy, within a script, to turn 'arguments' into 'options', which will simplify access to the data later in the script. In these cases, this method is provided to reset the argument list after removing any extraneous values.

See the Examples section, below, for an example.

reset ( Attribute )

Remove (undefine) an attribute contained in an object of this class.

get ( Attribute )
set ( Attribute, NewValue )

Fetch or set an attribute value in an object of this class.

Attribute

Specify the attribute name to access within the $opts object.

Value

Used with the set method, set the named attribute to a NewValue.

Examples:

 $currentValue = $opts->get( 'attribute' );

 $opts->set( 'attribute', "new value" );

Also see the Automatic Accessor Methods section, below, to obtain the value of an attribute using the atribute's name as an accessor method.

usage

The usage method returns the same Usage string passed to the new method as described above.

optArgs

The optArgs method returns a reference to the list of OptArgs passed to the new method as described above.

opts

The opts method returns a reference to a list of any option flags and/or values entered on the command line by the user.

args

The args method returns a reference to a list of any additional command-line arguments entered on the command line by the user. The return value with be either a 'list' or a 'list reference' depending upon the calling context.

 $argRef    = $opts->args;       # returns a 'list ref'
 (@argList) = $opts->args;       # returns a 'list'

 $arg0 = $argRef->[0];
 $arg1 = $argRef->[1];

For ensuring required arguments are entered, see the abortWithUsage method, below.

status
stat
err

Collect the status code and/or error string returned by the 'GetOptions' function of the Getopt::Long class. Also see the setErr method.

 ($stat,$err) = $opts->status;

 $stat  = $opts->stat;       # status number returned in scalar context 
 ($err) = $opts->stat;       # error message returned in array context 

 ($err) = $opts->err;

 $stat and die "$err\n\n". $opts->usage ."\n\n";
setErr ( Status [, Text ] )

This method can be used to override the values returned by the 'GetOptions' function of the Getopt::Long class. This is useful when crafting a custom error message for use by the abortOnError method.

Status

This parameter is expected to be a non-zero integer value.

Text

This parameter is expected to be a text string.

exitWithUsage ( [ Usage ] [, FD ] [, ExitStatus ] )
abortWithUsage ( [ Usage ] [, FD ] [, ExitStatus ] )

Since exiting with a Usage message is such a common occurrance, these methods are provided to simplify the process.

Usage

If no Usage string is passed, the default is to use the original value passed to the new method. If the original value does not already contain newline characters, a little formatting is done to the original value, adding some newline characters. However, no additional formatting is done if a Usage string is passed.

If a null value is passed (that is not undef), no usage text will be printed and the currently running script will terminate with an exit value of zero.

FD

If no FileDescriptor is passed, the default of *STDERR is used.

ExitStatus

For a simple exit the default ExitStatus is 0, and for an abort the default is 1.

Exit example (this example assumes usage as shown in the Synopsis section, above). This terminates a script with a value of zero by default.

 $opts->exitWithUsage  if $opts->help;

Abort example, when two command-line arguments are required in a calling script. This terminates a script with a value of one by default.

 ($arg0, $arg1) = ( $opts->args->[0],  $opts->args->[1] );

 $opts->abortWithUsage unless ($arg0 and $arg1);
abortOnError ( [ Message ] [, FD ] )

As an alternative to the exit/abort examples, shown just above, the abortOnError method provides several possible ways to generate an abort message.

Note: this method will return without taking any action unless the current value of the status attribute is non-zero.

The simplest way to use this method is with no arguments. A reasonably good default message is printed on STDERR, and this module terminates the currently running script with an exit value equal to the current value of the status value (which is -1 by default).

Objects of this class will trap any warning messages emitted during the parsing by GetOptions (normally, these are warnings are displayed on STDERR by the Getopt::Long class). If command-line parsing error(s) occur, the result(s) will be available via the stat or status methods.

The warning text generated by the GetOptions parsing will only be displayed by this abortOnError method when the Usage argument is undefined. Otherwise, it is assumed that the user of this module wants to display a custom error messgae (which may or may not include any GetOptions warning text).

This method will call exit using the current value of the status attribute. This will be -1 unless the setErr method was used to define an alternate value.

Message

If no Message string is passed, the default is to use the original value passed to the new method. If the original value does not already contain newline characters, a little formatting is done to the original value, adding some newline characters. However, no additional formatting is done if a Message string is passed.

If a null value is passed (that is not undef), no error text will be printed and the currently running script will terminate with the current value of the status attribute.

FD

If no FileDescriptor is passed, the default of *STDERR is used.

Examples:

 $opts = new PTools::Options( $usage, @optArgs );

 $opts->abortOnError;
 $opts->abortOnError("");
 $opts->abortOnError("\n A custom error message\n\n");

 $opts->setErr(-2, "\n Another custom error message\n\n");
 $opts->abortOnError;

Calling the setErr method can be used to override the default error attribute.

Note: A null message string will suppress printing the current value of the error attribute which, by default, will contain any warning messages emitted during the call to the GetOptions function (used internally to parse the command-line arguments).

dump ( [ Mode ] )

Display contents of the current object. This is useful when debugging, as the result is functional but not in a 'pretty' format.

By default, a few of the attributes used internally are not 'dumped' (these include the 'usage' text, list of 'opts' selected and 'optArgs' which are often fairly long and not very useful during debugging). If the optional Mode contains the string 'all', all attributes are included in the dump output.

In addition, by default, attribute values that are references are simply shown as the type of reference. If the optional Mode contains the string 'expand', reference attributes are expanded in the dump output. Note that object references are not expanded.

When used, a Mode of 'expand' can be interesting, but a Mode that includes 'all' can quickly become tedious.

Examples:

 die $opts->dump;

 die $opts->dump("all");
 die $opts->dump("expand");
 die $opts->dump("all/expand");

Automatic Accessor Methods

This class implements Perl's AUTOLOAD feature to allow any calling module to request an attribute value using any arbitrary attribute name as a method.

Using the above Synopsis as an example, if the module that invoked this class wishes to determine if the '-h' (--help) option was used, it could do so as follows.

 if ($opts->help) { ... }

Just remember to use the primary attribute name, as defined by the Getopt::Long class, and not an alias name.

In addition, the module or script that invokes this class can use the set method, described above, to create additional attributes in objects of this class. After storing new attribte values into the object, the attribute name may then be used as a method to return the attribute's current value.

The 'automatic accessor' mechanism described here may also be used to set a value for the named attribute. The following examples are equivalent, and both create the new attribute and give it an initial value. These same methods can be used at any later point to redefine the value of the named attribute.

 $opts->set("Debug", "true");
 $opts->Debug("true");

The value can then be retrieved using the newly created method instead of using the get method. The following examples are equivalent, and both fetch the current value for the named attribute.

 $value = $opts->get("Debug");
 $value = $opts->Debug();

Troubleshooting: If an 'automatic accessor' method does not return a value it is either because no attribute with that name currently exists, or because the attribute does not currently contain a value. If the results are not as expected, use the dump method, explained above, to see a complete list of the currently defined attributes and their values.

Usage Note: Occasionally attribute names may happen to clash with existing methods defined in this module. In this case, obviously, the automatic accessor mechanism will not work with those attributes. Currently, methods defined in this class include the following and, when accessing attributes with these names, the set and get methods must be used.

  abortOnError    exitWithHelp   param      setUsage
  abortWithHelp   exitWithUsage  parse      stat
  abortWithUsage  formatUsage    parseErr   status
  args            get            reset      usage
  config          getGetoptErr   resetArgs  _expandRef
  configure       new            set        AUTOLOAD
  dump            optArgs        setArgs    DESTROY
  err             opts           setErr

Performance Note: Upon first call to an 'automatic accessor' method this module will create a method of the same name. Subsequent calls to the accessor method will invoke the method directly, and not through Perl's AUTOLOAD mechanism.

EXAMPLES

Error Handling

As an alternative to the simple abort example shown in the Synopsis section, the abortOnError method provides several possible ways to generate an abort message.

 $opts = new PTools::Options( $usage, @optArgs );

 $opts->abortOnError;
 $opts->abortOnError("");
 $opts->abortOnError("\n Custom error string\n\n");

 $opts->setErr(-2, "\n Another custom error string\n\n");
 $opts->abortOnError;

Configuring Getopt::Long

By default, this module configures Getopt::Long for the 'bundling' of options. To disable this, or add any other desired configuration specifications for the Getopt::Long module, use the following syntax. Instantiating the object wth an empty argument list will delay parsing the command line until after the configuration can be accomplished.

 $usage = "Usage: $0 [-h] [-v[...]] filename";       # define usage help

 @optArgs = qw( help|h verbose|v+ );                 # specify valid opts

 $opts = new PTools::Options();                      # delay parsing @ARGV

 $opts->config( "no_bundling", "no_ignore_case" );   # configure the parser

 $opts->parse( $usage, @optArgs );                   # parse the @ARGV list

Specify 'no_ignore_case' if you wish to differentiate upper and lower case options for a single character (e.g., '-d <directory>' and '-D [<level>]'). Specify 'no_bundling' if you must still support long options that require a single dash (e.g., '-help'). This prevents bundling, such as using '-vvv' syntax with options that use the '+' specification (e.g, 'verbose|v+').

(As an alternative, specify 'bundling_override' which allows both option bundling and the use of long options with a single dash. But, before doing this, read the caveat in Getopt::Long regarding unexpected results when bundling options especially when mixed with long options.)

As an alternative mechanism, the 'Getopt::Long::Configure' method may be called directly. Note that module designers wishing to subclass this module can use this syntax to override the default behavior of this class.

 use PTools::Options;
 Getopt::Long::Configure qw( no_permute  no_bundling );

Depending on the application, it may be a good idea to put this in a BEGIN block.

 use PTools::Options;
 BEGIN { Getopt::Long::Configure( "no_permute", "no_bundling" ) }

See Getopt::Long for additional configuration settings and use with various environment variables.

Using With 'PTools::Debug' Class

This module works well with the PTools::Debug module, when used in a manner similar to the following example. See Debug for further details.

 use PTools::Debug;
 use PTools::Options;

 @optArgs = qw( help|h Debug|D:i );

 $usage = "Usage: $basename [-h] [-D [n]]";

 $opts  = new PTools::Options( $usage, @optArgs );

 $opts->abortOnError;
 $opts->exitWithUsage  if $opts->help;

 $debug = new PTools::Debug( $opts->Debug );

 $debug->warn( 0, "Debug output is enabled" );
 $debug->warn( 3, "Debug output at level 3" );

Using With 'PTools::Verbose' Class

This module works well with the PTools::Verbose module, when used in a manner similar to the following example. See Verbose for further details.

 use PTools::Verbose;
 use PTools::Options;

 @optArgs = qw( help|h verbose|v+ );

 $usage = "Usage: $basename [-h] [-v[...]]";

 $opts  = new PTools::Options( $usage, @optArgs );

 $opts->abortOnError;
 $opts->exitWithUsage  if $opts->help;

 $verbose = new PTools::Verbose( $opts->Verbose );

 $verbose->print( 1, "Verbose output is enabled" );
 $verbose->print( 3, "Verbose output at level 3" );

Flexible Argument Parsing

Sometimes it is handy within a script to turn 'arguments' into 'options' which simplifies access to the data later in the script. In these cases, flexibility is provided to alter how Getopt::Long parses arguments and to reset the argument list after removing any extraneous values.

Consider a situation where we want to collect options and arguments valid for an optional arbitrary command that are not valid arguments to the script for which we are parsing options. In this example, the lone dash ('-') will terminate parsing of the command line. For this to work, the 'config' method must be used to disable 'permuted' options, and the 'parse' method is used to perform the command line parsing. The following demonstrates command line parsing within a script named 'nway'.

 use PTools::Options;

 $usage = "nway [<options>] filename [ - command [ -arg [...]]]";

 @optArgs = qw( concurrent|c=i  Debug|D:i  help|h  preview|p:i );

 $opts = new PTools::Options();        # create an options parser
 $opts->config( "no_permute" );        # disable 'permuted' options
 $opts->parse( $usage, @optArgs );     # parse the @ARGV list

 $opts->abortOnError;                  # abort if parsing errors occurred
 $opts->exitWithUsage if $opts->help;  # exit gracefully if '-h' was used

 (@args) = $opts->args();              # get all cmd-line args
 $file   = shift @args;                # collect "filename" arg   (required)
 shift @args;                          # strip lone "-" character (if any)
 $cmd    = shift @args;                # collect "command" name   (if any)

 $file  or $opts->abortWithUsage;      # verify the required argument

Okay, at this point, any remaining @args belong to the [ -arg [...]] argument list that will be passed to the named "command". In this case, we want to turn the two arguments filename and command into options, and then reset the $opts argument list.

 $opts->set('filename', $file);        # then access as  $opts->filename
 $opts->set('command',  $cmd);         # then access as  $opts->command

 $opts->resetArgs( \@args );           # then access as  $opts->args

Yes, this is a long way to go for a small example, and it gets a little obscure, but it does provide a demonstration of the flexibility available when using this module.

See Getopt::Long for further details.

WARNINGS

By default, this module configures Getopt::Long for the 'bundling' of options. See the Configuring Getopt::Long section, above.

This module briefly changes the value of $SIG{__WARN__} (to collect any error output from the GetOptions method in the Getopt::Long class) and then resets this variable to back it's original value.

Also, one problem with auto generating accessor methods is that it's easy to make typos in the accessor name (or not notice when the '@optArgs' passed by the caller happens to change). In these cases it can be helpful to use the dump method, described above, to determine why no value is returned to the caller for an option that 'obviously' should be set.

DEPENDENCIES

This class depends upon the following class:

 Getopt::Long  version 2.17 or later

INHERITANCE

None currently.

SEE ALSO

See Getopt::Long (GetOptions method) for a complete description of the option definitions that can be passed in the OptArgs list to the new method of this class.

See Debug and Verbose for details of a simple implementation of 'debug' and 'verbose' output levels that works well in conjunction with this class. These classes are useful during the development and maintenance of other modules.

AUTHOR

Chris Cobb [no dot spam at ccobb dot net]

COPYRIGHT

Copyright (c) 1998-2007 by Chris Cobb. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.