File Coverage

blib/lib/Filter/HereDocIndent.pm
Criterion Covered Total %
statement 65 74 87.8
branch 19 28 67.8
condition n/a
subroutine 11 12 91.6
pod 0 4 0.0
total 95 118 80.5


line stmt bran cond sub pod time code
1             package Filter::HereDocIndent;
2 1     1   416 use strict;
  1         1  
  1         32  
3 1     1   5291 use Filter::Util::Call;
  1         2693  
  1         83  
4             # use Debug::ShowStuff ':all';
5 1     1   7 use re 'taint';
  1         6  
  1         52  
6 1     1   6 use vars qw($VERSION $debug);
  1         1  
  1         88  
7              
8             # documentation at end of file
9              
10              
11             # version
12             $VERSION = '1.01';
13              
14             # constants
15 1     1   8 use constant REG => 1;
  1         4  
  1         136  
16 1     1   6 use constant HEREDOC => 2;
  1         1  
  1         67  
17 1     1   7 use constant POD => 3; # reserved for later improvement
  1         8  
  1         1245  
18              
19              
20             #------------------------------------------------------------------
21             # new
22             #
23             sub new {
24 1     1 0 2 my ($class, %opts) = @_;
25 1         2 my $self = bless({}, $class);
26            
27             # default INDENT_CONTENT
28 1 50       10 defined($opts{'INDENT_CONTENT'}) or $opts{'INDENT_CONTENT'} = 1;
29 1         6 $self->{'INDENT_CONTENT'} = $opts{'INDENT_CONTENT'};
30            
31             # NWS: strip {nws} out of heredocs
32 1         2 $self->{'NWS'} = $opts{'NWS'};
33            
34             # default state
35 1         1 $self->{'state'} = REG;
36            
37             # return object
38 1         4 return $self;
39             }
40             #
41             # new
42             #------------------------------------------------------------------
43              
44              
45             #------------------------------------------------------------------
46             # import routine: creates filter object and adds it
47             # to the filters array
48             #
49             sub import {
50 1     1   9 my ($class, %opts) = @_;
51            
52             # add filter if set to do so
53 1 50       6 if ( defined($opts{'filter_add'}) ? $opts{'filter_add'} : 1 ) {
    50          
54 1         3 filter_add($class->new(%opts));
55             }
56             }
57             #
58             # import routine
59             #------------------------------------------------------------------
60              
61              
62             #------------------------------------------------------------------
63             # filter: this sub is run for every line in the calling script
64             #
65             sub filter {
66 62     62 0 17701 my $self = shift;
67 62         118 my $status = filter_read() ;
68 62         55 my $line = $_;
69            
70 62         72 ($status, $line) = $self->process_line($status, $line);
71            
72             # set line and return value
73 62         64 $_= $line;
74 62         1690 $status;
75             }
76             #
77             # filter
78             #------------------------------------------------------------------
79              
80              
81              
82             #------------------------------------------------------------------
83             # filter_block
84             #
85             sub filter_block {
86 0     0 0 0 my ($self, $block) = @_;
87 0         0 my (@lines, $status, $rv);
88            
89             # parse block into lines
90 0         0 @lines = split("\n", $block);
91            
92             # loop through lines
93             LINE_LOOP:
94 0         0 foreach my $line (@lines) {
95 0         0 ($status, $line) = $self->process_line(1, "$line\n");
96             }
97            
98             # get return string
99 0         0 $rv = join('', @lines);
100            
101             # return
102 0         0 return $rv;
103             }
104             #
105             # filter_block
106             #------------------------------------------------------------------
107              
108              
109              
110             #------------------------------------------------------------------
111             # process_line
112             #
113             sub process_line {
114 62     62 0 54 my ($self, $status, $line) = @_;
115            
116             # if we're at the end of the file
117 62 100       112 if (! $status) {
    100          
118             # for debugging this module
119 1 50       3 if ($debug)
  0         0  
120             {print STDERR "\n--------------------------\n"}
121             }
122            
123             # if in here doc
124             elsif ($self->{'state'} == HEREDOC) {
125             # if this is the end of the heredoc
126 8 100       40 if ($line =~ m|^(\s*)$self->{'del_regex'}\s*$|) {
127 2         3 my $len = length($1);
128            
129 2 50       5 if ($self->{'INDENT_CONTENT'}) {
130 2         2 foreach my $el (@{$self->{'lines'}}) {
  2         4  
131 6 100       50 $el =~ s|^\s{$len}|| or $el =~ s|^\s+||;
132 6 50       13 $el eq '' and $el = "\n";
133             }
134             }
135            
136 2         3 $line = join('', @{$self->{'lines'}}, $self->{'del'}, "\n");
  2         7  
137            
138             # add empty lines so that line numbers match up with original code
139             # NOTE: The following line still doesn't address the issue of
140             # {nws} removals
141             # $line .= "\n" x scalar(@{$self->{'lines'}});
142            
143 2         2 foreach (@{$self->{'lines'}})
  2         4  
144 6         7 { $line .= "\n" }
145            
146             # remove whitespace
147 2 50       5 if ($self->{'NWS'}) {
148 0         0 $line =~ s|\s*\{nws\}\s*||gs;
149             }
150            
151             # set state to regular code
152 2         3 $self->{'state'} = REG;
153             }
154            
155             # else add to lines array
156             else {
157 6         5 push @{$self->{'lines'}}, $line;
  6         9  
158 6         8 $line = '';
159             }
160             }
161            
162             # else in regular code
163             else {
164             # if this line starts a heredoc
165 53 100       104 if ($line =~ m/
166             ^ # start of line
167             [^#]* # anything except a comment marker
168             <<
169             \s*
170            
171             (
172             '[^']+'
173             |
174             "[^"]+"
175             |
176             \w+
177             )
178            
179             [^'"]*
180             ;
181             \s*
182            
183             /sx
184             ) {
185            
186 2         5 $self->{'del'} = $1;
187 2 50       11 $self->{'del'} =~ s|^'(.*)'$|$1| or $self->{'del'} =~ s|^"(.*)"$|$1|;
188 2         6 $self->{'del_regex'} = quotemeta($self->{'del'});
189            
190 2         3 $self->{'lines'} = [];
191 2         3 $self->{'state'} = HEREDOC;
192             }
193             }
194            
195             # for debugging this module
196 62 50       88 print STDERR $line if $debug;
197            
198 62         84 return ($status, $line);
199             }
200             #
201             # process_line
202             #------------------------------------------------------------------
203              
204              
205              
206             # return true
207             1;
208              
209             __END__