Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

vmod

by mirod (Canon)
on Dec 02, 2000 at 22:23 UTC ( #44575=snippet: print w/replies, xml ) Need Help??
Description:

I like to read the code of modules I have installed, but, especially when I use CPAN I never quite know when they are (and I am lazy!).

So this tool gets a module name (or the end part of a module name) and looks for it within @INC. Once it's found it it pages it.

A few additional refinements, you can just list the files, choose between multiple results and run the pager in batch (I like textedit)

A nice improvement would be to get the DIRSEP character automagically...

#!/usr/perl -w
use strict;

use File::Find;      # to find the source
use Getopt::Long;    # to process options
use Pod::Usage;      # generate usage from pod


# you can change those if needed
my $pager= 'less';   
my $DIRSEP='/';

my $batch= '';       # will get & if batch mode required
my ( $list, $help);  # other options
my %found;           # valid module files (a hash so we get only one o
+f each)

GetOptions( "pager:s"        => \$pager,
            "batch"          => sub { $batch= '&' },
            "list"           => \$list,
            "help"           => \$help,
          ) or pod2usage(2);

pod2usage(1) if $help;

my $module= shift || pod2usage(2);                 # get the module na
+me
pod2usage(2) if( @ARGV);

$module .= '.pm' unless $module=~ /\.pm$/;         # add .pm if needed
$module=~ s{(::|-)}{$DIRSEP}g;                     # replace :: or - b
+y /

find( { wanted => \&wanted, no_chdir => 1}, @INC); # go get the file f
+rom @INC

my @found= keys %found;                            # get unique files

unless( @found)                                    # nothing found, ex
+it
  { print "no source found for $module\n"; }
elsif( @found == 1)                                # found one:
  { my $file= shift @found;
    if( $list)
      { print "$module in $file\n";        }       #     list files
    else                                           #   or
      { system" $pager $file $batch";      }       #     page file
  }
else
  { my $i;
    if( $list)
      { print "found several candidates: \n",
          map { "  [@{[++$i]}] $_\n"} @found;
      }
    else
      { unshift @found, "quit";
        print "found several candidates: \n",
              map { "  [@{[$i++]}] $_\n"} @found; 

        # use Term::ReadLine to get the exact module index
        require Term::ReadLine; 
        import  Term::ReadLine;

        # get user input
        my $term = Term::ReadLine->new('vmod');
        my $prompt= '> ';
        my $index= $term->readline($prompt);

        exit unless( $index=~ /^\d+$/);        # make sure we have a n
+umber

        if( ($index > 0) && ($index<@found) )  # if it's a valid numbe
+r
          { my $file= $found[$index];          #   get the file
            system" $pager $file $batch";      #   page it
          }
      }
  }

exit;

# called for each file in the @INC forest
sub wanted
  { return unless(  m/$module$/i); 
    $found{$_}= 1;                            # store file name in %fo
+und
  }

__END__

=head1 NAME

vmod - a tool to display or page Perl modules
       if several modules are found then a choice is given

=head1 SYNOPSIS

viewmod [options] [file]

  file is the name of the module, with or without the .pm extension
       levels can be separated by '::', '/', '-' or the native directo
+ry
       separator

  Options:
    --help   -h     display this message
    --pager  -p     pager/editor to use (defaults to less)
    --batch  -b     run the pager in batch mode (with -p textedit for 
+example)
    --list   -l     only display the directory in which the source is




Replies are listed 'Best First'.
Re: vmod
by chipmunk (Parson) on Dec 02, 2000 at 23:20 UTC
    To do the conversion from module name to file path in a platform independent way, I suggest the File::Spec module, which is part of the core distribution. This will create a path appropriate for whatever system the code happens to be running on:
    use File::Spec; my @module = split /::|-/, $module; $module = File::Spec->catfile(@module);
    (Note: much of the documentation for File::Spec is actually, and unfortunately, in the File::Spec::Unix module. I haven't found that documentation on this site, so you'll have to read it on your local system.)
Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://44575]
help
Chatterbox?
[haukex]: Yes sorry I don't run them all the time, my POD tests are only run as author tests (and are excluded when I'm using Devel::Cover)
[Corion]: choroba: Hmm - no, I keep the snippets inline, but as my framework also has support for capturing output etc., maybe I should do the same...
[Corion]: haukex: Yes, that approach is sane, and it heals the fragility of Pod parsers in a nice way while still syntax-checking stuff
[choroba]: Unfortunately, none of it is online
[haukex]: I figured that POD tests make sense, but only as author tests
[choroba]: I mean, the slides are, but not the makefile with scripts to create them
[Corion]: haukex: I've only now arrived at that revelation ;)
[Corion]: choroba: I use spod5, which also has that support, and also implements its own kinda-make stuff
[haukex]: But that module I just linked to assumes that most verbatim blocks are runnable code, I have other modules where that's not the case, so there I just copy-and-paste the synopsis into the author tests...
[haukex]: not the most efficient, but then again, I don't have that many modules on CPAN :-)

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (10)
As of 2017-02-27 12:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?






    Results (385 votes). Check out past polls.