File Coverage

blib/lib/SHARYANTO/Module/Path.pm
Criterion Covered Total %
statement 48 59 81.3
branch 22 42 52.3
condition 7 12 58.3
subroutine 7 8 87.5
pod 1 1 100.0
total 85 122 69.6


line stmt bran cond sub pod time code
1             package SHARYANTO::Module::Path;
2              
3 1     1   655 use 5.010001;
  1         2  
  1         33  
4 1     1   5 use strict;
  1         1  
  1         24  
5 1     1   4 use warnings;
  1         2  
  1         21  
6              
7 1     1   885 use Perinci::Sub::Util qw(gen_modified_sub);
  1         1778  
  1         172  
8              
9             require Exporter;
10             our @ISA = qw(Exporter);
11             our @EXPORT_OK = qw(module_path pod_path);
12              
13             our $VERSION = '0.20'; # VERSION
14             our $DATE = '2014-08-26'; # DATE
15              
16             my $SEPARATOR;
17              
18             our %SPEC;
19              
20             BEGIN {
21 1 50   1   16 if ($^O =~ /^(dos|os2)/i) {
    50          
22 0         0 $SEPARATOR = '\\';
23             } elsif ($^O =~ /^MacOS/i) {
24 0         0 $SEPARATOR = ':';
25             } else {
26 1         572 $SEPARATOR = '/';
27             }
28             }
29              
30             $SPEC{module_path} = {
31             v => 1.1,
32             summary => 'Get path to locally installed Perl module',
33             description => <<'_',
34              
35             Search `@INC` (reference entries are skipped) and return path(s) to Perl module
36             files with the requested name.
37              
38             This function is like the one from `Module::Path`, except with a different
39             interface and more options (finding all matches instead of the first, the option
40             of not absolutizing paths, finding `.pmc` & `.pod` files, finding module
41             prefixes).
42              
43             _
44             args => {
45             module => {
46             summary => 'Module name to search',
47             schema => 'str*',
48             req => 1,
49             pos => 0,
50             },
51             find_pm => {
52             summary => 'Whether to find .pm files',
53             schema => 'bool',
54             default => 1,
55             },
56             find_pmc => {
57             summary => 'Whether to find .pmc files',
58             schema => 'bool',
59             default => 1,
60             },
61             find_pod => {
62             summary => 'Whether to find .pod files',
63             schema => 'bool',
64             default => 0,
65             },
66             find_prefix => {
67             summary => 'Whether to find module prefixes',
68             schema => 'bool',
69             default => 1,
70             },
71             all => {
72             summary => 'Return all results instead of just the first',
73             schema => 'bool',
74             default => 0,
75             },
76             abs => {
77             summary => 'Whether to return absolute paths',
78             schema => 'bool',
79             default => 0,
80             },
81             },
82             result => {
83             schema => ['any' => of => ['str*', ['array*' => of => 'str*']]],
84             },
85             result_naked => 1,
86             };
87             sub module_path {
88 6     6 1 1803 my %args = @_;
89              
90 6 50       21 my $module = $args{module} or die "Please specify module";
91              
92 6   50     31 $args{abs} //= 0;
93 6   50     24 $args{all} //= 0;
94 6   50     22 $args{find_pm} //= 1;
95 6   50     20 $args{find_pmc} //= 1;
96 6   50     23 $args{find_pod} //= 0;
97 6   100     19 $args{find_prefix} //= 0;
98              
99 6 50       12 require Cwd if $args{abs};
100              
101 6         9 my @res;
102 6 50   5   27 my $add = sub { push @res, $args{abs} ? Cwd::abs_path($_[0]) : $_[0] };
  5         21  
103              
104 6         9 my $relpath;
105              
106 6         16 ($relpath = $module) =~ s/::/$SEPARATOR/g;
107 6         17 $relpath =~ s/\.(pm|pmc|pod)\z//i;
108              
109 6         10 foreach my $dir (@INC) {
110 43 50       81 next if not defined($dir);
111 43 50       78 next if ref($dir);
112              
113 43         75 my $prefix = $dir . $SEPARATOR . $relpath;
114 43 50       81 if ($args{find_pmc}) {
115 43         68 my $file = $prefix . ".pmc";
116 43 50       931 if (-f $file) {
117 0         0 $add->($file);
118 0 0       0 last unless $args{all};
119             }
120             }
121 43 50       90 if ($args{find_pm}) {
122 43         64 my $file = $prefix . ".pm";
123 43 100       866 if (-f $file) {
124 4         10 $add->($file);
125 4 50       13 last unless $args{all};
126             }
127             }
128 39 50       79 if ($args{find_pod}) {
129 0         0 my $file = $prefix . ".pod";
130 0 0       0 if (-f $file) {
131 0         0 $add->($file);
132 0 0       0 last unless $args{all};
133             }
134             }
135 39 100       89 if ($args{find_prefix}) {
136 8 100       156 if (-d $prefix) {
137 1         3 $add->($prefix);
138 1 50       9 last unless $args{all};
139             }
140             }
141             }
142              
143 6 50       14 if ($args{all}) {
144 0         0 return \@res;
145             } else {
146 6 100       62 return @res ? $res[0] : undef;
147             }
148             }
149              
150             gen_modified_sub(
151             output_name => 'pod_path',
152             base_name => 'module_path',
153             summary => 'Find path to Perl POD files',
154             description => <<'_',
155              
156             Shortcut for `module_path(..., find_pm=>0, find_pmc=>0, find_pod=>1,
157             find_prefix=>1, )`.
158              
159             _
160             remove_args => [qw/find_pm find_pmc find_pod find_prefix/],
161             output_code => sub {
162 0     0     my %args = @_;
163 0           module_path(
164             %args, find_pm=>0, find_pmc=>0, find_pod=>1, find_prefix=>0);
165             },
166             );
167              
168             1;
169             # ABSTRACT: Get path to locally installed Perl module
170              
171             __END__
172              
173             =pod
174              
175             =encoding UTF-8
176              
177             =head1 NAME
178              
179             SHARYANTO::Module::Path - Get path to locally installed Perl module
180              
181             =head1 VERSION
182              
183             This document describes version 0.20 of SHARYANTO::Module::Path (from Perl distribution SHARYANTO-Module-Path), released on 2014-08-26.
184              
185             =head1 SYNOPSIS
186              
187             use SHARYANTO::Module::Path 'module_path', 'pod_path';
188              
189             $path = module_path(module=>'Test::More');
190             if (defined($path)) {
191             print "Test::More found at $path\n";
192             } else {
193             print "Danger Will Robinson!\n";
194             }
195              
196             # find all found modules, as well as .pmc and .pod files
197             @path = module_path(module=>'Foo::Bar', all=>1, find_pmc=>1, find_pod=>1);
198              
199             # just a shortcut for module_path(module=>'Foo',
200             find_pm=>0, find_pmc=>0, find_pod=>1);
201             $path = pod_path(module=>'Foo');
202              
203             =head1 DESCRIPTION
204              
205             This module is a fork of L<Module::Path>. It contains features that are not (or
206             have not been accepted) in the original module, namely: finding all matches
207             instead of the first found match, and finding .pmc/.pod in addition to .pm
208             files. There is also a difference of behavior: no abs_path() or symlink
209             resolving is being done by default because I think that's the sensible default
210             (doing abs_path() or resolving symlinks will sometimes fail or expose filesystem
211             quirks that we might not want to deal with at all). However, an C<abs> bool
212             option is provided if a user wants to do that.
213              
214             This module has also diverged by introducing a different interface since v0.14.
215              
216             References:
217              
218             =over
219              
220             =item * L<https://github.com/neilbowers/Module-Path/issues/6>
221              
222             =item * L<https://github.com/neilbowers/Module-Path/issues/7>
223              
224             =item * L<https://github.com/neilbowers/Module-Path/issues/10>
225              
226             =back
227              
228             =head1 FUNCTIONS
229              
230              
231             =head2 module_path(%args) -> array|str
232              
233             Get path to locally installed Perl module.
234              
235             Search C<@INC> (reference entries are skipped) and return path(s) to Perl module
236             files with the requested name.
237              
238             This function is like the one from C<Module::Path>, except with a different
239             interface and more options (finding all matches instead of the first, the option
240             of not absolutizing paths, finding C<.pmc> & C<.pod> files, finding module
241             prefixes).
242              
243             Arguments ('*' denotes required arguments):
244              
245             =over 4
246              
247             =item * B<abs> => I<bool> (default: 0)
248              
249             Whether to return absolute paths.
250              
251             =item * B<all> => I<bool> (default: 0)
252              
253             Return all results instead of just the first.
254              
255             =item * B<find_pm> => I<bool> (default: 1)
256              
257             Whether to find .pm files.
258              
259             =item * B<find_pmc> => I<bool> (default: 1)
260              
261             Whether to find .pmc files.
262              
263             =item * B<find_pod> => I<bool> (default: 0)
264              
265             Whether to find .pod files.
266              
267             =item * B<find_prefix> => I<bool> (default: 1)
268              
269             Whether to find module prefixes.
270              
271             =item * B<module>* => I<str>
272              
273             Module name to search.
274              
275             =back
276              
277             Return value:
278              
279             (any)
280              
281              
282             =head2 pod_path(%args) -> array|str
283              
284             Shortcut for `module_path(..., find_pm=>0, find_pmc=>0, find_pod=>1, find_prefix=>1, )`.
285              
286             Search C<@INC> (reference entries are skipped) and return path(s) to Perl module
287             files with the requested name.
288              
289             This function is like the one from C<Module::Path>, except with a different
290             interface and more options (finding all matches instead of the first, the option
291             of not absolutizing paths, finding C<.pmc> & C<.pod> files, finding module
292             prefixes).
293              
294             Arguments ('*' denotes required arguments):
295              
296             =over 4
297              
298             =item * B<abs> => I<bool> (default: 0)
299              
300             Whether to return absolute paths.
301              
302             =item * B<all> => I<bool> (default: 0)
303              
304             Return all results instead of just the first.
305              
306             =item * B<module>* => I<str>
307              
308             Module name to search.
309              
310             =back
311              
312             Return value:
313              
314             (any)
315              
316             =head1 SEE ALSO
317              
318             L<SHARYANTO>
319              
320             L<Module::Path>
321              
322             =head1 HOMEPAGE
323              
324             Please visit the project's homepage at L<https://metacpan.org/release/SHARYANTO-Module-Path>.
325              
326             =head1 SOURCE
327              
328             Source repository is at L<https://github.com/sharyanto/perl-Alt-Module-Path-SHARYANTO>.
329              
330             =head1 BUGS
331              
332             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=SHARYANTO-Module-Path>
333              
334             When submitting a bug or request, please include a test-file or a
335             patch to an existing test-file that illustrates the bug or desired
336             feature.
337              
338             =head1 AUTHOR
339              
340             Steven Haryanto <stevenharyanto@gmail.com>
341              
342             =head1 COPYRIGHT AND LICENSE
343              
344             This software is copyright (c) 2014 by Steven Haryanto.
345              
346             This is free software; you can redistribute it and/or modify it under
347             the same terms as the Perl 5 programming language system itself.
348              
349             =cut