diff --git a/Makefile.PL b/Makefile.PL index 3056b28..6959d49 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -17,16 +17,18 @@ my %WriteMakefileArgs = ( "MIN_PERL_VERSION" => "5.006", "NAME" => "Dist::Zilla::Plugin::Beam::Connector", "PREREQ_PM" => { + "Beam::Wire" => 0, "Carp" => 0, "Dist::Zilla::Role::Plugin" => 0, "Moose" => 0, + "MooseX::LazyRequire" => 0, + "Path::Tiny" => 0, "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, - "Path::Tiny" => 0, "Test::DZil" => 0, "Test::More" => "0.89", "constant" => 0, @@ -40,11 +42,13 @@ my %WriteMakefileArgs = ( my %FallbackPrereqs = ( + "Beam::Wire" => 0, "Carp" => 0, "Dist::Zilla::Role::Plugin" => 0, "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "Moose" => 0, + "MooseX::LazyRequire" => 0, "Path::Tiny" => 0, "Test::DZil" => 0, "Test::More" => "0.89", diff --git a/README.mkdn b/README.mkdn index 9ece41c..dbec283 100644 --- a/README.mkdn +++ b/README.mkdn @@ -15,6 +15,12 @@ version 0.001000 ; PluginA emitting event 'foo' passes the event to PluginB on = plugin:PluginA#foo => plugin:PluginB#handle_foo on = plugin:PluginA#bar => plugin:PluginB#handle_bar + ; Load 'beam.yml' as a Beam::Wire container + container = beam.yml + ; Handle Dist::Zilla plugin events with arbitrary classes + ; loaded by Beam::Wire + on = plugin:PluginA#foo => container:servicename#handle_foo + on = plugin:PluginA#bar => container:otherservicename#handle_bar # DESCRIPTION diff --git a/examples/neo-makemaker/beam.yml b/examples/neo-makemaker/beam.yml new file mode 100644 index 0000000..d8cf3e7 --- /dev/null +++ b/examples/neo-makemaker/beam.yml @@ -0,0 +1,9 @@ +--- +dyninject_g: + class: inc::My::NeoDynDepsLite + args: + letter: G +dyninject_m: + $class: inc::My::NeoDynDepsLite + letter: M + diff --git a/examples/neo-makemaker/dist.ini b/examples/neo-makemaker/dist.ini index be9863f..ab8a82c 100644 --- a/examples/neo-makemaker/dist.ini +++ b/examples/neo-makemaker/dist.ini @@ -15,5 +15,8 @@ prune_directory = ^Example- [=inc::My::NeoDynDeps / NDD] [Beam::Connector] +container = beam.yml on = plugin:MM#generate_prelude => plugin:NDD#inject_prelude on = plugin:MM#generate_prelude => plugin:NDD#inject_prelude +on = plugin:MM#generate_prelude => container:dyninject_g#inject_prelude +on = plugin:MM#generate_prelude => container:dyninject_m#inject_prelude diff --git a/examples/neo-makemaker/inc/My/NeoDynDepsLite.pm b/examples/neo-makemaker/inc/My/NeoDynDepsLite.pm new file mode 100644 index 0000000..2517e9c --- /dev/null +++ b/examples/neo-makemaker/inc/My/NeoDynDepsLite.pm @@ -0,0 +1,28 @@ +use 5.006; +use strict; +use warnings; + +package inc::My::NeoDynDepsLite; + +# ABSTRACT: A Lightweight injector thingy + +# AUTHORITY + +# Look ma, no Dzil! no Moose! Nothing! + +sub new { return bless { ref $_[1] ? %{ $_[1] } : @_[ 1 .. $#_ ] }, $_[0] } + +# This is obviously a rediculously tiny and simple big of code +# in comparison with the normal shenanigans. +sub inject_prelude { + my ( $self, $event ) = @_; + my $text = $event->prelude; + my $letter = $self->{letter} || 'H'; + $text .= <<"EOF"; +print "This message brought to you by the letter $letter"; +EOF + $event->prelude($text); + return; +} + +1; diff --git a/lib/Dist/Zilla/Plugin/Beam/Connector.pm b/lib/Dist/Zilla/Plugin/Beam/Connector.pm index 7b9cd58..9cc417e 100644 --- a/lib/Dist/Zilla/Plugin/Beam/Connector.pm +++ b/lib/Dist/Zilla/Plugin/Beam/Connector.pm @@ -11,7 +11,9 @@ our $VERSION = '0.001000'; # AUTHORITY use Moose qw( has around with ); +use MooseX::LazyRequire; use Carp qw( croak ); +use Path::Tiny qw( path ); with 'Dist::Zilla::Role::Plugin'; has 'on' => ( @@ -20,6 +22,12 @@ has 'on' => ( default => sub { [] }, ); +has 'container' => ( + isa => 'Str', + is => 'ro', + lazy_required => 1, +); + has '_on_parsed' => ( isa => 'ArrayRef', is => 'ro', @@ -27,6 +35,13 @@ has '_on_parsed' => ( builder => '_build_on_parsed', ); +has '_container' => ( + isa => 'Ref', + is => 'ro', + lazy => 1, + builder => '_build_container', +); + around mvp_multivalue_args => sub { my ( $orig, $self, @args ) = @_; return ( qw( on ), $self->$orig(@args) ); @@ -49,8 +64,11 @@ sub _parse_connector { if ( $connector =~ /\Aplugin:(.+?)[#]([^#]+)\z/sx ) { return { type => 'plugin', name => "$1", connection => "$2", }; } + if ( $connector =~ /\Acontainer:(.+?)[#]([^#]+)\z/sx ) { + return { type => 'container', name => "$1", connection => "$2", }; + } croak "Invalid connector specification \"$connector\"\n" # - . q[Didn't match "plugin:#"]; + . q[Didn't match "(plugin|container):#"]; } sub _parse_on_directive { @@ -78,12 +96,16 @@ sub _find_connector { croak "Can't resolve plugin \"$spec->{name}\" to an instance.\n" # . q[Did the plugin exist? Is the connection *after* it?]; } + if ( 'container' eq $spec->{type} ) { + return $self->_container->get( $spec->{'name'} ); + } croak "Unknown connector type \"$spec->{type}\""; } # This is to avoid making the sub a closure that contains the emitter sub _make_connector { my ( $recipient, $method_name ) = @_; + # Maybe weak ref? IDK return sub { my ($event) = @_; @@ -96,8 +118,8 @@ sub _connect { my $emitter_object = $self->_find_connector($emitter); my $listener_object = $self->_find_connector($listener); - my $emit_name = $emitter->{name}; - my $listen_name = $listener->{name}; + my $emit_name = $emitter->{type} . $emitter->{name}; + my $listen_name = $listener->{type} . $listener->{name}; my $emit_on = $emitter->{connection}; my $listen_on = $listener->{connection}; @@ -109,7 +131,7 @@ sub _connect { croak qq[Listener Target "$listen_name" has no "$listen_on" method to recive events]; } - $self->log_debug(['Connecting %s#<%s> to %s#<%s>', $emit_name, $emit_on, $listen_name, $listen_on ]); + $self->log_debug( [ 'Connecting %s#<%s> to %s#<%s>', $emit_name, $emit_on, $listen_name, $listen_on ] ); $emitter_object->on( $emit_on, _make_connector( $listener_object, $listen_on ) ); return; @@ -120,6 +142,15 @@ sub _build_on_parsed { return [ map { _parse_on_directive($_) } @{ $self->on } ]; } +sub _build_container { + my ($self) = @_; + my $file = $self->container; + require Beam::Wire; + $self->log_debug( [ 'Loading Beam::Wire container from %s', $file ] ); + my $wire = Beam::Wire->new( file => path( $self->zilla->root, $file ) ); + return $wire; +} + 1; =head1 SYNOPSIS @@ -131,6 +162,12 @@ sub _build_on_parsed { ; PluginA emitting event 'foo' passes the event to PluginB on = plugin:PluginA#foo => plugin:PluginB#handle_foo on = plugin:PluginA#bar => plugin:PluginB#handle_bar + ; Load 'beam.yml' as a Beam::Wire container + container = beam.yml + ; Handle Dist::Zilla plugin events with arbitrary classes + ; loaded by Beam::Wire + on = plugin:PluginA#foo => container:servicename#handle_foo + on = plugin:PluginA#bar => container:otherservicename#handle_bar =head1 DESCRIPTION diff --git a/t/example/neomake.t b/t/example/neomake.t index 576fd8a..20c6aee 100644 --- a/t/example/neomake.t +++ b/t/example/neomake.t @@ -27,5 +27,11 @@ is( scalar @matches, 4, "4 lines added referencing Win32" ); is( scalar( grep /MSWin32/i, @matches ), 2, "2 lines added referencing MSWin32" ); is( scalar( grep /Unsupported/i, @matches ), 2, "2 lines added referencing Unsupported" ); +my (@messages) = grep /This message brought/i, split /\n/, $file_content; +note explain \@messages; +is( scalar @messages, 2, "2 messages added by non-dzil code!" ); +is( scalar( grep /letter G/i, @messages ), 1, "Letter G arrived" ); +is( scalar( grep /letter M/i, @messages ), 1, "Letter M arrived" ); + done_testing;