in reply to extracting subroutine names (together with their packages) via PPI
I found some time to play around for you. Here's a way that works. It works by collecting up all PPI statements within the file, iterating over them until it hits a package, saves that name, then adds to a hash all the subs within that package:
use warnings; use strict; use Data::Dumper; use PPI; my $file = 'file.pl'; my $PPI_doc = PPI::Document->new($file); my $PPI_statements = $PPI_doc->find('PPI::Statement'); my %layout; my $package; for my $statement (@$PPI_statements) { if (ref $statement eq 'PPI::Statement::Package') { $package = $statement->namespace; } if (ref $statement eq 'PPI::Statement::Sub') { push @{ $layout{$package} }, $statement->name; } } print Dumper \%layout;
Given your test script:
$VAR1 = { 'Foo' => [ 'three', 'four' ], 'Fee' => [ 'one' ], 'Fi' => [ 'two' ] };
That's literally very quick and dirty, but it does exactly what you want from what I can tell.
Update: If you want to keep order of the packages (the subs will automatically be ordered), just keep the package names in an array (or you can modify the hash to keep an order field and a subs field or some such):
my $doc = PPI::Document->new($file); my $stmts = $doc->find('PPI::Statement'); my %layout; my @order; my $package; for (@$stmts) { if (ref $_ eq 'PPI::Statement::Package') { $package = $_->namespace; push @order, $package; } if (ref $_ eq 'PPI::Statement::Sub') { push @{ $layout{$package} }, $_->name; } } for (@order) { print "$_:\n"; for (@{ $layout{$_} }) { print "\t$_\n"; } }
Output:
Fee: one Fi: two Foo: three four
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: extracting subroutine names (together with their packages) via PPI
by clueless newbie (Curate) on Jul 06, 2023 at 21:52 UTC | |
by stevieb (Canon) on Jul 06, 2023 at 23:47 UTC | |
by clueless newbie (Curate) on Jul 07, 2023 at 00:51 UTC | |
by clueless newbie (Curate) on Jul 08, 2023 at 01:20 UTC |