[Templates] indentation and text files

Andy Wardley abw@andywardley.com
Thu, 2 Jan 2003 11:38:48 +0000


You could write a simple unindent filter...

   my $tt = Template->new({
       FILTERS => { 
           unindent => sub {
               my $text = shift;
               $text =~ s/^\s+//gm;
               return $text;
           },
       },
   })

...and use it like so:

[% FILTER unindent %]
  [% IF blah %]
	blahblah, lots of
 	text here
  [% ELSE %]
	show this instead
  [% END %]
[% END %]

A bit of a kludge, but it might be one way to do what you want.
 
The TT3 parser (that I'm working on right now) has much better support
for defining custom tags and meta-characters that will allow you to 
perform your own pre-processing options.

In addition to the standard TT tags like [% ... %] and $foo (when the 
INTERPOLATE option is set), you will be able to define additional tags
to which you can attach your own parsing or pre-processing code.

For example, you could define a tag which matches "\s+" at the start of
a line and then does nothing, other than consume the "\s+" from the input
stream, effectively removing it.

Then you could write:

  [% IF blah %]
        some text
        yada yada
  [% ELSE %]
        more text
        etc etc
  [% END %]

And it would be parsed as if you had written it:

  [% IF blah %]
  some text
  yada yada
  [% ELSE %]
  more text
  etc etc
  [% END %]

I've just knocked up a TT3 test script to do this and it seems to work
as expected.  TT3 is in a very early stage at the moment so the test is 
rather gnarly and not particularly informative (I'll be putting TT3 under 
public CVS repository RSN for those who are interested).  By the time 
everything is packaged and polished, you should be able to use it something 
like this:

  my $tt = Template->new({
      TAGS => [
          {
              START  => qr/(?m:^\s*)/,
              ACTION => 1,
          },
          # ...any other tags...
      ],
   });

The START item provides a regular expression for the scanner to match
and the ACTION in this case is set to 1 to indicate success with nothing
else to be done.  You can also set this ACTION to be a subroutine or
compiler method, allowing you to do all sort of other magic, too.

The great thing is that you can define as many different tag styles as
you like.  For example, you might also like to define a block quoting 
tag style which collapses all whitespace within its bounds.

  my $tt = Template->new({
      TAGS => [
          {
              START  => '<<' ,
              END    => '>>',
              ACTION => sub {
                  my ($compiler, $text) = @_;
		  $text =~ s/\s+/ /g;
                  $compiler->text($text);
              },
          },
      ],
   });

Now you can write:

  [% IF blah %]
  <<     blah blah
         yada yada
  >>
  [% END %]
 
and it is parsed as if written:

  [% IF blah %]
  blah blah yada yada
  [% END %]
 
>From this and the other early tests that I've been doing, I'm quite 
optimistic that the new scanner/parser/compiler architecture that I'm
working on is going to bring all kinds of new and useful capabilities
to the toolkit.

Although a complete and working TT3 is still some time away, it might 
be possible to back-engineer the new TT3 parser into TT2 so that you
can start using some of these new features sooner rather than later.

Cheers
A