templater: make a template a string-only iterator
authorDirkjan Ochtman <dirkjan@ochtman.nl>
Sun, 29 Jun 2008 13:16:25 +0200
changeset 6783 6d824dc86907
parent 6782 b9d6ab187523
child 6784 18c429ea3a0e
templater: make a template a string-only iterator
mercurial/templater.py
--- a/mercurial/templater.py	Sun Jun 29 14:20:01 2008 +0200
+++ b/mercurial/templater.py	Sun Jun 29 13:16:25 2008 +0200
@@ -81,18 +81,18 @@
     def __contains__(self, key):
         return key in self.cache or key in self.map
 
-    def __call__(self, t, **map):
-        '''perform expansion.
-        t is name of map element to expand.
-        map is added elements to use during expansion.'''
+    def _template(self, t):
+        '''Get the template for the given template name. Use a local cache.'''
         if not t in self.cache:
             try:
                 self.cache[t] = file(self.map[t]).read()
             except IOError, inst:
                 raise IOError(inst.args[0], _('template file %s: %s') %
                               (self.map[t], inst.args[1]))
-        tmpl = self.cache[t]
+        return self.cache[t]
 
+    def _process(self, tmpl, map):
+        '''Render a template. Returns a generator.'''
         while tmpl:
             m = self.template_re.search(tmpl)
             if not m:
@@ -119,13 +119,34 @@
                 lm = map.copy()
                 for i in v:
                     lm.update(i)
-                    yield self(format, **lm)
+                    t = self._template(format)
+                    yield self._process(t, lm)
             else:
                 if fl:
                     for f in fl.split("|")[1:]:
                         v = self.filters[f](v)
                 yield v
 
+    def __call__(self, t, **map):
+        '''Perform expansion. t is name of map element to expand. map contains
+        added elements for use during expansion. Is a generator.'''
+        tmpl = self._template(t)
+        iters = [self._process(tmpl, map)]
+        while iters:
+            try:
+                item = iters[0].next()
+            except StopIteration:
+                iters.pop(0)
+                continue
+            if isinstance(item, str):
+                yield item
+            elif item is None:
+                yield ''
+            elif hasattr(item, '__iter__'):
+                iters.insert(0, iter(item))
+            else:
+                yield str(item)
+
 def templatepath(name=None):
     '''return location of template file or directory (if no name).
     returns None if not found.'''