File Coverage

lib/Getopt/ArgParse/Parser.pm
Criterion Covered Total %
statement 538 557 96.5
branch 257 302 85.1
condition 108 132 81.8
subroutine 36 37 97.3
pod 0 15 0.0
total 939 1043 90.0


line stmt bran cond sub pod time code
1             package Getopt::ArgParse::Parser;
2              
3 20     20   234789 use Moo;
  20         249786  
  20         109  
4              
5 20     20   39880 use Getopt::Long qw(GetOptionsFromArray);
  20         236940  
  20         119  
6 20     20   19381 use Text::Wrap;
  20         47036  
  20         1175  
7 20     20   125 use Scalar::Util qw(blessed);
  20         34  
  20         1699  
8              
9 20     20   99 use File::Basename ();
  20         32  
  20         285  
10 20     20   6408 use Getopt::ArgParse::Namespace;
  20         46  
  20         933  
11              
12             use constant {
13 20         131049 TYPE_UNDEF => 0,
14             TYPE_SCALAR => 1,
15             TYPE_ARRAY => 2,
16             TYPE_COUNT => 3,
17             TYPE_PAIR => 4, # key=value pair
18             TYPE_BOOL => 5,
19              
20             CONST_TRUE => 1,
21             CONST_FALSE => 0,
22              
23             # Export these?
24             ScalarArg => 'scalar',
25             ArrayArg => 'Array',
26             PairArg => 'Pair',
27             CountArg => 'Count',
28             BoolArg => 'Bool',
29              
30             # Internal
31             ERROR_PREFIX => 'Getopt::ArgParse: ',
32 20     20   102 };
  20         22  
