File Coverage

lib/Getopt/Compact.pm
Criterion Covered Total %
statement 110 128 85.9
branch 32 50 64.0
condition 16 31 51.6
subroutine 16 18 88.8
pod 6 6 100.0
total 180 233 77.2


line stmt bran cond sub pod time code
1             # $Id: Compact.pm 15 2006-09-04 20:00:01Z andrew $
2             # Copyright (c) 2004-2006 Andrew Stewart Williams. All rights reserved.
3             # This program is free software; you can redistribute it and/or
4             # modify it under the same terms as Perl itself.
5              
6             package Getopt::Compact;
7 1     1   779 use strict;
  1         2  
  1         43  
8 1     1   1220 use Getopt::Long;
  1         13593  
  1         8  
9 1     1   216 use Config;
  1         2  
  1         36  
10 1     1   5 use File::Spec;
  1         1  
  1         27  
11 1     1   4 use Carp;
  1         2  
  1         72  
12 1     1   5 use vars qw($VERSION);
  1         1  
  1         57  
13 1         194 use constant CONSTRUCTOR_OPTIONS =>
14 1     1   5 (qw/struct usage name version author cmd args configure modes/);
  1         2  
15 1     1   5 use constant DEFAULT_CONFIG => (no_auto_abbrev => 1, bundling => 1);
  1         1  
  1         1403  
