File Coverage

lib/Template/Plugin/String.pm
Criterion Covered Total %
statement 161 163 98.7
branch 38 48 79.1
condition 26 37 70.2
subroutine 34 35 97.1
pod 25 30 83.3
total 284 313 90.7


line stmt bran cond sub pod time code
1             #============================================================= -*-Perl-*-
2             #
3             # Template::Plugin::String
4             #
5             # DESCRIPTION
6             # Template Toolkit plugin to implement a basic String object.
7             #
8             # AUTHOR
9             # Andy Wardley
10             #
11             # COPYRIGHT
12             # Copyright (C) 2001-2007 Andy Wardley. All Rights Reserved.
13             #
14             # This module is free software; you can redistribute it and/or
15             # modify it under the same terms as Perl itself.
16             #
17             #============================================================================
18              
19             package Template::Plugin::String;
20              
21 1     1   9135 use strict;
  1         3  
  1         201  
22 1     1   8 use warnings;
  1         4  
  1         47  
23 1     1   6 use base 'Template::Plugin';
  1         2  
  1         483  
24 1     1   5 use Template::Exception;
  1         3  
  1         25  
25              
26 1         9 use overload q|""| => "text",
27 1     1   5 fallback => 1;
  1         1  
28              
29             our $VERSION = 2.40;
30             our $ERROR = '';
31              
32             *centre = \*center;
33             *append = \*push;
34             *prepend = \*unshift;
35              
36             #------------------------------------------------------------------------
37              
38             sub new {
39 71     71 1 216 my ($class, @args) = @_;
40 71 100       167 my $context = ref $class ? undef : shift(@args);
41 71 100 100     396 my $config = @args && ref $args[-1] eq 'HASH' ? pop(@args) : { };
42              
43 71   66     317 $class = ref($class) || $class;
44              
45             my $text = defined $config->{ text }
46             ? $config->{ text }
47 71 100       241 : (@args ? shift(@args) : '');
    100          
48              
49             # print STDERR "text: [$text]\n";
50             # print STDERR "class: [$class]\n";
51            
52 71         473 my $self = bless {
53             text => $text,
54             filters => [ ],
55             _CONTEXT => $context,
56             }, $class;
57              
58 71   100     690 my $filter = $config->{ filter } || $config->{ filters };
59              
60             # install any output filters specified as 'filter' or 'filters' option
61 71 100       216 $self->output_filter($filter)
62             if $filter;
63              
64 71         582 return $self;
65             }
66              
67              
68             sub text {
69 70     70 1 251 my $self = shift;
70 70 100       123 return $self->{ text } unless @{ $self->{ filters } };
  70         480  
71              
72 10         23 my $text = $self->{ text };
73 10         16 my $context = $self->{ _CONTEXT };
74              
75 10         14 foreach my $dispatch (@{ $self->{ filters } }) {
  10         22  
76 18         30 my ($name, $args) = @$dispatch;
77 18   33     51 my $code = $context->filter($name, $args)
78             || $self->throw($context->error());
79 18         52 $text = &$code($text);
80             }
81 10         36 return $text;
82             }
83              
84              
85             sub copy {
86 14     14 1 182 my $self = shift;
87 14         40 $self->new($self->{ text });
88             }
89              
90              
91             sub throw {
92 0     0 0 0 my $self = shift;
93              
94 0         0 die (Template::Exception->new('String', join('', @_)));
95             }
96              
97              
98             #------------------------------------------------------------------------
99             # output_filter($filter)
100             #
101             # Install automatic output filter(s) for the string. $filter can a list:
102             # [ 'name1', 'name2' => [ ..args.. ], name4 => { ..args.. } ] or a hash
103             # { name1 => '', name2 => [ args ], name3 => { args } }
104             #------------------------------------------------------------------------
105              
106             sub output_filter {
107 10     10 0 52 my ($self, $filter) = @_;
108 10         13 my ($name, $args, $dispatch);
109 10         16 my $filters = $self->{ filters };
110 10         12 my $count = 0;
111              
112 10 100       42 if (ref $filter eq 'HASH') {
    100          
113 2         7 $filter = [ %$filter ];
114             }
115             elsif (ref $filter ne 'ARRAY') {
116 6         44 $filter = [ split(/\s*\W+\s*/, $filter) ];
117             }
118              
119 10         33 while (@$filter) {
120 17         23 $name = shift @$filter;
121              
122             # args may follow as a reference (or empty string, e.g. { foo => '' }
123 17 100 100     73 if (@$filter && (ref($filter->[0]) || ! length $filter->[0])) {
      66        
124 5         9 $args = shift @$filter;
125 5 100       10 if ($args) {
126 3 50       7 $args = [ $args ] unless ref $args eq 'ARRAY';
127             }
128             else {
129 2         3 $args = [ ];
130             }
131             }
132             else {
133 12         20 $args = [ ];
134             }
135              
136             # $self->DEBUG("adding output filter $name(@$args)\n");
137              
138 17         36 push(@$filters, [ $name, $args ]);
139 17         35 $count++;
140             }
141              
142 10         23 return '';
143             }
144              
145              
146             #------------------------------------------------------------------------
147              
148             sub push {
149 6     6 1 13 my $self = shift;
150 6         21 $self->{ text } .= join('', @_);
151 6         64 return $self;
152             }
153              
154              
155             sub unshift {
156 2     2 1 40 my $self = shift;
157 2         8 $self->{ text } = join('', @_) . $self->{ text };
158 2         8 return $self;
159             }
160              
161              
162             sub pop {
163 1     1 1 2 my $self = shift;
164 1   50     4 my $strip = shift || return $self;
165 1         23 $self->{ text } =~ s/$strip$//;
166 1         7 return $self;
167             }
168              
169              
170             sub shift {
171 1     1 1 3 my $self = shift;
172 1   50     5 my $strip = shift || return $self;
173 1         14 $self->{ text } =~ s/^$strip//;
174 1         6 return $self;
175             }
176              
177             #------------------------------------------------------------------------
178              
179             sub center {
180 2     2 1 5 my ($self, $width) = @_;
181 2         3 my $text = $self->{ text };
182 2         5 my $len = length $text;
183 2   50     8 $width ||= 0;
184              
185 2 50       8 if ($len < $width) {
186 2         7 my $lpad = int(($width - $len) / 2);
187 2         4 my $rpad = $width - $len - $lpad;
188 2         9 $self->{ text } = (' ' x $lpad) . $self->{ text } . (' ' x $rpad);
189             }
190              
191 2         8 return $self;
192             }
193              
194              
195             sub left {
196 1     1 1 4 my ($self, $width) = @_;
197 1         4 my $len = length $self->{ text };
198 1   50     4 $width ||= 0;
199              
200 1 50       7 $self->{ text } .= (' ' x ($width - $len))
201             if $width > $len;
202              
203 1         7 return $self;
204             }
205              
206              
207             sub right {
208 1     1 1 3 my ($self, $width) = @_;
209 1         3 my $len = length $self->{ text };
210 1   50     5 $width ||= 0;
211              
212             $self->{ text } = (' ' x ($width - $len)) . $self->{ text }
213 1 50       8 if $width > $len;
214              
215 1         5 return $self;
216             }
217              
218              
219             sub format {
220 1     1 1 3 my ($self, $format) = @_;
221 1 50       4 $format = '%s' unless defined $format;
222 1         8 $self->{ text } = sprintf($format, $self->{ text });
223 1         10 return $self;
224             }
225              
226              
227             sub filter {
228 2     2 0 43 my ($self, $name, @args) = @_;
229              
230 2         4 my $context = $self->{ _CONTEXT };
231              
232 2   33     7 my $code = $context->filter($name, \@args)
233             || $self->throw($context->error());
234 2         7 return &$code($self->{ text });
235             }
236              
237              
238             #------------------------------------------------------------------------
239              
240             sub upper {
241 1     1 1 3 my $self = CORE::shift;
242 1         5 $self->{ text } = uc $self->{ text };
243 1         10 return $self;
244             }
245              
246              
247             sub lower {
248 5     5 1 26 my $self = CORE::shift;
249 5         15 $self->{ text } = lc $self->{ text };
250 5         54 return $self;
251             }
252              
253              
254             sub capital {
255 1     1 1 21 my $self = CORE::shift;
256 1         10 $self->{ text } =~ s/^(.)/\U$1/;
257 1         5 return $self;
258             }
259              
260             #------------------------------------------------------------------------
261              
262             sub chop {
263 2     2 1 21 my $self = CORE::shift;
264 2         6 chop $self->{ text };
265 2         11 return $self;
266             }
267              
268              
269             sub chomp {
270 1     1 1 26 my $self = CORE::shift;
271 1         3 chomp $self->{ text };
272 1         100 return $self;
273             }
274              
275              
276             sub trim {
277 1     1 1 3 my $self = CORE::shift;
278 1         4 for ($self->{ text }) {
279 1         5 s/^\s+//;
280 1         6 s/\s+$//;
281             }
282 1         9 return $self;
283             }
284              
285              
286             sub collapse {
287 1     1 1 2 my $self = CORE::shift;
288 1         4 for ($self->{ text }) {
289 1         6 s/^\s+//;
290 1         5 s/\s+$//;
291 1         6 s/\s+/ /g
292             }
293 1         7 return $self;
294              
295             }
296              
297             #------------------------------------------------------------------------
298              
299             sub length {
300 1     1 1 2 my $self = CORE::shift;
301 1         8 return length $self->{ text };
302             }
303              
304              
305             sub truncate {
306 3     3 1 7 my ($self, $length, $suffix) = @_;
307 3 50       8 return $self unless defined $length;
308 3   100     12 $suffix ||= '';
309 3 100       22 return $self if CORE::length $self->{ text } <= $length;
310 2         9 $self->{ text } = CORE::substr($self->{ text }, 0,
311             $length - CORE::length($suffix)) . $suffix;
312 2         12 return $self;
313             }
314              
315              
316             sub substr {
317 6     6 0 62 my ($self, $offset, $length, $replacement) = @_;
318 6   100     18 $offset ||= 0;
319              
320 6 100       11 if(defined $length) {
321 4 100       8 if (defined $replacement) {
322 2         6 my $removed = CORE::substr( $self->{text}, $offset, $length );
323 2         6 CORE::substr( $self->{text}, $offset, $length ) = $replacement;
324 2         7 return $removed;
325             }
326             else {
327 2         12 return CORE::substr( $self->{text}, $offset, $length );
328             }
329             }
330             else {
331 2         10 return CORE::substr( $self->{text}, $offset );
332             }
333             }
334              
335              
336             sub repeat {
337 1     1 1 3 my ($self, $n) = @_;
338 1 50       5 return $self unless defined $n;
339 1         7 $self->{ text } = $self->{ text } x $n;
340 1         6 return $self;
341             }
342              
343              
344             sub replace {
345 1     1 1 4 my ($self, $search, $replace) = @_;
346 1 50       5 return $self unless defined $search;
347 1 50       4 $replace = '' unless defined $replace;
348 1         27 $self->{ text } =~ s/$search/$replace/g;
349 1         9 return $self;
350             }
351              
352              
353             sub remove {
354 2     2 1 3 my ($self, $search) = @_;
355 2 50       9 $search = '' unless defined $search;
356 2         56 $self->{ text } =~ s/$search//g;
357 2         14 return $self;
358             }
359              
360              
361             sub split {
362 5     5 1 10 my $self = CORE::shift;
363 5         11 my $split = CORE::shift;
364 5   100     24 my $limit = CORE::shift || 0;
365 5 100       15 $split = '\s+' unless defined $split;
366 5         138 return [ split($split, $self->{ text }, $limit) ];
367             }
368              
369              
370             sub search {
371 4     4 1 6 my ($self, $pattern) = @_;
372 4         67 return $self->{ text } =~ /$pattern/;
373             }
374              
375              
376             sub equals {
377 1     1 0 3 my ($self, $comparison) = @_;
378 1         4 return $self->{ text } eq $comparison;
379             }
380              
381              
382             1;
383              
384             __END__