File Coverage

blib/lib/App/Commando/Command.pm
Criterion Covered Total %
statement 104 121 85.9
branch 19 22 86.3
condition 10 22 45.4
subroutine 25 30 83.3
pod 0 18 0.0
total 158 213 74.1


line stmt bran cond sub pod time code
1             package App::Commando::Command;
2              
3 4     4   49898 use strict;
  4         12  
  4         152  
4 4     4   20 use warnings;
  4         7  
  4         96  
5              
6 4     4   22 use Carp;
  4         5  
  4         316  
7 4     4   2458 use Getopt::Long;
  4         35603  
  4         27  
8 4     4   2480 use Moo;
  4         49227  
  4         30  
9              
10 4     4   6843 use App::Commando::Logger;
  4         15  
  4         192  
11 4     4   2937 use App::Commando::Option;
  4         13  
  4         181  
12 4     4   2212 use App::Commando::Presenter;
  4         12  
  4         7451  
13              
14             has 'actions' => ( is => 'rw' );
15             has 'aliases' => ( is => 'ro' );
16             has 'commands' => ( is => 'rw' );
17             has 'description' => ( is => 'rw' );
18             has 'map' => ( is => 'ro' );
19             has 'name' => ( is => 'ro' );
20             has 'options' => ( is => 'rw' );
21             has 'parent' => ( is => 'rw' );
22              
23             sub BUILDARGS {
24 13     13 0 3657 my ($class, $name, $parent) = @_;
25              
26             return {
27 13         381 actions => [],
28             aliases => [],
29             commands => {},
30             map => {},
31             name => $name,
32             options => [],
33             parent => $parent,
34             };
35             }
36              
37             # Gets or sets the command version
38             sub version {
39 10     10 0 538 my ($self, $version) = @_;
40              
41 10 100       34 $self->{_version} = $version if defined $version;
42 10         57 return $self->{_version};
43             }
44              
45             sub syntax {
46 6     6 0 14 my ($self, $syntax) = @_;
47              
48 6 100       18 $self->{_syntax} = $syntax if defined $syntax;
49              
50 6         13 my @syntax_list = ();
51              
52 6 100       25 if ($self->parent) {
53 1         11 my $parent_syntax = $self->parent->syntax;
54 1         53 $parent_syntax =~ s/<[\w\s-]+>|\[[\w\s-]+\]//g;
55 1         5 $parent_syntax =~ s/^\s+|\s+$//g;
56 1         2 push @syntax_list, $parent_syntax;
57             }
58 6   66     48 push @syntax_list, ($self->{_syntax} || $self->name);
59              
60 6         31 return join ' ', @syntax_list;
61             }
62              
63             sub default_command {
64 3     3 0 633 my ($self, $command_name) = @_;
65              
66 3 100       8 if ($command_name) {
67 2 100       11 if (exists $self->commands->{$command_name}) {
68 1         8 return $self->{_default_command} = $self->commands->{$command_name};
69             }
70             else {
71 1         198 croak "$command_name couldn't be found in this command's list of " .
72             "commands.";
73             }
74             }
75             else {
76 1         4 return $self->{_default_command};
77             }
78             }
79              
80             sub option {
81 36     36 0 132 my ($self, $config_key, @info) = @_;
82              
83 36         699 my $option = App::Commando::Option->new($config_key, @info);
84 36         623 push @{$self->options}, $option;
  36         100  
85 36         121 $self->map->{$option} = $config_key;
86              
87 36         86 return $option;
88             }
89              
90             sub command {
91 0     0 0 0 my ($self, $command_name) = @_;
92              
93 0         0 my $cmd = App::Commando::Command->new($command_name, $self);
94 0         0 $self->commands->{$command_name} = $cmd;
95              
96 0         0 return $cmd;
97             }
98              
99             sub alias {
100 2     2 0 8 my ($self, $command_name) = @_;
101              
102 2         10 $self->logger->debug("adding alias to parent for self: $command_name");
103 2         4 push @{$self->aliases}, $command_name;
  2         14  
104 2 100       22 $self->parent->commands->{$command_name} = $self if defined $self->parent;
105             }
106              
107             sub action {
108 8     8 0 53 my ($self, $code) = @_;
109              
110 8         11 push @{$self->actions}, $code;
  8         26  
111             }
112              
113             sub logger {
114 11     11 0 18 my ($self) = @_;
115              
116 11 50       38 unless ($self->{_logger}) {
117 11         175 $self->{_logger} = App::Commando::Logger->new(*STDOUT);
118 11         124 $self->{_logger}->level('info');
119             $self->{_logger}->formatter(sub {
120 0     0   0 my ($level, $message) = @_;
121              
122 0         0 return $self->identity . ' | ' .
123             sprintf("%-7s", ucfirst lc $level) . ": $message\n";
124 11         75 });
125             }
126              
127 11         64 return $self->{_logger};
128             }
129              
130             sub go {
131 9     9 0 12 my ($self, $argv, $config) = @_;
132              
133 9 50 66     77 if (defined $argv->[0] && exists $self->commands->{$argv->[0]}) {
134 0         0 my $cmd = $self->commands->{$argv->[0]};
135 0         0 $self->logger->debug("Found subcommand " . $cmd->name);
136 0         0 shift @$argv;
137 0         0 $cmd->go($argv, $config);
138             }
139             else {
140 9         29 $self->logger->debug('No additional command found, time to exec');
141 9         30 $self->process_options($config);
142 9         1132 return $self;
143             }
144             }
145              
146             sub process_options {
147 9     9 0 17 my ($self, $config) = @_;
148              
149 9         15 my %options_spec = ();
150              
151 9         12 for my $option (@{$self->options}) {
  9         31  
152             $options_spec{$option->for_get_options} = sub {
153 6     6   1673 my ($name, $value) = @_;
154 6         33 $config->{$self->map->{$option}} = $value;
155 16         84 };
156             }
157              
158 9         40 %options_spec = $self->add_default_options(%options_spec);
159              
160 9         37 Getopt::Long::Configure('pass_through');
161 9         286 GetOptions(%options_spec);
162             }
163              
164             sub add_default_options {
165 9     9 0 22 my ($self, %options_spec) = @_;
166              
167 9         11 my $option;
168              
169 9         29 $option = $self->option('show_help', '-h', '--help', 'Show this message');
170             $options_spec{$option->for_get_options} = sub {
171 0     0   0 print $self->as_string . "\n";
172 0         0 exit(0);
173 9         46 };
174              
175 9         29 $option = $self->option('show_version', '-v', '--version',
176             'Print the name and version');
177             $options_spec{$option->for_get_options} = sub {
178 0   0 0   0 print(($self->name || '') . " " . ($self->version || '') . "\n");
      0        
179 0         0 exit(0);
180 9         53 };
181              
182 9         67 return %options_spec;
183             }
184              
185             sub execute {
186 8     8 0 15 my ($self, $argv, $config) = @_;
187              
188 8   50     18 $argv //= [];
189 8   50     14 $config //= {};
190              
191 8 50 33     8 if (!@{$self->actions} && defined $self->default_command) {
  8         33  
192 0         0 $self->default_command->execute;
193             }
194             else {
195 8         10 for my $action (@{$self->actions}) {
  8         16  
196 8         22 &$action($argv, $config);
197             }
198             }
199             }
200              
201             sub identity {
202 4     4 0 8 my ($self) = @_;
203              
204 4 100       11 return $self->full_name .
205             (defined $self->version ? ' ' . $self->version : '');
206             }
207              
208             sub full_name {
209 12     12 0 52 my ($self) = @_;
210              
211             return
212 12 100 66     103 ($self->parent && $self->parent->full_name ?
213             $self->parent->full_name . ' ' : '') .
214             $self->name;
215             }
216              
217             sub names_and_aliases {
218 4     4 0 8 my ($self) = @_;
219              
220 4         12 return join ', ', $self->name, @{$self->aliases};
  4         51  
221             }
222              
223             sub summarize {
224 3     3 0 7 my ($self) = @_;
225              
226 3   50     10 return sprintf " %-20s %s", $self->names_and_aliases,
227             ($self->description || '');
228             }
229              
230             sub as_string {
231 0     0 0   my ($self) = @_;
232              
233 0           return App::Commando::Presenter->new($self)->command_presentation;
234             }
235              
236             1;
237              
238             __END__