16              
17             $VERSION = "0.04";
18              
19             sub new {
20 2     2 1 852 my($class, %args) = @_;
21 2         6 my $self = bless {}, $class;
22 2         517 my(%opt, $i);
23              
24 2   100     11 $args{struct} ||= [];
25 2         4 for $i (CONSTRUCTOR_OPTIONS) {
26 18 100       32 next unless exists $args{$i};
27 5         17 $self->{$i} = delete $args{$i};
28             }
29 2         10 croak("unrecognised option: $_") for keys %args;
30              
31 2         2 my $struct = $self->{struct};
32 2 50       7 $self->{usage} = 1 unless exists $self->{usage};
33 2 50       3 unless ($self->{cmd}) {
34 2         12 require File::Basename;
35 2   50     86 $self->{cmd} = File::Basename::basename($0 || '');
36             }
37              
38             # more version munging
39 2   50     8 my $v = $self->{version} || $main::VERSION || '1.0';
40 2 50       6 $v = $1 if $v =~ /\$?Revision:?\s*([\d\.]+)/;
41 2         4 $self->{version} = $v;
42              
43             # add mode options
44 2 50       5 if ($self->{modes}) {
45 2         2 my @modeopt;
46 2         2 for my $m (@{$self->{modes}}) {
  2         4  
47 4         10 my($mc) = $m =~ /^(\w)/;
48 4 100       9 $mc = 'n' if $m eq 'test';
49 4         16 push @modeopt, [[$mc, $m], qq($m mode)];
50             }
51 2         4 unshift @$struct, @modeopt;
52             }
53              
54             # add --help option if usage is enabled
55 2 50 33     9 unshift @$struct, [[qw(h help)], qq(this help message)]
56             if $self->{usage} && !$self->_has_option('help');
57              
58             # add --man option unless one already exists
59 2 50       6 unless($self->_has_option('man')) {
60 2         3 push @$struct, ['man', qq(Display documentation)];
61 2         4 $self->{_allow_man} = 1;
62             }
63              
64 2         4 my $opthash = {};
65 2         5 $self->{opt} = \%opt;
66 2         3 for my $s (@$struct) {
67 15         20 my($m, $descr, $spec, $ref) = @$s;
68 15         30 my @onames = $self->_option_names($m);
69 15         32 my($longname) = grep length($_) > 1, @onames; # first long name
70 15   100     3370 my $o = join('|', @onames).($spec || '');
71 15 100       23 my $dest = $longname ? $longname : $onames[0];
72 15         40 $opt{$dest} = undef; # initialise destination
73 15 100       64 $opthash->{$o} = ref $ref ? $ref : \$opt{$dest};
74             }
75              
76             # configure getopt option preferences
77 2 50       4 my %config = (DEFAULT_CONFIG, %{$self->{configure} || {}});
  2         15  
78 2         7 my @gconf = grep $config{$_}, keys %config;
79 2 50       10 Getopt::Long::Configure(@gconf) if @gconf;
80              
81             # parse options
82 2         86 $self->{ret} = GetOptions(%$opthash);
83              
84 2         1476 return $self;
85             }
86              
87             sub opts {
88 2     2 1 5 my($self) = @_;
89 2         4 my $opt = $self->{opt};
90 2 50 33     17 if ($self->{_allow_man} && $opt->{man}) {
    50 33        
      33        
91             # display modified POD
92 0         0 $self->pod2usage();
93 0         0 exit !$self->status;
94             } elsif ($self->{usage} && ($opt->{help} || $self->status == 0)) {
95             # display usage message & exit
96 0         0 print $self->usage;
97 0         0 exit !$self->status;
98             }
99 2         4 return $opt;
100             }
101              
102             # munge & print a POD manpage
103             sub pod2usage {
104 0     0 1 0 my $self = shift;
105 0         0 my $usage = $self->usage;
106 0         0 my $script = $self->_find_program;
107              
108 0         0 require Getopt::Compact::PodMunger;
109 0         0 my $pod = new Getopt::Compact::PodMunger;
110 0 0       0 $pod->parse_from_file($script) if defined $script;
111 0   0     0 $pod->insert('NAME', $self->{name} || $self->{cmd});
112 0         0 $pod->insert('USAGE', $usage, 1);
113 0         0 $pod->insert('VERSION', $self->{version});
114 0         0 $pod->insert('AUTHOR', $self->{author});
115 0         0 $pod->print_manpage;
116             }
117              
118             # return return value of GetOptions
119 2     2 1 9 sub status { shift->{ret} }
120              
121             # return a string explaining usage
122             sub usage {
123 1     1 1 3566 my($self) = @_;
124 1         3 my $usage = "";
125 1         1 my($v, @help);
126              
127 1   100     18 my($name, $version, $cmd, $struct, $args) = map
128             $self->{$_} || '', qw/name version cmd struct args/;
129              
130 1 50       5 if($name) {
131 1         4 $usage .= $name;
132 1 50       4 $usage .= " v$version" if $version;
133 1         2 $usage .= "\n";
134             }
135 1         4 $usage .= "usage: $cmd [options] $args\n";
136              
137 1         3 for my $o (@$struct) {
138 12         20 my($opts, $desc) = @$o;
139 12 50       18 next unless defined $desc;
140 12         24 my @onames = $self->_option_names($opts);
141 26 100       61 my $optname = join
142 12         17 (', ', map { (length($_) > 1 ? '--' : '-').$_ } @onames);
143 12 100       25 $optname = " ".$optname unless length($onames[0]) == 1;
144 12         214 push @help, [ $optname, ucfirst($desc) ];
145             }
146 1         996 require Text::Table;
147 1         16087 my $sep = ' ';
148 1         7 my $tt = new Text::Table('options', \$sep, '');
149 1         909 $tt->load(@help);
150 1         633 $usage .= $tt."\n";
151 1         14820 return $usage;
152             }
153              
154 0     0 1 0 sub version { $VERSION }
155              
156             ######################################################################
157             # Private subs/methods
158              
159             sub _option_names {
160 51     51   59 my($self, $m) = @_;
161 51 100       159 return sort _opt_sort (ref $m eq 'ARRAY' ? @$m : $m);
162             }
163             sub _opt_sort {
164 72     72   133 my($la, $lb) = map length($_), $a, $b;
165 72 100 100     275 return $la <=> $lb if $la < 2 or $lb < 2;
166 12         30 return 0;
167             }
168              
169             sub _has_option {
170 4     4   3 my($self, $option) = @_;
171 4         12 return 1 if grep $_ eq $option, map
172 4 50       4 $self->_option_names($_->[0]), @{$self->{struct}};
173 4         20 return 0;
174             }
175              
176             # find the full path to the program, or undefined if it couldn't be found
177             sub _find_program {
178 1     1   4 my($self) = @_;
179 1 50       6 return $self->{_program} if exists $self->{_program};
180 1         3 my $script = $0;
181 1 50 33     30 if(defined $script && ! -e $script) {
182             # $0 is not the full path to script. look for script in path.
183 0         0 require Env::Path;
184 0         0 ($script) = Env::Path->Whence($script);
185             }
186 1         5 return $self->{_program} = $script;
187             }
188              
189             1;
190              
191             =head1 NAME
192              
193             Getopt::Compact - getopt processing in a compact statement with both
194             long and short options, and usage functionality.
195              
196             =head1 SYNOPSIS
197              
198             inside foobar.pl:
199              
200             use Getopt::Compact;
201              
202             # (1) simple usage:
203             my $opts = new Getopt::Compact
204             (struct =>
205             [[[qw(b baz)], qq(baz option)], # -b or --baz
206             ["foobar", qq(foobar option)], # --foobar only
207             ])->opts();
208              
209             # (2) or, a more advanced usage:
210             my $go = new Getopt::Compact
211             (name => 'foobar program', modes => [qw(verbose test debug)],
212             struct =>
213             [[[qw(w wibble)], qq(specify a wibble parameter), ':s'],
214             [[qw(f foobar)], qq(apply foobar algorithm)],
215             [[qw(j joobies)], qq(jooby integer list), '=i', \@joobs],
216             ]
217             );
218             my $opts = $go->opts;
219              
220             print "applying foobar algorithm\n" if $opt->{foobar};
221             print "joobs: @joobs\n" if @joobs;
222             print $go->usage if MyModule::some_error_condition($opts);
223              
224             using (2), running the command './foobar.pl -x' results in the
225             following output:
226              
227             Unknown option: x
228             foobar program v1.0
229             usage: foobar.pl [options]
230             options
231             -h, --help This help message
232             -v, --verbose Verbose mode
233             -n, --test Test mode
234             -d, --debug Debug mode
235             -w, --wibble Specify a wibble parameter
236             -f, --foobar Apply foobar algorithm
237             -j, --joobies Jooby integer list
238             --man Display documentation
239              
240             =head1 DESCRIPTION
241              
242             This is yet another Getopt related module. Getopt::Compact is geared
243             towards compactly and yet quite powerfully describing an option
244             syntax. Options can be parsed, returned as a hashref of values,
245             and/or displayed as a usage string or within the script POD.
246              
247             =head1 PUBLIC METHODS
248              
249             =over 4
250              
251             =item new()
252              
253             my $go = new Getopt::Compact(%options)
254              
255             Instantiates a Getopt::Compact object. This will parse the command
256             line arguments and store them for later retrieval (via the opts()
257             method). On error a usage string is printed and exit() is called,
258             unless you have set the 'usage' option to false.
259              
260             The following constructor options are recognised:
261              
262             =over 4
263              
264             =item C
265              
266             The name of the program. This is printed at the start of the usage string.
267              
268             =item C
269              
270             The command used to execute this program. Defaults to $0. This will be
271             printed as part of the usage string.
272              
273             =item C
274              
275             Program version. Can be an RCS Version string, or any other string.
276             Displayed in usage information. The default is ($main::VERSION || '1.0')
277              
278             =item C
279              
280             'usage' is set to true by default. Set it to false (0) to disable the
281             default behaviour of automatically printing a usage string and exiting
282             when there are parse errors or the --help option is given.
283              
284             =item C
285              
286             A string describing mandatory arguments to display in the usage string.
287             eg:
288              
289             print new Getopt::Compact
290             (args => 'foo', cmd => 'bar.pl')->usage;
291              
292             displays:
293              
294             usage: bar.pl [options] foo
295              
296             =item C
297              
298             This is a shortcut for defining boolean mode options, such as verbose
299             and test modes. Set it to an arrayref of mode names, eg
300             [qw(verbose test)]. The following statements are equivalent:
301              
302             # longhand version
303             my $go = new Getopt::Compact
304             (struct => [[[qw(v verbose)], qw(verbose mode)],
305             [[qw(n test)], qw(test mode)],
306             [[qw(d debug)], qw(debug mode)],
307             [[qw(f foobar)], qw(activate foobar)],
308             ]);
309              
310             and
311              
312             # shorthand version
313             my $go = new Getopt::Compact
314             (modes => [qw(verbose test debug)],
315             struct => [[[qw(f foobar)], qq(activate foobar)]]);
316              
317             Mode options will be prepended to any options defined via the 'struct'
318             option.
319              
320             =item C
321              
322             This is where most of the option configuration is done. The format
323             for a struct option is an arrayref of arrayrefs (see C) in
324             the following form (where [ ] denotes an array reference):
325              
326             struct => [optarray, optarray, ...]
327              
328             and each optarray is an array reference in the following form:
329             (only 'name specification' is required)
330              
331             [name spec, description, argument spec, destination]
332              
333             name specification may be a scalar string, eg "length", or a reference
334             to an array of alternate option names, eg [qw(l length)]. The option
335             name specification is also used to determine the key to the option
336             value in the hashref returned by C. See C for more
337             information.
338              
339             The argument specification is passed directly to Getopt::Long, so any
340             syntax recognised by Getopt::Long should also work here. Some argument
341             specifications are:
342              
343             =s Required string argument
344             :s Optional string argument
345             =i Required integer argument
346             + Value incrementing
347             ! Negatable option
348              
349             Refer to L documentation for more details on argument
350             specifications.
351              
352             The 'destination' is an optional reference to a variable that will
353             hold the option value. If destination is not specified it will be
354             stored internally by Getopt::Compact and can be retrieved via the
355             opts() method.
356             This is useful if you want options to accept multiple values. The
357             only way to achieve this is to use a destination that is a reference
358             to a list (see the joobies option in C by way of example).
359              
360             =item C
361              
362             Optional configure arguments to pass to Getopt::Long::Configure in the form
363             of a hashref of key, boolean value pairs.
364             By default, the following configuration is used:
365              
366             { no_auto_abbrev => 1, bundling => 1 }
367              
368             To disable bundling and have case insensitive single-character options you
369             would do the following:
370              
371             new Getopt::Compact
372             (configure => { ignorecase_always => 1, bundling => 0 });
373              
374             see Getopt::Long documentation for more information on configuration options.
375              
376             =back
377              
378             =item $go->usage()
379              
380             print $go->usage();
381              
382             Returns a usage string. Normally the usage string will be printed
383             automatically and the program will exit if the user supplies an
384             unrecognised argument or if the -h or --help option is given.
385             Automatic usage and exiting can be disabled by setting 'usage'
386             to false (0) in the constructor (see new()).
387             This method uses L internally to format the usage output.
388              
389             The following options may be automatically added by Getopt::Compact:
390              
391             =over 4
392              
393             =item "This help message" (-h or --help)
394              
395             A help option is automatically prepended to the list of available
396             options if the C constructor option is true (this is enabled by
397             default). When invoked with -h or --help, Getopt::Compact
398             automatically displays the usage string and exits.
399              
400             =item "Display documentation" (--man)
401              
402             This option is appended to the list of available options unless an
403             alternative --man option has been defined. When invoked with --man,
404             Getopt::Compact prints a modified version of its POD to stdout and
405             exits.
406              
407             =back
408              
409             =item $go->pod2usage()
410              
411             Displays the POD for the script. The POD will be altered to include
412             C, C and C sections unless they already exist.
413             This is invoked automatically when the --man option is given.
414              
415             =item $go->status()
416              
417             print "getopt ".($go->status ? 'success' : 'error'),"\n";
418              
419             The return value from Getopt::Long::Getoptions(). This is a true value
420             if the command line was processed successfully. Otherwise it returns a
421             false result.
422              
423             =item $go->opts()
424              
425             $opt = $go->opts;
426              
427             Returns a hashref of options keyed by option name. If the
428             constructor usage option is true (on by default), then a usage string
429             will be printed and the program will exit if it encounters an
430             unrecognised option or the -h or --help option is given.
431              
432             The key in %$opt for each option is determined by the option names
433             in the specification used in the C definition. For example:
434              
435             =over 4
436              
437             =item ["foo", qw(foo option)]
438              
439             The key will be "foo".
440              
441             =item [[qw(f foo)], qw(foo option)]
442              
443             =item [[qw(f foo foobar)], qw(foo option)]
444              
445             In both cases the key will be "foo". If multiple option names are
446             given, the first long option name (longer than one character) will be
447             used as the key.
448              
449             =item [[qw(a b)], qq(a or b option)]
450              
451             The key here will be "a". If all alternatives are one character, the first option name in the list is used as the key
452              
453             =back
454              
455             =back
456              
457             =head1 AUTHOR
458              
459             Andrew Stewart Williams
460              
461             =head1 SEE ALSO
462              
463             Getopt::Long
464              
465             =cut