File Coverage

blib/lib/Dist/Zilla/Role/TextTemplater.pm
Criterion Covered Total %
statement 112 113 99.1
branch 31 34 91.1
condition 7 11 63.6
subroutine 21 21 100.0
pod 4 4 100.0
total 175 183 95.6


line stmt bran cond sub pod time code
1             # ---------------------------------------------------------------------- copyright and license ---
2             #
3             # file: lib/Dist/Zilla/Role/TextTemplater.pm
4             #
5             # Copyright © 2015, 2016 Van de Bugger.
6             #
7             # This file is part of perl-Dist-Zilla-Role-TextTemplater.
8             #
9             # perl-Dist-Zilla-Role-TextTemplater is free software: you can redistribute it and/or modify it
10             # under the terms of the GNU General Public License as published by the Free Software Foundation,
11             # either version 3 of the License, or (at your option) any later version.
12             #
13             # perl-Dist-Zilla-Role-TextTemplater is distributed in the hope that it will be useful, but
14             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15             # PARTICULAR PURPOSE. See the GNU General Public License for more details.
16             #
17             # You should have received a copy of the GNU General Public License along with
18             # perl-Dist-Zilla-Role-TextTemplater. If not, see <http://www.gnu.org/licenses/>.
19             #
20             # ---------------------------------------------------------------------- copyright and license ---
21              
22             #pod =for :this This is C<Dist::Zilla::Role::TextTemplater> module documentation. Read this if you want to
23             #pod have text templating capabilities in your Dist::Zilla plugin.
24             #pod
25             #pod =for :those If you are using a C<TextTemplater>-based plugin, read the
26             #pod L<manual|Dist::Zilla::Role::TextTemplater::Manual>. General topics like getting source, building, installing, bug
27             #pod reporting and some others are covered in the F<README>.
28             #pod
29             #pod =for test_synopsis my ( $result, $template, $file );
30             #pod
31             #pod =head1 SYNOPSIS
32             #pod
33             #pod package Dist::Zilla::Plugin::YourPlugin;
34             #pod use Moose;
35             #pod use namespace::autoclean;
36             #pod with 'Dist::Zilla::Role::Plugin';
37             #pod with 'Dist::Zilla::Role::TextTemplater';
38             #pod
39             #pod sub method {
40             #pod my $self = shift( @_ );
41             #pod ...;
42             #pod $result = $self->fill_in_string( $template );
43             #pod ...;
44             #pod };
45             #pod
46             #pod sub another_method {
47             #pod my $self = shift( @_ );
48             #pod ...;
49             #pod $self->fill_in_file( $file );
50             #pod ...;
51             #pod };
52             #pod
53             #pod __PACKAGE__->meta->make_immutable;
54             #pod 1;
55             #pod
56             #pod =head1 DESCRIPTION
57             #pod
58             #pod The role provides a consuming plugin with C<fill_in_string> and C<fill_in_file> methods and bunch
59             #pod of accompanying attributes and F<dist.ini> options.
60             #pod
61             #pod =cut
62              
63             package Dist::Zilla::Role::TextTemplater;
64              
65 1     1   2135052 use Moose::Role;
  1         3  
  1         13  
66 1     1   8071 use namespace::autoclean;
  1         2  
  1         11  
67 1     1   101 use version 0.77;
  1         68  
  1         19  
68              
69             # ABSTRACT: Have text templating capabilities in your Dist::Zilla plugin
70             our $VERSION = 'v0.8.5_02'; # TRIAL VERSION
71              
72             with 'Dist::Zilla::Role::ErrorLogger' => { -version => 'v0.6.0' }; # Need `log_errors_in_file`.
73              
74 1     1   209 use Carp qw{ croak };
  1         4  
  1         106  
75 1     1   8 use Dist::Zilla::File::InMemory;
  1         2  
  1         48  
76 1     1   7 use Dist::Zilla::File::OnDisk;
  1         2  
  1         43  
77 1     1   6 use List::Util qw{ min max };
  1         2  
  1         104  
78 1     1   11 use Text::Template qw{};
  1         17  
  1         2794  
