File Coverage

blib/lib/Dist/Zilla/Plugin/Templates/File.pm
Criterion Covered Total %
statement 70 74 94.5
branch 8 10 80.0
condition 3 3 100.0
subroutine 15 15 100.0
pod 6 6 100.0
total 102 108 94.4


line stmt bran cond sub pod time code
1             # ---------------------------------------------------------------------- copyright and license ---
2             #
3             # file: lib/Dist/Zilla/Plugin/Templates/File.pm
4             #
5             # Copyright © 2015 Van de Bugger
6             #
7             # This file is part of perl-Dist-Zilla-Plugin-Templates.
8             #
9             # perl-Dist-Zilla-Plugin-Templates 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-Plugin-Templates is distributed in the hope that it will be useful, but WITHOUT
14             # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15             # 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-Plugin-Templates. If not, see <http://www.gnu.org/licenses/>.
19             #
20             # ---------------------------------------------------------------------- copyright and license ---
21              
22             #pod =for test_synopsis BEGIN { die "SKIP: Not Perl code.\n" };
23             #pod
24             #pod =head1 SYNOPSIS
25             #pod
26             #pod In a template:
27             #pod
28             #pod {{ include( 'as-is.txt' ); }}
29             #pod {{ include( 'verbatim.txt' )->indent; }}
30             #pod {{ include( 'template.txt' )->fill_in; }}
31             #pod {{ include( 'readme.pod' )->pod2text; }}
32             #pod {{ include( 'assa.txt' )->chomp->trim->indent; }}
33             #pod …
34             #pod
35             #pod =head1 DESCRIPTION
36             #pod
37             #pod This is a helper module for C<Dist::Zilla::Templates>. It provides few frequently used operations
38             #pod on include files.
39             #pod
40             #pod Usually objects are created by "include" function (see
41             #pod L<Dist::Zilla::Plugin::Templates/"include">).
42             #pod
43             #pod The object evaluated in string context returns the file content, so
44             #pod
45             #pod $file->content
46             #pod
47             #pod and
48             #pod
49             #pod "$file"
50             #pod
51             #pod produces the same result.
52             #pod
53             #pod =head1 SEE ALSO
54             #pod
55             #pod =for :list
56             #pod = L<Dist::Zilla>
57             #pod = L<Dist::Zilla::Role::FileFinderUser>
58             #pod = L<Dist::Zilla::Role::TextTemplater>
59             #pod = L<Text::Template>
60             #pod = L<Pod::Text>
61             #pod = L<Dist::Zilla::Plugin::Templates::Manual>
62             #pod
63             #pod =cut
64              
65             package Dist::Zilla::Plugin::Templates::File;
66              
67 1     1   4 use Moose;
  1         1  
  1         4  
68 1     1   3668 use namespace::autoclean 0.16;
  1         16  
  1         3  
69             # ^ `namespace::autoclean` pre-0.16 wipes out overloads,
70             # see <https://rt.cpan.org/Ticket/Display.html?id=50938>.
71 1     1   43 use version 0.77;
  1         10  
  1         4  
72              
73             # ABSTRACT: Frequently used operations on include files
74             our $VERSION = 'v0.6.2_02'; # TRIAL VERSION
75              
76             extends 'Dist::Zilla::File::InMemory';
77              
78             use overload '""' => sub {
79 21     21   989 my ( $self ) = @_;
80 21         63 return $self->content;
81 1     1   87 };
  1         1  
  1         8  
82              
83 1     1   577 use Pod::Text qw{}; # `Pod::Text` exports `pod2text` by default. Let us avoid it.
  1         21933  
  1         21  
84 1     1   4 use Carp qw{ croak };
  1         1  
  1         281  
