Why not adopt me?
NAME
Path::ScanINC - Emulate Perls internal handling of @INC.
VERSION
version 0.002
SYNOPSIS
The Aim of this module is to fully implement everything Perl does with @INC
, to be feature compatible with it, including the behaviour with regard to sub refs
in @INC
.
use Path::ScanINC;
# Normal usage.
my $inc = Path::ScanINC->new( );
# In case you need something that isn't @INC
# but works like it
my $inc = Path::ScanINC->new( inc => \@INC );
# Freeze the value of @INC at the time of object instantiation
# with regard to behaviour so later changes to @INC have no effect
my $inc = Path::ScanINC->new( immutable => 1 );
# Return the first file in @INC that matches.
my $file = $inc->first_file('Path', 'ScanINC.pm' );
# Find all possible versions of modules in @INC
my ( @files ) = $inc->all_files('Path', 'ScanINC.pm');
# Try to discover a File::ShareDir 'module' root.
my $dir = $inc->first_dir('auto','share','module');
# Should return the same as File::ShareDir::module_dir('Path::ScanINC')
# ( assuming such a directory existed, which there is presently no plans of )
my $dir = $inc->first_dir('auto','share','module','Path-ScanINC');
# Find All File::ShareDir roots in @INC
my ( @dirs ) = $inc->all_dirs('auto', 'share');
REF SUPPORT IN @INC
This module has elemental support for discovery of results in @INC
using CODE
/ARRAY
/BLESSED
entries in @INC
. However, due to a limitation as to how perl itself implements this functionality, the best we can do at present is simply return what the above are expected to return. This means if you have any of the above ref-types in @INC
, and one of those returns a true value
, you'll get handed back an ARRAY
reference instead of the file you were expecting.
Fortunately, @INC
barely ever has refs in it. But in the event you need to work with refs in @INC
and you expect that those refs will return true
, you have to pick one of two options, either :
- a. Write your code to work with the
array-ref
returned by the respective reference on a match - b. Use the
all_
family of methods and try pretendeding that there are noarray-refs
in the list it returns.
Its possible in a future release we may have better choices how to handle this situation in future, but don't bet on it.
Given that the API as defined by Perl mandates code-ref
's return lists containing file-handles
or iterative code-ref
's , not actual files, the best I can forsee at this time we'd be able to do to make life easier for you is creating a fake library somewhere in a tempdir
and stuffing the result of the code-ref
's into files in that dir prior to returning a path to the generated file.
( And it also tells me that they have to be "Real" file handles, not tied or blessed ones, so being able to ask a filehandle what file it represents is equally slim.... if that is of course what you require )
For more details, see perldoc perlfunc
or perldoc -f require
.
METHODS
new
my $object = $class->new(
inc => [ 'x', 'y', 'z' , ],
immutable => 1 | undef
);
immutable
if( $inc->immutable ) {
print "We're working with a snapshotted version of @INC";
}
inc
for my $i ( $inc->inc ) {
say "Plain: $incer" if not ref $incer;
say "Callback: $incer" if ref $incer;
}
Returns a copy of the internal version of @INC
it will be using.
If the object is immutable
, then this method will continue to report the same value as c<@INC>, or will be updated every time the orignal array reference passed during construction gets updated:
my $ref = [];
my $a = Path::ScanINC->new( inc => $inc );
my $b = Path::ScanINC->new( inc => $inc, immutable => 1 );
push @{$ref} , 'a';
is( [ $a->inc ]->[0] , 'a' , "non-immutable references keep tracking their original" );
isnt( [ $a->inc ]->[0] , 'a' , "immutable references are shallow-copied at construction" );
Do note of course that is a SHALLOW copy, so if you have multiple @INC
copies sharing the same array
/bless
references, changes to those references will be shared amongst all @INC
's .
first_file
if( defined ( my $file = $inc->first_file('Moose.pm') ) {
print "Yep, Moose seems to be available in \@INC , its at $file, but its not loaded (yet)\n";
}
This proves to be a handy little gem that replaces the oft used
if( try { require Moose ; 1 } ){
Yadayadayada
}
And adds the benefit of not needing to actually source the file to see if it exists or not.
IMPORTANT: PORTABILITIY
For best system portability, where possible, its suggested you specify paths as arrays of strings, not slash-separatad strings.
$inc->first_file('MooseX' , 'Declare.pm') # Good
$inc->first_file('MooseX/Declare.pm') # Bad.
This is for several reasons, all of which can be summarised as "Windows".
%INC
keys all use Unix notation.@INC
callbacks expect Unix notataion.\
is a valid path part on Unix.On Win32, we have to use
\
Separation, not/
for resolving physical files.
The sum of these means if you do this:
$inc->first_file('MooseX/Declare.pm')
On win32, it might just end up doing:
C:\some\path\here/MooseX/Declare.pm
Which may or may not work.
And additionally, if the above module is loaded, it will be loaded as
"MooseX/Declare.pm"
in %INC
, not what you'd expect, MooseX\Declare.pm
all_files
Returns all matches in all @INC
paths.
my $inc = Path::ScanINC->new();
push @INC, 'lib';
my ( @files ) = $inc->all_files('Something','Im','Working','On.pm');
pp(\@files );
# [
# '/something/........./lib/Something/Im/Working/On.pm',
# '/something/....../share/per5/lib/site_perl/5.15.9/Something/Im/Working/On.pm',
# ]
Chances are if you understand how this can be useful, you'll do so immediately.
Useful for debugging what module is being loaded, and possibly introspecting information about multiple parallel installs of modules in %ENV
, such as frequently the case with 'dual-life' modules.
perl -MPath::ScanINC -E 'my $scanner = Path::ScanINC->new(); say for $scanner->all_files(qw( Scalar Util.pm ))'
/usr/lib64/perl5/vendor_perl/5.12.4/x86_64-linux/Scalar/Util.pm
/usr/lib64/perl5/5.12.4/x86_64-linux/Scalar/Util.pm
Sort-of like ye' olde' perldoc -l
, but more like man -a
I might even be tempted to make a sub-module to make one-liners easier like
perl -MPath::ScanINC::All=Scalar/Util.pm
REMINDER: If there are REFS
in @INC
that match, they'll return array-ref
's, not strings.
first_dir
Just like first_file
except for locating directories.
all_dirs
Just like all_dirs
except for locating directories.
AUTHOR
Kent Fredric <kentnl@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Kent Fredric <kentnl@cpan.org>.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.