Thanks for everyone's help so far. Sorry for not being clear originally 
but it's not that I want alternatives to using replace - I know there's 
plenty of better solutions for the small example I gave - it's that I 
wanted to know if there was some trick to escaping $ (and possibly other 
operators) so the second argument is taken at "face value". I'm pretty 
sure I have to use replace in the real world problem I have (basically a 
search and replace on manually inserted placeholders within text).

Looks like I'll make a vmethod for quotemeta. Was just hoping I could 
fix this small problem without needing to edit the API!

Cheers all.

On 21/04/2010 19:29, Andy Wardley wrote:
> Travis Basevi wrote:
>  > Yes, I know that solution,
>
> Sorry, I totally missed that in your original message.
>
>  > but lets say the text comes from a database
>  > or some other source rather than being hardcoded in the template. Is
>  > there a more general/correct solution than something along the lines of:
>  >
>  > b.replace('_err_', a.replace('$','\$'));
>
> Ah, I see. I thought that was easy work for $50 million!
>
> I think Dave's got it right in terms of counting the backslashes.
>
> b.replace('_err_', a.replace('$','\\\$'));
>
> But I would be inclined to add a custom virtual method that does it all
> in Perl space. I typically use '.format' for this kind of thing:
>
> package My::Template;
> use base 'Template';
>
> sub new {
> my $class = shift;
> my $self = $class->SUPER::new(@_);
> my $context = $self->context;
>
> $context->define_vmethod(
> item => format => sub {
> sprintf($_[1], $_[0])
> }
> );
>
> return $self;
> }
>
> package main;
> my $tt = My::Template->new(...);
> ...etc...
>
> Then you can write:
>
> [% a = 'this problem will cost me $50 million to fix';
> b = 'WARNING: %s';
> a.format(b);
> %]
>
> I recall going to add this as a core virtual method at some point in
> the past, but I couldn't decide if it made more sense as b.format(a)
> or a.format(b). I guess I must have stalled before reaching any
> decision.
>
> Now that I look at it again, I think it makes more sense as b.format(a),
> otherwise you're limited to only one argument. But for that matter, it
> should probably just be called .sprintf
>
> [% format = "hello %s, the time is %s on %s";
> format.sprintf(username, time, date)
> %]
>
> Then the implementation is even simpler:
>
> $context->define_vmethod(
> item => format => sub {
> sprintf(shift, @_)
> }
> );
>
> The other possibility is to use the existing format filter.
>
> [% a | format(b) %]
>
> But be warned that it's a line-oriented filter so if your 'a' has any
> newlines in it then the filter will be applied to each line:
>
> [% a = "Oh Noes!\nThis will cost me $50 million to fix";
> b = "WARNING: %s";
> a | format(b);
> %]
>
> This will output:
>
> WARNING: Oh Noes!
> WARNING: This will cost me $50 million to fix
>
> HTH
> A
>




This email, including attachments may be privileged, confidential and is 
intended exclusively for the addressee. The views expressed may not be official 
policy, but the personal views of the originator. If you have received this 
email in error please notify the sender and delete it from your system.  Emails 
are not secure and may contain viruses.  No liability can be accepted for 
viruses that might be transferred by this email or any attachment.


_______________________________________________
templates mailing list
[email protected]
http://mail.template-toolkit.org/mailman/listinfo/templates

Reply via email to