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}};
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.