App-chot

 view release on metacpan or  search on metacpan

lib/App/chot.pm  view on Meta::CPAN

package App::chot;

our $VERSION = "1.04";

use v5.14;
use warnings;

use utf8;
use Encode;
use open IO => 'utf8', ':std';
use Pod::Usage;
use List::Util qw(any first);
use App::chot::Util;
use App::chot::Optex qw(detect_optex);
use App::chot::Found;
use Text::ParseWords qw(shellwords);

use Getopt::EX::Hashed; {
    Getopt::EX::Hashed->configure(DEFAULT => [ is => 'rw' ]);
    has one     => ' 1     ' ;
    has debug   => ' d +   ' ;
    has dryrun  => ' n     ' ;
    has info    => ' i     ' ;
    has raw     => ' r     ' ;
    has help    => ' h     ' , action => sub {
	pod2usage(-verbose => 99, -sections => [qw(SYNOPSIS)])
    } ;
    has list    => ' l +   ' ;
    has deref   => ' L     ' ;
    has man     => ' m     ' ;
    has number  => ' N !   ' , default => 0 ;
    has version => ' v     ' , action => sub { say "Version: $VERSION"; exit } ;
    has pager   => ' p =s  ' ;
    has column  => ' C :i  ' ;
    has suffix  => '   =s  ' , default => [ qw( .pm ) ] ;
    has type    => ' t =s  ' , default => 'Command:Perl:Python:Ruby:Node' ;
    has py      => '       ' , action => sub { $_->type('Python') } ;
    has pl      => '       ' , action => sub { $_->type('Perl') } ;
    has rb      => '       ' , action => sub { $_->type('Ruby') } ;
    has nd      => '       ' , action => sub { $_->type('Node') } ;
    has bat_theme => '   %   ' ,
	default => { light => 'Coldark-Cold', dark => 'Coldark-Dark' } ;
    has skip    => '   =s@ ' ,
	default => [] ;
} no Getopt::EX::Hashed;

sub run {
    my $app = shift;
    @_ = map { utf8::is_utf8($_) ? $_ : decode('utf8', $_) } @_;
    local @ARGV = splice @_;

    use Getopt::EX::Long qw(GetOptions Configure ExConfigure);
    ExConfigure BASECLASS => [ __PACKAGE__, "Getopt::EX" ];
    Configure qw(bundling no_getopt_compat);
    $app->getopt || pod2usage();

    my $name = pop @ARGV;
    if (!defined $name) {
	if ($app->man) {
	    my $script = $ENV{CHOT_SCRIPT_PATH} // $0;
	    exec 'perldoc', $script;
	    die "perldoc: $!\n";
	}
	pod2usage();
    }
    my @option = splice @ARGV;
    my $pager = $app->pager || $ENV{'CHOT_PAGER'} || _default_pager($app);

    #
    # Load and instantiate all finder objects once.
    # Each finder gets the same $app, $name, and shared $found,
    # and is reused across -i, main, and -m dispatch below.
    #
    my $found = App::chot::Found->new;
    my @finders;  # [ [$type, $finder_obj], ... ]
    for my $type (split /:+/, $app->type) {
	$type = _normalize_type($type);
	my $class = __PACKAGE__ . '::' . $type;
	eval "require $class" or do { warn $@ if $app->debug; next };
	push @finders, [
	    $type,
	    $class->new(app => $app, name => $name, found => $found),
	];
    }

    # -i mode: print trace/resolution info and exit
    if ($app->info) {
	for my $pair (@finders) {
	    my($type, $h) = @$pair;
	    $h->get_info if $h->can('get_info');
	}
	return 0;
    }

    #
    # Main discovery loop: try each finder in order.
    # Results are accumulated in $found so that later finders
    # (e.g., Python) can use paths found by earlier ones (e.g., Command).
    #
    my @found;
    for my $pair (@finders) {
	my($type, $h) = @$pair;
	warn "Trying finder: $type\n" if $app->debug;
	my @paths = grep { defined } $h->get_path;
	if (@paths) {
	    warn "Found by $type: @paths\n" if $app->debug;
	    push @found, @paths;
	    $found->add($type, @paths);
	    last if $app->one;
	} else {



( run in 3.002 seconds using v1.01-cache-2.11-cpan-d7f47b0818f )