File Coverage

blib/lib/Getopt/Janus/CLI.pm
Criterion Covered Total %
statement 64 103 62.1
branch 26 64 40.6
condition 9 24 37.5
subroutine 8 10 80.0
pod 0 6 0.0
total 107 207 51.6


line stmt bran cond sub pod time code
1            
2             require 5;
3             package Getopt::Janus::CLI;
4             # Get command-line interface options (yup, from @ARGV)
5            
6             @ISA = ('Getopt::Janus::SessionBase');
7             $VERSION = '1.03';
8 4     4   1314 use strict;
  4         8  
  4         148  
9 4     4   605 use Getopt::Janus (); # makes sure Getopt::Janus::DEBUG is defined
  4         47  
  4         134  
10 4     4   81 BEGIN { *DEBUG = \&Getopt::Janus::DEBUG }
11 4     4   2943 use Getopt::Janus::SessionBase;
  4         11  
  4         50  
12            
13             Getopt::Janus::DEBUG and print "Revving up ", __PACKAGE__, "\n";
14            
15 0     0 0 0 sub open_new_files { } # block it happening
16            
17             # TODO: make -h / --help produce help/longhelp (latter with license)
18            
19             # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
20            
21 2     2 0 5 sub review_result { } # no need for this all
22            
23             sub get_option_values {
24 2     2 0 4 my $self = shift;
25            
26 2 50       10 if($^O =~ m/Win32/) {
27 0   0     0 while( @ARGV and !length $ARGV[-1] ) { pop @ARGV }
  0         0  
28             }
29            
30 2         2 my $run_flag = 1;
31 2         8 my @args = @ARGV;
32 2         3 my %unknowns;
33            
34             my @values;
35 2         9 $self->parse_values(\@values, \@args, \%unknowns, \$run_flag);
36            
37 2 50       5 if( $run_flag ) {
38 2         3 DEBUG and print "parse_values has run_flag on, with values @values\n";
39 2         16 $self->consider_values( \@values );
40             } else {
41 0         0 DEBUG and print "parse_values has run_flag off\n values [@values]",
42             "\n unknowns [@{[sort keys %unknowns]}]\n args [@args]\n";
43 0         0 $self->complain_about( \@args, \%unknowns );
44 0         0 exit 1;
45             }
46 2         8 return;
47             }
48            
49             # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
50            
51             sub parse_values {
52 2     2 0 5 my($self, $values, $args, $unknowns, $run_flag_s) = (@_);
53 2         5 my($long, $short) = @$self{ 'long', 'short' };
54            
55 2         7 my $dummy = {'type' => 'yes_no', "_HACK_", 1};
56            
57 2         3 local $_;
58 2         9 while(@$args) {
59 5         6 $_ = $args->[0];
60 5 50       14 last if $_ eq '-'; # not a switch at all
61 5 100       11 shift(@$args), last if $_ eq '--'; # switch meaning 'end of switches'
62            
63 4 100 100     40 if( m/^-([_0-9a-zA-Z])$/s or m/^--?([-_0-9a-zA-Z]{2,})$/s ) { # -x or --xax
    100          
    50          
64             # And tolerate -xax
65 2 50 66     27 if(not( $short->{$1} || $long->{$1} )) {
    50 66        
      0        
      33        
66 0         0 ++$unknowns->{$1};
67 0         0 DEBUG and print "Unknown option $1\n";
68 0         0 shift @$args;
69             } elsif(
70             'yes_no' eq ( $short->{$1} || $long->{$1} )->{'type'}
71             or 'HELP' eq ( $short->{$1} || $long->{$1} )->{'type'}
72             ) {
73 2         5 push @$values, $1 => 1; # just note it as a true value and move on
74 2         7 shift @$args;
75             } else {
76             # It's a nonboolean value -- so snare the value and re-cycle
77             # it as a -x=foo or --xax=foo for the next pass
78 0 0 0     0 push @$args, '' if @$args == 1 and $^O =~ m/Win32/;
79 0         0 $args->[0] .= '=' . splice(@$args,1,1);
80             }
81            
82             } elsif( m/^-([_0-9a-zA-Z])=(.*?)$/s ) { # -x=foo
83 1 50       4 unless( exists $short->{$1} ) {
84 0         0 ++$unknowns->{$1};
85             } else {
86 1         3 push @$values, $1 => $2;
87             }
88 1         4 shift(@$args);
89            
90             } elsif( m/^--?([-_0-9a-zA-Z]{2,})=(.*?)$/s ) { # --xax=foo
91             # and tolerate -xax=foo
92 1 50       5 unless( exists $long->{$1} ) {
93 0         0 ++$unknowns->{$1};
94             } else {
95 1         4 push @$values, $1 => $2;
96             }
97 1         3 shift(@$args);
98            
99             } else {
100 0         0 $$run_flag_s = 0;
101 0         0 last; # leaving things unprocessed
102             }
103             }
104 2 50 33     14 $$run_flag_s = 0 if keys %$unknowns or @$args;
105 2         7 return;
106             }
107            
108             # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
109            
110             sub complain_about {
111 0     0 0 0 my( $self, $args, $unknowns ) = @_;
112            
113 0 0       0 if( keys %$unknowns ) {
114 0         0 my @them = sort keys %$unknowns;
115 0 0       0 foreach (@them) { s/^(.)$/-$1/s or s/^(.+)$/--$1/s } # add the prefixes
  0         0  
116 0         0 print "Unknown options that you used: [@them]\n\n"
117             }
118 0 0       0 print "Arguments left unprocessed: [@$args]\n\n" if @$args;
119 0         0 print $self->short_help_message;
120 0         0 return;
121             }
122            
123             # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
124            
125             sub consider_values {
126 2     2 0 5 my( $self, $values ) = @_;
127 2         4 my($long, $short) = @$self{ 'long', 'short' };
128            
129 2         3 my %seen;
130 2         7 my($option, $key, $value, $type, $oldval);
131 2         3 DEBUG and print "Values: @$values\n";
132 2         7 while( @$values ) {
133 4         7 $key = $values->[0];
134 4 100       11 $option = ( (length($key) == 1) ? $short : $long )->{$key};
135 4         15 ++$seen{$option};
136 4         6 $type = $option->{'type'};
137 4         6 my $slot_r = $option->{'slot'};
138 4         11 $oldval = $$slot_r;
139 4         8 $$slot_r = $values->[1];
140            
141 4         6 splice @$values,0,2;
142            
143 4         4 DEBUG and print "Option \"$key\" = \"$$slot_r\"\n";
144            
145 4 50       16 if( $type eq 'HELP' ) {
146 0 0       0 print '', (length($key) == 1)
147             ? $self->short_help_message : $self->long_help_message;
148 0         0 exit;
149             }
150            
151 4 50       13 if( $seen{$option} > 1 ) {
152 0         0 print "Duplicate setting for option ",
153             join('/', grep defined($_), @$option{'short', 'long'}),
154             ": \"$oldval\" and \"$$slot_r\".\n";
155 0         0 exit;
156             }
157            
158 4 100       19 if( $type eq 'yes_no' ) {
    50          
    50          
    50          
    50          
159 2         5 DEBUG > 1 and print "(Type $type needs no checking.)\n";
160            
161             } elsif( $type eq 'string' ) {
162 0         0 DEBUG > 1 and print "(Type $type needs no checking.)\n";
163            
164             } elsif( $type eq 'new_file' ) {
165 0 0       0 if(!length $$slot_r) {
166             #die "Option $key can't take \"\" as a value" unless length $$slot_r;
167             # No, it's okay to set this to null.
168             } else {
169             # Any further checking?
170             }
171            
172             } elsif( $type eq 'file' ) {
173 0 0       0 if(!length $$slot_r) {
174             #die "Option $key can't take \"\" as a value" unless length $$slot_r;
175             # No, it's okay to set this to null.
176             } else {
177 0 0       0 -e $$slot_r or die "Setting to a non-existent file in $key=$$slot_r\n";
178 0 0       0 -d _ and die "Setting to a directory in $key=$$slot_r\n";
179 0 0       0 -f _ or die "Setting to a non-file in $key=$$slot_r\n";
180 0 0       0 -r _ or die "Setting to an unreadable file in $key=$$slot_r\n";
181 0         0 DEBUG > 1 and print "File $$slot_r checks out.\n";
182             }
183            
184             } elsif( $type eq 'choose' ) {
185 2 50       4 if( grep $_ eq $$slot_r, @{$option->{'from'}} ) {
  2         15  
186 2         7 DEBUG > 1 and print "Choice $$slot_r checks out.\n";
187             } else {
188 0         0 die(
189             "Option $key=$$slot_r needs to be one of: [" .
190 0         0 join( '|', @{$option->{'from'}}) . "]\n"
191             );
192             }
193            
194             } else {
195 0         0 DEBUG and print "I don't know how to check an option of type $type\n";
196             }
197            
198             }
199            
200            
201            
202 2         6 return;
203             }
204            
205             # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
206             1;
207            
208             __END__