1 #============================================================= -*-Perl-*-
3 # Template::Plugin::String
6 # Template Toolkit plugin to implement a basic String object.
9 # Andy Wardley <abw@wardley.org>
12 # Copyright (C) 2001-2007 Andy Wardley. All Rights Reserved.
14 # This module is free software; you can redistribute it and/or
15 # modify it under the same terms as Perl itself.
17 #============================================================================
19 package Template::Plugin::String;
23 use base 'Template::Plugin';
24 use Template::Exception;
26 use overload q|""| => "text",
36 #------------------------------------------------------------------------
39 my ($class, @args) = @_;
40 my $context = ref $class ? undef : shift(@args);
41 my $config = @args && ref $args[-1] eq 'HASH' ? pop(@args) : { };
43 $class = ref($class) || $class;
45 my $text = defined $config->{ text }
47 : (@args ? shift(@args) : '');
49 # print STDERR "text: [$text]\n";
50 # print STDERR "class: [$class]\n";
58 my $filter = $config->{ filter } || $config->{ filters };
60 # install any output filters specified as 'filter' or 'filters' option
61 $self->output_filter($filter)
70 return $self->{ text } unless @{ $self->{ filters } };
72 my $text = $self->{ text };
73 my $context = $self->{ _CONTEXT };
75 foreach my $dispatch (@{ $self->{ filters } }) {
76 my ($name, $args) = @$dispatch;
77 my $code = $context->filter($name, $args)
78 || $self->throw($context->error());
79 $text = &$code($text);
87 $self->new($self->{ text });
94 die (Template::Exception->new('String', join('', @_)));
98 #------------------------------------------------------------------------
99 # output_filter($filter)
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 #------------------------------------------------------------------------
107 my ($self, $filter) = @_;
108 my ($name, $args, $dispatch);
109 my $filters = $self->{ filters };
112 if (ref $filter eq 'HASH') {
113 $filter = [ %$filter ];
115 elsif (ref $filter ne 'ARRAY') {
116 $filter = [ split(/\s*\W+\s*/, $filter) ];
120 $name = shift @$filter;
122 # args may follow as a reference (or empty string, e.g. { foo => '' }
123 if (@$filter && (ref($filter->[0]) || ! length $filter->[0])) {
124 $args = shift @$filter;
126 $args = [ $args ] unless ref $args eq 'ARRAY';
136 # $self->DEBUG("adding output filter $name(@$args)\n");
138 push(@$filters, [ $name, $args ]);
146 #------------------------------------------------------------------------
150 $self->{ text } .= join('', @_);
157 $self->{ text } = join('', @_) . $self->{ text };
164 my $strip = shift || return $self;
165 $self->{ text } =~ s/$strip$//;
172 my $strip = shift || return $self;
173 $self->{ text } =~ s/^$strip//;
177 #------------------------------------------------------------------------
180 my ($self, $width) = @_;
181 my $text = $self->{ text };
182 my $len = length $text;
186 my $lpad = int(($width - $len) / 2);
187 my $rpad = $width - $len - $lpad;
188 $self->{ text } = (' ' x $lpad) . $self->{ text } . (' ' x $rpad);
196 my ($self, $width) = @_;
197 my $len = length $self->{ text };
200 $self->{ text } .= (' ' x ($width - $len))
208 my ($self, $width) = @_;
209 my $len = length $self->{ text };
212 $self->{ text } = (' ' x ($width - $len)) . $self->{ text }
220 my ($self, $format) = @_;
221 $format = '%s' unless defined $format;
222 $self->{ text } = sprintf($format, $self->{ text });
228 my ($self, $name, @args) = @_;
230 my $context = $self->{ _CONTEXT };
232 my $code = $context->filter($name, \@args)
233 || $self->throw($context->error());
234 return &$code($self->{ text });
238 #------------------------------------------------------------------------
241 my $self = CORE::shift;
242 $self->{ text } = uc $self->{ text };
248 my $self = CORE::shift;
249 $self->{ text } = lc $self->{ text };
255 my $self = CORE::shift;
256 $self->{ text } =~ s/^(.)/\U$1/;
260 #------------------------------------------------------------------------
263 my $self = CORE::shift;
264 chop $self->{ text };
270 my $self = CORE::shift;
271 chomp $self->{ text };
277 my $self = CORE::shift;
278 for ($self->{ text }) {
287 my $self = CORE::shift;
288 for ($self->{ text }) {
297 #------------------------------------------------------------------------
300 my $self = CORE::shift;
301 return length $self->{ text };
306 my ($self, $length, $suffix) = @_;
307 return $self unless defined $length;
309 return $self if CORE::length $self->{ text } <= $length;
310 $self->{ text } = CORE::substr($self->{ text }, 0,
311 $length - CORE::length($suffix)) . $suffix;
317 my ($self, $offset, $length, $replacement) = @_;
320 if(defined $length) {
321 if (defined $replacement) {
322 my $removed = CORE::substr( $self->{text}, $offset, $length );
323 CORE::substr( $self->{text}, $offset, $length ) = $replacement;
327 return CORE::substr( $self->{text}, $offset, $length );
331 return CORE::substr( $self->{text}, $offset );
338 return $self unless defined $n;
339 $self->{ text } = $self->{ text } x $n;
345 my ($self, $search, $replace) = @_;
346 return $self unless defined $search;
347 $replace = '' unless defined $replace;
348 $self->{ text } =~ s/$search/$replace/g;
354 my ($self, $search) = @_;
355 $search = '' unless defined $search;
356 $self->{ text } =~ s/$search//g;
362 my $self = CORE::shift;
363 my $split = CORE::shift;
364 my $limit = CORE::shift || 0;
365 $split = '\s+' unless defined $split;
366 return [ split($split, $self->{ text }, $limit) ];
371 my ($self, $pattern) = @_;
372 return $self->{ text } =~ /$pattern/;
377 my ($self, $comparison) = @_;
378 return $self->{ text } eq $comparison;
388 Template::Plugin::String - Object oriented interface for string manipulation
392 # create String objects via USE directive
394 [% USE String 'initial text' %]
395 [% USE String text => 'initial text' %]
397 # or from an existing String via new()
398 [% newstring = String.new %]
399 [% newstring = String.new('newstring text') %]
400 [% newstring = String.new( text => 'newstring text' ) %]
402 # or from an existing String via copy()
403 [% newstring = String.copy %]
405 # append text to string
406 [% String.append('text to append') %]
408 # format left, right or center/centre padded
409 [% String.left(20) %]
410 [% String.right(20) %]
411 [% String.center(20) %] # American spelling
412 [% String.centre(20) %] # European spelling
414 # and various other methods...
418 This module implements a C<String> class for doing stringy things to
419 text in an object-oriented way.
421 You can create a C<String> object via the C<USE> directive, adding any
422 initial text value as an argument or as the named parameter C<text>.
425 [% USE String 'initial text' %]
426 [% USE String text='initial text' %]
428 The object created will be referenced as C<String> by default, but you
429 can provide a different variable name for the object to be assigned
432 [% USE greeting = String 'Hello World' %]
434 Once you've got a C<String> object, you can use it as a prototype to
435 create other C<String> objects with the C<new()> method.
438 [% greeting = String.new('Hello World') %]
440 The C<new()> method also accepts an initial text string as an argument
441 or the named parameter C<text>.
443 [% greeting = String.new( text => 'Hello World' ) %]
445 You can also call C<copy()> to create a new C<String> as a copy of the
448 [% greet2 = greeting.copy %]
450 The C<String> object has a C<text()> method to return the content of the
455 However, it is sufficient to simply print the string and let the
456 overloaded stringification operator call the C<text()> method
457 automatically for you.
461 Thus, you can treat C<String> objects pretty much like any regular piece
462 of text, interpolating it into other strings, for example:
464 [% msg = "It printed '$greeting' and then dumped core\n" %]
466 You also have the benefit of numerous other methods for manipulating
469 [% msg.append("PS Don't eat the yellow snow") %]
471 Note that all methods operate on and mutate the contents of the string
472 itself. If you want to operate on a copy of the string then simply
475 [% msg.copy.append("PS Don't eat the yellow snow") %]
477 These methods return a reference to the C<String> object itself. This
478 allows you to chain multiple methods together.
480 [% msg.copy.append('foo').right(72) %]
482 It also means that in the above examples, the C<String> is returned which
483 causes the C<text()> method to be called, which results in the new value of
484 the string being printed. To suppress printing of the string, you can
485 use the C<CALL> directive.
487 [% foo = String.new('foo') %]
489 [% foo.append('bar') %] # prints "foobar"
491 [% CALL foo.append('bar') %] # nothing
493 =head1 CONSTRUCTOR METHODS
495 These methods are used to create new C<String> objects.
499 Creates a new string using an initial value passed as a positional
500 argument or the named parameter C<text>.
503 [% msg = String.new('Hello World') %]
504 [% msg = String.new( text => 'Hello World' ) %]
508 Creates a new C<String> object which contains a copy of the original string.
510 [% msg2 = msg.copy %]
512 =head1 INSPECTOR METHODS
514 These methods are used to examine the string.
518 Returns the internal text value of the string. The stringification
519 operator is overloaded to call this method. Thus the following are
527 Returns the length of the string.
529 [% USE String("foo") %]
530 [% String.length %] # => 3
532 =head2 search($pattern)
534 Searches the string for the regular expression specified in C<$pattern>
535 returning true if found or false otherwise.
537 [% item = String.new('foo bar baz wiz waz woz') %]
538 [% item.search('wiz') ? 'WIZZY! :-)' : 'not wizzy :-(' %]
540 =head2 split($pattern, $limit)
542 Splits the string based on the delimiter C<$pattern> and optional C<$limit>.
543 Delegates to Perl's internal C<split()> so the parameters are exactly the same.
545 [% FOREACH item.split %]
549 [% FOREACH item.split('baz|waz') %]
553 =head1 MUTATOR METHODS
555 These methods modify the internal value of the string. For example:
557 [% USE str=String('foobar') %]
558 [% str.append('.html') %] # str => 'foobar.html'
560 The value of C<str> is now 'C<foobar.html>'. If you don't want
561 to modify the string then simply take a copy first.
563 [% str.copy.append('.html') %]
565 These methods all return a reference to the C<String> object itself. This
566 has two important benefits. The first is that when used as above, the
567 C<String> object 'C<str>' returned by the C<append()> method will be stringified
568 with a call to its C<text()> method. This will return the newly modified
569 string content. In other words, a directive like:
571 [% str.append('.html') %]
573 will update the string and also print the new value. If you just want
574 to update the string but not print the new value then use C<CALL>.
576 [% CALL str.append('.html') %]
578 The other benefit of these methods returning a reference to the C<String>
579 is that you can chain as many different method calls together as you
582 [% String.append('.html').trim.format(href) %]
584 Here are the methods:
586 =head2 push($suffix, ...) / append($suffix, ...)
588 Appends all arguments to the end of the string. The
589 C<append()> method is provided as an alias for C<push()>.
591 [% msg.push('foo', 'bar') %]
592 [% msg.append('foo', 'bar') %]
596 Removes the suffix passed as an argument from the end of the String.
598 [% USE String 'foo bar' %]
599 [% String.pop(' bar') %] # => 'foo'
601 =head2 unshift($prefix, ...) / prepend($prefix, ...)
603 Prepends all arguments to the beginning of the string. The
604 C<prepend()> method is provided as an alias for C<unshift()>.
606 [% msg.unshift('foo ', 'bar ') %]
607 [% msg.prepend('foo ', 'bar ') %]
609 =head2 shift($prefix)
611 Removes the prefix passed as an argument from the start of the String.
613 [% USE String 'foo bar' %]
614 [% String.shift('foo ') %] # => 'bar'
618 If the length of the string is less than C<$pad> then the string is left
619 formatted and padded with spaces to C<$pad> length.
625 As per L<left()> but right padding the C<String> to a length of C<$pad>.
629 =head2 center($pad) / centre($pad)
631 As per L<left()> and L<right()> but formatting the C<String> to be centered within
632 a space padded string of length C<$pad>. The C<centre()> method is provided as
633 an alias for C<center()>.
635 [% msg.center(20) %] # American spelling
636 [% msg.centre(20) %] # European spelling
638 =head2 format($format)
640 Apply a format in the style of C<sprintf()> to the string.
642 [% USE String("world") %]
643 [% String.format("Hello %s\n") %] # => "Hello World\n"
647 Converts the string to upper case.
649 [% USE String("foo") %]
650 [% String.upper %] # => 'FOO'
654 Converts the string to lower case
656 [% USE String("FOO") %]
657 [% String.lower %] # => 'foo'
661 Converts the first character of the string to upper case.
663 [% USE String("foo") %]
664 [% String.capital %] # => 'Foo'
666 The remainder of the string is left untouched. To force the string to
667 be all lower case with only the first letter capitalised, you can do
670 [% USE String("FOO") %]
671 [% String.lower.capital %] # => 'Foo'
675 Removes the last character from the string.
677 [% USE String("foop") %]
678 [% String.chop %] # => 'foo'
682 Removes the trailing newline from the string.
684 [% USE String("foo\n") %]
685 [% String.chomp %] # => 'foo'
689 Removes all leading and trailing whitespace from the string
691 [% USE String(" foo \n\n ") %]
692 [% String.trim %] # => 'foo'
696 Removes all leading and trailing whitespace and collapses any sequences
697 of multiple whitespace to a single space.
699 [% USE String(" \n\r \t foo \n \n bar \n") %]
700 [% String.collapse %] # => "foo bar"
702 =head2 truncate($length, $suffix)
704 Truncates the string to C<$length> characters.
706 [% USE String('long string') %]
707 [% String.truncate(4) %] # => 'long'
709 If C<$suffix> is specified then it will be appended to the truncated
710 string. In this case, the string will be further shortened by the
711 length of the suffix to ensure that the newly constructed string
712 complete with suffix is exactly C<$length> characters long.
714 [% USE msg = String('Hello World') %]
715 [% msg.truncate(8, '...') %] # => 'Hello...'
717 =head2 replace($search, $replace)
719 Replaces all occurences of C<$search> in the string with C<$replace>.
721 [% USE String('foo bar foo baz') %]
722 [% String.replace('foo', 'wiz') %] # => 'wiz bar wiz baz'
724 =head2 remove($search)
726 Remove all occurences of C<$search> in the string.
728 [% USE String('foo bar foo baz') %]
729 [% String.remove('foo ') %] # => 'bar baz'
731 =head2 repeat($count)
733 Repeats the string C<$count> times.
735 [% USE String('foo ') %]
736 [% String.repeat(3) %] # => 'foo foo foo '
740 Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
744 Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
746 This module is free software; you can redistribute it and/or
747 modify it under the same terms as Perl itself.
757 # perl-indent-level: 4
758 # indent-tabs-mode: nil
761 # vim: expandtab shiftwidth=4: