##// END OF EJS Templates
templater: separate template management and actual string processing
Dirkjan Ochtman -
r8218:e61cb281 default
parent child Browse files
Show More
@@ -21,7 +21,7 b' def parsestring(s, quoted=True):'
21
21
22 return s.decode('string_escape')
22 return s.decode('string_escape')
23
23
24 class templater(object):
24 class engine(object):
25 '''template expansion engine.
25 '''template expansion engine.
26
26
27 template expansion works like this. a map file contains key=value
27 template expansion works like this. a map file contains key=value
@@ -44,6 +44,68 b' class templater(object):'
44 template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))"
44 template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))"
45 r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]")
45 r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]")
46
46
47 def __init__(self, loader, filters={}, defaults={}):
48 self.loader = loader
49 self.filters = filters
50 self.defaults = defaults
51
52 def process(self, t, map):
53 '''Perform expansion. t is name of map element to expand. map contains
54 added elements for use during expansion. Is a generator.'''
55 tmpl = self.loader(t)
56 iters = [self._process(tmpl, map)]
57 while iters:
58 try:
59 item = iters[0].next()
60 except StopIteration:
61 iters.pop(0)
62 continue
63 if isinstance(item, str):
64 yield item
65 elif item is None:
66 yield ''
67 elif hasattr(item, '__iter__'):
68 iters.insert(0, iter(item))
69 else:
70 yield str(item)
71
72 def _process(self, tmpl, map):
73 '''Render a template. Returns a generator.'''
74 while tmpl:
75 m = self.template_re.search(tmpl)
76 if not m:
77 yield tmpl
78 break
79
80 start, end = m.span(0)
81 key, format, fl = m.groups()
82
83 if start:
84 yield tmpl[:start]
85 tmpl = tmpl[end:]
86
87 if key in map:
88 v = map[key]
89 else:
90 v = self.defaults.get(key, "")
91 if callable(v):
92 v = v(**map)
93 if format:
94 if not hasattr(v, '__iter__'):
95 raise SyntaxError(_("Error expanding '%s%%%s'")
96 % (key, format))
97 lm = map.copy()
98 for i in v:
99 lm.update(i)
100 yield self.process(format, lm)
101 else:
102 if fl:
103 for f in fl.split("|")[1:]:
104 v = self.filters[f](v)
105 yield v
106
107 class templater(object):
108
47 def __init__(self, mapfile, filters={}, defaults={}, cache={},
109 def __init__(self, mapfile, filters={}, defaults={}, cache={},
48 minchunk=1024, maxchunk=65536):
110 minchunk=1024, maxchunk=65536):
49 '''set up template engine.
111 '''set up template engine.
@@ -79,7 +141,7 b' class templater(object):'
79 def __contains__(self, key):
141 def __contains__(self, key):
80 return key in self.cache or key in self.map
142 return key in self.cache or key in self.map
81
143
82 def _template(self, t):
144 def load(self, t):
83 '''Get the template for the given template name. Use a local cache.'''
145 '''Get the template for the given template name. Use a local cache.'''
84 if not t in self.cache:
146 if not t in self.cache:
85 try:
147 try:
@@ -89,69 +151,14 b' class templater(object):'
89 (self.map[t], inst.args[1]))
151 (self.map[t], inst.args[1]))
90 return self.cache[t]
152 return self.cache[t]
91
153
92 def _process(self, tmpl, map):
93 '''Render a template. Returns a generator.'''
94 while tmpl:
95 m = self.template_re.search(tmpl)
96 if not m:
97 yield tmpl
98 break
99
100 start, end = m.span(0)
101 key, format, fl = m.groups()
102
103 if start:
104 yield tmpl[:start]
105 tmpl = tmpl[end:]
106
107 if key in map:
108 v = map[key]
109 else:
110 v = self.defaults.get(key, "")
111 if callable(v):
112 v = v(**map)
113 if format:
114 if not hasattr(v, '__iter__'):
115 raise SyntaxError(_("Error expanding '%s%%%s'")
116 % (key, format))
117 lm = map.copy()
118 for i in v:
119 lm.update(i)
120 t = self._template(format)
121 yield self._process(t, lm)
122 else:
123 if fl:
124 for f in fl.split("|")[1:]:
125 v = self.filters[f](v)
126 yield v
127
128 def __call__(self, t, **map):
154 def __call__(self, t, **map):
129 stream = self.expand(t, **map)
155 proc = engine(self.load, self.filters, self.defaults)
156 stream = proc.process(t, map)
130 if self.minchunk:
157 if self.minchunk:
131 stream = util.increasingchunks(stream, min=self.minchunk,
158 stream = util.increasingchunks(stream, min=self.minchunk,
132 max=self.maxchunk)
159 max=self.maxchunk)
133 return stream
160 return stream
134
161
135 def expand(self, t, **map):
136 '''Perform expansion. t is name of map element to expand. map contains
137 added elements for use during expansion. Is a generator.'''
138 tmpl = self._template(t)
139 iters = [self._process(tmpl, map)]
140 while iters:
141 try:
142 item = iters[0].next()
143 except StopIteration:
144 iters.pop(0)
145 continue
146 if isinstance(item, str):
147 yield item
148 elif item is None:
149 yield ''
150 elif hasattr(item, '__iter__'):
151 iters.insert(0, iter(item))
152 else:
153 yield str(item)
154
155 def templatepath(name=None):
162 def templatepath(name=None):
156 '''return location of template file or directory (if no name).
163 '''return location of template file or directory (if no name).
157 returns None if not found.'''
164 returns None if not found.'''
General Comments 0
You need to be logged in to leave comments. Login now