85              
86             # --------------------------------------------------------------------------------------------------
87              
88             #pod =attr _plugin
89             #pod
90             #pod Reference to the plugin created this object.
91             #pod
92             #pod C<Object>, read-only.
93             #pod
94             #pod =cut
95              
96             has _plugin => (
97             isa => 'Object',
98             is => 'ro',
99             weak_ref => 1,
100             );
101              
102             # --------------------------------------------------------------------------------------------------
103              
104             #pod =method chomp
105             #pod
106             #pod $file->chomp();
107             #pod $file->chomp( $count );
108             #pod
109             #pod Chomps the file content C<$count> times. If C<$count> is not specified, the method chomps all the
110             #pod trailing newlines (more exactly: all the trailing input record separators; see core function
111             #pod C<chomp> for details).
112             #pod
113             #pod Note: The methods chomps newlines from the end of file, I<not> from each line.
114             #pod
115             #pod The method returns C<$self> for chaining.
116             #pod
117             #pod =cut
118              
119             sub chomp { ## no critic ( ProhibitBuiltinHomonyms )
120 3     3 1 5 my ( $self, $count ) = @_;
121 3         13 my $content = $self->content;
122 3 100       167 if ( not defined( $count ) ) {
123 2         4 $count = -1;
124             };
125 3   100     21 while ( $count and CORE::chomp( $content ) ) {
126 7         20 -- $count;
127             };
128 3         9 $self->content( $content );
129 3         597 return $self;
130             };
131              
132             # --------------------------------------------------------------------------------------------------
133              
134             #pod =method fill_in
135             #pod
136             #pod $file->fill_in();
137             #pod $file->fill_in( \%variables, \%extra_args );
138             #pod
139             #pod Calls plugin's C<fill_in_file> method (which is defined in C<TextTemplater> role), passing C<$self>
140             #pod as the first argument. Returns C<$self>.
141             #pod
142             #pod Primary purpose of the method is including a file which is template itself:
143             #pod
144             #pod {{ include( 'doc/chapter1.pod' )->fill_in; }}
145             #pod
146             #pod Without C<fill_in>, F<doc/chapter1.pod> is included as-is, Perl code fragments, if any, are not
147             #pod evaluated.
148             #pod
149             #pod See L<Dist::Zilla::Role::TextTemplater/"fill_in_file">.
150             #pod
151             #pod =cut
152              
153             # TODO: Pass arguments recursively?
154              
155             sub fill_in {
156 6     6 1 11 my ( $self, @args ) = @_;
157 6         180 $self->_plugin->fill_in_file( $self, @args );
158 6         2163 return $self;
159             };
160              
161             # --------------------------------------------------------------------------------------------------
162              
163             #pod =method indent
164             #pod
165             #pod $file->indent();
166             #pod $file->indent( $size );
167             #pod
168             #pod Indents file content by inserting specified number of spaces to the beginning of every non-empty
169             #pod line. By default, file is indented with 4 spaces. The method returns C<$self> for chaining.
170             #pod
171             #pod Primary purpose of the method is including a file into POD as verbatim paragraph(s):
172             #pod
173             #pod =head2 example.pl
174             #pod
175             #pod {{ include( 'ex/example.pl' )->indent; }}
176             #pod
177             #pod =cut
178             #pod
179             #pod =cut
180              
181             sub indent {
182 3     3 1 5 my ( $self, $size ) = @_;
183 3 100       10 my $indent = ' ' x ( defined( $size ) ? $size : 4 );
184 3         9 my $content = $self->content;
185 3         172 $content =~ s{^(?!$)}{$indent}gmx;
186 3         7 $self->content( $content );
187 3         601 return $self;
188             };
189              
190             # --------------------------------------------------------------------------------------------------
191              
192             #pod =method munge
193             #pod
194             #pod $file->munge( \&func );
195             #pod $file->munge( sub { …modify $_ here… } );
196             #pod
197             #pod Calls the specified function. File content is passed to the function in C<$_> variable. Return
198             #pod value of the function is ignored. Value of C<$_> variable becomes new file content. The method
199             #pod returns C<$self> for chaining.
200             #pod
201             #pod =cut
202              
203             sub munge {
204 1     1 1 2 my ( $self, $sub ) = @_;
205 1         5 local $_ = $self->content;
206 1         58 $sub->();
207 1         3 $self->content( $_ );
208 1         235 return $self;
209             };
210              
211             # --------------------------------------------------------------------------------------------------
212              
213             #pod =method pod2text
214             #pod
215             #pod $file->pod2text( %options );
216             #pod
217             #pod Converts POD to plain text. It is a simple wrapper over C<Pod::Text>. See documentation on
218             #pod C<Pod::Text::new> for description of available options. The method returns C<$self> for chaining.
219             #pod
220             #pod Example:
221             #pod
222             #pod {{ include( 'readme.pod' )->pod2text( width => 80, quotes => 'none', loose => 1 ); }}
223             #pod
224             #pod See L<Pod::Text/"DESCRIPTION">.
225             #pod
226             #pod =cut
227              
228             sub pod2text {
229 3     3 1 8 my ( $self, %opts ) = @_;
230 3         13 my $name = $self->name;
231 3         134 my $parser = Pod::Text->new( %opts );
232 3         409 my ( $text, $errata );
233 3         17 $parser->output_string( \$text );
234 3 50       1029 if ( $parser->can( 'errata_seen' ) ) {
235 0         0 $parser->complain_stderr( 0 );
236 0         0 $parser->parse_string_document( $self->content );
237 0         0 $errata = $parser->errata_seen;
238             } else {
239             # Now do a dirty hack. `Pod::Simple` parser prior to 3.32 either print messages to `STDERR`
240             # or creates a section at the end of the document. There is no simple way to get error
241             # messages. Let us redefine its `_complain_warn` function to catch error messages.
242 3         10 $parser->complain_stderr( 1 );
243 1     1   4 no warnings 'redefine'; ## no critic ( ProhibitNoWarnings )
  1         1  
  1         265  
244             local *Pod::Simple::_complain_warn = sub { ## no critic ( ProtectPrivateVars )
245 2     2   569 my ( undef, $line, $msg ) = @_;
246 2         3 push( @{ $errata->{ $line } }, $msg );
  2         7  
247 3         37 };
248             # Ok, now parse POD and reports errors, if any:
249 3         19 $parser->parse_string_document( $self->content );
250             };
251             ## no critic ( RequireCarping )
252 3 100       4798 if ( $parser->any_errata_seen ) {
253 1         8 for my $line ( sort( keys( %$errata ) ) ) {
254 2         296 warn "$_ at $name line $line.\n" for @{ $errata->{ $line } };
  2         28  
255             };
256             # TODO: Use `log_errors_in_file` to repot POD errors?
257 1         226 die "POD errata found at $name.\n";
258             };
259 2 50       17 if ( not $parser->content_seen ) {
260 0         0 die "No POD content found at $name.\n";
261             };
262             ## critic ( RequireCarping )
263 2         17 $self->content( $text );
264 2         522 return $self;
265             };
266              
267             # --------------------------------------------------------------------------------------------------
268              
269             #pod =method trim
270             #pod
271             #pod $file->trim();
272             #pod
273             #pod Trims trailing whitespaces from every line. The method returns C<$self> for chaining.
274             #pod
275             #pod =cut
276              
277             sub trim {
278 1     1 1 2 my ( $self ) = @_;
279 1         5 my $content = $self->content;
280 1         66 $content =~ s{(?:(?!\n)\s)+$}{}gmx;
281 1         3 $self->content( $content );
282 1         199 return $self;
283             };
284              
285             # --------------------------------------------------------------------------------------------------
286              
287             __PACKAGE__->meta->make_immutable();
288              
289             1;
290              
291             # --------------------------------------------------------------------------------------------------
292              
293             #pod =head1 COPYRIGHT AND LICENSE
294             #pod
295             #pod Copyright (C) 2015 Van de Bugger
296             #pod
297             #pod License GPLv3+: The GNU General Public License version 3 or later
298             #pod <http://www.gnu.org/licenses/gpl-3.0.txt>.
299             #pod
300             #pod This is free software: you are free to change and redistribute it. There is
301             #pod NO WARRANTY, to the extent permitted by law.
302             #pod
303             #pod
304             #pod =cut
305              
306             # end of file #
307              
308             __END__
309              
310             =pod
311              
312             =encoding UTF-8
313              
314             =head1 NAME
315              
316             Dist::Zilla::Plugin::Templates::File - Frequently used operations on include files
317              
318             =head1 VERSION
319              
320             Version v0.6.2_02, released on 2016-12-19 18:05 UTC.
321             This is a B<trial release>.
322              
323             =for test_synopsis BEGIN { die "SKIP: Not Perl code.\n" };
324              
325             =head1 SYNOPSIS
326              
327             In a template:
328              
329             {{ include( 'as-is.txt' ); }}
330             {{ include( 'verbatim.txt' )->indent; }}
331             {{ include( 'template.txt' )->fill_in; }}
332             {{ include( 'readme.pod' )->pod2text; }}
333             {{ include( 'assa.txt' )->chomp->trim->indent; }}
334             …
335              
336             =head1 DESCRIPTION
337              
338             This is a helper module for C<Dist::Zilla::Templates>. It provides few frequently used operations
339             on include files.
340              
341             Usually objects are created by "include" function (see
342             L<Dist::Zilla::Plugin::Templates/"include">).
343              
344             The object evaluated in string context returns the file content, so
345              
346             $file->content
347              
348             and
349              
350             "$file"
351              
352             produces the same result.
353              
354             =head1 OBJECT ATTRIBUTES
355              
356             =head2 _plugin
357              
358             Reference to the plugin created this object.
359              
360             C<Object>, read-only.
361              
362             =head1 OBJECT METHODS
363              
364             =head2 chomp
365              
366             $file->chomp();
367             $file->chomp( $count );
368              
369             Chomps the file content C<$count> times. If C<$count> is not specified, the method chomps all the
370             trailing newlines (more exactly: all the trailing input record separators; see core function
371             C<chomp> for details).
372              
373             Note: The methods chomps newlines from the end of file, I<not> from each line.
374              
375             The method returns C<$self> for chaining.
376              
377             =head2 fill_in
378              
379             $file->fill_in();
380             $file->fill_in( \%variables, \%extra_args );
381              
382             Calls plugin's C<fill_in_file> method (which is defined in C<TextTemplater> role), passing C<$self>
383             as the first argument. Returns C<$self>.
384              
385             Primary purpose of the method is including a file which is template itself:
386              
387             {{ include( 'doc/chapter1.pod' )->fill_in; }}
388              
389             Without C<fill_in>, F<doc/chapter1.pod> is included as-is, Perl code fragments, if any, are not
390             evaluated.
391              
392             See L<Dist::Zilla::Role::TextTemplater/"fill_in_file">.
393              
394             =head2 indent
395              
396             $file->indent();
397             $file->indent( $size );
398              
399             Indents file content by inserting specified number of spaces to the beginning of every non-empty
400             line. By default, file is indented with 4 spaces. The method returns C<$self> for chaining.
401              
402             Primary purpose of the method is including a file into POD as verbatim paragraph(s):
403              
404             =head2 example.pl
405              
406             {{ include( 'ex/example.pl' )->indent; }}
407              
408             =cut
409              
410             =head2 munge
411              
412             $file->munge( \&func );
413             $file->munge( sub { …modify $_ here… } );
414              
415             Calls the specified function. File content is passed to the function in C<$_> variable. Return
416             value of the function is ignored. Value of C<$_> variable becomes new file content. The method
417             returns C<$self> for chaining.
418              
419             =head2 pod2text
420              
421             $file->pod2text( %options );
422              
423             Converts POD to plain text. It is a simple wrapper over C<Pod::Text>. See documentation on
424             C<Pod::Text::new> for description of available options. The method returns C<$self> for chaining.
425              
426             Example:
427              
428             {{ include( 'readme.pod' )->pod2text( width => 80, quotes => 'none', loose => 1 ); }}
429              
430             See L<Pod::Text/"DESCRIPTION">.
431              
432             =head2 trim
433              
434             $file->trim();
435              
436             Trims trailing whitespaces from every line. The method returns C<$self> for chaining.
437              
438             =head1 SEE ALSO
439              
440             =over 4
441              
442             =item L<Dist::Zilla>
443              
444             =item L<Dist::Zilla::Role::FileFinderUser>
445              
446             =item L<Dist::Zilla::Role::TextTemplater>
447              
448             =item L<Text::Template>
449              
450             =item L<Pod::Text>
451              
452             =item L<Dist::Zilla::Plugin::Templates::Manual>
453              
454             =back
455              
456             =head1 AUTHOR
457              
458             Van de Bugger <van.de.bugger@gmail.com>
459              
460             =head1 COPYRIGHT AND LICENSE
461              
462             Copyright (C) 2015 Van de Bugger
463              
464             License GPLv3+: The GNU General Public License version 3 or later
465             <http://www.gnu.org/licenses/gpl-3.0.txt>.
466              
467             This is free software: you are free to change and redistribute it. There is
468             NO WARRANTY, to the extent permitted by law.
469              
470             =cut