#!/usr/bin/perl
# $File: //depot/dist/bin/cpanp $
# $Revision: #3 $ $Change: 59 $ $DateTime: 2002/06/06 05:24:49 $

use strict;
use vars '$VERSION';

use CPANPLUS;
use Term::ReadLine;

$VERSION = CPANPLUS->VERSION;

=head1 NAME

cpanp - The CPANPLUS launcher

=head1 SYNOPSIS

B<cpanp>

B<cpanp> S<[ --[B<no>]I<option>... ]> S<[-]B<a>> S<[ I<author>... ]>

B<cpanp> S<[ --[B<no>]I<option>... ]> S<[-]B<dhilmp>> S<[ I<module>... ]>

=head1 DESCRIPTION

This script launches the B<CPANPLUS> utility to perform various operations
from the command line. If it's invoked without arguments, an interactive
shell is executed by default.

Optionally, it can take a single-letter switch and one or more argument,
to perform the associated action on each arguments. The commands are:

    a AUTHOR...     # search by author(s)
    m MODULE...     # search by module(s)
    f AUTHOR...     # list all distributions by an author(s)
    o [ MODULE... ] # list installed module(s) that aren't up to date
    i MODULE...     # install module(s)
    t MODULE...     # test module(s)
    u MODULE...     # uninstall module(s)
    d MODULE...     # download module(s) into current directory
    l MODULE...     # display detailed information about module(s)
    r MODULE...     # display README files of module(s)
    c MODULE...     # check for module report(s) from cpan-testers

Each command may be prefixed with one or more I<options>.  If preceded by
C<no>, the corresponding option will be set to C<0>, otherwise it's set to
C<1>. The valid options includes C<cpantest>, C<debug>, C<flush>, C<force>,
C<prereqs>, C<storable>, C<verbose> and C<md5>; please consult
C<CPANPLUS::Configure> for an explanation to their meanings.

=cut

my $opt;

my @bool = qw(cpantest debug flush force storable verbose md5 prereqs);

my $cmd = {
    a => "search",
    m => "search",
    f => "distributions",
    o => "uptodate",
    i => "install",
    t => "install",
    u => "uninstall",
    d => "fetch",
    l => "details",
    r => "readme",
    c => "reports",
};

my @cmd_stack;

while ($opt = shift(@ARGV)) {
    push @cmd_stack, "s $2 ".($1 ? 0 : 1) and next
        if ($opt =~ /^--(no)?(\w+)$/);

    $opt =~ s/^-//; $opt = lc(substr($opt, 0, 1));
    last;
};

push @cmd_stack, map { "$opt $_" } @ARGV if ($opt and exists $cmd->{$opt});

# special case: 'o' may take zero arguments.
@cmd_stack = $opt if !@cmd_stack and $opt eq 'o';

if (@cmd_stack) {
    # initializes configure setup if we've not been through it yet
    no strict 'refs';

    my $TR = ($^O eq 'MSWin32') ? 'Term::ReadLine::Stub'
                                : $Term::ReadLine::ISA[0];
                                
    # remember the old coderefs in case of a setoption-only invocation
    my $newref  = *{"$TR\::new"}{CODE};
    my $histref = *{"$TR\::addhistory"}{CODE};

    # save the original constructor arguments in the Faked arrayref
    *{"$TR\::new"} = sub {
        # shell only
        goto &{$newref} unless caller(0)->isa('CPANPLUS::Shell')
                            or caller(0) =~ /^CPANPLUS::Shell::/;

        return bless([@_], 'CPANPLUS::_Faked');
    };

    *{'CPANPLUS::_Faked::addhistory'} = sub { };
    *{'CPANPLUS::_Faked::readline'}   = sub {
        unless ($opt or @cmd_stack) {
            # there's no immediate actions anyway, and we've run out of 's',
            # so we restore the handlers and regen a genuine object

            *{"$TR\::new"} = $newref;
            *{"$TR\::addhistory"} = $histref;

            # regen self, pass the args to the new object
            return ($_[0] = $newref->(@{$_[0]}))->readline(@_[1..$#_]);
        }

        return shift @cmd_stack;
    };

    *{'CPANPLUS::_Faked::ReadLine'} = sub { $TR };
}

shell();

1;

__END__

=head1 SEE ALSO

L<CPANPLUS>

=head1 AUTHORS

Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>

=head1 COPYRIGHT

Copyright 2001, 2002 by Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>.

This program is free software; you can redistribute it and/or 
modify it under the same terms as Perl itself.

See L<http://www.perl.com/perl/misc/Artistic.html>

=cut

# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:
