File Coverage

blib/lib/Pod/Usage.pm
Criterion Covered Total %
statement 170 197 86.2
branch 105 148 70.9
condition 38 71 53.5
subroutine 13 16 81.2
pod 1 8 12.5
total 327 440 74.3


line stmt bran cond sub pod time code
1             #############################################################################
2             # Pod/Usage.pm -- print usage messages for the running script.
3             #
4             # Copyright (c) 1996-2000 by Bradford Appleton. All rights reserved.
5             # Copyright (c) 2001-2016 by Marek Rouchal.
6             # This file is part of "Pod-Usage". Pod-Usage is free software;
7             # you can redistribute it and/or modify it under the same terms
8             # as Perl itself.
9             #############################################################################
10              
11             package Pod::Usage;
12              
13 28     28   3336419 use strict;
  28         76  
  28         1685  
14             require 5.006; ## requires this Perl version or later
15              
16 28     28   199 use Carp;
  28         61  
  28         2645  
17 28     28   189 use Config;
  28         55  
  28         2147  
18 28     28   180 use Exporter qw(import);
  28         61  
  28         1114  
19 28     28   168 use File::Spec;
  28         32  
  28         3992  
20              
21             our $VERSION = '2.05';
22              
23             our @EXPORT = qw(&pod2usage);
24             our @ISA;
25             BEGIN {
26 28   50 28   279 $Pod::Usage::Formatter ||= 'Pod::Text';
27 28         2156 eval "require $Pod::Usage::Formatter";
28 28 50       2392293 die $@ if $@;
29 28         124709 @ISA = ( $Pod::Usage::Formatter );
30             }
31              
32             our $MAX_HEADING_LEVEL = 3;
33              
34             ##---------------------------------------------------------------------------
35              
36             ##---------------------------------
37             ## Function definitions begin here
38             ##---------------------------------
39              
40             sub pod2usage {
41 26     26 0 145484527 local($_) = shift;
42 26         657 my %opts;
43             ## Collect arguments
44 26 100       1083 if (@_ > 0) {
    100          
    100          
    100          
45             ## Too many arguments - assume that this is a hash and
46             ## the user forgot to pass a reference to it.
47 19         740 %opts = ($_, @_);
48             }
49             elsif (!defined $_) {
50 1         27 $_ = '';
51             }
52             elsif (ref $_) {
53             ## User passed a ref to a hash
54 3 50       46 %opts = %{$_} if (ref($_) eq 'HASH');
  3         101  
55             }
56             elsif (/^[-+]?\d+$/) {
57             ## User passed in the exit value to use
58 2         40 $opts{'-exitval'} = $_;
59             }
60             else {
61             ## User passed in a message to print before issuing usage.
62 1 50       46 $_ and $opts{'-message'} = $_;
63             }
64              
65             ## Need this for backward compatibility since we formerly used
66             ## options that were all uppercase words rather than ones that
67             ## looked like Unix command-line options.
68             ## to be uppercase keywords)
69             %opts = map {
70 26         626 my ($key, $val) = ($_, $opts{$_});
  75         455  
71 75         1234 $key =~ s/^(?=\w)/-/;
72 75 50       1214 $key =~ /^-msg/i and $key = '-message';
73 75 100       1363 $key =~ /^-exit/i and $key = '-exitval';
74 75         795 lc($key) => $val;
75             } (keys %opts);
76              
77             ## Now determine default -exitval and -verbose values to use
78 26 100 100     1761 if ((! defined $opts{'-exitval'}) && (! defined $opts{'-verbose'})) {
    100          
    100          
79 2         58 $opts{'-exitval'} = 2;
80 2         47 $opts{'-verbose'} = 0;
81             }
82             elsif (! defined $opts{'-exitval'}) {
83 3 50       177 $opts{'-exitval'} = ($opts{'-verbose'} > 0) ? 1 : 2;
84             }
85             elsif (! defined $opts{'-verbose'}) {
86             $opts{'-verbose'} = (lc($opts{'-exitval'}) eq 'noexit' ||
87 2   66     79 $opts{'-exitval'} < 2);
88             }
89              
90             ## Default the output file
91             $opts{'-output'} = (lc($opts{'-exitval'}) eq 'noexit' ||
92             $opts{'-exitval'} < 2) ? \*STDOUT : \*STDERR
93 26 100 100     1868 unless (defined $opts{'-output'});
    100          
94             ## Default the input file
95 26 100       626 $opts{'-input'} = $0 unless (defined $opts{'-input'});
96              
97             ## Look up input file in path if it doesn't exist.
98 26 100 100     2184 unless ((ref $opts{'-input'}) || (-e $opts{'-input'})) {
99 1         57 my $basename = $opts{'-input'};
100 1 50 33     120 my $pathsep = ($^O =~ /^(?:dos|os2|MSWin32)$/i) ? ';'
    50          
101             : (($^O eq 'MacOS' || $^O eq 'VMS') ? ',' : ':');
102 1   0     16 my $pathspec = $opts{'-pathlist'} || $ENV{PATH} || $ENV{PERL5LIB};
103              
104 1 50       15 my @paths = (ref $pathspec) ? @$pathspec : split($pathsep, $pathspec);
105 1         47 for my $dirname (@paths) {
106 1 50       90 $_ = length($dirname) ? File::Spec->catfile($dirname, $basename) : $basename;
107 1 50 33     133 last if (-e $_) && ($opts{'-input'} = $_);
108             }
109             }
110              
111             ## Now create a pod reader and constrain it to the desired sections.
112 26         2355 my $parser = Pod::Usage->new(USAGE_OPTIONS => \%opts);
113 26 100 66     736 if ($opts{'-verbose'} == 0) {
    100          
    100          
    50          
114 7         219 $parser->select('(?:SYNOPSIS|USAGE)\s*');
115             }
116             elsif ($opts{'-verbose'} == 1) {
117 4         89 my $opt_re = '(?i)' .
118             '(?:OPTIONS|ARGUMENTS)' .
119             '(?:\s*(?:AND|\/)\s*(?:OPTIONS|ARGUMENTS))?';
120 4         77 $parser->select( '(?:SYNOPSIS|USAGE)\s*', $opt_re, "DESCRIPTION/$opt_re" );
121             }
122             elsif ($opts{'-verbose'} >= 2 && $opts{'-verbose'} != 99) {
123 4         60 $parser->select('.*');
124             }
125             elsif ($opts{'-verbose'} == 99) {
126 11         119 my $sections = $opts{'-sections'};
127 11 100       269 $parser->select( (ref $sections) ? @$sections : $sections );
128 11         66 $opts{'-verbose'} = 1;
129             }
130              
131             ## Check for perldoc
132             my $progpath = $opts{'-perldoc'} ? $opts{'-perldoc'} :
133             File::Spec->catfile($Config{scriptdirexp} || $Config{scriptdir},
134 26 50 33     11677 'perldoc');
135              
136 26         473 my $version = sprintf("%vd",$^V);
137 26 50 33     2520 if ($Config{versiononly} and $Config{startperl} =~ /\Q$version\E$/ ) {
138 0         0 $progpath .= $version;
139             }
140 26 50       1038 $opts{'-noperldoc'} = 1 unless -e $progpath;
141              
142             ## Now translate the pod document and then exit with the desired status
143 26 100 100     733 if ( !$opts{'-noperldoc'}
      100        
      100        
144             and $opts{'-verbose'} >= 2
145             and !ref($opts{'-input'})
146             and $opts{'-output'} == \*STDOUT )
147             {
148             ## spit out the entire PODs. Might as well invoke perldoc
149 2 100       21 print { $opts{'-output'} } ($opts{'-message'}, "\n") if($opts{'-message'});
  1         10  
150 2 50 33     71 if(defined $opts{-input} && $opts{-input} =~ /^\s*(\S.*?)\s*$/) {
151             # the perldocs back to 5.005 should all have -F
152             # without -F there are warnings in -T scripts
153 2         18 my $f = $1;
154 2         9 my @perldoc_cmd = ($progpath);
155 2 100       9 if ($opts{'-perldocopt'}) {
156 1         5 $opts{'-perldocopt'} =~ s/^\s+|\s+$//g;
157 1         4 push @perldoc_cmd, split(/\s+/, $opts{'-perldocopt'});
158             }
159 2         31 push @perldoc_cmd, ('-F', $f);
160 2 50       8 unshift @perldoc_cmd, $opts{'-perlcmd'} if $opts{'-perlcmd'};
161 2         1521567 system(@perldoc_cmd);
162             # RT16091: fall back to more if perldoc failed
163 2 50       146 if($?) {
164             # RT131844: prefer PAGER env
165 0   0     0 my $pager = $ENV{PAGER} || $Config{pager};
166 0 0 0     0 if(defined($pager) && length($pager)) {
167 0 0       0 my $cmd = $pager . ' ' . ($^O =~ /win/i ? qq("$f") : quotemeta($f));
168 0         0 system($cmd);
169             } else {
170             # the most humble fallback; should work (at least) on *nix and Win
171 0         0 system('more', $f);
172             }
173             }
174             } else {
175 0         0 croak "Unspecified input file or insecure argument.\n";
176             }
177             }
178             else {
179 24         723 $parser->parse_from_file($opts{'-input'}, $opts{'-output'});
180             }
181              
182 25 100       13697 exit($opts{'-exitval'}) unless (lc($opts{'-exitval'}) eq 'noexit');
183             }
184              
185             ##---------------------------------------------------------------------------
186              
187             ##-------------------------------
188             ## Method definitions begin here
189             ##-------------------------------
190              
191             sub new {
192 26     26 1 551 my $this = shift;
193 26   33     784 my $class = ref($this) || $this;
194 26         2204 my %params = @_;
195 26         8675 my $self = {%params};
196 26         373 bless $self, $class;
197 26 100       6636 if ($self->can('initialize')) {
198 2         125 $self->initialize();
199             } else {
200             # pass through options to Pod::Text
201 24         3324 my %opts;
202 24         143 for (qw(alt code indent loose margin quotes sentence stderr utf8 width)) {
203 240         630 my $val = $params{USAGE_OPTIONS}{"-$_"};
204 240 50       655 $opts{$_} = $val if defined $val;
205             }
206 24         1591 $self = $self->SUPER::new(%opts);
207 24         22269 %$self = (%$self, %params);
208             }
209 26         211 return $self;
210             }
211              
212             # This subroutine was copied in whole-cloth from Pod::Select 1.60 in order to
213             # allow the ejection of Pod::Select from the core without breaking Pod::Usage.
214             # -- rjbs, 2013-03-18
215             sub _compile_section_spec {
216 38     38   278 my ($section_spec) = @_;
217 38         100 my (@regexs, $negated);
218              
219             ## Compile the spec into a list of regexs
220 38         158 local $_ = $section_spec;
221 38         383 s{\\\\}{\001}g; ## handle escaped backward slashes
222 38         302 s{\\/}{\002}g; ## handle escaped forward slashes
223              
224             ## Parse the regexs for the heading titles
225 38         307 @regexs = split(/\//, $_, $MAX_HEADING_LEVEL);
226              
227             ## Set default regex for ommitted levels
228 38         195 for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
229 114 100 66     1192 $regexs[$i] = '.*' unless ((defined $regexs[$i])
230             && (length $regexs[$i]));
231             }
232             ## Modify the regexs as needed and validate their syntax
233 38         88 my $bad_regexs = 0;
234 38         115 for (@regexs) {
235 114 50       367 $_ .= '.+' if ($_ eq '!');
236 114         542 s{\001}{\\\\}g; ## restore escaped backward slashes
237 114         303 s{\002}{\\/}g; ## restore escaped forward slashes
238 114         494 $negated = s/^\!//; ## check for negation
239 114         26090 eval "m{$_}"; ## check regex syntax
240 114 100       506 if ($@) {
241 1         4 ++$bad_regexs;
242 1         1328 carp qq{Bad regular expression /$_/ in "$section_spec": $@\n};
243             }
244             else {
245             ## Add the forward and rear anchors (and put the negator back)
246 113 50       467 $_ = '^' . $_ unless (/^\^/);
247 113 50       344 $_ = $_ . '$' unless (/\$$/);
248 113 100       392 $_ = '!' . $_ if ($negated);
249             }
250             }
251 38 100       303 return (! $bad_regexs) ? [ @regexs ] : undef;
252             }
253              
254             sub select {
255 26     26 0 243 my ($self, @sections) = @_;
256 26 50       1489 if ($ISA[0]->can('select')) {
257 0         0 $self->SUPER::select(@sections);
258             } else {
259             # we're using Pod::Simple - need to mimic the behavior of Pod::Select
260 26 50       163 my $add = ($sections[0] eq '+') ? shift(@sections) : '';
261             ## Reset the set of sections to use
262 26 50       103 unless (@sections) {
263 0 0       0 delete $self->{USAGE_SELECT} unless ($add);
264 0         0 return;
265             }
266             $self->{USAGE_SELECT} = []
267 26 50 33     326 unless ($add && $self->{USAGE_SELECT});
268 26         99 my $sref = $self->{USAGE_SELECT};
269             ## Compile each spec
270 26         519 for my $spec (@sections) {
271 38         205 my $cs = _compile_section_spec($spec);
272 38 100       147 if ( defined $cs ) {
273             ## Store them in our sections array
274 37         173 push(@$sref, $cs);
275             } else {
276 1         279 carp qq{Ignoring section spec "$spec"!\n};
277             }
278             }
279             }
280             }
281              
282             # Override Pod::Text->seq_i to return just "arg", not "*arg*".
283 0     0 0 0 sub seq_i { return $_[1] }
284             # Override Pod::Text->cmd_i to return just "arg", not "*arg*".
285             # newer version based on Pod::Simple
286             sub cmd_i {
287 31     31 0 755 my $self = shift;
288             # RT121489: highlighting should be there with Termcap
289 31 50       364 return $self->SUPER::cmd_i(@_) if $self->isa('Pod::Text::Termcap');
290 31         97 return $_[1];
291             }
292              
293             # This overrides the Pod::Text method to do something very akin to what
294             # Pod::Select did as well as the work done below by preprocess_paragraph.
295             # Note that the below is very, very specific to Pod::Text and Pod::Simple.
296             sub _handle_element_end {
297 712     712   311377 my ($self, $element) = @_;
298 712 100 66     3930 if ($element eq 'head1') {
    100          
299 91         577 $self->{USAGE_HEADINGS} = [ $$self{PENDING}[-1][1] ];
300 91 100       399 if ($self->{USAGE_OPTIONS}->{-verbose} < 2) {
301 84         530 $$self{PENDING}[-1][1] =~ s/^\s*SYNOPSIS\s*$/USAGE/;
302             }
303             } elsif ($element =~ /^head(\d+)$/ && $1) { # avoid 0
304 52         150 my $idx = $1 - 1;
305 52 50       310 $self->{USAGE_HEADINGS} = [] unless($self->{USAGE_HEADINGS});
306 52         172 $self->{USAGE_HEADINGS}->[$idx] = $$self{PENDING}[-1][1];
307             # we have to get rid of the lower headings
308 52         98 splice(@{$self->{USAGE_HEADINGS}},$idx+1);
  52         161  
309             }
310 712 100       2077 if ($element =~ /^head\d+$/) {
311 143         275 $$self{USAGE_SKIPPING} = 1;
312 143 50 33     1787 if (!$$self{USAGE_SELECT} || !@{ $$self{USAGE_SELECT} }) {
313 0         0 $$self{USAGE_SKIPPING} = 0;
314             } else {
315 143         200 my @headings = @{$$self{USAGE_HEADINGS}};
  143         371  
316 143         211 for my $section_spec ( @{$$self{USAGE_SELECT}} ) {
  143         2360  
317 206         307 my $match = 1;
318 206         939 for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
319 308 100       765 $headings[$i] = '' unless defined $headings[$i];
320 308         555 my $regex = $section_spec->[$i];
321 308         1818 my $negated = ($regex =~ s/^\!//);
322 308 100       11981 $match &= ($negated ? ($headings[$i] !~ /${regex}/)
323             : ($headings[$i] =~ /${regex}/));
324 308 100       1220 last unless ($match);
325             } # end heading levels
326 206 100       658 if ($match) {
327 40         95 $$self{USAGE_SKIPPING} = 0;
328 40         555 last;
329             }
330             } # end sections
331             }
332              
333             # Try to do some lowercasing instead of all-caps in headings, and use
334             # a colon to end all headings.
335 143 100       664 if($self->{USAGE_OPTIONS}->{-verbose} < 2) {
336 136         356 local $_ = $$self{PENDING}[-1][1];
337 136 100       754 s{([A-Z])([A-Z]+)}{((length($2) > 2) ? $1 : lc($1)) . lc($2)}ge;
  78         584  
338 136 50       1192 s/\s*$/:/ unless (/:\s*$/);
339 136         335 $_ .= "\n";
340 136         437 $$self{PENDING}[-1][1] = $_;
341             }
342             }
343 712 100 100     4722 if ($$self{USAGE_SKIPPING} && $element !~ m/^over-|^[BCFILSZ]$/) {
344 330         560 pop @{ $$self{PENDING} };
  330         1006  
345             } else {
346 382         3553 $self->SUPER::_handle_element_end($element);
347             }
348             }
349              
350             # required for Pod::Simple API
351             sub start_document {
352 23     23 0 177546 my $self = shift;
353 23         765 $self->SUPER::start_document();
354 23 100       41235 my $msg = $self->{USAGE_OPTIONS}->{-message} or return 1;
355 2         14 my $out_fh = $self->output_fh();
356 2         107 print $out_fh "$msg\n";
357             }
358              
359             # required for old Pod::Parser API
360             sub begin_pod {
361 0     0 0   my $self = shift;
362 0           $self->SUPER::begin_pod(); ## Have to call superclass
363 0 0         my $msg = $self->{USAGE_OPTIONS}->{-message} or return 1;
364 0           my $out_fh = $self->output_handle();
365 0           print $out_fh "$msg\n";
366             }
367              
368             sub preprocess_paragraph {
369 0     0 0   my $self = shift;
370 0           local $_ = shift;
371 0           my $line = shift;
372             ## See if this is a heading and we aren't printing the entire manpage.
373 0 0 0       if (($self->{USAGE_OPTIONS}->{-verbose} < 2) && /^=head/) {
374             ## Change the title of the SYNOPSIS section to USAGE
375 0           s/^=head1\s+SYNOPSIS\s*$/=head1 USAGE/;
376             ## Try to do some lowercasing instead of all-caps in headings
377 0 0         s{([A-Z])([A-Z]+)}{((length($2) > 2) ? $1 : lc($1)) . lc($2)}ge;
  0            
378             ## Use a colon to end all headings
379 0 0         s/\s*$/:/ unless (/:\s*$/);
380 0           $_ .= "\n";
381             }
382 0           return $self->SUPER::preprocess_paragraph($_);
383             }
384              
385             1; # keep require happy
386              
387             __END__