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
In reply to Re: extracting subroutine names (together with their packages) via PPI
by stevieb
in thread extracting subroutine names (together with their packages) via PPI
by clueless newbie
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |