Mouse::Util for pure-perl implementations of functions we depend on, in case the...
[gitmo/Mouse.git] / lib / Mouse.pm
index 92ee9af..52e83bc 100644 (file)
 package Mouse;
 use strict;
 use warnings;
+use base 'Exporter';
 
-our $VERSION = '0.06';
+our $VERSION = '0.07';
 use 5.006;
 
-use Sub::Exporter;
 use Carp 'confess';
 use Scalar::Util 'blessed';
-use Class::Method::Modifiers ();
 
 use Mouse::Meta::Attribute;
 use Mouse::Meta::Class;
 use Mouse::Object;
 use Mouse::TypeRegistry;
 
-do {
-    my $CALLER;
-
-    my %exports = (
-        meta => sub {
-            my $meta = Mouse::Meta::Class->initialize($CALLER);
-            return sub { $meta };
-        },
-
-        extends => sub {
-            my $caller = $CALLER;
-            return sub {
-                $caller->meta->superclasses(@_);
-            };
-        },
-
-        has => sub {
-            my $caller = $CALLER;
-
-            return sub {
-                my $meta = $caller->meta;
-
-                my $names = shift;
-                $names = [$names] if !ref($names);
-
-                for my $name (@$names) {
-                    if ($name =~ s/^\+//) {
-                        Mouse::Meta::Attribute->clone_parent($meta, $name, @_);
-                    }
-                    else {
-                        Mouse::Meta::Attribute->create($meta, $name, @_);
-                    }
-                }
-            };
-        },
-
-        confess => sub {
-            return \&confess;
-        },
-
-        blessed => sub {
-            return \&blessed;
-        },
-
-        before => sub {
-            return \&Class::Method::Modifiers::before;
-        },
-
-        after => sub {
-            return \&Class::Method::Modifiers::after;
-        },
-
-        around => sub {
-            return \&Class::Method::Modifiers::around;
-        },
-
-        with => sub {
-            my $caller = $CALLER;
-
-            return sub {
-                my $role  = shift;
-                my $class = $caller->meta;
-
-                confess "Mouse::Role only supports 'with' on individual roles at a time" if @_;
-
-                Mouse::load_class($role);
-                $role->meta->apply($class);
-            };
-        },
-    );
-
-    my $exporter = Sub::Exporter::build_exporter({
-        exports => \%exports,
-        groups  => { default => [':all'] },
-    });
-
-    sub import {
-        $CALLER = caller;
-
-        strict->import;
-        warnings->import;
-
-        my $meta = Mouse::Meta::Class->initialize($CALLER);
-        $meta->superclasses('Mouse::Object')
-            unless $meta->superclasses;
-
-        goto $exporter;
-    }
+our @EXPORT = qw(extends has before after around blessed confess with);
+
+sub extends { Mouse::Meta::Class->initialize(caller)->superclasses(@_) }
+
+sub has {
+    my $meta = Mouse::Meta::Class->initialize(caller);
 
-    sub unimport {
-        my $caller = caller;
+    my $names = shift;
+    $names = [$names] if !ref($names);
 
-        no strict 'refs';
-        for my $keyword (keys %exports) {
-            next if $keyword eq 'meta'; # we don't delete this one
-            delete ${ $caller . '::' }{$keyword};
+    for my $name (@$names) {
+        if ($name =~ s/^\+//) {
+            Mouse::Meta::Attribute->clone_parent($meta, $name, @_);
         }
+        else {
+            Mouse::Meta::Attribute->create($meta, $name, @_);
+        }
+    }
+}
+
+sub before {
+    my $meta = Mouse::Meta::Class->initialize(caller);
+
+    my $code = pop;
+
+    for (@_) {
+        $meta->add_before_method_modifier($_ => $code);
     }
-};
+}
+
+sub after {
+    my $meta = Mouse::Meta::Class->initialize(caller);
+
+    my $code = pop;
+
+    for (@_) {
+        $meta->add_after_method_modifier($_ => $code);
+    }
+}
+
+sub around {
+    my $meta = Mouse::Meta::Class->initialize(caller);
+
+    my $code = pop;
+
+    for (@_) {
+        $meta->add_around_method_modifier($_ => $code);
+    }
+}
+
+sub with {
+    my $meta = Mouse::Meta::Class->initialize(caller);
+
+    my $role  = shift;
+
+    confess "Mouse::Role only supports 'with' on individual roles at a time" if @_;
+
+    Mouse::load_class($role);
+    $role->meta->apply($meta);
+}
+
+sub import {
+    strict->import;
+    warnings->import;
+
+    my $caller = caller;
+
+    my $meta = Mouse::Meta::Class->initialize($caller);
+    $meta->superclasses('Mouse::Object')
+        unless $meta->superclasses;
+
+    no strict 'refs';
+    no warnings 'redefine';
+    *{$caller.'::meta'} = sub { $meta };
+
+    Mouse->export_to_level(1, @_);
+}
+
+sub unimport {
+    my $caller = caller;
+
+    no strict 'refs';
+    for my $keyword (@EXPORT) {
+        delete ${ $caller . '::' }{$keyword};
+    }
+}
 
 sub load_class {
     my $class = shift;
@@ -340,20 +326,11 @@ L</handles>, such as regular expression and coderef, are not yet supported.
 
 Lets you automatically weaken any reference stored in the attribute.
 
-=item trigger => CodeRef | HashRef
+=item trigger => CodeRef
 
-Historically, triggers have been like "after" method modifiers. They allowed
-you to run code after your attribute had been set. Passing a coderef to the
-C<trigger> option still works this way.
+Any time the attribute's value is set (either through the accessor or the constructor), the trigger is called on it. The trigger receives as arguments the instance, the new value, and the attribute instance.
 
-By passing a hashref to C<trigger>, you also get "before" and "around"
-triggers. The "before" and "after" triggers don't affect the act of setting
-the attribute value, and their return values are ignored. The "around" trigger
-can be used to change the value that is being set on the attribute, or prevent
-the attribute from being updated altogether. The "around" trigger's arguments
-are a code reference to set the attribute's value (this coderef expects the
-instance and the new value), the instance, the new value, and the attribute
-metaclass.
+Mouse 0.05 supported more complex triggers, but this behavior is now deprecated.
 
 =item builder => Str