[Templates] #line style directives in TT?

Andy Wardley abw@wardley.org
Wed, 25 Jul 2007 08:43:14 +0100


Hi Brad,

> It's a bit tricky because line numbers are a parse time thing, right?
> That's why my attempt a RAWPERL solution wasn't going to work.

Yep, that's right.

You would need to hard-code the LINE directive into Template::Parser.  Around 
line 376.

     if ($dir =~ /^TAGS\s+(.*)/i) {
         # blah
     }
+   elsif ($dir =~ /^LINE\s+(\d+)/i) {
+       $line = $1;
+   }
     else {
         # DIRECTIVE is pushed as:
	# ...etc...
    }

While adding the directive is fairly straightforward, it's adding the 
documentation, test, etc., that's a PITA.  So it's unlikely to make it into 
TT2 any time soon (if at all).

TT3 is a different matter, though.  Directives are implemented as separate 
objects so it's easy to add another one.  Here's one I just knocked up:

   package Template::Directive::Line;
   use base 'Template::Directive';

   our $FIRST = {
       LINE => \&parse,     # LINE keyword calls parse()
   };

   sub parse {
       my ($class, $text, $match, $parser, $tree) = @_;
       $$text =~ / \G \s* (\d+) /cgx
         || return $class->error_msg( bad_option => $match->{ keyword } );
       $match->{ line } = $1;
       return $tree;
   }

And here's an extract from a test script showing it working:

   -- test LINE directive --
   [% LINE 42 %]
   hello [% TAGS badger %]
   -- expect --
   <ERROR:Parse error at line 43: tag error - Invalid tag style specified: badger>

The "-- test ... --" and "-- expect --" lines are part of the test harness. 
The important part is the "Parse error at line 43" in the error message generated.

So I guess that's a roundabout way of saying that it's now in TT3.  :-)

For the sake of completeness, I suppose we should also have a FILE directive.

   [% FILE foo LINE 42 %]

And some way of inserting the file/line values back into a template.

   Hello World from [% FILE %] line [% LINE %]

There's a few issues to think about there, but in principle I'm all for it.

Cheers
A