MooX-Async-Console

 view release on metacpan or  search on metacpan

lib/MooX/Async.pm  view on Meta::CPAN

package MooX::Async;

our $VERSION = '0.006';
$VERSION = eval $VERSION;

=head1 NAME

MooX::IOAsync - BovIinate Oout :of: ASsync

=head1 SYNOPSIS

    package Thing;
    use Moo;
    use MooX::Async;

    # Extend an IO::Async module with MooX::Async:
    extends MooXAsync('Notifier');

    # Define a lazy attribute which will hold a callback subref with
    # an (optional) default implementation.
    event on_foo => sub { say "foo" };

=head1 DESCRIPTION

Allows a L<Moo> class to extend a L<IO::Async::Notifier> subclass with
the L<MooX::Async> role and the magic necessary to make
L<IO::Async::Notifier> work as a L<Moo> object.

=head1 BUGS

Certainly.

=cut

use Modern::Perl '2017';
use strictures 2;
use Moo (); # For _install_tracked
use Moo::Role; # For me
use Module::Runtime qw(compose_module_name module_notional_filename);
use namespace::clean;

sub import {
  my $pkg = caller;
  my $has = $pkg->can('has') or return;
  Moo::_install_tracked $pkg, event => sub {
    my $event = shift;
    my $sub = @_ % 2 ? pop : sub { die "$event event unimplemented" };
    $has->($event, @_, is => lazy => builder => sub { $sub });
  };
  Moo::_install_tracked $pkg, MooXAsync => \&MooXAsync;
}

=head1 EXPORTS

L</MooXAsync> and L</event> are exported unconditionally.

=over

=item event($name, [@args], [$subref]) => void

Install a lazy attribute to handle the event C<$name>. This is basically just:

    has $event => (@args, builder => sub { $subref });

=item MooXAsync($notifier) => $async_moo_class

Creates and returns the name of a class which extends C<$notifier>,
which can be an object or the name of a class which subclasses
L<IO::Async::Notifier> with L<Moo> and L<MooX::Async>.

Prepends C<IO::Async::> to C<$notifier> if it doesn't contain
C<::>. If C<$notifier> begins with C<::> then it is removed.

If C<$notifier> is an object then it is re-blessed into the new
package.

=back

=cut

sub MooXAsync {
  my $notifier = shift;
  # Ensure DOES('IO::Async::Notifier') and DOESN'T MooX::Async
  my $class = ref $notifier || $notifier; # Those who bless into '0' deserve what they get
  my $parent = $class =~ /^IO::Async::/ ? $class : compose_module_name('IO::Async', $class);
  my $pkg = $parent . '::' . __PACKAGE__;
  no strict 'refs';
  # This is ugly but I'm lazy.
  if (not scalar keys %{"$pkg\::"}) {
    eval <<"TOP" . <<'BOTTOM' or die; # Keep interpolated part seperate
      package $pkg;
      use Moo;
      extends '$parent';
TOP
      sub configure_unknown {  }



( run in 0.829 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )