File Coverage

blib/lib/Getopt/Easy.pm
Criterion Covered Total %
statement 51 55 92.7
branch 31 34 91.1
condition 7 8 87.5
subroutine 4 4 100.0
pod 0 1 0.0
total 93 102 91.1


line stmt bran cond sub pod time code
1 1     1   13274 use strict;
  1         3  
  1         41  
2 1     1   8 use warnings;
  1         2  
  1         80  
3              
4             package Getopt::Easy;
5             our $VERSION = 0.1;
6              
7 1     1   5 use Exporter;
  1         6  
  1         1678  
8             our @ISA = qw/Exporter/;
9             our %O;
10             our @EXPORT = qw/get_options %O/;
11              
12             sub get_options {
13 8     8 0 490 my ($optstr, $usage, $helpchars) = @_;
14              
15 8   50     32 $helpchars ||= "";
16 8         23 $optstr =~ s/^\s*//;
17 8         11 my $err = 0;
18 8         8 my (%options, %valid);
19 0         0 my ($l, $word);
20 8         17 for (split(/\s+/, $optstr)) {
21 22 100       118 ($l, $word) = /^(.)-(.*)$/
22             or die "$_: syntax error - must be like this: l-length\n";
23             #
24             # check for the = sign.
25             # there are two different uses of it
26             #
27 21 100       71 if ($word =~ s/=$//) {
    100          
28 8         10 $l .= '=';
29             } elsif ($word =~ s/=(.+)//) {
30 5         5 $l .= '=';
31 5         12 $valid{$word} = $1;
32             }
33 21         34 $options{$l} = $word;
34 21 100       56 $O{$word} = ($l =~ /=/)? "": 0 unless exists $O{$word};
    100          
35             }
36 7 50       15 exit if $err;
37             #
38             # with %options and %valid and %O and $helpchars initialized properly
39             # we are now ready to examine @ARGV
40             #
41 7         5 my ($arg, $let, $val);
42 7         7 $err = "";
43 7   100     42 ARGV: while (@ARGV and $ARGV[0] =~ s/^-//) {
44 12         18 $arg = shift @ARGV;
45 12 100       24 last if $arg eq "-"; # stop processing options
46 11         31 while ($arg =~ s/^(.)//) {
47 11         17 $let = $1;
48 11 50       36 if (index($helpchars, $let) >= 0) { # help
    100          
    100          
49 0         0 require "Pod/Text.pm";
50 0         0 Pod::Text->new->parse_from_file($0);
51 0         0 exit;
52             } elsif (exists $options{$let}) { # boolean
53 2         15 $O{$options{$let}} = 1;
54             } elsif (exists $options{"$let="}) { # with value
55 7 100 100     34 if ($arg eq "" and not $arg = shift @ARGV) {
    100          
56 1         3 $err .= "missing argument for -$let\n";
57 1         3 next ARGV;
58             } elsif ($arg =~ /^-/) {
59 1         3 $err .= "value $arg for -$let begins with a dash\n";
60 1         3 next ARGV;
61             } else {
62 5         10 $O{$options{"$let="}} = $arg;
63 5         6 $arg = "";
64             }
65 5 100       29 if (my $v = $valid{$options{"$let="}}) { # debugging style
66             #
67             # $v now contains the only valid options for -$let
68             #
69 2         4 my $opts = $O{$options{"$let="}};
70 2         25 $opts =~ s/[$v]//g; # remove the good ones
71 2 100       12 if ($opts) {
72 1 50       3 my $plural = (length($opts) > 1)? "s": "";
73 1         8 $err .= "for -$let: illegal option$plural: ".
74             "$opts, valid ones are: $v\n";
75             }
76             }
77             } else {
78 2         9 $err .= "unknown option: -$let\n";
79             }
80             }
81             }
82 7 100       18 if ($err) {
83 5 100       10 if ($usage) {
84             #
85             # make sure there is a newline
86             # else we'll get "at line ..."
87             #
88 1         3 chomp $usage;
89 1         2 $err .= "$usage\n";
90             }
91 5         24 die $err;
92             }
93             }
94              
95             1;
96              
97             =head1 NAME
98              
99             Getopt::Easy - parses command line options in a simple but capable way.
100              
101             =head1 SYNOPSIS
102              
103             use Getopt::Easy;
104              
105             get_options "v-verbose f-fname= D-debug=uSX",
106             "usage => "usage: prog [-v] [-f fname] [-D [uSX]] [-H]",
107             "H";
108              
109             print "reading $O{fname}\n" if $O{verbose};
110             print "SQL: $sql\n" if $O{debug} =~ /S/;
111              
112             =head1 DESCRIPTION
113              
114             Perl puts the command line parameters in the array @ARGV
115             allowing the user to examine and manipulate it like any
116             other array. There is a long tradition of putting optional
117             single character flags (preceded by a dash) in front of
118             other parameters like so:
119              
120             % ls -ltr *.h *.c
121             % tar -tvf all.tar
122             % ps -ax -U jsmith
123              
124             Many Getopt::* modules exist to help with the
125             parsing of these flags out of @ARGV.
126             For the author, Getopt::Std was visually too cryptic and
127             Getopt::Long was too large and complex for most normal applications.
128             Getopt::Easy is small, easy to understand, and provides a visual clarity.
129              
130             There are two things exported: get_options() and %O.
131              
132             get_options has 1 required parameter and 2 optional ones.
133             The first is a string describing the kind of options that
134             are expected. It is a space separated list of terms like this:
135              
136             get_options "v-verbose f-fname=";
137              
138             If the -v option is given on the command
139             line %O{verbose} will be set to 1 (true).
140             If the -f option is given then another argument is expected
141             which will be assigned to $O{fname}.
142              
143             Before parsing @ARGV, $O{verbose} will be initialized to 0 (false) and
144             $O{fname} to "" (unless they already have a value).
145              
146             If you give an unknown option get_options() will complain and exit:
147              
148             % prog -vX
149             unknown option: -X
150             %
151              
152             These conventions are implemented by Getopt::Easy:
153              
154             =over 4
155              
156             =item *
157              
158             The options can come in any order.
159              
160             =item *
161              
162             Multiple boolean options can be bundled together.
163              
164             =item *
165              
166             A command line argument of '--' will cause argument parsing to stop
167             so you can parse the rest of the options yourself.
168              
169             =item *
170              
171             Parsed arguments are removed from @ARGV.
172              
173             =back
174              
175             These invocations are equivalent:
176              
177             % prog -v -f infile
178             % prog -f infile -v # different order
179             % prog -v -finfile
180             % prog -vf infile
181             % prog -vfinfile
182              
183             This shows that the space between -f and infile is optional
184             and that you I bundle -f with -v but -f must be
185             the I option in the bundle.
186              
187             The optional second parameter to get_options() is
188             a usage message to be printed when an illegal option is given.
189              
190             get_options "v-verbose f-fname=",
191             "usage: prog [-v] [-f fname]";
192              
193             Now if an unknown option is given, the same
194             error message will be printed, as above, followed
195             by the usage message.
196            
197             % prog -vX
198             unknown option: -X
199             usage: prog [-v] [-f fname]
200             %
201              
202             =head2 HELP
203              
204             Sometimes the usage message is not enough and the
205             user needs more detailed and elaborate help. This is
206             where the 3rd optional parameter comes in.
207              
208             get_options "v-verbose f-fname=",
209             "usage: prog [-v] [-f fname] [-H]",
210             "H";
211              
212             Giving the -H option will cause the POD for the module
213             to be echoed to STDOUT - as if the user had typed
214             'perldoc prog'. See 'perldoc perlpod'.
215              
216             =head2 DEBUGGING
217              
218             There are various ways to implement a debugging option:
219              
220             GOOD:
221              
222             get_options "d-debug";
223              
224             print "val = $val\n" if $O{debug};
225              
226             BETTER:
227              
228             get_options "d-debug=";
229              
230             print "SQL = $sql\n" if $O{debug} >= 2;
231             print "val = $val\n" if $O{debug} >= 3;
232              
233             With this method there are various I of debugging.
234             Unfortunately, they often end up ranging from
235             'not enough' to 'too much' :(.
236              
237             BEST:
238              
239             get_options "d-debug=eSvL";
240              
241             print "SQL = $sql\n" if $O{debug} =~ /S/;
242             print "val = $val\n" if $O{debug }=~ /v/;
243            
244             With this kind of term the letters after the equal sign '=' are the
245             debugging options that are valid. Now the user can choose exactly
246             what kind of debugging output they wish to see.
247              
248             % prog -d SL
249              
250             Giving an illegal debugging option will
251             result in an error message:
252              
253             % prog -deXSf
254             for -d: illegal options: Xf, valid ones are: eSvL
255             %
256              
257             =head1 ACCESS ELSEWHERE
258              
259             If you want access to the %O hash from other files simply put:
260              
261             use Getopt::Easy;
262              
263             at the top of those files; the %O hash will again be exported into the
264             current package. You need to have:
265              
266             get_options ...;
267              
268             only once in the main file before anyone needs to look at the %O hash.
269              
270             =head1 STRICT
271              
272             It is easy to misspell a key for the %O hash. Tie::StrictHash
273             can help with this:
274              
275             use GetOpt::Easy;
276             use Tie::StrictHash;
277              
278             get_options "v-verbose f-fname=";
279             strict_hash %O;
280              
281             print "file name is $O{filename}\n";
282              
283             This will give a fatal error message:
284              
285             key 'filename' does not exist at prog line 6
286              
287             =head1 SEE ALSO
288              
289             Config::Easy allows configuration file entries
290             to be overidden with command line arguments.
291              
292             Tie::StrictHash protects against misspelling of key names.
293              
294             Date::Simple is an elegant way of dealing with dates.
295              
296             =head1 AUTHOR
297              
298             Jon Bjornstad