summaryrefslogtreecommitdiffstats
path: root/lib/IM/Engine/Plugin/Commands/OO.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IM/Engine/Plugin/Commands/OO.pm')
-rw-r--r--lib/IM/Engine/Plugin/Commands/OO.pm69
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/IM/Engine/Plugin/Commands/OO.pm b/lib/IM/Engine/Plugin/Commands/OO.pm
new file mode 100644
index 0000000..132d08a
--- /dev/null
+++ b/lib/IM/Engine/Plugin/Commands/OO.pm
@@ -0,0 +1,69 @@
+package IM::Engine::Plugin::Commands::OO;
+use Moose ();
+use Moose::Exporter;
+use Moose::Util::MetaRole;
+use Scalar::Util qw(blessed reftype);
+
+sub command {
+ my $caller = shift;
+ my $name = shift;
+ my $code;
+ $code = shift if reftype($_[0]) eq 'CODE';
+ my %args = @_;
+
+ my $method_meta = $caller->meta->get_method($name);
+ my $superclass = blessed($method_meta)
+ || $caller->meta->method_metaclass;
+ my @method_metaclass_roles = ('IM::Engine::Plugin::Commands::Trait::Method::Command');
+ push @method_metaclass_roles, 'IM::Engine::Plugin::Commands::Trait::Method::Formatted'
+ if $args{formatter};
+ my $method_metaclass = Moose::Meta::Class->create_anon_class(
+ superclasses => [$superclass],
+ roles => \@method_metaclass_roles,
+ cache => 1,
+ );
+ if ($method_meta) {
+ $method_metaclass->rebless_instance($method_meta);
+ }
+ else {
+ $method_meta = $method_metaclass->name->wrap(
+ $code,
+ package_name => $caller,
+ name => $name,
+ );
+ $caller->meta->add_method($name, $method_meta);
+ }
+ for my $attr (map { $_->meta->get_attribute_list } @method_metaclass_roles) {
+ next unless exists $args{$attr};
+ my $value = $args{$attr};
+ # XXX: shouldn't this just be a coercion?
+ my $munge_method = "_munge_$attr";
+ $value = $method_meta->$munge_method($value)
+ if $method_meta->can($munge_method);
+ $method_meta->$attr($value);
+ }
+}
+
+Moose::Exporter->setup_import_methods(
+ with_caller => ['command'],
+ also => ['Moose'],
+);
+
+sub init_meta {
+ shift;
+ my %options = @_;
+ Moose->init_meta(%options);
+ Moose::Util::MetaRole::apply_metaclass_roles(
+ for_class =>
+ $options{for_class},
+ attribute_metaclass_roles =>
+ ['IM::Engine::Plugin::Commands::Trait::Attribute::Command',
+ 'IM::Engine::Plugin::Commands::Trait::Attribute::Formatted'],
+ metaclass_roles =>
+ ['IM::Engine::Plugin::Commands::Trait::Class::Command',
+ 'IM::Engine::Plugin::Commands::Trait::Class::Formatted'],
+ );
+ return $options{for_class}->meta;
+}
+
+1;