NAME
Getopt::Args2 - command-line argument and option processor
VERSION
2.0.0_3 (2022-04-30)
SYNOPSIS
#!/usr/bin/env perl
use Getopt::Args2;
my $opts = optargs2(
comment => 'script to paint things',
optargs => sub {
arg item => (
isa => 'Str',
required => 1,
comment => 'the item to paint',
);
opt help => ( ishelp => 1 );
opt quiet => (
isa => 'Flag',
alias => 'q',
comment => 'output nothing while working',
);
},
);
print "Painting $opts->{item}\n" unless $opts->{quiet};
DESCRIPTION
Getopt::Args2 processes command line arguments, options, and subcommands according to the following definitions:
- Command
-
A program run from the command line to perform a task.
- Arguments
-
Arguments are positional parameters that pass information to a command. Arguments can be optional, but they should not be confused with Options below.
- Options
-
Options are non-positional parameters that pass information to a command. They are generally not required to be present (hence the name Option) but that is configurable. All options have a long form prefixed by '--', and may have a single letter alias prefixed by '-'.
- Subcommands
-
From the users point of view a subcommand is a special argument with its own set of arguments and options. However from a code authoring perspective subcommands are often implemented as stand-alone programs, called from the main script when the appropriate command arguments are given.
Getopt::Args2 is a re-write of the original OptArgs module with a cleaner code base and improved API. It should be preferred over OptArgs for new projects however OptArgs is not likely to disappear from CPAN anytime soon. Users converting to Getopt::Args2 from OptArgs need to be aware of the following:
- Obvious API changes: cmd(), optargs2(), subcmd()
-
Commands and subcommands must now be explicitly defined using
cmd()
andsubcmd()
. - class_optargs() no longer loads the class
-
Users must specifically require the class if they want to use it afterwards:
my ($class, $opts) = class_optargs('App::demo'); eval "require $class" or die $@; # new requirement
- Bool options with no default display as "--[no-]bool"
-
A Bool option without a default is now displayed with the "[no-]" prefix. What this means in practise is that many of your existing Bool options should likely become Flag options instead.
Simple Commands
To demonstrate the simple use case (i.e. with no subcommands) lets put the code from the synopsis in a file called paint
and observe the following interactions from the shell:
$ ./paint
usage: paint ITEM [OPTIONS...]
arguments:
ITEM the item to paint [required]
options:
--help, -h print a usage message and exit
--quiet, -q output nothing while working
The optargs2()
function parses the command line according to the included opt()
and arg()
declarations and returns a single HASH reference. If the command is not called correctly then an exception is thrown containing an automatically generated usage message as shown above. Because Getopt::Args2 fully knows the valid arguments and options it can detect a wide range of errors:
$ ./paint wall Perl is great
error: unexpected option or argument: Perl
So let's add that missing argument definition inside the optargs sub:
arg message => (
isa => 'Str',
comment => 'the message to paint on the item',
greedy => 1,
);
And then check the usage again:
$ ./paint
usage: paint ITEM [MESSAGE...] [OPTIONS...]
arguments:
ITEM the item to paint [required]
MESSAGE the message to paint on the item
options:
--help, -h print a usage message and exit
--quiet, -q output nothing while working
Note that optional arguments are surrounded by square brackets, and that three dots (...) are postfixed to greedy arguments. A greedy argument will swallow whatever is left on the comand line:
$ ./paint wall Perl is great
Painting on wall: "Perl is great".
Note that it probably doesn't make sense to define any more arguments once you have a greedy argument. Let's imagine you now want the user to be able to choose the colour if they don't like the default. An option might make sense here:
opt colour => (
isa => 'Str',
default => 'blue',
comment => 'the colour to use',
);
This now produces the following usage output:
usage: paint ITEM [MESSAGE...] [OPTIONS...]
arguments:
ITEM the item to paint
MESSAGE the message to paint on the item
options:
--colour=STR, -c the colour to use [blue]
--quiet, -q output nothing while working
The command line is parsed first for arguments, then for options, in the same order in which they are defined. This probably only of interest if you are using trigger actions on your options (see FUNCTIONS below for details).
Multi-Level Commands
Commands with subcommands require a different coding model and syntax which we will describe over three phases:
- Definitions
-
Your command structure is defined using calls to the
cmd()
andsubcmd()
functions. The first argument to both functions is the name of the Perl class that implements the (sub-)command.cmd 'App::demo' => ( comment => 'the demo command', optargs => sub { arg command => ( isa => 'SubCmd', required => 1, comment => 'command to run', ); opt quiet => ( isa => 'Flag', alias => 'q', comment => 'run quietly', ); }, ); subcmd 'App::demo::foo' => ( comment => 'demo foo', optargs => sub { arg action => ( isa => 'Str', required => 1, comment => 'command to run', ); }, ); subcmd 'App::demo::bar' => ( comment => 'demo bar', optargs => sub { opt baz => ( isa => 'Counter', comment => '+1', ); }, ); # Command hierarchy for the above code: # demo COMMAND [OPTIONS...] # demo foo ACTION [OPTIONS...] # demo bar [OPTIONS...]
An argument of type 'SubCmd' is an explicit indication that subcommands can occur in that position. The command hierarchy is based upon the natural parent/child structure of the class names. This definition can be done in your main script, or in one or more separate packages or plugins, as you like.
- Parsing
-
The
class_optargs()
function is called instead ofoptargs()
to parse the@ARGV
array and call the appropriatearg()
andopt()
definitions as needed. It's first argument is generally the top-level command name you used in your firstcmd()
call.my ($class, $opts) = class_optargs('App::demo'); printf "Running %s with %s\n", $class, Dumper($opts) unless $opts->{quiet};
The additional return value
$class
is the name of the actual (sub-)command to which the$opts
HASHref applies. Usage exceptions are raised just the same as with theoptargs()
function.error: unknown option "--invalid" usage: demo COMMAND [OPTIONS...] COMMAND command to run bar demo bar foo demo foo --quiet, -q run quietly
Note that options are inherited by subcommands.
- Dispatch/Execution
-
Once you have the subcommand name and the option/argument hashref you can either execute the action or dispatch to the appropriate class/package as you like.
There are probably several ways to layout command classes when you have lots of subcommands. Here is one way that seems to work for this module's author.
- lib/App/demo.pm, lib/App/demo/subcmd.pm
-
I typically put the actual (sub-)command implementations in lib/App/demo.pm and lib/App/demo/subcmd.pm. App::demo itself only needs to exists if the root command does something. However I tend to also make App::demo the base class for all subcommands so it is often a non-trivial piece of code.
- lib/App/demo/OptArgs.pm
-
App::demo::OptArgs is where I put all of my command definitions with names that match the actual implementation modules.
package App::demo::OptArgs; use Getopt::Args2; cmd 'App::demo' => ( comment => 'the demo app', optargs => sub { #... }, )
The reason for keeping this separate from lib/App/demo.pm is speed of loading. I don't want to have to load all of the modules that App::demo itself uses just to find out that I called the command incorrectly.
- bin/demo
-
The command script itself is then usually fairly short:
#!/usr/bin/env perl use Getopt::Args2 'class_optargs'; use App::demo::OptArgs; my ($class, $opts) = class_optargs('App::demo'); eval "require $class" or die $@; $class->new->run($opts);
The above does nothing more than load the definitions from App::demo::OptArgs, obtain the command name and options hashref, and then loads the appropriate package to run the command.
Formatting of Usage Messages
Usage messages attempt to present as much information as possible to the caller. Here is a brief overview of how the various types look and/or change depending on things like defaults.
The presentation of Bool options in usage messages is as follows:
Name Type Default Presentation
---- ---- ------- ------------
option Bool undef --[no-]option
option Bool true --no-option
option Bool false --option
option Counter * --option
The Flag option type is like a Bool that can only be set to true or left undefined. This makes sense for things such as --help
or --version
for which you never need to see a "--no" prefix.
Name Type Default Presentation
---- ---- ------- ------------
option Flag always undef --option
Note that Flags also makes sense for "negative" options which will only ever turn things off:
Name Type Default Presentation
---- ---- ------- ------------
no_option Flag always undef --no-option
# In Perl
opt no_foo => (
isa => 'Flag',
comment => 'disable the foo feature',
);
# Then later do { } unless $opts->{no_foo}
The remaining types are presented as follows:
Name Type isa_name Presentation
---- ---- -------- ------------
option ArrayRef - --option Str
option HashRef - --option Str
option Int - --option Int
option Num - --option Num
option Str - --option Str
option * XX --option XX
Defaults TO BE COMPLETED.
FUNCTIONS
The following functions are exported by default.
- arg( $name, %parameters )
-
Define a command argument, for example:
arg name => ( comment => 'the file to parse', default => '-', greedy => 0, isa => 'Str', # required => 1, );
The
arg()
function accepts the following parameters:- comment
-
Required. Used to generate the usage/help message.
- default
-
The value set when the argument is not given. Conflicts with the 'required' parameter.
If this is a subroutine reference it will be called with a hashref containg all option/argument values after parsing the source has finished. The value to be set must be returned, and any changes to the hashref are ignored.
- greedy
-
If true the argument swallows the rest of the command line.
- fallback
-
A hashref containing an argument definition for the event that a subcommand match is not found. This parameter is only valid when
isa
is aSubCmd
. The hashref must contain "isa", "name" and "comment" key/value pairs, and may contain a "greedy" key/value pair.This is generally useful when you want to calculate a command alias from a configuration file at runtime, or otherwise run commands which don't easily fall into the Getopt::Args2 subcommand model.
- isa
-
Required. Is mapped to a Getopt::Long type according to the following table:
optargs Getopt::Long ------------------------------ 'Str' '=s' 'Int' '=i' 'Num' '=f' 'ArrayRef' 's@' 'HashRef' 's%' 'SubCmd' '=s' 'OptArgRef' 's@'
An OptArgRef isa is an ArrayRef that doesn't undergo checks for unexpected options. It exists to capture options and arguments which get passed back into class_optargs again.
- isa_name
-
When provided this parameter will be presented instead of the generic presentation for the 'isa' parameter.
- required
-
Set to a true value when the caller must specify this argument. Conflicts with the 'default' parameter.
- show_default
-
Boolean to indicate if the default value should be shown in usage messages. Overrides the (sub-)command's
show_default
setting.
- class_optargs( $class, [ @argv ] ) -> ($subclass, $opts)
-
Parse @ARGV by default (or @argv when given) for the arguments and options defined for command
$class
.@ARGV
will first be decoded into UTF-8 (if necessary) from whatever I18N::Langinfo says your current locale codeset is.Throws an error / usage exception object (typically
Getopt::Args2::Usage
) for missing or invalid arguments/options. Uses OptArgs2::Pager for 'ishelp' output.Returns the following two values:
- $subclass
-
The actual subcommand name that was matched by parsing the arguments. This may be the same as
$class
. - $opts
-
a hashref containing key/value pairs for options and arguments combined.
As an aid for testing, if the passed in argument
@argv
(not @ARGV) contains a HASH reference, the key/value combinations of the hash will be added as options. An undefined value means a boolean option. - cmd( $class, %parameters ) -> Getopt::Args2::Cmd
-
Define a top-level command identified by
$class
which is typically a Perl package name. The following parameters are accepted:- abbrev
-
When set to true then subcommands can be abbreviated, up to their shortest, unique values.
- comment
-
A description of the command. Required.
- optargs
-
A subref containing calls to
arg()
andopt
. Note that options are inherited by subcommands so you don't need to define them again in child subcommands. - show_color
-
Boolean indicating if usage messages should use ANSI terminal color codes to highlight different elements. True by default.
- show_default
-
Boolean indicating if default values for options and arguments should be shown in usage messages. Can be overriden by sub-commands, args and opts. Off by default.
- opt( $name, %parameters )
-
Define a command option, for example:
opt colour => ( alias => 'c', comment => 'the colour to paint', default => 'blue', show_default => 1, isa => 'Str', );
Any underscores in
$name
are be replaced by dashes (-) for presentation and command-line parsing. Thearg()
function accepts the following parameters:- alias
-
A single character alias.
- comment
-
Required. Used to generate the usage/help message.
- default
-
The value set when the option is not given. Conflicts with the 'required' parameter.
If this is a subroutine reference it will be called with a hashref containing all option/argument values after parsing the source has finished. The value to be set must be returned, and any changes to the hashref are ignored.
- required
-
Set to a true value when the caller must specify this option. Conflicts with the 'default' parameter.
-
When true this option will not appear in usage messages unless the usage message is a help request.
This is handy if you have developer-only options, or options that are very rarely used that you don't want cluttering up your normal usage message.
- isa
-
Required. Is mapped to a Getopt::Long type according to the following table:
isa Getopt::Long --- ------------ 'ArrayRef' 's@' 'Flag' '!' 'Bool' '!' 'Counter' '+' 'HashRef' 's%' 'Int' '=i' 'Num' '=f' 'Str' '=s'
- isa_name
-
When provided this parameter will be presented instead of the generic presentation for the 'isa' parameter.
- ishelp
-
Makes the option behave like a typical
--help
, that displays a usage message and exits before errors are generated. Typically used alone as follows:opt help => ( ishelp => Getopt::Args2::STYLE_HELP, ); opt help_tree => ( ishelp => Getopt::Args2::STYLE_HELPTREE, alias => 'T', # or 'undef' if you don't want an alias );
The first option above is similar to this longhand version:
opt help => ( isa => 'Flag', alias => 'h', # first character of the opt name comment => 'print a usage message and exit', trigger => sub { # Start a pager for long messages print Getopt::Args2::usage(undef, Getopt::Args2::STYLE_HELP); # Stop the pager exit; } );
You can override any of the above with your own parameters.
- show_default
-
Boolean to indicate if the default value should be shown in usage messages. Overrides the (sub-)command's
show_default
setting. - trigger
-
The trigger parameter lets you define a subroutine that is called after processing before usage exceptions are raised. This is primarily to support --help or --version options which would typically override usage errors.
opt version => ( isa => 'Flag', alias => 'V', comment => 'print version string and exit', trigger => sub { my ( $cmd, $value ) = @_; die "$cmd version $VERSION\n"; } );
The trigger subref is passed two parameters: a Getopt::Args2::Cmd object and the value (if any) of the option. The Getopt::Args2::Cmd object is an internal one, but one public interface is has (in addition to the usage() method described in 'ishelp' above) is the usage_tree() method which gives a usage overview of all subcommands in the command hierarchy.
opt usage_tree => ( isa => 'Flag', alias => 'U', comment => 'print usage tree and exit', trigger => sub { my ( $cmd, $value ) = @_; die $cmd->usage_tree; } ); # demo COMMAND [OPTIONS...] # demo foo ACTION [OPTIONS...] # demo bar [OPTIONS...]
- optargs( [@argv] ) -> HASHref
-
Parse @ARGV by default (or @argv when given) for the arguments and options defined for the default global command. Argument decoding and exceptions are the same as for
class_optargs
, but this function returns only the combined argument/option values HASHref.This interface has been superceeded by
optargs2()
. - optargs2( @command_args_and_opts ) -> HASHref
-
This all-in-one function passes it's arguments directly to
cmd()
, callsclass_optargs()
, and returns only the$opts
HASHref result. It is the most convenient Getopt::Args2 interface for simple scripts. - subcmd( $class, %parameters ) -> Getopt::Args2::Cmd
-
Defines a subcommand identified by
$class
which must include the name of a previously defined (sub)command + '::'.Accepts the same parameters as
cmd()
in addition to the following:-
Hide the existence of this subcommand in non-help usage messages. This is handy if you have developer-only or rarely-used commands that you don't want cluttering up your normal usage message.
-
- usage( $class, [STYLE] ) -> Str
-
Only exported on request, this function returns the usage string for the command
$class
.
SEE ALSO
OptArgs2::Pager, OptArgs2::StatusLine, Getopt::Long
This module is duplicated on CPAN as OptArgs2, to cover both its original name and yet still be found in the mess that is Getopt::*.
SUPPORT & DEVELOPMENT
This distribution is managed via github:
https://github.com/mlawren/p5-OptArgs2/tree/devel
This distribution follows the semantic versioning model:
http://semver.org/
Code is tidied up on Git commit using githook-perltidy:
http://github.com/mlawren/githook-perltidy
AUTHOR
Mark Lawrence <nomad@null.net>
LICENSE
Copyright 2016-2022 Mark Lawrence <nomad@null.net>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.