File Coverage

blib/lib/Module/Path/More.pm
Criterion Covered Total %
statement 56 63 88.8
branch 26 42 61.9
condition 15 24 62.5
subroutine 6 7 85.7
pod 2 2 100.0
total 105 138 76.0


line stmt bran cond sub pod time code
1             package Module::Path::More;
2              
3             our $DATE = '2017-02-01'; # DATE
4             our $VERSION = '0.32'; # VERSION
5              
6 1     1   16525 use 5.010001;
  1         4  
7 1     1   3 use strict;
  1         1  
  1         15  
8 1     1   3 use warnings;
  1         1  
  1         134  
9              
10             require Exporter;
11             our @ISA = qw(Exporter);
12             our @EXPORT_OK = qw(module_path pod_path);
13              
14             our $SEPARATOR;
15              
16             our %SPEC;
17              
18             $SPEC{':package'} = {
19             v => 1.1,
20             summary => 'Get path to locally installed Perl module',
21             };
22              
23             BEGIN {
24 1 50   1   7 if ($^O =~ /^(dos|os2)/i) {
    50          
25 0         0 $SEPARATOR = '\\';
26             } elsif ($^O =~ /^MacOS/i) {
27 0         0 $SEPARATOR = ':';
28             } else {
29 1         561 $SEPARATOR = '/';
30             }
31             }
32              
33             $SPEC{module_path} = {
34             v => 1.1,
35             summary => 'Get path to locally installed Perl module',
36             description => <<'_',
37              
38             Search `@INC` (reference entries are skipped) and return path(s) to Perl module
39             files with the requested name.
40              
41             This function is like the one from , except with a different
42             interface and more options (finding all matches instead of the first, the option
43             of not absolutizing paths, finding `.pmc` & `.pod` files, finding module
44             prefixes).
45              
46             _
47             args => {
48             module => {
49             summary => 'Module name to search',
50             schema => 'str*',
51             req => 1,
52             pos => 0,
53             },
54             find_pm => {
55             summary => 'Whether to find .pm files',
56             schema => ['int*', min=>0],
57             default => 1,
58             description => <<'_',
59              
60             The value of this option is an integer number from 0. 0 means to not search for
61             .pm files, while number larger than 0 means to search for .pm files. The larger
62             the number, the lower the priority. If more than one type is found (prefix, .pm,
63             .pmc, .pod) then the type with the lowest number is returned first.
64              
65             _
66             },
67             find_pmc => {
68             summary => 'Whether to find .pmc files',
69             schema => ['int*', min=>0],
70             default => 2,
71             description => <<'_',
72              
73             The value of this option is an integer number from 0. 0 means to not search for
74             .pmc files, while number larger than 0 means to search for .pmc files. The
75             larger the number, the lower the priority. If more than one type is found
76             (prefix, .pm, .pmc, .pod) then the type with the lowest number is returned
77             first.
78              
79             _
80             },
81             find_pod => {
82             summary => 'Whether to find .pod files',
83             schema => ['int*', min=>0],
84             default => 0,
85             description => <<'_',
86              
87             The value of this option is an integer number from 0. 0 means to not search for
88             .pod files, while number larger than 0 means to search for .pod files. The
89             larger the number, the lower the priority. If more than one type is found
90             (prefix, .pm, .pmc, .pod) then the type with the lowest number is returned
91             first.
92              
93             _
94             },
95             find_prefix => {
96             summary => 'Whether to find module prefixes',
97             schema => ['int*', min=>0],
98             default => 0,
99             description => <<'_',
100              
101             The value of this option is an integer number from 0. 0 means to not search for
102             module prefix, while number larger than 0 means to search for module prefix. The
103             larger the number, the lower the priority. If more than one type is found
104             (prefix, .pm, .pmc, .pod) then the type with the lowest number is returned
105             first.
106              
107             _
108             },
109             all => {
110             summary => 'Return all results instead of just the first',
111             schema => 'bool',
112             default => 0,
113             },
114             abs => {
115             summary => 'Whether to return absolute paths',
116             schema => 'bool',
117             default => 0,
118             },
119             },
120             result => {
121             schema => ['any' => of => ['str*', ['array*' => of => 'str*']]],
122             },
123             result_naked => 1,
124             examples => [
125             {
126             summary => 'Find the first Foo::Bar (.pm or .pmc) in @INC',
127             args => {module => 'Foo::Bar'},
128             },
129             {
130             summary => 'Find all Foo::Bar (.pm or .pmc) in @INC, return absolute paths',
131             args => {module => 'Foo::Bar', all => 1, abs => 1},
132             },
133             {
134             summary => 'Find the Rinci (.pod first, then .pm) in @INC',
135             args => {module => 'Rinci', find_pod => 1, find_pm => 2, find_pmc => 0},
136             },
137             ],
138             };
139             sub module_path {
140 13     13 1 2691 my %args = @_;
141              
142 13 50       31 my $module = $args{module} or die "Please specify module";
143              
144 13   50     41 $args{abs} //= 0;
145 13   50     34 $args{all} //= 0;
146 13   100     27 $args{find_pm} //= 1;
147 13   100     27 $args{find_pmc} //= 2;
148 13   100     25 $args{find_pod} //= 0;
149 13   100     28 $args{find_prefix} //= 0;
150              
151 13 50       18 require Cwd if $args{abs};
152              
153 13         8 my @res;
154             my %unfound = (
155             ("pm" => 1) x !!$args{find_pm},
156             ("pmc" => 1) x !!$args{find_pmc},
157             ("pod" => 1) x !!$args{find_pod},
158             ("prefix" => 1) x !!$args{find_prefix},
159 13         38 );
160             my $add = sub {
161 23     23   26 my ($path, $prio) = @_;
162 23 50       54 push @res, [$args{abs} ? Cwd::abs_path($path) : $path, $prio];
163 13         34 };
164              
165 13         11 my $relpath;
166              
167 13         19 ($relpath = $module) =~ s/::/$SEPARATOR/g;
168 13         20 $relpath =~ s/\.(pm|pmc|pod)\z//i;
169              
170 13         16 foreach my $dir (@INC) {
171 142 50       171 next if not defined($dir);
172 142 50       150 next if ref($dir);
173              
174 142         142 my $prefix = $dir . $SEPARATOR . $relpath;
175 142 50       154 if ($args{find_pm}) {
176 142         121 my $file = $prefix . ".pm";
177 142 100       1331 if (-f $file) {
178 15         26 $add->($file, $args{find_pm});
179 15         18 delete $unfound{pm};
180 15 0 33     26 last if !keys(%unfound) && !$args{all};
181             }
182             }
183 142 100       168 if ($args{find_pmc}) {
184 114         97 my $file = $prefix . ".pmc";
185 114 50       1243 if (-f $file) {
186 0         0 $add->($file, $args{find_pmc});
187 0         0 delete $unfound{pmc};
188 0 0 0     0 last if !keys(%unfound) && !$args{all};
189             }
190             }
191 142 100       160 if ($args{find_pod}) {
192 28         20 my $file = $prefix . ".pod";
193 28 100       293 if (-f $file) {
194 3         5 $add->($file, $args{find_pod});
195 3         4 delete $unfound{pod};
196 3 50 66     12 last if !keys(%unfound) && !$args{all};
197             }
198             }
199 140 100       234 if ($args{find_prefix}) {
200 21 100       232 if (-d $prefix) {
201 5         10 $add->($prefix, $args{find_prefix});
202 5         3 delete $unfound{prefix};
203 5 50 66     16 last if !keys(%unfound) && !$args{all};
204             }
205             }
206             }
207              
208 13         27 @res = map { $_->[0] } sort { $a->[1] <=> $b->[1] } @res;
  23         42  
  14         19  
209              
210 13 50       23 if ($args{all}) {
211 0         0 return \@res;
212             } else {
213 13 100       100 return @res ? $res[0] : undef;
214             }
215             }
216              
217             $SPEC{pod_path} = {
218             v => 1.1,
219             summary => 'Get path to locally installed POD',
220             description => <<'_',
221              
222             This is a shortcut for:
223              
224             module_path(%args, find_pm=>0, find_pmc=>0, find_pod=>1, find_prefix=>0)
225              
226             _
227             args => {
228             module => {
229             summary => 'Module name to search',
230             schema => 'str*',
231             req => 1,
232             pos => 0,
233             },
234             all => {
235             summary => 'Return all results instead of just the first',
236             schema => 'bool',
237             default => 0,
238             },
239             abs => {
240             summary => 'Whether to return absolute paths',
241             schema => 'bool',
242             default => 0,
243             },
244             },
245             result => {
246             schema => ['any' => of => ['str*', ['array*' => of => 'str*']]],
247             },
248             result_naked => 1,
249             };
250             sub pod_path {
251 0     0 1   module_path(@_, find_pm=>0, find_pmc=>0, find_pod=>1, find_prefix=>0);
252             }
253              
254             1;
255             # ABSTRACT: Get path to locally installed Perl module
256              
257             __END__