79              
80             # --------------------------------------------------------------------------------------------------
81              
82             # It is a `my` variable, not a sub to keep consumer namespace clean.
83              
84             my $tt_param = sub {
85             my ( $name, $args ) = @_;
86             return Text::Template::_param( $name, %$args ); ## no critic ( ProtectPrivateSubs )
87             };
88              
89             # --------------------------------------------------------------------------------------------------
90              
91             #pod =attr delimiters
92             #pod
93             #pod Pair of opening delimiter and closing delimiter to denote code fragments in template.
94             #pod
95             #pod Attribute introduces F<dist.ini> option with the same name. Option value will be split on
96             #pod whitespaces (result should be two items) to initialize the attribute.
97             #pod
98             #pod C<Str|ArrayRef[Str]>, read-only. Default value is C<[ '{{', '}}' ]>.
99             #pod
100             #pod See L<Dist::Zilla::Role::TextTemplater/"Delimiters">.
101             #pod
102             #pod =cut
103              
104             has delimiters => (
105             is => 'ro',
106             isa => 'Str|ArrayRef[Str]',
107             lazy => 1,
108             default => sub { [ '{{', '}}' ] },
109             trigger => sub {
110             my ( $self, $new ) = @_;
111             if ( not ref( $new ) ) {
112             $new =~ s{\A\s+}{}x; # Drop leading ws, or `split` may leave the first item empty.
113             $new = [ split( qr{\s+}x, $new ) ];
114             @$new == 2
115             or croak "\"delimiters\" value must be Str of *two* whitespace-separated words";
116             $self->{ delimiters } = $new;
117             } else {
118             @$new == 2
119             or croak "\"delimiters\" value must be ArrayRef with *two* elements";
120             };
121             },
122             );
123              
124             # --------------------------------------------------------------------------------------------------
125              
126             #pod =attr package
127             #pod
128             #pod Name of package to evaluate code fragments in.
129             #pod
130             #pod Attribute introduces F<dist.ini> option with the same name.
131             #pod
132             #pod C<Str>, read-only, optional.
133             #pod
134             #pod See L<Dist::Zilla::Role::TextTemplater/"Package">.
135             #pod
136             #pod =cut
137              
138             has package => (
139             is => 'ro',
140             isa => 'Str',
141             init_arg => 'package',
142             );
143              
144             # --------------------------------------------------------------------------------------------------
145              
146             #pod =attr prepend
147             #pod
148             #pod Perl code to prepend to the beginning of every code fragment.
149             #pod
150             #pod Attribute introduces F<dist.ini> multi-value option with the same name.
151             #pod
152             #pod C<ArrayRef[Str]>, read-only, auto dereferenced. Default value is empty array. Consumers may specify
153             #pod alternative default by defining C<_build_prepend> method.
154             #pod
155             #pod See L<Dist::Zilla::Role::TextTemplater/"Prepend">.
156             #pod
157             #pod =cut
158              
159             has prepend => (
160             is => 'ro',
161             isa => 'ArrayRef[Str]',
162             builder => '_build_prepend',
163             auto_deref => 1,
164             );
165              
166             sub _build_prepend {
167 30     30   139937 return [];
168             };
169              
170             # --------------------------------------------------------------------------------------------------
171              
172             #pod =method tt_broken
173             #pod
174             #pod This method is called if a code fragment dies. It formats error message(s) and sends it to the log
175             #pod by calling C<log_error>.
176             #pod
177             #pod See C<BROKEN> option of L<Text::Template/"fill_in">.
178             #pod
179             #pod =cut
180              
181             sub tt_broken {
182 12     12 1 42 my ( $self, %args ) = @_;
183             #
184             # Parse arguments.
185             #
186 12         609 my $tfile = $self->tt_file->name; # Template filename.
187 12         781 my $tline = $args{ lineno }; # Template line where the broken code fragment begins.
188 12         67 my $tmesg = sprintf( 'Bad code fragment begins at %s line %d.', $tfile, $tline );
189 12         24 my $emesg = $args{ error }; # Actual error message.
190 12 100       236 my $eline = $emesg =~ m{ \s at \s \Q$tfile\E \s line \s (\d+)}x ? $1 : 0;
191             # Line of actual error (if it is in template file, zero otherwise).
192 12         50 chomp( $emesg );
193             #
194             # Report errors.
195             #
196 12         74 $self->log_error( $emesg );
197 12         6050 $self->log_error( ' ' . $tmesg );
198             # ^ `croak` when reporting call stack, indents it with tab. Let's do the same. However,
199             # tab has unpredictable width, so let us indent 'call stack' by four spaces.
200             #
201             # Now save errors to report in the template file.
202             #
203 12 100       3876 if ( $eline ) {
204 11         20 push( @{ $self->tt_errors }, $eline => $emesg );
  11         597  
205             };
206 12 100       49 if ( $tline != $eline ) {
207             # Do not report beginning of the bad code fragment if actual error occurred in the
208             # same file and line.
209 5         8 push( @{ $self->tt_errors }, $tline => $tmesg );
  5         315  
210             };
211 12         59 return $emesg;
212             };
213              
214             around tt_broken => sub {
215             my ( $orig, $self, @args ) = @_;
216             ++ $self->{ tt_broken_count };
217             my $rc = $self->$orig( @args );
218             if ( $self->tt_broken_count >= $self->tt_broken_limit ) {
219             $self->log_error( [
220             'Too many errors in %s, only first %d are reported.',
221             $self->tt_file->name,
222             $self->tt_broken_count,
223             ] );
224             $rc = undef;
225             };
226             return $rc;
227             };
228              
229             # --------------------------------------------------------------------------------------------------
230              
231             #pod =attr tt_file
232             #pod
233             #pod File being processed (either actual file or temporary C<InMemory> file when processing a string).
234             #pod Available only during template processing. May be used in C<tt_broken> method.
235             #pod
236             #pod C<Object>, read-only, not an init arg.
237             #pod
238             #pod =cut
239              
240             has tt_file => (
241             isa => 'Object',
242             is => 'ro',
243             init_arg => undef,
244             );
245              
246             # --------------------------------------------------------------------------------------------------
247              
248             #pod =attr tt_errors
249             #pod
250             #pod Errors detected in template file, in format suitable for C<log_errors_in_file> (defined in
251             #pod C<ErrorLogger> role). May be used in C<tt_broken> method.
252             #pod
253             #pod C<ArrayRef>, read-write, not an init arg.
254             #pod
255             #pod =cut
256              
257             has tt_errors => (
258             isa => 'ArrayRef',
259             is => 'rw',
260             init_arg => undef,
261             );
262              
263             # --------------------------------------------------------------------------------------------------
264              
265             #pod =attr tt_broken_count
266             #pod
267             #pod Number of C<tt_broken> calls. The counter is increased before C<tt_broken> call.
268             #pod
269             #pod C<Int>, read-only, not an init arg.
270             #pod
271             #pod =cut
272              
273             has tt_broken_count => (
274             is => 'ro',
275             isa => 'Int',
276             init_arg => undef,
277             default => 0,
278             );
279              
280             # --------------------------------------------------------------------------------------------------
281              
282             #pod =attr tt_broken_limit
283             #pod
284             #pod If number of completed C<tt_broken> calls equals or exceeds this limit, processing stops.
285             #pod
286             #pod C<Int>, read-only, not an init arg, default value 10.
287             #pod
288             #pod There is no (official) way to change the attribute value now. Let me know if you need it.
289             #pod
290             #pod =cut
291              
292             has tt_broken_limit => (
293             is => 'ro',
294             isa => 'Int',
295             init_arg => undef,
296             default => 10,
297             );
298              
299              
300             # --------------------------------------------------------------------------------------------------
301              
302             #pod =method mvp_multivalue_args
303             #pod
304             #pod The method tells C<Dist::Zilla> that C<prepend> is a multi-value option.
305             #pod
306             #pod =cut
307              
308             around mvp_multivalue_args => sub {
309             my ( $orig, $self ) = @_;
310             return ( $self->$orig(), qw{ prepend } );
311             };
312              
313             # --------------------------------------------------------------------------------------------------
314              
315             #pod =method tt_fill_in
316             #pod
317             #pod $file = Dist::Zilla::File::OnDisk( ... ); # or
318             #pod $file = Dist::Zilla::File::InMemory( ... ); # or
319             #pod $file = Dist::Zilla::File::FromCode( ... );
320             #pod
321             #pod $result = $self->fill_in_string( $file, \%variables, \%extra_args );
322             #pod $result = $self->fill_in_string( $file );
323             #pod
324             #pod Internal working horse of the role.
325             #pod
326             #pod The method creates C<Text::Template> object, enforces C<Text::Template> to respect C<filename>
327             #pod argument (see L<FILENAME parameter has no
328             #pod effect|https://rt.cpan.org/Ticket/Display.html?id=106093>), takes care about warnings, then calls
329             #pod C<fill_in> method on the object, making C<Text::Template> compilation errors (if found) more
330             #pod user-friendly.
331             #pod
332             #pod C<< $file->content >> is passed to the C<Text::Template> constructor. C<\%variables>,
333             #pod C<\%extra_args>, and C<package>, C<prepend>, C<broken> attributes are combined and passed to both
334             #pod C<Text::Template> constructor and C<fill_in> method.
335             #pod
336             #pod C<\%variables> become C<hash> C<Text::Template> option (see L<Text::Template/"HASH"> for details).
337             #pod Variables C<plugin> (reference to object executing the method, i. e. C<$self>) and C<dist>
338             #pod (reference to C<Dist::Zilla>, i. e. C<< $self->zilla >>) are added to C<\%variables> automatically,
339             #pod if they are not exist.
340             #pod
341             #pod C<package>, C<prepend>, C<broken> attributes become same-name C<Text::Template> options.
342             #pod C<\%extra_args> is expanded to list and passed last, so caller can override any option specified by
343             #pod C<tt_fill_in> (except C<filename>), for example:
344             #pod
345             #pod $self->tt_fill_in( $file, undef, { package => 'MY' } );
346             #pod
347             #pod will execute template code fragments in context of C<MY> package regardless of C<package>
348             #pod attribute. Another, a bit more complicated example:
349             #pod
350             #pod $self->tt_fill_in( $file, undef, { hash => { } } );
351             #pod
352             #pod processes template with no predefined variables: C<plugin> and C<dist> are added to C<\%variables>,
353             #pod but entire C<\%variables> is overridden by C<hash> extra argument.
354             #pod
355             #pod C<tt_fill_in> takes special care about package: by default nested C<tt_fill_in> calls use the same
356             #pod package as the outermost call. Of course, if C<package> extra argument is explicitly specified in
357             #pod inner call, it takes priority over default package.
358             #pod
359             #pod When defining variables with either C<\%variables> argument or C<hash> extra argument, remember that
360             #pod C<Text::Template> dereferences all the references. It especially important if you want to pass
361             #pod a reference to template:
362             #pod
363             #pod $array = [ … ]; $hash = { … };
364             #pod $self->tt_fill_in(
365             #pod $file,
366             #pod { array => \$array, hash => \$hash, plugin => \$self },
367             #pod );
368             #pod
369             #pod In template, C<$array> will be a reference to array, C<$hash> — reference to hash, C<$plugin> —
370             #pod reference to plugin. If you forget to take references, e. g.:
371             #pod
372             #pod $self->tt_fill_in(
373             #pod $file,
374             #pod { array => $array, hash => $hash, plugin => $self },
375             #pod );
376             #pod
377             #pod template will have C<@array> (array, not reference to array), C<%hash> (hash, not reference to
378             #pod hash), and C<$plugin> will be (oops!) undefined.
379             #pod
380             #pod Scalars can be passed either by reference or value:
381             #pod
382             #pod $self->tt_fill_in(
383             #pod $file,
384             #pod { str1 => "string", str2 => \"string" },
385             #pod );
386             #pod
387             #pod If C<$file> is mutable (i. e. does C<Dist::Zilla::Role::MutableFile> role), file content will be
388             #pod updated with result of template processing.
389             #pod
390             #pod See L<Text::Template/"HASH"> for more details.
391             #pod
392             #pod =cut
393              
394             sub tt_fill_in {
395 36     36 1 16475 my ( $self, $file, $hash, $args ) = @_;
396 36         239 $self->log_debug( [ 'processing %s', $file->name ] );
397 36 100       15779 my %hash = (
398             plugin => \( $self ),
399             dist => \( $self->zilla ),
400             $hash ? %$hash : (),
401             );
402             my %args = (
403             hash => \%hash,
404             delimiters => $self->delimiters,
405             ( package => $self->package ) x !! $self->package,
406             ( prepend => join( "\n", $self->prepend ) ) x !! $self->prepend,
407             broken => sub {
408 12     12   6802 my ( %args ) = @_; ## no critic ( ProhibitReusedNames )
409 12         94 return $args{ arg }->tt_broken( %args );
410             },
411 36 100       2205 broken_arg => $self,
412             $args ? %$args : (),
413             );
414 36         107 my ( $result, $errors ); {
415             # Original version of the code simply called `Text::Template::fill_in_string` function.
416             # However, this trivial approach does not work good because of `Text::Template` bug: it
417             # ignores `filename` argument, see <https://rt.cpan.org/Ticket/Display.html?id=106093>.
418             # It seems it will not be fixed soon. The bug can be workarounded by setting
419             # `Text::Template` object property `FILENAME`. In order to do it, we need access to
420             # `Text::Template` object, that means we have to create it manually, and then call
421             # `fill_in` method on it.
422 36         76 local $Text::Template::ERROR = undef;
  36         100  
423 36         281 my $tt = Text::Template->new( type => 'STRING', source => $file->content, %args );
424 36 50 33     9649 if ( defined( $tt ) and not defined( $Text::Template::ERROR ) ) {
425 36         154 my $package = $tt_param->( 'package', \%args );
426 36 100 66     813 if ( not defined( $package ) or $package eq '' ) {
427             # If package was not explicitly specified, create a private package.
428 29         350 $package = Dist::Zilla::Role::TextTemplater::_Package->new();
429             };
430             # Save package (either explicitly specified or auto-generated) in `package`
431             # attribute, to let recursive `fill_in_string` calls utilize the same package.
432 36         813 local $self->{ package } = "$package";
433 36         106 local $self->{ tt_file } = $file; # Will be used in `broken`.
434 36         119 local $self->{ tt_errors } = [];
435 36         121 local $self->{ tt_broken_count } = 0;
436 36         158 $tt->{ FILENAME } = $file->name; # Workaround for the bug.
437             {
438 36         2477 local $SIG{ __WARN__ } = sub { # TODO: Create an attribute?
439 4     4   440 my $msg = "$_[ 0 ]"; # Stringify message, it could be an object.
440 4         18 chomp( $msg );
441 4         25 $self->log( $msg );
442 36         387 };
443 36         206 $result = $tt->fill_in( %args, package => "$package" );
444             }
445             # `Text::Template` doc says:
446             # If the `BROKEN` function returns undef, `Text::Template` will immediately abort
447             # processing the template and return the text that it has accumulated so far.
448             # It seems it is not true, `fill_in` returns `undef`, not text accumulated so far.
449 36 100       16042 if ( defined( $Text::Template::ERROR ) ) {
450             # There are only few error message which can be generated by "Text::Template":
451             # Unmatched close brace at line $lineno
452             # End of data inside program text that began at line $prog_start
453             # Couldn't open file $fn: $!
454             # The latter cannot occur because we always fill in strings, never files.
455             # The problem is that these error messages does not include template name. Let us
456             # try to make them more user-friendly.
457 2         13 my $open = qr{\QEnd of data inside program text that began\E}x;
458 2         7 my $close = qr{\QUnmatched close brace\E}x;
459 2         79 my $known = qr{\A (?: ($open) | $close ) \s at \s line \s (\d+) \z }x;
460 2 50       27 if ( $Text::Template::ERROR =~ $known ) {
461 2         9 my ( $type, $line ) = ( $1, $2 );
462 2 100       10 my $msg = $type ? 'Unmatched opening delimiter' : 'Unmatched closing delimiter';
463             # ^ `Text::Template` error message "End of data inside program text that
464             # began at…" is too long at too complicated. Let us replace it with
465             # simpler one.
466 2         13 $Text::Template::ERROR =
467             sprintf( '%s at %s line %d.', $msg, $file->name, $line );
468 2         191 push( @{ $self->tt_errors }, $line => $Text::Template::ERROR );
  2         123  
469             };
470             };
471 36         2114 $errors = $self->tt_errors;
472             };
473 36 100       445 if ( defined( $Text::Template::ERROR ) ) {
474 2         20 $self->log_error( $Text::Template::ERROR );
475             };
476             };
477 36 100       1175 if ( @$errors ) {
478 11         67 $self->log_errors_in_file( $file, @$errors );
479             };
480 36         41681 $self->abort_if_error();
481 25 100       1771 if ( $file->does( 'Dist::Zilla::Role::MutableFile' ) ) {
482 24         4198 $file->content( $result );
483             };
484 25         23221 return $result;
485             };
486              
487             # --------------------------------------------------------------------------------------------------
488              
489             #pod =method fill_in_string
490             #pod
491             #pod $template = '…';
492             #pod $result = $self->fill_in_string( $template, \%variables, \%extra_args );
493             #pod $result = $self->fill_in_string( $template );
494             #pod
495             #pod The primary method of the role.
496             #pod
497             #pod The C<fill_in_string> interface is compatible with the same-name method of C<TextTemplate> role, so
498             #pod this role can be used as a drop-in replacement for C<TextTemplate>. However, method is
499             #pod implemented slightly differently, it may cause subtle differences in behaviour.
500             #pod
501             #pod The method creates temporary C<Dist::Zilla::File::InMemory> object with name C<"template"> (it can
502             #pod be overridden by C<filename> extra argument, though) and calls C<tt_fill_in> method, passing down
503             #pod temporary file, C<\%variables> and C<\%extra_args>.
504             #pod
505             #pod =cut
506              
507             sub fill_in_string {
508 29     29 1 13785 my ( $self, $string, $hash, $args ) = @_;
509 29   100     167 return $self->tt_fill_in(
510             Dist::Zilla::File::InMemory->new(
511             name => $tt_param->( 'filename', $args ) || 'template',
512             content => $string,
513             ),
514             $hash,
515             $args,
516             );
517             };
518              
519             # --------------------------------------------------------------------------------------------------
520              
521             #pod =method fill_in_file
522             #pod
523             #pod $file = Dist::Zilla::File::OnDisk->new( { … } ); # or
524             #pod $file = Dist::Zilla::File::InMemory->new( { … } ); # or
525             #pod $file = Dist::Zilla::File::FromCode->new( { … } ); # or
526             #pod $file = Path::Tiny->new( 'filename' ); # or
527             #pod $file = Path::Class::File->new( 'filename' ); # or
528             #pod $file = 'filename.ext';
529             #pod
530             #pod $result = $self->fill_in_file( $file, \%variables, \%extra_args );
531             #pod $result = $self->fill_in_file( $file );
532             #pod
533             #pod Similar to C<fill_in_string>, but the first argument is not a template but a file object or file
534             #pod name to read template from. File can be any of C<Dist::Zilla> file types (file is read with
535             #pod C<content> method) or C<Path::Tiny> file (file is read with C<slurp_utf8> method), or
536             #pod C<Path::Class::File> (read by C<< slurp( iomode => '<:encoding(UTF-8)' ) >>) or just a file name
537             #pod (temporary C<Dist::Zilla::File::OnDisk> object is created internally).
538             #pod
539             #pod Note that C<filename> extra argument is ignored, file name cannot be overridden.
540             #pod
541             #pod The method returns result of template processing. If the file is mutable (i. e. does
542             #pod C<Dist::Zilla::Role::MutableFile>) file content is also updated.
543             #pod
544             #pod B<Note:> C<Dist::Zilla::Role::MutableFile> introduced in C<Dist::Zilla> version 5.000. In earlier
545             #pod versions there is no C<Dist::Zilla::Role::MutableFile> role and so, file content is never updated.
546             #pod
547             #pod =cut
548              
549             sub fill_in_file {
550 7     7 1 15430 my ( $self, $file, $hash, $args ) = @_;
551 7         45 my $class = blessed( $file );
552 7 100       40 if ( $class ) {
553 6 100 66     179 if ( $file->isa( 'Moose::Object' ) and $file->does( 'Dist::Zilla::Role::File' ) ) {
    100          
    50          
554             # Do noting.
555             } elsif ( $file->isa( 'Path::Tiny' ) ) {
556 1         8 $file = Dist::Zilla::File::InMemory->new(
557             name => "$file",
558             content => $file->slurp_utf8(),
559             );
560             } elsif ( $file->isa( 'Path::Class::File' ) ) {
561 1         5 $file = Dist::Zilla::File::InMemory->new(
562             name => "$file",
563             content => $file->slurp( iomode => '<:encoding(UTF-8)' ),
564             );
565             } else {
566 0         0 croak "fill_in_file: unsupported file class: $class";
567             };
568             } else {
569 1         47 $file = Dist::Zilla::File::OnDisk->new(
570             name => "$file",
571             );
572             };
573 7         2339 return $self->tt_fill_in( $file, $hash, $args );
574             };
575              
576             # --------------------------------------------------------------------------------------------------
577              
578             # Helper class to create private packages. Actual creation and deletion is implemented in
579             # `Text::Template`, this class just adds automatical package deletion.
580              
581             {
582             ## no critic ( ProhibitMultiplePackages )
583             package Dist::Zilla::Role::TextTemplater::_Package;
584              
585 1     1   10 use strict;
  1         4  
  1         38  
586 1     1   6 use warnings;
  1         2  
  1         111  
587              
588             use overload '""' => sub {
589 58     58   87 my ( $self ) = @_;
590 58         398 return $self->{ name };
591 1     1   7 };
  1         2  
  1         19  
592              
593             sub new {
594 29     29   86 my ( $class ) = @_;
595 29         153 my $self = {
596             name => Text::Template::_gensym(), ## no critic ( ProtectPrivateSubs )
597             };
598 29         330 return bless( $self, $class );
599             };
600              
601             sub DESTROY {
602 29     29   52 my ( $self ) = @_;
603 29         147 Text::Template::_scrubpkg( $self->{ name } ); ## no critic ( ProtectPrivateSubs )
604 29         817 return;
605             };
606              
607             }
608              
609             # --------------------------------------------------------------------------------------------------
610              
611             1;
612              
613             # --------------------------------------------------------------------------------------------------
614              
615             #pod =note C<Text::Template> option spelling
616             #pod
617             #pod C<Text::Template> allows a programmer to use different spelling of options: all-caps, first-caps,
618             #pod all-lowercase, with and without leading dash, e. g.: C<HASH>, C<Hash>, C<hash>, C<-HASH>, C<-Hash>,
619             #pod C<-hash>. This is documented feature.
620             #pod
621             #pod C<Text::Template> recommends to pick a style and stick with it. (BTW, C<Text::Template>
622             #pod documentation uses all-caps spelling.) This role picked all-lowercase style. This choice have
623             #pod subtle consequences. Let us consider an example:
624             #pod
625             #pod $self->fill_in_string( $template, undef, { PACKAGE => 'MY' } );
626             #pod
627             #pod Extra option C<PACKAGE> may or may not have effect, depending on value of C<package> attribute (i.
628             #pod e. presence or absence C<package> option in F<dist.ini> file), because (this is not documented)
629             #pod spellings are not equal: different spellings have different priority. If C<PACKAGE> and C<package>
630             #pod are specified simultaneously, C<package> wins, C<PACKAGE> loses.
631             #pod
632             #pod This feature gives you a choice. If you want to ignore option specified by the user in F<dist.ini>
633             #pod and provide your value, use all-lowercase option name. If you want to provide default which can be
634             #pod overridden by the user, use all-caps options name.
635             #pod
636             #pod =cut
637              
638             # --------------------------------------------------------------------------------------------------
639              
640             #pod =note C<filename> option
641             #pod
642             #pod When C<Text::Template> reads template from a file, it uses the actual file name in error messages,
643             #pod e. g.:
644             #pod
645             #pod Undefined subroutine &foo called at dir/filename.ext line n
646             #pod
647             #pod where I<dir/filename.ext> is the name of file containing the template. When C<Text::Template>
648             #pod processes a string, it uses word "template" instead of file name, e. g.:
649             #pod
650             #pod Undefined subroutine &foo called at template line n
651             #pod
652             #pod The option C<filename> allows the caller to override it:
653             #pod
654             #pod $self->fill_in_file( $file, undef, { filename => 'Assa.txt' } );
655             #pod
656             #pod Error message would look like:
657             #pod
658             #pod Undefined subroutine &foo called at Assa.txt line n
659             #pod
660             #pod It may seem this does not make much sense, but in our case (C<Dist::Zilla> and its plugins)
661             #pod C<Text::Template> always processes strings and never reads files, because reading files is a duty
662             #pod of C<Dist::Zilla::File::OnDisk> class. Thus, using C<filename> option is critical to provide good
663             #pod error messages. Actually, C<fill_in_file> implementation looks like
664             #pod
665             #pod $self->fill_in_string(
666             #pod $file->content,
667             #pod undef,
668             #pod { filename => $file->name },
669             #pod );
670             #pod
671             #pod There are two problems with the option, though:
672             #pod
673             #pod =over
674             #pod
675             #pod =item *
676             #pod
677             #pod C<Text::Template> does not document this option.
678             #pod
679             #pod I believe it is a mistake and option should be documented.
680             #pod
681             #pod =item *
682             #pod
683             #pod C<Text::Template> ignores this option.
684             #pod
685             #pod I am sure this is a bug and hope it will be fixed eventually. I am afraid it will not be fixed
686             #pod soon, though.
687             #pod
688             #pod Meanwhile, C<TextTemplater> implements a workaround to let the option work, so C<TextTemplater>
689             #pod consumers can utilize the C<filename> option.
690             #pod
691             #pod =back
692             #pod
693             #pod =cut
694              
695             # --------------------------------------------------------------------------------------------------
696              
697             #pod =head1 SEE ALSO
698             #pod
699             #pod =for :list
700             #pod = L<Dist::Zilla>
701             #pod = L<Dist::Zilla::Role>
702             #pod = L<Dist::Zilla::Plugin>
703             #pod = L<Dist::Zilla::Role::TextTemplate>
704             #pod = L<Text::Template>
705             #pod
706             #pod =head1 COPYRIGHT AND LICENSE
707             #pod
708             #pod Copyright (C) 2015, 2016 Van de Bugger
709             #pod
710             #pod License GPLv3+: The GNU General Public License version 3 or later
711             #pod <http://www.gnu.org/licenses/gpl-3.0.txt>.
712             #pod
713             #pod This is free software: you are free to change and redistribute it. There is
714             #pod NO WARRANTY, to the extent permitted by law.
715             #pod
716             #pod
717             #pod =cut
718              
719             # doc/what.pod #
720              
721             #pod =encoding UTF-8
722             #pod
723             #pod =head1 WHAT?
724             #pod
725             #pod C<Dist-Zilla-Role-TextTemplater> is a C<Dist::Zilla> role, a replacement for standard role C<TextTemplate>. Both
726             #pod roles have the same great C<Text::Template> engine under the hood, but this one provides better
727             #pod control over the engine and much better error reporting.
728             #pod
729             #pod =cut
730              
731             # end of file #
732             # doc/why.pod #
733              
734             #pod =encoding UTF-8
735             #pod
736             #pod =head1 WHY?
737             #pod
738             #pod C<TextTemplate> role from C<Dist::Zilla> distribution v5.037 has the same great C<Text::Template>
739             #pod engine under the hood, but lacks of control and has I<awful> error reporting.
740             #pod
741             #pod =head2 Error Reporting
742             #pod
743             #pod Let us consider an example. For sake of example simplicity, it contains only one file, F<dist.ini>.
744             #pod Two files, F<lib/Assa.pm> and F<lib/Assa.pod>, are generated on-the-fly with C<GenerateFile>
745             #pod plugin.
746             #pod
747             #pod Have a look at F<dist.ini>:
748             #pod
749             #pod name = Assa
750             #pod version = 0.001
751             #pod abstract = Example
752             #pod [GenerateFile/lib/Assa.pm]
753             #pod filename = lib/Assa.pm
754             #pod content = package Assa; 1;
755             #pod [GenerateFile/lib/Assa/Manual.pod]
756             #pod filename = lib/Assa/Manual.pod
757             #pod content = =head1 NAME
758             #pod content =
759             #pod content = {{$dst->name} - {{$dist->abstract}}
760             #pod content =
761             #pod content = Version {{$dist->version}}.
762             #pod content =
763             #pod content = {{$dist->license->notice}}
764             #pod [TemplateFiles]
765             #pod filename = lib/Assa.pm
766             #pod filename = lib/Assa/Manual.pod
767             #pod [MetaResources::Template]
768             #pod homepage = https://example.org/release/{{$dist->name}}
769             #pod license = {{$dist->license->url}}
770             #pod
771             #pod
772             #pod (Do you see a typo? How many? Note this is a small example, real files are much larger.) Now let us
773             #pod build the distribution:
774             #pod
775             #pod $ dzil build
776             #pod [DZ] beginning to build Assa
777             #pod [TemplateFiles] Filling in the template returned undef for:
778             #pod [TemplateFiles] =head1 NAME
779             #pod [TemplateFiles]
780             #pod [TemplateFiles] {{$dst->name} - {{$dist->abstract}}
781             #pod [TemplateFiles]
782             #pod [TemplateFiles] Version {{$dist->version}}.
783             #pod [TemplateFiles]
784             #pod [TemplateFiles] {{$dist->license->notice}}
785             #pod
786             #pod [TemplateFiles] Filling in the template returned undef for:
787             #pod [TemplateFiles] =head1 NAME
788             #pod [TemplateFiles]
789             #pod [TemplateFiles] {{$dst->name} - {{$dist->abstract}}
790             #pod [TemplateFiles]
791             #pod [TemplateFiles] Version {{$dist->version}}.
792             #pod [TemplateFiles]
793             #pod [TemplateFiles] {{$dist->license->notice}}
794             #pod at /home/vdb/.usr/opt/local-lib/lib/perl5/x86_64-linux-thread-multi/Moose/Meta/Method/Delegation.pm line 110.
795             #pod
796             #pod
797             #pod Oops. What's happened? Where? Why? All we have is a highly unclear error message
798             #pod
799             #pod Filling in the template returned undef for:
800             #pod
801             #pod and file content printed twice. (Yep, if the file had 1000 lines, we would have it printed twice
802             #pod too.) We do not ever have a file name and have to guess it by the content. Good bug hunting, dude.
803             #pod
804             #pod Ok, let us fix the problem (mistyped closing delimiter in the first line of file
805             #pod F<lib/Assa/Manual.pod>) and build the distribution again:
806             #pod
807             #pod $ dzil build
808             #pod [DZ] beginning to build Assa
809             #pod Can't call method "name" on an undefined value at template line 3.
810             #pod
811             #pod
812             #pod Oops. Error message much is better now, but where the problem is? There are many templates in the
813             #pod project: F<lib/Assa.pm>, F<lib/Assa/Manual.pod>, and even resources in F<META.yml> — all are
814             #pod generated from templates. Where is the problem? Good bug hunting for us all.
815             #pod
816             #pod Such error reporting is simply unacceptable. I am a human, I often make mistakes, and I want the
817             #pod tool clearly warns me I<what> and I<where> the problem is, so I can fix it quickly. For example,
818             #pod in the first case I want to see:
819             #pod
820             #pod $ dzil build
821             #pod [DZ] beginning to build Assa
822             #pod [Templates] Unmatched opening delimiter at lib/Assa/Manual.pod line 3.
823             #pod [Templates] lib/Assa/Manual.pod:
824             #pod [Templates] 1: =head1 NAME
825             #pod [Templates] 2:
826             #pod [Templates] 3: {{$dst->name} - {{$dist->abstract}}
827             #pod [Templates] ^^^ Unmatched opening delimiter at lib/Assa/Manual.pod line 3. ^^^
828             #pod [Templates] 4:
829             #pod [Templates] 5: Version {{$dist->version}}.
830             #pod [Templates] ... skipped 2 lines ...
831             #pod Aborting...
832             #pod
833             #pod
834             #pod In the second case:
835             #pod
836             #pod $ dzil build
837             #pod [DZ] beginning to build Assa
838             #pod [Templates] Can't call method "name" on an undefined value at lib/Assa/Manual.pod line 3.
839             #pod [Templates] Bad code fragment begins at lib/Assa/Manual.pod line 3.
840             #pod [Templates] lib/Assa/Manual.pod:
841             #pod [Templates] 1: =head1 NAME
842             #pod [Templates] 2:
843             #pod [Templates] 3: {{$dst->name}} - {{$dist->abstract}}
844             #pod [Templates] ^^^ Can't call method "name" on an undefined value at lib/Assa/Manual.pod line 3. ^^^
845             #pod [Templates] ^^^ Bad code fragment begins at lib/Assa/Manual.pod line 3. ^^^
846             #pod [Templates] 4:
847             #pod [Templates] 5: Version {{$dist->version}}.
848             #pod [Templates] ... skipped 2 lines ...
849             #pod Aborting...
850             #pod
851             #pod
852             #pod C<TextTemplater> makes it real. All I need is using C<TextTemplater>-based plugins: C<Templates>,
853             #pod C<MetaResources::Template> (starting from v0.002).
854             #pod
855             #pod =head2 Engine Control
856             #pod
857             #pod C<TextTemplater> allows the end-user to specify C<delimiters>, C<package> and C<prepend> engine
858             #pod options in F<dist.ini> file, while C<TextTemplate> allows to specify C<prepend> only
859             #pod programmatically, and does I<not> allow to specify C<delimiters> and C<package>.
860             #pod
861             #pod =cut
862              
863             # end of file #
864              
865              
866             # end of file #
867              
868             __END__
869              
870             =pod
871              
872             =encoding UTF-8
873              
874             =head1 NAME
875              
876             Dist::Zilla::Role::TextTemplater - Have text templating capabilities in your Dist::Zilla plugin
877              
878             =head1 VERSION
879              
880             Version v0.8.5_02, released on 2016-11-08 23:14 UTC.
881             This is a B<trial release>.
882              
883             =head1 WHAT?
884              
885             C<Dist-Zilla-Role-TextTemplater> is a C<Dist::Zilla> role, a replacement for standard role C<TextTemplate>. Both
886             roles have the same great C<Text::Template> engine under the hood, but this one provides better
887             control over the engine and much better error reporting.
888              
889             This is C<Dist::Zilla::Role::TextTemplater> module documentation. Read this if you want to
890             have text templating capabilities in your Dist::Zilla plugin.
891              
892             If you are using a C<TextTemplater>-based plugin, read the
893             L<manual|Dist::Zilla::Role::TextTemplater::Manual>. General topics like getting source, building, installing, bug
894             reporting and some others are covered in the F<README>.
895              
896             =for test_synopsis my ( $result, $template, $file );
897              
898             =head1 SYNOPSIS
899              
900             package Dist::Zilla::Plugin::YourPlugin;
901             use Moose;
902             use namespace::autoclean;
903             with 'Dist::Zilla::Role::Plugin';
904             with 'Dist::Zilla::Role::TextTemplater';
905              
906             sub method {
907             my $self = shift( @_ );
908             ...;
909             $result = $self->fill_in_string( $template );
910             ...;
911             };
912              
913             sub another_method {
914             my $self = shift( @_ );
915             ...;
916             $self->fill_in_file( $file );
917             ...;
918             };
919              
920             __PACKAGE__->meta->make_immutable;
921             1;
922              
923             =head1 DESCRIPTION
924              
925             The role provides a consuming plugin with C<fill_in_string> and C<fill_in_file> methods and bunch
926             of accompanying attributes and F<dist.ini> options.
927              
928             =head1 OBJECT ATTRIBUTES
929              
930             =head2 delimiters
931              
932             Pair of opening delimiter and closing delimiter to denote code fragments in template.
933              
934             Attribute introduces F<dist.ini> option with the same name. Option value will be split on
935             whitespaces (result should be two items) to initialize the attribute.
936              
937             C<Str|ArrayRef[Str]>, read-only. Default value is C<[ '{{', '}}' ]>.
938              
939             See L<Dist::Zilla::Role::TextTemplater/"Delimiters">.
940              
941             =head2 package
942              
943             Name of package to evaluate code fragments in.
944              
945             Attribute introduces F<dist.ini> option with the same name.
946              
947             C<Str>, read-only, optional.
948              
949             See L<Dist::Zilla::Role::TextTemplater/"Package">.
950              
951             =head2 prepend
952              
953             Perl code to prepend to the beginning of every code fragment.
954              
955             Attribute introduces F<dist.ini> multi-value option with the same name.
956              
957             C<ArrayRef[Str]>, read-only, auto dereferenced. Default value is empty array. Consumers may specify
958             alternative default by defining C<_build_prepend> method.
959              
960             See L<Dist::Zilla::Role::TextTemplater/"Prepend">.
961              
962             =head2 tt_file
963              
964             File being processed (either actual file or temporary C<InMemory> file when processing a string).
965             Available only during template processing. May be used in C<tt_broken> method.
966              
967             C<Object>, read-only, not an init arg.
968              
969             =head2 tt_errors
970              
971             Errors detected in template file, in format suitable for C<log_errors_in_file> (defined in
972             C<ErrorLogger> role). May be used in C<tt_broken> method.
973              
974             C<ArrayRef>, read-write, not an init arg.
975              
976             =head2 tt_broken_count
977              
978             Number of C<tt_broken> calls. The counter is increased before C<tt_broken> call.
979              
980             C<Int>, read-only, not an init arg.
981              
982             =head2 tt_broken_limit
983              
984             If number of completed C<tt_broken> calls equals or exceeds this limit, processing stops.
985              
986             C<Int>, read-only, not an init arg, default value 10.
987              
988             There is no (official) way to change the attribute value now. Let me know if you need it.
989              
990             =head1 OBJECT METHODS
991              
992             =head2 tt_broken
993              
994             This method is called if a code fragment dies. It formats error message(s) and sends it to the log
995             by calling C<log_error>.
996              
997             See C<BROKEN> option of L<Text::Template/"fill_in">.
998              
999             =head2 mvp_multivalue_args
1000              
1001             The method tells C<Dist::Zilla> that C<prepend> is a multi-value option.
1002              
1003             =head2 tt_fill_in
1004              
1005             $file = Dist::Zilla::File::OnDisk( ... ); # or
1006             $file = Dist::Zilla::File::InMemory( ... ); # or
1007             $file = Dist::Zilla::File::FromCode( ... );
1008              
1009             $result = $self->fill_in_string( $file, \%variables, \%extra_args );
1010             $result = $self->fill_in_string( $file );
1011              
1012             Internal working horse of the role.
1013              
1014             The method creates C<Text::Template> object, enforces C<Text::Template> to respect C<filename>
1015             argument (see L<FILENAME parameter has no
1016             effect|https://rt.cpan.org/Ticket/Display.html?id=106093>), takes care about warnings, then calls
1017             C<fill_in> method on the object, making C<Text::Template> compilation errors (if found) more
1018             user-friendly.
1019              
1020             C<< $file->content >> is passed to the C<Text::Template> constructor. C<\%variables>,
1021             C<\%extra_args>, and C<package>, C<prepend>, C<broken> attributes are combined and passed to both
1022             C<Text::Template> constructor and C<fill_in> method.
1023              
1024             C<\%variables> become C<hash> C<Text::Template> option (see L<Text::Template/"HASH"> for details).
1025             Variables C<plugin> (reference to object executing the method, i. e. C<$self>) and C<dist>
1026             (reference to C<Dist::Zilla>, i. e. C<< $self->zilla >>) are added to C<\%variables> automatically,
1027             if they are not exist.
1028              
1029             C<package>, C<prepend>, C<broken> attributes become same-name C<Text::Template> options.
1030             C<\%extra_args> is expanded to list and passed last, so caller can override any option specified by
1031             C<tt_fill_in> (except C<filename>), for example:
1032              
1033             $self->tt_fill_in( $file, undef, { package => 'MY' } );
1034              
1035             will execute template code fragments in context of C<MY> package regardless of C<package>
1036             attribute. Another, a bit more complicated example:
1037              
1038             $self->tt_fill_in( $file, undef, { hash => { } } );
1039              
1040             processes template with no predefined variables: C<plugin> and C<dist> are added to C<\%variables>,
1041             but entire C<\%variables> is overridden by C<hash> extra argument.
1042              
1043             C<tt_fill_in> takes special care about package: by default nested C<tt_fill_in> calls use the same
1044             package as the outermost call. Of course, if C<package> extra argument is explicitly specified in
1045             inner call, it takes priority over default package.
1046              
1047             When defining variables with either C<\%variables> argument or C<hash> extra argument, remember that
1048             C<Text::Template> dereferences all the references. It especially important if you want to pass
1049             a reference to template:
1050              
1051             $array = [ … ]; $hash = { … };
1052             $self->tt_fill_in(
1053             $file,
1054             { array => \$array, hash => \$hash, plugin => \$self },
1055             );
1056              
1057             In template, C<$array> will be a reference to array, C<$hash> — reference to hash, C<$plugin> —
1058             reference to plugin. If you forget to take references, e. g.:
1059              
1060             $self->tt_fill_in(
1061             $file,
1062             { array => $array, hash => $hash, plugin => $self },
1063             );
1064              
1065             template will have C<@array> (array, not reference to array), C<%hash> (hash, not reference to
1066             hash), and C<$plugin> will be (oops!) undefined.
1067              
1068             Scalars can be passed either by reference or value:
1069              
1070             $self->tt_fill_in(
1071             $file,
1072             { str1 => "string", str2 => \"string" },
1073             );
1074              
1075             If C<$file> is mutable (i. e. does C<Dist::Zilla::Role::MutableFile> role), file content will be
1076             updated with result of template processing.
1077              
1078             See L<Text::Template/"HASH"> for more details.
1079              
1080             =head2 fill_in_string
1081              
1082             $template = '…';
1083             $result = $self->fill_in_string( $template, \%variables, \%extra_args );
1084             $result = $self->fill_in_string( $template );
1085              
1086             The primary method of the role.
1087              
1088             The C<fill_in_string> interface is compatible with the same-name method of C<TextTemplate> role, so
1089             this role can be used as a drop-in replacement for C<TextTemplate>. However, method is
1090             implemented slightly differently, it may cause subtle differences in behaviour.
1091              
1092             The method creates temporary C<Dist::Zilla::File::InMemory> object with name C<"template"> (it can
1093             be overridden by C<filename> extra argument, though) and calls C<tt_fill_in> method, passing down
1094             temporary file, C<\%variables> and C<\%extra_args>.
1095              
1096             =head2 fill_in_file
1097              
1098             $file = Dist::Zilla::File::OnDisk->new( { … } ); # or
1099             $file = Dist::Zilla::File::InMemory->new( { … } ); # or
1100             $file = Dist::Zilla::File::FromCode->new( { … } ); # or
1101             $file = Path::Tiny->new( 'filename' ); # or
1102             $file = Path::Class::File->new( 'filename' ); # or
1103             $file = 'filename.ext';
1104              
1105             $result = $self->fill_in_file( $file, \%variables, \%extra_args );
1106             $result = $self->fill_in_file( $file );
1107              
1108             Similar to C<fill_in_string>, but the first argument is not a template but a file object or file
1109             name to read template from. File can be any of C<Dist::Zilla> file types (file is read with
1110             C<content> method) or C<Path::Tiny> file (file is read with C<slurp_utf8> method), or
1111             C<Path::Class::File> (read by C<< slurp( iomode => '<:encoding(UTF-8)' ) >>) or just a file name
1112             (temporary C<Dist::Zilla::File::OnDisk> object is created internally).
1113              
1114             Note that C<filename> extra argument is ignored, file name cannot be overridden.
1115              
1116             The method returns result of template processing. If the file is mutable (i. e. does
1117             C<Dist::Zilla::Role::MutableFile>) file content is also updated.
1118              
1119             B<Note:> C<Dist::Zilla::Role::MutableFile> introduced in C<Dist::Zilla> version 5.000. In earlier
1120             versions there is no C<Dist::Zilla::Role::MutableFile> role and so, file content is never updated.
1121              
1122             =head1 NOTES
1123              
1124             =head2 C<Text::Template> option spelling
1125              
1126             C<Text::Template> allows a programmer to use different spelling of options: all-caps, first-caps,
1127             all-lowercase, with and without leading dash, e. g.: C<HASH>, C<Hash>, C<hash>, C<-HASH>, C<-Hash>,
1128             C<-hash>. This is documented feature.
1129              
1130             C<Text::Template> recommends to pick a style and stick with it. (BTW, C<Text::Template>
1131             documentation uses all-caps spelling.) This role picked all-lowercase style. This choice have
1132             subtle consequences. Let us consider an example:
1133              
1134             $self->fill_in_string( $template, undef, { PACKAGE => 'MY' } );
1135              
1136             Extra option C<PACKAGE> may or may not have effect, depending on value of C<package> attribute (i.
1137             e. presence or absence C<package> option in F<dist.ini> file), because (this is not documented)
1138             spellings are not equal: different spellings have different priority. If C<PACKAGE> and C<package>
1139             are specified simultaneously, C<package> wins, C<PACKAGE> loses.
1140              
1141             This feature gives you a choice. If you want to ignore option specified by the user in F<dist.ini>
1142             and provide your value, use all-lowercase option name. If you want to provide default which can be
1143             overridden by the user, use all-caps options name.
1144              
1145             =head2 C<filename> option
1146              
1147             When C<Text::Template> reads template from a file, it uses the actual file name in error messages,
1148             e. g.:
1149              
1150             Undefined subroutine &foo called at dir/filename.ext line n
1151              
1152             where I<dir/filename.ext> is the name of file containing the template. When C<Text::Template>
1153             processes a string, it uses word "template" instead of file name, e. g.:
1154              
1155             Undefined subroutine &foo called at template line n
1156              
1157             The option C<filename> allows the caller to override it:
1158              
1159             $self->fill_in_file( $file, undef, { filename => 'Assa.txt' } );
1160              
1161             Error message would look like:
1162              
1163             Undefined subroutine &foo called at Assa.txt line n
1164              
1165             It may seem this does not make much sense, but in our case (C<Dist::Zilla> and its plugins)
1166             C<Text::Template> always processes strings and never reads files, because reading files is a duty
1167             of C<Dist::Zilla::File::OnDisk> class. Thus, using C<filename> option is critical to provide good
1168             error messages. Actually, C<fill_in_file> implementation looks like
1169              
1170             $self->fill_in_string(
1171             $file->content,
1172             undef,
1173             { filename => $file->name },
1174             );
1175              
1176             There are two problems with the option, though:
1177              
1178             =over
1179              
1180             =item *
1181              
1182             C<Text::Template> does not document this option.
1183              
1184             I believe it is a mistake and option should be documented.
1185              
1186             =item *
1187              
1188             C<Text::Template> ignores this option.
1189              
1190             I am sure this is a bug and hope it will be fixed eventually. I am afraid it will not be fixed
1191             soon, though.
1192              
1193             Meanwhile, C<TextTemplater> implements a workaround to let the option work, so C<TextTemplater>
1194             consumers can utilize the C<filename> option.
1195              
1196             =back
1197              
1198             =head1 WHY?
1199              
1200             C<TextTemplate> role from C<Dist::Zilla> distribution v5.037 has the same great C<Text::Template>
1201             engine under the hood, but lacks of control and has I<awful> error reporting.
1202              
1203             =head2 Error Reporting
1204              
1205             Let us consider an example. For sake of example simplicity, it contains only one file, F<dist.ini>.
1206             Two files, F<lib/Assa.pm> and F<lib/Assa.pod>, are generated on-the-fly with C<GenerateFile>
1207             plugin.
1208              
1209             Have a look at F<dist.ini>:
1210              
1211             name = Assa
1212             version = 0.001
1213             abstract = Example
1214             [GenerateFile/lib/Assa.pm]
1215             filename = lib/Assa.pm
1216             content = package Assa; 1;
1217             [GenerateFile/lib/Assa/Manual.pod]
1218             filename = lib/Assa/Manual.pod
1219             content = =head1 NAME
1220             content =
1221             content = {{$dst->name} - {{$dist->abstract}}
1222             content =
1223             content = Version {{$dist->version}}.
1224             content =
1225             content = {{$dist->license->notice}}
1226             [TemplateFiles]
1227             filename = lib/Assa.pm
1228             filename = lib/Assa/Manual.pod
1229             [MetaResources::Template]
1230             homepage = https://example.org/release/{{$dist->name}}
1231             license = {{$dist->license->url}}
1232              
1233             (Do you see a typo? How many? Note this is a small example, real files are much larger.) Now let us
1234             build the distribution:
1235              
1236             $ dzil build
1237             [DZ] beginning to build Assa
1238             [TemplateFiles] Filling in the template returned undef for:
1239             [TemplateFiles] =head1 NAME
1240             [TemplateFiles]
1241             [TemplateFiles] {{$dst->name} - {{$dist->abstract}}
1242             [TemplateFiles]
1243             [TemplateFiles] Version {{$dist->version}}.
1244             [TemplateFiles]
1245             [TemplateFiles] {{$dist->license->notice}}
1246              
1247             [TemplateFiles] Filling in the template returned undef for:
1248             [TemplateFiles] =head1 NAME
1249             [TemplateFiles]
1250             [TemplateFiles] {{$dst->name} - {{$dist->abstract}}
1251             [TemplateFiles]
1252             [TemplateFiles] Version {{$dist->version}}.
1253             [TemplateFiles]
1254             [TemplateFiles] {{$dist->license->notice}}
1255             at /home/vdb/.usr/opt/local-lib/lib/perl5/x86_64-linux-thread-multi/Moose/Meta/Method/Delegation.pm line 110.
1256              
1257             Oops. What's happened? Where? Why? All we have is a highly unclear error message
1258              
1259             Filling in the template returned undef for:
1260              
1261             and file content printed twice. (Yep, if the file had 1000 lines, we would have it printed twice
1262             too.) We do not ever have a file name and have to guess it by the content. Good bug hunting, dude.
1263              
1264             Ok, let us fix the problem (mistyped closing delimiter in the first line of file
1265             F<lib/Assa/Manual.pod>) and build the distribution again:
1266              
1267             $ dzil build
1268             [DZ] beginning to build Assa
1269             Can't call method "name" on an undefined value at template line 3.
1270              
1271             Oops. Error message much is better now, but where the problem is? There are many templates in the
1272             project: F<lib/Assa.pm>, F<lib/Assa/Manual.pod>, and even resources in F<META.yml> — all are
1273             generated from templates. Where is the problem? Good bug hunting for us all.
1274              
1275             Such error reporting is simply unacceptable. I am a human, I often make mistakes, and I want the
1276             tool clearly warns me I<what> and I<where> the problem is, so I can fix it quickly. For example,
1277             in the first case I want to see:
1278              
1279             $ dzil build
1280             [DZ] beginning to build Assa
1281             [Templates] Unmatched opening delimiter at lib/Assa/Manual.pod line 3.
1282             [Templates] lib/Assa/Manual.pod:
1283             [Templates] 1: =head1 NAME
1284             [Templates] 2:
1285             [Templates] 3: {{$dst->name} - {{$dist->abstract}}
1286             [Templates] ^^^ Unmatched opening delimiter at lib/Assa/Manual.pod line 3. ^^^
1287             [Templates] 4:
1288             [Templates] 5: Version {{$dist->version}}.
1289             [Templates] ... skipped 2 lines ...
1290             Aborting...
1291              
1292             In the second case:
1293              
1294             $ dzil build
1295             [DZ] beginning to build Assa
1296             [Templates] Can't call method "name" on an undefined value at lib/Assa/Manual.pod line 3.
1297             [Templates] Bad code fragment begins at lib/Assa/Manual.pod line 3.
1298             [Templates] lib/Assa/Manual.pod:
1299             [Templates] 1: =head1 NAME
1300             [Templates] 2:
1301             [Templates] 3: {{$dst->name}} - {{$dist->abstract}}
1302             [Templates] ^^^ Can't call method "name" on an undefined value at lib/Assa/Manual.pod line 3. ^^^
1303             [Templates] ^^^ Bad code fragment begins at lib/Assa/Manual.pod line 3. ^^^
1304             [Templates] 4:
1305             [Templates] 5: Version {{$dist->version}}.
1306             [Templates] ... skipped 2 lines ...
1307             Aborting...
1308              
1309             C<TextTemplater> makes it real. All I need is using C<TextTemplater>-based plugins: C<Templates>,
1310             C<MetaResources::Template> (starting from v0.002).
1311              
1312             =head2 Engine Control
1313              
1314             C<TextTemplater> allows the end-user to specify C<delimiters>, C<package> and C<prepend> engine
1315             options in F<dist.ini> file, while C<TextTemplate> allows to specify C<prepend> only
1316             programmatically, and does I<not> allow to specify C<delimiters> and C<package>.
1317              
1318             =head1 SEE ALSO
1319              
1320             =over 4
1321              
1322             =item L<Dist::Zilla>
1323              
1324             =item L<Dist::Zilla::Role>
1325              
1326             =item L<Dist::Zilla::Plugin>
1327              
1328             =item L<Dist::Zilla::Role::TextTemplate>
1329              
1330             =item L<Text::Template>
1331              
1332             =back
1333              
1334             =head1 AUTHOR
1335              
1336             Van de Bugger <van.de.bugger@gmail.com>
1337              
1338             =head1 COPYRIGHT AND LICENSE
1339              
1340             Copyright (C) 2015, 2016 Van de Bugger
1341              
1342             License GPLv3+: The GNU General Public License version 3 or later
1343             <http://www.gnu.org/licenses/gpl-3.0.txt>.
1344              
1345             This is free software: you are free to change and redistribute it. There is
1346             NO WARRANTY, to the extent permitted by law.
1347              
1348             =cut