File Coverage

blib/lib/Catmandu/Cmd/help.pm
Criterion Covered Total %
statement 20 66 30.3
branch 2 16 12.5
condition 1 3 33.3
subroutine 8 15 53.3
pod 3 5 60.0
total 34 105 32.3


line stmt bran cond sub pod time code
1             package Catmandu::Cmd::help;
2              
3 14     14   135635 use Catmandu::Sane;
  14         42  
  14         104  
4              
5             our $VERSION = '1.2020';
6              
7 14     14   116 use parent 'Catmandu::Cmd';
  14         34  
  14         88  
8 14     14   8304 use App::Cmd::Command::help;
  14         5861  
  14         427  
9 14     14   104 use Catmandu::Util qw(require_package pod_section);
  14         38  
  14         782  
10 14     14   92 use namespace::clean;
  14         36  
  14         86  
11              
12             sub usage_desc {
13 5     5 1 124 '%c help [ <command> | ( export | import | store | fix ) <name> ]';
14             }
15              
16 60     60 1 8280 sub command_names {qw/help --help -h -?/}
17              
18             my %MODULES = (
19             Exporter => {
20             re => qr/^export(er)?$/i,
21             usage => [
22             "catmandu convert ... to %n [options]",
23             "catmandu export ... to %n [options]",
24             ],
25             },
26             Importer => {
27             re => qr/^import(er)?$/i,
28             usage => [
29             "catmandu convert %n [options] to ...",
30             "catmandu import %n [options] to ...",
31             ],
32             },
33             Store => {
34             re => qr/^(store|copy)$/i,
35             usage => [
36             "catmandu import ... to %n [options]",
37             "catmandu copy ... to %n [options]",
38             "catmandu export %n [options] ...",
39             "catmandu copy %n [options] ...",
40             ]
41             },
42             Fix => {re => qr/^fix$/i, usage => ["%n( [options] )"]},
43             'Fix::Bind' =>
44             {re => qr/^bind$/i, usage => ["do %n( [options] ) ... end"]},
45             'Fix::Condition' =>
46             {re => qr/^condition$/i, usage => ["if %n( [options] ) ... end"]},
47             );
48              
49             sub execute {
50 5     5 1 91 my ($self, $opts, $args) = @_;
51              
52             # TODO: list available Importer/Exporters/Stores/Fixes...
53              
54 5 50 33     42 if (@$args == 2) {
    50          
55              
56             # detect many forms such as:
57             # export JSON, exporter JSON, JSON export, JSON exporter
58 0         0 foreach (0, 1) {
59 0         0 foreach my $type (keys %MODULES) {
60 0 0       0 if ($args->[$_] =~ $MODULES{$type}->{re}) {
61 0         0 $self->help_about($type, $args->[($_ + 1) % 2]);
62 0         0 return;
63             }
64             }
65             }
66             }
67             elsif (@$args == 1 && $args->[0] =~ qr/^fix(es)?$/) {
68 0         0 $self->help_fixes;
69 0         0 return;
70             }
71              
72 5         37 App::Cmd::Command::help::execute(@_);
73             }
74              
75             sub help_about {
76 0     0 0   my ($self, $type, $name) = @_;
77              
78 0           my $class;
79 0 0         if ($type eq 'Fix') {
80 0           foreach ('Fix', 'Fix::Bind', 'Fix::Condition') {
81 0           $type = $_;
82             try {
83 0     0     require_package($name, "Catmandu::$type");
84 0           $class = "Catmandu::${type}::$name";
85             }
86 0     0     catch { };
87 0 0         last if $class;
88             }
89 0 0         unless ($class) {
90 0           Catmandu::NoSuchFixPackage->throw(
91             {
92             message => "No such fix package: $name",
93             package_name =>
94             "Catmandu::Fix::(Bind::|Condition::)?$name",
95             fix_name => $name,
96             }
97             );
98             }
99             }
100              
101 0           $class = "Catmandu::${type}::$name";
102 0           require_package($class);
103              
104 0           my $about = pod_section($class, "name");
105 0           $about =~ s/\n/ /mg;
106 0           say ucfirst($about);
107              
108 0           say "\nUsage:";
109 0           print join "", map {s/%n/$name/g; " $_\n"} @{$MODULES{$type}->{usage}};
  0            
  0            
  0            
110              
111 0           my $descr = pod_section($class, "description");
112 0           chomp $descr;
113 0 0         say "\n$descr" if $descr;
114              
115             # TODO: include examples?
116              
117 0           my $options = pod_section($class, "configuration");
118 0 0         if ($options) {
119 0           $options =~ s/^([a-z0-9_-]+)\s*\n?/--$1, /mgi;
120 0           $options
121 0           =~ s/^(--[a-z0-9_-]+(,\s*--[a-z0-9_-]+)*),\s*([^-])/" $1\n $3"/emgi;
122 0           print "\nOptions:\n$options";
123             }
124             }
125              
126             sub help_fixes {
127 0     0 0   my ($self) = @_;
128              
129             my $fixes = Catmandu->importer(
130             'Modules',
131             namespace => 'Catmandu::Fix',
132             primary => 1
133             )->select(name => qr/::[a-z][^:]*$/)->map(
134             sub {
135 0     0     $_[0]->{name} =~ s/.*:://;
136 0           $_[0];
137             }
138 0           );
139              
140 0     0     my $len = $fixes->max(sub {length $_[0]->{name}});
  0            
141             $fixes->sorted('name')->each(
142             sub {
143 0     0     say sprintf "%-${len}s %s", $_[0]->{name}, $_[0]->{about};
144             }
145 0           );
146              
147 0           say "\nGet additional help with: catmandu help fix <NAME>";
148             }
149              
150             1;
151              
152             __END__
153              
154             =pod
155              
156             =head1 NAME
157              
158             Catmandu::Cmd::help - show help
159              
160             =head1 EXAMPLES
161              
162             catmandu help convert
163             catmandu help import JSON
164             catmandu help help
165             catmandu help fix set_field
166              
167             =cut