File Coverage

blib/lib/OptArgs.pm
Criterion Covered Total %
statement 331 349 94.8
branch 153 194 78.8
condition 58 82 70.7
subroutine 20 21 95.2
pod 7 7 100.0
total 569 653 87.1


line stmt bran cond sub pod time code
1             package OptArgs;
2 11     11   235153 use strict;
  11         27  
  11         299  
3 11     11   59 use warnings;
  11         22  
  11         329  
4 11     11   60 use Carp qw/croak carp/;
  11         27  
  11         653  
5 11     11   9504 use Encode qw/decode/;
  11         119251  
  11         950  
6             use Exporter::Tidy
7 11         87 default => [qw/opt arg optargs usage subcmd/],
8 11     11   15558 other => [qw/dispatch class_optargs/];
  11         122  
9 11     11   13674 use Getopt::Long qw/GetOptionsFromArray/;
  11         167399  
  11         72  
10 11     11   2143 use List::Util qw/max/;
  11         22  
  11         56168  
11              
12             our $VERSION = '0.1.17_1';
13             our $COLOUR = 0;
14             our $ABBREV = 0;
15             our $SORT = 0;
16              
17             my %seen; # hash of hashes keyed by 'caller', then opt/arg name
18             my %opts; # option configuration keyed by 'caller'
19             my %args; # argument configuration keyed by 'caller'
20             my %caller; # current 'caller' keyed by real caller
21             my %desc; # sub-command descriptions
22             my %dispatching; # track optargs() calls from dispatch classes
23             my %hidden; # subcmd hiding by default
24              
25             # internal function for App::optargs
26             sub _cmdlist {
27 4     4   15 return sort grep { $_ ne 'App::optargs' } keys %seen;
  36         84  
28             }
29              
30             # ------------------------------------------------------------------------
31             # Sub-command definition
32             #
33             # This works by faking caller context in opt() and arg()
34             # ------------------------------------------------------------------------
35             my %subcmd_params = (
36             cmd => undef,
37             comment => undef,
38             hidden => undef,
39              
40             # alias => '',
41             # ishelp => undef,
42             );
43              
44             my @subcmd_required = (qw/cmd comment/);
45              
46             sub subcmd {
47 18     18 1 1806 my $params = {@_};
48 18         33 my $caller = caller;
49              
50 18 100       35 if ( my @missing = grep { !exists $params->{$_} } @subcmd_required ) {
  36         118  
51 1         202 croak "missing required parameter(s): @missing";
52             }
53              
54 17 50       49 if ( my @invalid = grep { !exists $subcmd_params{$_} } keys %$params ) {
  36         103  
55 0         0 my @valid = keys %subcmd_params;
56 0         0 croak "invalid parameter(s): @invalid (valid: @valid)";
57             }
58              
59             # croak "'ishelp' can only be applied to Bool opts"
60             # if $params->{ishelp} and $params->{isa} ne 'Bool';
61              
62             my @cmd =
63             ref $params->{cmd} eq 'ARRAY'
64 10         24 ? @{ $params->{cmd} }
65 17 100       66 : ( $params->{cmd} );
66 17 50       60 croak 'missing cmd elements' unless @cmd;
67              
68 17         31 my $name = pop @cmd;
69 17         43 my $parent = join( '::', $caller, @cmd );
70 17         27 $parent =~ s/-/_/g;
71              
72 17 100       209 croak "parent command not found: @cmd" unless $seen{$parent};
73              
74 16         38 my $package = $parent . '::' . $name;
75 16         22 $package =~ s/-/_/g;
76              
77 16 100       199 croak "sub command already defined: @cmd $name" if $seen{$package};
78              
79 15         25 $caller{$caller} = $package;
80 15         38 $desc{$package} = $params->{comment};
81 15         34 $seen{$package} = {};
82 15         31 $opts{$package} = [];
83 15         28 $args{$package} = [];
84 15         29 $hidden{$package} = $params->{hidden};
85              
86 15         20 my $parent_arg = ( grep { $_->{isa} eq 'SubCmd' } @{ $args{$parent} } )[0];
  16         48  
  15         35  
87 15         21 push( @{ $parent_arg->{subcommands} }, $name );
  15         35  
88              
89 15         51 return;
90             }
91              
92             # ------------------------------------------------------------------------
93             # Option definition
94             # ------------------------------------------------------------------------
95             my %opt_params = (
96             isa => undef,
97             comment => undef,
98             default => undef,
99             alias => '',
100             ishelp => undef,
101             hidden => undef,
102             );
103              
104             my @opt_required = (qw/isa comment/);
105              
106             my %opt_isa = (
107             'Bool' => '!',
108             'Counter' => '+',
109             'Str' => '=s',
110             'Int' => '=i',
111             'Num' => '=f',
112             'ArrayRef' => '=s@',
113             'HashRef' => '=s%',
114             );
115              
116             sub opt {
117 43     43 1 7301 my $name = shift;
118 43         155 my $params = {@_};
119 43         81 my $caller = caller;
120 43   66     187 my $package = $caller{$caller} || $caller;
121              
122 43 100       563 croak 'usage: opt $name => (%parameters)' unless $name;
123 39 100       428 croak "'$name' already defined" if $seen{$package}->{$name};
124              
125 37 100       68 if ( my @missing = grep { !exists $params->{$_} } @opt_required ) {
  74         350  
126 2         273 croak "missing required parameter(s): @missing";
127             }
128              
129 35 100       161 if ( my @invalid = grep { !exists $opt_params{$_} } keys %$params ) {
  91         252  
130 1         6 my @valid = keys %opt_params;
131 1         176 croak "invalid parameter(s): @invalid (valid: @valid)";
132             }
133              
134             croak "'ishelp' can only be applied to Bool opts"
135 34 100 100     331 if $params->{ishelp} and $params->{isa} ne 'Bool';
136              
137             croak "unknown type: $params->{isa}"
138 33 100       312 unless exists $opt_isa{ $params->{isa} };
139              
140 32         182 $params = { %opt_params, %$params };
141 32         102 $params->{package} = $package;
142 32         79 $params->{name} = $name;
143 32         62 $params->{length} = length $name;
144 32         44 $params->{acount} = do { my @tmp = split( '|', $params->{alias} ) };
  32         111  
145 32         60 $params->{type} = 'opt';
146 32         61 $params->{ISA} = $params->{name};
147              
148 32 100       208 if ( ( my $dashed = $params->{name} ) =~ s/_/-/g ) {
149 3         8 $params->{dashed} = $dashed;
150 3         14 $params->{ISA} .= '|' . $dashed;
151             }
152              
153 32 100       94 $params->{ISA} .= '|' . $params->{alias} if $params->{alias};
154 32         81 $params->{ISA} .= $opt_isa{ $params->{isa} };
155              
156 32         47 push( @{ $opts{$package} }, $params );
  32         80  
157 32   100     115 $args{$package} ||= [];
158 32         80 $seen{$package}->{$name}++;
159              
160 32         83 return;
161             }
162              
163             # ------------------------------------------------------------------------
164             # Argument definition
165             # ------------------------------------------------------------------------
166             my %arg_params = (
167             isa => undef,
168             comment => undef,
169             required => undef,
170             default => undef,
171             greedy => undef,
172             fallback => undef,
173             );
174              
175             my @arg_required = (qw/isa comment/);
176              
177             my %arg_isa = (
178             'Str' => '=s',
179             'Int' => '=i',
180             'Num' => '=f',
181             'ArrayRef' => '=s@',
182             'HashRef' => '=s%',
183             'SubCmd' => '=s',
184             );
185              
186             sub arg {
187 32     32 1 9336 my $name = shift;
188 32         112 my $params = {@_};
189 32         67 my $caller = caller;
190 32   66     161 my $package = $caller{$caller} || $caller;
191              
192 32 100       547 croak 'usage: arg $name => (%parameters)' unless $name;
193 28 100       444 croak "'$name' already defined" if $seen{$package}->{$name};
194              
195 26 100       50 if ( my @missing = grep { !exists $params->{$_} } @arg_required ) {
  52         206  
196 2         270 croak "missing required parameter(s): @missing";
197             }
198              
199 24 100       82 if ( my @invalid = grep { !exists $arg_params{$_} } keys %$params ) {
  65         193  
200 1         7 my @valid = keys %arg_params;
201 1         172 croak "invalid parameter(s): @invalid (valid: @valid)";
202             }
203              
204             croak "unknown type: $params->{isa}"
205 23 100       262 unless exists $arg_isa{ $params->{isa} };
206              
207             croak "'default' and 'required' cannot be used together"
208 22 100 100     268 if defined $params->{default} and defined $params->{required};
209              
210             croak "'fallback' only valid with isa 'SubCmd'"
211 21 100 100     260 if $params->{fallback} and $params->{isa} ne 'SubCmd';
212              
213             croak "fallback must be a hashref"
214 20 100 100     225 if defined $params->{fallback} && ref $params->{fallback} ne 'HASH';
215              
216 19         44 $params->{package} = $package;
217 19         48 $params->{name} = $name;
218 19         38 $params->{length} = length $name;
219 19         34 $params->{acount} = 0;
220 19         47 $params->{type} = 'arg';
221 19         69 $params->{ISA} = $params->{name} . $arg_isa{ $params->{isa} };
222              
223 19         76 push( @{ $args{$package} }, $params );
  19         46  
224 19   100     68 $opts{$package} ||= [];
225 19         53 $seen{$package}->{$name}++;
226              
227 19 100       53 if ( $params->{fallback} ) {
228 1         4 my $p = $package . '::' . uc $params->{fallback}->{name};
229 1         2 $p =~ s/-/_/g;
230 1         3 $opts{$p} = [];
231 1         2 $args{$p} = [];
232 1         3 $desc{$p} = $params->{fallback}->{comment};
233             }
234              
235 19         50 return;
236             }
237              
238             # ------------------------------------------------------------------------
239             # Usage message generation
240             # ------------------------------------------------------------------------
241              
242             sub _usage {
243 7     7   24 my $caller = shift;
244 7         17 my $error = shift;
245 7         11 my $ishelp = shift;
246 7         27 my $terminal = -t STDOUT;
247 7 50 66     38 my $red = ( $COLOUR && $terminal ) ? "\e[0;31m" : '';
248 7         13 my $yellow = ''; #( $COLOUR && $terminal ) ? "\e[0;33m" : '';
249 7         9 my $grey = ''; #( $COLOUR && $terminal ) ? "\e[1;30m" : '';
250 7 50 66     30 my $reset = ( $COLOUR && $terminal ) ? "\e[0m" : '';
251 7         14 my $parent = $caller;
252 7         10 my @args = @{ $args{$caller} };
  7         21  
253 7         11 my @opts = @{ $opts{$caller} };
  7         20  
254 7         10 my @parents;
255             my @usage;
256 0         0 my @uargs;
257 0         0 my @uopts;
258 0         0 my $usage;
259              
260 7         42 require File::Basename;
261 7 50       276 my $me = File::Basename::basename( defined &static::list ? $^X : $0 );
262              
263 7 100       27 if ($error) {
264 3         12 $usage .= "${red}error:$reset $error\n\n";
265             }
266              
267 7 100       28 $usage .= $yellow . ( $ishelp ? 'help:' : 'usage:' ) . $reset . ' ' . $me;
268              
269 7         41 while ( $parent =~ s/(.*)::(.*)/$1/ ) {
270 8 100       23 last unless $seen{$parent};
271 3         8 ( my $name = $2 ) =~ s/_/-/g;
272 3         6 unshift( @parents, $name );
273 3         4 unshift( @opts, @{ $opts{$parent} } );
  3         20  
274             }
275              
276 7 100       23 $usage .= ' ' . join( ' ', @parents ) if @parents;
277              
278 7         16 my $last = $args[$#args];
279              
280 7 100       25 if ($last) {
281 6         41 foreach my $def (@args) {
282 6         11 $usage .= ' ';
283 6 50       19 $usage .= '[' unless $def->{required};
284 6         16 $usage .= uc $def->{name};
285 6 50       21 $usage .= '...' if $def->{greedy};
286 6 50       17 $usage .= ']' unless $def->{required};
287 6         26 push( @uargs, [ uc $def->{name}, $def->{comment} ] );
288             }
289             }
290              
291 7 50       24 $usage .= ' [OPTIONS...]' if @opts;
292              
293 7         13 $usage .= "\n";
294              
295             $usage .= "\n ${grey}Synopsis:$reset\n $desc{$caller}\n"
296 7 50 66     26 if $ishelp and $desc{$caller};
297              
298 7 50 66     46 if ( $ishelp and my $version = $caller->VERSION ) {
299 0         0 $usage .= "\n ${grey}Version:$reset\n $version\n";
300             }
301              
302 7 100 100     40 if ( $last && $last->{isa} eq 'SubCmd' ) {
303 4         15 $usage .= "\n ${grey}" . ucfirst( $last->{name} ) . ":$reset\n";
304              
305 4         5 my @subcommands = @{ $last->{subcommands} };
  4         11  
306              
307             push( @subcommands, uc $last->{fallback}->{name} )
308             if (
309             exists $last->{fallback}
310             && ( $ishelp
311             or !$last->{fallback}->{hidden} )
312 4 0 0     12 );
      33        
313              
314 4 100       14 @subcommands = sort @subcommands if $SORT;
315              
316 4         8 foreach my $subcommand (@subcommands) {
317 10         20 my $pkg = $last->{package} . '::' . $subcommand;
318 10         13 $pkg =~ s/-/_/g;
319 10 50 66     33 next if $hidden{$pkg} and !$ishelp;
320 10         31 push( @usage, [ $subcommand, $desc{$pkg} ] );
321             }
322              
323             }
324              
325 7 100       22 @opts = sort { $a->{name} cmp $b->{name} } @opts if $SORT;
  3         7  
326              
327 7         13 foreach my $opt (@opts) {
328 18 50 33     60 next if $opt->{hidden} and !$ishelp;
329              
330 18         45 ( my $name = $opt->{name} ) =~ s/_/-/g;
331              
332 18 50 66     71 if ( $opt->{isa} eq 'Bool' and $opt->{default} ) {
333 0         0 $name = 'no-' . $name;
334             }
335              
336 18 100       42 $name .= ',' if $opt->{alias};
337             push(
338             @uopts,
339             [
340             '--' . $name,
341             $opt->{alias}
342             ? '-' . $opt->{alias}
343             : '',
344             $opt->{comment}
345 18 100       90 ]
346             );
347             }
348              
349 7 50       20 if (@uopts) {
350 7         14 my $w1 = max( map { length $_->[0] } @uopts );
  18         51  
351 7         18 my $fmt = '%-' . $w1 . "s %s";
352              
353 7         13 @uopts = map { [ sprintf( $fmt, $_->[0], $_->[1] ), $_->[2] ] } @uopts;
  18         90  
354             }
355              
356 7         17 my $w1 = max( map { length $_->[0] } @usage, @uargs, @uopts );
  34         58  
357 7         19 my $format = ' %-' . $w1 . "s %s\n";
358              
359 7 100       19 if (@usage) {
360 4         7 foreach my $row (@usage) {
361 10         30 $usage .= sprintf( $format, @$row );
362             }
363             }
364 7 100 100     39 if ( @uargs and $last->{isa} ne 'SubCmd' ) {
365 2         7 $usage .= "\n ${grey}Arguments:$reset\n";
366 2         5 foreach my $row (@uargs) {
367 2         10 $usage .= sprintf( $format, @$row );
368             }
369             }
370 7 50       20 if (@uopts) {
371 7         62 $usage .= "\n ${grey}Options:$reset\n";
372 7         16 foreach my $row (@uopts) {
373 18         50 $usage .= sprintf( $format, @$row );
374             }
375             }
376              
377 7         12 $usage .= "\n";
378 7         100 return bless( \$usage, 'OptArgs::Usage' );
379             }
380              
381             sub _synopsis {
382 32     32   43 my $caller = shift;
383 32         43 my $parent = $caller;
384 32         36 my @args = @{ $args{$caller} };
  32         76  
385 32         39 my @parents;
386              
387 32         124 require File::Basename;
388 32         711 my $usage = File::Basename::basename($0);
389              
390 32         173 while ( $parent =~ s/(.*)::(.*)/$1/ ) {
391 88 100       204 last unless $seen{$parent};
392 56         102 ( my $name = $2 ) =~ s/_/-/g;
393 56         268 unshift( @parents, $name );
394             }
395              
396 32 100       93 $usage .= ' ' . join( ' ', @parents ) if @parents;
397              
398 32 100       81 if ( my $last = $args[$#args] ) {
399 12         21 foreach my $def (@args) {
400 12         14 $usage .= ' ';
401 12 50       28 $usage .= '[' unless $def->{required};
402 12         19 $usage .= uc $def->{name};
403 12 50       25 $usage .= '...' if $def->{greedy};
404 12 50       34 $usage .= ']' unless $def->{required};
405             }
406             }
407              
408 32         136 return 'usage: ' . $usage . "\n";
409             }
410              
411             sub usage {
412 0     0 1 0 my $caller = caller;
413 0         0 return _usage( $caller, @_ );
414             }
415              
416             # ------------------------------------------------------------------------
417             # Option/Argument processing
418             # ------------------------------------------------------------------------
419             sub _optargs {
420 50     50   69 my $caller = shift;
421 50         91 my $source = \@_;
422 50         122 my $source_hash = {};
423 50         75 my $package = $caller;
424              
425 50 100 100     251 if ( !@_ and @ARGV ) {
426             my $CODESET =
427 27         42 eval { require I18N::Langinfo; I18N::Langinfo::CODESET() };
  27         7325  
  27         6037  
428              
429 27 50       80 if ($CODESET) {
430 27         82 my $codeset = I18N::Langinfo::langinfo($CODESET);
431 27         137 $_ = decode( $codeset, $_ ) for @ARGV;
432             }
433              
434 27         6725 $source = \@ARGV;
435             }
436             else {
437 23         57 $source_hash = { map { %$_ } grep { ref $_ eq 'HASH' } @$source };
  0         0  
  29         65  
438 23         62 $source = [ grep { ref $_ ne 'HASH' } @$source ];
  29         70  
439             }
440              
441 50 50       94 map { Carp::croak('_optargs argument undefined!') if !defined $_ } @$source;
  84         274  
442              
443             croak "no option or argument defined for $caller"
444             unless exists $opts{$package}
445 50 50 66     271 or exists $args{$package};
446              
447 49         188 Getopt::Long::Configure(qw/pass_through no_auto_abbrev no_ignore_case/);
448              
449 49         2814 my @config = ( @{ $opts{$package} }, @{ $args{$package} } );
  49         111  
  49         117  
450              
451 49         79 my $ishelp;
452             my $missing_required;
453 49         71 my $optargs = {};
454 49         71 my @coderef_default_keys;
455              
456 49         157 while ( my $try = shift @config ) {
457 210         230 my $result;
458              
459 210 100       546 if ( $try->{type} eq 'opt' ) {
    50          
460 155 50       339 if ( exists $source_hash->{ $try->{name} } ) {
461 0         0 $result = delete $source_hash->{ $try->{name} };
462             }
463             else {
464 155         455 GetOptionsFromArray( $source, $try->{ISA} => \$result );
465             }
466             }
467             elsif ( $try->{type} eq 'arg' ) {
468 55 100 100     229 if (@$source) {
    50          
    100          
469 34 50       96 die _usage( $package, qq{Unknown option "$source->[0]"} )
470             if $source->[0] =~ m/^--\S/;
471              
472             die _usage( $package, qq{Unknown option "$source->[0]"} )
473             if $source->[0] =~ m/^-\S/
474             and !(
475             $source->[0] =~ m/^-\d/ and ( $try->{isa} ne 'Num'
476 34 50 0     116 or $try->{isa} ne 'Int' )
      33        
477             );
478              
479 34 100       71 if ( $try->{greedy} ) {
480 2         3 my @later;
481 2 50 33     7 if ( @config and @$source > @config ) {
482 0         0 push( @later, pop @$source ) for @config;
483             }
484              
485 2 50       9 if ( $try->{isa} eq 'ArrayRef' ) {
    50          
486 0         0 $result = [@$source];
487             }
488             elsif ( $try->{isa} eq 'HashRef' ) {
489 0         0 $result = { map { split /=/, $_ } @$source };
  0         0  
490             }
491             else {
492 2         4 $result = "@$source";
493             }
494              
495 2         13 shift @$source while @$source;
496 2         3 push( @$source, @later );
497             }
498             else {
499 32 100       110 if ( $try->{isa} eq 'ArrayRef' ) {
    100          
500 1         3 $result = [ shift @$source ];
501             }
502             elsif ( $try->{isa} eq 'HashRef' ) {
503 1         6 $result = { split /=/, shift @$source };
504             }
505             else {
506 30         54 $result = shift @$source;
507             }
508             }
509              
510             # TODO: type check using Param::Utils?
511             }
512             elsif ( exists $source_hash->{ $try->{name} } ) {
513 0         0 $result = delete $source_hash->{ $try->{name} };
514             }
515             elsif ( $try->{required} and !$ishelp ) {
516 2         3 $missing_required++;
517 2         9 next;
518             }
519              
520 53 100 100     194 if ( $try->{isa} eq 'SubCmd' and $result ) {
521              
522             # look up abbreviated words
523 10 100       24 if ($ABBREV) {
524 6         1185 require Text::Abbrev;
525             my %words =
526 13         67 map { m/^$package\:\:(\w+)$/; $1 => 1 }
  13         47  
527 6         64 grep { m/^$package\:\:(\w+)$/ }
  48         213  
528             keys %seen;
529 6         27 my %abbrev = Text::Abbrev::abbrev( keys %words );
530 6 50       354 $result = $abbrev{$result} if defined $abbrev{$result};
531             }
532              
533 10         25 my $newpackage = $package . '::' . $result;
534 10         17 $newpackage =~ s/-/_/g;
535              
536 10 100       30 if ( exists $seen{$newpackage} ) {
    50          
537 8         12 $package = $newpackage;
538 8         12 @config = grep { $_->{type} eq 'opt' } @config;
  0         0  
539 8         12 push( @config, @{ $opts{$package} }, @{ $args{$package} } );
  8         15  
  8         16  
540             }
541             elsif ( !$ishelp ) {
542 2 100       6 if ( $try->{fallback} ) {
543 1         3 unshift @$source, $result;
544 1         3 $try->{fallback}->{type} = 'arg';
545 1         2 unshift( @config, $try->{fallback} );
546 1         4 next;
547             }
548             else {
549             die _usage( $package,
550 1         5 "Unknown " . uc( $try->{name} ) . qq{ "$result"} );
551             }
552             }
553              
554 8         16 $result = undef;
555             }
556              
557             }
558              
559 206 100       21892 if ( defined $result ) {
    100          
560 51         151 $optargs->{ $try->{name} } = $result;
561             }
562             elsif ( defined $try->{default} ) {
563             push( @coderef_default_keys, $try->{name} )
564 16 100       51 if ref $try->{default} eq 'CODE';
565 16         42 $optargs->{ $try->{name} } = $result = $try->{default};
566             }
567              
568 206 100 66     937 $ishelp = 1 if $result and $try->{ishelp};
569              
570             }
571              
572 48 100       302 if ($ishelp) {
    100          
    100          
    50          
573 2         5 die _usage( $package, undef, 1 );
574             }
575             elsif ($missing_required) {
576 2         7 die _usage($package);
577             }
578             elsif (@$source) {
579 2         14 die _usage( $package, "Unexpected options or arguments: @$source" );
580             }
581             elsif ( my @unexpected = keys %$source_hash ) {
582 0         0 die _usage( $package,
583             "Unexpected HASH options or arguments: @unexpected" );
584             }
585              
586             # Re-calculate the default if it was a subref
587 42         90 foreach my $key (@coderef_default_keys) {
588 8         436 $optargs->{$key} = $optargs->{$key}->( {%$optargs} );
589             }
590              
591 42         1719 return ( $package, $optargs );
592             }
593              
594             sub optargs {
595 37     37 1 2461 my $caller = caller;
596              
597             carp "optargs() called from dispatch handler"
598 37 50       110 if $dispatching{$caller};
599              
600 37         108 my ( $package, $optargs ) = _optargs( $caller, @_ );
601 34         216 return $optargs;
602             }
603              
604             sub class_optargs {
605 13     13 1 18 my $caller = shift;
606              
607 13 50       30 croak 'dispatch($class, [@argv])' unless $caller;
608             carp "optargs_class() called from dispatch handler"
609 13 50       37 if $dispatching{$caller};
610              
611 13 50       565 die $@ unless eval "require $caller;";
612              
613 13         111 my ( $class, $optargs ) = _optargs( $caller, @_ );
614              
615 8 50       438 croak $@ unless eval "require $class;1;";
616 8         28 return ( $class, $optargs );
617             }
618              
619             sub dispatch {
620 16     16 1 8162 my $method = shift;
621 16         24 my $class = shift;
622              
623 16 100 100     344 croak 'dispatch($method, $class, [@argv])' unless $method and $class;
624 14 100       841 croak $@ unless eval "require $class;1;";
625              
626 13         49 my ( $package, $optargs ) = class_optargs( $class, @_ );
627              
628 8         61 my $sub = $package->can($method);
629 8 50       21 die "Can't find method $method via package $package" unless $sub;
630              
631 8         16 $dispatching{$class}++;
632 8         23 my @results = $sub->($optargs);
633 8         304 $dispatching{$class}--;
634 8 100       41 return @results if wantarray;
635 4         16 return $results[0];
636             }
637              
638             package OptArgs::Usage;
639             use overload
640 7     7   229 bool => sub { 1 },
641 7     7   883 '""' => sub { ${ $_[0] } },
  7         81  
642 11     11   1182 fallback => 1;
  11         22  
  11         144  
643              
644             1;
645              
646             __END__