Bugs:
----

- Use "UNIVERSIAL::isa(...)" and "SUPER" in the appropriate places
so that sub-classes work correctly.
    

Why should H::T use SUPER?
  
If H::T::E calls H::T->do_something, then when a subclass overrides that do_something method, the subclass method isn't called.  ie: this is needed when subclassing H::T::E.  It also important in the "_new_from_loop" case where you want your subclass hooks to be executed.


  
Optimisations
-------------

- Allow output()ing use a scalar reference.  This allows the ref to
by used by further instances of H::T (or other code), thus saving a
copy of the text buffer.
    

++

  
- Use a more powerful regular expression to chunk up the template.
Since Perl's regex parsing is quite fast, the parsing of a template
is quicker since the chunks now always begin with <TMPL_ (rather
than simply splitting on '<'
    

I'm not sure I follow. What regex would you use instead?
  
m!(?=<(?:\!--\s*)?/?[Tt][Mm][Pp][Ll]_)!

instead of

m/(?=<)/


The regex itself may be slower - I haven't tested its parse performance, but since the parse_stack is now much smaller the output()ing is faster by a small margin.

- Provide a profiling option which dumps some profiling statistics.
 This can be used to enhance H::T performance.  [ This is how I was
able to determine where to look for the performance patch. ]
    

++

  
- Make Vanguard compatibility available as a filter rather than part
of Template.pm
    

++, or deprecate it and then drop it completely. Sam/Jesse, is anyone still
using that who also upgrades H::T?

  
- Provide a method where a hashref can be passed in as the
value-type for a param, so that it self-expands into the
corresponding TMPL_VAR's / TMPL_LOOP's.  Often data comes out of a
database API as a hash-per-row; depending on how the programmer is
using H::T, this can minimise data copying.
    

I'm not sure I follow here. hashref's are already used for loops. Are you
talking about having something like this:
  $tmpl->param(
    person => {
      first_name => 'Michael',
      last_name  => 'Peters',
    }
  );

And then in the template something like this:
  <tmpl_var person.first_name> <tmpl_var person.last_name> ?

If so, then HTML::Template::Plugin::Dot may be more what you're looking for.
  
I think there are multiple separate pieces of functionality provided by HT::P::Dot  which are useful in their own right, but yes.  In fact, the implementation provided in ::Dot would probably run slightly faster than my implementation under some cases (although I think it wouldn't handle new TMPL_XXX tags - not sure...)

Except that HT::Pluggable doesn't subclass from H::T::E  (... in some very specific hack'ish scenarios using H::T::E is a blessing... I'd really like to keep using it).


Note also, HT::Pluggable suffers a little from the same lack of function-call hooks, ie: it re-implements the param() method.  In reality, the function-call dispatch mechanism may need to implement something like the implementation in DBI / DBD, rather than subclassing H::T / H::T::E.

Enhacements
-----------

- Modify the ESCAPE module handling so that it dynamically loads the
requested module.  This would allow people to create their own
escape code to suite their specific needs. eg: H::T is often used to
output text which is not HTML - in those cases the rules for
escaping can be different; or, someone may want to build an escape
module that chains existing modules.
    

This might be useful, but I'm sort of ambivalent.\

  
- Provide hooks to allow sub-classes to implement their own TMPL_xxx
syntax.  This is particularly useful when a particular H::T::E
expression frequently uses a function call -> it becomes possible to
promote that function call to become first class TMPL_XXX syntax.
 This makes it easier on the template programmer and allows the
expression to run faster too.
    

Again, possibly useful. Maybe a compelling use case would help spur the discussion.
  
I provided an example.

Another...  I provide the TMPL_CATGETS call to template developers; it takes constant-strings and/or template variables.

The TMPL_CATGETS expression takes the arguments and applies them to the language engine.  The language engine returns parse_stack objects.

Later when the page is rendered, the language-engine objects get executed returning the appropriate language translation.  Since language translations are updated daily, the rendering will get the latest translations.


To provide the ability to create new TMPL_XXX tags, some function calls need to be added where currently H::T simply dies.

- Allow '.' as a template variable.  This makes it a bit easier to
group similar variables

- Allow the '&' and '|' operators in expressions.
    

You want bitwise and/or? use case?
  
yes

<TMPL_IF EXPR="user_permissions & some_funky_menu_permission">

where "user_permissions" is the users' permission as a bit-set, and "some_funky_menu_permissions" is a bit-mask.

One could argue that a template variable of "user_some_funky_permission" should be created by the application.   But then why should the application programmer create the cross-product of every template variable; it is up to the template designer to decide when the some_funky_menu gets displayed.

- Package some predefined / common filters.
    

like...?
  
like every filter that has been posted to the users-list.  Here are a few:

#
# allow trailing slash in <TMPL_xxx /> tags
#
sub allow_trailing_slash {
  my $filter = sub {
    my $text_ref = shift;
    my $match = qr/(<[Tt][Mm][Pp][Ll]_[^>]+)\/>/;
    $$text_ref =~ s/$match/$1>/g;
  };
  return $filter;
}

#
# Translate the SSI "include virtual" into a template include:
#
sub ssi_include_virtual {
  my $filter = sub {
    my $text_ref = shift;
    my $match = qr/<!--\s*#include virtual="[\/]?(.+?)"\s*-->/i;
    $$text_ref =~ s/$match/<TMPL_INCLUDE NAME="$1">/g;
  };
  return $filter;
}

#
# Decompress gzip-comressed templates
#
sub gzipped_templates {
  eval { require Compress::Zlib; };
  croak "To use gzip-compressed templates, you need into install Compress::Zlib" if ($@);
  my $filter = sub {
    my $text_ref = shift;
    require Compress::Zlib;
    $text_ref = Compress::Zlib::uncompress($text_ref);
  };
  return $filter;
}

#
# Allow template variables to use %var% syntax
#
sub percent_variables {
  my $filter = sub {
    my $text_ref = shift;
    my $match = qr/%([-\w\/\.+]+)%/;
    $$text_ref =~ s/$match/<TMPL_VAR NAME="$1">/g;
  };
  return $filter;
}

#
# Strip newline's following TMPL_XXX statements
#
sub strip_tmpl_newline {
  my $filter = sub {
    my $text_ref = shift;
    $$text_ref =~ s/(<TMPL_[~>]>)[\r\n]+/$1/g;
  };
}


- Package a preload mechanism for preloading templates into the
memory/file caches.
    

++

Krang already does this on it's own to load all it's H::T template. Why not put
the code into H::T itself.

  
- Now that H::T::E supports a unary context, provide some unary
operators too. eg: the 'not' operator
    

++

  
- Provide TMPL_ELSIF ... This simply makes it easier on the template
programmer.  And incurs no runtime overhead to boot.
    

++++ - this would prevent a lot of ugly looking templates that I've been guilty
of making.

  
- Provide '__even__' when using loop-context-vars.  Yes it is
redundant but some people's brain hurts when using inverted contexts
(ie: TMPL_UNLESS + TMPL_ELSE).  In particular, it works well when
used with TMPL_ELSIF.
    

Again, I'm ambivalent.

  
- Allow recursive H::T invocations for those cases where people
_realy_ want to do <TMPL_INCLUDE <TMPL_VAR>>... [ and thus deal with
the consequences of such an act... :-) ]
    

Would this just apply to tmpl_include or to all vars? If everything, then it
would need a 2 pass parser right? That would be pretty painful performance wise.
  
yes, this needs the parser to run multiple times, and it runs quite a bit slower to boot - what a deal....  However, H::T is not always used in an online web environment - you may be able to tolerate some performance loss at the expense of making your templates more dynamic.

Mathew