Decl::Template - implements a template in the Decl system.
A template is a textual representation of a class of data structures. A template has named slots and other value specifications that permit an arbitary set of data to be extracted from the environment of its invocation and formatted into a text block that can be used to do something else. In Decl, that "something else" is often the creation of a new set of nodes, but the typical use of templates is to express data in display text.
This class, instead of implementing a template itself, actually implements a template environment. A template, after all, is just a piece of text - and its output is also a piece of text. All the interesting stuff falls into the environment - it is in the environment that we determine the values of all our slots, after all. And in the Decl context, that is no trivial task.
doesn't do much except set up the engine according to the parameters.
Given a value environment (by default, a hashref) and the name of a value, a valuator finds the value.
If nothing else is specified, the hashref valuator is used. In the Decl context, a node will generally be used and the node's own valuation function is used as the valuator.
Given a variable specification, prepare it for use as a lookup key.
Given a spanning command string, parse out the initial word (the command) and leave the arguments (the rest). Drop the . or +.
Given a parsed spanning command and the value object and valuator function to be used, express the command. This is really just a dispatcher for a command table.
Here's how you register a spanning command. Just name it and provide a closure for it, and you're good to go.
These are our three default spanning commands. More can be added to the table.
express_repeat does the heavy lifting in expressing the list template and can be recycled in other forms of list template.
Takes a value specification, cleans up the name, applies filters, and returns the final value. TODO: filters.
This parses our template language into a kind of interlanguage consisting of interleaved plain text and commands to be carried out to generate text. Then we can either express the command structure, or alternatively translate it into some other template language.
So. Our template language is text interspersed with fields delimited by default delimiters of [[ and ]]. (These can be overridden.) Its output is a list (or arrayref) of commands. Plain text between fields is output exactly as-is, and so the output "command" is simply a string containing that text.
Most fields are variable lookups, and these turn into ['lookup', '<variable>'] - where "variable" can be an extended command if our valuation function knows how to handle them. The basic template engine, however, simply looks up names in a hashref.
Any field of the form [[.<command> <args>]] is a "dotted command" or "spanning command". The default ones defined are .repeat, .with, and .if; you can write your own, though. (TODO: provide a way to hook them in.) A dotted command extends until it hits [[.end]], and they can of course be nested.
The Decl node framework will also provide a .select command, which will do exactly what you think it will. I think, based on this alone, you could probably build a believable report generator.
Within a spanning command,
you can define subranges with [[+<range> <args]].
This is used for
else in the
else in the
What you get back is then a hashref with any subranges stored by name for your viewing pleasure.
The parser outputs a spanning command like this:
['<command with string arguments>', [<list of contained template items>], [ [<subcommand>, <subcommand arguments>, <list of contained items>], ... (this part is optional and repeated for as many subcommands as appear) ] ]
The hashref of named subspans likewise has arrayrefs for values. Each of the arrayrefs in this structure has already been parsed by the time all is said and done.
Given a parse tree returned from the above function, plus a value structure and a way to retrieve first-level values from it (second-level values are presumed to be hashrefs or arrayrefs returned from the first level, and perhaps there might someday be motivation to extend that notion to some kind of lazy evaluation, but today is not that day), (breathe) returns the expressed template. Which is just a string.
Non-default spanning commands must be defined in the engine before use.
$template is omitted, the default template for the engine is used. If
$values is omitted, same goes for any previously defined values. And the default
$valuator is defined above.
<michael at vivtek.com>
Please report any bugs or feature requests to
bug-decl at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Decl. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
Copyright 2010 Michael Roberts.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.