Mouse::Util for pure-perl implementations of functions we depend on, in case the...
[gitmo/Mouse.git] / lib / Mouse.pm
index 99fab48..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
 
-Triggers are like method modifiers for setting attribute values. You can have
-a "before" and an "after" trigger, each of which receive as arguments the instance, the new value, and the attribute metaclass. Historically, triggers have
-only been "after" modifiers, so if you use a coderef for the C<trigger> option,
-it will maintain that compatibility. Like method modifiers, you can't really
-affect the act of setting the attribute value, and the return values of the 
-modifiers are ignored.
+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.
 
-There's also an "around" trigger which you can use to change the value that
-is being set on the attribute, or even prevent the attribute from being
-updated. The around trigger receives as arguments a code reference to invoke
-to set the attribute's value (which expects as arguments 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