File Coverage

blib/lib/CTK/Helper.pm
Criterion Covered Total %
statement 42 48 87.5
branch n/a
condition n/a
subroutine 14 17 82.3
pod 3 3 100.0
total 59 68 86.7


line stmt bran cond sub pod time code
1             package CTK::Helper; # $Id: Helper.pm 264 2019-05-17 21:17:51Z minus $
2 1     1   69172 use strict;
  1         10  
  1         30  
3 1     1   615 use utf8;
  1         15  
  1         5  
4              
5             =encoding utf8
6              
7             =head1 NAME
8              
9             CTK::Helper - Helper for building CTK scripts. CLI user interface
10              
11             =head1 VIRSION
12              
13             Version 2.70
14              
15             =head1 SYNOPSIS
16              
17             none
18              
19             =head1 DESCRIPTION
20              
21             Helper for building CTK scripts
22              
23             No public subroutines
24              
25             =head2 nope, skip, yep
26              
27             Internal use only!
28              
29             See C
30              
31             =head1 HISTORY
32              
33             See C file
34              
35             =head1 DEPENDENCIES
36              
37             L
38              
39             =head1 TO DO
40              
41             See C file
42              
43             =head1 BUGS
44              
45             Coming soon
46              
47             =head1 SEE ALSO
48              
49             L
50              
51             =head1 AUTHOR
52              
53             Serż Minus (Sergey Lepenkov) L Eabalama@cpan.orgE
54              
55             =head1 COPYRIGHT
56              
57             Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved
58              
59             =head1 LICENSE
60              
61             This program is free software; you can redistribute it and/or
62             modify it under the same terms as Perl itself.
63              
64             See C file and L
65              
66             =cut
67              
68 1     1   46 use vars qw/$VERSION/;
  1         2  
  1         59  
69             $VERSION = '2.70';
70              
71 1     1   24 use feature qw/say/;
  1         1  
  1         139  
72             #use autouse 'Data::Dumper' => qw(Dumper); #$Data::Dumper::Deparse = 1;
73              
74 1     1   7 use base qw/ CTK::App /;
  1         2  
  1         474  
75              
76 1     1   7 use CTK;
  1         2  
  1         38  
77 1     1   6 use CTK::Util;
  1         2  
  1         30  
78 1     1   477 use CTK::Skel;
  1         3  
  1         52  
79 1     1   7 use Term::ANSIColor qw/colored/;
  1         2  
  1         46  
80 1     1   5 use File::Spec;
  1         2  
  1         24  
81 1     1   5 use Cwd qw/getcwd/;
  1         2  
  1         37  
82 1     1   570 use Text::SimpleTable;
  1         2517  
  1         37  
83 1     1   564 use File::Copy::Recursive qw(dircopy dirmove);
  1         6906  
  1         115  
84              
85             use constant {
86 1         1754 PROJECT_NAME => "Foo",
87             PROJECT_TYPE_DEFAULT => "regular",
88             PROJECT_TYPES => {
89             regular => [qw/common extra regular/],
90             module => [qw/common module/],
91             tiny => [qw/tiny/],
92             daemon => [qw/common extra daemon/],
93             },
94             PROJECT_SKELS => {
95             common => "CTK::Skel::Common",
96             regular => "CTK::Skel::Regular",
97             module => "CTK::Skel::Module",
98             tiny => "CTK::Skel::Tiny",
99             daemon => "CTK::Skel::Daemon",
100             extra => "CTK::Skel::Extra",
101             },
102             PROJECT_VARS => [qw/
103             CTK_VERSION
104             PROJECT_NAME
105             PROJECT_NAMEL
106             PROJECT_TYPE
107             GMT
108             /],
109 1     1   8 };
  1         3  
