#!/usr/bin/perl

=head1 NAME

corelist - a commandline frontend to Module::CoreList

=head1 DESCRIPTION

See L<Module::CoreList> for one.

=head1 SYNOPSIS

    corelist -v [<PerlVersion>]
    corelist [-a] <ModuleName> | /<ModuleRegex>/ [<ModuleVersion>] ...
    corelist [-v <PerlVersion>] [ <ModuleName> | /<ModuleNameRegex>/ ] ...

=head1 OPTIONS

=over

=item -a modulename

    corelist -a utf8

    utf8  was first released with perl 5.006
      5.006      undef
      5.006001   undef
      5.006002   undef
      5.007003   1.00
      5.008      1.00
      5.008001   1.02
      5.008002   1.02
      5.008003   1.02
      5.008004   1.03
      5.008005   1.04
      5.008006   1.04
      5.008007   1.05
      5.008008   1.06
      5.009      1.02
      5.009001   1.02
      5.009002   1.04
      5.009003   1.06

=item -? or -help

help! help! help! to see more help, try --man.

=item -man

all of the help

=item -v

lists all of the perl release versions we got the CoreList for.

If you pass a version argument (value of C<$]>, like 5.00503),
you get a list of all the modules and their respective versions.

In module filtering context, it can be used as Perl version filter.

=back

=cut

use Module::CoreList;
use Getopt::Long;
use Pod::Usage;
use strict;
use warnings;
use version ();

my %Opts;

GetOptions(\%Opts, qw[ help|?! man! v|version:f a! ] );

pod2usage(1) if $Opts{help};
pod2usage(-verbose=>2) if $Opts{man};

if(exists $Opts{v} ){
    if( !$Opts{v} ) {
        print "\nModule::CoreList has info on the following perl versions:\n";
        print "$_\n" for sort keys %Module::CoreList::version;
        print "\n";
        exit 0;
    }

    $Opts{v} = numify_version( $Opts{v} );
    if( !exists $Module::CoreList::version{$Opts{v}} ) {
        print "\nModule::CoreList has no info on perl v$Opts{v}\n\n";
        exit 1;
    }

    if ( !@ARGV ) {
	print "\nThe following modules were in perl v$Opts{v} CORE\n";
	print "$_ ", $Module::CoreList::version{$Opts{v}}{$_} || " ","\n"
	for sort keys %{$Module::CoreList::version{$Opts{v}}};
	print "\n";
	exit 0;
    }
}

if ( !@ARGV ) {
    pod2usage(0);
}

while (@ARGV) {
	my ($mod, $ver);
	if ($ARGV[0] =~ /=/) {
	    ($mod, $ver) = split /=/, shift @ARGV;
	} else {
	    $mod = shift @ARGV;
	    $ver = (@ARGV && $ARGV[0] =~ /^\d/) ? shift @ARGV : "";
	}

	if ($mod !~ m|^/(.*)/([imosx]*)$|) { # not a regex
	    module_version($mod,$ver);
	} else {
	    my $re;
	    eval { $re = $2 ? qr/(?$2)($1)/ : qr/$1/; }; # trap exceptions while building regex
	    if ($@) {
		# regex errors are usually like 'Quantifier follow nothing in regex; marked by ...'
		# then we drop text after ';' to shorten message
		my $errmsg = $@ =~ /(.*);/ ? $1 : $@;
		warn "\n$mod  is a bad regex: $errmsg\n";
		next;
	    }
	    my @mod = Module::CoreList->find_modules($re);
	    if (@mod) {
		module_version($_, $ver) for @mod;
	    } else {
		$ver |= '';
		print "\n$mod $ver has no match in CORE (or so I think)\n";
	    }

	}
}

exit();

sub module_version {
    my($mod,$ver) = @_;

    if ( $Opts{v} ) {
        return printf "  %-24s %-10s\n",
            $mod,
            $Module::CoreList::version{$Opts{v}}{$mod} || 'undef';
    }

    $ver = "" unless defined $ver;

    my $ret = Module::CoreList->first_release(@_);
    my $msg = "$mod $ver";

    if( defined $ret ) {
        $msg .= " was ";
        $msg .= "first " unless $ver;
        $msg .= "released with perl $ret"
    } else {
        $msg .= " was not in CORE (or so I think)";
    }

    print "\n",$msg,"\n";

    if(defined $ret and exists $Opts{a} and $Opts{a}){
        for my $v(
            sort keys %Module::CoreList::version ){

            printf "  %-10s %-10s\n",
                $v,
                $Module::CoreList::version{$v}{$mod}
                    || 'undef'
                    if exists $Module::CoreList::version{$v}{$mod};
        }
        print "\n";
    }
}

sub numify_version {
    my $ver = shift;
    if ( index( $ver, q{.}, index( $ver, q{.} ) ) >= 0 ) {
        $ver = version->new($ver)->numify;
    }
    return $ver;
}

=head1 EXAMPLES

    $ corelist File::Spec

    File::Spec  was first released with perl 5.005

    $ corelist File::Spec 0.83

    File::Spec 0.83 was released with perl 5.007003

    $ corelist File::Spec 0.89

    File::Spec 0.89 was not in CORE (or so I think)

    $ corelist File::Spec::Aliens

    File::Spec::Aliens  was not in CORE (or so I think)

    $ corelist /IPC::Open/

    IPC::Open2  was first released with perl 5

    IPC::Open3  was first released with perl 5

    $ corelist /MANIFEST/i

    ExtUtils::Manifest  was first released with perl 5.001

    $ corelist /Template/

    /Template/  has no match in CORE (or so I think)

    $ corelist -v 5.8.8 B

    B                        1.09_01

    $ corelist -v 5.8.8 /^B::/

    B::Asmdata               1.01
    B::Assembler             0.07
    B::Bblock                1.02_01
    B::Bytecode              1.01_01
    B::C                     1.04_01
    B::CC                    1.00_01
    B::Concise               0.66
    B::Debug                 1.02_01
    B::Deparse               0.71
    B::Disassembler          1.05
    B::Lint                  1.03
    B::O                     1.00
    B::Showlex               1.02
    B::Stackobj              1.00
    B::Stash                 1.00
    B::Terse                 1.03_01
    B::Xref                  1.01

=head1 COPYRIGHT

Copyright (c) 2002-2006 by D.H. aka PodMaster

Current maintainer : Rafael Garcia-Suarez E<lt>rgarciasuarez at gmail dot
comE<gt>

This program is distributed under the same terms as perl itself.
See http://perl.org/ or http://cpan.org/ for more info on that.

=cut
