|
||||
|
||||
|
|
NameText::Wigwam::Tutorials::Basics - The basics of Wigwam templating.
DescriptionThis tutorial explains the fundamentals of the Wigwam framework from a template writer's perspective.
IntroductionWigwam is a utility that provides the basic tools and features to build custom template scripting environments. Because environments will vary, this tutorial will focus on the the basic constructs and elements that make up Wigwam templates.
TemplatesWigwam templates consist of simple plain-text documents which are interspersed with special tags that act as place holders where data is to be inserted. These tags contain tokens which can either represent data or manipulate it in some way. When the template is parsed, each tag is systematically processed from top to bottom and replaced by the resulting text that they produce.
Code tagsCode tags are denoted by a pair of delimiters, typically
TokensTokens are the basic elements which make up the Wigwam scripting environment. There are three basic types of tokens: literals; variables; and directives.
LiteralsLiterals are used to represent a value that does not change. There are two types of literals: quoted; and unquoted numeric. Quoted literals are identified by their surrounding quotation marks: [!! "This is a quoted literal" !!] [!! 'Single quotes can also be used' !!] Unquoted numeric literals are any series of characters that equates to a valid numeric value. [!! -42 !!] [!! 98.6 !!] [!! +186E3 !!] By default, Wigwam treats anything that appears to be a valid floating point number as a literal numeric value. This behavior can be controlled via the numbers configuration option.
VariablesVariables are used to access values within Wigwam's variable space. Wigwam variables are identified by their lack of identifier characters. [!! foo !!] [!! bar !!] [!! bazz !!]
DirectivesDirectives add functionality to the environment by allowing operations to be performed within templates. They are identified by the hash mark preceding them. [!! #directive !!] Directives are stored in modules and plug-ins which can be loaded on demand from within templates, thereby the directives available in any given template environment depends upon which modules and plug-ins have been loaded. The documentation for any given directive should be distributed with the plug-in or module that provides it. Always consult this documentation to obtain the specifics of its function and usage.
ArgumentsDirectives often require arguments to be used as parameters for performing an operation. Arguments may consist of any of the three basic token types and are always placed immediately after the directive (this is the basis of prefix syntax). The #define directive demonstrated below expects two arguments: a variable name; and a value. It assigns a value to a variable and does not produce any output. 1: [!! #define foo "bar" !!] 2: [!! foo !!] output: 1: 2: bar Note: The numbers followed by colons in many examples herein serve no purpose other than to demonstrate what is happening line by line as the template is parsed. The most important thing to remember about directives is that each requires a fixed number of arguments. 1: [!! #define foo "bar" "bazz" !!] 2: foo=[!! foo !!] output: 1: bazz 2: foo=bar What's happening on line 1 is that
BlocksBlocks are used to group a number of tokens together so that their combined values may be joined and used as a single argument. There are two types of blocks: code blocks; and text blocks. Both block types may also contain an unlimited number of nested blocks and will always produce a string value (text).
Code blocksCode blocks are represented by the brace characters
1: [!! #define foo { "bar" "bazz" } !!]
2: foo=[!! foo !!]
output:
1:
2: foo=barbazz
Text blocksText blocks are denoted by the special tag delimiters 1: [!! #define foo !!>bar bazz<!! !!] 2: foo=[!! foo !!] output: 1: 2: foo=bar bazz Text blocks are typically used when it makes more sense to express a value as a large block of text as opposed to a long string of tokens. As an example, let's say you have a simple template code snippet that you've now decided you want stored in a variable: The [!!thing!!] is guaranteed to [!!function!!] or your [!!cost!!] will be refunded! An unappealing approach would be to convert it into a string of tokens, like so:
[!!
#define variable {
"The "
thing
" is guaranteed to "
function
" or your "
cost
" will be refunded!"
}
!!]
A much better alternative is to place the unaltered code snippet between text block delimiters, as it doesn't require us to make any alterations to the code snippet. [!! #define variable !!> The [!!thing!!] is guaranteed to [!!function!!] or your [!!cost!!] will be refunded! <!! !!]
CommentsComments exist within tag delimiters and are used to document code. Anything
existing between the comment delimiters 1: [!! #define foo 'bar' /* This assigns a value to a variable */ !!] 2: [!! foo /* output the value of the variable */ !!] output: 1: 2: bar
White-space trimmingWhite-space outside of any individual tag delimiter can be eliminated at compile time by using the white-space trimming tag delimiters. These alternate tag delimiters will remove all tabs and spaces directly outside the delimiter up to and including the first new-line (if encountered before a non-tab or non-space). Anything beyond that will be left untouched. By default, Wigwam defines the following white-space trimming tag delimiters which, outside of their white-space trimming function, are equivalent to their non-trimming counterparts. [!~ /* White space trimming code tag delimiters */ ~!] [!! ~!> White space trimming text block delimiters <!~ !!] The [!! 'quick ' ~!> brown <!! 'fox ' ~!] jump [!~ 'ed ' !!] [!~ 'over' !!> the <!~ ' lazy' !!] dogs. produces The quick brown fox jumped over the lazy dogs.
Configuration tagEach template may contain its own configuration options tag which is processed prior to template execution. It can be used to specify parsing options, debugging features, template characteristics (such as redefining tag delimiters), or to load plug-ins & modules. These options are defined via a uniquely identified and specially formatted configuration tag. They take the following form:
<< Wigwam
Options:
/* Tag delimiters */
code_open = [!!;
code_term = !!];
text_open = !!>;
text_term = <!!;
/* White space trimming tag delimiters */
code_open_trim = [!~;
code_term_trim = ~!];
text_open_trim = ~!>;
text_term_trim = <!~;
/* Other common options */
numbers = float;
plugins = DirectiveSet;
modules = Core/Cgi, Core/Html;
/* These comments are ignored */
>>
Only the first encountered configuration tag is processed for any given template. Any other configuration tags within the template will be treated as plain text. This feature is useful when dealing with templates that generate other templates. The configuration tag may also be used to define default settings for, or impose restrictions upon, subsequently invoked templates, though that aspect will not be covered in this tutorial.
Data managementThis section focuses on the basic conventions involved in managing Perl's various data types from within templates.
StringsString values are nothing more than text, so handling them is straightforward. 1: [!! #define foo "bar" /* Store a string value into the variable foo */ !!] 2: [!! foo /* echo the value */ !!] output: 1: 2: bar
ArraysAn array (sometimes referred to as a list) is simply an ordered list of values which may consist of strings, arrays, hashes or nested data structures made up of some combination of any or all of these data types. Arrays can be defined within templates using the parenthesis characters 1: [!! #define stuff ( "one" "two" "three" ) !!] 2: [!! stuff:0 !!] 3: [!! stuff:1 !!] 4: [!! stuff:2 !!] output: 1: 2: one 3: two 4: three Another means for defining arrays is to use the angle brackets 1: [!! #define stuff < one two three > !!] 2: [!! stuff:0 !!] 3: [!! stuff:1 !!] 4: [!! stuff:2 !!] output: 1: 2: one 3: two 4: three Laziness is not the only motivation for the angle brackets - they also make template code more readable in many situations.
HashesA hash is a list of values which are accessible by way of an associated key, as opposed to an element number as with arrays. Like arrays, hash values may consist of strings or nested data structures. Hashes can be defined within templates by using the percent 1: [!! #define hashlist %< one uno two dos three tres > !!] 2: [!! hashlist.one !!] 3: [!! hashlist.two !!] 4: [!! hashlist.three !!] output: 1: 2: uno 3: dos 4: tres
Backtick metacharacterThe backtick metacharacter can be used in place of either the dot or colon metacharacters to detect the type of data being accessed and use the appropriate lookup syntax to access the data stored there. It can also be used to perform operations on the data itself. The following example defines an array of data, displays the data, then performs the same operation on a hash of data.
0: [!! #macro showdata { #parameters <data> #foreach item data`values`sort item } !!]
1: [!! #define data < a b c d > /* Array */ !!]
2: [!! &showdata(data) !!]
3: [!! #define data %< Aye a Bee b Cee c Dee d > /* Hash */ !!]
4: [!! &showdata(data) !!]
output:
1:
2: abcd
3:
4: abcd
Variable InterpolationVariable interpolation is an indispensable tool for accessing data indirectly. Wigwam allows variable interpolation through the use of square brackets within the variable names. [!! #define foobazz "FOOBAR" !!] [!! #define quux "bazz" !!] [!! foo[quux] !!] produces: FOOBAR Interpolation is typically used to access hash or array elements when the key or element number is stored in a variable.
[!!
#define rules %<
paper %<
rock "You win - paper wraps rock"
scissors "You lose - scissors cuts paper"
>
rock %<
paper "You lose - paper wraps rock"
scissors "You win - rock crushes scissors"
>
scissors %<
rock "You lose - rock crushes scissors"
paper "You win - scissors cuts paper"
>
>
#define choice rules`keys`rand /* Random choice */
#define challenge rules`keys`rand /* ditto */
!!]
I've chosen [!! choice !!], you challenge with [!! challenge !!].
Outcome: [!! #or rules.[challenge].[choice] "We tie" !!].
There is no limit on the number of nested square brackets that can be used on any given variable.
Try itYou can try out Wigwam on-line using the html form at the following address: http://www.wigwamhq.org/tryit/
AuthorDJOHNSTON, <djohnston@cpan.org> WINGNUT, <wingnut@cpan.org> The latest Wigwam version and documentation are available at http://www.wigwamhq.org
Copyright and LicenseCopyright 2004-2007 by Scot Woodward and Daniel Johnston This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |