| 311 |
dpurdie |
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 |
# This file is part of "PodParser". PodParser is free software;
|
|
|
6 |
# you can redistribute it and/or modify it under the same terms
|
|
|
7 |
# as Perl itself.
|
|
|
8 |
#############################################################################
|
|
|
9 |
|
|
|
10 |
package Pod::Usage;
|
|
|
11 |
use strict;
|
|
|
12 |
|
|
|
13 |
use vars qw($VERSION @ISA @EXPORT);
|
|
|
14 |
use JatsError;
|
|
|
15 |
$VERSION = '1.36'; ## Current version of this package
|
|
|
16 |
require 5.005; ## requires this Perl version or later
|
|
|
17 |
|
|
|
18 |
=head1 NAME
|
|
|
19 |
|
|
|
20 |
Pod::Usage, pod2usage() - print a usage message from embedded pod documentation
|
|
|
21 |
|
|
|
22 |
=head1 SYNOPSIS
|
|
|
23 |
|
|
|
24 |
use Pod::Usage
|
|
|
25 |
|
|
|
26 |
my $message_text = "This text precedes the usage message.";
|
|
|
27 |
my $exit_status = 2; ## The exit status to use
|
|
|
28 |
my $verbose_level = 0; ## The verbose level to use
|
|
|
29 |
my $filehandle = \*STDERR; ## The filehandle to write to
|
|
|
30 |
|
|
|
31 |
pod2usage($message_text);
|
|
|
32 |
|
|
|
33 |
pod2usage($exit_status);
|
|
|
34 |
|
|
|
35 |
pod2usage( { -message => $message_text ,
|
|
|
36 |
-exitval => $exit_status ,
|
|
|
37 |
-verbose => $verbose_level,
|
|
|
38 |
-output => $filehandle } );
|
|
|
39 |
|
|
|
40 |
pod2usage( -msg => $message_text ,
|
|
|
41 |
-exitval => $exit_status ,
|
|
|
42 |
-verbose => $verbose_level,
|
|
|
43 |
-output => $filehandle );
|
|
|
44 |
|
|
|
45 |
pod2usage( -verbose => 2,
|
|
|
46 |
-noperldoc => 1 )
|
|
|
47 |
|
|
|
48 |
=head1 ARGUMENTS
|
|
|
49 |
|
|
|
50 |
B<pod2usage> should be given either a single argument, or a list of
|
|
|
51 |
arguments corresponding to an associative array (a "hash"). When a single
|
|
|
52 |
argument is given, it should correspond to exactly one of the following:
|
|
|
53 |
|
|
|
54 |
=over 4
|
|
|
55 |
|
|
|
56 |
=item *
|
|
|
57 |
|
|
|
58 |
A string containing the text of a message to print I<before> printing
|
|
|
59 |
the usage message
|
|
|
60 |
|
|
|
61 |
=item *
|
|
|
62 |
|
|
|
63 |
A numeric value corresponding to the desired exit status
|
|
|
64 |
|
|
|
65 |
=item *
|
|
|
66 |
|
|
|
67 |
A reference to a hash
|
|
|
68 |
|
|
|
69 |
=back
|
|
|
70 |
|
|
|
71 |
If more than one argument is given then the entire argument list is
|
|
|
72 |
assumed to be a hash. If a hash is supplied (either as a reference or
|
|
|
73 |
as a list) it should contain one or more elements with the following
|
|
|
74 |
keys:
|
|
|
75 |
|
|
|
76 |
=over 4
|
|
|
77 |
|
|
|
78 |
=item C<-message>
|
|
|
79 |
|
|
|
80 |
=item C<-msg>
|
|
|
81 |
|
|
|
82 |
The text of a message to print immediately prior to printing the
|
|
|
83 |
program's usage message.
|
|
|
84 |
|
|
|
85 |
=item C<-exitval>
|
|
|
86 |
|
|
|
87 |
The desired exit status to pass to the B<exit()> function.
|
|
|
88 |
This should be an integer, or else the string "NOEXIT" to
|
|
|
89 |
indicate that control should simply be returned without
|
|
|
90 |
terminating the invoking process.
|
|
|
91 |
|
|
|
92 |
=item C<-verbose>
|
|
|
93 |
|
|
|
94 |
The desired level of "verboseness" to use when printing the usage
|
|
|
95 |
message. If the corresponding value is 0, then only the "SYNOPSIS"
|
|
|
96 |
section of the pod documentation is printed. If the corresponding value
|
|
|
97 |
is 1, then the "SYNOPSIS" section, along with any section entitled
|
|
|
98 |
"OPTIONS", "ARGUMENTS", or "OPTIONS AND ARGUMENTS" is printed. If the
|
|
|
99 |
corresponding value is 2 or more then the entire manpage is printed.
|
|
|
100 |
|
|
|
101 |
The special verbosity level 99 requires to also specify the -sections
|
|
|
102 |
parameter; then these sections are extracted (see L<Pod::Select>)
|
|
|
103 |
and printed.
|
|
|
104 |
|
|
|
105 |
=item C<-sections>
|
|
|
106 |
|
|
|
107 |
A string representing a selection list for sections to be printed
|
|
|
108 |
when -verbose is set to 99, e.g. C<"NAME|SYNOPSIS|DESCRIPTION|VERSION">.
|
|
|
109 |
|
|
|
110 |
Alternatively, an array reference of section specifications can be used:
|
|
|
111 |
|
|
|
112 |
pod2usage(-verbose => 99,
|
|
|
113 |
-sections => [ qw(fred fred/subsection) ] );
|
|
|
114 |
|
|
|
115 |
=item C<-output>
|
|
|
116 |
|
|
|
117 |
A reference to a filehandle, or the pathname of a file to which the
|
|
|
118 |
usage message should be written. The default is C<\*STDERR> unless the
|
|
|
119 |
exit value is less than 2 (in which case the default is C<\*STDOUT>).
|
|
|
120 |
|
|
|
121 |
=item C<-input>
|
|
|
122 |
|
|
|
123 |
A reference to a filehandle, or the pathname of a file from which the
|
|
|
124 |
invoking script's pod documentation should be read. It defaults to the
|
|
|
125 |
file indicated by C<$0> (C<$PROGRAM_NAME> for users of F<English.pm>).
|
|
|
126 |
|
|
|
127 |
If you are calling B<pod2usage()> from a module and want to display
|
|
|
128 |
that module's POD, you can use this:
|
|
|
129 |
|
|
|
130 |
use Pod::Find qw(pod_where);
|
|
|
131 |
pod2usage( -input => pod_where({-inc => 1}, __PACKAGE__) );
|
|
|
132 |
|
|
|
133 |
=item C<-pathlist>
|
|
|
134 |
|
|
|
135 |
A list of directory paths. If the input file does not exist, then it
|
|
|
136 |
will be searched for in the given directory list (in the order the
|
|
|
137 |
directories appear in the list). It defaults to the list of directories
|
|
|
138 |
implied by C<$ENV{PATH}>. The list may be specified either by a reference
|
|
|
139 |
to an array, or by a string of directory paths which use the same path
|
|
|
140 |
separator as C<$ENV{PATH}> on your system (e.g., C<:> for Unix, C<;> for
|
|
|
141 |
MSWin32 and DOS).
|
|
|
142 |
|
|
|
143 |
=item C<-noperldoc>
|
|
|
144 |
|
|
|
145 |
By default, Pod::Usage will call L<perldoc> when -verbose >= 2 is
|
|
|
146 |
specified. This does not work well e.g. if the script was packed
|
|
|
147 |
with L<PAR>. The -noperldoc option suppresses the external call to
|
|
|
148 |
L<perldoc> and uses the simple text formatter (L<Pod::Text>) to
|
|
|
149 |
output the POD.
|
|
|
150 |
|
|
|
151 |
=back
|
|
|
152 |
|
|
|
153 |
=head1 DESCRIPTION
|
|
|
154 |
|
|
|
155 |
B<pod2usage> will print a usage message for the invoking script (using
|
|
|
156 |
its embedded pod documentation) and then exit the script with the
|
|
|
157 |
desired exit status. The usage message printed may have any one of three
|
|
|
158 |
levels of "verboseness": If the verbose level is 0, then only a synopsis
|
|
|
159 |
is printed. If the verbose level is 1, then the synopsis is printed
|
|
|
160 |
along with a description (if present) of the command line options and
|
|
|
161 |
arguments. If the verbose level is 2, then the entire manual page is
|
|
|
162 |
printed.
|
|
|
163 |
|
|
|
164 |
Unless they are explicitly specified, the default values for the exit
|
|
|
165 |
status, verbose level, and output stream to use are determined as
|
|
|
166 |
follows:
|
|
|
167 |
|
|
|
168 |
=over 4
|
|
|
169 |
|
|
|
170 |
=item *
|
|
|
171 |
|
|
|
172 |
If neither the exit status nor the verbose level is specified, then the
|
|
|
173 |
default is to use an exit status of 2 with a verbose level of 0.
|
|
|
174 |
|
|
|
175 |
=item *
|
|
|
176 |
|
|
|
177 |
If an exit status I<is> specified but the verbose level is I<not>, then the
|
|
|
178 |
verbose level will default to 1 if the exit status is less than 2 and
|
|
|
179 |
will default to 0 otherwise.
|
|
|
180 |
|
|
|
181 |
=item *
|
|
|
182 |
|
|
|
183 |
If an exit status is I<not> specified but verbose level I<is> given, then
|
|
|
184 |
the exit status will default to 2 if the verbose level is 0 and will
|
|
|
185 |
default to 1 otherwise.
|
|
|
186 |
|
|
|
187 |
=item *
|
|
|
188 |
|
|
|
189 |
If the exit status used is less than 2, then output is printed on
|
|
|
190 |
C<STDOUT>. Otherwise output is printed on C<STDERR>.
|
|
|
191 |
|
|
|
192 |
=back
|
|
|
193 |
|
|
|
194 |
Although the above may seem a bit confusing at first, it generally does
|
|
|
195 |
"the right thing" in most situations. This determination of the default
|
|
|
196 |
values to use is based upon the following typical Unix conventions:
|
|
|
197 |
|
|
|
198 |
=over 4
|
|
|
199 |
|
|
|
200 |
=item *
|
|
|
201 |
|
|
|
202 |
An exit status of 0 implies "success". For example, B<diff(1)> exits
|
|
|
203 |
with a status of 0 if the two files have the same contents.
|
|
|
204 |
|
|
|
205 |
=item *
|
|
|
206 |
|
|
|
207 |
An exit status of 1 implies possibly abnormal, but non-defective, program
|
|
|
208 |
termination. For example, B<grep(1)> exits with a status of 1 if
|
|
|
209 |
it did I<not> find a matching line for the given regular expression.
|
|
|
210 |
|
|
|
211 |
=item *
|
|
|
212 |
|
|
|
213 |
An exit status of 2 or more implies a fatal error. For example, B<ls(1)>
|
|
|
214 |
exits with a status of 2 if you specify an illegal (unknown) option on
|
|
|
215 |
the command line.
|
|
|
216 |
|
|
|
217 |
=item *
|
|
|
218 |
|
|
|
219 |
Usage messages issued as a result of bad command-line syntax should go
|
|
|
220 |
to C<STDERR>. However, usage messages issued due to an explicit request
|
|
|
221 |
to print usage (like specifying B<-help> on the command line) should go
|
|
|
222 |
to C<STDOUT>, just in case the user wants to pipe the output to a pager
|
|
|
223 |
(such as B<more(1)>).
|
|
|
224 |
|
|
|
225 |
=item *
|
|
|
226 |
|
|
|
227 |
If program usage has been explicitly requested by the user, it is often
|
|
|
228 |
desirable to exit with a status of 1 (as opposed to 0) after issuing
|
|
|
229 |
the user-requested usage message. It is also desirable to give a
|
|
|
230 |
more verbose description of program usage in this case.
|
|
|
231 |
|
|
|
232 |
=back
|
|
|
233 |
|
|
|
234 |
B<pod2usage> doesn't force the above conventions upon you, but it will
|
|
|
235 |
use them by default if you don't expressly tell it to do otherwise. The
|
|
|
236 |
ability of B<pod2usage()> to accept a single number or a string makes it
|
|
|
237 |
convenient to use as an innocent looking error message handling function:
|
|
|
238 |
|
|
|
239 |
use Pod::Usage;
|
|
|
240 |
use Getopt::Long;
|
|
|
241 |
|
|
|
242 |
## Parse options
|
|
|
243 |
GetOptions("help", "man", "flag1") || pod2usage(2);
|
|
|
244 |
pod2usage(1) if ($opt_help);
|
|
|
245 |
pod2usage(-verbose => 2) if ($opt_man);
|
|
|
246 |
|
|
|
247 |
## Check for too many filenames
|
|
|
248 |
pod2usage("$0: Too many files given.\n") if (@ARGV > 1);
|
|
|
249 |
|
|
|
250 |
Some user's however may feel that the above "economy of expression" is
|
|
|
251 |
not particularly readable nor consistent and may instead choose to do
|
|
|
252 |
something more like the following:
|
|
|
253 |
|
|
|
254 |
use Pod::Usage;
|
|
|
255 |
use Getopt::Long;
|
|
|
256 |
|
|
|
257 |
## Parse options
|
|
|
258 |
GetOptions("help", "man", "flag1") || pod2usage(-verbose => 0);
|
|
|
259 |
pod2usage(-verbose => 1) if ($opt_help);
|
|
|
260 |
pod2usage(-verbose => 2) if ($opt_man);
|
|
|
261 |
|
|
|
262 |
## Check for too many filenames
|
|
|
263 |
pod2usage(-verbose => 2, -message => "$0: Too many files given.\n")
|
|
|
264 |
if (@ARGV > 1);
|
|
|
265 |
|
|
|
266 |
As with all things in Perl, I<there's more than one way to do it>, and
|
|
|
267 |
B<pod2usage()> adheres to this philosophy. If you are interested in
|
|
|
268 |
seeing a number of different ways to invoke B<pod2usage> (although by no
|
|
|
269 |
means exhaustive), please refer to L<"EXAMPLES">.
|
|
|
270 |
|
|
|
271 |
=head1 EXAMPLES
|
|
|
272 |
|
|
|
273 |
Each of the following invocations of C<pod2usage()> will print just the
|
|
|
274 |
"SYNOPSIS" section to C<STDERR> and will exit with a status of 2:
|
|
|
275 |
|
|
|
276 |
pod2usage();
|
|
|
277 |
|
|
|
278 |
pod2usage(2);
|
|
|
279 |
|
|
|
280 |
pod2usage(-verbose => 0);
|
|
|
281 |
|
|
|
282 |
pod2usage(-exitval => 2);
|
|
|
283 |
|
|
|
284 |
pod2usage({-exitval => 2, -output => \*STDERR});
|
|
|
285 |
|
|
|
286 |
pod2usage({-verbose => 0, -output => \*STDERR});
|
|
|
287 |
|
|
|
288 |
pod2usage(-exitval => 2, -verbose => 0);
|
|
|
289 |
|
|
|
290 |
pod2usage(-exitval => 2, -verbose => 0, -output => \*STDERR);
|
|
|
291 |
|
|
|
292 |
Each of the following invocations of C<pod2usage()> will print a message
|
|
|
293 |
of "Syntax error." (followed by a newline) to C<STDERR>, immediately
|
|
|
294 |
followed by just the "SYNOPSIS" section (also printed to C<STDERR>) and
|
|
|
295 |
will exit with a status of 2:
|
|
|
296 |
|
|
|
297 |
pod2usage("Syntax error.");
|
|
|
298 |
|
|
|
299 |
pod2usage(-message => "Syntax error.", -verbose => 0);
|
|
|
300 |
|
|
|
301 |
pod2usage(-msg => "Syntax error.", -exitval => 2);
|
|
|
302 |
|
|
|
303 |
pod2usage({-msg => "Syntax error.", -exitval => 2, -output => \*STDERR});
|
|
|
304 |
|
|
|
305 |
pod2usage({-msg => "Syntax error.", -verbose => 0, -output => \*STDERR});
|
|
|
306 |
|
|
|
307 |
pod2usage(-msg => "Syntax error.", -exitval => 2, -verbose => 0);
|
|
|
308 |
|
|
|
309 |
pod2usage(-message => "Syntax error.",
|
|
|
310 |
-exitval => 2,
|
|
|
311 |
-verbose => 0,
|
|
|
312 |
-output => \*STDERR);
|
|
|
313 |
|
|
|
314 |
Each of the following invocations of C<pod2usage()> will print the
|
|
|
315 |
"SYNOPSIS" section and any "OPTIONS" and/or "ARGUMENTS" sections to
|
|
|
316 |
C<STDOUT> and will exit with a status of 1:
|
|
|
317 |
|
|
|
318 |
pod2usage(1);
|
|
|
319 |
|
|
|
320 |
pod2usage(-verbose => 1);
|
|
|
321 |
|
|
|
322 |
pod2usage(-exitval => 1);
|
|
|
323 |
|
|
|
324 |
pod2usage({-exitval => 1, -output => \*STDOUT});
|
|
|
325 |
|
|
|
326 |
pod2usage({-verbose => 1, -output => \*STDOUT});
|
|
|
327 |
|
|
|
328 |
pod2usage(-exitval => 1, -verbose => 1);
|
|
|
329 |
|
|
|
330 |
pod2usage(-exitval => 1, -verbose => 1, -output => \*STDOUT});
|
|
|
331 |
|
|
|
332 |
Each of the following invocations of C<pod2usage()> will print the
|
|
|
333 |
entire manual page to C<STDOUT> and will exit with a status of 1:
|
|
|
334 |
|
|
|
335 |
pod2usage(-verbose => 2);
|
|
|
336 |
|
|
|
337 |
pod2usage({-verbose => 2, -output => \*STDOUT});
|
|
|
338 |
|
|
|
339 |
pod2usage(-exitval => 1, -verbose => 2);
|
|
|
340 |
|
|
|
341 |
pod2usage({-exitval => 1, -verbose => 2, -output => \*STDOUT});
|
|
|
342 |
|
|
|
343 |
=head2 Recommended Use
|
|
|
344 |
|
|
|
345 |
Most scripts should print some type of usage message to C<STDERR> when a
|
|
|
346 |
command line syntax error is detected. They should also provide an
|
|
|
347 |
option (usually C<-H> or C<-help>) to print a (possibly more verbose)
|
|
|
348 |
usage message to C<STDOUT>. Some scripts may even wish to go so far as to
|
|
|
349 |
provide a means of printing their complete documentation to C<STDOUT>
|
|
|
350 |
(perhaps by allowing a C<-man> option). The following complete example
|
|
|
351 |
uses B<Pod::Usage> in combination with B<Getopt::Long> to do all of these
|
|
|
352 |
things:
|
|
|
353 |
|
|
|
354 |
use Getopt::Long;
|
|
|
355 |
use Pod::Usage;
|
|
|
356 |
|
|
|
357 |
my $man = 0;
|
|
|
358 |
my $help = 0;
|
|
|
359 |
## Parse options and print usage if there is a syntax error,
|
|
|
360 |
## or if usage was explicitly requested.
|
|
|
361 |
GetOptions('help|?' => \$help, man => \$man) or pod2usage(2);
|
|
|
362 |
pod2usage(1) if $help;
|
|
|
363 |
pod2usage(-verbose => 2) if $man;
|
|
|
364 |
|
|
|
365 |
## If no arguments were given, then allow STDIN to be used only
|
|
|
366 |
## if it's not connected to a terminal (otherwise print usage)
|
|
|
367 |
pod2usage("$0: No files given.") if ((@ARGV == 0) && (-t STDIN));
|
|
|
368 |
__END__
|
|
|
369 |
|
|
|
370 |
=head1 NAME
|
|
|
371 |
|
|
|
372 |
sample - Using GetOpt::Long and Pod::Usage
|
|
|
373 |
|
|
|
374 |
=head1 SYNOPSIS
|
|
|
375 |
|
|
|
376 |
sample [options] [file ...]
|
|
|
377 |
|
|
|
378 |
Options:
|
|
|
379 |
-help brief help message
|
|
|
380 |
-man full documentation
|
|
|
381 |
|
|
|
382 |
=head1 OPTIONS
|
|
|
383 |
|
|
|
384 |
=over 8
|
|
|
385 |
|
|
|
386 |
=item B<-help>
|
|
|
387 |
|
|
|
388 |
Print a brief help message and exits.
|
|
|
389 |
|
|
|
390 |
=item B<-man>
|
|
|
391 |
|
|
|
392 |
Prints the manual page and exits.
|
|
|
393 |
|
|
|
394 |
=back
|
|
|
395 |
|
|
|
396 |
=head1 DESCRIPTION
|
|
|
397 |
|
|
|
398 |
B<This program> will read the given input file(s) and do something
|
|
|
399 |
useful with the contents thereof.
|
|
|
400 |
|
|
|
401 |
=cut
|
|
|
402 |
|
|
|
403 |
=head1 CAVEATS
|
|
|
404 |
|
|
|
405 |
By default, B<pod2usage()> will use C<$0> as the path to the pod input
|
|
|
406 |
file. Unfortunately, not all systems on which Perl runs will set C<$0>
|
|
|
407 |
properly (although if C<$0> isn't found, B<pod2usage()> will search
|
|
|
408 |
C<$ENV{PATH}> or else the list specified by the C<-pathlist> option).
|
|
|
409 |
If this is the case for your system, you may need to explicitly specify
|
|
|
410 |
the path to the pod docs for the invoking script using something
|
|
|
411 |
similar to the following:
|
|
|
412 |
|
|
|
413 |
pod2usage(-exitval => 2, -input => "/path/to/your/pod/docs");
|
|
|
414 |
|
|
|
415 |
In the pathological case that a script is called via a relative path
|
|
|
416 |
I<and> the script itself changes the current working directory
|
|
|
417 |
(see L<perlfunc/chdir>) I<before> calling pod2usage, Pod::Usage will
|
|
|
418 |
fail even on robust platforms. Don't do that.
|
|
|
419 |
|
|
|
420 |
=head1 AUTHOR
|
|
|
421 |
|
|
|
422 |
Please report bugs using L<http://rt.cpan.org>.
|
|
|
423 |
|
|
|
424 |
Marek Rouchal E<lt>marekr@cpan.orgE<gt>
|
|
|
425 |
|
|
|
426 |
Brad Appleton E<lt>bradapp@enteract.comE<gt>
|
|
|
427 |
|
|
|
428 |
Based on code for B<Pod::Text::pod2text()> written by
|
|
|
429 |
Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>
|
|
|
430 |
|
|
|
431 |
=head1 ACKNOWLEDGMENTS
|
|
|
432 |
|
|
|
433 |
Steven McDougall E<lt>swmcd@world.std.comE<gt> for his help and patience
|
|
|
434 |
with re-writing this manpage.
|
|
|
435 |
|
|
|
436 |
=head1 SEE ALSO
|
|
|
437 |
|
|
|
438 |
L<Pod::Parser>, L<Getopt::Long>, L<Pod::Find>
|
|
|
439 |
|
|
|
440 |
=cut
|
|
|
441 |
|
|
|
442 |
#############################################################################
|
|
|
443 |
|
|
|
444 |
#use diagnostics;
|
|
|
445 |
use Carp;
|
|
|
446 |
use Config;
|
|
|
447 |
use Exporter;
|
|
|
448 |
use File::Spec;
|
|
|
449 |
|
|
|
450 |
@EXPORT = qw(&pod2usage);
|
|
|
451 |
BEGIN {
|
|
|
452 |
require Pod::PlainText;
|
|
|
453 |
@ISA = qw( Pod::PlainText );
|
|
|
454 |
}
|
|
|
455 |
|
|
|
456 |
require Pod::Select;
|
|
|
457 |
|
|
|
458 |
##---------------------------------------------------------------------------
|
|
|
459 |
|
|
|
460 |
##---------------------------------
|
|
|
461 |
## Function definitions begin here
|
|
|
462 |
##---------------------------------
|
|
|
463 |
|
|
|
464 |
sub pod2usage {
|
|
|
465 |
local($_) = shift;
|
| 313 |
dpurdie |
466 |
my %opts ;
|
| 311 |
dpurdie |
467 |
## Collect arguments
|
|
|
468 |
if (@_ > 0) {
|
|
|
469 |
## Too many arguments - assume that this is a hash and
|
|
|
470 |
## the user forgot to pass a reference to it.
|
|
|
471 |
%opts = ($_, @_);
|
|
|
472 |
}
|
|
|
473 |
elsif (!defined $_) {
|
|
|
474 |
$_ = '';
|
|
|
475 |
}
|
|
|
476 |
elsif (ref $_) {
|
|
|
477 |
## User passed a ref to a hash
|
|
|
478 |
%opts = %{$_} if (ref($_) eq 'HASH');
|
|
|
479 |
}
|
|
|
480 |
elsif (/^[-+]?\d+$/) {
|
|
|
481 |
## User passed in the exit value to use
|
|
|
482 |
$opts{'-exitval'} = $_;
|
|
|
483 |
}
|
|
|
484 |
else {
|
|
|
485 |
## User passed in a message to print before issuing usage.
|
|
|
486 |
$_ and $opts{'-message'} = $_;
|
|
|
487 |
}
|
|
|
488 |
|
| 313 |
dpurdie |
489 |
#
|
|
|
490 |
# Defaults
|
|
|
491 |
# Don't use perldoc - it creates different output
|
|
|
492 |
#
|
|
|
493 |
$opts{-noperldoc} ||= 1;
|
|
|
494 |
|
| 311 |
dpurdie |
495 |
## Need this for backward compatibility since we formerly used
|
|
|
496 |
## options that were all uppercase words rather than ones that
|
|
|
497 |
## looked like Unix command-line options.
|
|
|
498 |
## to be uppercase keywords)
|
|
|
499 |
%opts = map {
|
|
|
500 |
my ($key, $val) = ($_, $opts{$_});
|
|
|
501 |
$key =~ s/^(?=\w)/-/;
|
|
|
502 |
$key =~ /^-msg/i and $key = '-message';
|
|
|
503 |
$key =~ /^-exit/i and $key = '-exitval';
|
|
|
504 |
lc($key) => $val;
|
|
|
505 |
} (keys %opts);
|
|
|
506 |
|
|
|
507 |
## Now determine default -exitval and -verbose values to use
|
|
|
508 |
if ((! defined $opts{'-exitval'}) && (! defined $opts{'-verbose'})) {
|
|
|
509 |
$opts{'-exitval'} = 2;
|
|
|
510 |
$opts{'-verbose'} = 0;
|
|
|
511 |
}
|
|
|
512 |
elsif (! defined $opts{'-exitval'}) {
|
|
|
513 |
$opts{'-exitval'} = ($opts{'-verbose'} > 0) ? 1 : 2;
|
|
|
514 |
}
|
|
|
515 |
elsif (! defined $opts{'-verbose'}) {
|
|
|
516 |
$opts{'-verbose'} = (lc($opts{'-exitval'}) eq 'noexit' ||
|
|
|
517 |
$opts{'-exitval'} < 2);
|
|
|
518 |
}
|
|
|
519 |
|
|
|
520 |
## Default the output file
|
|
|
521 |
$opts{'-output'} = (lc($opts{'-exitval'}) eq 'noexit' ||
|
|
|
522 |
$opts{'-exitval'} < 2) ? \*STDOUT : \*STDERR
|
|
|
523 |
unless (defined $opts{'-output'});
|
|
|
524 |
## Default the input file
|
|
|
525 |
$opts{'-input'} = $0 unless (defined $opts{'-input'});
|
|
|
526 |
|
|
|
527 |
## Look up input file in path if it doesnt exist.
|
|
|
528 |
unless ((ref $opts{'-input'}) || (-e $opts{'-input'})) {
|
|
|
529 |
my $basename = $opts{'-input'};
|
|
|
530 |
my $pathsep = ($^O =~ /^(?:dos|os2|MSWin32)$/i) ? ';'
|
|
|
531 |
: (($^O eq 'MacOS' || $^O eq 'VMS') ? ',' : ':');
|
|
|
532 |
my $pathspec = $opts{'-pathlist'} || $ENV{PATH} || $ENV{PERL5LIB};
|
|
|
533 |
|
|
|
534 |
my @paths = (ref $pathspec) ? @$pathspec : split($pathsep, $pathspec);
|
|
|
535 |
for my $dirname (@paths) {
|
|
|
536 |
$_ = File::Spec->catfile($dirname, $basename) if length;
|
|
|
537 |
last if (-e $_) && ($opts{'-input'} = $_);
|
|
|
538 |
}
|
|
|
539 |
}
|
|
|
540 |
|
|
|
541 |
## Now create a pod reader and constrain it to the desired sections.
|
|
|
542 |
my $parser = new Pod::Usage(USAGE_OPTIONS => \%opts);
|
|
|
543 |
if ($opts{'-verbose'} == 0) {
|
|
|
544 |
$parser->select('(?:SYNOPSIS|USAGE)\s*');
|
|
|
545 |
}
|
|
|
546 |
elsif ($opts{'-verbose'} == 1) {
|
|
|
547 |
my $opt_re = '(?i)' .
|
|
|
548 |
'(?:OPTIONS|ARGUMENTS)' .
|
|
|
549 |
'(?:\s*(?:AND|\/)\s*(?:OPTIONS|ARGUMENTS))?';
|
|
|
550 |
$parser->select( '(?:SYNOPSIS|USAGE)\s*', $opt_re, "DESCRIPTION/$opt_re" );
|
|
|
551 |
}
|
|
|
552 |
elsif ($opts{'-verbose'} >= 2 && $opts{'-verbose'} != 99) {
|
|
|
553 |
$parser->select('.*');
|
|
|
554 |
}
|
|
|
555 |
elsif ($opts{'-verbose'} == 99) {
|
|
|
556 |
my $sections = $opts{'-sections'};
|
|
|
557 |
$parser->select( (ref $sections) ? @$sections : $sections );
|
|
|
558 |
$opts{'-verbose'} = 1;
|
|
|
559 |
}
|
|
|
560 |
|
|
|
561 |
## Now translate the pod document and then exit with the desired status
|
|
|
562 |
if ( !$opts{'-noperldoc'}
|
|
|
563 |
and $opts{'-verbose'} >= 2
|
|
|
564 |
and !ref($opts{'-input'})
|
|
|
565 |
and $opts{'-output'} == \*STDOUT )
|
|
|
566 |
{
|
|
|
567 |
## spit out the entire PODs. Might as well invoke perldoc
|
|
|
568 |
my $progpath = File::Spec->catfile($Config{scriptdir}, 'perldoc');
|
|
|
569 |
print { $opts{'-output'} } ($opts{'-message'}, "\n") if($opts{'-message'});
|
|
|
570 |
if(defined $opts{-input} && $opts{-input} =~ /^\s*(\S.*?)\s*$/) {
|
|
|
571 |
# the perldocs back to 5.005 should all have -F
|
|
|
572 |
# without -F there are warnings in -T scripts
|
|
|
573 |
system($progpath, '-F', $1);
|
|
|
574 |
if($?) {
|
|
|
575 |
# RT16091: fall back to more if perldoc failed
|
|
|
576 |
system(($Config{pager} || $ENV{PAGER} || '/bin/more'), $1);
|
|
|
577 |
}
|
|
|
578 |
} else {
|
|
|
579 |
croak "Unspecified input file or insecure argument.\n";
|
|
|
580 |
}
|
|
|
581 |
}
|
|
|
582 |
else {
|
|
|
583 |
$parser->parse_from_file($opts{'-input'}, $opts{'-output'});
|
|
|
584 |
}
|
|
|
585 |
|
|
|
586 |
exit($opts{'-exitval'}) unless (lc($opts{'-exitval'}) eq 'noexit');
|
|
|
587 |
}
|
|
|
588 |
|
|
|
589 |
##---------------------------------------------------------------------------
|
|
|
590 |
|
|
|
591 |
##-------------------------------
|
|
|
592 |
## Method definitions begin here
|
|
|
593 |
##-------------------------------
|
|
|
594 |
|
|
|
595 |
sub new {
|
|
|
596 |
my $this = shift;
|
|
|
597 |
my $class = ref($this) || $this;
|
|
|
598 |
my %params = @_;
|
|
|
599 |
my $self = {%params};
|
|
|
600 |
bless $self, $class;
|
|
|
601 |
if ($self->can('initialize')) {
|
|
|
602 |
$self->initialize();
|
|
|
603 |
} else {
|
|
|
604 |
$self = $self->SUPER::new();
|
|
|
605 |
%$self = (%$self, %params);
|
|
|
606 |
}
|
|
|
607 |
return $self;
|
|
|
608 |
}
|
|
|
609 |
|
|
|
610 |
sub select {
|
|
|
611 |
my ($self, @sections) = @_;
|
|
|
612 |
if ($ISA[0]->can('select')) {
|
|
|
613 |
$self->SUPER::select(@sections);
|
|
|
614 |
} else {
|
|
|
615 |
# we're using Pod::Simple - need to mimic the behavior of Pod::Select
|
|
|
616 |
my $add = ($sections[0] eq '+') ? shift(@sections) : '';
|
|
|
617 |
## Reset the set of sections to use
|
|
|
618 |
unless (@sections) {
|
|
|
619 |
delete $self->{USAGE_SELECT} unless ($add);
|
|
|
620 |
return;
|
|
|
621 |
}
|
|
|
622 |
$self->{USAGE_SELECT} = []
|
|
|
623 |
unless ($add && $self->{USAGE_SELECT});
|
|
|
624 |
my $sref = $self->{USAGE_SELECT};
|
|
|
625 |
## Compile each spec
|
|
|
626 |
for my $spec (@sections) {
|
|
|
627 |
my $cs = Pod::Select::_compile_section_spec($spec);
|
|
|
628 |
if ( defined $cs ) {
|
|
|
629 |
## Store them in our sections array
|
|
|
630 |
push(@$sref, $cs);
|
|
|
631 |
} else {
|
|
|
632 |
carp qq{Ignoring section spec "$spec"!\n};
|
|
|
633 |
}
|
|
|
634 |
}
|
|
|
635 |
}
|
|
|
636 |
}
|
|
|
637 |
|
|
|
638 |
# Override Pod::Text->seq_i to return just "arg", not "*arg*".
|
|
|
639 |
sub seq_i { return $_[1] }
|
|
|
640 |
|
|
|
641 |
# This overrides the Pod::Text method to do something very akin to what
|
|
|
642 |
# Pod::Select did as well as the work done below by preprocess_paragraph.
|
|
|
643 |
# Note that the below is very, very specific to Pod::Text.
|
|
|
644 |
sub _handle_element_end {
|
|
|
645 |
my ($self, $element) = @_;
|
|
|
646 |
if ($element eq 'head1') {
|
|
|
647 |
$self->{USAGE_HEADINGS} = [ $$self{PENDING}[-1][1] ];
|
|
|
648 |
if ($self->{USAGE_OPTIONS}->{-verbose} < 2) {
|
|
|
649 |
$$self{PENDING}[-1][1] =~ s/^\s*SYNOPSIS\s*$/USAGE/;
|
|
|
650 |
}
|
|
|
651 |
} elsif ($element =~ /^head(\d+)$/ && $1) { # avoid 0
|
|
|
652 |
my $idx = $1 - 1;
|
|
|
653 |
$self->{USAGE_HEADINGS} = [] unless($self->{USAGE_HEADINGS});
|
|
|
654 |
$self->{USAGE_HEADINGS}->[$idx] = $$self{PENDING}[-1][1];
|
|
|
655 |
}
|
|
|
656 |
if ($element =~ /^head\d+$/) {
|
|
|
657 |
$$self{USAGE_SKIPPING} = 1;
|
|
|
658 |
if (!$$self{USAGE_SELECT} || !@{ $$self{USAGE_SELECT} }) {
|
|
|
659 |
$$self{USAGE_SKIPPING} = 0;
|
|
|
660 |
} else {
|
|
|
661 |
my @headings = @{$$self{USAGE_HEADINGS}};
|
|
|
662 |
for my $section_spec ( @{$$self{USAGE_SELECT}} ) {
|
|
|
663 |
my $match = 1;
|
|
|
664 |
for (my $i = 0; $i < $Pod::Select::MAX_HEADING_LEVEL; ++$i) {
|
|
|
665 |
$headings[$i] = '' unless defined $headings[$i];
|
|
|
666 |
my $regex = $section_spec->[$i];
|
|
|
667 |
my $negated = ($regex =~ s/^\!//);
|
|
|
668 |
$match &= ($negated ? ($headings[$i] !~ /${regex}/)
|
|
|
669 |
: ($headings[$i] =~ /${regex}/));
|
|
|
670 |
last unless ($match);
|
|
|
671 |
} # end heading levels
|
|
|
672 |
if ($match) {
|
|
|
673 |
$$self{USAGE_SKIPPING} = 0;
|
|
|
674 |
last;
|
|
|
675 |
}
|
|
|
676 |
} # end sections
|
|
|
677 |
}
|
|
|
678 |
|
|
|
679 |
# Try to do some lowercasing instead of all-caps in headings, and use
|
|
|
680 |
# a colon to end all headings.
|
|
|
681 |
if($self->{USAGE_OPTIONS}->{-verbose} < 2) {
|
|
|
682 |
local $_ = $$self{PENDING}[-1][1];
|
|
|
683 |
s{([A-Z])([A-Z]+)}{((length($2) > 2) ? $1 : lc($1)) . lc($2)}ge;
|
|
|
684 |
s/\s*$/:/ unless (/:\s*$/);
|
|
|
685 |
$_ .= "\n";
|
|
|
686 |
$$self{PENDING}[-1][1] = $_;
|
|
|
687 |
}
|
|
|
688 |
}
|
|
|
689 |
if ($$self{USAGE_SKIPPING} && $element !~ m/^over-/) {
|
|
|
690 |
pop @{ $$self{PENDING} };
|
|
|
691 |
} else {
|
|
|
692 |
$self->SUPER::_handle_element_end($element);
|
|
|
693 |
}
|
|
|
694 |
}
|
|
|
695 |
|
|
|
696 |
# required for Pod::Simple API
|
|
|
697 |
sub start_document {
|
|
|
698 |
my $self = shift;
|
|
|
699 |
$self->SUPER::start_document();
|
|
|
700 |
my $msg = $self->{USAGE_OPTIONS}->{-message} or return 1;
|
|
|
701 |
my $out_fh = $self->output_fh();
|
|
|
702 |
print $out_fh "$msg\n";
|
|
|
703 |
}
|
|
|
704 |
|
|
|
705 |
# required for old Pod::Parser API
|
|
|
706 |
sub begin_pod {
|
|
|
707 |
my $self = shift;
|
|
|
708 |
$self->SUPER::begin_pod(); ## Have to call superclass
|
|
|
709 |
my $msg = $self->{USAGE_OPTIONS}->{-message} or return 1;
|
|
|
710 |
my $out_fh = $self->output_handle();
|
|
|
711 |
print $out_fh "$msg\n";
|
|
|
712 |
}
|
|
|
713 |
|
|
|
714 |
sub preprocess_paragraph {
|
|
|
715 |
my $self = shift;
|
|
|
716 |
local $_ = shift;
|
|
|
717 |
my $line = shift;
|
|
|
718 |
## See if this is a heading and we arent printing the entire manpage.
|
|
|
719 |
if (($self->{USAGE_OPTIONS}->{-verbose} < 2) && /^=head/) {
|
|
|
720 |
## Change the title of the SYNOPSIS section to USAGE
|
|
|
721 |
s/^=head1\s+SYNOPSIS\s*$/=head1 USAGE/;
|
|
|
722 |
## Try to do some lowercasing instead of all-caps in headings
|
|
|
723 |
s{([A-Z])([A-Z]+)}{((length($2) > 2) ? $1 : lc($1)) . lc($2)}ge;
|
|
|
724 |
## Use a colon to end all headings
|
|
|
725 |
s/\s*$/:/ unless (/:\s*$/);
|
|
|
726 |
$_ .= "\n";
|
|
|
727 |
}
|
|
|
728 |
return $self->SUPER::preprocess_paragraph($_);
|
|
|
729 |
}
|
|
|
730 |
|
|
|
731 |
1; # keep require happy
|