File Coverage

blib/lib/Footprintless/App/ActionCommand.pm
Criterion Covered Total %
statement 41 66 62.1
branch 7 22 31.8
condition 0 6 0.0
subroutine 9 14 64.2
pod 5 5 100.0
total 62 113 54.8


line stmt bran cond sub pod time code
1 5     5   1911 use strict;
  5         9  
  5         121  
2 5     5   22 use warnings;
  5         7  
  5         370  
3              
4             package Footprintless::App::ActionCommand;
5             $Footprintless::App::ActionCommand::VERSION = '1.29';
6             # ABSTRACT: A base class for action commands
7             # PODNAME: Footprintless::App::ActionCommand
8              
9 5     5   27 use Carp;
  5         6  
  5         399  
10 5     5   27 use Footprintless::App -command;
  5         15  
  5         39  
11 5     5   3791 use Getopt::Long::Descriptive;
  5         48190  
  5         33  
12 5     5   1388 use Log::Any;
  5         9  
  5         33  
13              
14             my $logger = Log::Any->get_logger();
15              
16             sub _coord_desc {
17 0     0   0 return 'COORD';
18             }
19              
20             sub _default_action {
21 0     0   0 return;
22             }
23              
24             sub description {
25 0     0 1 0 my ($self) = @_;
26              
27 0 0 0     0 if ( $self->{action} && !$self->{is_default_action} ) {
28 0         0 return $self->{action}->description();
29             }
30             else {
31 0         0 require Footprintless::App::DocumentationUtil;
32 0         0 my $pod_description = Footprintless::App::DocumentationUtil::description($self);
33 0         0 my %actions = $self->_actions();
34              
35 0         0 my $default_action = $self->_default_action();
36 0 0       0 $default_action =
37             $default_action
38             ? "\n\nDefault action: $default_action"
39             : '';
40              
41             return
42 0         0 $pod_description
43             . "\nAvailable actions:\n\n"
44             . $self->_format_actions( $self->_actions() )
45             . $default_action;
46             }
47             }
48              
49             sub execute {
50 8     8 1 110 my ( $self, $opts, $args ) = @_;
51              
52 8         36 $self->{action}->execute( $self->{action_opts}, $self->{action_args} );
53             }
54              
55             sub _format_actions {
56 0     0   0 my ( $self, %actions ) = @_;
57              
58 0         0 my %abstracts = ();
59 0         0 my $max_length = 0;
60 0         0 foreach my $key ( keys(%actions) ) {
61 0         0 my $length = length($key);
62 0         0 $abstracts{$key} = Footprintless::App::DocumentationUtil::abstract( $actions{$key} );
63 0 0       0 $max_length = $length if ( $length > $max_length );
64             }
65              
66             return join( "\n",
67 0         0 map { sprintf( " %${max_length}s: %s", $_, $abstracts{$_} ); } sort keys(%actions) );
  0         0  
68             }
69              
70             sub prepare {
71 8     8 1 494 my ( $class, $app, @args ) = @_;
72              
73 8         38 my ( $opts, $remaining_args, %fields ) =
74             $class->_process_args( \@args, $class->usage_desc(), $class->opt_spec() );
75              
76 8         3028 my ( $coordinate, $action_name, @action_args ) = @$remaining_args;
77 8         23 $fields{coordinate} = $coordinate;
78              
79 8 50       23 if ($action_name) {
80 8         18 $fields{action_name} = $action_name;
81             }
82             else {
83 0         0 $fields{action_name} = $class->_default_action();
84 0         0 $fields{is_default_action} = 1;
85             }
86              
87 8 50       23 if ( $fields{action_name} ) {
88 8         31 my %actions = $class->_actions();
89 8         20 my $action = $actions{ $fields{action_name} };
90 8 50       24 if ($action) {
91 8         14 { eval "require $action" }; ## no critic
  8         558  
92 8         38 ( $fields{action}, $fields{action_opts}, $fields{action_args} ) =
93             $action->prepare( $app, $app->footprintless(), $coordinate, @action_args );
94             }
95             }
96              
97             return (
98 8         71 $class->new(
99             { app => $app,
100             %fields
101             }
102             ),
103             $opts,
104             $remaining_args
105             );
106             }
107              
108             sub usage {
109 0     0 1 0 my ($self) = @_;
110             return ( $self->{action} && !$self->{is_default_action} )
111             ? $self->{action}->usage()
112 0 0 0     0 : $self->{usage};
113             }
114              
115             sub validate_args {
116 8     8 1 191 my ( $self, $opts, $args ) = @_;
117              
118 8 50       35 $self->usage_error("coordinate required") unless ( $self->{coordinate} );
119 8 50       22 $self->usage_error("action required") unless ( $self->{action_name} );
120             $self->usage_error("invalid action [$self->{action_name}]")
121 8 50       35 unless ( $self->{action} );
122              
123 8         16 eval { $self->{action}->validate_args( $self->{action_opts}, $self->{action_args} ); };
  8         33  
124 8 50       34 if ($@) {
125 0           $self->usage_error($@);
126             }
127             }
128              
129             1;
130              
131             __END__