summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorianb <devnull@localhost>2007-07-24 01:03:50 +0000
committerianb <devnull@localhost>2007-07-24 01:03:50 +0000
commit550480d76ba9a5632e39461cfa81dfd92473d77f (patch)
treedb7eebfc9ee94db0f18ce9f23e9f719da04c4957
parent5e4933d8e0c9c5424872ed789ad999229c00bbb0 (diff)
downloadtempita-550480d76ba9a5632e39461cfa81dfd92473d77f.tar.gz
more docs
-rw-r--r--docs/index.txt200
1 files changed, 187 insertions, 13 deletions
diff --git a/docs/index.txt b/docs/index.txt
index f19e8d5..50d05f5 100644
--- a/docs/index.txt
+++ b/docs/index.txt
@@ -93,6 +93,13 @@ Lastly, you can give a dictionary-like object as the argument to
There's also an `HTMLTemplate`_ class that is more appropriate for
templates that produce HTML.
+You can also instantiate a template from a filename with
+``Template.from_filename(filename, namespace={}, encoding=None)``.
+This is like calling::
+
+ Template(open(filename, 'rb').read().decode(encoding),
+ name=filename, namespace=namespace)
+
Unicode
-------
@@ -108,12 +115,17 @@ attribute. It will try to use that encoding whenever ``unicode`` and
>>> tmpl.substitute(name=u'Jos\xe9')
'Hi Jos\xc3\xa9'
+The default encoding is UTF8.
+
The Language
============
The language is fairly simple; all the constructs look like
``{{stuff}}``.
+Substitution
+------------
+
To insert a variable or expression, use ``{{expression}}``. You can't
use ``}}`` in your expression, but if it comes up just use ``} }``
(put a space between them). You can pass your expression through
@@ -127,6 +139,21 @@ If you want to have ``{{`` or ``}}`` in your template, you must use
the built-in variables like ``{{start_braces}}`` and
``{{end_braces}}``. There's no escape character.
+None, as a special case, is substituted as the empty string.
+
+Also there is a command for setting default values in your template::
+
+ {{default width = 100}}
+
+You can use this so that the ``width`` variable will always have a
+value in your template (the number ``100``). If someone calls
+``tmpl.substitute(width=200)`` then this will have no effect; only if
+the variable is undefined will this default matter. You can use any
+expression to the right of the ``=``.
+
+if
+--
+
You can do an if statement with::
{{if condition}}
@@ -140,12 +167,20 @@ You can do an if statement with::
Some of the blank lines will be removed when, as in this case, they
only contain a single directive. A trailing ``:`` is optional.
+for
+---
+
Loops should be unsurprising::
{{for a, b in items}}
{{a}} = {{b | repr}}
{{endfor}}
+See? Unsurprising.
+
+Python blocks
+-------------
+
For anything more complicated, you can use blocks of Python code,
like::
@@ -172,26 +207,165 @@ define functions. So you can do something like::
{{s | pad}} {{value | repr}}
{{endfor}}
-The last construct is for setting defaults in your template, like::
+As a last detail ``{{# comments...}}`` doesn't do anything at all,
+because it is a comment.
- {{default width = 100}}
+bunch and looper
+----------------
-You can use this so that the ``width`` variable will always have a
-value in your template (the number ``100``). If someone calls
-``tmpl.substitute(width=200)`` then this will have no effect; only if
-the variable is undefined will this default matter.
+There's two kinds of objects provided to help you in your templates.
+The first is ``tempita.bunch``, which is just a dictionary that also
+lets you use attributes::
-As a last detail ``{{# comments...}}`` doesn't do anything at all,
-because it is a comment.
+ >>> bunch = tempita.bunch(a=1)
+ >>> bunch.a
+ 1
+ >>> bunch.items()
+ [('a', 1)]
+ >>> bunch.default = None
+ >>> print bunch.b
+ None
+
+This can be nice for passing options into a template.
+
+The other object is for use inside the template, and is part of the
+default namespace, ``looper``. This can be used in ``for`` loops in
+some convenient ways. You basically use it like::
+
+ {{for loop, item in looper(seq)}}
+ ...
+ {{endfor}}
+
+The ``loop`` object has a bunch of useful methods and attributes::
+
+ ``.index``
+ The index of the current item (like you'd get with
+ ``enumerate()``)
+ ``.number``
+ The number: ``.index + 1``
+ ``.item``
+ The item you are looking at. Which you probably already have,
+ but it's there if you want it.
+ ``.next``
+ The next item in the sequence, or None if it's the last item.
+ ``.previous``
+ The previous item in the sequence, or None if it's the first
+ item.
+ ``.odd``
+ True if this is an odd item. The first item is even.
+ ``.even``
+ True if it's even.
+ ``.first``
+ True if this is the first item.
+ ``.last``
+ True if this is the last item.
+ ``.length``
+ The total length of the sequence.
+ ``.first_group(getter=None)``
+ Returns true if this item is the first in the group, where the
+ group is either of equal objects (probably boring), or when you
+ give a getter. getter can be ``'.attribute'``, like
+ ``'.last_name'`` -- this lets you group people by their last
+ name. Or a method, like ``'.birth_year()'`` -- which calls the
+ method. If it's just a string, it is expected to be a key in a
+ dictionary, like ``'name'`` which groups on ``item['name']``.
+ Or you can give a function which returns the value to group on.
+ This always returns true when ``.first`` returns true.
+ ``.last_group(getter=None)``
+ Like ``first_group``, only returns True when it's the last of
+ the group. This always returns true when ``.last`` returns true.
+
+Note that there's currently a limitation in the templating language,
+so you can't do ``{{for loop, (key, value) in looper(d.items())}}``.
+You'll have to do::
+
+ {{for loop, key_value in looper(d.items())}}
+ {{py:key, value = key_value}}
+ ...
+ {{endfor}}
+
+HTMLTemplate
+============
+
+In addition to ``Template`` there is a template specialized for HTML,
+``HTMLTemplate`` (and the substitution function ``sub_html``).
+
+The basic thing that it adds is automatic HTML quoting. All values
+substituted into your template will be quoted unless they are
+specially marked.
+
+You mark objects as instances of ``tempita.html``. The easiest way is
+``{{some_string | html}}``, though you can also use
+``tempita.html(string)`` in your functions.
+
+An example::
+
+ >>> tmpl = tempita.HTMLTemplate('''\
+ ... Hi {{name}}!
+ ... <a href="{{href}}">{{title|html}}</a>''')
+ >>> name = tempita.html('<img src="bob.jpg">')
+ >>> href = 'Attack!">'
+ >>> title = '<i>Homepage</i>'
+ >>> tmpl.substitute(locals())
+ 'Hi <img src="bob.jpg">!\n<a href="Attack!&quot;&gt;"><i>Homepage</i></a>'
+
+It also adds a couple handy builtins::
+
+ ``html_quote(value)``:
+ HTML quotes the value. Turns all unicode values into
+ character references, so it always returns ASCII text. Also
+ it calls ``str(value)`` or ``unicode(value)``, so you can do
+ things like ``html_quote(1)``.
+
+ ``url(value)``:
+ Does URL quoting, similar to ``html_quote()``.
+
+ ``attr(**kw)``:
+ Inserts attributes. Use like::
+
+ <div {{attr(width=width, class_=div_class)}}>
+
+ Then it'll put in something like ``width="{{width}}"
+ class={{div_class}}``. But any attribute that is None is left
+ out entirely.
+
+Extending Tempita
+=================
+
+It's not really meant for extension. Instead you should just write
+Python functions and classes that do what you want, and use them in
+the template. You can either add the namespace to the constructor, or
+extend ``default_namespace`` in your own subclass.
+
+The extension that ``HTMLTemplate`` uses is to subclass and override
+the ``_repr(value, pos)`` function. This is called on each object
+just before inserting it in the template.
+
+Two other methods you might want to look at are ``_eval(code, ns,
+pos)`` and ``_exec(code, ns, pos)``, which evaluate and execute
+expressions and statements. You could probably make this language
+safe with appropriate implementations of those methods.
Still To Do
===========
-Currently nested structures in ``for`` loop assignments don't work,
-like ``for (a, b), c in x``. They should.
+* Currently nested structures in ``for`` loop assignments don't work,
+ like ``for (a, b), c in x``. They should.
+
+* There's no way to handle exceptions, except in your ``py:`` code.
+ I'm not sure what there should be.
+
+* Probably I should try to dedent ``py:`` code.
+
+* There should be some way of calling a function with a chunk of the
+ template. Maybe like::
-There's no way to handle exceptions, except in your ``py:`` code. I'm
-not sure what there should be.
+ {{call expr}}
+ template code...
+ {{endcall}}
-Probably I should try to dedent ``py:`` code.
+ That means ``{{expr(result_of_template_code)}}``. But maybe there
+ should be another assignment form too, if you don't want to
+ immediately put the output in the code. And then you get methods.
+ Is this going too far?