Text-FillIn

 view release on metacpan or  search on metacpan

FillIn.pm  view on Meta::CPAN


sub find_value { $main::TVars{ $_[0] } }

sub run_function {
   # Usage: $result = &run_function("some_function(param1,param2,param3)");
	my $text = shift;
   my ($function_name, $args) = $text =~ /(\w+)\((.*)\)/
      or die ("Can't understand function call '$text'");
	no strict('refs');  # Allow symbolic name substitution for a little while
   return &{"TExport::$function_name"}( split(/,/, $args) );
}


1;

__END__


=head1 NAME

Text::FillIn.pm - a class implementing a fill-in template

=head1 SYNOPSIS

 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

=head1 DESCRIPTION

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.  B<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".

=head2 Defining the structure of templates

=over 4

=item * delimiters

B<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 B<[[> and B<]]>, 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.

=item * interpretation hooks

In order to interpret templates, C<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 C<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 B<Text::FillIn> sees
some text like "some [[$vars]] and some [[&funk]]", it will run
C<&Text::FillIn::find_value> to find the value of [[$vars]], and it will
run C<&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 {

FillIn.pm  view on Meta::CPAN

    'Pi is about [[&add_numbers(3,.1,.04,.001,.0006)]]'
 );
 $template->interpret_and_print;


In the original version of C<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.


=item * template directories

You can tell C<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

=back



=head1 METHODS

=over 4

=item * new Text::FillIn($text)

This is the constructor, which means it returns a new object of type B<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]]");

=item * $template->get_file( $filename );

This will look for a template called $filename (in the directories given in 
B<$template-E<gt>path()>) and slurp it in.  If $filename starts with / , 
then B<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 ('.').

=item * $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.

=item * $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.

=back

The following methods all get and/or set certain attributes of the template.  They can
all be called as instance methods, a la C<$template-E<gt>Ldelim()>, or as static methods,
a la C<Text::FillIn-E<gt>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.

=over 4

=item * $template->Ldelim($new_delimiter)

=item * $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.

=item * $template->text($new_text)

Get or set the contents of the template.

=item * $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.

=item * $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.

=item * $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()



( run in 0.432 second using v1.01-cache-2.11-cpan-e1769b4cff6 )