File Coverage

blib/lib/Getopt/Function.pm
Criterion Covered Total %
statement 27 114 23.6
branch 2 48 4.1
condition n/a
subroutine 7 12 58.3
pod 6 8 75.0
total 42 182 23.0


line stmt bran cond sub pod time code
1             package Getopt::Function;
2             @ISA=qw(Exporter);
3             @EXPORT_OK = qw(maketrue makevalue);
4              
5 1     1   1871 use Getopt::Mixed 1.006, 'nextOption';
  1         2630  
  1         157  
6              
7 1     1   7 use strict;
  1         3  
  1         28  
8 1     1   5 use Carp;
  1         5  
  1         93  
9 1     1   5 use vars qw($VERSION $verbose_default);
  1         2  
  1         2013  
10             $VERSION=0.017;
11              
12              
13             =head1 NAME
14              
15             Getopt::Function - provide mixed options with help information
16              
17             =head1 SYNOPSIS
18              
19             use Getopt::Function qw(maketrue makevalue);
20             $::opthandler = new Getopt::Function
21             [ ], {
22             ] }
23             $result = GetOptions (...option-descriptions...);
24             $::opthandler->std_opts;
25             $::opthandler->check_opts;
26              
27             =head1 DESCRIPTION
28              
29             The B of this module is to make it easy to provide sophisticated and
30             complex interfaces to commands in a simple to use and clear manner
31             with proper help facilities.
32              
33             It is designed to do this by making it possible to write the options,
34             with documentation and subroutines to implement them, directly into a
35             hash and then call the appropriate ones as options detected on the
36             command line.
37              
38             =head2 $gto = new Getopt::Function
39              
40             This constructor takes two arguments. the first is a reference to a
41             list of options names in Getopt::Mixed format (see the documentation
42             for Getopt::Mixed), but with options grouped in strings with their
43             different forms.
44              
45             The second argument is a reference to a hash of option functions and
46             descriptions. Example:-
47              
48             new Getopt::Function
49             [ "red r>red", "green g>green",
50             "bright=s b>bright"] ,
51             { "red" => [ &maketrue,
52             "print using red" ],
53             "green" => [ sub { print STERR "warning: the green isn't very "
54             . "good\n"; &maketrue},
55             "print using green" ],
56             "bright" => [ &makevalue, "set brightness", "INTENSITY" ],
57             }
58              
59              
60             =head1 EXAMPLE
61              
62             This is a basic code example using most features
63              
64              
65             use Getopt::Function qw(maketrue makevalue);
66              
67             use vars qw($not_perfect $redirect $since);
68              
69             $::ignore_missing=0;
70             @::exclude=();
71             @::include=();
72             $::maxno=0;
73              
74             $::opthandler = new Getopt::Function
75             [ "version V>version",
76             "usage h>usage help>usage",
77             "help-opt=s",
78             "verbose:i v>verbose",
79             "exclude=s e>exclude",
80             "include=s i>include",
81             "maxno=i",
82             ],
83             {
84             "exclude" => [ sub { push @::exclude, $::value; },
85             "Add a list of regular expressions for URLs to ignore.",
86             "EXCLUDE RE" ],
87             "include" => [ sub { push @::include, $::value; },
88             "Give regular expression for URLs to check (if this "
89             . "option is given others aren't checked).",
90             "INCLUDE RE" ],
91             "maxno" => [ \&makevalue,
92             "stop after a certain number",
93             "ITERATIONS" ],
94             };
95             $::opthandler->std_opts;
96              
97             $::opthandler->check_opts;
98              
99             sub usage() {
100             print <
101             example [options]
102              
103             EOF
104             $::opthandler->list_opts;
105             print <
106              
107             Show off how we could use uptions
108             EOF
109             }
110              
111             sub version() {
112             print <<'EOF';
113             example version
114             $NOTId: example.pl,v 1.3 1010/10/22 09:10:46 joebloggs Exp $
115             EOF
116             }
117              
118             my @list=biglist(); #get a list of things
119             foreach $item ( @biglist ) {
120             $maxno--;
121             $maxno==0 && last;
122             is_member ($item, @include) or is_member ($item, @exclude) && next;
123             do_big_things @item;
124             }
125              
126             =cut
127              
128             #FIXME we should either get rid of the grouping restriction by
129             #reordering the list ourselves or we should do some basic checking
130             #that the list is validly grouped.
131              
132              
133             sub new {
134 1     1 1 28 my $class=shift;
135 1         3 my $self=bless {}, $class;
136 1         7 my $optlist=shift;
137 1         5 my $opthash=shift;
138 1         15 $self->{"list"}=$optlist;
139 1         4 $self->{"hash"}=$opthash;
140 1         4 return $self;
141             }
142              
143              
144             =head2 $gto->std_opts
145              
146             This adds the standard options provided by the options module its self
147             to the hash. It says nothing about the option list so some of these
148             options may be made inaccessible.
149              
150             To use these you have to provide the usage() and version() functions
151             in the main package. Something like this.
152              
153             sub usage() {
154             print <
155             lists-from-files.pl [options] url-base file-base
156              
157             EOF
158             $::opthandler->list_opts;
159             print <
160              
161             Extract the link and index information from a directory containing
162             HTML files.
163             EOF
164             }
165              
166             sub version() {
167             print <<'EOF';
168             lists-from-files version
169             $Id: Function.pm,v 1.10 2001/08/30 21:31:11 mikedlr Exp $
170             EOF
171             }
172              
173              
174             The standard functions will not override ones you have already provided.
175              
176             =over 4
177              
178             =item usage
179              
180             This just gives the usage information for the program then exits.
181             Normally this should be mapped also to the C<--help> option (and
182             possibly a short option like C<-h> if that's available).
183              
184             =item version
185              
186             This prints the version of the program then exits.
187              
188             =item help-opt
189              
190             This gives the help information for the options which are its
191             parameters.
192              
193             =item verbose
194              
195             This sets the variable C<$::verbose> to the value given as a parameter or
196             C<$Getopt::Function::verbose_default> (default value 4) if no value is given.
197              
198             =item silent
199              
200             This sets the variable silent to be true for hushing normal program
201             output. Standard aliases to create for this would be C<--quiet> and
202             C<-q>.
203              
204             =back
205              
206             =cut
207              
208             $verbose_default=4;
209              
210             my %std_opts = (
211             "usage" => [ sub { main::usage(); exit(); },
212             "Describe usage of this program." ],
213             "version" => [ sub { main::version(); exit(); },
214             "Give version information for this program" ],
215             "help-opt" => [ sub { foreach (split /\s+/, $::value) {
216             $::opt_obj->help_opt($::value);
217             } exit();},
218             "Give help information for a given option",
219             "OPTION" ],
220             "verbose" => [ sub { ($::value eq "") ? ($::verbose=$verbose_default)
221             : ($::verbose=$::value); },
222             "Give information about what the program is doing. " .
223             "Set value to control what information is given.",
224             "VERBOSITY" ],
225             "silent" => [ \&maketrue, "Program should generate no output " .
226             "except in case of error." ],
227             );
228              
229              
230             sub std_opts {
231 1     1 1 6 my $self=shift;
232 1         3 my $opt_hash=$self->{"hash"};
233 1         2 my $key;
234 1         7 foreach $key (keys %std_opts) {
235 5 50       170 $opt_hash->{$key} = $std_opts{$key}
236             unless defined $opt_hash->{$key};
237             }
238             }
239              
240             =head1 maketrue
241              
242             This provides a convenience function which simply sets a variable in
243             the main package true according to the option it is called for. If
244             the option is negative (no-... e.g. no-delete as opposed to delete),
245             it sets the variable false.
246              
247             If the option name contains B<-> then this is substituted for with
248             a B<_>.
249              
250             =cut
251              
252             sub maketrue {
253 0 0   0 0 0 confess '$::option must be defined' unless $::option;
254 0         0 $::option =~ s/-/_/g;
255 0 0       0 if ( $::option =~ m/^no_/ ) {
256 0         0 $::option =~ s/^no_//;
257 0         0 eval "\$::$::option = 0";
258             } else {
259 0         0 eval "\$::$::option = 1";
260             }
261             }
262              
263              
264             =head1 makevalue
265              
266             This provides a convenience function which simply sets a variable in
267             the main package corresponding to the option to a the given value.
268              
269             If the option name contains B<-> then this is substituted for with
270             a B<_>.
271              
272             =cut
273              
274             sub makevalue {
275 2 50   2 0 29 confess '$::option must be defined' unless $::option;
276 2         5 $::option =~ s/-/_/g;
277 2         182 eval "\$::$::option = " . '$::value';
278             }
279              
280              
281             =head2 check_opts
282              
283             Checks all of the options calling the appropriate functions.
284              
285             The following local variables are available to the function in the
286             main package.
287              
288             =over 4
289              
290             =item $::opt_obj
291              
292             The option object. This can be used to call include
293              
294             =item $::option
295              
296             This is the option that was called. The same as the hash key that is
297             used. It is determined through the option list. See above.
298              
299             =item $::value
300              
301             If the option can take a parameter this will contain it. It will be
302             undefined if the parameter wasn't given.
303              
304             =item $::as_entered
305              
306             This will be the option string as entered.
307              
308             =back
309              
310             =cut
311              
312              
313             sub check_opts {
314 0     0 1   my $self=shift;
315 0           my $opt_list=$self->{"list"};
316 0           my $opt_hash=$self->{"hash"};
317 0           Getopt::Mixed::init(@$opt_list);
318              
319 0           local ( $::option, $::value, $::as_entered, $::opt_obj);
320 0           $::opt_obj=$self;
321 0           while (($::option, $::value, $::as_entered) = nextOption()) {
322 0           &{$opt_hash->{$::option}[0]};
  0            
323             }
324             }
325              
326             =head2 opt_usage
327              
328             This is really an internal function and is used to implement list_opts
329             and help_opt. Given a string from the options list, this prints out
330             the the options listed in the string and their docuentation in a neat
331             format.
332              
333             =cut
334              
335             sub opt_usage ($$) {
336 0     0 1   my $self=shift;
337 0           $_=shift;
338 0           my $opt_hash=$self->{"hash"};
339              
340 0           s/(\S+)\s+(.+)/$2 $1/; #move key option to last
341 0           my $optname;
342             my $olen;
343 0           my $ostr = " ";
344 0 0         m/^\s*[-A-Za-z]{2,}\S*\s*$/ and $ostr = $ostr . " ";
345 0           OPTION: foreach ( split /\s+/, $_ ) { #FIXME will split ever work?
346 0           my ($opt, $meaning, $control ) =
347             m{^ ([-A-Za-z]+) (?: ([>:=]) ([-A-Za-z]+) )? $ }x ;
348 0 0         die "badly formed option string `$_'" unless $opt ;
349 0 0         $ostr = $ostr . '-' unless length $opt == 1;
350 0           $ostr = $ostr . '-' . $opt;
351 0 0         unless ($meaning) { $optname=$opt; next OPTION; }
  0            
  0            
352 0 0         $meaning =~ m/>/ and next OPTION;
353 0           $optname=$opt;
354 0 0         $meaning =~ m/:/ && do { #optional value
355 0           $ostr = $ostr . '[';
356 0 0         $ostr = $ostr . '=' unless length $opt == 1;
357 0           $ostr = $ostr . $opt_hash->{$opt}[2] . ']';
358             };
359 0 0         $meaning =~ m/=/ && do { #mandatory value
360 0 0         $ostr = $ostr . '=' unless length $opt == 1;
361 0           $ostr = $ostr . $opt_hash->{$opt}->[2];
362             };
363             } continue { #print each form of option
364 0           $ostr = $ostr . " ";
365             }
366 0 0         die "malformed option" unless defined $optname;
367              
368 0           print $ostr;
369 0           my $width=80;
370 0           my $opt_indent=25;
371 0           my $line_len=$width - $opt_indent;
372 0 0         if ((length $ostr) < $opt_indent) {
373 0           print " " x ($opt_indent - (length $ostr) );
374             }
375              
376 0           $_ = $opt_hash->{$optname}[1];
377 0 0         if (length $ostr > $opt_indent) {
378             #FIXME what about too short lines.. it's programmers
379             #responsibility, but we should be reasonably okay.
380 0           my $left=$width - length $ostr;
381 0           (my $firstline,$_) = m[(
382             (?:(?:.{1,$left})(?=\Z|\n)) # a line ended by a newline
383             | #or
384             (?:(?:.{1,$left})(?=\s)) # a line broken at a space
385             | #or
386             (?:[\S]{$left}) # too long.. break anyway
387             ) (.*) #the rest.
388             ]xg;
389 0           print $firstline, "\n";
390 0 0         return unless $_;
391 0           print " " x $opt_indent;
392             }
393 0 0         Carp::croak( "no help information for option $optname" ) unless $_;
394 0           my @lines = m[\s*
395             (
396             (?:(?:.{1,$line_len})(?=\Z|\n)) # a line ended by a newline or EOS
397             | #or
398             (?:(?:.{1,$line_len})(?=\s)) # a line broken at a space
399             | #or
400             (?:[\S]{$line_len}) # too long.. break anyway
401             )
402             ]xg;
403 0           my $first=shift @lines;
404 0           print STDOUT $first, "\n";
405 0           foreach (@lines) {
406 0           print " " x $opt_indent, $_, "\n";
407             }
408             }
409              
410              
411             =head2 list_opts
412              
413             This function prints out the usage information for all of the options.
414              
415             =cut
416              
417             sub list_opts ($) {
418 0     0 1   my $self=shift;
419 0           my $opt_list=$self->{"list"};
420 0           my $opt_hash=$self->{"hash"};
421 0           OPTSTRING: foreach (@$opt_list) {
422 0 0         m/^$/ && do { print "\n"; next OPTSTRING};
  0            
  0            
423 0           $self->opt_usage($_);
424             } #loop over the strings
425             }
426              
427              
428             =head2 help_opt
429              
430             This function searches through the array of options until it gets one
431             which matches then prints out its documentation.
432              
433             If the help option is a single character then we only print out a
434             single character option which matches exactly. Otherwise we print the
435             first long option who's start matches. This doesn't guarantee that we
436             unambiguously have chosen that option, but could be useful where
437             someone has forgotten part of the option name...
438              
439             =cut
440              
441             sub help_opt ($$) {
442 0     0 1   my $self=shift;
443 0           my $opt_list=$self->{"list"};
444 0           my $opt_hash=$self->{"hash"};
445 0           my $option = shift;
446 0 0         $option =~ m/^-/ && die "for option help please give the option without '-'s";
447 0           my $found=0;
448 0 0         if ((length $option) == 1) {
449 0           foreach (@{$opt_list}) {
  0            
450 0 0         m/(^|\s)$option([>:=]|$)/ && do { $self->opt_usage($_); $found++};
  0            
  0            
451             }
452             } else {
453 0           foreach (@{$opt_list}) {
  0            
454 0           my @call_list = ($_);
455 0 0         m/(^|\s)$option/ && do { $self->opt_usage($_); $found++};
  0            
  0            
456             }
457             }
458 0 0         die "Couldn't find a matching option for $option" unless $found;
459             }
460              
461             =head1 BUGS
462              
463             There is no scheme for automatic way to do negation. The workaround
464             is to define the negative and positive options. This should be fixed.
465              
466             =cut
467              
468             1;
469