|
Item Description: Declarative command line argument parser
Review Synopsis:
Getopt::Declare A quickie overview.
Getopt::Declare is a module for parsing command line options -- and
like many of Damian Conway's modules, this one has obviously been
eating its wheaties with large doses of steroids (and it arrives with
circa 1,500 lines of documentation to prove it). In short, this is not
your mother's command line parser.
Not satisfied with giving us yet another command line parser,
Damian has given us a declarative language to specify not only
command line options, but descriptions, parameter types, and actions
as well. But don't let the size of the docs intimidate you, it is
surprisingly simple to use.
The basic mechanics of using the module are as follows:
#!/usr/bin/perl -w
use strict;
use Getopt::Declare;
my $spec = <<'SPEC';
# put your specification here
SPEC
my $ops = Getopt::Declare->new($spec);
# rest of your program
Obviously, it is the specification we are really interested in.
So let's look a very trivial greplike script using the module:
#!/usr/bin/perl -w
use strict;
use Getopt::Declare;
use vars qw/$not $re/;
$::VERSION = 0.01;
my $spec = <<'EOS';
-p <pattern> pattern [required]
{ $re = $pattern }
-f <INFILE>... input filename(s) [required]
{ defer{process(@INFILE)} }
-not print out non-matches
{ $not = 1 }
EOS
my $opts = Getopt::Declare->new($spec);
sub process {
@ARGV = @_;
while(<>){
if($::not){
print unless /$::re/;
} else {
print if /$::re/;
}
}
}
__END__
An option declaration is comprised of a few components: the option
specification itself (followed by one or more tabs); the option
description (with optional directives); and an optional action block
to be executed if the option is found. Let's break out the -f option
above and look at each component:
-f <INFILE>...
# So we specify an option that looks like '-f' which takes one or
# more arguments (that's the ... part) that will be stored in the
# variable @INFILE for the action block
input filename(s) [required]
# This is the description of the option followed by the
# [required] directive which means this option must be present on
# the command line
{ defer{process(@INFILE)} }
# This is the action block. The defer() function is from
# Getopt::Declare and takes a code block which will not be
# executed until all the command line options have been parsed.
# Here we merely provide our own function and pass it the files
# from the -f option as arguments.
The option variable is available as a lexical variable within the
action block, and you may set or access any globals that are available
at the time of parsing. In our example above we set the global
$re and $not variables in the action blocks
so we can access those later rather than accessing those options via
the $opts object. We deferred our file processing action
because we want to ensure all options have been parsed (and all
globals set) before we start grepping our files.
You can also restrict parameter types when specifying parameter
variables using a few predefined parameter types:
-p <var:s> # accept strings
-n <var:n> # accept any real number
-i <var:i> # accept only integers
And, because this is Perl, you can also specify your own regex to
limit the types of things a parameter should accept or define new
types:
-hw <hw:/\d+x\d+$/> HeightxWidth coordinates
#or
[pvtype: coord /\d+x\d+$]
-hw <hw:coord> HeightxWidth coordinates
This module also gives us a -help option for free, and
a -v option (if you've defined a $VERSION
variable). Here's what we get with those:
$ perl dopt.pl -v
dopt.pl: version 0.01 (Fri Feb 2 09:30:34 2001)
$ perl dopt.pl -help
Usage: dopt.pl [options] -p <pattern> -f <INFILE>...
dopt.pl -help
dopt.pl -version
Options:
-p <pattern> pattern
-f <INFILE>... input filename(s)
-not print out non-matches
And, with 1,500 lines of documentation I've clearly only
scratched the surface in this little overview. Go ahead and grab it,
read the docs, and play around (and, if you're feeling brave, read the
code too).
Re: Getopt::Declare by petral (Curate) on Feb 03, 2001 at 03:15 UTC |
Excellent quick start. I've been thinking about going back to look at this module, and this review makes it easier to jump in.
It's worth quoting his line from the BUGS section of the man page:
If nothing else, it shouldn't take 1500 lines to explain a package that was designed for intuitive ease of use!
p | [reply] |
Re (tilly) 1: Getopt::Declare by tilly (Archbishop) on Feb 03, 2001 at 05:17 UTC |
| [reply] |
|
$ time perl -MGetopt::Std -e 1
0.07user 0.00system 0:00.07elapsed 97%CPU
$ time perl -MGetopt::Long -e 1
0.19user 0.05system 0:00.23elapsed 102%CPU
$ time perl -MGetopt::Declare -e 1
0.59user 0.08system 0:00.67elapsed 99%CPU
For the option parsing itself, that'll depend on how much extra
work you put into the declaration (action blocks, more sophisticated
parameter checking, etc.). Certainly it isn't the option-processing
answer to every problem, but if it's easy to code and read and the
startup/parse hit (amortized over runtime) isn't crucial, it is
certainly worth looking into. It won't compete with Getopt::Std for
efficiency on simple things, but there's a boatload of functionality
I didn't mention -- here's the clustering example from the docs:
For example, given the parameter specifications:
-+ Swap signs
-a Append mode
-b Bitwise compare
-c <FILE> Create new file
+del Delete old file
+e <NICE:i> Execute (at specified nice level) when com
+plete
The following command-lines (amongst others) are all exactly equivalen
+t:
-a -b -c newfile +e20 +del
-abc newfile +dele20
-abcnewfile+dele20
-abcnewfile +e 20del
Also: optional parameter lists, abbreviations, mutex directive (only
one of a given set of options may appear on the command line). And,
it can be told to parse a config file rather than @ARGV, and can
return the parser object itself so you could use it to parse multiple
such sources. There might even be a kitchen sink in the source
somewhere, and you never know when one of those will come in handy.
| [reply] [d/l] [select] |
Re: Getopt::Declare by mirod (Canon) on Feb 16, 2001 at 14:35 UTC |
| [reply] |
|
| [reply] |
Back to Reviews
|