Request for more contextual data to filters and coderef vars
"Brad Choate" <[email protected]>
| Newsgroups | gmane.comp.lang.perl.modules.html-template |
|---|---|
| Message-ID | <[email protected]> |
Hi all-- brand new to the list, but I've been using HTML::Template for
some time. Just to quickly introduce myself... I work at Six Apart as
one of the engineers of Movable Type. MT uses HTML::Template for all
of its application UI.
I'd like to request that HTML::Template provide more useful contextual
information to any user-supplied coderefs through filters and template
parameters that are coderefs.
First, for filters: a filter should be able to determine what file is
currently being processed, if the contents of the template did come
from a file. I was able to find the HTML::Template package variable
that has a filename ($HTML::Template::fname), but it's the filename of
the parent of the template that is passed to the filter, not the
filename of the template being processed by the filter. So, if I have
foo.tmpl:
<TMPL_INCLUDE NAME=bar.tmpl>
When I process foo.tmpl with a filter parameter, the filter is invoked
once for foo.tmpl, then again for bar.tmpl. The
$HTML::Template::fname set during the second call is for foo.tmpl.
And, it would be helpful if the reference to the template object was
passed to the filter too.
I don't see any way to currently get either of these things. I've
attached a patch for version 2.8 that adds what I'm looking for; at
the very least, it may help explain what I'm wanting.
Second, for template vars that are coderefs.
To me, these are a bit limited since the coderef has no way to
determine it's context. I'm envisioning a scenario like this:
<TMPL_LOOP NAME=X>
<TMPL_VAR NAME=CODE_FOO>
</TMPL_LOOP>
The coderef associated with 'code_foo' is called for each iteration of
the array in parameter 'x', but 'code_foo' has no way to access the
active row of data. Futhermore, it doesn't even know what parameter
name is being used to invoke it. If I were to assign the same coderef
for 'CODE_FOO' and 'CODE_BAR', the routine could do different things
based on the param name. Within a loop like this, it would be cool if
it could access the loop contextual values like "__first__", etc. It
would also be helpful to know if the coderef was being run from within
a loop, and what the name of that loop is. If it were in a loop within
a loop, within a loop, in file "x.tmpl", it should be able to
determine all that. I realize this would require some significant
changes; by the time the output method is run, the parameter names
aren't available. Perhaps if a coderef var is found during the parse
step, it could wrap it with a closure that supplies the context to the
original coderef.
-Brad
Template.patch
(application/octet-stream, 2.3 KB)
*** Template-2.8.pm Sat Feb 25 02:37:57 2006
--- Template.pm Sat Feb 25 08:40:30 2006
***************
*** 1599,1604 ****
--- 1599,1605 ----
my $self = shift;
my $options = $self->{options};
+ local $HTML::Template::this_file;
my @pstacks = ($self->{parse_stack});
while(@pstacks) {
my $pstack = pop(@pstacks);
***************
*** 1625,1630 ****
--- 1626,1632 ----
print STDERR "### HTML::Template Memory Debug ### START INIT_TEMPLATE ", $self->{proc_mem}->size(), "\n"
if $options->{memory_debug};
+ local $HTML::Template::this_file;
if (exists($options->{filename})) {
my $filepath = $options->{filepath};
if (not defined $filepath) {
***************
*** 1643,1648 ****
--- 1645,1651 ----
$self->{template} = "";
while (read(TEMPLATE, $self->{template}, 10240, length($self->{template}))) {}
close(TEMPLATE);
+ $HTML::Template::this_file = $filepath;
} elsif (exists($options->{scalarref})) {
# copy in the template text
***************
*** 1704,1715 ****
eval {
if ($format eq 'scalar') {
# call
! $sub->($template_ref);
} else {
# modulate
my @array = map { $_."\n" } split("\n", $$template_ref);
# call
! $sub->(\@array);
# demodulate
$$template_ref = join("", @array);
}
--- 1707,1718 ----
eval {
if ($format eq 'scalar') {
# call
! $sub->($template_ref, $self);
} else {
# modulate
my @array = map { $_."\n" } split("\n", $$template_ref);
# call
! $sub->(\@array, $self);
# demodulate
$$template_ref = join("", @array);
}
***************
*** 2247,2253 ****
my $included_template = "";
while(read(TEMPLATE, $included_template, 10240, length($included_template))) {}
close(TEMPLATE);
!
# call filters if necessary
$self->_call_filters(\$included_template) if @{$options->{filter}};
--- 2250,2257 ----
my $included_template = "";
while(read(TEMPLATE, $included_template, 10240, length($included_template))) {}
close(TEMPLATE);
!
! local $HTML::Template::this_file = $filepath;
# call filters if necessary
$self->_call_filters(\$included_template) if @{$options->{filter}};