| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Kelp::Generator; |
|
2
|
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
20
|
use Kelp::Base; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
23
|
|
|
4
|
3
|
|
|
3
|
|
2725
|
use Path::Tiny; |
|
|
3
|
|
|
|
|
51356
|
|
|
|
3
|
|
|
|
|
203
|
|
|
5
|
3
|
|
|
3
|
|
1486
|
use Kelp::Template; |
|
|
3
|
|
|
|
|
9
|
|
|
|
3
|
|
|
|
|
15
|
|
|
6
|
3
|
|
|
3
|
|
15
|
use Carp; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
3252
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
attr -templates_dir => sub { path(__FILE__)->parent . '/templates' }; |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
sub list_templates |
|
11
|
|
|
|
|
|
|
{ |
|
12
|
2
|
|
|
2
|
1
|
5
|
my ($self) = @_; |
|
13
|
|
|
|
|
|
|
|
|
14
|
2
|
|
|
|
|
17
|
my $dir = $self->templates_dir; |
|
15
|
2
|
|
|
|
|
454
|
return map { path($_)->basename } glob "$dir/*"; |
|
|
4
|
|
|
|
|
148
|
|
|
16
|
|
|
|
|
|
|
} |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub get_template_files |
|
19
|
|
|
|
|
|
|
{ |
|
20
|
1
|
|
|
1
|
1
|
4
|
my ($self, $template) = @_; |
|
21
|
|
|
|
|
|
|
|
|
22
|
1
|
|
|
|
|
6
|
my $dir = $self->templates_dir; |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# instead of just globbing for files, introduce template files that will |
|
25
|
|
|
|
|
|
|
# list all the files for a template (otherwise any old files will just stay |
|
26
|
|
|
|
|
|
|
# there and be generated in new versions) |
|
27
|
1
|
|
|
|
|
5
|
my ($index_file) = map { "$dir/$_/template" } |
|
28
|
1
|
|
|
|
|
270
|
grep { $_ eq $template } |
|
|
2
|
|
|
|
|
68
|
|
|
29
|
|
|
|
|
|
|
$self->list_templates |
|
30
|
|
|
|
|
|
|
; |
|
31
|
1
|
50
|
|
|
|
7
|
return unless $index_file; |
|
32
|
|
|
|
|
|
|
|
|
33
|
1
|
|
|
|
|
3
|
my $index = path($index_file); |
|
34
|
1
|
50
|
|
|
|
39
|
return unless $index->is_file; |
|
35
|
|
|
|
|
|
|
|
|
36
|
1
|
|
|
|
|
45
|
my @files = map { s/^\s+//; s/\s+$//; $_ } $index->lines({chomp => 1}); |
|
|
11
|
|
|
|
|
401
|
|
|
|
11
|
|
|
|
|
66
|
|
|
|
11
|
|
|
|
|
21
|
|
|
37
|
1
|
|
|
|
|
5
|
return map { "$dir/$template/$_" } grep { length } @files; |
|
|
10
|
|
|
|
|
26
|
|
|
|
11
|
|
|
|
|
18
|
|
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub get_template |
|
41
|
|
|
|
|
|
|
{ |
|
42
|
2
|
|
|
2
|
1
|
9
|
my ($self, $template, $name, %args) = @_; |
|
43
|
|
|
|
|
|
|
|
|
44
|
2
|
100
|
|
|
|
9
|
croak "Invalid name $name - not a Perl package name" |
|
45
|
|
|
|
|
|
|
unless $name =~ m/^[\w:]+$/; |
|
46
|
|
|
|
|
|
|
|
|
47
|
1
|
|
|
|
|
4
|
my $vars = {name => $name, %args}; |
|
48
|
1
|
|
|
|
|
5
|
my @parts = split(/::/, $name); |
|
49
|
1
|
|
|
|
|
4
|
$vars->{module_file} = pop @parts; |
|
50
|
1
|
|
|
|
|
4
|
$vars->{module_path} = join('/', @parts); |
|
51
|
|
|
|
|
|
|
|
|
52
|
1
|
|
|
|
|
6
|
my @list = $self->get_template_files($template); |
|
53
|
1
|
50
|
|
|
|
5
|
croak "There's no generation template for $template" |
|
54
|
|
|
|
|
|
|
unless @list > 0; |
|
55
|
|
|
|
|
|
|
|
|
56
|
1
|
|
|
|
|
3
|
my @retval; |
|
57
|
1
|
|
|
|
|
15
|
my $tt = Kelp::Template->new(); |
|
58
|
1
|
|
|
|
|
3
|
for my $path (@list) { |
|
59
|
10
|
|
|
|
|
34
|
my $file = path($path); |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# resolve the destination name |
|
62
|
|
|
|
|
|
|
# hyphens become directory separators |
|
63
|
10
|
|
|
|
|
483
|
(my $dest_file = $file->basename) =~ s{-}{/}g; |
|
64
|
10
|
|
|
|
|
511
|
$dest_file =~ s/NAME/$vars->{name}/g; |
|
65
|
10
|
|
|
|
|
28
|
$dest_file =~ s/PATH/$vars->{module_path}/g; |
|
66
|
10
|
|
|
|
|
20
|
$dest_file =~ s/FILE/$vars->{module_file}/g; |
|
67
|
10
|
|
|
|
|
20
|
$dest_file =~ s/DOT/./g; |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# process the template, if it is .gen (generated) |
|
70
|
10
|
|
|
|
|
48
|
my $contents = $file->slurp({binmode => ':encoding(UTF-8)'}); |
|
71
|
10
|
100
|
|
|
|
5425
|
if ($dest_file =~ /\.gen$/) { |
|
72
|
9
|
|
|
|
|
37
|
$dest_file =~ s/\.gen$//; |
|
73
|
9
|
|
|
|
|
40
|
$contents = $tt->process(\$contents, $vars); |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
|
|
76
|
10
|
|
|
|
|
65
|
push @retval, [$dest_file, $contents]; |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
1
|
|
|
|
|
27
|
return \@retval; |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
1; |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=pod |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=head1 NAME |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
Kelp::Generator - Generation templates |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
use Kelp::Generator; |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
my $gen = Kelp::Generator->new; |
|
95
|
|
|
|
|
|
|
# get available templates |
|
96
|
|
|
|
|
|
|
my @template = $gen->list_templates; |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# get parsed files (ready to be saved) |
|
99
|
|
|
|
|
|
|
my $files_aref = $gen->get_template($template, 'App::Name'); |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
for my $file (@$files_aref) { |
|
102
|
|
|
|
|
|
|
my ($file_name, $file_contents) = @$file; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
This is a class for discovery and parsing of generation templates for Kelp. A |
|
108
|
|
|
|
|
|
|
generation template is a set of files that can be parsed using |
|
109
|
|
|
|
|
|
|
L<Template::Tiny> and inserted into a given directory. This class only handles |
|
110
|
|
|
|
|
|
|
the discovery and parsing of these templates. The C<kelp-generator> script or |
|
111
|
|
|
|
|
|
|
custom script should handle saving them in a destination directory. |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head1 TEMPLATE CREATION |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head2 Discovery |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
This class will look into a directory in its installation tree to discover |
|
118
|
|
|
|
|
|
|
available templates. The folder is C<Kelp/templates> by default and can be |
|
119
|
|
|
|
|
|
|
changed by constructing the object with different C<templates_dir> attribute. |
|
120
|
|
|
|
|
|
|
This means that CPAN modules can add templates to L<Kelp/templates> and they |
|
121
|
|
|
|
|
|
|
will be discovered as long as they have been installed in the same root |
|
122
|
|
|
|
|
|
|
directory as Kelp without changing the contents of the package variable. Any |
|
123
|
|
|
|
|
|
|
template that can be discovered in the default directory will be usable in the |
|
124
|
|
|
|
|
|
|
C<kelp-generator> script. |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head2 Contents |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
The directory structure of C<Kelp/templates> directory is as follows: |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
+ templates |
|
131
|
|
|
|
|
|
|
| + template_name |
|
132
|
|
|
|
|
|
|
| - template |
|
133
|
|
|
|
|
|
|
| - file1.pl.gen |
|
134
|
|
|
|
|
|
|
| - NAME.pm.gen |
|
135
|
|
|
|
|
|
|
| + another_template_name |
|
136
|
|
|
|
|
|
|
| - template |
|
137
|
|
|
|
|
|
|
| - file1.tt |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Each template directory must have a file named C<template>, which lists all the |
|
140
|
|
|
|
|
|
|
files in that template like this: |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
file1.pl.gen |
|
143
|
|
|
|
|
|
|
NAME.pm.gen |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
Any file that is not listed will not be used. |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head2 Template files |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Each template file can contain L<Template> code: |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
My::App::Name eq [% name %] |
|
152
|
|
|
|
|
|
|
Name eq [% module_file %] |
|
153
|
|
|
|
|
|
|
My/App eq [% module_path %] |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
It will be replaced accordingly, but only if the file ends with C<.gen> |
|
156
|
|
|
|
|
|
|
extension. This extension also allows template files not to be confused with |
|
157
|
|
|
|
|
|
|
real files, so should be used most of the time. The only case where the C<.gen> |
|
158
|
|
|
|
|
|
|
extension should not be used in when generating template files using the same |
|
159
|
|
|
|
|
|
|
syntax as L<Template>, because there's no way to tell which directives should |
|
160
|
|
|
|
|
|
|
not be interpreted right away. |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Files can also contain NAME, FILE, PATH and DOT in their name, which will be |
|
163
|
|
|
|
|
|
|
replaced by C<name>, C<module_file>, C<module_path> and C<.>. |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head1 INTERFACE |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head2 Methods |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head3 new |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
my $gen = Kelp::Generator->new(templates_dir => $dir); |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Constructs a Kelp::Generator instance. C<templates_dir> is optional. |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head3 templates_dir |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Returns the current templates directory. Can be changed by passing an argument |
|
178
|
|
|
|
|
|
|
of this name to C<new> |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head3 get_template |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
my $template_aref = $gen->get_template($template_name, $application_name, %more_vars); |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Finds and parses template with L<Template::Tiny>, returning an array reference of files: |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
['file1.pl', 'contents'], |
|
187
|
|
|
|
|
|
|
['replaced_name.pm', 'contents'], |
|
188
|
|
|
|
|
|
|
... |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Filenames will have directories and C<.gen> suffix stripped and all |
|
191
|
|
|
|
|
|
|
placeholders replaced. File contents will be ready for saving. |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
C<%more_vars> can be specified to insert more variables into the template. |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head3 list_templates |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
my @templates = $gen->list_templates; |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Discovers and returns all the generation template names as a list. |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=head3 get_template_files |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
my @files = $gen->get_template_files($template_name); |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Returns the list of template files for a given template. Will return full |
|
206
|
|
|
|
|
|
|
paths, not just file names. |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=cut |
|
209
|
|
|
|
|
|
|
|