1#========================================================================
2#
3# TODO
4#
5# DESCRIPTION
6#   TODO list for the Template Toolkit version 2.20, containing
7#   known bugs, limitations, planned enhancements, long term visions 
8#   and a few whacky ideas.  Development on TT2 has effectively 
9#   ceased for everything but bug fixes.  All new features and general
10#   enhancements are being saved for TT3.
11#
12# AUTHOR
13#   Andy Wardley   <abw@wardley.org>
14#
15#========================================================================
16
17
18#------------------------------------------------------------------------
19# Miscellaneous
20#------------------------------------------------------------------------
21
22* The 'eval' filter leaks memory, as reported by Colin Johnson.  The
23  filter subroutine created contains a reference to the context and then
24  gets cached in the FILTER_CACHE item of the context.  Hey presto -
25  circular references.  The reset() method should probably clear the
26  FILTER_CACHE.  Also need to check the plugins cache for similar
27  problems.  UPDATE: this may now have been fixed.
28
29* The handling of the DELIMITER parameter could be improved.  At the 
30  moments it's hardcoded and hacked to Do The Right Thing for Win32
31  but I'd prefer it to Do The Good Thing.
32
33* If you use 'ttree' with a COMPILE_EXT or COMPILE_DIR option then
34  templates in the 'lib' directories will be compiled, but those in
35  the src directories will not.  This is because ttree does a chdir()
36  to the src directory and processes files as './myfile'.  TT doesn't
37  compile RELATIVE files by default.
38
39* No recursion checking is performed for BLOCKs, only
40  Template::Document instances.  This is probably the way it will stay
41  (unless anyone shouts loudly enough) but it should be documented
42  anyway.  STOP PRESS: I had an idea that bare BLOCK subs should be
43  blessed into Template::Document class to allow $template->process()
44  to be called regardless.  Template::Document methods would need to
45  test $self for CODE/HASH and Do The Right Thing.  This would then
46  allow recursion testing for BLOCKs as well as Template::Document
47  objects.
48
49* It would be nice if there was an option so that the files generated
50  under the COMPILE_DIR are relative to the INCLUDE_PATH and not absolute.
51  This could cause potential conflicts (e.g. if INCLUDE_PATH changes
52  between sessions and the same files in different INCLUDE_PATH dirs
53  maps to the samed compiled version) but is convenient for those times
54  when you know that's not going to be a problem.
55
56* Craig Barratt notes, in fixing the problem with NEXT not working 
57  inside SWITCH (see Changes v2.04):
58
59    By the way, I came across another arcane bug:
60
61	NEXT FOREACH k = [1];
62
63    is legal syntax but is an infinite loop, since $_[0]->{ INFOR } in
64    Parser.yp is not set when the NEXT is parsed, so it generates a
65    plain "next;" rather than calling $factor->next().  I don't see an
66    easy, clean fix.
67
68
69#------------------------------------------------------------------------
70# Documentation
71#------------------------------------------------------------------------
72
73* Extend the FAQ.
74
75
76#------------------------------------------------------------------------
77# Directives
78#------------------------------------------------------------------------
79
80* A 'FOR', like 'FOREACH' but without using an iterator.  You wouldn't get 
81  the 'loop' reference to test 'first', 'last', etc., against, but it would
82  be faster for those cases when you didn't need it.  This will likely 
83  be implemented as a facility feature (see later).
84
85* PRINT should be defined as a new directive, doing what the print() 
86  method of Template::View currently does (the Right Thing).
87
88    [% PRINT node %]    ===    [% tt.view.print(node) %]
89
90  NOTE TO SELF: this is a Very Good Idea [tm].  PRINT becomes the way to 
91  display a data structure (e.g. hash, list, XML element, MyThingy, database
92  record, etc.) in an "intelligent" fashion.  Implemented underneath via 
93  the current default VIEW.
94
95* ARGS.  There may be a requirement for reusable template components
96  to define what variables they plan to use.  This would allow some
97  optimisation and also possibly help to avoid global variable clashes.
98  Would also be a useful "comment" directive for human readers and maybe
99  also help in debugging (WARNING: expected 'title' argument).
100
101    [% ARGS title		# no default
102	    bgcol='#ffffff'	# default value
103    %]
104
105
106#------------------------------------------------------------------------
107# Parser
108#------------------------------------------------------------------------
109
110* Lists don't accept arbitrary expressions as elements, although 
111  function arguments now do.  So you can do this: [% foo(bar + 1) %],
112  but you can't do this: [% foo = [bar + 1] %].  This has been fixed in 
113  the v3 parser.  
114
115* The parser isn't as intelligent as it could be about blocks of template
116  code commented out en masse.  The pre-scanner find the first terminating 
117  END_TAG after an opening tag, regardless of it being on a 
118  commented line or not.
119  e.g.
120    [%#
121      # 
122      #  [% INCLUDE blah %] <- directive ends here
123      #  foo                <- this gets printed
124    %]
125
126* Craig Barratt reports the following:
127
128  I looked at Parse.yp to see how hard it would be to push FILTER
129  evaluation down into the expr rule, so that you could put filters
130  inside expressions (eg: using repeat() just like &quot;x&quot; in
131  perl).  More about that later.
132
133  In browsing through Parser.yp I noticed several issues:
134
135  - The operator precedence is very different to perl, C etc.
136    For example, these expressions evaluate differently in
137    TT2 versus perl, C etc:
138
139      + "1 || 0 && 0" evaluates to 0 in TT2 and 1 in perl or C.  
140        TT2 parses it as (1||0) && 0; in perl and C && is higher
141        precedence than ||.
142
143      + "1 + !0 + 1" evaluates to 1 in TT2 and 3 in perl or C.
144        TT2 parses it as 1 + !(0 + 1); in perl and C ! is higher
145        precedence than +.
146
147      + Many other expressions parse incorrectly, but the effect
148        is benign since most rules return flat text that perl
149        correctly re-parses.  Eg, 2 * 3 + 4 is incorrectly parsed
150        as (2 * (3 + 4)), but happily just the string "2 * 3 + 4"
151        is compiled by perl, which correctly evaluates it as
152        (2 * 3) + 4.
153
154  - There is no unary minus and the NUMBER token is signed. So you can
155    write "x = -2;" but not "x = -y;". Moreover, "x = 1 -1;" is a syntax
156    error (since "1 -1" returns just two tokens NUMBER, NUMBER). (As a
157    workaround you can rewrite these as "x = 0-y;" and "x = 1 - 1".)
158
159  - You cannot have expressions in lists ([..]) and function arguments.
160
161  I have modified the Parser.pm (to make NUMBER unsigned) and modified
162  Grammar.pm.skel and Parser.yp to fix most of these issues (improved
163  operator precedence, unary minus and plus), and also to allow
164  expressions in a few more places (eg: range).  But the last item
165  has me stuck.
166
167  The parse rules for lists and function arguments make COMMA optional,
168  so you can equivalently write [1 2 3 4] or [1,,,,,2 3 4] or [1,2,3,4].
169  This makes it very difficult to make each term an expression, because
170  the resulting grammar has many ambiguities.  For example, is [1 -1]
171  two elements [1, -1] or a single element [0]?  One partial solution is
172  to move the bracketed expression rule '(' expr ')' to the term rule,
173  allowing expressions to be included via parens.  But there are also
174  ambiguities, eg: does [foo (1+1)] have 2 elements or is it a function
175  call to foo?
176
177  Without allowing expressions in lists or function arguments, the unary
178  minus change I've made means that the NUMBER token is unsigned, so with
179  my changes you cannot write [-1, 2, 3].  Not a good thing.
180
181  One solution is to change the grammar so that COMMAs are required in
182  lists and arguments, but that would break several test cases and
183  probably break lots of old templates.  But this might be the only
184  way to produce a grammar that is a lot more similar to perl.
185
186  Another solution is to ignore these issues altogether and use temporary
187  variables to precompute expressions that you need in lists or function
188  arguments, or use explicit lvalue assignments, eg:
189
190    foo(x + 2);             becomes    temp = x + 2;
191                                       foo(temp);
192
193  or
194
195    List = [x+1,x+2,x+4];   becomes    List   = [];
196                                       List.0 = x+1;
197                                       List.1 = x+2;
198                                       List.2 = x+4;
199
200  Both of these look ugly to me.
201
202  Back to the FILTER issues. Ultimately I'd like to be able to embed filters
203  as low precedence operators in expressions, and write:
204
205    List = [
206        "foo" | repeat(10),
207        "bar" | repeat(10)
208    ];
209
210  but I doubt there is a non-ambiguous upward compatible grammar that
211  supports this.
212
213  Comments?
214
215
216#------------------------------------------------------------------------
217# Plugins
218#------------------------------------------------------------------------
219
220* We need a way to easily enable/disable certain plugins.  This should
221  be addressed by facility provision.  Probably something for v3.
222
223* The Template::Plugin DBI iterator first/last() methods don't behave 
224  the same as list first/last().  Randal also reports that get_all()
225  doesn't work as it should - may be a conflict in code/docs?  Again,
226  this is a problem to solve in TT3.
227
228* PLUGINS could accept a reference to an object which is used as a 
229  singleton factory for a plugin.  (NOTE: 2.01 includes PLUGIN_FACTORY
230  to implement this, but currently undocumented because it's likely to
231  change).
232
233* A more general solution for XML (e.g. DOM, XPath, etc) would be for
234  TT to support a PerlSAX handler which generates the appropriate
235  callbacks to the view.  This should make it possible to easily
236  display XML content from XML::DOM, XML::XPath, or any other SAX
237  compliant source.
238
239  Something like this:
240
241    # define a view
242    [% VIEW my_view 
243         prefix="my/xml/dom/path/" ;
244       END
245    %]
246
247    # get some XML
248    [% USE dom = XML.DOM %]
249    [% doc = dom.parser(my.files.xmldata) %]
250    
251    # ask the view to print the data
252    [% my_view.print(doc) %]
253
254  The view print() method will call the relevant 2SAX method on the 
255  XML node, passing a SAX2TTView handler to make the relevant calls 
256  back to the view to display parts of the XML data model as SAX events
257  are received.
258
259
260#------------------------------------------------------------------------
261# Views
262#------------------------------------------------------------------------
263
264The current implementation is there to get me (and anybody else who's
265interested) using it and trying to identify the problems, requirements
266and general issues involved.  I've got a better idea now about what a
267VIEW should be in notional terms, but I'm still not quite sure about
268the syntax and API.
269
270General thoughts:
271
272* A view defines a set of templates.  Things like prefix, suffix, 
273  default, etc., can be specified to customise template selection.
274  In this sense, it is like a custom provider of those templates.
275  It implements the template() method to fetch a template according
276  to those rules.
277
278* It is also a custom processor of those templates.  It implements the 
279  process() method.  In this sense, it is like a custom context.
280
281* It also implements dispatch logic to apply the right template to the
282  right kind of data.  It does this via the print() method.  It may 
283  have all kinds of custom dispatch logic.
284
285* A view takes responsiblity for things template related as opposed 
286  to anything data related (stash) or application logic related
287  (plugins, runtime code, etc).  It is the user interface facility
288  within the engine.
289
290