Module-Util-1.09000755001750001750 012073556301 14112 5ustar00mattlawmattlaw000000000000Module-Util-1.09/Makefile.PL000444001750001750 50012073556301 16174 0ustar00mattlawmattlaw000000000000# Note: this file was auto-generated by Module::Build::Compat version 0.4003 require 5.005003; use Module::Build::Compat 0.02; use lib '_build/lib'; Module::Build::Compat->run_build_pl(args => \@ARGV); require MyModuleBuilder; Module::Build::Compat->write_makefile(build_class => 'MyModuleBuilder'); Module-Util-1.09/Changes000444001750001750 211212073556301 15536 0ustar00mattlawmattlaw000000000000Changes document for Module::Util 1.09 - Thu Jan 10 2013 - Added module_name_parts 1.08 - Mon May 28 2012 - Added an explicit =encoding directive to avoid pod errors 1.07 - Tue Apr 7 2009 - No changes since 1.06 1.06 - Mon Mar 16 2009 - Attempted to get tests working with perl 5.6 (RT 44173) - Suppressed warnings generated by File::Find (RT 40924) 1.05 - Fri Nov 7 2008 - Bugfix RT 40632 1.04 - Sat Jun 28 2008 - Removed dependency on File::Find::Rule 1.03 - Tue Oct 24 2006 - Added -V switch to pm_which, to display versions - Made find_in_namespace return unique module names 1.02 - Thu Oct 12 2006 - Fixed version numbers in this file. - Added a work around for a potential bug in find_in_namespace on windows when resolving paths against relative directories in the include path 1.01 - Wed Apr 28 2006 - Added --version switch to pm_which - Fixed a bug in pm_which's -I switch (extra paths were ignored) - Fixed a bug with pm_which's -p switch - Changed Module::Util's SYNOPSIS a little 1.00 - Thu Nov 10 2005 - Initial revision Module-Util-1.09/META.json000444001750001750 176312073556301 15677 0ustar00mattlawmattlaw000000000000{ "abstract" : "Module name tools and transformations", "author" : [ "Matt Lawrence Emattlaw@cpan.orgE" ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4003, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Module-Util", "prereqs" : { "build" : { "requires" : { "Test::More" : "0" } }, "configure" : { "requires" : { "Module::Build" : "0.40" } }, "runtime" : { "requires" : { "perl" : "v5.5.3" } } }, "provides" : { "Module::Util" : { "file" : "lib/Module/Util.pm", "version" : "1.09" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ] }, "version" : "1.09" } Module-Util-1.09/MANIFEST000444001750001750 32612073556301 15361 0ustar00mattlawmattlaw000000000000Build.PL Changes lib/Module/Util.pm Makefile.PL MANIFEST This list of files META.yml README scripts/pm_which t/01..module.t t/99..pod.t t/data/NS/One.pm t/data/NS2/One.pm t/more/01..validate_all_cpan.t META.json Module-Util-1.09/META.yml000444001750001750 107312073556301 15521 0ustar00mattlawmattlaw000000000000--- abstract: 'Module name tools and transformations' author: - 'Matt Lawrence Emattlaw@cpan.orgE' build_requires: Test::More: 0 configure_requires: Module::Build: 0.40 dynamic_config: 1 generated_by: 'Module::Build version 0.4003, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Module-Util provides: Module::Util: file: lib/Module/Util.pm version: 1.09 requires: perl: v5.5.3 resources: license: http://dev.perl.org/licenses/ version: 1.09 Module-Util-1.09/README000444001750001750 1214712073556301 15154 0ustar00mattlawmattlaw000000000000NAME Module::Util - Module name tools and transformations SYNOPSIS use Module::Util qw( :all ); $valid = is_valid_module_name $potential_module; $relative_path = module_path $module_name; $file_system_path = module_fs_path $module_name; # load module at runtime require module_path $module_name; # (see perldoc -f require for limitations of this approach.) DESCRIPTION This module provides a few useful functions for manipulating module names. Its main aim is to centralise some of the functions commonly used by modules that manipulate other modules in some way, like converting module names to relative paths. EXPORTS Nothing by default. Use the tag :all to import all functions. FUNCTIONS is_valid_module_name $bool = is_valid_module_name($module) Returns true if $module looks like a module name, false otherwise. module_is_loaded $abs_path_or_hook = module_is_loaded($module) Returns the %INC entry for the given module. This is usually the absolute path of the module, but sometimes it is the hook object that loaded it. See perldoc -f require Equivalent to: $INC{module_path($module)}; Except that invalid module names simply return false without generating warnings. find_installed $path = find_installed($module, [@inc]) Returns the first found installed location of the given module. This is always an absolute filesystem path, even if it is derived from a relative path in the include list. By default, @INC is searched, but this can be overridden by providing extra arguments. # look in @INC $path = find_installed("Module::Util") # look only in lib and blib/lib, not in @INC $path = find_installed("Module::Util", 'lib', 'blib/lib') Note that this will ignore any references in the search path, so it doesn't necessarily follow that the module cannot be successfully "require"d if this returns nothing. all_installed @paths = all_installed($module, [@inc]) Like find_installed, but will return multiple results if the module is installed in multiple locations. find_in_namespace @modules = find_in_namespace($namespace, [ @inc ]) Searches for modules under a given namespace in the search path (@INC by default). find_in_namespace("My::Namespace"); Returns unique installed module names under the namespace. Note that this does not include the passed-in name, even if it is the name of an installed module. Use of an empty string as the namespace returns all modules in @inc. module_path $path = module_path($module) Returns a relative path in the form used in %INC. Which I am led to believe is always a unix file path, regardless of the platform. If the argument is not a valid module name, nothing is returned. module_fs_path $path = module_fs_path($module) Like module_path, but returns the path in the native filesystem format. On unix systems, this should be identical to module_path. path_to_module $module = path_to_module($path) Transforms a relative unix file path into a module name. # Print loaded modules as module names instead of paths: print join("\n", map { path_to_module($_) } keys %INC Returns undef if the resulting module name is not valid. fs_path_to_module $module = fs_path_to_module($fs_path) Transforms relative filesystem paths into module names. # on windows: fs_path_to_module("Module\\Util.pm") # returns Module::Util Returns undef if the resulting module is not valid. module_path_parts @parts = module_path_parts($module_name) Returns the module name split into parts suitable for feeding to File::Spec->catfile. module_path_parts('Module::Util') # returns ('Module', 'Util.pm') If the module name is invalid, nothing is returned. canonical_module_name $module = canonical_module_name($module); Returns the canonical module name for the given module. This basically consists of eliminating any apostrophe symbols and replacing them with '::'. canonical_module_name("Acme::Don't"); # Acme::Don::t Returns undef if the name is not valid. module_name_parts @parts = module_name_parts($module); Returns a list of name parts for the given module. module_name_parts('Acme::Example); # ('Acme', 'Example') BUGS None known. Please report any found. SEE ALSO pm_which, a command-line utility for finding installed perl modules that is bundled with this module. Other, similar CPAN modules: Class::Inspector, Module::Info, Module::Require, UNIVERSAL::require, Module::Runtime perldoc -f require AUTHOR Matt Lawrence THANKS Alexander Kühne, Adrian Lai and Daniel Lukasiak for submitting patches. COPYRIGHT Copyright 2005 Matt Lawrence, All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Module-Util-1.09/Build.PL000444001750001750 252512073556301 15547 0ustar00mattlawmattlaw000000000000use strict; use warnings; =head1 NAME Build.PL - Build script generator for Module::Util =head1 SYNOPSIS perl Build.PL ./Build test ./Build install or perl Makefile.PL make test make install =head1 ADDITIONAL TESTS A very lengthy test script is provided in addition to the normal test suite. It checks the is_valid_module_name function against every module name in CPAN. It is not necessary for normal use of the module, but might come in handy for anyone who wants to make changes to the code and verify. To run this test, use: ./Build test_more or make test_more =cut use Module::Build; my $class = Module::Build->subclass( code => q( sub ACTION_test_more { my $self = shift; my %files = map { $_ => 1 } glob('t/more/*.t'); $self->{properties}{test_files} = \%files; return $self->ACTION_test(); } ), ); $class->new( module_name => 'Module::Util', requires => { perl => '5.5.3', }, build_requires => { 'Test::More' => 0, }, configure_requires => { 'Module::Build' => '0.40', }, script_files => [ glob("scripts/*") ], license => 'perl', create_makefile_pl => 'small', create_readme => 1, )->create_build_script; Module-Util-1.09/lib000755001750001750 012073556301 14660 5ustar00mattlawmattlaw000000000000Module-Util-1.09/lib/Module000755001750001750 012073556301 16105 5ustar00mattlawmattlaw000000000000Module-Util-1.09/lib/Module/Util.pm000444001750001750 2131312073556301 17535 0ustar00mattlawmattlaw000000000000package Module::Util; use strict; use warnings; our $VERSION = '1.09'; =encoding UTF-8 =head1 NAME Module::Util - Module name tools and transformations =head1 SYNOPSIS use Module::Util qw( :all ); $valid = is_valid_module_name $potential_module; $relative_path = module_path $module_name; $file_system_path = module_fs_path $module_name; # load module at runtime require module_path $module_name; # (see perldoc -f require for limitations of this approach.) =head1 DESCRIPTION This module provides a few useful functions for manipulating module names. Its main aim is to centralise some of the functions commonly used by modules that manipulate other modules in some way, like converting module names to relative paths. =cut use Exporter; use File::Spec::Functions qw( catfile rel2abs abs2rel splitpath splitdir ); use File::Find; =head1 EXPORTS Nothing by default. Use the tag :all to import all functions. =head1 FUNCTIONS =cut our @ISA = qw( Exporter ); our @EXPORT = (); our @EXPORT_OK = qw( is_valid_module_name module_is_loaded find_installed all_installed find_in_namespace module_path module_fs_path module_path_parts path_to_module fs_path_to_module canonical_module_name module_name_parts ); our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); my $SEPARATOR = qr/ :: | ' /x; # leading underscores are technically valid as module names # but no CPAN module has one. our $module_re = qr/[[:alpha:]_] \w* (?: $SEPARATOR \w+ )*/xo; =head2 is_valid_module_name $bool = is_valid_module_name($module) Returns true if $module looks like a module name, false otherwise. =cut sub is_valid_module_name ($) { my $module = shift; return $module =~ /\A $module_re \z/xo; } =head2 module_is_loaded $abs_path_or_hook = module_is_loaded($module) Returns the %INC entry for the given module. This is usually the absolute path of the module, but sometimes it is the hook object that loaded it. See perldoc -f require Equivalent to: $INC{module_path($module)}; Except that invalid module names simply return false without generating warnings. =cut sub module_is_loaded ($) { my $module = shift; my $path = module_path($module) or return; return $INC{$path}; } =head2 find_installed $path = find_installed($module, [@inc]) Returns the first found installed location of the given module. This is always an absolute filesystem path, even if it is derived from a relative path in the include list. By default, @INC is searched, but this can be overridden by providing extra arguments. # look in @INC $path = find_installed("Module::Util") # look only in lib and blib/lib, not in @INC $path = find_installed("Module::Util", 'lib', 'blib/lib') Note that this will ignore any references in the search path, so it doesn't necessarily follow that the module cannot be successfully Cd if this returns nothing. =cut sub find_installed ($;@) { my $module = shift; my @inc = @_ ? @_ : @INC; for my $path (_abs_paths($module, @inc)) { return $path if -e $path; } return; } =head2 all_installed @paths = all_installed($module, [@inc]) Like find_installed, but will return multiple results if the module is installed in multiple locations. =cut sub all_installed ($;@) { my $module = shift; my @inc = @_ ? @_ : @INC; return grep { -e } _abs_paths($module, @inc); } =head2 find_in_namespace @modules = find_in_namespace($namespace, [ @inc ]) Searches for modules under a given namespace in the search path (@INC by default). find_in_namespace("My::Namespace"); Returns unique installed module names under the namespace. Note that this does not include the passed-in name, even if it is the name of an installed module. Use of an empty string as the namespace returns all modules in @inc. =cut sub find_in_namespace ($;@) { my $ns = shift; my @inc = @_ ? @_ : @INC; my (@out, $ns_path); if ($ns ne '') { $ns_path = module_fs_path($ns) or return; $ns_path =~ s/\.pm\z//; } else { $ns_path = ''; } for my $root (@inc) { my $ns_root = rel2abs($ns_path, $root); for my $path (_find_modules($ns_root)) { my $rel_path = abs2rel($path, rel2abs($root)); push @out, fs_path_to_module($rel_path); } } my %seen; return grep { !$seen{$_}++ } @out; } sub _find_modules { my @roots = @_; # versions of File::Find from earlier perls don't have this feature BEGIN { unimport warnings qw( File::Find ) if $] >= 5.008 } my @out; File::Find::find({ no_chdir => 1, wanted => sub { push @out, $_ if -f $_ && /\.pm\z/ } }, @roots); return @out; } # munge a module name into multiple possible installed locations sub _abs_paths { my ($module, @inc) = @_; my $path = module_fs_path($module) or return; return map { rel2abs($path, $_) } grep { !ref } @inc; } =head2 module_path $path = module_path($module) Returns a relative path in the form used in %INC. Which I am led to believe is always a unix file path, regardless of the platform. If the argument is not a valid module name, nothing is returned. =cut sub module_path ($) { my $module = shift; my @parts = module_path_parts($module) or return; return join('/', @parts); } =head2 module_fs_path $path = module_fs_path($module) Like module_path, but returns the path in the native filesystem format. On unix systems, this should be identical to module_path. =cut sub module_fs_path ($) { my $module = shift; my @parts = module_path_parts($module) or return; return catfile(@parts); } =head2 path_to_module $module = path_to_module($path) Transforms a relative unix file path into a module name. # Print loaded modules as module names instead of paths: print join("\n", map { path_to_module($_) } keys %INC Returns undef if the resulting module name is not valid. =cut sub path_to_module { my $path = shift; return _join_parts(split('/', $path)); } =head2 fs_path_to_module $module = fs_path_to_module($fs_path) Transforms relative filesystem paths into module names. # on windows: fs_path_to_module("Module\\Util.pm") # returns Module::Util Returns undef if the resulting module is not valid. =cut sub fs_path_to_module { my $path = shift; my (undef, $dir, $file) = splitpath($path); my @dirs = grep { length } splitdir($dir); return _join_parts(@dirs, $file); } # opposite of module_path_parts, keep private sub _join_parts { my @parts = @_; $parts[-1] =~ s/\.pm\z// or return; my $module = join('::', @parts); return unless is_valid_module_name($module); return $module; } =head2 module_path_parts @parts = module_path_parts($module_name) Returns the module name split into parts suitable for feeding to File::Spec->catfile. module_path_parts('Module::Util') # returns ('Module', 'Util.pm') If the module name is invalid, nothing is returned. =cut sub module_path_parts ($) { my $module = shift; my @parts = module_name_parts($module) or return; $parts[-1] .= '.pm'; return @parts; } =head2 canonical_module_name $module = canonical_module_name($module); Returns the canonical module name for the given module. This basically consists of eliminating any apostrophe symbols and replacing them with '::'. canonical_module_name("Acme::Don't"); # Acme::Don::t Returns undef if the name is not valid. =cut sub canonical_module_name ($) { my $module = shift; return unless is_valid_module_name($module); # $module = _join_parts(module_path_parts($module)); $module =~ s/'/::/g; return $module; } =head2 module_name_parts @parts = module_name_parts($module); Returns a list of name parts for the given module. module_name_parts('Acme::Example); # ('Acme', 'Example') =cut sub module_name_parts ($) { my $module = shift; $module = canonical_module_name($module) or return; return split($SEPARATOR, $module); } 1; __END__ =head1 BUGS None known. Please report any found. =head1 SEE ALSO L, a command-line utility for finding installed perl modules that is bundled with this module. Other, similar CPAN modules: L, L, L, L, L perldoc -f require =head1 AUTHOR Matt Lawrence Emattlaw@cpan.orgE =head1 THANKS Alexander Kühne, Adrian Lai and Daniel Lukasiak for submitting patches. =head1 COPYRIGHT Copyright 2005 Matt Lawrence, All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut vim: ts=8 sts=4 sw=4 sr et Module-Util-1.09/t000755001750001750 012073556301 14355 5ustar00mattlawmattlaw000000000000Module-Util-1.09/t/99..pod.t000444001750001750 125512073556301 16002 0ustar00mattlawmattlaw000000000000use strict; use warnings; use File::Spec::Functions qw( catdir ); use Test::More tests => 3; BEGIN { use_ok('Module::Util', qw( find_installed module_fs_path )); } SKIP: { eval { require Test::Pod; import Test::Pod; }; skip "Test::Pod not installed", 1 if $@; my $file = find_installed('Module::Util', catdir 'lib'); pod_file_ok($file, "Module::Util pod ok"); } SKIP: { eval { require Test::Pod::Coverage; import Test::Pod::Coverage; }; skip "Test::Pod::Coverage not installed", 1 if $@; pod_coverage_ok( 'Module::Util', "Module::Util pod coverage ok" ); } __END__ vim: ft=perl Module-Util-1.09/t/01..module.t000444001750001750 576512073556301 16476 0ustar00mattlawmattlaw000000000000use strict; use warnings; use File::Spec::Functions qw( catfile catdir ); use Test::More tests => 44; our $module; BEGIN { $module = "Module::Util"; use_ok($module, qw( :all )); } ok(is_valid_module_name($module), 'is_valid_module_name'); ok(find_installed($module), "find_installed"); my @expected_parts = qw( Module Util.pm ); my $path = module_path($module); ok(exists($INC{$path}), 'module_path agress with %INC'); is_deeply([module_path_parts($module)], \@expected_parts, 'module_path_parts()'); is(module_path($path), undef, 'module_path($path) is undef'); ok(!is_valid_module_name($path), 'a path is not a valid module name'); ok(!find_installed($path), 'a path is not a valid module'); is(path_to_module($path), $module, "path_to_module($path) == $module"); $path = module_fs_path($module); ok($path, "module_fs_path($module)"); is(fs_path_to_module($path), $module, "fs_path_to_module($path) == $module"); is(canonical_module_name("Acme::Don't"), 'Acme::Don::t', "Acme::Don't"); # Module names mustn't have leading or trailing '::' or leading numbers my @invalid = qw( :: ::My::Module My::Module:: 3l337::M0d3wl ); for my $invalid (@invalid) { ok(!is_valid_module_name($invalid), "'$invalid' is not valid"); ok(!find_installed($invalid), "'$invalid' is not a module"); ok(!module_path($invalid), "'$invalid' has no path"); ok(!module_fs_path($invalid), "'$invalid' has no fs path"); } ok(module_is_loaded($module), "Module::Util is loaded"); ok(!module_is_loaded("::Invalid"), "::Invalid is not loaded"); ok(!find_installed($module, 't/lib'), "Module::Util not found in t/lib"); is(all_installed($module, 'lib'), 1, "Module::Util only found once in lib"); is(all_installed("::Invalid"), 0, "::Invalid is not installed at all"); { my @in_ns; my $dir = catdir(qw( t data )); @in_ns = find_in_namespace('NS', $dir); is_deeply(\@in_ns, ['NS::One'], 'find_in_namespace'); @in_ns = find_in_namespace('', $dir); is_deeply([ sort @in_ns ], ['NS2::One', 'NS::One'], 'find_in_namespace'); for my $invalid (@invalid) { ok(!find_in_namespace($invalid), "'$invalid' is not a valid namespace"); } } $path = catfile('lib', module_fs_path($module)) || ''; ok(-f $path, "'$path' exists"); # path_to_module should fail when given a module name ok(!path_to_module($module), "path_to_module($module) fails"); # should fail on an absolute path too. $path = find_installed($module) || ''; ok(!path_to_module($path), "path_to_module($path) fails"); my @parts = module_name_parts( 'One::Two::Three' ); is_deeply( \@parts, [qw(One Two Three)] ); SKIP: { skip "No warnings suppression on perl < 5.8", 1 unless $] >= 5.008; my @warnings; local $SIG{__WARN__} = sub { push @warnings, @_ }; find_in_namespace('', catdir(qw( fake path ))); ok !@warnings, 'no warnings generated when searching in missing path' or diag join("\n", @warnings); } __END__ vim: ft=perl ts=8 sts=4 sw=4 sr et Module-Util-1.09/t/data000755001750001750 012073556301 15266 5ustar00mattlawmattlaw000000000000Module-Util-1.09/t/data/NS000755001750001750 012073556301 15606 5ustar00mattlawmattlaw000000000000Module-Util-1.09/t/data/NS/One.pm000444001750001750 11412073556301 16776 0ustar00mattlawmattlaw000000000000package NS::One; our $VERSION = 1; # Dummy Module for namespace test 1; Module-Util-1.09/t/data/NS2000755001750001750 012073556301 15670 5ustar00mattlawmattlaw000000000000Module-Util-1.09/t/data/NS2/One.pm000444001750001750 11512073556301 17061 0ustar00mattlawmattlaw000000000000package NS2::One; our $VERSION = 1; # Dummy Module for namespace test 1; Module-Util-1.09/t/more000755001750001750 012073556301 15317 5ustar00mattlawmattlaw000000000000Module-Util-1.09/t/more/01..validate_all_cpan.t000444001750001750 267412073556301 21571 0ustar00mattlawmattlaw000000000000use strict; use warnings; use IPC::Open3; use Test::More; # Make sure Module::Util::is_valid_module_name agrees with perl for every module # on CPAN my @modules; BEGIN { require CPAN; @modules = map { $_->id } CPAN::Shell->expand("Module", "/./"); plan tests => 1 + @modules; use_ok('Module::Util', qw( is_valid_module_name )); } # some pragmata that are valid but fail really_valid my @known_valid = qw( open if sort ); # build a regex to recognise the names above. my $known_valid = do { local $" = '|'; qr{^(?:@known_valid)$} }; # Check that the module name is really valid. # Not all modules reported by CPAN are! sub really_valid ($) { my $module = shift; return 1 if $module =~ $known_valid; # Check syntax using another perl interpreter. Very time consuming! my($in, $out, $err); my $pid = open3($in, $out, $err, $^X, '-c', '-e', "require $module") or die "Couldn't run $^X: $!"; close $in; close $err if defined $err; my $line = <$out>; close $out; waitpid($pid, 0); # if we see syntax OK, the module name must be valid! my $valid = $line =~ /syntax OK/; # diag "$line: $valid"; return $valid } for my $module (@modules) { my $valid = really_valid($module); my $ok = not (is_valid_module_name($module) xor $valid); ok($ok, "'$module' is ".($valid ? '' : 'not')." valid"); } __END__ vim: ft=perl ts=8 sts=4 sw=4 sr et Module-Util-1.09/scripts000755001750001750 012073556301 15601 5ustar00mattlawmattlaw000000000000Module-Util-1.09/scripts/pm_which000444001750001750 1523012073556301 17500 0ustar00mattlawmattlaw000000000000#!/usr/bin/perl use strict; use warnings; our $VERSION = '1.02'; # Removing this dependency # use Text::Trim qw( trim ); use List::Util qw( max ); use Module::Util qw( :all ); use Pod::Usage; use Getopt::Long qw( :config posix_default bundling ); =head1 NAME pm_which - find installed modules =head1 SYNOPSIS pm_which [ options ] module(s) Returns the path to the given module(s) =head2 OPTIONS -q, --quiet Just print paths -p, --paths Just convert the module name into a relative path -a, --all Print all paths, not just the first one found -n, --namespace Print all modules in the given namespace -m Only print module names, not paths -V Show module version -I libpath Add a path to search (like perl -I) -d, --dump Dump paths that would be searched (@INC by default) -h, --help Print this message -v, --version Print version information - Read modules from stdin, one per line =cut our($quiet, $all, $namespace, $name_only, $paths, $dump, $stdin, $version); our @search = @INC; GetOptions( 'q|quiet' => \$quiet, 'a|all' => \$all, 'p|paths' => \$paths, 'd|dump' => \$dump, 'n|namespace' => \$namespace, 'm' => \$name_only, 'V' => \$version, '' => \$stdin, 'h|help' => sub { pod2usage(-exitval => 0) }, 'I=s' => sub { unshift @search, $_[1] }, 'v|version' => \&version, ) or pod2usage( -exitval => 1 ); if ($dump) { print join("\n", @search), "\n"; exit 0; } require ExtUtils::MakeMaker if $version; our @modules = @ARGV; # Also read module names from STDIN if we have '-' switch # Removing Text::Trim dependency # push @modules, trim if $stdin; if ($stdin) { my @from_stdin = ; for (@from_stdin) { s/\A\s*//; s/\s*\z//; } push @modules, @from_stdin; } pod2usage( -exitval => 1, -message => 'No modules selected') unless @modules; if ($namespace) { my @found; for my $ns (@modules) { push @found, $ns if find_installed($ns, @search); push @found, find_in_namespace($ns, @search); } @modules = @found; } # We can just print and exit if we're just interested in module names. # However, if we also want versions, we have to get the path(s) anyway. if ($name_only and not $version) { print map { "$_\n" } @modules; exit 0; } # Find the maximum length of module names my $width = max map { length } @modules; my $exit = 0; MODULE: for my $module (@modules) { unless (is_valid_module_name($module)) { # Maybe the module is actually a path: my $new = path_to_module($module) || fs_path_to_module($module); if ($new) { $module = $new; } else { $exit = 2; warn "'$module' is not a valid module name\n"; next MODULE; } } if ($paths) { print module_path $module, "\n"; next MODULE; } my @paths = $all ? all_installed($module, @search) : find_installed($module, @search) ; my $prefix = ''; unless ($quiet or @modules == 1 or $name_only) { # print the module name as well as the path $prefix = sprintf("%-${width}s - ", $module); } if (@paths) { for my $path (@paths) { if ($version) { my $version = eval { MM->parse_version($path) }; if ($@) { warn "$0: Error finding version for '$module': $@\n"; $exit = 2; } # We might not want to display the path $path = $module if $name_only; $path .= defined $version ? " [ $version ]" : ''; } print $prefix, $path, "\n"; } } else { $exit = 2; print $prefix, "not found\n" unless $quiet; } } exit $exit; sub version { my $path = module_is_loaded('Module::Util'); print "pm_which $VERSION\n", "Using Module::Util $Module::Util::VERSION at $path\n"; exit 0; } __END__ =head1 DESCRIPTION This tool reports the locations of installed perl modules. By default it lists the location of each specified module that would be loaded by require. =head1 OPTION DETAILS =head2 quiet Under quiet mode, module names are suppressed and missing modules are not reported. Normal output: $ pm_which Module::One Module::Two Missing::Module Module::One - /path/to/Module/One.pm Module::Two - /path/to/Module/Two.pm Missing::Module - not found Under --quiet: $ pm_which -q Module::One Module::Two Missing::Module /path/to/Module/One.pm /path/to/Module/Two.pm =head2 paths In "paths" mode, each module is simply converted into a relative file path. This is possible even when the module is not installed. $ pm_which -p Missing::Module Missing/Module.pm =head2 all When the "all" switch is specified, all installed modules will be reported, not just the first one. This is useful for determining when there is a module installed in multiple locations. $ pm_which -a MyModule /path/to/MyModule.pm /home/me/perl/MyModule.pm =head2 namespace Arguments are taken as namespaces to search under. $ pm_which -n MyModule MyModule - /path/to/MyModule.pm MyModule::Foo - /path/to/MyModule/Foo.pm MyModule::Foo::Bar - /path/to/MyModule/Foo/Bar.pm =head2 -m Disables printing of module paths. This is only really useful in conjunction with --namespace. $ pm_which -nm MyModule MyModule MyModule::Foo MyModule::Foo::Bar =head2 -V Prints the version of each module, according to L. $ pm_which -V MyModule MyModule - /path/to/MyModule.pm [ 1.00 ] $ pm_which -Vnm MyModule MyModule [ 1.00 ] MyModule::Foo [ 0.01 ] MyModule::Foo::Bar [ undef ] =head2 dump Dumps the paths that would be searched and exits. This is @INC modified by any -I switches. $ pm_which --dump /usr/lib/perl5/site_perl/5.8.6 /usr/lib/perl5/vendor_perl/5.8.6 ... $ pm_which -I lib --dump -I blib/lib lib blib/lib /usr/lib/perl5/site_perl/5.8.6 ... =head2 version Prints the version number of the script, plus the version and path of Module::Util that was loaded. =head1 EXIT CODES =over =item * 0 - Everything was OK =item * 1 - Initialisation failed (bad switches?) =item * 2 - Some modules were not installed =back =head1 SEE ALSO This utility comes with L. =head1 AUTHOR Matt Lawrence Emattlaw@cpan.orgE =cut vim: ts=8 sts=4 sw=4 sr et