File Coverage

blib/lib/Games/Lacuna/Task/ActionProto.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Games::Lacuna::Task::ActionProto;
2              
3 1     1   1674 use 5.010;
  1         24  
  1         56  
4             our $VERSION = $Games::Lacuna::Task::VERSION;
5              
6 1     1   522 use Moose;
  0            
  0            
7             extends qw(Games::Lacuna::Task);
8              
9             use List::Util qw(max);
10             use Try::Tiny;
11             use Games::Lacuna::Task::Utils qw(name_to_class class_to_name);
12              
13             sub run {
14             my ($self) = @_;
15            
16             my $task_name = shift(@ARGV);
17             my $task_class = name_to_class($task_name);
18            
19             if (! defined $task_name) {
20             say "Missing command";
21             $self->global_usage();
22             } elsif ($task_name ~~ [qw(help ? --help -h -? --usage usage)]) {
23             $self->global_usage();
24             } elsif (! ($task_class ~~ [$self->all_actions()])) {
25             say "Unknown command '$task_name'";
26             $self->global_usage();
27             } else {
28             $ARGV[0] = '--help'
29             if defined $ARGV[0] && $ARGV[0] eq 'help';
30            
31             my ($ok,$error) = $self->load_action($task_class);
32            
33             if (! $ok) {
34             $self->log('error',$error);
35             } else {
36             my $configdir;
37             my $loglevel;
38             my $help;
39             my $debug;
40            
41             my $opt_parser = Getopt::Long::Parser->new( config => [ qw( no_auto_help pass_through ) ] );
42             $opt_parser->getoptions(
43             "configdir=s" => \$configdir,
44             "debug" => \$debug,
45             "loglevel=s" => \$loglevel,
46             "help|usage|?" => \$help,
47             );
48            
49             $self->loglevel($loglevel)
50             if $loglevel;
51            
52             $self->configdir($configdir)
53             if defined $configdir && $configdir ne '';
54            
55             $self->debug($debug)
56             if defined $debug;
57              
58             my $task_config = $self->client->task_config($task_name);
59            
60             if ($help) {
61             $self->task_usage($task_class);
62             } else {
63             eval {
64             my $pa = $task_class->process_argv($task_config);
65            
66             my $object = $task_class->new(
67             ARGV => $pa->argv_copy,
68             extra_argv => $pa->extra_argv,
69             #usage => $pa->usage,
70             %{ $task_config }, # explicit params to ->new
71             %{ $pa->cli_params }, # params from CLI
72             );
73            
74             $self->log('notice',("=" x ($Games::Lacuna::Task::Constants::SCREEN_WIDTH - 8)));
75             $self->log('notice',"Running task %s for empire %s",$task_name,$self->empire_name);
76             $object->execute;
77             $self->log('notice',("=" x ($Games::Lacuna::Task::Constants::SCREEN_WIDTH - 8)));
78             };
79             if (my $error = $@) {
80             $error =~ s/\n.+//s;
81             $self->log('error',$error);
82             $self->task_usage($task_class);
83             return;
84             }
85             }
86             }
87             }
88            
89             return;
90             }
91              
92              
93             sub _usage_attributes {
94             my ($self,$class) = @_;
95            
96             my @attributes;
97            
98             my $meta = $class->meta;
99             foreach my $attribute ($meta->get_all_attributes) {
100             next
101             if $attribute->does('NoGetopt');
102            
103             my @names;
104             if ($attribute->can('cmd_flag')) {
105             push(@names,$attribute->cmd_flag);
106             } else {
107             push(@names,$attribute->name);
108             }
109            
110             if ($attribute->can('cmd_aliases')
111             && $attribute->cmd_aliases) {
112             push(@names, @{$attribute->cmd_aliases});
113             }
114             my $attribute_name = join(' ', map { (length($_) == 1) ? "-$_":"--$_" } @names);
115            
116             push(@attributes,[$attribute_name,$attribute->documentation]);
117             }
118            
119             @attributes = sort { $a->[0] cmp $b->[0] } @attributes;
120            
121             return _format_list(@attributes);
122             }
123              
124             sub _usage_header {
125             my ($self,$command) = @_;
126            
127             $command ||= 'command';
128            
129             my $caller = Path::Class::File->new($0)->basename;
130            
131             return <<USAGE_HEADER;
132             usage:
133             $caller $command [long options...]
134             $caller help
135             $caller $command --help
136             USAGE_HEADER
137             }
138              
139             sub task_usage {
140             my ($self,$task_class) = @_;
141            
142             my $task_name = class_to_name($task_class);
143            
144             my $usage_header = $self->_usage_header($task_name);
145             my $short_description = $task_class->description;
146             my $options = $self->_usage_attributes($task_class);
147            
148             say <<USAGE_ACTION;
149             $usage_header
150             short description:
151             $short_description
152              
153             options:
154             $options
155             USAGE_ACTION
156              
157             return;
158             }
159              
160             sub global_usage {
161             my ($self) = @_;
162            
163             my @commands;
164             push(@commands,['help','Prints this usage information']);
165            
166             foreach my $task_class ($self->all_actions()) {
167             my ($ok,$error) = $self->load_action($task_class);
168             next
169             unless $ok;
170             my $task_command = class_to_name($task_class);
171             my $meta = $task_class->meta;
172             my $description = $task_class->description;
173             my $no_automatic = $meta->can('no_automatic') ? $meta->no_automatic : 0;
174             $description .= " [Manual]"
175             if $no_automatic;
176             push(@commands,[$task_command,$description]);
177             }
178            
179             @commands = sort { $a->[0] cmp $b->[0] } @commands;
180            
181             my $global_options = $self->_usage_attributes($self);
182             my $available_commands = _format_list(@commands);
183             my $usage_header = $self->_usage_header();
184            
185             say <<USAGE;
186             $usage_header
187             global options:
188             $global_options
189              
190             available commands:
191             $available_commands
192             USAGE
193              
194             return;
195             }
196              
197             sub _format_list {
198             my (@list) = @_;
199            
200             my $max_length = max(map { length($_->[0]) } @list);
201             my $description_length = $Games::Lacuna::Task::Constants::SCREEN_WIDTH - $max_length - 7;
202             my $prefix_length = $max_length + 5 + 1;
203             my @return;
204            
205             foreach my $command (@list) {
206             my $description = $command->[1];
207             $description .= " [Manual]"
208             if $command->[2];
209             my @lines = _split_string($description_length,$description);
210             push (@return,sprintf(' %-*s %s',$max_length,$command->[0],shift(@lines)));
211             while (my $line = shift (@lines)) {
212             push(@return,' 'x $prefix_length.$line);
213             }
214             }
215             return join("\n",@return);
216             }
217              
218             sub _split_string {
219             my ($maxlength, $string) = @_;
220            
221             return $string
222             if length $string <= $maxlength;
223              
224             my @lines;
225             while (length $string > $maxlength) {
226             my $idx = rindex( substr( $string, 0, $maxlength ), q{ }, );
227             last unless $idx >= 0;
228             push @lines, substr($string, 0, $idx);
229             substr($string, 0, $idx + 1) = q{};
230             }
231             push @lines, $string;
232             return @lines;
233             }
234              
235             __PACKAGE__->meta->make_immutable;
236             no Moose;
237             1;