File Coverage

blib/lib/Getopt/Base.pm
Criterion Covered Total %
statement 244 268 91.0
branch 110 166 66.2
condition 20 34 58.8
subroutine 22 25 88.0
pod 13 13 100.0
total 409 506 80.8


line stmt bran cond sub pod time code
1             package Getopt::Base;
2             $VERSION = v0.0.3;
3              
4 2     2   22725 use warnings;
  2         4  
  2         62  
5 2     2   9 use strict;
  2         4  
  2         105  
6 2     2   22 use Carp;
  2         3  
  2         6973  
7              
8             =head1 NAME
9              
10             Getopt::Base - foundation for oo GetOpt support
11              
12             =head1 SYNOPSIS
13              
14             package Getopt::YAWTDI;
15              
16             use base 'Getopt::Base';
17             ...
18              
19             sub main {
20             my $opt = Getopt::YAWTDI->new(%setup)->process(\@args) or return;
21              
22             my $foo = $opt->foo;
23             ...
24             }
25              
26             =head1 ABOUT
27              
28             This module provides a foundation on which to build numerous forms of
29             Getopt:: support, but does not supply any particular frontend.
30              
31             =head1 ALPHA
32              
33             This module is still growing. Your help with documentation and API
34             suggestions are welcome.
35              
36             =head1 Features
37              
38             Modules built on this foundation will have the following features:
39              
40             =over
41              
42             =item object-based output
43              
44             The get() method returns an object with accessors. You may supply your
45             own object.
46              
47             =item loadable modes
48              
49             A program (such as svn, svk, git) with multiple modes may cleanly load
50             an additional set of options during @args processing.
51              
52             =item long/short options, types, &c
53              
54             Options are of the --long-form or the '-s' (short form). Short options
55             may be bundled (opterand must follow the bundle.) Long options can be
56             give in one or two-word form (e.g. '--opt=foo' or '--opt foo'.) Options
57             may be 'typed' as boolean/string/integer/float and and be of the single
58             or multi-element array/hash form. All boolean-type options
59             automatically support the '--no-foo' negated form.
60              
61             =item ordered callbacks
62              
63             Items in C will be triggered in as-defined order before any of
64             the items in C are processed. This allows for e.g. loading
65             config files or printing help/version messages.
66              
67             =item cleanly callable
68              
69             It should not be necessary for any callbacks to exit(). If one of them
70             called stop(), then get() returns false and the caller should do the
71             same. Errors will throw an error with croak().
72              
73             =back
74              
75             =cut
76              
77             =head1 Constructor
78              
79             =head2 new
80              
81             my $go = Getopt::Base->new(%setup);
82              
83             =cut
84              
85             sub new {
86 18     18 1 4200 my $package = shift;
87 18   33     278 my $class = ref($package) || $package;
88 18         90 my $self = {
89             opt_data => {},
90             short => {},
91             aliases => {},
92             positional => [],
93             };
94 18         49 bless($self, $class);
95 18         53 $self->_prepare(@_);
96 12         37 return($self);
97             } # end subroutine new definition
98             ########################################################################
99              
100             =head2 _prepare
101              
102             $self->_prepare(%params);
103              
104             =cut
105              
106             sub _prepare {
107 18     18   30 my $self = shift;
108 18         48 my %params = @_;
109              
110 18   100     67 my $options = $params{options} || [];
111 18 50       54 (@$options % 2) and croak("odd number of elements in 'options'");
112 18         59 for(my $i = 0; $i < @$options; $i+=2) {
113 18         27 $self->add_option($options->[$i], %{$options->[$i+1]});
  18         85  
114             }
115              
116 15 100       47 if(my $pos = $params{positional}) {
117 7         23 $self->add_positionals(@$pos);
118             }
119              
120 12         33 foreach my $key (qw(arg_handler)) {
121 12 50       64 $self->{$key} = $params{$key} if(exists($params{$key}));
122             }
123              
124             } # end subroutine _prepare definition
125             ########################################################################
126              
127             =head1 Methods
128              
129             =head2 process
130              
131             Process the @argv, removing options and opterands in-place.
132              
133             my $obj = $go->process(\@argv) or return;
134              
135             The storage object may also be passed explicitly.
136              
137             $obj = $go->process(\@argv, object => $obj) or return;
138              
139             =cut
140              
141             sub process {
142 37     37 1 982 my $self = shift;
143 37         101 my $args = shift;
144 37 50       113 (@_ % 2) and croak('odd number of arguments');
145 37         71 my %also = @_;
146              
147 37         89 local $self->{stopped} = 0; # loop control
148 37         79 my $keep = local $self->{tokeep} = [];
149 37         89 my $toset = local $self->{toset} = [];
150              
151 37   33     157 my $o = local $self->{object} = $also{object} || $self->object;
152              
153 37         95 while(@$args) {
154 60 50       137 last if($self->{stopped});
155 60         88 my $arg = shift(@$args);
156              
157 60 100       798 last if($arg eq '--');
158              
159 57         220 my ($dash) = $arg =~ m/^(-*)/;
160              
161 57 100       158 if($dash eq '') { $self->process_arg($arg); }
  23 100       57  
    50          
162             elsif($dash eq '--') {
163 28 100       100 if($arg =~ s/=(.*)//) { unshift(@$args, $1); }
  2         8  
164 28         75 $self->process_option($self->_find_option($arg), $args);
165             }
166             elsif($dash eq '-') {
167 6         21 my @got = $self->_unbundle($arg);
168 6         9 my $last = pop(@got);
169 6         14 $self->process_option($_) for(@got);
170 6         19 $self->process_option($last, $args);
171             }
172 0         0 else { croak("oops: $arg") }
173             }
174 37         84 @$args = (@$keep, @$args);
175 37 50       113 return() if($self->{stopped} < 0);
176              
177 37         76 my %is_set = map({$_->[0]->{name} => 1} @$toset);
  34         141  
178              
179             # always call hooked options with defined defaults
180             # (or else need to define a setting for this)
181 37 50       60 foreach my $d (
  50         188  
182 37         89 grep {$_->{call} and $_->{default}} values %{$self->{opt_data}}
183             ) {
184 0 0       0 next if $is_set{$d->{name}};
185 0         0 my $def = $d->{default};
186 0 0 0     0 $def = (ref($def) || '') eq 'CODE' ? $def->() : $def;
187 0         0 $self->store($d, $def);
188 0         0 $d->{call}->($self, $def);
189             }
190              
191             # store all other inputs
192 37         156 $self->store(@$_) for(@$toset);
193              
194             # evaluate positionals
195 36 100       96 if(@$args) {
196             # TODO this needs better logic for e.g. qw(list scalar scalar)
197 19         20 foreach my $k (@{$self->{positional}}) {
  19         51  
198 17 100 66     263 if(! $is_set{$k} or $self->{opt_data}{$k}{form}) {
199 6         18 $self->store($k, shift(@$args));
200             }
201 17 100       53 @$args or last; # TODO check requiredness?
202             }
203             }
204              
205             # pickup any lazy defaults at this point
206 36 100       265 if(my $def = $self->{_defaults}) {
207 2         5 foreach my $do (@$def) {
208 2         4 my ($k, $sub) = @$do;
209 2 50       8 next if(exists $o->{$k});
210 2 50       7 if(my $isa = $self->{opt_data}{$k}{isa}) {
211 2         104 eval("require $isa");
212 2 50       331 $@ and croak("ack: $@");
213             }
214 2         8 $self->store($k, $sub->());
215             }
216             }
217              
218 36         207 return($o);
219             } # end subroutine process definition
220             ########################################################################
221              
222             =head1 Controlling process()
223              
224             =head2 stop
225              
226             Stops the option processing when called from an action handler. Always
227             returns false.
228              
229             $go->stop;
230              
231             This is used for some forms of two-stage processing, where an action or
232             argument indicates that all of the remaining inputs are to be handled
233             elsewhere.
234              
235             =head2 quit
236              
237             Stops the option processing and prevents process() from returning an object . Always returns false.
238              
239             $go->quit;
240              
241             This is used for options like C<--version> and C<--help>, where you have
242             a terminal action.
243              
244             =cut
245              
246 0     0 1 0 sub stop { shift->{stopped} = 1; return(); }
  0         0  
247 0     0 1 0 sub quit { shift->{stopped} = -1; return(); }
  0         0  
248             ########################################################################
249              
250             =head1 Handling Inputs
251              
252             =head2 process_option
253              
254             $self->process_option($name, \@argv);
255              
256             =cut
257              
258             sub process_option {
259 34     34 1 52 my $self = shift;
260 34         50 my ($name, $argv) = @_;
261 34   50     70 $argv ||= [];
262              
263 34 50       93 my $toset = $self->{toset} or croak("out of context");
264              
265 34 50       108 my $d = ref($name) ? $name : $self->{opt_data}{$name} or
    50          
266             croak("invalid: $name");
267 34         58 $name = $d->{name};
268              
269 34         39 my $v;
270 34 100       83 if($d->{type} eq 'boolean') {
271 13 100       34 $v = $d->{opposes} ? 0 : 1;
272             }
273             else {
274 21 50       43 @$argv or croak("option '$d->{name}' requires a value");
275 21         36 $v = shift(@$argv);
276             }
277              
278 34 50       78 if(my $sub = $d->{call}) {
279             # TODO should we try to set a value?
280             # TODO this should probably also be in the store() routine?
281 0         0 my $check = $self->_checker($name);
282 0         0 push(@$toset, [$d, $v]);
283 0         0 return $sub->($self, $check->($v));
284             }
285             else {
286 34 100 100     186 if(($d->{form}||'') eq 'HASH') {
287 3         17 my @pair = split(/=/, $v, 2);
288 3 50       8 croak("hash options require 'key=value' form (not '$v')")
289             unless(@pair == 2);
290 3         19 push(@$toset, [$d, @pair]);
291             }
292             else {
293 31         176 push(@$toset, [$d, $v]);
294             }
295             }
296             } # end subroutine process_option definition
297             ########################################################################
298              
299             =head2 process_arg
300              
301             $self->process_arg($arg);
302              
303             =cut
304              
305             sub process_arg {
306 23     23 1 28 my $self = shift;
307 23         28 my ($arg) = @_;
308              
309 23 50       57 my $keep = $self->{tokeep} or croak("out of context");
310              
311             # check for mode
312 23 50       50 if(my $do = $self->{arg_handler}) {
313             # XXX what's the API for this? Return vs stop and so on.
314 0 0       0 $do->($self, $arg) or return;
315             }
316              
317 23         84 push(@$keep, $arg);
318             } # end subroutine process_arg definition
319             ########################################################################
320              
321             =head1 Setup
322              
323             =head2 add_option
324              
325             Add an option.
326              
327             $go->add_option(name => %settings);
328              
329             =cut
330              
331             sub add_option {
332 22     22 1 43 my $self = shift;
333 22         31 my $name = shift;
334 22 50       54 (@_ % 2) and croak("odd number of arguments");
335 22         306 my %s = @_;
336              
337 22 100       224 croak("options cannot contain dashes ('$name')") if($name =~ m/-/);
338 21 100       46 unless($s{form}) {
339 20         37 my $ref = ref($s{default});
340 20 100 100     76 $s{form} = $ref if($ref and $ref ne 'CODE');
341             }
342             else {
343 1         5 $s{form} = uc($s{form});
344             }
345              
346 21 100       53 unless($s{type}) {
347 6 100       21 $s{type} = $s{form} ? 'string' : 'boolean';
348             }
349              
350 21 50       51 if(my $callback = $s{call}) {
351 0 0 0     0 croak("not a code reference") unless(ref($callback) ||'' eq 'CODE');
352             }
353              
354 21         33 $s{name} = $name; # XXX I guess
355              
356 21 50       51 if($self->{opt_data}{$name}) {
357             # warn "$name already defined\n";
358             # TODO no big deal?
359 0 0       0 croak("option '$name' already defined") unless($name =~ m/^no_/);
360             }
361             else {
362 21         67 $self->{opt_data}{$name} = \%s;
363             }
364              
365 21 100       63 if($s{type} eq 'boolean') {
366 6         39 $self->{opt_data}{"no_$name"} = {%s, opposes => $name};
367             }
368              
369 21 100       60 $self->add_aliases($name => $s{short}, @{$s{aliases} || []});
  21         135  
370              
371             } # end subroutine add_option definition
372             ########################################################################
373              
374             # TODO this is only sugar then?
375             # =head2 add_action
376             #
377             # $go->add_action(name => sub {...}, %settings);
378             #
379             # =cut
380             #
381             # sub add_action {
382             # my $self = shift;
383             # my ($name, $callback, @and) = @_;
384             #
385             # $self->add_option($name, @and, call => $callback);
386             # } # end subroutine add_action definition
387             # ########################################################################
388              
389             =head2 add_positionals
390              
391             $go->add_positionals(@list);
392              
393             =cut
394              
395             sub add_positionals {
396 7     7 1 11 my $self = shift;
397 7         15 my (@list) = @_;
398              
399 7         15 foreach my $item (@list) {
400 8 100       599 my $d = $self->{opt_data}{$item} or
401             croak("positional '$item' is not an option");
402 6 100       157 croak("positional '$item' cannot be a boolean")
403             if($d->{type} eq 'boolean');
404 5         5 push(@{$self->{positional}}, $item);
  5         18  
405             }
406             } # end subroutine add_positionals definition
407             ########################################################################
408              
409             =head2 add_aliases
410              
411             $go->add_aliases($canonical => \@short, @list);
412              
413             =cut
414              
415             sub add_aliases {
416 22     22 1 36 my $self = shift;
417 22         63 my ($canon, $short, @and) = @_;
418              
419 22 100       46 if(defined($short)) {
420 6         15 my $st = $self->{short};
421 6 50       18 ref($short) or croak("'shortlist' argument must be an array ref");
422 6         12 foreach my $item (@$short) {
423 9 100       194 croak("short options must be only one character ('$item')")
424             if(length($item) != 1);
425 8 50       21 croak("short option '$item' is already linked to '$st->{$item}'")
426             if(exists($st->{$item}));
427 8         27 $st->{$item} = $canon;
428             }
429             }
430              
431 21         33 my $at = $self->{aliases};
432 21         106 foreach my $item (@and) {
433 5 100       187 croak("aliases cannot contain dashes ('$item')") if($item =~ m/-/);
434 4 50       9 croak("alias '$item' is already linked to '$at->{$item}'")
435             if(exists($at->{$item}));
436 4         16 $at->{$item} = $canon;
437             }
438            
439             } # end subroutine add_aliases definition
440             ########################################################################
441              
442             =head2 store
443              
444             $go->store(key => $value, $value2, ...);
445              
446             =cut
447              
448             sub store {
449 42     42 1 74 my $self = shift;
450 42         261 my ($k, @v) = @_;
451              
452 42 50       145 my $o = $self->{object} or croak("out of context");
453 42 100       131 my $d = ref($k) ? $k : $self->{opt_data}{$k} or
    50          
454             croak("no such option: $k");
455 42         66 $k = $d->{name};
456              
457 42         100 my $check = $self->_checker($k);
458              
459 41 100       277 if(my $form = $d->{form}) {
460 8 100       20 if($form eq 'HASH') {
461 3   50     11 $o->{$k} ||= {};
462 3 50       9 (@v % 2) and croak("odd number of values to store for '$k'");
463 3         10 while(@v) {
464 3         7 my $key = shift(@v); my $val = shift(@v);
  3         5  
465 3         90 $o->{$k}{$key} = $check->($val);
466             }
467             }
468             else {
469 5         6 push(@{$o->{$k}}, map({$check->($_)} @v));
  5         14  
  5         150  
470             }
471             }
472             else {
473 33         1143 $o->{$k} = $check->($v[0]);
474             }
475             } # end subroutine store definition
476             ########################################################################
477              
478             =head2 _checker
479              
480             Builds a check subref for the given $name.
481              
482             my $subref = $self->_checker($name);
483              
484             =cut
485              
486             sub _checker {
487 58     58   69 my $self = shift;
488 58         82 my ($item) = @_;
489              
490 58 50       156 my $d = $self->{opt_data}{$item} or die("nothing for $item");
491              
492 58         70 my $checkcode = '';
493 58 100       127 if(my $isa = $d->{isa}) {
494 5         375 eval("require $isa");
495 5 100       2937 $@ and croak("ack: $@");
496 4         18 $checkcode .= '$val = ' . "$isa" . '->new($val) ' .
497             " unless(eval {\$val->isa('$isa')});";
498             }
499 57 50       449 if(my $type = $d->{type}) {
500             # TODO check integer/number-ness
501             }
502 57         5242 my $check = eval("sub {
503             my \$val = shift;
504             $checkcode
505             return(\$val);
506             }");
507 57 50       156 $@ and die "ouch $@";
508              
509 57         139 return($check);
510             } # _checker ###########################################################
511              
512             =head2 set_values
513              
514             $go->set_values(%hash);
515              
516             =cut
517              
518             sub set_values {
519 0     0 1 0 my $self = shift;
520 0         0 my %hash = @_;
521              
522 0         0 foreach my $k (keys %hash) {
523             # XXX I need to think about whether this has exceptional cases
524 0         0 my $v = $hash{$k};
525 0         0 my $ref = ref($v);
526 0 0       0 $self->store($k, $ref
    0          
    0          
527             ? $ref eq 'HASH'
528             ? %$v
529             : $ref eq 'ARRAY'
530             ? @$v
531             : $v
532             : $v);
533             }
534             } # end subroutine set_values definition
535             ########################################################################
536              
537             =head2 object
538              
539             Default/current result-storage object. Subclasses may wish to
540             override this.
541              
542             my $obj = $go->object;
543              
544             =cut
545              
546             sub object {
547 37     37 1 52 my $self = shift;
548 37 50       99 return $self->{object} if($self->{object});
549              
550 37         80 return $self->make_object;
551             } # end subroutine object definition
552             ########################################################################
553              
554             =head2 make_object
555              
556             Constructs an empty (with defaults) data object from the set options.
557              
558             my $obj = $self->make_object;
559              
560             =cut
561              
562             sub make_object {
563 37     37 1 47 my $self = shift;
564 37         125 my $obj = Getopt::Base::Accessors->new($self->{opt_data});
565             # XXX should find a nicer way to pass these around
566 37         549 $self->{_defaults} = delete $obj->{__defaults};
567              
568             # XXX ugly, but we need to honor isa on default values
569 37         124 foreach my $k (keys %$obj) {
570 16         46 my $checker = $self->_checker($k);
571 16         436 $obj->{$k} = $checker->($obj->{$k});
572             }
573              
574 37         205 return $obj;
575             } # make_object ########################################################
576              
577              
578             =head2 _find_option
579              
580             Fetches the option data for the canonical match (de-aliased) of $opt.
581              
582             my $d = $self->_find_option($opt);
583              
584             =cut
585              
586             sub _find_option {
587 28     28   38 my $self = shift;
588 28         38 my ($opt) = @_;
589              
590 28         77 my $key = $opt;
591 28         5318 $key =~ s/^--//; $key =~ s/-/_/g;
  28         64  
592              
593             # exact match
594 28 100       103 if(my $d = $self->{opt_data}{$key}) { return($d); }
  17         69  
595              
596 40         321 my @hit = grep({$_ =~ m/^$key/}
  11         30  
597 11         26 keys %{$self->{aliases}},
598 11         16 keys %{$self->{opt_data}}
599             );
600 11 50       35 croak("option '$opt' is invalid") unless(@hit);
601 11 50       27 croak("option '$opt' is not long enough to be unique") if(@hit > 1);
602              
603 11   66     45 my $canon = $self->{aliases}{$hit[0]} || $hit[0];
604 11 50       34 my $d = $self->{opt_data}{$canon} or
605             croak("alias '$hit[0]' has no canonical form ($canon)");
606              
607 11         41 return($d);
608             } # end subroutine _find_option definition
609             ########################################################################
610              
611             =head2 _unbundle
612              
613             my @d = $self->_unbundle($blah);
614              
615             =cut
616              
617             sub _unbundle {
618 6     6   10 my $self = shift;
619 6         8 my $bun = shift;
620 6         25 $bun =~ s/^-//;
621              
622 6         8 my @d;
623 6         21 foreach my $c (split(//, $bun)) {
624 6 50       24 my $canon = $self->{short}{$c} or
625             croak("short option '$c' is not defined");
626 6 50       22 my $data = $self->{opt_data}{$canon} or
627             croak("short option '$c' points to non-existent '$canon'");
628 6         17 push(@d, $data);
629             }
630              
631 6         19 foreach my $i (0..($#d-1)) {
632 0 0       0 croak("option '$d[$i]->{name}' is not a bundle-able flag")
633             unless($d[$i]->{type} eq 'boolean');
634             }
635 6         19 return(@d);
636             } # end subroutine _unbundle definition
637             ########################################################################
638              
639             {
640             package Getopt::Base::Accessors;
641              
642             =head1 Accessor Class
643              
644             This is the default object for holding results. It will contain
645             accessors for all of the defined options.
646              
647             =head2 new
648              
649             my $o = Getopt::Base::Accessors->new($opt_data);
650              
651             =cut
652              
653             sub new {
654 37     37   48 my $class = shift;
655 37         40 my $opt_data = shift;
656              
657 37         54 my $self = {};
658              
659 37         698 $class .= "::$self";
660              
661 37         216 bless($self, $class);
662              
663 37         126 foreach my $k (keys %$opt_data) {
664             # warn "$k\n";
665 50         77 my $o = $opt_data->{$k};
666 50 100 50     299 next if(($o->{type} ||'' eq 'boolean') and $o->{opposes});
      66        
667 38         55 my $sub;
668 38 100       97 if(my $r = $o->{form}) {
669             # warn "form for $k : $r";
670 3         5 my $def = $o->{default};
671 3 100       10 if($r eq 'HASH') {
    50          
672 1 50       4 $self->{$k} = {$def ? %$def : ()};
673 1         107 $sub = eval("sub {\%{shift->{$k}}}");
674             }
675             elsif($r eq 'ARRAY') {
676 2 100       20 $self->{$k} = [$def ? @$def : ()];
677 2         138 $sub = eval("sub {\@{shift->{$k}}}");
678             }
679             else {
680 0         0 Carp::croak("unknown ref type '$r'");
681             }
682             }
683             else {
684 35         2969 $sub = eval("sub {shift->{$k}}");
685 35 100       117 if(exists $o->{default}) {
686 15         32 my $def = $o->{default};
687 15 100 100     77 if((ref($def)||'') eq 'CODE') {
688             # lazy
689 2         2 push(@{$self->{__defaults}}, [$k, $def]);
  2         11  
690             }
691             else {
692 13         36 $self->{$k} = $def
693             }
694             }
695             }
696             {
697 2     2   16 no strict 'refs';
  2         4  
  2         217  
  38         37  
698 38         45 *{$class . '::' . $k} = $sub;
  38         299  
699             }
700             }
701             # and we need to cleanup this object class
702             my $destroy = sub {
703 2     2   9 my $st = do { no strict 'refs'; \%{$class . '::'}};
  2     37   4  
  2         257  
  37         22676  
  37         53  
  37         205  
704 37         536 delete($st->{$_}) for(keys %$st);
705 37         326 return;
706 37         150 };
707 2     2   9 { no strict 'refs'; *{$class . '::' . 'DESTROY'} = $destroy; }
  2         4  
  2         208  
  37         57  
  37         44  
  37         199  
708              
709 37         82 return $self;
710             } # end subroutine new definition
711             ########################################################################
712              
713             };
714              
715              
716             =head1 AUTHOR
717              
718             Eric Wilhelm @
719              
720             http://scratchcomputing.com/
721              
722             =head1 BUGS
723              
724             If you found this module on CPAN, please report any bugs or feature
725             requests through the web interface at L. I will be
726             notified, and then you'll automatically be notified of progress on your
727             bug as I make changes.
728              
729             If you pulled this development version from my /svn/, please contact me
730             directly.
731              
732             =head1 COPYRIGHT
733              
734             Copyright (C) 2009 Eric L. Wilhelm, All Rights Reserved.
735              
736             =head1 NO WARRANTY
737              
738             Absolutely, positively NO WARRANTY, neither express or implied, is
739             offered with this software. You use this software at your own risk. In
740             case of loss, no person or entity owes you anything whatsoever. You
741             have been warned.
742              
743             =head1 LICENSE
744              
745             This program is free software; you can redistribute it and/or modify it
746             under the same terms as Perl itself.
747              
748             =cut
749              
750             # vi:ts=2:sw=2:et:sta
751             1;