1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#!/usr/bin/perl use v5.20; use strict; use warnings; use PPI; use PPI::Dumper; use Mojo::File qw(path); die 'Need file' if !$ARGV[0]; my $code = path( $ARGV[0] )->slurp; my $doc = PPI::Document->new( \$code ); #PPI::Dumper->new( $doc )->print and exit; my $top_level_requires = $doc->find( sub { $_[1]->isa('PPI::Token::Word') and ( $_[1]->content eq 'requires' or $_[1]->content eq 'recommends' ) and $_[1]->parent->parent->isa('PPI::Document') } ); my $feature_requires; if ( $ARGV[1] ) { my $feature_block = $doc->find( sub { $_[1]->isa('PPI::Token::Word') and $_[1]->content eq 'feature' and do { my $sibling = $_[1]->snext_sibling; my $value = $sibling->can('string') ? $sibling->string : $sibling->content; $value eq $ARGV[1] } } ); if ( $feature_block ) { $feature_requires = $feature_block->[0]->parent->find( sub { $_[1]->isa('PPI::Token::Word') and ( $_[1]->content eq 'requires' or $_[1]->content eq 'recommends' ) } ); } } for my $required ( @{ $top_level_requires || [] }, @{ $feature_requires || [] } ) { say $required->parent->content; }
1
2
3
4
5
6
7
8
9
requires 'Mojolicious' => 8;
feature 'sqlite', 'SQLite support' => sub {
recommends 'DBD::SQLite';
};
feature 'mariadb', 'MariaDB support' => sub {
recommends 'DBD::mysql';
};
1
2
3
4
5
$ parse_cpanfile.pl cpanfile
requires 'Mojolicious' => 8;
$ parse_cpanfile.pl cpanfile mariadb
requires 'Mojolicious' => 8;
recommends 'DBD::mysql';