Momo

 view release on metacpan or  search on metacpan

lib/Momo.pm  view on Meta::CPAN

package Momo;

# ABSTRACT: a simple oop module inspired from Mojo::Base and Moo
use utf8;
use strict;
use warnings;
use Carp;
use Role::Tiny ();
use Scalar::Util qw(set_prototype);
use Class::Method::Modifiers;

our $VERSION = 1.2;

sub import {
    my $class = shift;

    {
        no strict 'refs';
        no warnings 'redefine';

        my $package = caller;
        push @{ $package . '::ISA' }, 'Momo';
        # install methodes into package,make the package get magic feature
        # install class method modifiers
        if( not defined &{ $package."::has" } ){
            *{ $package . '::has' } = sub { attr( $package, @_ ) };
        }
        if( not defined &{ $package."::extends" } ) {
            *{ $package . '::extends' } = sub {
            for (@_) {
                ( my $file = $_ ) =~ s!::|'!/!g;
                eval { require "$file.pm" };
                push @{ $package . '::ISA' }, $_;
            }
            };
        }
        if( not defined &{ $package."::with" } ){
        *{ $package . '::with' } = sub {
            Role::Tiny->apply_roles_to_package( $package, @_ );
        };
        }
        for my $method (qw(before after around)) {
            *{ $package . '::' . $method } = sub {
                Class::Method::Modifiers::install_modifier( $package, $method,
                    @_ );
            };
        }
        set_prototype \&{ $package . '::extends' }, '@';
        set_prototype \&{ $package . '::with' },    '@';
    }
    strict->import;
    warnings->import;
    utf8->import;
    Carp->import;
    if ( $] >= 5.010 ) {
        require 'feature.pm';
        feature->import( ':' . substr("$^V",1,4) );
    }

}

sub new {
    my $class = shift;
    bless @_ ? @_ > 1 ? {@_} : { %{ $_[0] } } : {}, ref $class || $class;
}

sub attr {
    my ( $class, $attrs, $default ) = @_;
    return unless ( $class = ref $class || $class ) && $attrs;

    Carp::croak 'Default has to be a code reference or constant value'
      if ref $default && ref $default ne 'CODE';

    # Compile attributes
    for my $attr ( @{ ref $attrs eq 'ARRAY' ? $attrs : [$attrs] } ) {
        Carp::croak qq{Attribute "$attr" invalid}
          unless $attr =~ /^[a-zA-Z_]\w*$/;

        my $code = "package $class;\nsub $attr {\n  if (\@_ == 1) {\n";
        unless ( defined $default ) { $code .= "    return \$_[0]{'$attr'};" }
        else {
            $code .= "    return \$_[0]{'$attr'} if exists \$_[0]{'$attr'};\n";
            $code .= "    return \$_[0]{'$attr'} = ";
            $code .=
              ref $default eq 'CODE' ? '$default->($_[0]);' : '$default;';
        }

        $code .= "\n  }\n  \$_[0]{'$attr'} = \$_[1];\n";
        $code .= "  \$_[0];\n}";

        no strict 'refs';
        warn "-- Attribute $attr in $class\n$code\n\n" if $ENV{MOMO_DEBUG};
        Carp::croak "Momo error: $@" unless eval "$code;1";
    }
}

sub tap {
    my ( $self, $cb ) = @_;
    $_->$cb for $self;
    return $self;
}

1;

=encoding utf8

=head1 NAME

Momo,a simple oop module inspired from Mojo::Base and Moo.

=head1 SYNOPSIS



( run in 3.252 seconds using v1.01-cache-2.11-cpan-0bb4e1dffa6 )