All,
There seems to be occasional discussion on this list about
[% str = 'foobar' %]
[% str.replace('(foo)(bar)', '$2$1' %]
not working. You get a literal '$2$1' inserted in to your document,
instead of the expected 'barfoo'.
This sort of functionality is often desirable. For example, you might
want to filter text to automatically add links to other documents. Say,
converting text that matches 'rt#(\d+)' in to links to an RT issue
tracking system.
At the moment there seem to be two options.
1. Do it in a [% PERL %] block.
2. Write a custom filter to look for your magic string and do the
replacement, and filter your text through this filter.
The first is not necessarily a good option. EVALPERL might not be
enabled in your TT install, and it assumes that the person writing the
templates is familiar with Perl, which might not be the case.
The second can rapidly get unwieldy if you have lots of filters that you
want to run your text through. For example, the organisation I work for
has at least three different ticketing systems, depending on which part
of the business you work for, to say nothing of all the other sites that
it might be useful to link to.
So, to get to the point... I'm looking for feedback for
Template::Plugin::Subst. I've included an early draft at the bottom of
this message.
If you install it, you can use it like so:
[% USE Subst %]
[% FILTER $Subst
pattern='rt#(\d+)'
replacement='<a href="/rt.cgi?t=$1">$1</a>' %]
Here's a ticket ref: rt#1234
And here's another one: rt#4321
[% END %]
or chain several of them together;
[% USE rt = Subst
pattern='rt#(\d+)'
replacement='... $1 ...' %]
[% USE isbn = Subst
pattern='isbn#(\d+)'
replacement='... $1 ...' %]
[% USE svn = Subst
pattern='svn#(\d+)'
replacement='... $1 ...' %]
[% text | $rt | $isbn | $svn %]
if, for some reason, you were expecting 'text' to contain references to
RT tickets, ISBN numbers (which you might point at Amazon), and
Subversion repository revision numbers.
Limitations:
* assumes the match is going to be global. That should really be
an option.
* ditto for any other options you can pass to s///
* Will probably do bad things if your text contains literal
'$1', '$2', etc
I've got to clean it up, write some more tests, and update the
documentation before I send it off to CPAN. But before I do.
First, is this useful?
Second, is there any other functionality people would like to see?
N
package Template::Plugin::Subst
use Template::Plugin::Filter;
use base qw(Template::Plugin::Filter);
use Test::More; # for diag()
# Boilerplate
sub init {
my $self = shift;
$self->{_DYNAMIC} = 1;
return $self;
}
# More or less boilerplate
sub filter {
my($self, $text, $args, $config) = @_;
$config = $self->merge_config($config);
my $pattern = $config->{pattern};
my $replacement = $config->{replacement};
$text = subst($text, $pattern, $replacement);
return $text;
}
sub subst {
my($text, $pattern, $replacement) = @_;
if($text !~ m/$pattern/) {
# diag "text does not match '$pattern', returning";
return $text;
}
# If there are no subgroups then it's a simple search/replace
if($#- == 0) {
# diag "No subgroups found, doing simple search/replace";
$text =~ s/$pattern/$replacement/g;
return $text;
}
# First, save the original text, and what was matched
my $saved_text = $text;
my $PREMATCH = substr($saved_text, 0, $-[0]);
my $MATCHED = substr($saved_text, $-[0], $+[0] - $-[0]);
my $POSTMATCH = substr($saved_text, $+[0]);
# Save the positions where we matched
my @saved_match_start = @-;
my @saved_match_end = @+;
# diag "PREMATCH : <<$PREMATCH>>";
# diag "MATCHED : <<$MATCHED>>";
# diag "POSTMATCH: <<$POSTMATCH>>";
# Now do the s///. This will leave placeholders (literally, '$1', '$2',
# etc, in the replaced text.
# diag "Doing s///";
$MATCHED =~ s/$pattern/$replacement/;
# diag "MATCHED: <<$MATCHED>>";
foreach my $i (1..$#saved_match_start) {
my $backref = substr($saved_text,
$saved_match_start[$i],
$saved_match_end[$i] - $saved_match_start[$i]);
$MATCHED =~ s/\$$i/$backref/g;
}
# diag "Fixed up backrefs";
# diag "MATCHED: <<$MATCHED>>";
return $PREMATCH . $MATCHED . subst($POSTMATCH, $pattern, $replacement);
}
_______________________________________________
templates mailing list
[email protected]
http://lists.template-toolkit.org/mailman/listinfo/templates