File Coverage

blib/lib/App/AppSpec.pm
Criterion Covered Total %
statement 23 105 21.9
branch 0 30 0.0
condition 0 6 0.0
subroutine 8 13 61.5
pod 4 4 100.0
total 35 158 22.1


line stmt bran cond sub pod time code
1             # ABSTRACT: App Module ad utilities for appspec tool
2 2     2   88814 use strict;
  2         13  
  2         49  
3 2     2   8 use warnings;
  2         2  
  2         40  
4 2     2   26 use 5.010;
  2         5  
5 2     2   509 use utf8;
  2         14  
  2         10  
6             package App::AppSpec;
7 2     2   1049 use Term::ANSIColor;
  2         14179  
  2         119  
8 2     2   881 use YAML::PP;
  2         82231  
  2         103  
9 2     2   15 use File::Basename qw/ dirname /;
  2         5  
  2         230  
10              
11             our $VERSION = '0.005'; # VERSION
12              
13 2     2   13 use base 'App::Spec::Run::Cmd';
  2         5  
  2         816  
14              
15             sub _read_spec {
16 0     0     my ($self, $run) = @_;
17 0           my $parameters = $run->parameters;
18              
19 0           my $spec_file = $parameters->{spec_file};
20 0           my $spec = App::Spec->read($spec_file);
21 0           return $spec;
22             }
23              
24             sub cmd_completion {
25 0     0 1   my ($self, $run) = @_;
26 0           my $options = $run->options;
27 0           my $parameters = $run->parameters;
28 0           my $name = $options->{name};
29              
30 0 0         my $shell = $options->{zsh} ? "zsh" : $options->{bash} ? "bash" : '';
    0          
31 0 0         die "Specify which shell" unless $shell;
32              
33 0           my $spec = $self->_read_spec($run);
34 0 0         if (defined $name) {
35 0           $spec->name($name);
36             }
37 0           my $completion = $spec->generate_completion(
38             shell => $shell,
39             );
40 0           say $completion;
41             }
42              
43             sub generate_pod {
44 0     0 1   my ($self, $run) = @_;
45 0           my $parameters = $run->parameters;
46              
47 0           my $spec = $self->_read_spec($run);
48              
49 0           require App::Spec::Pod;
50 0           my $generator = App::Spec::Pod->new(
51             spec => $spec,
52             );
53 0           my $pod = $generator->generate;
54              
55 0           say $pod;
56             }
57              
58             sub cmd_validate {
59 0     0 1   my ($self, $run) = @_;
60 0           my $options = $run->options;
61 0           my $parameters = $run->parameters;
62              
63 0           my @errors;
64 0           require App::AppSpec::Schema::Validator;
65 0           my $validator = App::AppSpec::Schema::Validator->new;
66 0           my $spec_file = $parameters->{spec_file};
67 0 0         if (ref $spec_file eq 'SCALAR') {
68 0           my $spec = YAML::PP::Load($$spec_file);
69 0           @errors = $validator->validate_spec($spec);
70             }
71             else {
72 0           @errors = $validator->validate_spec_file($spec_file);
73             }
74 0           binmode STDOUT, ":encoding(utf-8)";
75 0 0         if (@errors) {
76 0           print $validator->format_errors(\@errors);
77 0           say $run->colored(out => red => "Not valid!");
78             }
79             else {
80 0           say $run->colored(out => [qw/ bold green /] => "Validated ✓");
81             }
82             }
83              
84             sub cmd_new {
85 0     0 1   my ($self, $run) = @_;
86 0           my $options = $run->options;
87 0           my $params = $run->parameters;
88 0           my $dist_path = $params->{path};
89 0           require File::Path;
90              
91 0           my $name = $options->{name};
92 0           my $class = $options->{class};
93 0           my $overwrite = $options->{overwrite};
94 0 0         unless ($name =~ m/^\w[\w+-]*/) {
95 0           die "Option name '$name': invalid app name";
96             }
97 0 0         unless ($class =~ m/^[a-zA-Z]\w*(::\w+)+$/) {
98 0           die "Option class '$class': invalid classname";
99             }
100 0           my $dist = $class;
101 0           $dist =~ s/::/-/g;
102 0   0       $dist = $dist_path // $dist;
103 0 0 0       if (-d $dist and not $overwrite) {
    0          
104 0           die "Directory $dist already exists";
105             }
106             elsif (-d $dist) {
107 0           say "Removing old $dist directory first";
108 0           File::Path::remove_tree($dist);
109             }
110 0           my $spec = <<"EOM";
111             name: $name
112             appspec: { version: '0.001' }
113             class: $class
114             title: 'app title'
115             description: 'app description'
116             options:
117             - name: some-flag
118             type: flag
119             summary: option summary
120             - spec: other-option=s --another option
121             EOM
122 0 0         my $subname = $options->{"with-subcommands"} ? "mycommand" : "execute";
123 0           my $module = <<"EOM";
124             package $class;
125             use strict;
126             use warnings;
127             use feature qw/ say /;
128             use base 'App::Spec::Run::Cmd';
129              
130             sub $subname \{
131             my (\$self, \$run) = \@_;
132             my \$options = \$run->options;
133             my \$parameters = \$run->parameters;
134              
135             say "Hello world";
136             \}
137              
138             1;
139             EOM
140 0           my $script = <<"EOM";
141             #!/usr/bin/env perl
142             use strict;
143             use warnings;
144              
145             use App::Spec;
146             use App::AppSpec;
147             use $class;
148             use File::Share qw/ dist_file /;
149              
150             my \$specfile = dist_file("$dist", "$name-spec.yaml");
151             my \$spec = App::Spec->read(\$specfile);
152             my \$run = \$spec->runner;
153             \$run->run;
154             EOM
155 0 0         if ($options->{"with-subcommands"}) {
156 0           $spec .= <<"EOM";
157             subcommands:
158             mycommand:
159             summary: "Summary for mycommand"
160             op: "mycommand"
161             description: "Description for mycommand"
162             parameters:
163             - name: "myparam"
164             summary: "Summary for myparam"
165             required: 1
166             EOM
167             }
168 0           my $module_path = $class;
169 0           $module_path =~ s#::#/#g;
170 0           $module_path = "$dist/lib/$module_path.pm";
171 0           File::Path::make_path($dist);
172 0           File::Path::make_path("$dist/share");
173 0           File::Path::make_path("$dist/bin");
174 0           File::Path::make_path(dirname $module_path);
175 0           my $specfile = "$dist/share/$name-spec.yaml";
176 0           say "Writing spec to $specfile";
177 0 0         open my $fh, ">", $specfile or die $!;
178 0           print $fh $spec;
179 0           close $fh;
180              
181 0 0         open $fh, ">", $module_path or die $!;
182 0           print $fh $module;
183 0           close $fh;
184              
185 0 0         open $fh, ">", "$dist/bin/$name" or die $!;
186 0           print $fh $script;
187 0           close $fh;
188             }
189              
190             =pod
191              
192             =head1 NAME
193              
194             App::AppSpec - Utilities for App::Spec authors
195              
196             =head1 SYNOPSIS
197              
198             See L documentation for the command line utility.
199              
200             =head1 DESCRIPTION
201              
202             This is the app class for the L command line tool.
203             It contains utilities for L files, like generating
204             completion or pod from it.
205              
206             =head1 METHODS
207              
208             =over 4
209              
210             =item cmd_completion, cmd_new, cmd_validate, generate_pod
211              
212             =back
213              
214             =head1 LICENSE
215              
216             This library is free software and may be distributed under the same terms
217             as perl itself.
218              
219             =cut
220              
221             1;