File Coverage

lib/Dist/Zilla/Plugin/Munge/Whitespace.pm
Criterion Covered Total %
statement 21 68 30.8
branch 0 14 0.0
condition 0 6 0.0
subroutine 7 15 46.6
pod 0 2 0.0
total 28 105 26.6


line stmt bran cond sub pod time code
1 1     1   563 use 5.006; # our
  1         2  
  1         28  
2 1     1   3 use strict;
  1         1  
  1         20  
3 1     1   3 use warnings;
  1         6  
  1         48  
4              
5             package Dist::Zilla::Plugin::Munge::Whitespace;
6              
7             our $VERSION = '0.001000';
8              
9             # ABSTRACT: Strip superfluous spaces from pesky files.
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 1     1   447 use Moose qw( has with around );
  1         303241  
  1         8  
14 1     1   4627 use Dist::Zilla::Role::FileMunger 1.000; # munge_file
  1         50107  
  1         35  
15 1     1   576 use Dist::Zilla::Util::ConfigDumper qw( config_dumper );
  1         1281  
  1         5  
16              
17             with 'Dist::Zilla::Role::FileMunger';
18              
19             has 'preserve_trailing' => ( is => 'ro', isa => 'Bool', lazy => 1, default => sub { undef } );
20             has 'preserve_cr' => ( is => 'ro', isa => 'Bool', lazy => 1, default => sub { undef } );
21             has 'filename' => ( is => 'ro', isa => 'ArrayRef', lazy => 1, default => sub { [] } );
22             has 'match' => ( is => 'ro', isa => 'ArrayRef', lazy => 1, default => sub { [] } );
23              
24             has '_match_expr' => ( is => 'ro', isa => 'RegexpRef', lazy_build => 1 );
25             has '_eol_kill_expr' => ( is => 'ro', isa => 'RegexpRef', lazy_build => 1 );
26              
27             around dump_config => config_dumper( __PACKAGE__, { attrs => [qw( preserve_trailing preserve_cr filename match )] } );
28              
29             __PACKAGE__->meta->make_immutable;
30 1     1   158 no Moose;
  1         1  
  1         7  
