##// END OF EJS Templates
templater: raise nested functions
Matt Mackall -
r10852:0d50586a default
parent child Browse files
Show More
@@ -17,13 +17,15 b' def _flatten(thing):'
17 if isinstance(thing, str):
17 if isinstance(thing, str):
18 yield thing
18 yield thing
19 elif not hasattr(thing, '__iter__'):
19 elif not hasattr(thing, '__iter__'):
20 yield str(thing)
20 if i is not None:
21 elif thing is not None:
21 yield str(thing)
22 else:
22 for i in thing:
23 for i in thing:
23 if isinstance(i, str):
24 if isinstance(i, str):
24 yield i
25 yield i
25 elif not hasattr(i, '__iter__'):
26 elif not hasattr(i, '__iter__'):
26 yield str(i)
27 if i is not None:
28 yield str(i)
27 elif i is not None:
29 elif i is not None:
28 for j in _flatten(i):
30 for j in _flatten(i):
29 yield j
31 yield j
@@ -64,77 +66,85 b' class engine(object):'
64 self._defaults = defaults
66 self._defaults = defaults
65 self._cache = {}
67 self._cache = {}
66
68
67 def process(self, t, mapping):
69 def _load(self, t):
68 '''Perform expansion. t is name of map element to expand. mapping contains
70 '''load, parse, and cache a template'''
69 added elements for use during expansion. Is a generator.'''
70 if t not in self._cache:
71 if t not in self._cache:
71 self._cache[t] = self._parse(self._loader(t))
72 self._cache[t] = self._parse(self._loader(t))
72 return _flatten(self._process(self._cache[t], mapping))
73 return self._cache[t]
74
75 def process(self, t, mapping):
76 '''Perform expansion. t is name of map element to expand.
77 mapping contains added elements for use during expansion. Is a
78 generator.'''
79
80 return _flatten(self._process(self._load(t), mapping))
81
82 def _get(self, mapping, key):
83 v = mapping.get(key)
84 if v is None:
85 v = self._defaults.get(key, '')
86 if hasattr(v, '__call__'):
87 v = v(**mapping)
88 return v
89
90 def _raw(self, mapping, x):
91 return x
92
93 def _filter(self, mapping, parts):
94 filters, val = parts
95 x = self._get(mapping, val)
96 for f in filters:
97 x = f(x)
98 return x
99
100 def _format(self, mapping, args):
101 key, parsed = args
102 v = self._get(mapping, key)
103 if not hasattr(v, '__iter__'):
104 raise SyntaxError(_("error expanding '%s%%%s'")
105 % (key, format))
106 lm = mapping.copy()
107 for i in v:
108 if isinstance(i, dict):
109 lm.update(i)
110 yield self._process(parsed, lm)
111 else:
112 # v is not an iterable of dicts, this happen when 'key'
113 # has been fully expanded already and format is useless.
114 # If so, return the expanded value.
115 yield i
73
116
74 def _parse(self, tmpl):
117 def _parse(self, tmpl):
75 '''preparse a template'''
118 '''preparse a template'''
76
119
77 defget = self._defaults.get
78 def getter(mapping, key):
79 v = mapping.get(key)
80 if v is None:
81 v = defget(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
111 parsed = []
120 parsed = []
112 pos, stop = 0, len(tmpl)
121 pos, stop = 0, len(tmpl)
113 while pos < stop:
122 while pos < stop:
114 n = tmpl.find('{', pos)
123 n = tmpl.find('{', pos)
115 if n < 0:
124 if n < 0:
116 parsed.append((raw, tmpl[pos:stop]))
125 parsed.append((self._raw, tmpl[pos:stop]))
117 break
126 break
118 if n > 0 and tmpl[n - 1] == '\\':
127 if n > 0 and tmpl[n - 1] == '\\':
119 # escaped
128 # escaped
120 parsed.append((raw, tmpl[pos:n + 1]))
129 parsed.append((self._raw, tmpl[pos:n + 1]))
121 pos = n + 1
130 pos = n + 1
122 continue
131 continue
123 if n > pos:
132 if n > pos:
124 parsed.append((raw, tmpl[pos:n]))
133 parsed.append((self._raw, tmpl[pos:n]))
125
134
126 pos = n
135 pos = n
127 n = tmpl.find('}', pos)
136 n = tmpl.find('}', pos)
128 if n < 0:
137 if n < 0:
129 # no closing
138 # no closing
130 parsed.append((raw, tmpl[pos:stop]))
139 parsed.append((self._raw, tmpl[pos:stop]))
131 break
140 break
132
141
133 expr = tmpl[pos + 1:n]
142 expr = tmpl[pos + 1:n]
134 pos = n + 1
143 pos = n + 1
135
144
136 if '%' in expr:
145 if '%' in expr:
137 parsed.append((formatter, expr.split('%')))
146 key, t = expr.split('%')
147 parsed.append((self._format, (key, self._load(t))))
138 elif '|' in expr:
148 elif '|' in expr:
139 parts = expr.split('|')
149 parts = expr.split('|')
140 val = parts[0]
150 val = parts[0]
@@ -142,9 +152,9 b' class engine(object):'
142 filters = [self._filters[f] for f in parts[1:]]
152 filters = [self._filters[f] for f in parts[1:]]
143 except KeyError, i:
153 except KeyError, i:
144 raise SyntaxError(_("unknown filter '%s'") % i[0])
154 raise SyntaxError(_("unknown filter '%s'") % i[0])
145 parsed.append((filt, (filters, val)))
155 parsed.append((self._filter, (filters, val)))
146 else:
156 else:
147 parsed.append((getter, expr))
157 parsed.append((self._get, expr))
148
158
149 return parsed
159 return parsed
150
160
General Comments 0
You need to be logged in to leave comments. Login now