File Coverage

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


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