33              
34             # Allow customization
35             # default actions
36             my %Action2ClassMap = (
37             '_store' => 'Getopt::ArgParse::ActionStore',
38             '_append' => 'Getopt::ArgParse::ActionAppend',
39             '_count' => 'Getopt::ArgParse::ActionCount',
40             # Not supported - Maybe in the future
41             # '_help' => 'Getopt::ArgParse::ActionHelp',
42             # '_version' => 'Getopt::ArgParse::ActionVersion',
43             );
44              
45             my %Type2ConstMap = (
46             '' => TYPE_UNDEF(),
47             'Scalar' => TYPE_SCALAR(),
48             'Array' => TYPE_ARRAY(),
49             'Count' => TYPE_COUNT(),
50             'Pair' => TYPE_PAIR(),
51             'Bool' => TYPE_BOOL(),
52             );
53              
54              
55             sub _croak {
56 38     38   398 die join('', @_);
57             }
58              
59             # Program name. Default $0
60              
61             has prog => ( is => 'rw', required => 1, default => sub { File::Basename::basename($0) }, );
62              
63             # short one
64             has help => ( is => 'rw', required => 1, default => sub { '' }, );
65              
66             # long one
67             has description => ( is => 'rw', required => 1, default => sub { '' }, );
68              
69             has epilog => ( is => 'rw', required => 1, default => sub { '' }, );
70              
71             has error_prefix => (is => 'rw', default => sub { ERROR_PREFIX() }, );
72              
73             has aliases => (is => 'ro', default => sub { [] }); # for subcommand only
74              
75             # namespace() - Read/write
76             # Contains the parsed results.
77             has namespace => (
78             is => 'rw',
79             isa => sub {
80             return undef unless $_[0]; # allow undef
81             my $class = blessed $_[0];
82             die 'namespace doesn\'t comform to the required interface'
83             unless $class && $class->can('set_attr') && $class->can('get_attr');
84             },
85             );
86              
87             # parent - Readonly
88             has parents => (
89             is => 'ro',
90             isa => sub {
91             my $parents = shift;
92             for my $parent (@$parents) {
93             my $parent_class = blessed $parent;
94             die 'parent is not a Getopt::ArgParse::Parser'
95             unless $parent_class && $parent_class->isa(__PACKAGE__);
96             }
97             },
98             default => sub { [] },
99             );
100              
101             # parser_configs - Read/write
102              
103             # The configurations that will be passed to Getopt::Long::Configure(
104             # $self->parser_configs ) when parse_args is invoked.
105             has parser_configs => ( is => 'rw', required => 1, default => sub { [] }, );
106              
107             # Behavioural properties
108             #
109             # Print usage message if help is no, by default. Turn this off by
110             # setting this to a false value
111             has print_usage_if_help => (is => 'ro', default => 1);
112              
113             # internal properties
114              
115             has _option_position => ( is => 'rw', required => 1, default => sub { 0 } );
116              
117             # The current subcommand the same as namespace->current_command
118             has _command => ( is => 'rw');
119              
120             sub BUILD {
121 62     62 0 399 my $self = shift;
122              
123 62         171 $self->{-option_specs} = {};
124 62         131 $self->{-position_specs} = {};
125              
126 62         184 $self->add_argument(
127             '--help', '-h',
128             type => 'Bool',
129             dest => 'help',
130             help => 'show this help message and exit',
131             reset => 1,
132             );
133              
134             # merge
135 62         68 for my $parent (@{$self->parents}) {
  62         1190  
136 5         12 $self->copy($parent);
137             }
138             }
139              
140             #
141             sub _check_parent {
142 18     18   13 my $parent = shift;
143 18         38 my $parent_class = blessed $parent;
144 18 50 33     111 _croak 'Parent is not a Getopt::ArgParse::Parser'
145             unless $parent_class && $parent_class->isa(__PACKAGE__);
146             }
147              
148             sub copy {
149 5     5 0 6 my $self = shift;
150 5         7 my $parent = shift;
151              
152 5 50       7 _croak 'Parent is missing' unless $parent;
153 5         9 _check_parent($parent);
154              
155 5         7 $self->copy_args($parent);
156 5         13 $self->copy_parsers($parent);
157             }
158              
159             sub copy_args {
160 7     7 0 22 my $self = shift;
161 7         7 my $parent = shift;
162              
163 7 50       12 _croak 'Parent is missing' unless $parent;
164 7         9 _check_parent($parent);
165              
166 7         5 $self->add_arguments( @{ $parent->{-pristine_add_arguments} } );
  7         20  
167             }
168              
169             sub copy_parsers {
170 6     6 0 12 my $self = shift;
171 6         7 my $parent = shift;
172              
173 6 50       10 _croak 'Parent is missing' unless $parent;
174 6         11 _check_parent($parent);
175              
176 6 100       99 if (exists $parent->{-subparsers}) {
177 2         8 $self->add_subparsers(
178 2         3 @{$parent->{-pristine_add_subparsers}->[0]}
179             );
180              
181 2         2 for my $args (@{$parent->{-pristine_add_parser}}) {
  2         7  
182 6         17 my $command = $args->[0];
183 6 100       11 next if $command eq 'help';
184 4         15 $self->add_parser(
185             @$args,
186             parents => [ $parent->{-subparsers}{-parsers}{$command} ],
187             );
188             }
189             }
190             }
191              
192             #
193             # subcommands
194             #
195             sub add_subparsers {
196 16     16 0 2293 my $self = shift;
197              
198 16         21 push @{$self->{-pristine_add_subparsers}}, [ @_ ];
  16         72  
199              
200 16 100       66 _croak $self->error_prefix . 'Incorrect number of arguments' if scalar(@_) % 2;
201              
202 15         33 my $args = { @_ };
203              
204 15   100     85 my $title = (delete $args->{title} || 'Subcommands') . ':';
205 15   100     88 my $description = delete $args->{description} || '';
206              
207 15 100       51 _croak $self->error_prefix . sprintf(
208             'Unknown parameters: %s',
209             join(',', keys %$args)
210             ) if keys %$args;
211              
212 14 100       51 if (exists $self->{-subparsers}) {
213 1         5 _croak $self->error_prefix . 'Subparsers already added';
214             }
215              
216 13         63 $self->{-subparsers}{-title} = $title;
217 13         43 $self->{-subparsers}{-description} = $description;
218 13         54 $self->{-subparsers}{-alias_map} = {};
219              
220 13         149 my $hp = $self->add_parser(
221             'help',
222             help => 'display help information about ' . $self->prog,
223             );
224              
225 13         166 $hp->add_arguments(
226             [
227             '--all', '-a',
228             help => 'Show the full usage',
229             type => 'Bool',
230             ],
231             [
232             'command',
233             help => 'Show the usage for this command',
234             dest => 'help_command',
235             nargs => 1,
236             ],
237             );
238              
239 13         49 return $self;
240             }
241              
242             # $command, aliases => [], help => ''
243             sub add_parser {
244 36     36 0 2344 my $self = shift;
245              
246 36 100       169 _croak $self->error_prefix . 'add_subparsers() is not called first' unless $self->{-subparsers};
247              
248 35         44 my $command = shift;
249              
250 35 100       112 _croak $self->error_prefix . 'Subcommand is empty' unless $command;
251              
252 34 100       94 _croak $self->error_prefix . 'Incorrect number of arguments' if scalar(@_) % 2;
253              
254 33 100       111 if (exists $self->{-subparsers}{-parsers}{$command}) {
255 1         5 _croak $self->error_prefix . "Subcommand $command already defined";
256             }
257              
258 32         69 my $args = { @_ };
259              
260 32   100     128 my $parents = delete $args->{parents} || [];
261 32         37 push @{ $self->{-pristine_add_parser} }, [ $command, %$args ];
  32         122  
262              
263 32 50       110 _croak $self->error_prefix . 'Add_subparsers() is not called first' unless $self->{-subparsers};
264              
265 32   100     96 my $help = delete $args->{help} || '';
266 32   100     110 my $description = delete $args->{description} || '';
267 32   100     111 my $aliases = delete $args->{aliases} || [];
268              
269 32 100       80 _croak $self->error_prefix . 'Aliases is not an arrayref'
270             if ref($aliases) ne 'ARRAY';
271              
272 31 100       70 _croak $self->error_prefix . sprintf(
273             'Unknown parameters: %s',
274             join(',', keys %$args)
275             ) if keys %$args;
276              
277 30         37 my $alias_map = {};
278              
279 30         59 for my $alias ($command, @$aliases) {
280 35 100       133 if (exists $self->{-subparsers}{-alias_map}{$alias}) {
281 1         10 _croak $self->error_prefix
282             . "Alias=$alias already used by command="
283             . $self->{-subparsers}{-alias_map}{$alias};
284             }
285             }
286              
287 29         117 $self->{-subparsers}{-alias_map}{$_} = $command for ($command, @$aliases);
288              
289 29         35 my $prog = $command;
290              
291             # $prog .= ' (' . join(', ', @$aliases) . ')' if @$aliases;
292              
293 29         65 $self->{-subparsers}{-aliases}{$command} = $aliases;
294 29         770 return $self->{-subparsers}{-parsers}{$command} = __PACKAGE__->new(
295             prog => $prog,
296             aliases => $aliases, # subcommand
297             help => $help,
298             parents => $parents,
299             description => $description,
300             error_prefix => $self->error_prefix,
301             print_usage_if_help => $self->print_usage_if_help,
302             );
303             }
304              
305 0     0 0 0 sub get_parser { $_[0]->_get_subcommand_parser(@_) }
306              
307             *add_arg = \&add_argument;
308              
309             *add_args = \&add_arguments;
310              
311             # add_arguments([arg_spec], [arg_spec1], ...)
312             # Add multiple arguments.
313             # Interface method
314             sub add_arguments {
315 22     22 0 45 my $self = shift;
316              
317 22         66 $self->add_argument(@$_) for @_;
318              
319 22         42 return $self;
320             }
321              
322             #
323             sub add_argument {
324 201     201 0 11030 my $self = shift;
325              
326 201 100       428 return unless @_; # mostly harmless
327             #
328             # FIXME: This is for merginng parent parents This is a dirty hack
329             # and should be done properly by merging internal specs
330             # and subcommand merging is missing
331             #
332 200         188 push @{ $self->{-pristine_add_arguments} }, [ @_ ];
  200         772  
333              
334 200         560 my ($name, $flags, $rest) = $self->_parse_for_name_and_flags([ @_ ]);
335              
336 200 100       551 _croak $self->error_prefix . 'Incorrect number of arguments' if scalar(@$rest) % 2;
337              
338 199 100       330 _croak $self->error_prefix . 'Empty option name' unless $name;
339              
340 198         460 my $args = { @$rest };
341              
342 198         181 my @flags = @{ $flags };
  198         337  
343              
344             ################
345             # nargs - positional only
346             ################
347             ################
348             # type
349             ################
350 198   100     576 my $type_name = delete $args->{type} || 'Scalar';
351 198 100       522 my $type = $Type2ConstMap{$type_name} if exists $Type2ConstMap{$type_name};
352 198 100       389 _croak $self->error_prefix . "Unknown type=$type_name" unless defined $type;
353              
354 197         243 my $nargs = delete $args->{nargs};
355              
356 197 100       345 if ( defined $nargs ) {
357 28 100       69 _croak $self->error_prefix . 'Nargs only allowed for positional options' if @flags;
358              
359 27 100 100     226 if ( $type != TYPE_PAIR
      100        
      100        
360             && $type != TYPE_ARRAY
361             && $nargs ne '1'
362             && $nargs ne '?'
363             ) {
364 3         5 $type = TYPE_ARRAY;
365             }
366             }
367              
368 196 100 100     899 if ($type == TYPE_COUNT) {
    100          
369 10 50       39 $args->{action} = '_count' unless defined $args->{action};
370 10 100       34 $args->{default} = 0 unless defined $args->{default};
371             } elsif ($type == TYPE_ARRAY || $type == TYPE_PAIR) {
372 23 50       86 $args->{action} = '_append' unless defined $args->{action};
373             } else {
374             # pass
375             }
376              
377             ################
378             # action
379             ################
380 196   100     560 my $action_name = delete $args->{action} || '_store';
381              
382 196 50       487 my $action = $Action2ClassMap{$action_name}
383             if exists $Action2ClassMap{$action_name};
384              
385 196 50       335 $action = $action_name unless $action;
386              
387             {
388 196         158 local $SIG{__WARN__};
  196         534  
389 196         359 local $SIG{__DIE__};
390              
391 196         9552 eval "require $action";
392              
393 196 50       1019 _croak $self->error_prefix . "Cannot load $action for action=$action_name" if $@;
394             };
395              
396             ################
397             # split
398             ################
399 196         307 my $split = delete $args->{split};
400 196 50 66     461 if (defined $split && !$split && $split =~ /^ +$/) {
      33        
401 0         0 _croak $self->error_prefix . 'Cannot use whitespaces to split';
402             }
403              
404 196 50 100     407 if (defined $split && $type != TYPE_ARRAY && $type != TYPE_PAIR) {
      66        
405 0         0 _croak $self->error_prefix . 'Split only for Array and Pair';
406             }
407              
408             ################
409             # default
410             ################
411 196         226 my $default;
412 196 100       383 if (exists $args->{default}) {
413 20         37 my $val = delete $args->{default};
414              
415 20 100       94 if (ref($val) eq 'ARRAY') {
    100          
416 2         5 $default = $val;
417             } elsif (ref($val) eq 'HASH') {
418 5 100       17 _croak $self->error_prefix . 'HASH default only for type Pair'
419             if $type != TYPE_PAIR;
420 4         6 $default = $val;
421             } else {
422 13         30 $default = [ $val ];
423             }
424              
425 19 100       52 if ($type != TYPE_PAIR) {
426 15 100 100     88 if ($type != TYPE_ARRAY && scalar(@$default) > 1) {
427 1         8 _croak $self->error_prefix . 'Multiple default values for scalar type: $name';
428             }
429             }
430             }
431              
432             ################
433             # choices
434             ################
435 194   100     692 my $choices = delete $args->{choices} || undef;
436 194 50 100     408 if ( $choices
      66        
437             && ref($choices) ne 'CODE'
438             && ref($choices) ne 'ARRAY' )
439             {
440 0         0 _croak $self->error_prefix . "Must provide choices in an arrayref or a coderef";
441             }
442              
443 194   100     547 my $choices_i = delete $args->{choices_i} || undef;
444              
445 194 100 100     376 if ($choices && $choices_i) {
446 1         6 _croak $self->error_prefix . 'Not allow to specify choices and choices_i';
447             }
448              
449 193 100 100     353 if ( $choices_i
450             && ref($choices_i) ne 'ARRAY' )
451             {
452 1         5 _croak $self->error_prefix . "Must provide choices_i in an arrayref";
453             }
454              
455             ################
456             # required
457             ################
458 192   100     546 my $required = delete $args->{required} || '';
459              
460 192 100 100     578 if ($type == TYPE_BOOL || $type == TYPE_COUNT) {
461 117         148 $required = ''; # TYPE_BOOL and TYPE_COUNT will already have default values
462             }
463              
464             ################
465             # help
466             ################
467 192   100     462 my $help = delete $args->{help} || '';
468              
469             ################
470             # metavar
471             ################
472 192   33     656 my $metavar = delete $args->{metavar} || uc($name);
473              
474 192 100 100     551 $metavar = ''
475             if $type == TYPE_BOOL
476             || $action_name eq '_count';
477              
478             ################
479             # dest
480             ################
481 192   66     501 my $dest = delete $args->{dest} || $name;
482 192         321 $dest =~ s/-/_/g; # option-name becomes option_name
483              
484 192 100       375 if (@flags) {
485 152         157 while (my ($d, $s) = each %{$self->{-option_specs}}) {
  290         982  
486 139 100       268 if ($dest ne $d) {
487 123         156 for my $f (@flags) {
488 304         700 _croak $self->error_prefix . "Flag $f already used for a different option ($d)"
489 173 100       164 if grep { $f eq $_ } @{$s->{flags}};
  173         254  
490             }
491             }
492             }
493              
494 151 50       396 if (exists $self->{-position_specs}{$dest}) {
495 0         0 _croak $self->error_prefix . "Option dest=$dest already used by a positional argument";
496             }
497             } else {
498 40 100       167 if (exists $self->{-option_specs}{$dest}) {
499 1         5 _croak $self->error_prefix . "Option dest=$dest already used by an optional argument";
500             }
501             }
502              
503             # never modify existing ones so that the parent's structure will
504             # not be modified
505 190   100     2214 my $spec = {
506             name => $name,
507             flags => \@flags,
508             action => $action,
509             nargs => $nargs,
510             split => $split,
511             required => $required || '',
512             type => $type,
513             default => $default,
514             choices => $choices,
515             choices_i => $choices_i,
516             dest => $dest,
517             metavar => $metavar,
518             help => $help,
519             position => $self->{-option_position}++, # sort order
520             groups => [ '' ],
521             };
522              
523 190         208 my $specs;
524 190 100       270 if (@flags) {
525 151         233 $specs = $self->{-option_specs};
526             } else {
527 39         99 $specs = $self->{-position_specs};
528             }
529              
530             # reset
531 190 100       413 if (delete $args->{reset}) {
532 81 100       1338 $self->namespace->set_attr($spec->{dest}, undef) if $self->namespace;
533 81         10540 delete $specs->{$spec->{dest}};
534             }
535              
536 190 50       464 _croak $self->error_prefix . sprintf(
537             'Unknown spec: %s',
538             join(',', keys %$args)
539             ) if keys %$args;
540              
541             # type check
542 190 100       399 if (exists $specs->{$spec->{dest}}) {
543 3         42 _croak $self->error_prefix . sprintf(
544             'Redefine option %s without reset',
545             $spec->{dest},
546             );
547             }
548              
549             # override
550 187         291 $specs->{$spec->{dest}} = $spec;
551              
552             # specs changed, need to force to resort specs by groups
553 187 50       378 delete $self->{-groups} if $self->{-groups};
554              
555             # Return $self for chaining, $self->add_argument()->add_argument()
556             # or use add_arguments
557 187         744 return $self;
558             }
559              
560             sub _parse_for_name_and_flags {
561 200     200   191 my $self = shift;
562 200         179 my $args = shift;
563              
564 200         169 my ($name, @flags);
565             FLAG:
566 200         413 while (my $flag = shift @$args) {
567 458 100       797 if (substr($flag, 0, 1) eq '-') {
568 272         621 push @flags, $flag;
569             } else {
570 186         274 unshift @$args, $flag;
571 186         286 last FLAG;
572             }
573             }
574              
575             # It's a positional argument spec if there are no flags
576 200 100       400 $name = @flags ? $flags[0] : shift(@$args);
577 200         635 $name =~ s/^-+//g;
578              
579 200         515 return ( $name, \@flags, $args );
580             }
581              
582             #
583             # parse_args([@_])
584             #
585             # Parse @ARGV if called without passing arguments. It returns an
586             # instance of ArgParse::Namespace upon success
587             #
588             # Interface
589              
590             sub parse_args {
591 82     82 0 6552 my $self = shift;
592              
593 82 100       451 my @argv = scalar(@_) ? @_ : @ARGV;
594              
595 82         454 $self->{-saved_argv} = \@ARGV;
596 82         117 @ARGV = ();
597              
598 129         317 my @option_specs = sort {
599 82         484 $a->{position} <=> $b->{position}
600 82         118 } values %{$self->{-option_specs}};
601              
602 29         58 my @position_specs = sort {
603 82         264 $a->{position} <=> $b->{position}
604 82         98 } values %{$self->{-position_specs}};
605              
606 82         193 $self->{-argv} = \@argv;
607             # We still want to continue even if @argv is empty to allow:
608             # - namespace initialization
609             # - default values asssigned
610             # - post checks applied, e.g. required check
611              
612 82 100       2372 $self->namespace(Getopt::ArgParse::Namespace->new) unless $self->namespace;
613              
614 82         492 my $parsed_subcmd;
615 82         1358 $self->namespace->set_attr(current_command => undef);
616              
617             # If the first argument is a subcommand, it will parse for the
618             # subcommand
619 82 100 100     426 if (exists $self->{-subparsers} && scalar(@argv) && defined($argv[0]) && substr($argv[0], 0, 1) ne '-') {
      33        
      66        
620             # Subcommand must appear as the first argument
621             # or it will parse as the top command
622 11         21 my $cmd = shift @argv;
623 11         38 my $subparser = $self->_get_subcommand_parser($cmd);
624 11 100       57 _croak $self->error_prefix
625             . sprintf("%s is not a %s command. See help", $cmd, $self->prog)
626             unless $subparser;
627              
628 10         34 $parsed_subcmd = $self->_parse_subcommand($self->_command => $subparser);
629              
630 10         162 $self->namespace->set_attr(current_command => $self->_command);
631             }
632              
633 81 100       160 if (!$parsed_subcmd) {
634 71 50       295 $self->_parse_optional_args(\@option_specs) if @option_specs;
635 64 100       225 $self->_parse_positional_args(\@position_specs) if @position_specs;
636              
637 56 100 100     1043 if ($self->print_usage_if_help() && $self->namespace->get_attr('help')) {
638 1         9 $self->print_usage();
639 1         136 exit(0);
640             }
641             } else {
642 10 100 100     80 if ($self->print_usage_if_help() && $self->_command() eq 'help') {
643 2 100       41 if ($self->namespace->get_attr('help_command')) {
644 1         4 $self->print_command_usage();
645 1         120 exit(0);
646             } else {
647 1         2 $self->print_usage();
648 1         111 exit(0);
649             }
650             }
651             }
652              
653             # Return value
654 63         1031 return $self->namespace;
655             }
656              
657             sub _get_subcommand_parser {
658 13     13   19 my $self = shift;
659 13         18 my $alias = shift;
660              
661 13 50       38 return unless $alias;
662              
663 13 100       87 my $command = $self->{-subparsers}{-alias_map}{$alias}
664             if exists $self->{-subparsers}{-alias_map}{$alias};
665              
666 13 100       29 return unless $command;
667              
668 12         57 $self->_command($command);
669             # The subcommand parser must exist if the alias is mapped
670 12         36 return $self->{-subparsers}{-parsers}{$command};
671             }
672              
673             sub _parse_subcommand {
674 10     10   25 my $self = shift;
675 10         16 my ($cmd, $subparser) = @_;
676              
677 10         185 $subparser->namespace($self->namespace);
678 10         69 $subparser->parse_args(@{$self->{-argv}});
  10         83  
679              
680 10         59 $self->{-argv} = $subparser->{-argv};
681              
682 10         20 return 1;
683             }
684              
685             #
686             # After each call of parse_args(), call this to retrieve any
687             # unconsumed arguments
688             # Interface call
689             #
690             sub argv {
691 1 50   1 0 1 @{ $_[0]->{-argv} || [] };
  1         9  
692             }
693              
694             sub _parse_optional_args {
695 71     71   105 my $self = shift;
696 71         75 my $specs = shift;
697 71         120 my $options = {};
698 71         104 my $dest2spec = {};
699              
700 71         144 for my $spec ( @$specs ) {
701 158         139 my @values;
702 158         331 $dest2spec->{$spec->{dest}} = $self->_get_option_spec($spec);
703 158 100 100     1132 if ( $spec->{type} == TYPE_ARRAY
      100        
      100        
704             || $spec->{type} == TYPE_COUNT
705             || $spec->{type} == TYPE_PAIR
706             || $spec->{type} == TYPE_SCALAR
707             ) {
708 66         57 my @values;
709 66         194 $options->{ $dest2spec->{$spec->{dest}} } = \@values;
710             } else {
711 92         82 my $value;
712 92         250 $options->{ $dest2spec->{$spec->{dest}} } = \$value;
713             }
714             }
715              
716 71         88 Getopt::Long::Configure( @{ $self->parser_configs });
  71         533  
717              
718 71         812 my (@warns, $result);
719              
720 71         137 eval {
721 71     2   529 local $SIG{__WARN__} = sub { push @warns, @_ };
  2         350  
722 71         184 local $SIG{__DIE__};
723              
724 71         389 $result = GetOptionsFromArray( $self->{-argv}, %$options );
725              
726 71         19458 1;
727             };
728              
729             # die on errors
730 71 50       177 _croak $self->error_prefix, $@ if $@;
731              
732 71 100       158 _croak $self->error_prefix, @warns if @warns;
733              
734 69 50       149 _croak $self->error_prefix, 'Failed to parse for options' if !$result;
735              
736 69         186 Getopt::Long::Configure('default');
737              
738 69         1733 $self->_post_parse_processing($specs, $options, $dest2spec);
739              
740 66         183 $self->_apply_action($specs, $options, $dest2spec);
741              
742 65         160 $self->_post_apply_processing($specs, $options, $dest2spec);
743             }
744              
745             sub _parse_positional_args {
746 32     32   41 my $self = shift;
747 32         38 my $specs = shift;
748              
749             # short-circuit it if it's for help
750 32 100       558 return if $self->namespace->get_attr('help');
751              
752 31         50 my $options = {};
753 31         71 my $dest2spec = {};
754              
755 31         56 for my $spec (@$specs) {
756 53         104 $dest2spec->{$spec->{dest}} = $spec->{dest};
757 53         74 my @values = ();
758             # Always assigne values to an option
759 53         124 $options->{$spec->{dest}} = \@values;
760             }
761              
762             POSITION_SPEC:
763 31         55 for my $spec (@$specs) {
764 53         79 my $values = $options->{$spec->{dest}};
765              
766 53 50       100 if ($spec->{type} == TYPE_BOOL) {
767 0         0 _croak $self->error_prefix . 'Bool not allowed for positional arguments';
768             }
769              
770 53         54 my $number = 1;
771 53 100       103 my $nargs = defined $spec->{nargs} ? $spec->{nargs} : 1;
772 53 100       120 if (defined $spec->{nargs}) {
773 32 100       194 if ($nargs eq '?') {
    100          
    100          
    100          
774 5         6 $number = 1;
775             } elsif ($nargs eq '+') {
776 3 100       3 _croak $self->error_prefix . "Too few arguments: narg='+'" unless @{$self->{-argv}};
  3         14  
777 2         2 $number = scalar @{$self->{-argv}};
  2         3  
778             } elsif ($nargs eq '*') { # remainder
779 3         2 $number = scalar @{$self->{-argv}};
  3         6  
780             } elsif ($nargs !~ /^\d+$/) {
781 1         6 _croak $self->error_prefix . 'Invalid nargs:' . $nargs;
782             } else {
783 20         26 $number = $nargs;
784             }
785             }
786              
787 51 100       47 push @$values, splice(@{$self->{-argv}}, 0, $number) if @{$self->{-argv}};
  37         85  
  51         204  
788              
789             # If no values, let it pass for required checking
790             # If there are values, make sure there is the right number of
791             # values
792 51 100 100     229 if (scalar(@$values) && scalar(@$values) != $number) {
793 3         34 _croak($self->error_prefix . sprintf(
794             'Too few arguments for %s: expected:%d,actual:%d',
795             $spec->{dest}, $number, scalar(@$values),
796             )
797             );
798             }
799             }
800              
801 26         68 $self->_post_parse_processing($specs, $options, $dest2spec);
802              
803 26         52 $self->_apply_action($specs, $options, $dest2spec);
804              
805 26         55 $self->_post_apply_processing($specs, $options, $dest2spec);
806             }
807              
808             #
809             sub _post_parse_processing {
810 95     95   117 my $self = shift;
811 95         131 my ($option_specs, $options, $dest2spec) = @_;
812              
813             #
814 95         147 for my $spec ( @$option_specs ) {
815 198         326 my $values = $options->{ $dest2spec->{$spec->{dest}} };
816              
817 198 50       302 if (defined($values)) {
818 198 100       377 if (ref $values eq 'SCALAR') {
819 90 100       151 if (defined($$values)) {
820 11         25 $values = [ $$values ];
821             } else {
822 79         134 $values = [];
823             }
824             }
825             } else {
826 0         0 $values = [];
827             }
828              
829 198         289 $options->{ $dest2spec->{$spec->{dest}} } = $values;
830              
831             # default
832 198 100 100     3942 if (!defined($self->namespace->get_attr($spec->{dest}))
      100        
833             && scalar(@$values) < 1
834             && defined($spec->{default}) )
835             {
836 8 100       44 if ($spec->{type} == TYPE_COUNT) {
    100          
    100          
837 1         15 $self->namespace->set_attr($spec->{dest}, @{$spec->{default}});
  1         6  
838             } elsif ($spec->{type} == TYPE_BOOL) {
839 1         15 $self->namespace->set_attr($spec->{dest}, @{$spec->{default}});
  1         6  
840             } elsif ($spec->{type} == TYPE_PAIR) {
841 2         49 $self->namespace->set_attr($spec->{dest}, $spec->{default});
842             } else {
843 4         5 push @$values, @{$spec->{default}};
  4         10  
844             }
845             }
846              
847             # split and expand
848             # Pair are processed here as well
849 198 100       388 if ( my $delimit = $spec->{split} ) {
850 5         2 my @expanded;
851 5         7 for my $v (@$values) {
852 12 100       31 push @expanded,
853             map {
854 4         17 $spec->{type} == TYPE_PAIR ? { split('=', $_) } : $_
855             } split($delimit, $v);
856             }
857              
858 5         11 $options->{ $dest2spec->{$spec->{dest} } } = \@expanded;
859             } else {
860             # Process PAIR only
861 193 100       361 if ($spec->{type} == TYPE_PAIR) {
862 6         22 $options->{ $dest2spec->{$spec->{dest} } }
863 5         14 = [ map { { split('=', $_) } } @$values ];
864             }
865             }
866              
867             # choices
868 198 100       337 if ( $spec->{choices} ) {
869 5 100       9 if (ref($spec->{choices}) eq 'CODE') {
870 2         3 for my $v (@$values) {
871 2         6 $spec->{choices}->($v);
872             }
873             } else {
874 9 50       20 my %choices =
875 3         7 map { defined($_) ? $_ : '_undef' => 1 }
876 3         6 @{$spec->{choices}};
877              
878             VALUE:
879 3         5 for my $v (@$values) {
880 2 50       5 my $k = defined($v) ? $v : '_undef';
881 2 100       6 next VALUE if exists $choices{$k};
882              
883 1         10 _croak $self->error_prefix . sprintf(
884             "Option %s value %s not in choices: [ %s ]",
885 1         3 $spec->{dest}, $v, join( ', ', @{ $spec->{choices} } ),
886             );
887             }
888             }
889             }
890              
891 196 100       503 if ( $spec->{choices_i} ) {
892 6 50       19 my %choices =
893 3         7 map { defined($_) ? uc($_) : '_undef' => 1 }
894 3         3 @{$spec->{choices_i}};
895              
896             VALUE:
897 3         6 for my $v (@$values) {
898 3 50       6 my $k = defined($v) ? uc($v) : '_undef';
899 3 100       11 next VALUE if exists $choices{$k};
900              
901 1         7 _croak $self->error_prefix . sprintf(
902             "Option %s value %s not in choices: [ %s ] (case insensitive)",
903 1         3 $spec->{dest}, $v, join( ', ', @{ $spec->{choices_i} } ),
904             );
905             }
906             }
907             }
908              
909 92         133 return '';
910             }
911              
912             sub _apply_action {
913 92     92   110 my $self = shift;
914 92         111 my ($specs, $options, $dest2spec) = @_;
915              
916 92         141 for my $spec (@$specs) {
917             # Init
918             # We want to preserve already set attributes if the namespace
919             # is passed in.
920             #
921             # This is because one may want to load configs from a file
922             # into a namespace and then use the same namespace for parsing
923             # configs from command line.
924             #
925 189 100       3234 $self->namespace->set_attr($spec->{dest}, undef)
926             unless defined($self->namespace->get_attr($spec->{dest}));
927              
928 189         3043 my $error = $spec->{action}->apply(
929             $spec,
930             $self->namespace,
931             $options->{ $dest2spec->{$spec->{dest}} },
932             $spec->{name},
933             );
934              
935 189 100       445 _croak $self->error_prefix . $error if $error;
936             }
937              
938 91         127 return '';
939             }
940              
941             sub _post_apply_processing {
942 91     91   92 my $self = shift;
943 91         130 my ($specs, $options, $dest2spec) = @_;
944              
945             #
946             # required is checked after applying actions
947             # This is because required checking is bypassed if help is on
948             #
949 91         160 for my $spec (@$specs) {
950 186         3025 my $v = $self->namespace->get_attr($spec->{dest});
951              
952             # required
953 186 100 100     1002 if ( $spec->{required} && not $self->namespace->get_attr('help') ) {
954 15         16 my $has_v;
955 15 100       45 if ($spec->{type} == TYPE_ARRAY) {
    50          
956 6         12 $has_v = @$v;
957             } elsif ($spec->{type} == TYPE_PAIR) {
958 0         0 $has_v = scalar(keys %$v);
959             } else {
960 9         11 $has_v = defined $v;
961             }
962              
963 15 100       94 _croak $self->error_prefix . sprintf("Option %s is required\n", $spec->{dest}) unless $has_v;
964             }
965             }
966             }
967              
968             # interface
969             sub print_usage {
970 3     3 0 10 my $self = shift;
971              
972 3         19 my $usage = $self->format_usage;
973              
974 3         2347 print STDERR $_, "\n" for @$usage;
975             }
976              
977             # interface
978             sub print_command_usage {
979 1     1 0 3 my $self = shift;
980 1   33     43 my $command = shift
981             || $self->namespace->get_attr('help_command')
982             || $self->namespace->get_attr('current_command'); # running help command
983              
984 1         15 my $usage = $self->format_command_usage($command);
985 1 50       5 if ($usage) {
986 1         681 print STDERR $_, "\n" for @$usage;
987             } else {
988 0         0 print STDERR
989             $self->error_prefix,
990             sprintf('No help for %s. See help', $self->namespace->get_attr('help_command')),
991             "\n";
992             }
993             }
994              
995             # Interface
996             sub format_usage {
997 5     5 0 11 my $self = shift;
998              
999 5 50       54 $self->_sort_specs_by_groups() unless $self->{-groups};
1000              
1001 5         11 my $old_wrap_columns = $Text::Wrap::columns;
1002              
1003 5         6 my @usage;
1004              
1005 5         39 my $aliases = $self->aliases;
1006 5         30 my $prog = $self->prog;
1007 5 100       25 $prog .= ' (' . join(', ', @$aliases) . ')' if @$aliases;
1008 5         87 push @usage, wrap('', '', $prog. ': ' . $self->help);
1009              
1010 5         1266 my ($help, $option_string) = $self->_format_group_usage();
1011 5         8 $Text::Wrap::columns = 80;
1012              
1013 5         26 my $header = sprintf(
1014             'usage: %s %s',
1015             $self->prog, $option_string
1016             );
1017              
1018 5         16 push @usage, wrap('', '', $header);
1019              
1020 5 100       989 if ($self->description) {
1021 2         21 my @lines = split("\n", $self->description);
1022              
1023 2         5 my @paragraphs;
1024              
1025 2         2 my $para = '';
1026 2         4 for my $line (@lines) {
1027 32 100       56 if ($line =~ /^\s*$/) {
1028 2         4 push @paragraphs, $para;
1029 2         5 $para = '';
1030             } else {
1031 30 100       50 $para .= ( $para ? ' ' : '' ) . $line;
1032             }
1033             }
1034              
1035 2         2 push @paragraphs, $para;
1036 2         4 for (@paragraphs) {
1037 4         1636 push @usage, '';
1038 4         8 push @usage, wrap('', '', $_);
1039             }
1040             }
1041              
1042 5         793 push @usage, '';
1043              
1044 5         15 push @usage, @$help;
1045              
1046 5 100       20 if (exists $self->{-subparsers}) {
1047 3         6 push @usage, '';
1048 3         14 push @usage, wrap('', '', $self->{-subparsers}{-title});
1049 3 100       554 push @usage, wrap('', '', $self->{-subparsers}{-description}) if $self->{-subparsers}{-description};
1050              
1051 3         92 my $max = 12;
1052              
1053 3         4 for my $command ( keys %{$self->{-subparsers}{-parsers}} ) {
  3         41  
1054 6         8 my $len = length($command);
1055 6 50       14 $max = $len if $len > $max;
1056             }
1057              
1058 3         6 $max *= -1;
1059              
1060 3         5 for my $command ( sort keys %{$self->{-subparsers}{-parsers}} ) {
  3         16  
1061 6         22 my $parser = $self->{-subparsers}{-parsers}{$command};
1062 6         16 my $tab_head = ' ' x ( -1 * $max + 2 );
1063              
1064 6         34 my @desc = split("\n", wrap('', '', $parser->help));
1065 6   50     770 my $desc = (shift @desc) || '';
1066 6         12 $_ = $tab_head . $_ for @desc;
1067 6         37 push @usage, sprintf(" %${max}s %s", $command, join("\n", $desc, @desc));
1068             }
1069             }
1070              
1071 5 100       51 push @usage, '', wrap('', '', $self->epilog) if $self->epilog;
1072              
1073 5         189 $Text::Wrap::columns = $old_wrap_columns; # restore to original
1074              
1075 5         27 return \@usage;
1076             }
1077              
1078             sub format_command_usage {
1079 2     2 0 12 my $self = shift;
1080 2         3 my $alias = shift;
1081              
1082 2         7 my $subp = $self->_get_subcommand_parser($alias);
1083 2 50       6 return '' unless $subp;
1084              
1085 2         6 return $subp->format_usage();
1086             }
1087              
1088             # FIXME: Maybe we should remove this grouping thing
1089             sub _sort_specs_by_groups {
1090 5     5   7 my $self = shift;
1091              
1092 5         16 my $specs = $self->{-option_specs};
1093              
1094 5         10 for my $dest ( keys %{ $specs } ) {
  5         42  
1095 15         16 for my $group ( @{ $specs->{$dest}{groups} } ) {
  15         36  
1096 15         12 push @{ $self->{-groups}{$group}{-option} }, $specs->{$dest};
  15         71  
1097             }
1098             }
1099              
1100 5         15 $specs = $self->{-position_specs};
1101              
1102 5         9 for my $dest ( keys %{ $specs } ) {
  5         12  
1103 2         1 for my $group ( @{ $specs->{$dest}{groups} } ) {
  2         3  
1104 2         2 push @{ $self->{-groups}{$group}{-position} }, $specs->{$dest};
  2         8  
1105             }
1106             }
1107             }
1108              
1109             sub _format_group_usage {
1110 5     5   11 my $self = shift;
1111 5         22 my $group = '';
1112             # my $group = shift || '';
1113              
1114 5 50       32 unless ($self->{-groups}) {
1115 0         0 $self->_sort_specs_by_groups();
1116             }
1117              
1118 5         8 my $old_wrap_columns = $Text::Wrap::columns;
1119 5         21 $Text::Wrap::columns = 80;
1120              
1121 5         12 my @usage;
1122              
1123 17         35 my @option_specs = sort {
1124 5 50       41 $a->{position} <=> $b->{position}
1125 5         12 } @{ $self->{-groups}{$group}{-option} || [] };
1126              
1127 15         77 my @flag_items = map {
1128 5         10 ($_->{required} ? '' : '[')
1129 15 100       30 . join('|', @{$_->{flags}})
    100          
1130             . ($_->{required} ? '' : ']')
1131             } @option_specs;
1132              
1133 1         3 my @position_specs = sort {
1134 5 100       57 $a->{position} <=> $b->{position}
1135 5         125 } @{ $self->{-groups}{$group}{-position} || [] };
1136              
1137 2 50       11 my @position_items = map {
    50          
1138 5         12 ($_->{required} ? '' : '[')
1139             . $_->{metavar}
1140             . ($_->{required} ? '' : ']')
1141             } @position_specs;
1142              
1143 5 100       38 my @subcommand_items = ('', '[]') if exists $self->{-subparsers};
1144              
1145 5 50       13 if ($group) {
1146 0   0     0 push @usage, wrap('', '', $group . ': ' . ($self->{-group_description}{$group} || '') );
1147             }
1148              
1149 5 100       13 if (@position_specs) {
1150 1         2 push @usage, 'positional arguments:';
1151 1         2 push @usage, @{ $self->_format_usage_by_spec(\@position_specs) };
  1         4  
1152             }
1153              
1154 5 50       14 if (@option_specs) {
1155 5         19 push @usage, 'optional arguments:';
1156 5         6 push @usage, @{ $self->_format_usage_by_spec(\@option_specs) };
  5         18  
1157             }
1158              
1159 5         10 $Text::Wrap::columns = $old_wrap_columns; # restore to original
1160              
1161 5         48 return ( \@usage, join(' ', @position_items, @flag_items, @subcommand_items) ) ;
1162             }
1163              
1164             sub _format_usage_by_spec {
1165 6     6   87 my $self = shift;
1166 6         8 my $specs = shift;
1167              
1168 6 50       17 return unless $specs;
1169              
1170 6         6 my @usage;
1171 6         8 my $max = 10;
1172 6         7 my @item_help;
1173              
1174 6         13 for my $spec ( @$specs ) {
1175 17         68 my $item = sprintf(
1176             "%s %s",
1177 17         15 join(', ', @{$spec->{flags}}),
1178             $spec->{metavar},
1179             );
1180 17         20 my $len = length($item);
1181 17 100       37 $max = $len if $len > $max;
1182              
1183             # generate default string
1184 17         24 my $default = '';
1185 17         18 my $values = [];
1186              
1187 17 100       38 if (defined $spec->{default}) {
1188 3 100       14 if (ref $spec->{default} eq 'HASH') {
    50          
1189 1         2 while (my ($k, $v) = each %{$spec->{default}}) {
  3         8  
1190 2         4 push @$values, "$k=$v";
1191             }
1192             } elsif (ref $spec->{default} eq "ARRAY") {
1193 2         5 $values = $spec->{default};
1194             } else {
1195 0         0 $values = [ $spec->{default} ];
1196             }
1197             }
1198              
1199 17 100       35 if (@$values) {
1200 3         10 $default = 'Default: ' . join(', ', @$values);
1201             }
1202              
1203             # generate choice string
1204 17         11 my $choices;
1205 17         57 my $case = '';
1206              
1207 17 50 33     56 if ($spec->{choices} && ref $spec->{choices} ne 'CODE') {
    50          
1208 0         0 $choices = $spec->{choices};
1209 0         0 $case = 'case sensitive';
1210             } elsif ($spec->{choices_i}) {
1211 0         0 $choices = $spec->{choices_i};
1212 0         0 $case = 'case insensitive';
1213             } else {
1214 17         30 $choices = undef;
1215             }
1216              
1217 17         20 my $choice_str = '';
1218 17 50       29 if ($choices) {
1219 0         0 $choice_str = 'Choices: [' . join(', ', @$choices) . '], ' . $case . "\n";
1220             }
1221              
1222 17 100 66     126 push @item_help, [
1223             $item,
1224             ($spec->{required} ? ' ' : '?'),
1225             join("\n", ($spec->{help} || 'This is option ' . $spec->{dest}), $choice_str . $default),
1226             ];
1227             }
1228              
1229 6         18 $max *= -1;
1230 6         14 my $format = " %${max}s %s %s";
1231 6         8 $Text::Wrap::columns = 60;
1232 6         16 for my $ih (@item_help) {
1233 17         23 my $item_len = length($ih->[0]);
1234             # The prefixed whitespace in subsequent lines in the wrapped
1235             # help string
1236 17         38 my $sub_tab = " " x (-1 * $max + 4 + 4 + 2);
1237 17         44 my @help = split("\n", wrap('', '', $ih->[2]));
1238              
1239 17   50     2199 my $help = (shift @help) || '' ; # head
1240 17         32 $_ = $sub_tab . $_ for @help; # tail
1241              
1242 17         82 push @usage, sprintf($format, $ih->[0], $ih->[1], join("\n", $help, @help));
1243             }
1244              
1245 6         27 return \@usage;
1246             }
1247              
1248             # translate option spec to the one accepted by
1249             # Getopt::Long::GetOptions
1250             sub _get_option_spec {
1251 158     158   167 my $self = shift;
1252 158         142 my $spec = shift;
1253              
1254 158         132 my @flags = @{ $spec->{flags} };
  158         367  
1255 158         824 $_ =~ s/^-+// for @flags;
1256 158         282 my $name = join('|', @flags);
1257 158         148 my $type = 's';
1258 158         145 my $desttype = '';
1259              
1260 158         140 my $optional_flag = '='; # not optional
1261              
1262 158 100       620 if ($spec->{type} == TYPE_SCALAR) {
    100          
    100          
    50          
    100          
    50          
1263 48         49 $desttype = '@';
1264             } elsif ($spec->{type} == TYPE_ARRAY) {
1265 10         11 $desttype = '@';
1266             } elsif ($spec->{type} == TYPE_PAIR) {
1267 4         7 $desttype = '@';
1268             } elsif ($spec->{type} == TYPE_UNDEF) {
1269 0         0 $optional_flag = ':';
1270             } elsif ($spec->{type} == TYPE_BOOL) {
1271 92         122 $type = '';
1272 92         92 $optional_flag = '';
1273 92         120 $desttype = '';
1274             } elsif ($spec->{type} == TYPE_COUNT) {
1275             # pass
1276 4         2 $type = '';
1277 4         4 $optional_flag = '';
1278 4         4 $desttype = '+';
1279             } else {
1280             # pass
1281             # should never be here
1282 0   0     0 _croak $self->error_prefix . 'Unknown type:' . ($spec->{type} || 'undef');
1283             }
1284              
1285 158         142 my $repeat = '';
1286              
1287 158         225 my $opt = join('', $name, $optional_flag, $type, $repeat, $desttype);
1288              
1289 158         447 return $opt;
1290             }
1291              
1292             1;
1293              
1294             __END__