Cheetah TODO list
-----------------

* If you are working on a task please put your initials at the end of the
  description

* When a task is completed please remember to note it in the CHANGES file

Languague Specification
================================================================================

- revisit parsed #include directives.  Are they necessary at all??
  (This is a rhetorical question.  They are necessary.  However, the
  Users' Guide needs better examples about when and when not to use
  #include.  Also, consider making '#include' do a raw include, and
  something else do a parsed include ('#include parsed', '#include cheetah'?),
  so that users get parsing only if they explicitly request it.

- write a formalized grammar for Cheetah in BNF 

Implementation
================================================================================

- implement some better error handling for misformed #for, #if, #try directives,
  etc.  At the moment these errors are not caught until Python executes the
  code.

- create better error message for bad code such as:
  ##cache
  This is a cached region.  $voom
  #end cache

- fix bug in Parser.getDefArgList() that is mucking up lists where the comma has
  been forgotten:

  > #cache timer='.5m' id='cache1'
  > This is a cached region.  $voom
  > #end cache
  > 
  > the error is:
  > 
  > "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Compiler.py",
  > line 102, in genCacheInfoFromArgList
  >     val = self.genTimeInterval(val)
  >   File
  > "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/Compiler.py",
  > line 75, in genTimeInterval
  >     interval = float(timeString)*60
  > ValueError: invalid literal for float(): .5m' id'cache1
  > 
  > 
  > Running under pdb shows that Parser.getDefArgList() returned:
  > "30m' id'cache1" .


- Delete whitespace before a comment on the same line.  The methods are
  Parser.eatComment() and Parser.eatMultiLineComment().  It's already
  working if the line contains 'STUFF#slurp   ## comment'.  Need to make
  it work for 'STUFF    ## comment' (but retain the EOL newline).  

- 'python setup.py uninstall'.  This may require hacking an uninstall feature
  into distutils.

- 'errorCatcher None' to stop catching errors in the middle of a template.

- #del is the only statement that's missing, and there seems to be no other way
  to do it.  #silent wants an expression, not a statement.  I'm mainly thinking
  about deleting keys from local dictionaries -- delattr() doesn't do this --
  but there's no reason it shouldn't work on local subscripts, attributes and
  variables too.  Leave open the possibility for '#del global' (opposite of
  '#set global') in the future if it's needed, and 
  '#del searchList $var["key"]' too.  I don't know about '#del searchList $var':
  that could be hard to implement, but maybe somebody will want it someday.

- Finish up changes to #indent so that it matches the Users' Guide. (MO)


Rewrite the caching framework
=============================
- add #cache varyBy= (tied to Tavis' proposed caching framework for Webware)

- #cache test= with a one-variable test produces invalid Python (an empty
  if-block).  Example in Cheetah Developers' Guide, section
  "#cache with test: expression and method conditions".

- #cache id= seems to be ignoring the ID and generating a random numeric
  ID instead.  Is it working?  Do cache IDs have to be numeric?

- Other ideas in Tavis' head.


Cheetah command revamp
===============================================================================
- Usage: cheetah COMMAND ARGUMENTS
- Commands:
     cheetah --help | -h
     cheetah --version
     cheetah compile | c           # .tmpl -> .py
     cheetah fill | f              # .tmpl -> .html       (Not implemented yet)

- Options common to 'compile', 'fill' and 'cgi':
    -i EXT                         # input file extension  (-i '' for no ext)
    -o EXT                         # output file extension (-o '' for no ext)
    -R                             # recurse subdirectories
    -                              # (as input filename) input from stdin
    -p                             # output to stdout

- Options for 'fill' (and .py template modules):
    --env                          # Push environment onto searchList.
    --pickle=FILE                  # Unpickle FILE and push onto searchList.
                                   # (--pickle=-  => unpickle from stdin)

- Remove options:
    cheetah-compile -w             # Same as 'cheetah fill' but less powerful.
    cheetah -c                     # 'cheetah c' is easier to type.
    -p (pickle)                    # Conflicts with -p (to stdout)

- Input extension, unless overridden by -i, is ".tmpl".  If an input file is 
  specified but does not exist, try adding this extension.  When recursing,
  consider only files with this extension.

- Output extension, unless overridden by -o, is ".py" for 'cheetah compile'
  and 'cheetah cgi', and ".html" for 'cheetah fill'.

- Program will examine its own name ( os.path.basename(sys.argv[0]) ), and if
  it looks like "cheetah-WORD", use WORD as the command instead of sys.argv[1] .
  Then cheetah-compile can be a symlink or copy of this, and people can create
  cheetah-fill etc if desired.


#entry $func($arg1, $arg2="default", $**kw)
===============================================================================
Make a wrapper function in the .py template module that builds a searchList
from its positional arguments, then instantiates and fills a template and
returns the result.  The preceding example would create a function thus:
	def func(arg1, arg2="default", searchList=None, **kw):
		"""Function docstring."""
		sl = {'arg1': arg1, 'arg2': arg2}
		if searchList is None:
			searchList = [sl]
		elif type(searchList) == types.ListType:
			searchList.insert(0, sl)
		else:
			raise TypeError("arg 'searchList'")
		t = TheTemplate(searchList=searchList, **kw)
		return str(t)
##doc-entry: and #*doc-entry: comments are appended to the function docstring.
	Finally, make this function accessible directly from the shell.
If there are any non-option arguments on the command line, call the function
instead of filling the template the normal way.  
	This would perhaps make more sense as arguments to .respond().  But
.respond() has that pesky 'trans' argument that mustn't be interfered with,
and other programs may assume .respond() takes only one argument.  Also, 
when called via str(), str() cannot take arguments.
	

Upload File
========================================================================
A mixin method in Cheetah.Utils (for Template) that handles file uploads --
these are too complicated for .webInput().  The method should do a "safe"
file upload; e.g., http://us3.php.net/manual/en/features.file-upload.php ,
within the limitations of Python's cgi module.  The user has the choice of
three destinations for the file contents: (A) copied to a local
path you specify, (B) placed in a namespace variable like .cgiImport()
does, or (C) returned.  (B) parallels .webInput, but (A) will certainly be
desirable situations where we just want to save the file, not read it into
memory.  Reject files larger than a user-specified size or not in a list of
user-approved MIME types.  Define appropriate exceptions for typical
file-upload errors.  Method name .webUploadFileAsString?
	One situation to support is when  form has a text(area) field
related to a file-upload control on the same form, and the user has the choice
of typing into the field or uploading a text file.  We need a method that
updates the text field's value if there is an uploaded file, but not if there
isn't.  This may be handled by the regular method(s) or may require a separate
method.


Test Suite
================================================================================
- test cases for the SkeletonPage framework
- add cases that test the cheetah-compile script
- add cases that test the integration with WebKit.  Since these must be called
  from a running WebKit server, make a servlet that runs the tests and outputs
  diagnostics to the browser.

Website
================================================================================
- automate the documentation update 
- See if we can get WebKit working on Sourceforge...

Examples
================================================================================
- create some non-html code generation examples
  - SQL
  - LaTeX
  - form email
- Template definitions in a database.  .py template modules in a 
  database?  Caching template classes and/or instances extracted from
  a database.
- Pickled templates?

