package Dist::Zilla::Plugin::Boilerplate;{ use Dist::Zilla 4 (); use Moose; use namespace::autoclean; use PPI; use Moose::Autobox 0.09; use Path::Class; #use This::Is::A::Test 'foo','bar'; #use This::Is::A::Test ('foo','bar'); #use This::Is::A::Test qw(foo bar); # ABSTRACT: foo with( 'Dist::Zilla::Role::FileMunger', 'Dist::Zilla::Role::FileFinderUser' => { default_finders => [ ':InstallModules', ':IncModules', ':ExecFiles', ':TestFiles', ], }, 'Dist::Zilla::Role::PPI', ); sub mvp_multivalue_args { 'code_line' }; has code_line => ( is => 'ro', isa => 'ArrayRef[Str]', required => 1, ); sub code { shift->code_line->join("\n") } has _parsed_code => ( is => 'ro', isa => 'PPI::Element', init_arg => undef, builder => '_build_parsed_code', ); sub _build_parsed_code { my ($self) = @_; my $code = $self->code; PPI::Document->new(\$code); } sub import { my ($class,@tags) = @_; my ($caller,$filename) = caller(); require Dist::Zilla::Dist::Builder; my $zilla = Dist::Zilla::Dist::Builder->from_config({ chrome => Dist::Zilla::Plugin::Boilerplate::Chrome->new(), dist_root => $class->_find_dzil_root($filename), }); my %tags;@tags{@tags}=(); my @useful = $zilla->plugins->grep( sub{ $_->isa($class) && exists $tags{$_->plugin_name} } )->flatten; for my $instance (@useful) { $instance->eval_in($caller); } 1; } sub _find_dzil_root { my ($self,$filename) = @_; my $d = file($filename)->parent; while ($d && ! glob($d->file('dist.*'))) { $d=$d->parent } return $d; } sub eval_in { my ($self,$package) = @_; my $code = $self->code;my $name = $self->plugin_name; my $str = "{package $package;$code;1}"; local $@; eval $str or $self->log_fatal("Couldn't eval code for boilerplate into $package: $@"); } sub munge_files { my ($self) = @_; $self->munge_file($_) for $self->found_files->flatten; } sub munge_file { my ($self, $file) = @_; my $doc = $self->ppi_document_for_file($file); my $my_uses = $doc->find( sub{ my $element = $_[1]; $element->isa('PPI::Statement::Include') && $element->type eq 'use' && $element->module eq __PACKAGE__ } ); return unless $my_uses; for my $use ($my_uses->flatten) { my $tags = $self->_find_tags_from_ppi($use->arguments); if ($tags->first(sub{$_ eq $self->plugin_name})) { for my $elem ($self->_parsed_code->children) { $use->insert_before($elem) or $self->log_fatal("Couldn't insert $elem before $use\n"); } $use->delete; } } $self->save_ppi_document_to_file($doc,$file); } sub _find_tags_from_ppi { my ($self,$node) = @_; if ($node->isa('PPI::Token::Quote')) { return [$node->string]; } elsif ($node->isa('PPI::Token::QuoteLike::Words')) { return [$node->literal]; } elsif ($node->isa('PPI::Token')) { return [ $node->content ]; # probably wrong } elsif ($node->can('find')) { return [ ($node->find('PPI::Token::Quote') || []) ->map(sub{$_->string})->flatten(), ($node->find('PPI::Token::QuoteLike::Words') || []) ->map(sub{$_->literal})->flatten, ]; } else { return [] } } } package Dist::Zilla::Plugin::Boilerplate::Chrome;{ use Moose; has logger => ( is => 'ro', default => sub { Log::Dispatchouli->new({ ident => 'Dist::Zilla::Plugin::Boilerplate', log_pid => 0, to_self => 0, to_stdout => 0, to_stderr => 1, to_file => 0, quiet_fatal => 'stderr', }); } ); with 'Dist::Zilla::Role::Chrome'; sub prompt_str { return '' } sub prompt_yn { return 'n' } sub prompt_any_key { return } } 1;