File Coverage

lib/Module/Provision/TraitFor/Rendering.pm
Criterion Covered Total %
statement 53 87 60.9
branch 3 24 12.5
condition 1 15 6.6
subroutine 14 18 77.7
pod 5 5 100.0
total 76 149 51.0


line stmt bran cond sub pod time code
1             package Module::Provision::TraitFor::Rendering;
2              
3 1     1   677 use namespace::autoclean;
  1         3  
  1         9  
4              
5 1     1   85 use Class::Usul::Constants qw( EXCEPTION_CLASS FALSE NUL OK TRUE );
  1         3  
  1         9  
6 1     1   889 use Class::Usul::Functions qw( app_prefix is_arrayref distname io throw );
  1         2  
  1         9  
7 1     1   1277 use File::DataClass::Types qw( ArrayRef Bool Directory Path SimpleStr );
  1         2  
  1         9  
8 1     1   1590 use File::ShareDir ( );
  1         1831  
  1         38  
9 1     1   7 use Scalar::Util qw( blessed weaken );
  1         3  
  1         59  
10 1     1   477 use Template;
  1         15504  
  1         36  
11 1     1   8 use Unexpected::Functions qw( Unspecified );
  1         3  
  1         11  
12 1     1   389 use Moo::Role;
  1         3  
  1         10  
13 1     1   426 use Class::Usul::Options;
  1         4  
  1         13  
