File Coverage

blib/lib/App/Cmd/Command.pm
Criterion Covered Total %
statement 73 75 97.3
branch 14 24 58.3
condition 7 8 87.5
subroutine 20 20 100.0
pod 12 12 100.0
total 126 139 90.6


line stmt bran cond sub pod time code
1 16     16   5905 use strict;
  16         38  
  16         489  
2 16     16   82 use warnings;
  16         34  
  16         800  
3              
4             package App::Cmd::Command 0.335;
5              
6 16     16   1631 use App::Cmd::ArgProcessor;
  16         37  
  16         579  
7 16     16   620 BEGIN { our @ISA = 'App::Cmd::ArgProcessor' };
8              
9             # ABSTRACT: a base class for App::Cmd commands
10              
11 16     16   135 use Carp ();
  16         34  
  16         16480  
12              
13             #pod =method prepare
14             #pod
15             #pod my ($cmd, $opt, $args) = $class->prepare($app, @args);
16             #pod
17             #pod This method is the primary way in which App::Cmd::Command objects are built.
18             #pod Given the remaining command line arguments meant for the command, it returns
19             #pod the Command object, parsed options (as a hashref), and remaining arguments (as
20             #pod an arrayref).
21             #pod
22             #pod In the usage above, C<$app> is the App::Cmd object that is invoking the
23             #pod command.
24             #pod
25             #pod =cut
26              
27             sub prepare {
28 29     29 1 92 my ($class, $app, @args) = @_;
29              
30 29         180 my ($opt, $args, %fields)
31             = $class->_process_args(\@args, $class->_option_processing_params($app));
32              
33             return (
34 28         244 $class->new({ app => $app, %fields }),
35             $opt,
36             @$args,
37             );
38             }
39              
40             sub _option_processing_params {
41 29     29   79 my ($class, @args) = @_;
42              
43             return (
44 29         158 $class->usage_desc(@args),
45             $class->opt_spec(@args),
46             );
47             }
48              
49             #pod =method new
50             #pod
51             #pod This returns a new instance of the command plugin. Probably only C
52             #pod should use this.
53             #pod
54             #pod =cut
55              
56             sub new {
57 30     30 1 75 my ($class, $arg) = @_;
58 30         240 bless $arg => $class;
59             }
60              
61             #pod =method execute
62             #pod
63             #pod $command_plugin->execute(\%opt, \@args);
64             #pod
65             #pod This method does whatever it is the command should do! It is passed a hash
66             #pod reference of the parsed command-line options and an array reference of left
67             #pod over arguments.
68             #pod
69             #pod If no C method is defined, it will try to call C -- but it will
70             #pod warn about this behavior during testing, to remind you to fix the method name!
71             #pod
72             #pod =cut
73              
74             sub execute {
75 1     1 1 3 my $class = shift;
76              
77 1 50       9 if (my $run = $class->can('run')) {
78             warn "App::Cmd::Command subclasses should implement ->execute not ->run"
79 0 0       0 if $ENV{HARNESS_ACTIVE};
80              
81 0         0 return $class->$run(@_);
82             }
83              
84 1         227 Carp::croak ref($class) . " does not implement mandatory method 'execute'\n";
85             }
86              
87             #pod =method app
88             #pod
89             #pod This method returns the App::Cmd object into which this command is plugged.
90             #pod
91             #pod =cut
92              
93 52     52 1 269 sub app { $_[0]->{app}; }
94              
95             #pod =method usage
96             #pod
97             #pod This method returns the usage object for this command. (See
98             #pod L).
99             #pod
100             #pod =cut
101              
102 10     10 1 92 sub usage { $_[0]->{usage}; }
103              
104             #pod =method command_names
105             #pod
106             #pod This method returns a list of command names handled by this plugin. The
107             #pod first item returned is the 'canonical' name of the command.
108             #pod
109             #pod If this method is not overridden by an App::Cmd::Command subclass, it will
110             #pod return the last part of the plugin's package name, converted to lowercase.
111             #pod For example, YourApp::Cmd::Command::Init will, by default, handle the command
112             #pod "init".
113             #pod
114             #pod Subclasses should generally get the superclass value of C
115             #pod and then append aliases.
116             #pod
117             #pod =cut
118              
119             sub command_names {
120             # from UNIVERSAL::moniker
121 128   66 128 1 1036 (ref( $_[0] ) || $_[0]) =~ /([^:]+)$/;
122 128         520 return lc $1;
123             }
124              
125             #pod =method usage_desc
126             #pod
127             #pod This method should be overridden to provide a usage string. (This is the first
128             #pod argument passed to C from Getopt::Long::Descriptive.)
129             #pod
130             #pod If not overridden, it returns "%c COMMAND %o"; COMMAND is the first item in
131             #pod the result of the C method.
132             #pod
133             #pod =cut
134              
135             sub usage_desc {
136 22     22 1 58 my ($self) = @_;
137              
138 22         81 my ($command) = $self->command_names;
139 22         161 return "%c $command %o"
140             }
141              
142             #pod =method opt_spec
143             #pod
144             #pod This method should be overridden to provide option specifications. (This is
145             #pod list of arguments passed to C from Getopt::Long::Descriptive,
146             #pod after the first.)
147             #pod
148             #pod If not overridden, it returns an empty list.
149             #pod
150             #pod =cut
151              
152             sub opt_spec {
153 15     15 1 94 return;
154             }
155              
156             #pod =method validate_args
157             #pod
158             #pod $command_plugin->validate_args(\%opt, \@args);
159             #pod
160             #pod This method is passed a hashref of command line options (as processed by
161             #pod Getopt::Long::Descriptive) and an arrayref of leftover arguments. It may throw
162             #pod an exception (preferably by calling C, below) if they are invalid,
163             #pod or it may do nothing to allow processing to continue.
164             #pod
165             #pod =cut
166              
167       19 1   sub validate_args { }
168              
169             #pod =method usage_error
170             #pod
171             #pod $self->usage_error("This command must not be run by root!");
172             #pod
173             #pod This method should be called to die with human-friendly usage output, during
174             #pod C.
175             #pod
176             #pod =cut
177              
178             sub usage_error {
179 1     1 1 14 my ( $self, $error ) = @_;
180 1         7 die "Error: $error\nUsage: " . $self->_usage_text;
181             }
182              
183             sub _usage_text {
184 1     1   3 my ($self) = @_;
185 1         2 local $@;
186 1         3 join "\n", eval { $self->app->_usage_text }, eval { $self->usage->text };
  1         6  
  1         8  
187             }
188              
189             #pod =method abstract
190             #pod
191             #pod This method returns a short description of the command's purpose. If this
192             #pod method is not overridden, it will return the abstract from the module's Pod.
193             #pod If it can't find the abstract, it will look for a comment starting with
194             #pod "ABSTRACT:" like the ones used by L.
195             #pod
196             #pod =cut
197              
198             # stolen from ExtUtils::MakeMaker
199             sub abstract {
200 29     29 1 61 my ($class) = @_;
201 29 50       62 $class = ref $class if ref $class;
202              
203 29         41 my $result;
204             my $weaver_abstract;
205              
206             # classname to filename
207 29         141 (my $pm_file = $class) =~ s!::!/!g;
208 29         59 $pm_file .= '.pm';
209 29 50       82 $pm_file = $INC{$pm_file} or return "(unknown)";
210              
211             # if the pm file exists, open it and parse it
212 29 50       1212 open my $fh, "<", $pm_file or return "(unknown)";
213              
214 29         180 local $/ = "\n";
215 29         51 my $inpod;
216              
217 29         553 while (local $_ = <$fh>) {
218             # =cut toggles, it doesn't end :-/
219 1226 50 100     3390 $inpod = /^=cut/ ? !$inpod : $inpod || /^=(?!cut)/;
220              
221 1226 100       2146 if (/#+\s*ABSTRACT: (.*)/){
222             # takes ABSTRACT: ... if no POD defined yet
223 9         27 $weaver_abstract = $1;
224             }
225              
226 1226 100       3217 next unless $inpod;
227 99         142 chomp;
228              
229 99 100       722 next unless /^(?:$class\s-\s)(.*)/;
230              
231 21         56 $result = $1;
232 21         38 last;
233             }
234              
235 29   100     619 return $result || $weaver_abstract || "(unknown)";
236             }
237              
238             #pod =method description
239             #pod
240             #pod This method can be overridden to provide full option description. It
241             #pod is used by the built-in L command.
242             #pod
243             #pod If not overridden, it uses L to extract the description
244             #pod from the module's Pod DESCRIPTION section or the empty string.
245             #pod
246             #pod =cut
247              
248             sub description {
249 4     4 1 12 my ($class) = @_;
250 4 50       17 $class = ref $class if ref $class;
251              
252             # classname to filename
253 4         27 (my $pm_file = $class) =~ s!::!/!g;
254 4         12 $pm_file .= '.pm';
255 4 50       20 $pm_file = $INC{$pm_file} or return '';
256              
257 4 50       198 open my $input, "<", $pm_file or return '';
258              
259 4         18 my $descr = "";
260 4     2   140 open my $output, ">", \$descr;
  2         14  
  2         4  
  2         16  
261              
262 4         2588 require Pod::Usage;
263 4         102034 Pod::Usage::pod2usage( -input => $input,
264             -output => $output,
265             -exit => "NOEXIT",
266             -verbose => 99,
267             -sections => "DESCRIPTION",
268             indent => 0
269             );
270 4         31654 $descr =~ s/Description:\n//m;
271 4         14 chomp $descr;
272              
273 4         96 return $descr;
274             }
275              
276             1;
277              
278             __END__