> Yep, that's it. When TT compiles the template down to Perl code, it adds
>
> #file $file line $line
>
> lines which tell Perl where to report errors from. It's these, and only
> these, that the FILE/LINE directives would control. (err... I think).
Sounds good. Sounds like a sufficient scope.
> > The words FILE and LINE and particularly
> > file and line are used extensively in existing templates. I don't think
> > that the proposed directives add enough functionality to warrant making
> > them reserved words.
>
> I agree that they're of limited value. However, TT3 allows you to enable
> or disable individual directives. So if you're using a lot of FILE
> variables, then you could disable (or more like, not enable) the FILE
> directive.
It is trivial to disable directives in Template::Alloy too. But it seems
rather a pain to have to enable it - or sometimes have to disable it. The
DEBUG directive and configuration items under TT2 are good - but they are
very cumbersome to have to go and enable or disable. If you are working with
cached compiled templates, you have to clear your cache each time you turn
DEBUG on or off - and that is assuming the developer can find where to turn
those on and off or even has access to be able to. If the FILE and LINE
directives aren't enabled by default, they will be seldom used and will have
the same issue any document caches will have to be cleared.
I think that a design consideration should be included that apart from
changing "CONSTANTS", there should be a 1 to 1 correlation between document
and its cached copy. That can't be entirely true as TRIM, PRE_CHOMP,
POST_CHOMP, V1DOLLAR, ANYCASE, V2PIPE, SYNTAX, and AUTO_EVAL all affect the
parsed document. However, items such as DEBUG, DUMP, FILE, and LINE probably
shouldn't have an affect on the cached document - or else it is going to
cause a headache when those items don't show up if the developer decides to
enable them.
> Also, we don't have to be as worried about reserved words in TT3 as we do
> in TT2 because a directive keyword isn't actually a reserved word. A
> keyword only has significance in a position where keywords are expected.
> ISTR Template::Alloy is the same.
>
> [% GET FILE %] # no problem
> [% wibble(FILE) %] # cool
Right. This is the same in Template::Alloy. The larger problem is
[% FILE %] or [% file %] when ANYCASE is set.
> The more general solution to this problem is namespaces. By using an
> explicit namespace prefix you can tell the parser what you really mean:
I think it is a partial solution, but I think the best solution is
non-proliferation of DIRECTIVES. I think the namespaces are neat - they
offer the benefit of adding all sorts of data to templates (well I actually
already think that TT does a fine job and namespaces might be overkill), but
I don't want to have to be sprinkling namespaces around just because I'm
nervous a newer version of TT3 is going to clash on a reserved word. This is
why Perl's use of sigils is wonderful - you can't clash a variable with a
function. I'm not suggesting using sigils and I'm not encouraging use of
V1DOLLAR. I like TT's syntax clean-ness. Adding many directives, especially
ones that are the same as commonly used variable names, seems like an
eventual problem. And not enabling directives by default because they are
potentially conflicting doesn't seem like the right solution.
The other mini-language toolkits don't have this issue because it is
impossible to mix up a variable name with a directive.
<TMPL_LOOP LOOP> # HTML::Template
<!--echo "echo"--> # Text::Tmpl
#set($set = 1) # Velocity
[% GET GET %] # OK in TT3 or Template::Alloy, error in TT2
[% GET %] # Error in TT2, TT3 or Template::Alloy
Using a namespace such as [% var:GET %] seems like a partial solution. If
directives are going to be hoisted to a higher level (such as is easy to do
in Template::Alloy and TT3) then there needs to be a way to disambiguate
directives from variables (the dir:GET is possible - but I think a
punctuation solution may be better) or we have to be extremely careful in
picking new DIRECTIVE names.
> (I'm not sure about 'dir:' as a prefix, BTW. It could be confused with a
> directory, but whatever it's called, you get the idea).
I think 'dir' is too easily confused.
> Namespaces provide general purpose parser hooks. As well as being used to
> disambiguating tokens for the parser, they can be used to implement all
> kinds of other interesting compile time behaviour.
I think they sound interesting.
> So we'll have a namespace handler that you can enable/disable which
> provides access to the file/line data and anything else relating to the
> template. e.g.
>
> [% template:file = 'badger' %]
> [% template:line = 42 %]
This seems to negate the need for the FILE and LINE directives. If there are
both and they aren't merged, it seems that it is going to introduce a bit of
confusion to newcomers when they should use one or the other. Perhaps the
FILE and LINE directives should be named ERROR_FILE and ERROR_LINE.
> The nice thing is that these "variables" are resolved at compile time, but
> can be used at runtime. So if you write:
>
> [% call_my_sub(template:file, template:line) %]
This is nice and certainly would be easy to add to Alloy.
> As an aside, this also gives you an easy way to define your own constants.
> Something like this:
>
> Template->new(
> namespaces => {
> site => {
> constants => {
> And then this:
>
> Welcome to [% site:title %].
> Which is compiled down to this:
>
> Welcome to Badger World
That is nice. TT2 already has that mechanism with the NAMESPACE
configuration - the only difference being using a "." instead of the ":". I
know that there will be different parsing methods available to each
namespace - but that is about the only difference in this particular use
case. It seems to be YAWTPIV (yet another way to pass in variables).
I know that there is much more to namespaces, and that we'll be able to do
many neat things with them, and that they'll be easy to use. The
HTML::Template camp prides itself on simplicity - which is why they had to
write HTML::Template::Expr (because HTML::Template was too simple). The
Template toolkit camp loves the amount of functionality that is available in
TT2. I love the amount of functionality that is available in TT. I think
that it is the perfect level of functionality. I think that there is a point
that too much functionality can be added to future versions of TT. I think
VIEWs are an example of too much functionality. The documentation somewhere
mentioned that they did solve a fairly complex problem somewhere - but I
don't know that they warrant being in core. I think namespaces and arbitrary
parsing may be beginning to head in the "too much" direction. I think most
people view TT as a template engine - not as another language. Perhaps the
end goal is to have a PHP competitor with college courses to become certified
in TT. I apologize that this has turned into somewhat of a rant - but
something at the back of my head thinks that TT2 was almost the sweetspot and
that adding more is overkill.
> The problem I have with this from an implementation point of view is that
> it could result in one monolithic CONFIG directive that has to know about
> all the different possible options, how to parse them, and what to do with
> them after that.
There already is one place for all of the CONFIG data - as in when you call
Template->new(\%CONFIG).
Text::Tmpl requires you to call a different method for every configuration
item that you want to set. It is a pain and it is ugly (I've switch contexts
momentarily from operating in the TT mini-language to Perl - but I'll switch
back).
my $obj = Text::Tmpl->new;
$obj->set_delimiters('#[', ']#');
$obj->set_strip(0);
$obj->set_values($vars);
$obj->set_dir("$test_dir/");
Compare that with TT
my $obj = Template->new(
START_TAG => '#[',
END_TAG => ']#',
TRIM => 0,
VARIABLES => $vars,
INCLUDE_PATH => "$test_dir/",
);
Much nicer cleaner. I guess in the end the amount of documentation is about
equal. I just had to repeat myself less.
I think the same holds for configuration set during the processing of a
template. I don't look at the CONFIG directive as squashing it all into one
place, I look at it as one place to look and see what I can configure. I
think it is more consistent and easy to the developer. And it helps with the
non-proliferation of directives.
Along a similar vein - one area that I'd like to see in TT is the ability to
call a method to update the configuration at a later point before or after
templates are processed - as in
my $obj = Template->new;
$obj->config(TRIM => 0);
Once you have this ability, well then the CONFIG directive is a trivial call
to this method.
> It's not particularly difficult to implement that way, but I think it will
> lead to an implementation which is less flexible than the current one where
> each directive does just one thing and can be enabled or disabled at will.
Generally items such as TAGS or LINE are going to need access to the guts in
order to function properly - they are inflexible by nature. For example,
without access to the parsing guts, the TAGS directive would always have to
be used as follows:
[% TAGS html --><!-- GET foo --><!-- TAGS template %]
Notice the need to have the closing tag end with the newly defined tag, this
is because if the TAGS directive was abstracted, it would have to return
control to the main parser that would then be looking for the new style of
closing tags. This particular issue is why I haven't yet made it possible to
set TAG_STYLE via the CONFIG directive in Template::Alloy. Not everything
can be cleanly abstracted even through abstraction is an admirable goal.
> So if we do have a CONFIG directive then it should just act as a container
> for other directives. Rather than doing any parsing itself, it would just
> enable a bunch of other directives within that scope (i.e. to the end of
> the current tag)
I'd argue the other way around. If you do add the other directives, they
should call the central CONFIG directive's code. The opposite way of looking
at it is that CONFIG already does all of the argument parsing for you. Why
add more directives that have to have their own rules - even if it is easy to
do so. And the CONFIG directive really should use the $template->config
method that already knows how to handle each of the config items. If there
is abstraction - the config method which is called by the CONFIG directive
(and possibly by other custom directives) is where that abstraction should
go.
> That way we can keep TAGS, EMBED, IGNORE, etc., as self-contained
> directives that each do one thing and do it well.
Not sure what EMBED is, but IGNORE (from past threads) would be relatively
easy to abstract to its own compartment. Some directives can be abstracted.
Some cannot. There is going to have to be a distinguishing between the two.
META and VIEW and BLOCK and END tags are all samples that can't be abstracted
as easy.
> In this scenario, they
> would be disabled by default until you hit a CONFIG directive.
If you have to use a CONFIG directive to enable them (assuming you mean FILE
and LINE), why not just use CONFIG to set them.
I do like the thought of the ability to disable directives. This seems like a
good way to drop privileges before including untrusted templates.
> At that
> point, they become enabled (in the same way that 'CASE' is "enabled" within
> the context of a 'SWITCH' directive, for example).
I think that is a bit different. In that case the directive is parsed and
recognized as being out of context. It is always enabled, it just throws an
error if you aren't in a SWITCH. You can't use "CASE" as a variable name
even outside of a SWITCH.
> Hope that makes some kind of sense. In essence, yes, I think we can do
> that, or something like it.
Sounds good.
I'm not meaning to throw so many kinks into the chain here. I'm just wanting
to help make sure that TT remains consistent - even as new features are
added. I am afraid of second system syndrome. I think that Template (the
version 2 series) is in the top 10 of all perl modules ever created. You
have done a remarkable job for the Perl community. I want TT3 to be TT2 with
the quirks ironed out. This email is primarily intended to be a sounding
board to help. In the end - the design is yours.
Paul
_______________________________________________
templates mailing list
[email protected]
http://lists.template-toolkit.org/mailman/listinfo/templates