diff options
Diffstat (limited to 'lib/IM/Engine/Plugin/Commands/Trait/Attribute/Formatted.pm')
-rw-r--r-- | lib/IM/Engine/Plugin/Commands/Trait/Attribute/Formatted.pm | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/IM/Engine/Plugin/Commands/Trait/Attribute/Formatted.pm b/lib/IM/Engine/Plugin/Commands/Trait/Attribute/Formatted.pm new file mode 100644 index 0000000..e7a17e1 --- /dev/null +++ b/lib/IM/Engine/Plugin/Commands/Trait/Attribute/Formatted.pm @@ -0,0 +1,58 @@ +package IM::Engine::Plugin::Commands::Trait::Attribute::Formatted; +use Moose::Role; + +# when the attribute is being constructed, the accessor methods haven't been +# generated yet, so we need to store the formatter here, and then apply it +# after the accessor methods exist +has formatter => ( + is => 'rw', + isa => 'CodeRef', + predicate => 'has_formatter', +); + +before _process_options => sub { + my $self = shift; + my ($name, $options) = @_; + Carp::cluck("only commands will have a formatter applied") + if exists($options->{formatter}) && !$options->{command}; +}; + +after attach_to_class => sub { + my $self = shift; + my ($meta) = @_; + return if $self->has_formatter; + return unless $self->command; + return unless $self->has_type_constraint; + my $tc = $self->type_constraint; + for my $tc_name ($meta->formattable_tcs) { + if ($tc->is_a_type_of($tc_name)) { + $self->formatter($meta->formatter_for($tc_name)); + return; + } + } +}; + +around accessor_metaclass => sub { + my $orig = shift; + my $self = shift; + my $metaclass = $self->$orig(@_); + return $metaclass unless $self->has_formatter; + return Moose::Meta::Class->create_anon_class( + superclasses => [$metaclass], + roles => ['IM::Engine::Plugin::Commands::Trait::Method::Formatted'], + cache => 1, + )->name; +}; + +after install_accessors => sub { + my $self = shift; + if ($self->has_formatter) { + my $formatter = $self->formatter; + my $method_meta = $self->get_read_method_ref; + $method_meta->formatter($formatter); + } +}; + +no Moose::Role; + +1; |