NAME

GT::Template - simple template parsing module


SYNOPSIS

    use GT::Template;
    my $var = GT::Template->parse('file.txt', { key => 'value' });
    ...
    print $var;

or

    use GT::Template;
    GT::Template->parse_print('file.txt', { key => 'value' });


DESCRIPTION

GT::Template provides a simple way (one line) to parse a template (which can be either a file or a string) and make sophisticated replacements.

It supports simple replacements, conditionals, function calls, including other templates, and more.

Additionally, through using pre-compiled files, subsequent parses of a template will be very fast.

Template Syntax

The template parser replaces tags with content. By default a tag is anything enclosed between <% and %>. These can be changed by specifying a value to the begin() and end() methods.

Variable Substitution
At the simplest level of GT::Template are simple variable replacements such as:
    You are <%age%> years old.

where age would be replaced with a value.

Sets
You can set values from within a template by using:
    <%set Title = 'Login'%>

and now <%Title%> will be equal to Login. This is especially useful for includes, where you could, for example, set a Title variable to a string that will be displayed in an included template.

You can also set one variable to the value of another, such as:

    <%set title = $return_title%>

This will set the variable ``title'' with the value of the variable ``return_title.''

Operators
GT::Template is capable of performing some basic math calculations and one string-multiple function in templates displaying the results in the parsed template.

For example, if the 'age' variable is 15, the following tag:

    <%age + 10%>

will display 25 in the template. Besides addition there are the following operators, which work as expected: - * / % (remainder) ^ (raised to the power of)

The following operators are also worth explaining:


    i/
    /N
    ~ (Remainder difference)
    x (String multiplier)

i/ performs integral division between the two numbers. For example, '4' i/ 3 will result in 1. '100' i/ 3 would result in 33, etc.

/N does not actually use a literal N, instead N should be replaced by a number. The result will be formatted (and rounded) to N decimal places. For example, '4' /3 3 would result in: 1.333, while '5' /3 3 would give you: 1.667. '3' /3 3 would be 1.000.

Note that i/ and /0 are not the same, as can be illustrated here: 38 i/ '3.8' => 12 - becomes 38 i/ 3 38 /0 '3.8' => 10 - 38 / 3.8 is calculated, then rounded with 0 decimal place precision.

You should be sure of which one you mean to use, or you may end up with unexpected results.

~ is used to get a remainder difference. Where 8 % 5 would return 3, 8 ~ 5 will return 2. This is calculated as the divisor (5) minus the remainder (3). This is useful when generating tables in a loop - when you hit the end of the loop, you want to be able to put an empty cell with a colspan of however many rows are left. Something like: <%row_num ~ 5%> will give you the proper value.

