discourse-legacysite-perl/site/glist/lib/GT/Template/Tutorial.pod
2024-06-17 22:24:05 +10:00

1017 lines
31 KiB
Plaintext

=head1 NAME
GT::Template::Tutorial - Gossamer Threads template syntax documentation
=head1 Template Syntax
At its most basic level, the template parser replaces tags with content. By
default a tag is anything enclosed between C<E<lt>%> and C<%E<gt>>. For the
purposes of this document, these two values will be assumed.
=head2 Variable Substitution
At the simplest level of GT::Template templates are simple variable
replacements. For example, consider the following template code:
You are <%age%> years old.
This would be displayed with '<%age%>' replaced with a value. For example, if
C<age> was given a value of 35, the above would be displayed as:
You are 35 years old.
A more complex form of variable access is also available, which is covered
later in the
L<Advanced variables using references|/"Advanced variables using references">
section of this document.
=head2 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
C<include>s, 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."
Note that when using " " for a string, you may include variables by using the
$variable or ${variable} syntaxes, such as:
<%set title = "A $main_title page: ${secondary_title}Z"%>
Additionally, the sequence "\n", "\t", and "\r" produce a linefeed character,
tab, and carriage return, respectively. Additionally, a \ may precede any
non-letter/word character to mean just the character:
<%set price_display = "Price:\n\tTotal: \"\$3.40\""%>
which would set price_display to:
Price:
Total: "$3.40"
Note that the interpolation of variables and \ escapes do *not* apply when
using 'single quotes' as the string delimiter. In such cases, only \\ and \'
have a special meaning - they are used for a literal \ and ' character.
=head2 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 C<E<lt>%name%E<gt>E<lt>%name%E<gt>> 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 C<print> is 3, this will print:
My TextMy TextMy Text
this comes in handy when doing things like indentation.
The same string quoting interpolation rules mentioned in L</Sets> apply here -
both " and ' are accepted as delimiters, with different interpolation rules.
=head2 Set modifiers
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"
||= - sets a variable if not already set
&&= - sets a variable if already set
=head2 Set + Operators
You can combine the above operator functions with sets (including sets with modifiers) by simply adding C<set foo => to the beginning of the operator tag. For example:
<%set foo += 3 * 3%> # foo is now set to whatever it was, + 9
<%set foo *= 3 + 3%> # foo has been multiplied by 9
<%set foo = $bar /0 2%> # foo is now set to half of $bar, rounded to an integer (see /N above)
=head2 Conditionals
You can use conditionals C<if>, C<ifnot> (or C<unless>), C<elseif>, and C<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 C<elsif> instead of C<elseif> (drop the 'e').
C<unless> and C<endunless> are aliases for C<ifnot> and C<endif>, respectively,
and may be used interchangeably.
All conditionals must be ended with an C<endif> tag, although may contain any
number of C<elseif> conditionals and/or a single C<else> conditional between
the C<if> and C<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%>
=head2 Comparisons
Inside conditionals you can use C<E<lt>>, C<E<gt>>, C<E<lt>=>, C<E<gt>=>,
C<==>, C<!=>, C<lt>, C<gt>, C<le>, C<ge>, C<eq>, C<ne>, C<contains>, C<starts>,
and C<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.
C<lt>, C<gt>, C<le>, C<ge>, C<eq>, and C<ne> are the alphabetical equivelants
of C<E<lt>>, C<E<gt>>, C<E<lt>=>, C<E<gt>=>, C<==>, and C<!=>, respectively.
In terms of less-than and greater-than comparisons, the comparison is similar
to a dictionary: C<aa> is less than C<b>, but greater than C<a>; C<10> is
greater than C<1>, but less than C<2>; C<Z> is less than C<a>, due to
capitalization (unless using C<ilt>, C<ige>, etc.). C<contains> will be true
if the variable contains the right-hand side. C<starts> and C<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:
C<ilt>, C<igt>, C<ile>, C<ige>, C<ieq>, C<ine>, C<icontains>, C<istarts>, and
C<iends>. These comparisons work exactly like the versions _without_ the i
except that the comparison is case-insensitive.
C<start>, C<istart>, C<end>, and C<iend> are aliases for the comparison with an
added C<s>. C<like> and C<ilike> are deprecated aliases for C<contains> and
C<icontains> and should no longer be used.
=head2 Logical Operators
If statements (including elseif statements) may contain multiple conditions
using one of the two booleans operators C<or> and C<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 C<or> and
C<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 C<and>, except that with C<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).
=head2 Loops
Inside your template you can use loops to loop through an array reference, code
reference, or through a fixed set of numbers. If using an array reference, each
element should be either a hash reference or a scalar value, and when using a
code reference every return should be a hash reference or scalar value, or
C<undef> to end the loop. The variables in the hash reference will then be
available for that iteration of the loop, or, if using scalar values, the value
will be available as the <%loop_value%> variable.
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 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.
When using array reference-based loops (which are much more common than and
preferred to the alternative code reference-based loops), you can use the
C<loopvar.length> variable which will contain the number of items contained
within the loop.
To loop through a particular range of numbers, you can use the following syntax:
<%loop 1 to 5%>
...
<%endloop%>
This can alternatively be written as:
<%loop 1 .. 5%>
...
<%endloop%>
Additionally, either or both of the two values may be a variable, such as:
<%loop $start to $finish%>
...
<%endloop%>
Inside the loop, the current value is accessible via the <%loop_value%>
variable, as if you were simply looping over an array of integers. The looping
always occurs in increments of C<1>, and the start and end values will have any
fractional value truncated.
=head2 Filters
Filters can be used to alter the appearance of a tag. The general format of
a filter is:
<%filtername variable%>
Multiple filternames can be chained together as well, such as:
<%filtername1 filtername2 filtername3 variable%>
The filter closest to the variable name will be applied first. In the above
example, that means C<filtername3> will be applied, then
C<filtername2> applied to the result, then C<filtername1> applied to that
result.
The filters available include:
=over 4
=item escape_html
This filter will perform HTML-escaping of the variable. Specifically,
C<E<lt>>, C<E<gt>>, C<&>, and C<"> are converted to their HTML equivelants
(C<&lt;>, C<&gt;>, C<&amp;>, and C<&quot;>, respectively).
Assuming that C<somevar> contains the value C<abc&def"ghi>, the following:
<%escape_html somevar%>
will become:
abc&amp;def&quot;ghi
If the template parser has escape mode turned on, this would cause variables to
be escaped *twice* -- unless, of course, the variable is passed as a scalar
reference.
=item unescape_html
This filter will unescape the HTML escapes C<&amp;>, C<&lt;>, C<&gt;>, and
C<&quot;> back to their original forms of C<E<lt>>, C<E<gt>>, C<&>, and C<">,
respectively.
=item escape_url
When adding a value to a URL is necessary, C<escape_url> can be used to convert
characters other than alphanumeric (a-z, A-Z, 0-9) C<.>, and <-> to the
URL-escaped %XX form (where XX is a two-digit hexadecimal value).
For example, if you want to use the tag C<E<lt>%name%E<gt>> in a URL, it is
recommended to instead use C<E<lt>%escape_url name%E<gt>>. In particular, this
avoids the possibility of the CGI parameters being passed incorrectly when a
variable contains letters such as C<?>, C<;>, C<=>, etc.
=item unescape_url
This filter performs the opposite of escape_url - that is, any sequence of
C<%XX>, where C<XX> is any two hexadecimal characters, and the C<+> character
will be converted to the appropriate character - a single space in the case of
the C<+>.
=item escape_js
This filter will safely escape a javascript variable so that it can be used
inside a javascript string delimited with either "double quotes" or 'single
quotes'. Specifically, it puts a C<\> in front of every C<\>, C<'> and C<">
character and converts newlines to C<\n>.
var javascriptVariable = '<%escape_js somevar%>';
=item nbsp
This filter will display the variable with all whitespace converted to HTML
non-breaking space escapes (C<&nbsp;>). This is particularly useful when
attempting to display something accurately which may contain spaces, or when
attempting to ensure that a value containing spaces does not wrap over multiple
lines.
=item uc
=item lc
These filters display the variable with all letters changed to uppercase
(C<uc>) or lowercase (C<lc>).
=item ucfirst
=item lcfirst
These filters convert the first character of the variable to uppercase
(C<ucfirst>) or lowercase (C<lcfirst>).
=back
Some filter examples, assuming the following variables have been set:
var1 => "<html>",
var2 => "test&lt;b&gt;&amp;&lt;/b&gt;two",
var3 => "test't<hr>ee",
fname => "john",
lname => "DOE"
Examples:
Template code --> Becomes
============= =======
<tag attr="<%escape_html var1%>"> --> <tag attr="&lt;html&gt;">
<%unescape_html var2%> --> test<b>&</b>two
var jsVar = '<%escape_js var3%>'; --> var jsVar = 'test\'three';
<a href="a?f=<%escape_url unescape_html var2">
--> <a href="a?f=test%3Cb%3E%26%3C%2Fb%3Etwo">
<a onclick="jsVar = '<%escape_html escape_js var3%>'">
--> <a onclick="jsVar = 'test\'t&lt;hr&gt;ee'">
=head2 Includes
You can include other files. Any tags inside the includes will be evaluated as
if the content of the included file were included in the current file (although
there is one exception: unclosed if tags inside the include will be implicitly
ended). Includes can occur anywhere - inside if statements, for loops, other
includes, etc. 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 C<include> with a C<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.
GT::Template also supports including a file based on the value of a variable by
specifying the variable name (starting with a $) for the filename:
<%include $var%>
This allows for more powerful include abilities. For example, if you wanted
to have a single outer template which includes another, variable template you
could use an outer template (for the purposes of this example, assume this
template is named 'outer.html') something like:
<html>
<head><title><%title%></title></head>
<body>
<div style="border: 5px solid black">
<%include $inner_template%>
</div>
</body>
</html>
Then, inside other templates, you would do:
abc.html:
=========
<%set inner_template = 'abc_content.html'%>
<%set title = 'ABC'%>
<%include layout.html%>
xyz.html:
=========
<%set inner_template = 'xyz_content.html'%>
<%set title = 'XYZ'%>
<%include layout.html%>
Now both abc.html and xyz.html would show up with the same page layout defined
in layout.html, with a content section coming from their respective
*_content.html templates.
If an included template does not exist in the current template set, inherited
template sets will be checked as well. For details on template set
inheritance, see L<GT::Template::Inheritance>.
=head2 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 C<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
by prefixing it with a $, such as:
<%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
-E<gt>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.
=head2 Comparisons with Functions
You can combine use a function for an if/elseif statement I<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.
=head2 Sets with Functions
You may use a function call as the I<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.
=head2 Comments
Comments can be used to add comments about a template, or comment out existing
sections of template code. Comments start with the template opening tag
followed by C<--> (typically C<E<lt>%-->) and end with C<--> followed by the
template closing tag (typically C<--%E<gt>>). Additionally, comments may
contain other template tags, including other comments.
A simple comment:
<%-- This is a comment, and will not be displayed --%>
A comment example demonstrating included tags and nested comments:
<%--
<%template_tag%>
<%-- This is a comment, and will not be displayed <%-- another comment --%>--%>
<%if test%>example<%endif%>
--%>
=head2 Advanced variables using references
A more complex form of variable access is available which allows you to access
values contained within hash and/or array reference variables. These variables
can be used anywhere ordinary variables are permitted - including C<set>s.
For example, assume a variable named "person" has been passed to the template
parser with a value of:
{
name => "John Doe",
age => 35,
hair => "brown"
}
The following example:
<%person.name%> is <%person.age%> and has <%person.hair%> hair.
Would display:
John Doe is 35 and has brown hair.
Arrays are accessed in exactly the same way, using the array index (starting
from 0). Assume for the following example that a variable C<phone> has been
provided, with the following value:
['(555) 555-5678', '(555) 555-6789', '(555) 555-7890']
The following example:
Primary phone number: <%phone.0%>
Secondary numbers: <%loop phone%><%unless first%><%loop_value%> <%endunless%><%endloop%>
Will display:
Primary phone number: (555) 555-5678
Secondary numbers: (555) 555-6789 (555) 555-7890
Furthurmore, the size of array reference values (such as array reference-based
loops) may be determined by adding C<.length> to the end of the tag. Using the
same "phone" value above, the following:
Primary phone number: <%phone.0%>
<%if phone.length > 1%>Secondary numbers: <%loop phone%><%unless first%><%loop_value%> <%endunless%><%endloop%><%endif%>
Would display the same content, however if the "phone" value contained only a
single value, the "Secondary numbers" line would not be displayed at all:
Primary phone number: (555) 555-5678
Data structures of abitrary depth are supported, and can consist of any
combination of array and hash references.
Consider the following more complex example, with a C<people> variable set to
the following loop:
[
{
name => "John Doe",
age => 35,
hair => "no",
phone => {
work => "(555) 555-5678",
home => "(555) 555-6789"
}
},
{
name => "Jane Doe",
age => 25,
hair => "brown",
phone => {
work => "(555) 555-5678",
home => "(555) 555-1234"
}
}
]
The following template code:
<%loop person%><%row_num%>. <%name%>, <%age%> years of age, <%hair%> hair. Phone: work: <%phone.work%>, home: <%phone.home%>.
<%endloop%>
The first person on the list, <%person.0.name%>, can be reached at either <%person.0.phone.work%> or <%person.0.phone.home%>.
Will display:
1. John Doe, 35 years of age, no hair. Phone: work: (555) 555-5678, home: (555) 555-6789.
2. Jane Doe, 25 years of age, brown hair. Phone: work: (555) 555-5678, home: (555) 555-1234.
The first person on the list, John Doe, can be reached at either (555) 555-5678 or (555) 555-6789.
In addition to hash reference support, L<GT::Config|GT::Config> objects and
L<GT::CGI|GT::CGI> objects can be accessed as if they were hashes. So with:
config => $gt_config_object,
in => $cgi_object
The following:
<%config.variable1%>
<%in.parameter1%>
would access C<$gt_config_object-E<gt>{variable1}> and
C<$cgi_object-E<gt>param('parameter1')>. If used in a C<E<lt>%set ...%E<gt>>
command, the following:
<%set config.variable1 = 4%>
<%set in.parameter1 = 5%>
would set C<$gt_config_object-E<gt>{variable1}> to 4, and call
C<$cgi_object-E<gt>param('parameter1', '5')>, thereby setting it to 5.
Furthermore, complex variable expressions may contain other variables, such as:
<%set parameter = 'variable1'%>
<%config.$parameter%>
which would display the same thing as C<E<lt>%config.variable1%E<gt>>. Note
that complex variables cannot be used here - that is:
<%set abc.def = 'ghi'%>
<%config.$abc.def%>
will read the value of abc, then access config.(value).def. It I<is>, however,
possible to put a . inside a value, such as:
<%set abc = 'def.ghi'%>
<%config.$abc%>
would be equivalent to:
<%config.def.ghi%>
Complex variables can be used inside double quoted strings (wherever
double-quoted strings are accepted) but only in the form ${a.b}. Specifically,
the following:
<%set var1.key1 = 3%><%set var2 = "$var1.key1"%>
does not actually set var2 to "3" - the following achieves the desired effect:
<%set var1.key1 = 3%><%set var2 = "${var1.key1}"%>
Complex variables containing other variables are also supported, such as:
<%set var1 = "${var1.$keyvar}"%>
=head2 Whitespace compression
Normally, template tags do not affect the whitespace around them, however it is
sometimes desirable or necessary to remove the whitespace immediately before or
immediately after the tag. Consider the following example, which is intended
to print the values in 'values' that are odd and less than 10, separated by
-'s:
<%set found_one = 0%>
<%loop values%>
<%set odd = loop_value % 2%>
<%if loop_value < 10 and odd%>
<%if found_one%>
<%-- We've seen one before, so print the '-' --%>
-
<%else%>
<%-- We haven't seen one, so don't print the '-', but print it next time --%>
<%set found_one = 1%>
<%endif%>
<%loop_value%>
<%endif%>
<%endloop%>
will actually produce, given a loopvar containing the values 1 through 15,
the following output (where _'s are actually spaces):
____
____
________
____________
____________
________
________1
____
____
____
____
____
________
____________
____________-
________
________3
____
____
____
____
____
________
____________
____________-
________
________5
____
____
____
____
____
________
____________
____________-
________
________7
____
____
____
____
____
________
____________
____________-
________
________9
____
____
____
____
____
____
____
____
____
____
____
____
____
There are, of course, various ways around this - for instance, you could put
all the tags on one line with no spaces between them. However, such an
approach becomes very difficult to look at and use. The alternative is to use
GT::Templates's whitespace compression tags.
Any tag (including comments) may start or end (or start I<and> end) with a ~ -
if present, leading (if at the beginning of the tag) and/or trailing (if at the
end of the tag) spaces, tabs, and newline characters will be removed. So, you
could change the above code to the following:
<%set found_one = 0 ~%>
<%loop values ~%>
<%set odd = loop_value % 2 ~%>
<%if loop_value < 10 and odd ~%>
<%if found_one ~%>
<%-- We've seen one before, so print the '-' --~%>
-
<%~ else ~%>
<%-- We haven't seen one, so don't print the '-', but print it next time --~%>
<%set found_one = 1 ~%>
<%endif ~%>
<%loop_value ~%>
<%endif ~%>
<%endloop%>
Assuming the same data, this would give you a result of:
1-3-5-7-9
The spaces around the tags are not necessary - that is, you could write
C<E<lt>%~tag_name ~%E<gt>> C<E<lt>%~ tag_name ~ %E<gt>> C<E<lt>% ~ tagname ~ %E<gt>>
or any other variants. The style in the example above is used only for
improved readability.
Note that this option only affects whitespace in the current template, and does
not affect the value of variables or the content of includes. Example:
abc <%~ varname ~%> def
Assuming 'varname' contains the value C<' value '>, the above will produce the
output:
abc value def
but I<not>:
abcvaluedef
Likewise with includes:
abc <%~ include page.html ~%> def
Assuming page.html contains the following (with a space before "a" and after
"z"):
az
you will get the following output:
abc az def
or possibly, if the include contains a newline character at the end:
abc az
def
but I<not>:
abcazdef
Additionally, you may use the special tag C<E<lt>%~%E<gt>> to eliminate both
leading and trailing whitespace without needing a tag. For example:
a
<%~%>
b
<% ~ %>
c
will output:
abc
=head2 Variable Dumping
Often it is useful to dump the value of all tags available on the current page,
or the value of a single variable. For this, there is a built-in DUMP function
to dump a variable:
<%DUMP%>
<%DUMP variable%>
<%DUMP variable.key%>
The first example will display a dump of all the tags available wherever the
C<E<lt>%DUMP%E<gt>> tag is added, while the second and third examples will
display a dump of the 'variable' and 'variable.key' values, respectively.
C<DUMP> tags should only be used for debugging purposes; they are not intended
to be used on live, publically accessible templates as they may contain
sensitive data that should not be made publically available.
=head1 COPYRIGHT
Copyright (c) 2005 Gossamer Threads, Inc. All Rights Reserved.
http://www.gossamer-threads.com/
=head1 SEE ALSO
L<GT::Template> - for documentation on invoking the template parser.
L<GT::Template::Inheritance> - for documentation on template inheritance.
=head1 VERSION
Revision: $Id: Tutorial.pod,v 2.11 2005/04/23 23:11:33 brewt Exp $
=cut