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