14              
15             requires qw( add_leader appldir builder config dist_module exec_perms file
16             incdir initial_wd loc log perms stash testdir vcs yorn );
17              
18             # Object attributes (public)
19             option 'force' => is => 'ro', isa => Bool,
20             documentation => 'Overwrite files if they already exist',
21             default => FALSE, short => 'f';
22              
23             option 'templates' => is => 'ro', isa => SimpleStr, format => 's',
24             documentation => 'Non default location of the code templates',
25             default => NUL;
26              
27             has 'template_dir' => is => 'lazy', isa => Directory, coerce => TRUE,
28             init_arg => undef;
29              
30             has 'template_list' => is => 'lazy', isa => ArrayRef, init_arg => undef;
31              
32             # Object attributes (private)
33             has '_template_index' => is => 'lazy', isa => Path, coerce => TRUE,
34             init_arg => undef;
35              
36             # Private methods
37             my $_deref_tmpl = sub {
38             my ($self, $car) = @_; '_' ne substr $car, 0, 1 and return $car;
39              
40             my $reader = substr $car, 1; return $self->$reader();
41             };
42              
43             my $_merge_lists = sub {
44             my ($self, $args) = @_; my $list = $args->{templates};
45              
46             push @{ $list }, @{ $args->{builders}->{ $self->builder } };
47             $self->vcs ne 'none' and push @{ $list }, @{ $args->{vcs}->{ $self->vcs } };
48              
49             return $list;
50             };
51              
52             my $_template_args = sub {
53             my $self = shift; weaken( $self ); my $args = { ABSOLUTE => TRUE, };
54              
55             $args->{VARIABLES}->{loc} = sub { $self->loc( @_ ) };
56              
57             return $args;
58             };
59              
60             # Construction
61             sub _build_template_dir {
62 1     1   21 my $self = shift;
63 1         8 my $class = blessed $self;
64 1 50       12 my $tgt = $self->templates
65             ? io( [ $self->templates ] )->absolute( $self->initial_wd )
66             : io( [ $self->config->my_home, '.'.(app_prefix $class) ] );
67              
68 1 50       885 $tgt->exists and return $tgt; $tgt->mkpath( $self->exec_perms );
  1         80  
69              
70 1         439 my $dist = io( File::ShareDir::dist_dir( distname $class ) );
71              
72 1         717 $_->copy( $tgt ) for ($dist->all_files);
73              
74 1         32667 return $tgt;
75             }
76              
77             sub _build__template_index {
78 1     1   32 return $_[ 0 ]->template_dir->catfile( $_[ 0 ]->config->template_index );
79             }
80              
81             sub _build_template_list {
82 1     1   13 my $self = shift; my $index = $self->_template_index;
  1         16  
83              
84 1 50 33     3536 my $data; $index->exists and $data = $self->file->data_load
  1         5  
85             ( paths => [ $index ], storage_class => 'Any' )
86             and return $self->$_merge_lists( $data );
87 1         68 my $builders = {
88             DZ => [ [ 'dist.ini', '_appldir' ],
89             [ 'DZ_Build.PL', [ '_appldir', '.build.PL' ], ], ],
90             MB => [ [ 'Build.PL', '_appldir' ], ], };
91 1         9 my $templates = [ [ 'Changes', '_appldir' ],
92             [ 'MANIFEST.SKIP', '_appldir' ],
93             [ 'travis.yml', [ '_appldir', '.travis.yml' ] ],
94             [ 'perl_module.pm', '_dist_module' ],
95             [ '02pod.t', '_testdir' ],
96             [ '03podcoverage.t', '_testdir' ],
97             [ '05kwalitee.t', '_testdir' ],
98             [ '06yaml.t', '_testdir' ],
99             [ '07podspelling.t', '_testdir' ],
100             [ '10test_script.t', '_testdir' ],
101             [ 'boilerplate.pm', '_testdir' ], ];
102 1         7 my $vcs = {
103             git => [ [ 'gitcommit-msg', [ '_appldir', '.gitcommit-msg' ] ],
104             [ 'gitignore', [ '_appldir', '.gitignore' ] ],
105             [ 'gitpre-commit', [ '_appldir', '.gitpre-commit' ] ], ],
106             svn => [], };
107              
108 1         26 $self->output( 'Creating index [_1]', { args => [ $index ] } );
109 1         115911 $data = { builders => $builders, templates => $templates, vcs => $vcs };
110 1         26 $self->file->data_dump
111             ( data => $data, path => $index, storage_class => 'Any' );
112 1         105844 return $self->$_merge_lists( $data );
113             }
114              
115             # Public methods
116             sub dump_stash : method {
117 0     0 1 0 my $self = shift; $self->dumper( $self->stash ); return OK;
  0         0  
  0         0  
118             }
119              
120             sub expand_tuple {
121 0     0 1 0 my ($self, $tuple) = @_;
122              
123 0         0 for (my $i = 0, my $max = @{ $tuple }; $i < $max; $i++) {
  0         0  
124 0 0       0 if (is_arrayref $tuple->[ $i ]) {
125 0         0 $tuple->[ $i ]->[ 0 ] = $self->$_deref_tmpl( $tuple->[ $i ]->[ 0 ] );
126 0         0 $tuple->[ $i ] = io( $tuple->[ $i ] );
127             }
128             else {
129 0         0 $tuple->[ $i ] = $self->$_deref_tmpl( $tuple->[ $i ] );
130             }
131             }
132              
133 0         0 return $tuple;
134             }
135              
136             sub init_templates : method {
137 1     1 1 1732 my $self = shift; $self->template_list; return OK;
  1         19  
  1         32  
138             }
139              
140             sub render_template {
141 0     0 1   my ($self, $template, $target) = @_;
142              
143 0 0         $template or throw Unspecified, [ 'Template' ];
144 0 0         $target or throw Unspecified, [ 'Template target' ];
145              
146 0 0 0       $target->exists and $target->is_dir
147             and $target = $target->catfile( $template );
148 0           $template = $self->template_dir->catfile( $template );
149              
150 0 0         $template->exists or
151             return $self->log->warn( $self->loc( 'Path [_1] not found', $template ) );
152              
153 0           my $file = $target->filename; my $prompt;
  0            
154              
155 0 0 0       $target->exists and not $self->force
      0        
      0        
156             and $prompt = $self->loc( 'File [_1] exists, overwrite?', $file )
157             and not $self->yorn( $self->add_leader( $prompt ), FALSE, TRUE )
158             and return $target;
159              
160 0 0         my $tmplt = Template->new( $self->$_template_args )
161             or throw $Template::ERROR;
162 0           my $text = NUL;
163              
164 0 0         $tmplt->process( $template->pathname, $self->stash, \$text )
165             or throw $tmplt->error();
166 0           $target->perms( $self->perms )->print( $text ); $target->close;
  0            
167 0           return $target;
168             }
169              
170             sub render_templates {
171 0 0   0 1   my $self = shift; $self->quiet or $self->output( 'Rendering templates' );
  0            
172              
173 0           for my $tuple (map { $self->expand_tuple( $_ ) } @{ $self->template_list }) {
  0            
  0            
174 0           $self->render_template( @{ $tuple } );
  0            
175             }
176              
177 0           return;
178             }
179              
180             1;
181              
182             __END__
183              
184             =pod
185              
186             =encoding utf8
187              
188             =head1 Name
189              
190             Module::Provision::TraitFor::Rendering - Renders Templates
191              
192             =head1 Synopsis
193              
194             use Moose;
195              
196             extends 'Module::Provision::Base';
197             with 'Module::Provision::TraitFor::Rendering';
198              
199             =head1 Description
200              
201             Renders templates. Uses a list stored in the index file F<index.json> which
202             by default is in the F<~/.module_provision> directory
203              
204             =head1 Configuration and Environment
205              
206             Requires the consuming class to define the attributes; C<appldir>,
207             C<builder>, C<dist_module>, C<incdir>, C<initial_wd>, C<stash>,
208             C<testdir>, and C<vcs>
209              
210             Defines the following attributes;
211              
212             =over 3
213              
214             =item C<force>
215              
216             Overwrite the output files if they already exist
217              
218             =item C<templates>
219              
220             Location of the code templates in the users home directory. Defaults to
221             F<.module_provision>
222              
223             =item C<template_dir>
224              
225             Directory where the templates live
226              
227             =item C<template_list>
228              
229             Data structure that maps the files in the template directory to the files
230             in the project directory
231              
232             =back
233              
234             =head1 Subroutines/Methods
235              
236             =head2 dump_stash - Dump the hash ref used to render a template
237              
238             $exit_code = $self->dump_stash;
239              
240             Uses the internal dumper method to produce a pretty coloured listing
241              
242             =head2 expand_tuple
243              
244             $tuple = $self->expand_tuple( $tuple );
245              
246             Expands the references in the passed tuple
247              
248             =head2 init_templates - Initialise the template directory
249              
250             $exit_code = $self->init_templates;
251              
252             Initialise the F<.module_provision> directory and create the F<index.json> file
253              
254             =head2 render_template
255              
256             $target = $self->render_template( $template, $target );
257              
258             Renders a single template using L<Template>
259              
260             =head2 render_templates
261              
262             $self->render_templates;
263              
264             Renders the list of templates in C<< $self->template_list >> be
265             repeatedly calling calling L</render_template>
266              
267             =head1 Diagnostics
268              
269             None
270              
271             =head1 Dependencies
272              
273             =over 3
274              
275             =item L<Class::Usul>
276              
277             =item L<File::DataClass>
278              
279             =item L<File::ShareDir>
280              
281             =item L<Moose::Role>
282              
283             =item L<Template>
284              
285             =back
286              
287             =head1 Incompatibilities
288              
289             There are no known incompatibilities in this module
290              
291             =head1 Bugs and Limitations
292              
293             There are no known bugs in this module.
294             Please report problems to the address below.
295             Patches are welcome
296              
297             =head1 Acknowledgements
298              
299             Larry Wall - For the Perl programming language
300              
301             =head1 Author
302              
303             Peter Flanigan, C<< <pjfl@cpan.org> >>
304              
305             =head1 License and Copyright
306              
307             Copyright (c) 2017 Peter Flanigan. All rights reserved
308              
309             This program is free software; you can redistribute it and/or modify it
310             under the same terms as Perl itself. See L<perlartistic>
311              
312             This program is distributed in the hope that it will be useful,
313             but WITHOUT WARRANTY; without even the implied warranty of
314             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
315              
316             =cut
317              
318             # Local Variables:
319             # mode: perl
320             # tab-width: 3
321             # End: