File Coverage

blib/lib/Catmandu/Cmd.pm
Criterion Covered Total %
statement 54 72 75.0
branch 9 16 56.2
condition 1 2 50.0
subroutine 13 16 81.2
pod 7 7 100.0
total 84 113 74.3


line stmt bran cond sub pod time code
1             package Catmandu::Cmd;
2              
3 14     14   135363 use Catmandu::Sane;
  14         32  
  14         81  
4              
5             our $VERSION = '1.2020';
6              
7 14     14   114 use parent qw(App::Cmd::Command);
  14         28  
  14         126  
8 14     14   39362 use Catmandu::Util qw(is_array_ref pod_section);
  14         33  
  14         803  
9 14     14   7289 use Catmandu::Fix;
  14         893  
  14         628  
10 14     14   9180 use Encode qw(decode);
  14         193806  
  14         1034  
11 14     14   758 use Log::Any ();
  14         145  
  14         336  
12 14     14   107 use namespace::clean;
  14         32  
  14         103  
13              
14             sub log {
15 0     0 1 0 Log::Any->get_logger(category => ref($_[0]));
16             }
17              
18             # Internal required by App::Cmd;
19             sub prepare {
20 39     39 1 54295 my ($self, $app, @args) = @_;
21              
22             # not always available
23 39         105 eval {
24 39         6776 require I18N::Langinfo;
25 39         13408 I18N::Langinfo->import(qw(langinfo CODESET));
26 39         317 my $codeset = langinfo(CODESET());
27 39         136 @args = map {decode $codeset, $_} @args;
  134         8290  
28             };
29 39         5023 $self->SUPER::prepare($app, @args);
30             }
31              
32             # Internal required by App::Cmd
33             sub opt_spec {
34 39     39 1 1676 my ($class, $cli) = @_;
35             (
36 39         221 ['help|h|?', "print this usage screen"],
37             $cli->global_opt_spec, $class->command_opt_spec($cli),
38             );
39             }
40              
41             # Internal required by App::Cmd
42             sub execute {
43 34     34 1 752 my ($self, $opts, $args) = @_;
44              
45 34 50       252 if ($opts->{version}) {
46 0         0 print $Catmandu::VERSION;
47 0         0 exit;
48             }
49 34 50       153 if ($opts->{help}) {
50 0         0 print $self->usage->text;
51 0         0 exit;
52             }
53              
54 34         190 $self->command($opts, $args);
55             }
56              
57             # show examples, if available in POD
58             sub description {
59 0     0 1 0 my $class = ref shift;
60              
61 0         0 my $s = pod_section($class, "name");
62 0         0 $s =~ s/.*\s+-\s+//;
63 0         0 $s = ucfirst($s);
64 0         0 $s .= "\n";
65              
66 0         0 for (pod_section($class, "examples")) {
67 0         0 $s .= "Examples:\n\n$_";
68             }
69              
70 0         0 "$s\nOptions:";
71             }
72              
73             # These should be implemented by the Catmandu::Cmd's
74       5 1   sub command_opt_spec { }
75       0 1   sub command { }
76              
77             # helpers
78             sub _parse_options {
79 32     32   123 my ($self, $args, %opts) = @_;
80              
81 32   50     262 $opts{separator} //= 'to';
82              
83 32         101 my $a = my $lft_args = [];
84 32         86 my $o = my $lft_opts = {};
85 32         74 my $rgt_args = [];
86 32         77 my $rgt_opts = {};
87              
88 32         244 for (my $i = 0; $i < @$args; $i++) {
89 81         166 my $arg = $args->[$i];
90 81 100       340 if ($arg eq $opts{separator}) {
    100          
91 22         55 $a = $rgt_args;
92 22         56 $o = $rgt_opts;
93             }
94             elsif ($arg =~ s/^-+//) {
95 15         57 $arg =~ s/-/_/g;
96 15 50       44 if (exists $o->{$arg}) {
97 0 0       0 if (is_array_ref($o->{$arg})) {
98 0         0 push @{$o->{$arg}}, $args->[++$i];
  0         0  
99             }
100             else {
101 0         0 $o->{$arg} = [$o->{$arg}, $args->[++$i]];
102             }
103             }
104             else {
105 15         87 $o->{$arg} = $args->[++$i];
106             }
107             }
108             else {
109 44         165 push @$a, $arg;
110             }
111             }
112              
113 32         169 return $lft_args, $lft_opts, $rgt_args, $rgt_opts;
114             }
115              
116             sub _build_fixer {
117 9     9   38 my ($self, $opts) = @_;
118 9 50       48 if ($opts->var) {
119 0         0 return Catmandu::Fix->new(
120             preprocess => 1,
121             fixes => $opts->fix,
122             variables => $opts->var,
123             );
124             }
125             Catmandu::Fix->new(
126 9 50       75 preprocess => $opts->preprocess ? 1 : 0,
127             fixes => $opts->fix,
128             );
129             }
130              
131             1;
132              
133             __END__
134              
135             =pod
136              
137             =head1 NAME
138              
139             Catmandu::Cmd - A base class for extending the Catmandu command line
140              
141             =head1 SYNOPSIS
142              
143             # to create a command:
144             $ catmandu hello_world
145              
146             # you need a package:
147             package Catmandu::Cmd::hello_world;
148             use parent 'Catmandu::Cmd';
149              
150             sub command_opt_spec {
151             (
152             [ "greeting|g=s", "provide a greeting text" ],
153             );
154             }
155              
156             sub description {
157             <<EOS;
158             examples:
159              
160             catmandu hello_world --greeting "Hoi"
161              
162             options:
163             EOS
164             }
165              
166             sub command {
167             my ($self, $opts, $args) = @_;
168             my $greeting = $opts->greeting // 'Hello';
169             print "$greeting, World!\n"
170             }
171              
172             =head1 NAME
173              
174             Catmandu::Cmd::hello_world - prints a funny line
175              
176             =cut
177              
178              
179              
180             =head1 DESCRIPTION
181              
182             Catmandu:Cmd is a base class to extend the commands that can be provided for
183             the 'catmandu' command line tools. New catmandu commands should be defined in
184             the Catmandu::Cmd namespace and extend Catmandu::Cmd.
185              
186             Every command needs to implement 4 things:
187              
188             * command_opt_spec - which should return an array of command options with documentation
189             * description - a long description of the command
190             * command - the body which is executed
191             * head1 NAME - a short description of the command
192              
193             =head1 METHODS
194              
195             =head2 log()
196              
197             Access to the logger
198              
199             =head2 command_opt_spec()
200              
201             This method should be overridden to provide option specifications. (This is list of arguments passed to describe_options from Getopt::Long::Descriptive, after the first.)
202              
203             If not overridden, it returns an empty list.
204              
205             =head2 description()
206              
207             This method should return a string containing the long documentation of the command
208              
209             =head2 command()
210              
211             This method does whatever it is the command should do! It is passed a hash reference of the parsed command-line options and an array reference of left over arguments.
212              
213             =head1 DOCUMENTATION
214              
215             At least provide for every command a NAME documentation
216              
217             =head1 SEE ALSO
218              
219             L<Catmandu::Cmd::config> , L<Catmandu::Cmd::convert> , L<Catmandu::Cmd::count> ,
220             L<Catmandu::Cmd::data> , L<Catmandu::Cmd::delete> , L<Catmandu::Cmd::export>,
221             L<Catmandu::Cmd::import> , L<Catmandu::Cmd::move> , L<Catmandu::Cmd::run>
222              
223             =cut