As mentioned, there is also one string operator, 'x'. When you use 'x', the variable (or value as we'll see in a second) will be displayed ``n'' times, where ``n'' is the integral value of the right hand side.

Assuming that the 'name' variable is 'Jason', this tag:

    <%name x 2%>

will display JasonJason in the parsed template. Like this, it isn't all that useful because you could simply put <%name%><%name%> in your template. However, the right hand side may instead use the value of a variable, such as in this example:

    <%name x $print%>

Assuming that 'name' is still 'Jason', and that 'print' is 3, this would display:

    JasonJasonJason

Though this is useful as is, this is taken a step furthur: the first does not always have to be a variable. By using 'single quotation marks' or ``double quotation marks'' we can display fixed text a variable number of times.

For example:

    <%'My Text' x $print%>

Again assuming that the variable print is 3, this will print:


    My TextMy TextMy Text

this comes in handy when doing things like indentation.

Note that what we want to use for ``My Text'' might contain `` or ' characters. If it only contains '', and not ', it is advisible to use ' instead of `` as the string delimiter. If, however, you need to use the same quotes inside the string as you use to delimit the string, you should precede the quotes with a blackslash (\) and any backslashes with a backslash. For example, if you wanted to display the three characters \''' thirty times, you would have to write it as one of the following two lines:

    <%"\\'\"" x 30%>
    <%'\\\'"' x 30%>

Hopefully such occurances are rare, but not impossible; hence the support for using either ' or `` as the delimiting character.

Set + Operators
You can add, subtract, etc. to your variables with the following syntax:
    <%set variable += 3%>

+= can be changed to the following:

    += - Adds to a variable
    -= - Subtracts from a variable
    *= - Multiplies a variable
    /= - Divides a variable
    %= - Set a variable to a remainder
    ^= - Raise a variable to a power
    .= - Appends to a string
    x= - "Multiplies" a string - "ab" x 3 is "ababab"

Conditionals
You can use conditionals if, ifnot (or unless), elseif, and else as in:
    <%if age%>
        You are <%age%> years old.
    <%elseif sex%>
        You are <%sex%>.
    <%else%>
        I know nothing about you!
    <%endif%>
    <%ifnot login%>
        You are not logged in!
    <%endif%>
    <%unless age%>
        I don't know how old you are!
    <%endif%>

If you like you may use elsif instead of elseif (drop the 'e'). unless and endunless are aliases for ifnot and endif, respectively, and may be used interchangeably.

All conditionals must be ended with an endif tag, although may contain any number of elseif conditionals and/or a single else conditional between the if and endif tags.

Conditionals may be nested within each other, to arbitrary depth:

    <%if age%>
        You are <%age%> years old
        <%if sex%>
            and you are <%sex%>
        <%endif%>
    <%endif%>

Comparisons
Inside conditionals you can use <, >, <=, >=, ==, !=, lt, gt, le, ge, eq, ne, contains, starts, and ends. This allows you to do things like:
    <%if age == 15%>
        You're 15!
    <%endif%>

where the == can be replaced with any operator listed above. If the right hand side of the equation starts with a '$', the string will be interpolated as a variable. If you wish to use a string starting with a literal $, you can avoid this interpolation by adding quotes around the right hand value. The left hand side is always a variable.

lt, gt, le, ge, eq, and ne are he alphabetical equivelants of <, >, <=, >=, ==, and !=, respectively. In terms of less-than and greater-than comparisons, the comparison is similar to a dictionary: aa is less than b, but greater than a; 10 is greater than 1, but less than 2; Z is less than a, due to capitalization (unless using ilt, ige, etc.). contains will be true if the variable contains the right-hand side. starts and ends will be true if the variable starts with, or ends with, respectively, the right-hand value.

There are also case-insensitive versions of the string comparisons - they are: ilt, igt, ile, ige, ieq, ine, icontains, istarts, and iends. These comparisons work exactly like the versions _without_ the i except that the comparison is case-insensitive.

start, istart, end, and iend are aliases for the comparison with an added s. like and ilike are deprecated aliases for contains and icontains and should no longer be used.

Logical Operators
If statements (including elseif statements) may contain multiple conditions using one of the two booleans operators or and and. For example:
    <%if age and sex and color%>
        I know your age, sex and hair color.
    <%else%>
        I don't have enough information about you!
    <%endif%>
    <%if age < 10 or age > 90 or status eq banned%>
        You are not permitted to view this page.
    <%endif%>

It should be noted that it is currently not possible to mix both or and and in a single if statement - you may, however, use the same boolean multiple times in a single statement. (Brackets) are also not currently supported.

Internally, if statements will be short-circuited as soon as possible. That means that for the following tag: <%if foo = 1 or foo = 2 or foo = 3%> the following will occur: First, variable ``foo'' will be tested to see if it is numerically equal to 1. If it is, the rest of the checks are aborted since the if will pass regardless. If it is not, foo = 2 will be checked, and if true, will abort the next check, and so on until a condition is true or the end of the list of statements is encountered.

Likewise with and, except that with and the parser will stop checking as soon as the first false value is encountered (since a false value means the entire condition will be false).

Loops
Inside your template you can use loops to loop through an array reference, or code reference. If using an array reference, each element should be a hash reference, and when using a code reference every return should be a hash reference - or undef to end the loop. The variables in the hash reference will then be available for that iteration of the loop.

For example:

    <%loop people%>
        <%if name eq 'Jason'%>
            I have <%color%> hair.
        <%else%>
            <%name%> has <%color%> hair.
        <%endif%>
    <%endloop%>

would loop through all values of pens, and for each one would print the sentence substituting the color of the pen. Also, inside your loop you can use the following tags:

    <%row_num%> - a counter for what row is being looped, starts at 1.
    <%first%>   - boolean value that is true if this is the first row, false otherwise.
    <%last%>    - boolean value that is true if this is the last row, false otherwise.
    <%inner%>   - boolean value that is true if this is not first and not last.
    <%even%>    - boolean value is true if row_num is even.
    <%odd%>     - boolean value is true if row_num is odd.

You could use even and odd tags to produce alternating colors like:

    <%loop results%>
        <tr><td bgcolor="<%if even%>white<%else%>silver<%endif%>">..</td></tr>
    <%endloop%>

Also, you can use <%lastloop%> to abort the loop and skip straight to the current loop's <%endloop%> tag, and <%nextloop%> to load the next loop variables and jump back to the beginning of the current loop.

The 6 built-in variables (row_num, first, last, ...) and any variables set via the loop variable will only be available for the current loop iteration, after which the variables of the next loop iteration will be set, or, for variables that exist in one iteration but not the next, the variables that existed prior to the loop being called will be restored.

escape_url escapeURL
Most variable will already be escaped for html viewing by default. Being able to use these variables on one page in a URL and in the html page can be a bit tricky. If you are using escape mode, this function simply URL encodes the variable. Otherwise, this function unescapes html escapes and URL encodes the variable.
    <%escape_url somevar%>

escape_html escapeHTML
Whether or not in escape mode, this directive will HTML escape the variable. The variable will _not_ be escaped twice in escape mode.
    <%escape_html somevar%>

unescape_html unescapeHTML
The directive will unescape the HTML escapes &amp;, &lt;, &gt;, and &quot;

escape_js escapeJS
This directive will safely escape a javascript variable so that it can be used inside a javascript string delimited with either ``double quotes'' or 'single quotes.'
    <%escape_js somevar%>

nbsp
This directive will display the tag with all whitespace in a variable converted to non-breaking spaces (&nbsp;). This is useful when attempting to display something accurately which may contain spaces, or when attempting to ensure that a value does not wrap over multiple lines.

Includes
You can include other files. Any tags inside the includes will be evaluated. You can also have includes inside of includes, inside if statements, or even inside loops. The following tag:
    <%if info%>
        <%include info.txt%>
    <%else%>
        <%include noinfo.txt%>
    <%endif%>

will include either the file info.txt (if info is true) or noinfo.txt (if info is false or not set). It must be in the template's root directory which is defined using $obj->root, or '.' by default.

A useful application of the include tag is to include files inside a loop, as in:

    <%loop people%>
        <%include person.txt%>
    <%endloop%>

Another useful example is in including a common header or footer to all pages. If, for example, you have a header.htm that you wish to be included, but it needs a variable title, you could combine the include with a set, such as:

    <%set Title = 'Login'%>
    <%include header.htm%>

and then in your header.htm:

    <html>
        <head>
            <title><%Title%>
            </title>
        </head>

This would allow you to have different titles, but still include the same header template on each page.

Functions
You can call functions in either the variable substitution or in the comparison. The function must reside in a package, and you must do the full qualification.
    A script header normally looks like <%CGI::header%>

which would call &CGI::header(). You can pass arguments to this as in:

    A script header normally looks like <%CGI::header ('text/html')%>.

Also, you can pass any currently available template variable to the function using:

    <%CGI::header ($variable)%>

Multiple arguments may be passed by comma separating the arguments, as in: <%Mypackage::mysub($age, 'Title')%>

If a function returns a hash reference, those values will be added to the current substitution set. Suppose you have a function:

    package Mypackage;
    sub load_globals {
        ..
        return { age => 15, color => red };
    }

You could then do:

    <%Mypackage::load_globals%>
    You are <%age%> years old, with <%color%> hair!

Functions are loaded while parsing, so calling the function with different arguments (to set your variables to different values) is possible.

Since package names can make functions rather long and ugly, you can call ->parse() with an ``alias'' key in the options hash. This key should contain shortcut => function pairs. For example, if you want to call Foo::Bar::blah() in your template, you could pass: asdf => 'Foo::Bar::blah', and when <%asdf%> or <%asdf(...)%> is encountered, Foo::Bar::blah will be called.

Comparisons with Functions
You can combine use a function for an if/elseif statement value, as in:
    <%if age == My::years_old%>
        You are the same age as me!
    <%endif%>

which would call My::years_old() and compare the return value to the value of the ``age'' variable.

Sets with Functions
You may use a function call as the value of a ``set'' instruction to set a template variable based on the return value of the function. The following code will set a variable named ``age'' to the return value of Mypackage::age():
    <%set age = Mypackage::age%>

Arguments passed are the same as the arguments to a regular function.

Parse Options

The third argument to parse is an optional hash of options. Valid options include:

root => path
This sets the path to where the template files are.

string => $template
Passing in string => $template will use $template as your template to parse, rather then load from a file.

print => 0
If set to 1, this will print the template to the currently selected filehandle (STDOUT), and returns 1. If set to 0 (default), returns parsed tempalte.

compress => 0
Setting compress => 1 will compress all white space generated by the program. This is great for HTML, but shouldn't be used for text templates.

strict => 0
If set to 0, any template errors will not be displayed. The default is 1. This means if you have a tag <%mytag%> and mytag is not in your list of variables, with strict on, it will get replaced with an Unknown tag error, with strict off it will get replaced with an empty string.

escape => 0
This will HTML escape all variables before they are printed. Scalar references will be dereferenced and not escaped.

The forth option to parse is an optional hash of aliases to set up for functions. The key should be the function call to alias and the value should be the function aliased. For example:

    print GT::Template->parse(
        'file.htm',
        { key => 'value' },
        { compress => 1 },
        { myfunc => 'Long::Package::Name::To::myfunc' }
    );

Now in your template you can do:

    <%myfunc('argument')%>

Which will call Long::Package::Name::To::myfunc.


EXAMPLES

Some examples to get you going:

    # Parse a string in $template and replace <%key%> with 'value'.
    print GT::Template->parse('stringname', { key => 'value' }, { string => $template });
    # Compress output of template, print it as it is parsed, not after entirely parsed.
    GT::Template->parse_print('file.txt', { key => 'value' }, { compress => 1 });
    # Don't display warnings on invalid keys.
    print GT::Template->parse('file.txt', { key => 'value' }, { strict => 0 });
    # Create a template object using custom settings.
    my $obj = new GT::Template({
        root => '/path/to/templates',
        compress => 0,
        strict => 0,
        begin => '<!',
        end => '!>'
    });
    my $replace = {
        a => 'b',
        c => 'd',
        e => 'f'
    };
    $obj->parse_print('file2.txt', $replace);


COPYRIGHT

Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved. http://www.gossamer-threads.com/


VERSION

Revision: $Id: Template.pm,v 2.109 2004/05/05 00:57:47 jagerman Exp $