#!perl

our $DATE = '2014-09-17'; # DATE
our $VERSION = '0.02'; # VERSION

use 5.010;
use strict;
use warnings;

use App::PMUtils;
use Perinci::CmdLine::Any -prefer_lite=>1;

our %SPEC;
$SPEC{plsub} = {
    v => 1.1,
    summary => 'List subroutines defined in a Perl script (or module)',
    description => <<'_',



_
    args => {
        module => {
            schema => 'str*',
            completion => $App::PMUtils::_complete_module,
            cmdline_aliases => {m=>{}},
        },
        file => {
            summary => 'Specify file instead of module',
            schema  => 'str*',
            pos     => 0,
        },
        detail => {
            schema => 'bool',
        },
    },
    result_naked=>1,
};
sub plsub {
    require Compiler::Lexer;
    require SHARYANTO::Module::Path;

    my %args = @_;
    my $path;
    if (defined $args{module}) {
        my $mod = $args{module};
        $mod =~ s/\.pm$//; $mod =~ s!/!::!g; # convenience
        $path = SHARYANTO::Module::Path::module_path(module=>$mod);
        die "Can't find module '$mod'" unless $path;
    } elsif (defined $args{file}) {
        $path = $args{file};
        (-f $path) or die "No such file '$path'\n";
    } else {
        die "Please specify file or module (-m)\n";
    }

    my $lexer = Compiler::Lexer->new($path);
    my $ct = do {
        undef $/;
        open my $fh, "<", $path or die "Can't open '$path': $!\n";
        <$fh>;
    };
    my $tokens = $lexer->tokenize($ct);
    my @res;
    for my $i (0..@$tokens-1) {
        my $t = $tokens->[$i];
        my $sub;
        if ($i < @$tokens-1 && $t->{name} eq 'FunctionDecl') {
            my $t2 = $tokens->[$i+1];
            if ($t2->{name} eq 'Function') {
                $sub = $t2->{data};
            }
        }
        if ($sub) {
            if ($args{detail}) {
                push @res, {
                    name => $sub,
                    line => $t->{line},
                };
            } else {
                push @res, $sub;
            }
        }
    }
    \@res;
}

Perinci::CmdLine::Any->new(
    url => '/main/plsub',
)->run;

# ABSTRACT: List subroutines defined in a Perl script (or module)
# PODNAME: plsub

__END__

=pod

=encoding UTF-8

=head1 NAME

plsub - List subroutines defined in a Perl script (or module)

=head1 VERSION

This document describes version 0.02 of plsub (from Perl distribution App-PlUtils), released on 2014-09-17.

=head1 SYNOPSIS

 % plsub Some/script.pl
 % plsub --module Some::Module

Sample output:

 % plsub --module Org::Element::Table
 +--------------+
 | BUILD        |
 | rows         |
 | row_count    |
 | column_count |
 | as_aoa       |
 +--------------+

 % plsub -m Org/Element/Table --detail
 +------+--------------+
 | line | name         |
 | 13   | BUILD        |
 | 55   | rows         |
 | 65   | row_count    |
 | 75   | column_count |
 | 96   | as_aoa       |
 +------+--------------+

To active bash completion:

 % complete -C plsub plsub; # can be put in bash startup file e.g. .bashrc
 % plsub -m MIME/<tab>
 % plsub -m "MIME::B<tab> ; # use quote (' or ") if you want to use :: as separator

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/App-PlUtils>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-App-PlUtils>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-PlUtils>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by perlancar@cpan.org.

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

=cut
