line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
############################################################################# |
2
|
|
|
|
|
|
|
# Pod/Find.pm -- finds files containing POD documentation |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Author: Marek Rouchal |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Copyright (C) 1999-2000 by Marek Rouchal (and borrowing code |
7
|
|
|
|
|
|
|
# from Nick Ing-Simmon's PodToHtml). All rights reserved. |
8
|
|
|
|
|
|
|
# This file is part of "PodParser". Pod::Find is free software; |
9
|
|
|
|
|
|
|
# you can redistribute it and/or modify it under the same terms |
10
|
|
|
|
|
|
|
# as Perl itself. |
11
|
|
|
|
|
|
|
############################################################################# |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package Pod::Find; |
14
|
|
|
|
|
|
|
use strict; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
use vars qw($VERSION); |
17
|
|
|
|
|
|
|
$VERSION = '1.64'; ## Current version of this package |
18
|
|
|
|
|
|
|
require 5.005; ## requires this Perl version or later |
19
|
|
|
|
|
|
|
use Carp; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
BEGIN { |
22
|
|
|
|
|
|
|
if ($] < 5.006) { |
23
|
|
|
|
|
|
|
require Symbol; |
24
|
|
|
|
|
|
|
import Symbol; |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
############################################################################# |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 NAME |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Pod::Find - find POD documents in directory trees |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 SYNOPSIS |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
use Pod::Find qw(pod_find simplify_name); |
37
|
|
|
|
|
|
|
my %pods = pod_find({ -verbose => 1, -inc => 1 }); |
38
|
|
|
|
|
|
|
foreach(keys %pods) { |
39
|
|
|
|
|
|
|
print "found library POD `$pods{$_}' in $_\n"; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
print "podname=",simplify_name('a/b/c/mymodule.pod'),"\n"; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
$location = pod_where( { -inc => 1 }, "Pod::Find" ); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 DESCRIPTION |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
B
|
49
|
|
|
|
|
|
|
higher) are going to remove Pod-Parser from core and use L |
50
|
|
|
|
|
|
|
for all things POD.> |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
B provides a set of functions to locate POD files. Note that |
53
|
|
|
|
|
|
|
no function is exported by default to avoid pollution of your namespace, |
54
|
|
|
|
|
|
|
so be sure to specify them in the B |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
use Pod::Find qw(pod_find); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
From this version on the typical SCM (software configuration management) |
59
|
|
|
|
|
|
|
directories are ignored. These are: RCS, CVS, SCCS, .svn, .hg, .git, .sync |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=cut |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
#use diagnostics; |
64
|
|
|
|
|
|
|
use Exporter; |
65
|
|
|
|
|
|
|
use File::Spec; |
66
|
|
|
|
|
|
|
use File::Find; |
67
|
|
|
|
|
|
|
use Cwd qw(abs_path cwd); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
use vars qw(@ISA @EXPORT_OK $VERSION); |
70
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
71
|
|
|
|
|
|
|
@EXPORT_OK = qw(&pod_find &simplify_name &pod_where &contains_pod); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# package global variables |
74
|
|
|
|
|
|
|
my $SIMPLIFY_RX; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=head2 C |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
The function B searches for POD documents in a given set of |
79
|
|
|
|
|
|
|
files and/or directories. It returns a hash with the file names as keys |
80
|
|
|
|
|
|
|
and the POD name as value. The POD name is derived from the file name |
81
|
|
|
|
|
|
|
and its position in the directory tree. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
E.g. when searching in F<$HOME/perl5lib>, the file |
84
|
|
|
|
|
|
|
F<$HOME/perl5lib/MyModule.pm> would get the POD name I, |
85
|
|
|
|
|
|
|
whereas F<$HOME/perl5lib/Myclass/Subclass.pm> would be |
86
|
|
|
|
|
|
|
I. The name information can be used for POD |
87
|
|
|
|
|
|
|
translators. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
Only text files containing at least one valid POD command are found. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
A warning is printed if more than one POD file with the same POD name |
92
|
|
|
|
|
|
|
is found, e.g. F in different directories. This usually |
93
|
|
|
|
|
|
|
indicates duplicate occurrences of modules in the I<@INC> search path. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
B The first argument for B may be a hash reference |
96
|
|
|
|
|
|
|
with options. The rest are either directories that are searched |
97
|
|
|
|
|
|
|
recursively or files. The POD names of files are the plain basenames |
98
|
|
|
|
|
|
|
with any Perl-like extension (.pm, .pl, .pod) stripped. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=over 4 |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=item C<-verbose =E 1> |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
Print progress information while scanning. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item C<-perl =E 1> |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
Apply Perl-specific heuristics to find the correct PODs. This includes |
109
|
|
|
|
|
|
|
stripping Perl-like extensions, omitting subdirectories that are numeric |
110
|
|
|
|
|
|
|
but do I match the current Perl interpreter's version id, suppressing |
111
|
|
|
|
|
|
|
F as a module hierarchy name etc. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=item C<-script =E 1> |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Search for PODs in the current Perl interpreter's installation |
116
|
|
|
|
|
|
|
B. This is taken from the local L module. |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=item C<-inc =E 1> |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Search for PODs in the current Perl interpreter's I<@INC> paths. This |
121
|
|
|
|
|
|
|
automatically considers paths specified in the C environment |
122
|
|
|
|
|
|
|
as this is included in I<@INC> by the Perl interpreter itself. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=back |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=cut |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# return a hash of the POD files found |
129
|
|
|
|
|
|
|
# first argument may be a hashref (options), |
130
|
|
|
|
|
|
|
# rest is a list of directories to search recursively |
131
|
|
|
|
|
|
|
sub pod_find |
132
|
|
|
|
|
|
|
{ |
133
|
0
|
|
|
0
|
1
|
|
my %opts; |
134
|
0
|
0
|
|
|
|
|
if(ref $_[0]) { |
135
|
0
|
|
|
|
|
|
%opts = %{shift()}; |
|
0
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
0
|
|
0
|
|
|
|
$opts{-verbose} ||= 0; |
139
|
0
|
|
0
|
|
|
|
$opts{-perl} ||= 0; |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
my (@search) = @_; |
142
|
|
|
|
|
|
|
|
143
|
0
|
0
|
|
|
|
|
if($opts{-script}) { |
144
|
0
|
|
|
|
|
|
require Config; |
145
|
|
|
|
|
|
|
push(@search, $Config::Config{scriptdir}) |
146
|
0
|
0
|
|
|
|
|
if -d $Config::Config{scriptdir}; |
147
|
0
|
|
|
|
|
|
$opts{-perl} = 1; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
0
|
0
|
|
|
|
|
if($opts{-inc}) { |
151
|
0
|
0
|
|
|
|
|
if ($^O eq 'MacOS') { |
152
|
|
|
|
|
|
|
# tolerate '.', './some_dir' and '(../)+some_dir' on Mac OS |
153
|
0
|
|
|
|
|
|
my @new_INC = @INC; |
154
|
0
|
|
|
|
|
|
for (@new_INC) { |
155
|
0
|
0
|
|
|
|
|
if ( $_ eq '.' ) { |
|
|
0
|
|
|
|
|
|
156
|
0
|
|
|
|
|
|
$_ = ':'; |
157
|
0
|
|
|
|
|
|
} elsif ( $_ =~ s{^((?:\.\./)+)}{':' x (length($1)/3)}e ) { |
158
|
0
|
|
|
|
|
|
$_ = ':'. $_; |
159
|
|
|
|
|
|
|
} else { |
160
|
0
|
|
|
|
|
|
$_ =~ s{^\./}{:}; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
} |
163
|
0
|
|
|
|
|
|
push(@search, grep($_ ne File::Spec->curdir, @new_INC)); |
164
|
|
|
|
|
|
|
} else { |
165
|
0
|
|
|
|
|
|
my %seen; |
166
|
0
|
|
|
|
|
|
my $curdir = File::Spec->curdir; |
167
|
0
|
|
|
|
|
|
foreach(@INC) { |
168
|
0
|
0
|
|
|
|
|
next if $_ eq $curdir; |
169
|
0
|
|
|
|
|
|
my $path = abs_path($_); |
170
|
0
|
0
|
|
|
|
|
push(@search, $path) unless $seen{$path}++; |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
$opts{-perl} = 1; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
0
|
0
|
|
|
|
|
if($opts{-perl}) { |
178
|
0
|
|
|
|
|
|
require Config; |
179
|
|
|
|
|
|
|
# this code simplifies the POD name for Perl modules: |
180
|
|
|
|
|
|
|
# * remove "site_perl" |
181
|
|
|
|
|
|
|
# * remove e.g. "i586-linux" (from 'archname') |
182
|
|
|
|
|
|
|
# * remove e.g. 5.00503 |
183
|
|
|
|
|
|
|
# * remove pod/ if followed by *.pod (e.g. in pod/perlfunc.pod) |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Mac OS: |
186
|
|
|
|
|
|
|
# * remove ":?site_perl:" |
187
|
|
|
|
|
|
|
# * remove :?pod: if followed by *.pod (e.g. in :pod:perlfunc.pod) |
188
|
|
|
|
|
|
|
|
189
|
0
|
0
|
|
|
|
|
if ($^O eq 'MacOS') { |
190
|
0
|
|
|
|
|
|
$SIMPLIFY_RX = |
191
|
|
|
|
|
|
|
qq!^(?i:\:?site_perl\:|\:?pod\:(?=.*?\\.pod\\z))*!; |
192
|
|
|
|
|
|
|
} else { |
193
|
0
|
|
|
|
|
|
$SIMPLIFY_RX = |
194
|
|
|
|
|
|
|
qq!^(?i:site(_perl)?/|\Q$Config::Config{archname}\E/|\\d+\\.\\d+([_.]?\\d+)?/|pod/(?=.*?\\.pod\\z))*!; |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
0
|
|
|
|
|
|
my %dirs_visited; |
199
|
|
|
|
|
|
|
my %pods; |
200
|
0
|
|
|
|
|
|
my %names; |
201
|
0
|
|
|
|
|
|
my $pwd = cwd(); |
202
|
|
|
|
|
|
|
|
203
|
0
|
|
|
|
|
|
foreach my $try (@search) { |
204
|
0
|
0
|
|
|
|
|
unless(File::Spec->file_name_is_absolute($try)) { |
205
|
|
|
|
|
|
|
# make path absolute |
206
|
0
|
|
|
|
|
|
$try = File::Spec->catfile($pwd,$try); |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
# simplify path |
209
|
|
|
|
|
|
|
# on VMS canonpath will vmsify:[the.path], but File::Find::find |
210
|
|
|
|
|
|
|
# wants /unixy/paths |
211
|
0
|
0
|
|
|
|
|
if ($^O eq 'VMS') { |
212
|
0
|
|
|
|
|
|
$try = VMS::Filespec::unixify($try); |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
else { |
215
|
0
|
|
|
|
|
|
$try = File::Spec->canonpath($try); |
216
|
|
|
|
|
|
|
} |
217
|
0
|
|
|
|
|
|
my $name; |
218
|
0
|
0
|
|
|
|
|
if(-f $try) { |
219
|
0
|
0
|
|
|
|
|
if($name = _check_and_extract_name($try, $opts{-verbose})) { |
220
|
0
|
|
|
|
|
|
_check_for_duplicates($try, $name, \%names, \%pods); |
221
|
|
|
|
|
|
|
} |
222
|
0
|
|
|
|
|
|
next; |
223
|
|
|
|
|
|
|
} |
224
|
0
|
0
|
|
|
|
|
my $root_rx = $^O eq 'MacOS' ? qq!^\Q$try\E! : qq!^\Q$try\E/!; |
225
|
0
|
|
|
|
|
|
$root_rx=~ s|//$|/|; # remove trailing double slash |
226
|
|
|
|
|
|
|
File::Find::find( sub { |
227
|
0
|
|
|
0
|
|
|
my $item = $File::Find::name; |
228
|
0
|
0
|
|
|
|
|
if(-d) { |
229
|
0
|
0
|
|
|
|
|
if($item =~ m{/(?:RCS|CVS|SCCS|\.svn|\.hg|\.git|\.sync)$}) { |
|
|
0
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
$File::Find::prune = 1; |
231
|
0
|
|
|
|
|
|
return; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
elsif($dirs_visited{$item}) { |
234
|
|
|
|
|
|
|
warn "Directory '$item' already seen, skipping.\n" |
235
|
0
|
0
|
|
|
|
|
if($opts{-verbose}); |
236
|
0
|
|
|
|
|
|
$File::Find::prune = 1; |
237
|
0
|
|
|
|
|
|
return; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
else { |
240
|
0
|
|
|
|
|
|
$dirs_visited{$item} = 1; |
241
|
|
|
|
|
|
|
} |
242
|
0
|
0
|
0
|
|
|
|
if($opts{-perl} && /^(\d+\.[\d_]+)\z/s && eval "$1" != $]) { |
|
|
|
0
|
|
|
|
|
243
|
0
|
|
|
|
|
|
$File::Find::prune = 1; |
244
|
|
|
|
|
|
|
warn "Perl $] version mismatch on $_, skipping.\n" |
245
|
0
|
0
|
|
|
|
|
if($opts{-verbose}); |
246
|
|
|
|
|
|
|
} |
247
|
0
|
|
|
|
|
|
return; |
248
|
|
|
|
|
|
|
} |
249
|
0
|
0
|
|
|
|
|
if($name = _check_and_extract_name($item, $opts{-verbose}, $root_rx)) { |
250
|
0
|
|
|
|
|
|
_check_for_duplicates($item, $name, \%names, \%pods); |
251
|
|
|
|
|
|
|
} |
252
|
0
|
|
|
|
|
|
}, $try); # end of File::Find::find |
253
|
|
|
|
|
|
|
} |
254
|
0
|
|
|
|
|
|
chdir $pwd; |
255
|
0
|
|
|
|
|
|
return %pods; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub _check_for_duplicates { |
259
|
0
|
|
|
0
|
|
|
my ($file, $name, $names_ref, $pods_ref) = @_; |
260
|
0
|
0
|
|
|
|
|
if($$names_ref{$name}) { |
261
|
0
|
|
|
|
|
|
warn "Duplicate POD found (shadowing?): $name ($file)\n"; |
262
|
|
|
|
|
|
|
warn ' Already seen in ', |
263
|
0
|
|
|
|
|
|
join(' ', grep($$pods_ref{$_} eq $name, keys %$pods_ref)),"\n"; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
else { |
266
|
0
|
|
|
|
|
|
$$names_ref{$name} = 1; |
267
|
|
|
|
|
|
|
} |
268
|
0
|
|
|
|
|
|
return $$pods_ref{$file} = $name; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub _check_and_extract_name { |
272
|
0
|
|
|
0
|
|
|
my ($file, $verbose, $root_rx) = @_; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# check extension or executable flag |
275
|
|
|
|
|
|
|
# this involves testing the .bat extension on Win32! |
276
|
0
|
0
|
0
|
|
|
|
unless(-f $file && -T $file && ($file =~ /\.(pod|pm|plx?)\z/i || -x $file )) { |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
277
|
0
|
|
|
|
|
|
return; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
0
|
0
|
|
|
|
|
return unless contains_pod($file,$verbose); |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
# strip non-significant path components |
283
|
|
|
|
|
|
|
# TODO what happens on e.g. Win32? |
284
|
0
|
|
|
|
|
|
my $name = $file; |
285
|
0
|
0
|
|
|
|
|
if(defined $root_rx) { |
286
|
0
|
|
|
|
|
|
$name =~ s/$root_rx//is; |
287
|
0
|
0
|
|
|
|
|
$name =~ s/$SIMPLIFY_RX//is if(defined $SIMPLIFY_RX); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
else { |
290
|
0
|
0
|
|
|
|
|
if ($^O eq 'MacOS') { |
291
|
0
|
|
|
|
|
|
$name =~ s/^.*://s; |
292
|
|
|
|
|
|
|
} else { |
293
|
0
|
|
|
|
|
|
$name =~ s{^.*/}{}s; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
} |
296
|
0
|
|
|
|
|
|
_simplify($name); |
297
|
0
|
|
|
|
|
|
$name =~ s{/+}{::}g; |
298
|
0
|
0
|
|
|
|
|
if ($^O eq 'MacOS') { |
299
|
0
|
|
|
|
|
|
$name =~ s{:+}{::}g; # : -> :: |
300
|
|
|
|
|
|
|
} else { |
301
|
0
|
|
|
|
|
|
$name =~ s{/+}{::}g; # / -> :: |
302
|
|
|
|
|
|
|
} |
303
|
0
|
|
|
|
|
|
return $name; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 C |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
The function B is equivalent to B, but also |
309
|
|
|
|
|
|
|
strips Perl-like extensions (.pm, .pl, .pod) and extensions like |
310
|
|
|
|
|
|
|
F<.bat>, F<.cmd> on Win32 and OS/2, or F<.com> on VMS, respectively. |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=cut |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# basic simplification of the POD name: |
315
|
|
|
|
|
|
|
# basename & strip extension |
316
|
|
|
|
|
|
|
sub simplify_name { |
317
|
0
|
|
|
0
|
1
|
|
my ($str) = @_; |
318
|
|
|
|
|
|
|
# remove all path components |
319
|
0
|
0
|
|
|
|
|
if ($^O eq 'MacOS') { |
320
|
0
|
|
|
|
|
|
$str =~ s/^.*://s; |
321
|
|
|
|
|
|
|
} else { |
322
|
0
|
|
|
|
|
|
$str =~ s{^.*/}{}s; |
323
|
|
|
|
|
|
|
} |
324
|
0
|
|
|
|
|
|
_simplify($str); |
325
|
0
|
|
|
|
|
|
return $str; |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# internal sub only |
329
|
|
|
|
|
|
|
sub _simplify { |
330
|
|
|
|
|
|
|
# strip Perl's own extensions |
331
|
0
|
|
|
0
|
|
|
$_[0] =~ s/\.(pod|pm|plx?)\z//i; |
332
|
|
|
|
|
|
|
# strip meaningless extensions on Win32 and OS/2 |
333
|
0
|
0
|
|
|
|
|
$_[0] =~ s/\.(bat|exe|cmd)\z//i if($^O =~ /mswin|os2/i); |
334
|
|
|
|
|
|
|
# strip meaningless extensions on VMS |
335
|
0
|
0
|
|
|
|
|
$_[0] =~ s/\.(com)\z//i if($^O eq 'VMS'); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# contribution from Tim Jenness |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head2 C |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
Returns the location of a pod document given a search directory |
343
|
|
|
|
|
|
|
and a module (e.g. C) or script (e.g. C) name. |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
Options: |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=over 4 |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=item C<-inc =E 1> |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
Search @INC for the pod and also the C defined in the |
352
|
|
|
|
|
|
|
L module. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=item C<-dirs =E [ $dir1, $dir2, ... ]> |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
Reference to an array of search directories. These are searched in order |
357
|
|
|
|
|
|
|
before looking in C<@INC> (if B<-inc>). Current directory is used if |
358
|
|
|
|
|
|
|
none are specified. |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=item C<-verbose =E 1> |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
List directories as they are searched |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=back |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
Returns the full path of the first occurrence to the file. |
367
|
|
|
|
|
|
|
Package names (eg 'A::B') are automatically converted to directory |
368
|
|
|
|
|
|
|
names in the selected directory. (eg on unix 'A::B' is converted to |
369
|
|
|
|
|
|
|
'A/B'). Additionally, '.pm', '.pl' and '.pod' are appended to the |
370
|
|
|
|
|
|
|
search automatically if required. |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
A subdirectory F is also checked if it exists in any of the given |
373
|
|
|
|
|
|
|
search directories. This ensures that e.g. L is |
374
|
|
|
|
|
|
|
found. |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
It is assumed that if a module name is supplied, that that name |
377
|
|
|
|
|
|
|
matches the file name. Pods are not opened to check for the 'NAME' |
378
|
|
|
|
|
|
|
entry. |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
A check is made to make sure that the file that is found does |
381
|
|
|
|
|
|
|
contain some pod documentation. |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=cut |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
sub pod_where { |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
# default options |
388
|
0
|
|
|
0
|
1
|
|
my %options = ( |
389
|
|
|
|
|
|
|
'-inc' => 0, |
390
|
|
|
|
|
|
|
'-verbose' => 0, |
391
|
|
|
|
|
|
|
'-dirs' => [ File::Spec->curdir ], |
392
|
|
|
|
|
|
|
); |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
# Check for an options hash as first argument |
395
|
0
|
0
|
0
|
|
|
|
if (defined $_[0] && ref($_[0]) eq 'HASH') { |
396
|
0
|
|
|
|
|
|
my $opt = shift; |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# Merge default options with supplied options |
399
|
0
|
|
|
|
|
|
%options = (%options, %$opt); |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
# Check usage |
403
|
0
|
0
|
|
|
|
|
carp 'Usage: pod_where({options}, $pod)' unless (scalar(@_)); |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# Read argument |
406
|
0
|
|
|
|
|
|
my $pod = shift; |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
# Split on :: and then join the name together using File::Spec |
409
|
0
|
|
|
|
|
|
my @parts = split (/::/, $pod); |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
# Get full directory list |
412
|
0
|
|
|
|
|
|
my @search_dirs = @{ $options{'-dirs'} }; |
|
0
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
|
414
|
0
|
0
|
|
|
|
|
if ($options{'-inc'}) { |
415
|
|
|
|
|
|
|
|
416
|
0
|
|
|
|
|
|
require Config; |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# Add @INC |
419
|
0
|
0
|
0
|
|
|
|
if ($^O eq 'MacOS' && $options{'-inc'}) { |
|
|
0
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# tolerate '.', './some_dir' and '(../)+some_dir' on Mac OS |
421
|
0
|
|
|
|
|
|
my @new_INC = @INC; |
422
|
0
|
|
|
|
|
|
for (@new_INC) { |
423
|
0
|
0
|
|
|
|
|
if ( $_ eq '.' ) { |
|
|
0
|
|
|
|
|
|
424
|
0
|
|
|
|
|
|
$_ = ':'; |
425
|
0
|
|
|
|
|
|
} elsif ( $_ =~ s{^((?:\.\./)+)}{':' x (length($1)/3)}e ) { |
426
|
0
|
|
|
|
|
|
$_ = ':'. $_; |
427
|
|
|
|
|
|
|
} else { |
428
|
0
|
|
|
|
|
|
$_ =~ s{^\./}{:}; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
} |
431
|
0
|
|
|
|
|
|
push (@search_dirs, @new_INC); |
432
|
|
|
|
|
|
|
} elsif ($options{'-inc'}) { |
433
|
0
|
|
|
|
|
|
push (@search_dirs, @INC); |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# Add location of pod documentation for perl man pages (eg perlfunc) |
437
|
|
|
|
|
|
|
# This is a pod directory in the private install tree |
438
|
|
|
|
|
|
|
#my $perlpoddir = File::Spec->catdir($Config::Config{'installprivlib'}, |
439
|
|
|
|
|
|
|
# 'pod'); |
440
|
|
|
|
|
|
|
#push (@search_dirs, $perlpoddir) |
441
|
|
|
|
|
|
|
# if -d $perlpoddir; |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# Add location of binaries such as pod2text |
444
|
|
|
|
|
|
|
push (@search_dirs, $Config::Config{'scriptdir'}) |
445
|
0
|
0
|
|
|
|
|
if -d $Config::Config{'scriptdir'}; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
warn 'Search path is: '.join(' ', @search_dirs)."\n" |
449
|
0
|
0
|
|
|
|
|
if $options{'-verbose'}; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# Loop over directories |
452
|
0
|
|
|
|
|
|
Dir: foreach my $dir ( @search_dirs ) { |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# Don't bother if can't find the directory |
455
|
0
|
0
|
|
|
|
|
if (-d $dir) { |
456
|
|
|
|
|
|
|
warn "Looking in directory $dir\n" |
457
|
0
|
0
|
|
|
|
|
if $options{'-verbose'}; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# Now concatenate this directory with the pod we are searching for |
460
|
0
|
|
|
|
|
|
my $fullname = File::Spec->catfile($dir, @parts); |
461
|
0
|
0
|
|
|
|
|
$fullname = VMS::Filespec::unixify($fullname) if $^O eq 'VMS'; |
462
|
|
|
|
|
|
|
warn "Filename is now $fullname\n" |
463
|
0
|
0
|
|
|
|
|
if $options{'-verbose'}; |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
# Loop over possible extensions |
466
|
0
|
|
|
|
|
|
foreach my $ext ('', '.pod', '.pm', '.pl') { |
467
|
0
|
|
|
|
|
|
my $fullext = $fullname . $ext; |
468
|
0
|
0
|
0
|
|
|
|
if (-f $fullext && |
469
|
|
|
|
|
|
|
contains_pod($fullext, $options{'-verbose'}) ) { |
470
|
0
|
0
|
|
|
|
|
warn "FOUND: $fullext\n" if $options{'-verbose'}; |
471
|
0
|
|
|
|
|
|
return $fullext; |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
} else { |
475
|
|
|
|
|
|
|
warn "Directory $dir does not exist\n" |
476
|
0
|
0
|
|
|
|
|
if $options{'-verbose'}; |
477
|
0
|
|
|
|
|
|
next Dir; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
# for some strange reason the path on MacOS/darwin/cygwin is |
480
|
|
|
|
|
|
|
# 'pods' not 'pod' |
481
|
|
|
|
|
|
|
# this could be the case also for other systems that |
482
|
|
|
|
|
|
|
# have a case-tolerant file system, but File::Spec |
483
|
|
|
|
|
|
|
# does not recognize 'darwin' yet. And cygwin also has "pods", |
484
|
|
|
|
|
|
|
# but is not case tolerant. Oh well... |
485
|
0
|
0
|
0
|
|
|
|
if((File::Spec->case_tolerant || $^O =~ /macos|darwin|cygwin/i) |
|
|
|
0
|
|
|
|
|
486
|
|
|
|
|
|
|
&& -d File::Spec->catdir($dir,'pods')) { |
487
|
0
|
|
|
|
|
|
$dir = File::Spec->catdir($dir,'pods'); |
488
|
0
|
|
|
|
|
|
redo Dir; |
489
|
|
|
|
|
|
|
} |
490
|
0
|
0
|
|
|
|
|
if(-d File::Spec->catdir($dir,'pod')) { |
491
|
0
|
|
|
|
|
|
$dir = File::Spec->catdir($dir,'pod'); |
492
|
0
|
|
|
|
|
|
redo Dir; |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
# No match; |
496
|
0
|
|
|
|
|
|
return; |
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=head2 C |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Returns true if the supplied filename (not POD module) contains some pod |
502
|
|
|
|
|
|
|
information. |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=cut |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
sub contains_pod { |
507
|
0
|
|
|
0
|
1
|
|
my $file = shift; |
508
|
0
|
|
|
|
|
|
my $verbose = 0; |
509
|
0
|
0
|
|
|
|
|
$verbose = shift if @_; |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
# check for one line of POD |
512
|
0
|
|
|
|
|
|
my $podfh; |
513
|
0
|
0
|
|
|
|
|
if ($] < 5.006) { |
514
|
0
|
|
|
|
|
|
$podfh = gensym(); |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
0
|
0
|
|
|
|
|
unless(open($podfh,"<$file")) { |
518
|
0
|
|
|
|
|
|
warn "Error: $file is unreadable: $!\n"; |
519
|
0
|
|
|
|
|
|
return; |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
|
522
|
0
|
|
|
|
|
|
local $/ = undef; |
523
|
0
|
|
|
|
|
|
my $pod = <$podfh>; |
524
|
0
|
0
|
|
|
|
|
close($podfh) || die "Error closing $file: $!\n"; |
525
|
0
|
0
|
|
|
|
|
unless($pod =~ /^=(head\d|pod|over|item|cut)\b/m) { |
526
|
0
|
0
|
|
|
|
|
warn "No POD in $file, skipping.\n" |
527
|
|
|
|
|
|
|
if($verbose); |
528
|
0
|
|
|
|
|
|
return 0; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
|
531
|
0
|
|
|
|
|
|
return 1; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=head1 AUTHOR |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
Please report bugs using L. |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
Marek Rouchal Emarekr@cpan.orgE, |
539
|
|
|
|
|
|
|
heavily borrowing code from Nick Ing-Simmons' PodToHtml. |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
Tim Jenness Et.jenness@jach.hawaii.eduE provided |
542
|
|
|
|
|
|
|
C and C. |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
B is part of the L distribution. |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=head1 SEE ALSO |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
L, L, L |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
=cut |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
1; |
553
|
|
|
|
|
|
|
|