The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Text::Template::Base - Expand template text with embedded Perl

SYNOPSIS

 use Text::Template::Base;

DESCRIPTION

This module is an enhanced version of M-J. Dominus' Text::Template version 1.45.

I have tried to contact M-J. to get my patches (included in this distribution in the patches/ directory) into Text::Template but never got an answer.

For usage information see Text::Template.

DIFFERENCES COMPARED TO Text::Template 1.45

The OUT function (to be used within templates)

The OUT function serves a similar purpose as $OUT. It is automatically installed in the package the template is evaluated in. Hence a template can look like this:

        Here is a list of the things I have got for you since 1907:
        { foreach $i (@items) {
            OUT "  * $i\n";
          }
        }

The advantage of the function over $OUT is that it wastes less memory. Suppose you have a very long list of items. Using $OUT it is first accumulated in that variable and then appended to the resulting string. That means it uses twice the memory (for a short time). With the OUT function each piece of generated text is immediately appended to the resulting string.

But the main advantage lies in using the OUT function in combination with the OUTPUT option to fill_in. Now a piece of output is directly put out and nothing at all accumulated.

There is also a drawback. $OUT is an ordinary variable and can be used as such. This template cannot be easily converted to using OUT:

        Here is a list of the things I have got for you since 1907:
        { foreach $i (@items) {
            $OUT .= "  * $i\n";
            if( some_error ) {
              # forget the output so far
              $OUT = "An error has occurred";
              last;
            }
          }
        }

NOTE, the OUT function doesn't work with the SAFE option.

The OUTPUT parameter to new() and fill_in

Text::Template allows for a file handle to be passed as OUTPUT parameter. Each chunk of output will be written directly to this handle.

With this module a subroutine can be passed instead of the file handle. Each chunk of output will be passed to this function as the only parameter.

 $template->fill_in(OUTPUT => sub { print $_[0] }, ...);

The FILENAME parameter to new() and fill_in

When Text::Template generates error messages it tries to include the file name and line number where the error has happened. But for some template types the file name is not known. In such cases Text::Template simply uses the string template. With the FILENAME parameter this string can be configured.

The EVALCACHE parameter to new() and fill_in

Normally Text::Template calls eval each time to evaluate a piece of Perl code. This can be a performance killer if the same piece is evaluated over and over again.

One solution could be to wrap the piece of code into a subroutine, have Perl compile that routine only once and use it many times.

If EVALCACHE is given Text::Template does exactly that. A piece of perl code is wrapped as a subroutine, compiled and the resulting code references are saved in the EVALCACHE with the actual perl text as key.

EVALCACHE does not currently work if the SAFE option is used.

There are a few pitfalls with that method that have to be looked out by the template programmer. Suppose you have that piece of code in a template:

        my $var = 5;
        sub function {
          return $var++;
        }
        $OUT.=function() for( 1..3 );

That piece will producess the string 567 in $OUT each time it is evaluated. But if it is wrapped into a subroutine it looks like:

        sub {
          my $var = 5;
          sub function {
            return $var++;
          }
          $OUT.=function() for( 1..3 );
        };

If that anonymous function is called several times it produces 012, 345 and so on. The problem is that named functions (like function) are created at compile time while anonymous functions (like the outer sub) at run time. Hence, the $var my-variable is not available in function. Perl solves thar conflict by creating a separate variable $var at compile time that is initially undef. Evaluated in numerical context is gives 0.

So, how can the code fragment be converted so that the function is created at runtime. There are 2 ways. Firstly, you can use function references:

        sub {
          my $var = 5;
          my $function = sub {
            return $var++;
          };
          $OUT.=$function->() for( 1..3 );
        };

Now both the inner and the outer functions are anomymous and both are created at runtime. But calling function as $function->() may not be convenient. So, the second way uses a localized symbol:

        sub {
          my $var = 5;
          local *function = sub {
            return $var++;
          };
          $OUT.=function() for( 1..3 );
        };

For more information see http://perl.apache.org/docs/general/perl_reference/perl_reference.html#my____Scoped_Variable_in_Nested_Subroutines

The #line directive in templates

Correct line numbers are crucial for debugging. If a template is fetched from a larger file and passed to Text::Template::Base as string Text::Template::Base doesn't know at which line of the larger file the template starts. Hence, it cannot produce correct error messages.

The solution is to prepend the template string (assuming default delimiters are used) with

        {#line NUMBER}

where NUMBER is the actual line number where the template starts.

If custom delimiters are used replace the braces by them. Assuming [% and %] as delimiters that directive should look:

        [%#line NUMBER%]

Note that there must not be any other character between the opening delimiter and the #line and between the NUMBER and the closing delimiter not even spaces. Also, there must be only one space between #line and NUMBER.

The #line directive works not only at the beginning of a template. Suppose you have a larger template and have cut out some parts prior to passing it to Text::Template::Base as a string. Replace these parts with correct #line directives and your error messages are correct.

AUTHOR

Torsten Foertsch, <torsten.foertsch@gmx.net>

Most of this module is borrowed from Text::Template by Mark-Jason Dominus, Plover Systems