1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
# You may distribute under the terms of the GNU General Public License
#
# (C) Paul Evans, 2008-2014 -- leonerd@leonerd.org.uk
package Circle::Command;
use strict;
use warnings;
our $VERSION = '0.173320';
use Attribute::Storage qw( get_subattrs get_subattr find_subs_with_attr );
require mro;
sub _find_commands
{
my ( $obj, $cinv, $containedby ) = @_;
my @ret;
my %commands;
while( $obj ) {
my %subs = find_subs_with_attr( mro::get_linear_isa( ref $obj ), "Command_description",
matching => qr/^command_/,
);
foreach my $name ( keys %subs ) {
( my $commandname = $name ) =~ s/^command_//;
my $cv = $subs{$name};
next if $commands{$commandname};
my $subof = get_subattr( $cv, "Command_subof" );
next if $containedby and !$subof or
!$containedby and $subof or
$containedby and $subof and $containedby ne $subof;
my $attrs = get_subattrs( $cv );
$commands{$commandname} = 1;
push @ret, __PACKAGE__->new( %$attrs,
name => $commandname,
obj => $obj,
cv => $cv,
);
}
# Collect in parent too
$obj = $obj->can( "commandable_parent" ) && $obj->commandable_parent( $cinv );
}
return @ret;
}
sub root_commands
{
my $class = shift;
my ( $cinv ) = @_;
return map { $_->name => $_ } _find_commands( $cinv->invocant, $cinv, undef );
}
# Object stuff
sub new
{
my $class = shift;
my %attrs = @_;
$attrs{name} =~ s/_/ /g;
return bless \%attrs, $class;
}
sub sub_commands
{
my $self = shift;
my ( $cinv ) = @_;
return map { $_->shortname => $_ } _find_commands( $cinv->invocant, $cinv, $self->name );
}
sub name
{
my $self = shift; return $self->{name};
}
sub shortname
{
my $self = shift;
( split m/ /, $self->name )[-1];
}
sub is_default
{
my $self = shift; return $self->{Command_default};
}
sub desc
{
my $self = shift; return $self->{Command_description}[0] || "[no description]";
}
sub detail
{
my $self = shift; return $self->{Command_description}[1];
}
sub args
{
my $self = shift;
return unless $self->{Command_arg};
return @{ $self->{Command_arg} };
}
sub opts
{
my $self = shift;
return $self->{Command_opt};
}
sub default_sub
{
my $self = shift;
my ( $cinv ) = @_;
my %subs = $self->sub_commands( $cinv );
my @defaults = grep { $_->is_default } values %subs;
return $defaults[0] if @defaults == 1; # Only if it's unique
return;
}
sub invoke
{
my $self = shift; $self->{cv}->( $self->{obj}, @_ );
}
0x55AA;
|