|
|
| |
FillIn(3) |
User Contributed Perl Documentation |
FillIn(3) |
Text::FillIn.pm - a class implementing a fill-in template
use Text::FillIn;
# Set the functions to do the filling-in:
Text::FillIn->hook('$', sub { return ${$_[0]} }); # Hard reference
Text::FillIn->hook('&', "main::run_function"); # Symbolic reference
sub run_function { return &{$_[0]} }
$template = new Text::FillIn('some text with [[$vars]] and [[&routines]]');
$filled_in = $template->interpret(); # Returns filled-in template
print $filled_in;
$template->interpret_and_print(); # Prints template to currently
# selected filehandle
# Or
$template = new Text::FillIn();
$template->set_text('the text is [[ $[[$var1]][[$var2]] ]]');
$TVars{'var1'} = 'two_';
$TVars{'var2'} = 'parter';
$TVars{'two_parter'} = 'interpreted';
$template->interpret_and_print(); # Prints "the text is interpreted"
# Or
$template = new Text::FillIn();
$template->get_file('/etc/template_dir/my_template'); # Fetches a file
# Or
$template = new Text::FillIn();
$template->path('.', '/etc/template_dir'); # Where to find templates
$template->get_file('my_template'); # Gets ./my_template or
# /etc/template_dir/my_template
This module provides a class for doing fill-in templates. These templates may be
used as web pages with dynamic content, e-mail messages with fill-in fields,
or whatever other uses you might think of. Text::FillIn provides handy
methods for fetching files from the disk, printing a template while
interpreting it (also called streaming), and nested fill-in sections (i.e.
expressions like [[ $th[[$thing2]]ing1 ]] are legal).
Note that the version number here is 0.04 - that means that the
interface may change a bit. In fact, it's already changed some with respect
to 0.02 (see the CHANGES file). In particular, the
$LEFT_DELIM, $RIGHT_DELIM,
%HOOK, and @TEMPLATE_PATH
variables are gone, replaced by a default/instance variable system.
I might also change the default hooks or something. Please read
the CHANGES file before upgrading to find out whether I've changed anything
you use.
In this documentation, I generally use "template" to
mean "an object of class Text::FillIn".
- delimiters
Text::FillIn has some special variables that it uses to
do its work. You can set those variables and customize the way templates
get filled in.
The delimiters that set fill-in sections of your form apart
from the rest of the form are generally [[ and ]], but
they don't have to be, you can set them to whatever you want. So you
could do this:
Text::FillIn->Ldelim('{');
Text::FillIn->Rdelim('}');
$template->set_text('this is a {$variable} and a {&function}.');
Whatever you set the delimiter to, you can put backslashes
before them in your templates, to force them to be interpreted as
literals:
$template->set_text('some [[$[[$var2]][[$var]]]] and \[[ text \]]');
$template->interpret_and_print();
# Prints "some stuff and [[ text ]]"
You cannot currently have several different kinds of
delimiters in a single template.
- interpretation hooks
In order to interpret templates,
"Text::FillIn" needs to know how to
treat different kinds of [[tags]] it finds. The way it accomplishes this
is through "hook functions." These are various functions that
"Text::FillIn" will run when
confronted with various kinds of fill-in fields. There are two hooks
provided by default:
Text::FillIn->hook('$') is \&find_value,
Text::FillIn->hook('&') is \&run_function.
So if you leave these hooks the way they are, when
Text::FillIn sees some text like "some [[$vars]] and some
[[&funk]]", it will run
&Text::FillIn::find_value to find the value
of [[$vars]], and it will run
&Text::FillIn::run_function to find the
value of [[&funk]]. This is based on the first non-whitespace
character after the delimiter, which is required to be a non-word
character (no letters, numbers, or underscores). You can define hooks
for any non-word character you want:
$template = new Text::FillIn("some [[!mushrooms]] were in my shoes!");
$template->hook('!', "main::scream_it"); # or \&scream_it
sub scream_it {
my $text = shift;
return uc($text); # Uppercase-it
}
$new_text = $template->interpret();
# Returns "some MUSHROOMS were in my shoes!"
Every hook function will be passed all the text between the
delimiters, without any surrounding whitespace or the leading identifier
(the & or $, or whatever). Hooks can be given as either hard
references or symbolic references, but if they are symbolic, they need
to use the complete package name and everything.
Beginning in version 0.04, you may use some object's methods
as hook functions. For example, if you have a template
$template and another object
$myObj, you can instruct
$template to call
"$myObj->find_value()" and
"$myObj->run_function()" to fill in
templates. See the
"$template->object()" method
below.
- the default hook functions
The hook functions installed with the shipping version of this
module are &Text::FillIn::find_value and
&Text::FillIn::run_function. They are
extremely simple. I suggest you take a look at them to see how they
work. What follows here is a description of how these functions will
fill in your templates.
The &find_value function looks for
an entry in a hash called %main::TVars. So put
an entry in this hash if you want it to be available to templates:
my $template = new Text::FillIn( 'hey, [[$you]]!' );
$::TVars{'you'} = 'Sam';
$template->interpret_and_print(); # Prints "hey, Sam!"
The &run_function function looks
for a function in the "TExport"
package and runs it. The reason it doesn't look in the main package is
that you probably don't want to make all the functions in your program
available to the templates (not that putting all your program's
functions in the main package is always the greatest programming style).
Here are a couple of ways to make functions available:
sub TExport::add_numbers {
my $result;
foreach (@_) {
$result += $_;
}
return $result;
}
# or, if you like:
package TExport;
sub add_numbers {
my $result;
foreach (@_) {
$result += $_;
}
return $result;
}
The &run_function function will
split the argument string at commas, and pass the resultant list to your
function:
my $template = new Text::FillIn(
'Pi is about [[&add_numbers(3,.1,.04,.001,.0006)]]'
);
$template->interpret_and_print;
In the original version of
"Text::FillIn", I didn't provide any
hook functions. I expected people to write their own, partly because I
didn't want to stifle creativity or anything. I now include hook
functions because the ones I give will probably work okay for most
people, and providing them means it's easier to use the module right out
of "the box." But I hope you won't be afraid to write your own
hooks - if mine don't work well for you, by all means go ahead and
replace them with your own. If you think you've written some really
killer hooks, let me know. I may include cool ones with future
distributions.
- template directories
You can tell "Text::FillIn"
where to look for templates:
Text::FillIn->path('.', '/etc/template_dir');
$template->get_file('my_template'); # Gets ./my_template or /etc/template_dir/my_template
- new Text::FillIn($text)
This is the constructor, which means it returns a new object
of type Text::FillIn. If you feed it some text, it will set the
template's text to be what you give it:
$template = new Text::FillIn("some [[$vars]] and some [[&funk]]");
- $template->get_file(
$filename );
This will look for a template called
$filename (in the directories given in
$template->path()) and slurp it
in. If $filename starts with / , then
Text::FillIn will treat $filename as an
absolute path, and not search through the directories for it:
$template->get_file( "my_template" );
$template->get_file( "/weird/place/with/template" );
The default path is ('.').
- $template->interpret()
Returns the interpreted contents of the template:
$interpreted_text = $template->interpret();
This, along with interpret_and_print, are the main point of
this whole module.
- $template->interpret_and_print()
Interprets the [[ fill-in parts ]] of a template and prints
the template, streaming its output as much as possible. This means that
if it encounters an expression like "[[ stuff [[ more stuff]]
]]", it will fill in [[ more stuff ]], then use the filled-in value
to resolve the value of [[ stuff something ]], and then print it
out.
If it encounters an expression like "stuff1 [[thing1]]
stuff2 [[thing2]]", it will print stuff1, then the value of
[[thing1]], then stuff2, then the value of [[thing2]]. This is as
streamed as possible if you want nested brackets to resolve
correctly.
The following methods all get and/or set certain attributes of the
template. They can all be called as instance methods, a la
"$template->Ldelim()", or as static
methods, a la "Text::FillIn->Ldelim()".
Using an instance method only changes the given template, it does not affect
the properties of any other template. Using a static method will change the
default behavior of all templates created in the future.
I think I need to reserve the right to change what happens when
you create a template $t, then change the default
behavior of all templates, then call
$t->interpret() -- should it use the new
defaults or the old defaults? Currently it uses the old defaults, but that
might change.
- $template->Ldelim($new_delimiter)
- $template->Rdelim($new_delimiter)
Get or set the left or right delimiter. When called with no
arguments, simply returns the delimiter. When called with an argument,
sets the delimiter.
- $template->text($new_text)
Get or set the contents of the template.
- $template->path($dir1,
$dir2, ...)
Get or set the list of directories to search for templates in.
The path is used in the get_file() method.
- $template->hook($character,
$hook_function)
Get or set the functions for filling in the sections of the
template between delimiters. The first argument is the non-word
character the hook is installed under. The second argument, if present,
is the function to install as a hook. It may either be a hard reference
to a function, a string containing the fully package-qualified name of a
function, or if you're using objects to fill in your template, a method
name. See also the subsection on interpretation hooks in the DESCRIPTION
section.
- $template->object($obj)
As of version 0.04, you may use method calls on an arbitrary
object as template hooks. This can be very powerful. Your code might
look like this:
$t = new Text::FillIn("some [[$animal]]s");
$obj = new MyClass(animal=>'chicken'); # Create some object
$t->object($obj); # Tell $t to use methods of $obj as hooks
$t->hook('$', 'lookup_var'); # Set the method name for '$'
$t->interpret_and_print(); # Calls $obj->lookup_var()
The object methods will be passed the same arguments as
regular (static) hook functions.
- $template->property(
$name, $value );
This method lets you get and set arbitrary properties of the
template, like this:
$template->property('color', 'blue'); # Set the color
# ... some code...
$color = $template->property('color'); # Get the color
The Text::FillIn class doesn't actually pay any
attention whatsoever to the properties - it's purely for your own
convenience, so that small changes in functionality can be achieved
without having to subclass Text::FillIn.
If you want to use nested fill-ins on your template, make sure things get
printed in the order you think they'll be printed. If you have something like
this: "[[$var_number_[[&get_number]]]]",
and your &get_number prints a number, you won't get the results you
probably want. Text::FillIn will print your number, then try to
interpret "[[$var_number_]]", which probably
won't work.
The solution is to make &get_number return its number
rather than print it. Then Text::FillIn will turn
"[[$var_number_[[&get_number]]]]" into
"[[$var_number_5]]", and then print the
value of $var_number_5. That's probably what you
wanted.
The deprecated methods get_text(), set_text(),
get_property(), and set_property() will be removed in version
0.06 and greater. Use text() and property() instead.
By slick use of local() variables, it would be possible to
have Text::FillIn keep track of when it's doing nested tags and when it's
not, allowing the user to nest tags using arbitrary depth and not have to
worry about the above "common mistake." This would let hook
functions be oblivious to whether they're supposed to print their results or
return them, since Text::FillIn would keep track of it all. This will take
some doing on my part, but it's not insurmountable. It would probably
involve evaluating the tags from the outside in, rather than the inside
out.
The interpreting engine can be fooled by certain backslashing sequences like
"\\[[$var]]", which looks to it like the
"[[" is backslashed. I think I know how to
fix this, but I need to think about it a little.
Ken Williams (ken@forum.swarthmore.edu)
Copyright (c) 1998 Swarthmore College. All rights reserved. This
program is free software; you can redistribute it and/or modify it under the
same terms as Perl itself.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |