-#!perl
+
package Mouse;
use strict;
use warnings;
+use 5.006;
+use base 'Exporter';
-our $VERSION = '0.03';
+our $VERSION = '0.13';
use 5.006;
-use Sub::Exporter;
+BEGIN {
+ if ($ENV{MOUSE_DEBUG}) {
+ *DEBUG = sub (){ 1 };
+ } else {
+ *DEBUG = sub (){ 0 };
+ }
+}
+
use Carp 'confess';
use Scalar::Util 'blessed';
-use Class::Method::Modifiers ();
+use Mouse::Util;
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 {
- return sub {
- my $package = caller;
- my $names = shift;
- $names = [$names] if !ref($names);
-
- for my $name (@$names) {
- Mouse::Meta::Attribute->create($package, $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;
- },
- );
-
- 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);
+
+ 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, @_);
+ }
+ }
+}
+
+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 {
+ Mouse::Util::apply_all_roles((caller)[0], @_);
+}
+
+sub import {
+ my $class = shift;
+
+ strict->import;
+ warnings->import;
+
+ my $caller = caller;
- sub unimport {
- 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 };
+
+ if (@_) {
+ __PACKAGE__->export_to_level( 1, $class, @_);
+ } else {
+ # shortcut for the common case of no type character
no strict 'refs';
- for my $keyword (keys %exports) {
- next if $keyword eq 'meta'; # we don't delete this one
- delete ${ $caller . '::' }{$keyword};
+ for my $keyword (@EXPORT) {
+ *{ $caller . '::' . $keyword } = *{__PACKAGE__ . '::' . $keyword};
}
}
-};
+}
+
+sub unimport {
+ my $caller = caller;
+
+ no strict 'refs';
+ for my $keyword (@EXPORT) {
+ delete ${ $caller . '::' }{$keyword};
+ }
+}
sub load_class {
my $class = shift;
confess "Invalid class name ($display)";
}
+ return 1 if $class eq 'Mouse::Object';
return 1 if is_class_loaded($class);
(my $file = "$class.pm") =~ s{::}{/}g;
functionality, faster. In particular, L<Moose/has> is missing only a few
expert-level features.
+We're also going as light on dependencies as possible. Most functions we use
+from L<Scalar::Util> are copied into this dist. L<Scalar::Util> is required if
+you'd like weak references; there's simply no way to do it from pure Perl.
+L<Class::Method::Modifiers> is required if you want support for L</before>,
+L</after>, and L</around>.
+
=head2 MOOSE COMPAT
Compatibility with Moose has been the utmost concern. Fewer than 1% of the
tests fail when run against Moose instead of Mouse. Mouse code coverage is also
-over 99%. Even the error messages are taken from Moose. The Mouse code just
-runs the test suite 3x-4x faster.
+over 96%. Even the error messages are taken from Moose. The Mouse code just
+runs the test suite 4x faster.
The idea is that, if you need the extra power, you should be able to run
C<s/Mouse/Moose/g> on your codebase and have nothing break. To that end,
=head3 Roles
-Fixing this one slightly less soon. stevan has suggested an implementation
-strategy. Mouse currently mostly ignores methods.
+We're working on fixing this one! stevan has suggested an implementation
+strategy. Mouse currently ignores methods, so that needs to be fixed next.
+Roles that consist entirely of attributes may be usable in this very version.
=head3 Complex types
Installs a "before" method modifier. See L<Moose/before> or
L<Class::Method::Modifiers/before>.
+Use of this feature requires L<Class::Method::Modifiers>!
+
=head2 after (method|methods) => Code
Installs an "after" method modifier. See L<Moose/after> or
L<Class::Method::Modifiers/after>.
+Use of this feature requires L<Class::Method::Modifiers>!
+
=head2 around (method|methods) => Code
Installs an "around" method modifier. See L<Moose/around> or
L<Class::Method::Modifiers/around>.
+Use of this feature requires L<Class::Method::Modifiers>!
+
=head2 has (name|names) => parameters
Adds an attribute (or if passed an arrayref of names, multiple attributes) to
has a builder, then providing a value for the attribute in the constructor is
optional.
-=item init_arg => Str
+=item init_arg => Str | Undef
-Allows you to use a different key name in the constructor.
+Allows you to use a different key name in the constructor. If undef, the
+attribue can't be passed to the constructor.
=item default => Value | CodeRef
Lets you automatically weaken any reference stored in the attribute.
-=item trigger => Coderef
+Use of this feature requires L<Scalar::Util>!
+
+=item trigger => CodeRef
+
+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.
-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.
+Mouse 0.05 supported more complex triggers, but this behavior is now removed.
=item builder => Str
bucket status). You must specify an appropriate type constraint to use
auto_deref.
+=item lazy_build => 0|1
+
+Automatically define lazy => 1 as well as builder => "_build_$attr", clearer =>
+"clear_$attr', predicate => 'has_$attr' unless they are already defined.
+
=back
=head2 confess error -> BOOM
Shawn M Moore, C<< <sartak at gmail.com> >>
+Yuval Kogman, C<< <nothingmuch at woobling.org> >>
+
with plenty of code borrowed from L<Class::MOP> and L<Moose>
=head1 BUGS