31              
32              
33              
34              
35              
36              
37              
38 0     0 0   sub mvp_multivalue_args { return qw{ filename match } }
39              
40             sub munge_file {
41 0     0 0   my ( $self, $file ) = @_;
42 0 0         return unless $file->name =~ $self->_match_expr;
43 0 0         if ( $file->isa('Dist::Zilla::File::FromCode') ) {
44 0           return $self->_munge_from_code($file);
45             }
46 0           return $self->_munge_static($file);
47             }
48              
49             sub _build__match_expr {
50 0     0     my ($self) = @_;
51 0           my (@matches) = @{ $self->match };
  0            
52 0 0         if ( scalar @{ $self->filename } ) {
  0            
53 0           unshift @matches, sprintf q[\A(?:%s)\z], join q[|], map { quotemeta } @{ $self->filename };
  0            
  0            
54             }
55 0           my $combined = join q[|], @matches;
56              
57             ## no critic (RegularExpressions::RequireDotMatchAnything)
58             ## no critic (RegularExpressions::RequireLineBoundaryMatching)
59             ## no critic (RegularExpressions::RequireExtendedFormatting)
60              
61 0           return qr/$combined/;
62             }
63              
64             sub _build__eol_kill_expr {
65 0     0     my ($self) = @_;
66              
67             ## no critic (RegularExpressions::RequireDotMatchAnything)
68             ## no critic (RegularExpressions::RequireLineBoundaryMatching)
69             ## no critic (RegularExpressions::RequireExtendedFormatting)
70              
71 0           my $bad_bits = qr//;
72 0           my $end_line;
73 0 0         if ( not $self->preserve_trailing ) {
74              
75             # Add horrible spaces to end
76 0           $bad_bits = qr/[\x{20}\x{09}]+/;
77             }
78 0 0         if ( $self->preserve_cr ) {
79              
80             # preserve CR keeps the CR optional as part of the EOL lookahead.
81 0           $end_line = qr/(?=\x{0D}?\x{0A}|\z)/;
82             }
83             else {
84             # No-preserve CR swallows any CRs directly before the EOL lookahead.
85 0           $end_line = qr/\x{0D}?(?=\x{0A}|\z)/;
86             }
87              
88 0           return qr/${bad_bits}${end_line}/;
89             }
90              
91             sub _munge_string {
92 0     0     my ( $self, $name, $string ) = @_;
93 0           $self->log_debug( [ 'Stripping trailing whitespace from %s', $name ] );
94              
95 0 0 0       if ( $self->preserve_cr and $self->preserve_trailing ) {
96              
97             # Noop, both EOL transformations
98             }
99             else {
100             ## no critic (RegularExpressions::RequireDotMatchAnything)
101             ## no critic (RegularExpressions::RequireLineBoundaryMatching)
102             ## no critic (RegularExpressions::RequireExtendedFormatting)
103              
104 0           my $expr = $self->_eol_kill_expr;
105 0           $string =~ s/$expr//g;
106             }
107 0           return $string;
108             }
109              
110             sub _munge_from_code {
111 0     0     my ( $self, $file ) = @_;
112 0 0 0       if ( $file->can('code_return_type') and 'text' ne $file->code_return_type ) {
113 0           $self->log_debug( [ 'Skipping %s: does not return text', $file->name ] );
114 0           return;
115             }
116 0           $self->log_debug( [ 'Munging FromCode (prep): %s', $file->name ] );
117 0           my $orig_coderef = $file->code();
118             $file->code(
119             sub {
120 0     0     $self->log_debug( [ 'Munging FromCode (write): %s', $file->name ] );
121 0           my $content = $file->$orig_coderef();
122 0           return $self->_munge_string( $file->name, $content );
123             },
124 0           );
125 0           return;
126             }
127              
128             sub _munge_static {
129 0     0     my ( $self, $file ) = @_;
130 0           $self->log_debug( [ 'Munging Static file: %s', $file->name ] );
131 0           my $content = $file->content;
132 0           $file->content( $self->_munge_string( $file->name, $content ) );
133 0           return;
134             }
135              
136             1;
137              
138             __END__
139              
140             =pod
141              
142             =encoding UTF-8
143              
144             =head1 NAME
145              
146             Dist::Zilla::Plugin::Munge::Whitespace - Strip superfluous spaces from pesky files.
147              
148             =head1 VERSION
149              
150             version 0.001000
151              
152             =head1 DESCRIPTION
153              
154             This plugin can be used with Dist::Zilla to remove remove white-space from selected files.
155              
156             In its default mode of operation, it will strip trailing white-space from the selected files in the following forms:
157              
158             =over 4
159              
160             =item * C<0x20>: The literal space character
161              
162             =item * C<0x9>: The literal tab character, otherwise known as C<\t>
163              
164             =item * C<0xD>: The Carriage Return character, otherwise known as C<\r> ( But only immediately before a \n )
165              
166             =back
167              
168             =for comment nobody cares
169              
170             =for Pod::Coverage mvp_multivalue_args munge_file
171              
172             =head1 USAGE
173              
174             [Munge::Whitespace]
175             filename = LICENSE ; *Cough*: https://github.com/Perl-Toolchain-Gang/Software-License/pull/30
176             filename = Changes
177             match = lib/*.pm
178              
179             ; Power User Options
180             ; Note: turning both of these options on at present would be idiotic.
181             ; unless you like applying substituion regex to whole files just to duplicate a string
182             preserve_trailing = 1 ; Don't nom trailing \s and \t
183             preserve_cr = 1 ; Don't turn \r\n into \n
184              
185             Note: This is just a standard munger, and will munge any files it gets told to munge.
186              
187             It will not however write files out anywhere or make your source tree all pretty.
188              
189             It will however scrub the files you have on their way out to your dist, or on their way out
190             to any other plugins you might have, like L<< C<CopyFromRelease>|Dist::Zilla::Plugin::CopyFilesFromRelease >>
191             or L<< C<CopyFromBuild>|Dist::Zilla::Plugin::CopyFilesFromBuild >>, and a smart player can probably combine
192             parts of this with either of those and have their dist automatically cleaned up for them when they run C<dzil build>.
193              
194             They might also enjoy the luxurious benefits of having sensitive white-space accidentally sent to a magical wonderland,
195             which breaks their code, or have a glorious race condition where something important they were working on and hadn't
196             gotten committed to git yet get eaten due to the file on disk getting updated, and their editor dutifully rejoicing
197             and prompting to reload their file, which may make them respond to the pavlovian conditioning to click "OK",
198             followed by much wailing and gnashing of teeth.
199              
200             Please enjoy our quality product, from the team at FootGuns Inc.
201              
202             =head1 TODO
203              
204             =over 4
205              
206             =item * C<finder> support.
207              
208             I figured I could, but C<YKW,FI>.
209              
210             =item * tests
211              
212             Would be useful. But dogfood for now.
213              
214             =item * indentation normalization
215              
216             Sounds like work.
217              
218             =back
219              
220             =head1 AUTHOR
221              
222             Kent Fredric <kentnl@cpan.org>
223              
224             =head1 COPYRIGHT AND LICENSE
225              
226             This software is copyright (c) 2015 by Kent Fredric <kentfredric@gmail.com>.
227              
228             This is free software; you can redistribute it and/or modify it under
229             the same terms as the Perl 5 programming language system itself.
230              
231             =cut