110              
111             __PACKAGE__->register_handler(
112             handler => "usage",
113             description => "Usage",
114             code => sub {
115             ### CODE:
116             my ($self, $meta, @params) = @_;
117             say(<
118             Usage:
119             ctklib [-dv] [-t regular|tiny|module|daemon] [-D /project/dir] create [PROJECTNAME]
120             ctklib create
121             ctklib create
122             ctklib test
123             ctklib -H
124             ctklib -V
125             USAGE
126             return 0;
127             });
128              
129             __PACKAGE__->register_handler(
130             handler => "version",
131             description => "CTK Version",
132             code => sub {
133             ### CODE:
134             my ($self, $meta, @params) = @_;
135             say sprintf("CTK Version: %s.%s", CTK->VERSION, $self->revision);
136             return 1;
137             });
138              
139             __PACKAGE__->register_handler(
140             handler => "test",
141             description => "CTK Testing",
142             code => sub {
143             ### CODE:
144             my ($self, $meta, @params) = @_;
145             say("Testing CTK environment...");
146             my $summary = 1; # OK
147              
148             # CTK version
149             my $ver = CTK->VERSION;
150             if ($ver) {
151             yep("CTK version: %s", $ver);
152             } else {
153             $summary = nope("Can't get CTK version");
154             }
155              
156             # CTK version
157             my $rev = $self->revision;
158             if ($rev) {
159             yep("CTK revision: %s", $rev);
160             } else {
161             $summary = nope("Can't get CTK revision");
162             }
163              
164             # Handlers list
165             my @handlers = $self->list_handlers;
166             if (@handlers) {
167             yep("Handlers: %s", join(", ", @handlers));
168             } else {
169             $summary = nope("Can't get list of handlers");
170             }
171              
172             # Allowed skels
173             my $skel = new CTK::Skel ( -skels => PROJECT_SKELS );
174             if (my @skels = $skel->skels) {
175             yep("Allowed skeletons: %s", join(", ", @skels));
176             } else {
177             $summary = nope("Can't get list of skeletons");
178             }
179              
180             # Summary
181             if ($summary) {
182             yep("All tests was passed");
183             } else {
184             nope("Testing failed");
185             }
186             print "\n";
187              
188             return 1;
189             });
190              
191             __PACKAGE__->register_handler(
192             handler => "create",
193             description => "Project making",
194             code => sub {
195             ### CODE:
196             my ($self, $meta, @params) = @_;
197             my $projectname = @params ? shift @params : '';
198             my $tty = $self->option("tty");
199             my $yes = $self->option("yes") ? 1 : 0;
200             my $type = $self->option("type");
201             my $dir = $self->option("dir");
202             my %vars = (
203             CTK_VERSION => CTK->VERSION,
204             GMT => CTK::Util::dtf("%w %MON %_D %hh:%mm:%ss %YYYY %Z", time(), 'GMT'), # scalar(gmtime)." GMT"
205             );
206              
207             # Project name
208             {
209             unless ($projectname) {
210             $projectname = ($tty && !$yes)
211             ? $self->cli_prompt('Project Name:', PROJECT_NAME)
212             : PROJECT_NAME;
213             }
214             $projectname =~ s/[^a-z0-9_]/X/ig;
215             if ($tty && $projectname !~ /^[A-Z]/) {
216             printf "The selected name begins with a small letter: %s\n", $projectname;
217             if (!$yes) {
218             return skip('Operation aborted')
219             if $self->cli_prompt('Are you sure you want to continue?:','no') !~ /^\s*y/i;
220             }
221             }
222             $vars{PROJECT_NAME} = $projectname;
223             $vars{PROJECT_NAMEL} = lc($projectname);
224             }
225              
226             # Project type
227             {
228             my $atypes = PROJECT_TYPES;
229             unless ($type) {
230             $type = ($tty && !$yes)
231             ? lc($self->cli_prompt(
232             sprintf('Project type (%s):', join(", ", keys(%$atypes))),
233             PROJECT_TYPE_DEFAULT
234             ))
235             : PROJECT_TYPE_DEFAULT;
236             }
237             return nope('Incorrect type') unless $atypes->{$type};
238             $vars{PROJECT_TYPE} = $type;
239             }
240              
241             # Directory
242             $dir ||= ($tty && !$yes)
243             ? $self->cli_prompt('Please provide destination directory:', File::Spec->catdir(getcwd(), $projectname))
244             : File::Spec->catdir(getcwd(), $projectname);
245             if (-e $dir) {
246             if ($tty) {
247             if (!$yes) {
248             return skip('Operation aborted')
249             if $self->cli_prompt(sprintf('Directory "%s" already exists! Are you sure you want to continue?:', $dir),'no') !~ /^\s*y/i;
250             }
251             } else {
252             return skip('Directory "%s" already exists! Operation forced aborted because pipe mode is enabled', $dir);
253             }
254             }
255              
256             # Summary
257             if ($tty) {
258             my $tbl = Text::SimpleTable->new(
259             [ 25, 'PARAM' ],
260             [ 57, 'VALUE / MESSAGE' ],
261             );
262             $tbl->row( $_, $vars{$_} ) for @{(PROJECT_VARS)};
263             $tbl->hr;
264             $tbl->row( "DIRECTORY", $dir );
265             print("\n",colored(['cyan on_black'], "SUMMARY TABLE:"),"\n", colored(['cyan on_black'], $tbl->draw), "\n");
266             return skip('Operation aborted') if !$yes
267             && $self->cli_prompt('All right?:','yes') !~ /^\s*y/i;
268             }
269              
270             # Start building!
271             {
272             my $tmpdirobj = File::Temp->newdir(TEMPLATE => lc($projectname).'XXXXX', TMPDIR => 1);
273             my $tmpdir = $tmpdirobj->dirname;
274             my $skel = new CTK::Skel (
275             -name => $projectname,
276             -root => $tmpdir,
277             -skels => PROJECT_SKELS,
278             -debug => $tty,
279             -vars => {
280             CTKVERSION => CTK->VERSION,
281             PROJECT_VERSION => "1.00",
282             AUTHOR => "Mr. Anonymous",
283             ADMIN => "root\@example.com",
284             HOMEPAGE => "https://www.example.com",
285             },
286             );
287              
288             #$tmpdir = File::Spec->catdir($self->tempdir, lc($projectname));
289             printf("Creating %s project %s to %s...\n\n", $type, $projectname, $tmpdir);
290              
291             my $skels = PROJECT_TYPES()->{$type} || [];
292             foreach my $s (@$skels) {
293             if ($skel->build($s, $tmpdir, {%vars})) {
294             yep("The %s files have been successfully processed", $s);
295             } else {
296             return nope("Can't build the project to \"%s\" directory", $tmpdir);
297             }
298             }
299              
300             # Move to destination directory
301             if (dirmove($tmpdir, $dir)) {
302             yep("Project was successfully created!");
303             printf("\nAll the project files was located in %s directory\n", $dir);
304             } else {
305             return nope("Can't move directory from \"%s\" to \"%s\": %s", $tmpdir, $dir, $!);
306             }
307             }
308              
309             return 0;
310             });
311              
312             # Colored print
313             sub yep {
314 0     0 1   print(colored(['green on_black'], '[ OK ]'), ' ', sprintf(shift, @_), "\n");
315 0           return 1;
316             }
317             sub nope {
318 0     0 1   print(colored(['red on_black'], '[ FAIL ]'), ' ', sprintf(shift, @_), "\n");
319 0           return 0;
320             }
321             sub skip {
322 0     0 1   print(colored(['yellow on_black'], '[ SKIP ]'), ' ', sprintf(shift, @_), "\n");
323 0           return 1;
324             }
325              
326             1;
327              
328             __END__