Index: markup/template.py
===================================================================
--- markup/template.py	(revision 281)
+++ markup/template.py	(working copy)
@@ -1080,6 +1080,106 @@
 SUB = Template.SUB
 
 
+class TextTemplate(Template):
+    """Implementation of a simple text-based template engine.
+    
+    >>> tmpl = TextTemplate('''Dear $name,
+    ... 
+    ... We have the following items for you:
+    ... #for item in items
+    ...  * $item
+    ... #endfor
+    ... 
+    ... All the best,
+    ... Foobar''')
+    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text')
+    Dear Joe,
+    <BLANKLINE>
+    We have the following items for you:
+     * 1
+     * 2
+     * 3
+    <BLANKLINE>
+    All the best,
+    Foobar
+
+    >>> tmpl = TextTemplate('''#def sayhi(name)
+    ... Hello, $name!
+    ... #enddef
+    ... ${sayhi('world')}''')
+    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text')
+    Hello, world!
+    <BLANKLINE>
+    """
+
+    directives = [('def', DefDirective),
+                  ('comment', StripDirective),
+                  ('when', WhenDirective),
+                  ('otherwise', OtherwiseDirective),
+                  ('for', ForDirective),
+                  ('if', IfDirective),
+                  ('choose', ChooseDirective),
+                  ('with', WithDirective)]
+    _dir_by_name = dict(directives)
+    _dir_order = [directive[1] for directive in directives]
+
+    _directive_re = re.compile('^\s*#(\w+.*)\n?', re.MULTILINE)
+
+    def parse(self):
+        stream = [] # list of events of the "compiled" template
+        dirmap = {} # temporary mapping of directives to elements
+        depth = 0
+
+        source = self.source.read()
+        offset = 0
+        lineno = 1
+        for idx, mo in enumerate(self._directive_re.finditer(source)):
+            start, end = mo.span()
+            if start > offset:
+                text = source[offset:start]
+                for kind, data, pos in self._interpolate(text, self.filename,
+                                                         lineno, 0):
+                    stream.append((kind, data, pos))
+                lineno += len(text.splitlines())
+
+            text = source[start:end].lstrip().lstrip('#')
+            lineno += len(text.splitlines())
+            directive = text.split(None, 1)
+            if len(directive) > 1:
+                command, value = directive
+            else:
+                command, value = directive[0], None
+
+            if not command.startswith('end'):
+                cls = self._dir_by_name.get(command)
+                if cls is None:
+                    raise BadDirectiveError(command)
+                directive = cls(value, self.filename, lineno, 0)
+                dirmap[depth] = (directive, len(stream))
+                depth += 1
+            else:
+                depth -= 1
+                command = command[3:]
+                if depth in dirmap:
+                    directive, start_offset = dirmap.pop(depth)
+                    substream = stream[start_offset:]
+                    stream[start_offset:] = [(SUB, ([directive], substream),
+                                              (self.filename, lineno, 0))]
+
+            offset = end
+
+        if offset < len(source):
+            text = source[offset:]
+            for kind, data, pos in self._interpolate(text, self.filename,
+                                                     lineno, 0):
+                stream.append((kind, data, pos))
+
+        return stream
+
+    def _match(self, stream, ctxt=None):
+        return stream
+
+
 class TemplateLoader(object):
     """Responsible for loading templates from files on the specified search
     path.
@@ -1126,7 +1226,7 @@
         self._cache = {}
         self._mtime = {}
 
-    def load(self, filename, relative_to=None):
+    def load(self, filename, relative_to=None, cls=Template):
         """Load the template with the given name.
         
         If the `filename` parameter is relative, this method searches the search
@@ -1179,7 +1279,7 @@
             try:
                 fileobj = open(filepath, 'U')
                 try:
-                    tmpl = Template(fileobj, basedir=dirname, filename=filename)
+                    tmpl = cls(fileobj, basedir=dirname, filename=filename)
                     tmpl.filters.append(IncludeFilter(self))
                 finally:
                     fileobj.close()
