##// END OF EJS Templates
templater: extend preparsing...
Matt Mackall -
r10846:594140b1 default
parent child Browse files
Show More
@@ -72,95 +72,86 b' class engine(object):'
72 72 else:
73 73 yield str(item)
74 74
75 def _format(self, expr, get, map):
76 key, format = expr.split('%')
77 v = get(key)
78 if not hasattr(v, '__iter__'):
79 raise SyntaxError(_("error expanding '%s%%%s'") % (key, format))
80 lm = map.copy()
81 for i in v:
82 if isinstance(i, dict):
83 lm.update(i)
84 yield self.process(format, lm)
85 else:
86 # v is not an iterable of dicts, this happen when 'key'
87 # has been fully expanded already and format is useless.
88 # If so, return the expanded value.
89 yield i
90
91 def _filter(self, expr, get, map):
92 if expr not in self.cache:
93 parts = expr.split('|')
94 val = parts[0]
95 try:
96 filters = [self.filters[f] for f in parts[1:]]
97 except KeyError, i:
98 raise SyntaxError(_("unknown filter '%s'") % i[0])
99 def apply(get):
100 x = get(val)
101 for f in filters:
102 x = f(x)
103 return x
104 self.cache[expr] = apply
105 return self.cache[expr](get)
106
107 75 def _parse(self, tmpl):
108 76 '''preparse a template'''
109 77
78 def getter(mapping, key):
79 v = mapping.get(key)
80 if v is None:
81 v = self.defaults.get(key, '')
82 if hasattr(v, '__call__'):
83 v = v(**mapping)
84 return v
85
86 def raw(mapping, x):
87 return x
88 def filt(mapping, parts):
89 filters, val = parts
90 x = getter(mapping, val)
91 for f in filters:
92 x = f(x)
93 return x
94 def formatter(mapping, args):
95 key, format = args
96 v = getter(mapping, key)
97 if not hasattr(v, '__iter__'):
98 raise SyntaxError(_("error expanding '%s%%%s'")
99 % (key, format))
100 lm = mapping.copy()
101 for i in v:
102 if isinstance(i, dict):
103 lm.update(i)
104 yield self.process(format, lm)
105 else:
106 # v is not an iterable of dicts, this happen when 'key'
107 # has been fully expanded already and format is useless.
108 # If so, return the expanded value.
109 yield i
110
110 111 parsed = []
111 112 pos, stop = 0, len(tmpl)
112 113 while pos < stop:
113 114 n = tmpl.find('{', pos)
114 115 if n < 0:
115 parsed.append(('', tmpl[pos:stop]))
116 parsed.append((raw, tmpl[pos:stop]))
116 117 break
117 118 if n > 0 and tmpl[n - 1] == '\\':
118 119 # escaped
119 parsed.append(('', tmpl[pos:n + 1]))
120 parsed.append((raw, tmpl[pos:n + 1]))
120 121 pos = n + 1
121 122 continue
122 123 if n > pos:
123 parsed.append(('', tmpl[pos:n]))
124 parsed.append((raw, tmpl[pos:n]))
124 125
125 126 pos = n
126 127 n = tmpl.find('}', pos)
127 128 if n < 0:
128 129 # no closing
129 parsed.append(('', tmpl[pos:stop]))
130 parsed.append((raw, tmpl[pos:stop]))
130 131 break
131 132
132 133 expr = tmpl[pos + 1:n]
133 134 pos = n + 1
134 135
135 136 if '%' in expr:
136 parsed.append(('%', expr))
137 parsed.append((formatter, expr.split('%')))
137 138 elif '|' in expr:
138 parsed.append(('|', expr))
139 parts = expr.split('|')
140 val = parts[0]
141 try:
142 filters = [self.filters[f] for f in parts[1:]]
143 except KeyError, i:
144 raise SyntaxError(_("unknown filter '%s'") % i[0])
145 parsed.append((filt, (filters, val)))
139 146 else:
140 parsed.append(('g', expr))
147 parsed.append((getter, expr))
141 148
142 149 return parsed
143 150
144 def _process(self, parsed, map):
151 def _process(self, parsed, mapping):
145 152 '''Render a template. Returns a generator.'''
146
147 def get(key):
148 v = map.get(key)
149 if v is None:
150 v = self.defaults.get(key, '')
151 if hasattr(v, '__call__'):
152 v = v(**map)
153 return v
154
155 for t, e in parsed:
156 if not t:
157 yield e
158 elif t is '|':
159 yield self._filter(e, get, map)
160 elif t is '%':
161 yield self._format(e, get, map)
162 elif t is 'g':
163 yield get(e)
153 for f, e in parsed:
154 yield f(mapping, e)
164 155
165 156 engines = {'default': engine}
166 157
General Comments 0
You need to be logged in to leave comments. Login now