This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
"Pod::Html bug and fix: missing </UL> in index", #F085
[perl5.git] / utils / perldoc.PL
CommitLineData
4633a7c4
LW
1#!/usr/local/bin/perl
2
3use Config;
4use File::Basename qw(&basename &dirname);
5
85880f03 6# List explicitly here the variables you want Configure to
7# generate. Metaconfig only looks for shell variables, so you
8# have to mention them as if they were shell variables, not
9# %Config entries. Thus you write
4633a7c4 10# $startperl
85880f03 11# to ensure Configure will look for $Config{startperl}.
4633a7c4
LW
12
13# This forces PL files to create target in same directory as PL file.
14# This is so that make depend always knows where to find PL derivatives.
44a8e56a 15chdir dirname($0);
16$file = basename($0, '.PL');
774d564b 17$file .= '.com' if $^O eq 'VMS';
4633a7c4
LW
18
19open OUT,">$file" or die "Can't create $file: $!";
20
21print "Extracting $file (with variable substitutions)\n";
22
23# In this section, perl variables will be expanded during extraction.
24# You can use $Config{...} to use Configure variables.
25
85880f03 26print OUT <<"!GROK!THIS!";
5f05dabc 27$Config{startperl}
28 eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
29 if \$running_under_some_shell;
55497cff 30
31\@pagers = ();
32push \@pagers, "$Config{'pager'}" if -x "$Config{'pager'}";
4633a7c4
LW
33!GROK!THIS!
34
35# In the following, perl variables are not expanded during extraction.
36
37print OUT <<'!NO!SUBS!';
38
39#
40# Perldoc revision #1 -- look up a piece of documentation in .pod format that
41# is embedded in the perl installation tree.
42#
43# This is not to be confused with Tom Christianson's perlman, which is a
44# man replacement, written in perl. This perldoc is strictly for reading
45# the perl manuals, though it too is written in perl.
4633a7c4
LW
46
47if(@ARGV<1) {
0b166b66 48 $me = $0; # Editing $0 is unportable
fb73857a 49 $me =~ s,.*/,,;
4633a7c4 50 die <<EOF;
0b166b66
IZ
51Usage: $me [-h] [-v] [-t] [-u] [-m] [-l] PageName|ModuleName|ProgramName
52 $me -f PerlFunc
4633a7c4
LW
53
54We suggest you use "perldoc perldoc" to get aquainted
55with the system.
56EOF
57}
58
59use Getopt::Std;
59586d77
IZ
60use Config '%Config';
61
fb73857a 62@global_found = ();
63$global_target = "";
64
7eda7aea 65$Is_VMS = $^O eq 'VMS';
137443ea 66$Is_MSWin32 = $^O eq 'MSWin32';
4633a7c4
LW
67
68sub usage{
ff0cee69 69 warn "@_\n" if @_;
70 # Erase evidence of previous errors (if any), so exit status is simple.
71 $! = 0;
4633a7c4 72 die <<EOF;
31bdbec1
GA
73perldoc [options] PageName|ModuleName|ProgramName...
74perldoc [options] -f BuiltinFunction
75
76Options:
137443ea 77 -h Display this help message
78 -t Display pod using pod2text instead of pod2man and nroff
79 (-t is the default on win32)
85880f03 80 -u Display unformatted pod text
7eda7aea 81 -m Display modules file in its entirety
44a8e56a 82 -l Display the modules file name
137443ea 83 -v Verbosely describe what's going on
31bdbec1 84
4633a7c4
LW
85PageName|ModuleName...
86 is the name of a piece of documentation that you want to look at. You
87 may either give a descriptive name of the page (as in the case of
88 `perlfunc') the name of a module, either like `Term::Info',
89 `Term/Info', the partial name of a module, like `info', or
90 `makemaker', or the name of a program, like `perldoc'.
31bdbec1
GA
91
92BuiltinFunction
93 is the name of a perl function. Will extract documentation from
94 `perlfunc'.
4633a7c4
LW
95
96Any switches in the PERLDOC environment variable will be used before the
97command line arguments.
98
99EOF
100}
101
102use Text::ParseWords;
103
104
105unshift(@ARGV,shellwords($ENV{"PERLDOC"}));
106
31bdbec1 107getopts("mhtluvf:") || usage;
85880f03 108
109usage if $opt_h || $opt_h; # avoid -w warning
4633a7c4 110
137443ea 111if ($opt_t + $opt_u + $opt_m + $opt_l > 1) {
112 usage("only one of -t, -u, -m or -l")
113} elsif ($Is_MSWin32) {
114 $opt_t = 1 unless $opt_t + $opt_u + $opt_m + $opt_l;
115}
4633a7c4 116
7eda7aea 117if ($opt_t) { require Pod::Text; import Pod::Text; }
4633a7c4 118
31bdbec1
GA
119if ($opt_f) {
120 @pages = ("perlfunc");
121} else {
122 @pages = @ARGV;
123}
124
fb73857a 125# Does this look like a module or extension directory?
126if (-f "Makefile.PL") {
127 # Add ., lib and blib/* libs to @INC (if they exist)
128 unshift(@INC, '.');
129 unshift(@INC, 'lib') if -d 'lib';
130 require ExtUtils::testlib;
131}
132
31bdbec1 133
85880f03 134
4633a7c4 135sub containspod {
fb73857a 136 my($file, $readit) = @_;
137 return 1 if !$readit && $file =~ /\.pod$/i;
138 local($_);
139 open(TEST,"<$file");
140 while(<TEST>) {
141 if(/^=head/) {
142 close(TEST);
143 return 1;
4633a7c4 144 }
fb73857a 145 }
146 close(TEST);
147 return 0;
4633a7c4
LW
148}
149
84902520 150sub minus_f_nocase {
4633a7c4 151 my($file) = @_;
84902520
TB
152 # on a case-forgiving file system we can simply use -f $file
153 if ($Is_VMS or $Is_MSWin32 or $^O eq 'os2') {
fb73857a 154 return $file if -f $file and -r _;
155 warn "Ignored $file: unreadable\n" unless -r _;
156 return '';
84902520 157 }
4633a7c4
LW
158 local *DIR;
159 local($")="/";
160 my(@p,$p,$cip);
161 foreach $p (split(/\//, $file)){
fb73857a 162 my $try = "@p/$p";
163 stat $try;
164 if (-d _){
4633a7c4 165 push @p, $p;
fb73857a 166 if ( $p eq $global_target) {
167 $tmp_path = join ('/', @p);
168 my $path_f = 0;
169 for (@global_found) {
170 $path_f = 1 if $_ eq $tmp_path;
171 }
172 push (@global_found, $tmp_path) unless $path_f;
173 print STDERR "Found as @p but directory\n" if $opt_v;
174 }
175 } elsif (-f _ && -r _) {
176 return $try;
177 } elsif (-f _) {
178 warn "Ignored $try: unreadable\n";
4633a7c4
LW
179 } else {
180 my $found=0;
181 my $lcp = lc $p;
182 opendir DIR, "@p";
183 while ($cip=readdir(DIR)) {
184 if (lc $cip eq $lcp){
185 $found++;
186 last;
187 }
188 }
189 closedir DIR;
190 return "" unless $found;
191 push @p, $cip;
fb73857a 192 return "@p" if -f "@p" and -r _;
193 warn "Ignored $file: unreadable\n" if -f _;
4633a7c4
LW
194 }
195 }
196 return; # is not a file
fb73857a 197}
4633a7c4 198
fb73857a 199
200sub check_file {
201 my($file) = @_;
202 return minus_f_nocase($file) && containspod($file) ? $file : "";
203}
204
205
206sub searchfor {
207 my($recurse,$s,@dirs) = @_;
208 $s =~ s!::!/!g;
209 $s = VMS::Filespec::unixify($s) if $Is_VMS;
210 return $s if -f $s && containspod($s);
211 printf STDERR "Looking for $s in @dirs\n" if $opt_v;
212 my $ret;
213 my $i;
214 my $dir;
215 $global_target = (split('/', $s))[-1];
216 for ($i=0; $i<@dirs; $i++) {
217 $dir = $dirs[$i];
218 ($dir = VMS::Filespec::unixpath($dir)) =~ s!/$!! if $Is_VMS;
219 if ( ( $ret = check_file "$dir/$s.pod")
220 or ( $ret = check_file "$dir/$s.pm")
221 or ( $ret = check_file "$dir/$s")
222 or ( $Is_VMS and
223 $ret = check_file "$dir/$s.com")
59586d77 224 or ( $^O eq 'os2' and
fb73857a 225 $ret = check_file "$dir/$s.cmd")
59586d77 226 or ( ($Is_MSWin32 or $^O eq 'os2') and
fb73857a 227 $ret = check_file "$dir/$s.bat")
228 or ( $ret = check_file "$dir/pod/$s.pod")
229 or ( $ret = check_file "$dir/pod/$s")
230 ) {
231 return $ret;
232 }
233
234 if ($recurse) {
235 opendir(D,$dir);
236 my @newdirs = map "$dir/$_", grep {
237 not /^\.\.?$/ and
238 not /^auto$/ and # save time! don't search auto dirs
239 -d "$dir/$_"
240 } readdir D;
241 closedir(D);
242 next unless @newdirs;
243 @newdirs = map((s/.dir$//,$_)[1],@newdirs) if $Is_VMS;
244 print STDERR "Also looking in @newdirs\n" if $opt_v;
245 push(@dirs,@newdirs);
246 }
247 }
248 return ();
249}
4633a7c4
LW
250
251
252foreach (@pages) {
253 print STDERR "Searching for $_\n" if $opt_v;
254 # We must look both in @INC for library modules and in PATH
255 # for executables, like h2xs or perldoc itself.
256 @searchdirs = @INC;
7eda7aea 257 unless ($opt_m) {
258 if ($Is_VMS) {
259 my($i,$trn);
260 for ($i = 0; $trn = $ENV{'DCL$PATH'.$i}; $i++) {
261 push(@searchdirs,$trn);
262 }
263 } else {
59586d77
IZ
264 push(@searchdirs, grep(-d, split($Config{path_sep},
265 $ENV{'PATH'})));
7eda7aea 266 }
267 @files= searchfor(0,$_,@searchdirs);
85880f03 268 }
4633a7c4
LW
269 if( @files ) {
270 print STDERR "Found as @files\n" if $opt_v;
271 } else {
272 # no match, try recursive search
273
274 @searchdirs = grep(!/^\.$/,@INC);
275
4633a7c4
LW
276 @files= searchfor(1,$_,@searchdirs);
277 if( @files ) {
85880f03 278 print STDERR "Loosely found as @files\n" if $opt_v;
4633a7c4 279 } else {
fb73857a 280 print STDERR "No documentation found for \"$_\".\n";
281 if (@global_found) {
282 print STDERR "However, try\n";
283 my $dir = $file = "";
284 for $dir (@global_found) {
285 opendir(DIR, $dir) or die "$!";
286 while ($file = readdir(DIR)) {
287 next if ($file =~ /^\./);
288 $file =~ s/\.(pm|pod)$//;
289 print STDERR "\tperldoc $_\::$file\n";
290 }
291 closedir DIR;
292 }
293 }
4633a7c4
LW
294 }
295 }
296 push(@found,@files);
297}
298
299if(!@found) {
85880f03 300 exit ($Is_VMS ? 98962 : 1);
4633a7c4
LW
301}
302
44a8e56a 303if ($opt_l) {
304 print join("\n", @found), "\n";
305 exit;
306}
307
31bdbec1 308if( ! -t STDOUT ) { $no_tty = 1 }
4633a7c4 309
137443ea 310if ($Is_MSWin32) {
311 $tmp = "$ENV{TEMP}\\perldoc1.$$";
312 push @pagers, qw( more< less notepad );
55497cff 313 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
137443ea 314} elsif ($Is_VMS) {
4633a7c4 315 $tmp = 'Sys$Scratch:perldoc.tmp1_'.$$;
55497cff 316 push @pagers, qw( most more less type/page );
137443ea 317} else {
59586d77
IZ
318 if ($^O eq 'os2') {
319 require POSIX;
320 $tmp = POSIX::tmpnam();
321 } else {
322 $tmp = "/tmp/perldoc1.$$";
323 }
137443ea 324 push @pagers, qw( more less pg view cat );
325 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
4633a7c4 326}
44a8e56a 327unshift @pagers, $ENV{PERLDOC_PAGER} if $ENV{PERLDOC_PAGER};
4633a7c4 328
7eda7aea 329if ($opt_m) {
1e422769 330 foreach $pager (@pagers) {
331 system("$pager @found") or exit;
332 }
333 if ($Is_VMS) { eval 'use vmsish qw(status exit); exit $?' }
334 exit 1;
7eda7aea 335}
336
31bdbec1
GA
337if ($opt_f) {
338 my $perlfunc = shift @found;
339 open(PFUNC, $perlfunc) or die "Can't open $perlfunc: $!";
340
341 # Skip introduction
342 while (<PFUNC>) {
343 last if /^=head2 Alphabetical Listing of Perl Functions/;
344 }
345
346 # Look for our function
347 my $found = 0;
fb73857a 348 my @pod;
31bdbec1
GA
349 while (<PFUNC>) {
350 if (/^=item\s+\Q$opt_f\E\b/o) {
fb73857a 351 $found = 1;
31bdbec1 352 } elsif (/^=item/) {
fb73857a 353 last if $found > 1;
31bdbec1 354 }
fb73857a 355 next unless $found;
356 push @pod, $_;
357 ++$found if /^\w/; # found descriptive text
31bdbec1
GA
358 }
359 if (@pod) {
360 if ($opt_t) {
361 open(FORMATTER, "| pod2text") || die "Can't start filter";
362 print FORMATTER "=over 8\n\n";
363 print FORMATTER @pod;
364 print FORMATTER "=back\n";
365 close(FORMATTER);
366 } else {
367 print @pod;
368 }
369 } else {
ed5c9e50 370 die "No documentation for perl function `$opt_f' found\n";
31bdbec1
GA
371 }
372 exit;
373}
374
4633a7c4 375foreach (@found) {
7eda7aea 376
85880f03 377 if($opt_t) {
378 open(TMP,">>$tmp");
379 Pod::Text::pod2text($_,*TMP);
380 close(TMP);
381 } elsif(not $opt_u) {
1e422769 382 my $cmd = "pod2man --lax $_ | nroff -man";
383 $cmd .= " | col -x" if $^O =~ /hpux/;
384 $rslt = `$cmd`;
385 unless(($err = $?)) {
386 open(TMP,">>$tmp");
387 print TMP $rslt;
388 close TMP;
40fc7247 389 }
85880f03 390 }
4633a7c4 391
85880f03 392 if( $opt_u or $err or -z $tmp) {
4633a7c4
LW
393 open(OUT,">>$tmp");
394 open(IN,"<$_");
85880f03 395 $cut = 1;
396 while (<IN>) {
397 $cut = $1 eq 'cut' if /^=(\w+)/;
398 next if $cut;
399 print OUT;
400 }
4633a7c4
LW
401 close(IN);
402 close(OUT);
403 }
404}
405
31bdbec1 406if( $no_tty ) {
4633a7c4
LW
407 open(TMP,"<$tmp");
408 print while <TMP>;
409 close(TMP);
410} else {
85880f03 411 foreach $pager (@pagers) {
1e422769 412 system("$pager $tmp") or last;
4633a7c4
LW
413 }
414}
415
4161 while unlink($tmp); #Possibly pointless VMSism
417
418exit 0;
7eda7aea 419
420__END__
421
422=head1 NAME
423
424perldoc - Look up Perl documentation in pod format.
425
426=head1 SYNOPSIS
427
44a8e56a 428B<perldoc> [B<-h>] [B<-v>] [B<-t>] [B<-u>] [B<-m>] [B<-l>] PageName|ModuleName|ProgramName
7eda7aea 429
31bdbec1
GA
430B<perldoc> B<-f> BuiltinFunction
431
7eda7aea 432=head1 DESCRIPTION
433
40fc7247 434I<perldoc> looks up a piece of documentation in .pod format that is embedded
435in the perl installation tree or in a perl script, and displays it via
436C<pod2man | nroff -man | $PAGER>. (In addition, if running under HP-UX,
437C<col -x> will be used.) This is primarily used for the documentation for
438the perl library modules.
7eda7aea 439
440Your system may also have man pages installed for those modules, in
441which case you can probably just use the man(1) command.
442
443=head1 OPTIONS
444
445=over 5
446
447=item B<-h> help
448
449Prints out a brief help message.
450
451=item B<-v> verbose
452
453Describes search for the item in detail.
454
455=item B<-t> text output
456
457Display docs using plain text converter, instead of nroff. This may be faster,
458but it won't look as nice.
459
460=item B<-u> unformatted
461
462Find docs only; skip reformatting by pod2*
463
464=item B<-m> module
465
466Display the entire module: both code and unformatted pod documentation.
467This may be useful if the docs don't explain a function in the detail
468you need, and you'd like to inspect the code directly; perldoc will find
469the file for you and simply hand it off for display.
470
44a8e56a 471=item B<-l> file name only
472
473Display the file name of the module found.
474
31bdbec1
GA
475=item B<-f> perlfunc
476
477The B<-f> option followed by the name of a perl built in function will
478extract the documentation of this function from L<perlfunc>.
479
7eda7aea 480=item B<PageName|ModuleName|ProgramName>
481
482The item you want to look up. Nested modules (such as C<File::Basename>)
483are specified either as C<File::Basename> or C<File/Basename>. You may also
484give a descriptive name of a page, such as C<perlfunc>. You make also give a
485partial or wrong-case name, such as "basename" for "File::Basename", but
486this will be slower, if there is more then one page with the same partial
487name, you will only get the first one.
488
489=back
490
491=head1 ENVIRONMENT
492
493Any switches in the C<PERLDOC> environment variable will be used before the
494command line arguments. C<perldoc> also searches directories
495specified by the C<PERL5LIB> (or C<PERLLIB> if C<PERL5LIB> is not
496defined) and C<PATH> environment variables.
497(The latter is so that embedded pods for executables, such as
498C<perldoc> itself, are available.)
499
500=head1 AUTHOR
501
502Kenneth Albanowski <kjahds@kjahds.com>
503
504Minor updates by Andy Dougherty <doughera@lafcol.lafayette.edu>
505
7eda7aea 506=cut
507
508#
137443ea 509# Version 1.12: Sat Apr 12 22:41:09 EST 1997
510# Gurusamy Sarathy <gsar@umich.edu>
511# -various fixes for win32
7eda7aea 512# Version 1.11: Tue Dec 26 09:54:33 EST 1995
513# Kenneth Albanowski <kjahds@kjahds.com>
514# -added Charles Bailey's further VMS patches, and -u switch
515# -added -t switch, with pod2text support
516#
517# Version 1.10: Thu Nov 9 07:23:47 EST 1995
518# Kenneth Albanowski <kjahds@kjahds.com>
519# -added VMS support
520# -added better error recognition (on no found pages, just exit. On
521# missing nroff/pod2man, just display raw pod.)
522# -added recursive/case-insensitive matching (thanks, Andreas). This
523# slows things down a bit, unfortunately. Give a precise name, and
524# it'll run faster.
525#
526# Version 1.01: Tue May 30 14:47:34 EDT 1995
527# Andy Dougherty <doughera@lafcol.lafayette.edu>
528# -added pod documentation.
529# -added PATH searching.
530# -added searching pod/ subdirectory (mainly to pick up perlfunc.pod
531# and friends.
532#
533#
534# TODO:
535#
536# Cache directories read during sloppy match
4633a7c4
LW
537!NO!SUBS!
538
539close OUT or die "Can't close $file: $!";
540chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
541exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';