Mercurial > hg
comparison mercurial/templater.py @ 10845:9d8194c2fcbd
templater: preparse templates and cache
This breaks templates down into a list of literal and {} groups, with
group types preidentified.
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 05 Apr 2010 15:25:08 -0500 |
parents | b91c1804008e |
children | 594140b1e12d |
comparison
equal
deleted
inserted
replaced
10844:6722ba3bf80b | 10845:9d8194c2fcbd |
---|---|
45 def __init__(self, loader, filters={}, defaults={}): | 45 def __init__(self, loader, filters={}, defaults={}): |
46 self.loader = loader | 46 self.loader = loader |
47 self.filters = filters | 47 self.filters = filters |
48 self.defaults = defaults | 48 self.defaults = defaults |
49 self.cache = {} | 49 self.cache = {} |
50 self.parsecache = {} | |
50 | 51 |
51 def process(self, t, map): | 52 def process(self, t, map): |
52 '''Perform expansion. t is name of map element to expand. map contains | 53 '''Perform expansion. t is name of map element to expand. map contains |
53 added elements for use during expansion. Is a generator.''' | 54 added elements for use during expansion. Is a generator.''' |
54 tmpl = self.loader(t) | 55 if t not in self.parsecache: |
55 iters = [self._process(tmpl, map)] | 56 tmpl = self.loader(t) |
57 self.parsecache[t] = self._parse(tmpl) | |
58 parsed = self.parsecache[t] | |
59 iters = [self._process(parsed, map)] | |
56 while iters: | 60 while iters: |
57 try: | 61 try: |
58 item = iters[0].next() | 62 item = iters[0].next() |
59 except StopIteration: | 63 except StopIteration: |
60 iters.pop(0) | 64 iters.pop(0) |
98 x = f(x) | 102 x = f(x) |
99 return x | 103 return x |
100 self.cache[expr] = apply | 104 self.cache[expr] = apply |
101 return self.cache[expr](get) | 105 return self.cache[expr](get) |
102 | 106 |
103 def _process(self, tmpl, map): | 107 def _parse(self, tmpl): |
108 '''preparse a template''' | |
109 | |
110 parsed = [] | |
111 pos, stop = 0, len(tmpl) | |
112 while pos < stop: | |
113 n = tmpl.find('{', pos) | |
114 if n < 0: | |
115 parsed.append(('', tmpl[pos:stop])) | |
116 break | |
117 if n > 0 and tmpl[n - 1] == '\\': | |
118 # escaped | |
119 parsed.append(('', tmpl[pos:n + 1])) | |
120 pos = n + 1 | |
121 continue | |
122 if n > pos: | |
123 parsed.append(('', tmpl[pos:n])) | |
124 | |
125 pos = n | |
126 n = tmpl.find('}', pos) | |
127 if n < 0: | |
128 # no closing | |
129 parsed.append(('', tmpl[pos:stop])) | |
130 break | |
131 | |
132 expr = tmpl[pos + 1:n] | |
133 pos = n + 1 | |
134 | |
135 if '%' in expr: | |
136 parsed.append(('%', expr)) | |
137 elif '|' in expr: | |
138 parsed.append(('|', expr)) | |
139 else: | |
140 parsed.append(('g', expr)) | |
141 | |
142 return parsed | |
143 | |
144 def _process(self, parsed, map): | |
104 '''Render a template. Returns a generator.''' | 145 '''Render a template. Returns a generator.''' |
105 | 146 |
106 def get(key): | 147 def get(key): |
107 v = map.get(key) | 148 v = map.get(key) |
108 if v is None: | 149 if v is None: |
109 v = self.defaults.get(key, '') | 150 v = self.defaults.get(key, '') |
110 if hasattr(v, '__call__'): | 151 if hasattr(v, '__call__'): |
111 v = v(**map) | 152 v = v(**map) |
112 return v | 153 return v |
113 | 154 |
114 pos, stop = 0, len(tmpl) | 155 for t, e in parsed: |
115 while pos < stop: | 156 if not t: |
116 n = tmpl.find('{', pos) | 157 yield e |
117 if n < 0: | 158 elif t is '|': |
118 yield tmpl[pos:stop] | 159 yield self._filter(e, get, map) |
119 break | 160 elif t is '%': |
120 if n > 0 and tmpl[n - 1] == '\\': | 161 yield self._format(e, get, map) |
121 # escaped | 162 elif t is 'g': |
122 yield tmpl[pos:n + 1] | 163 yield get(e) |
123 pos = n + 1 | |
124 continue | |
125 if n > pos: | |
126 yield tmpl[pos:n] | |
127 | |
128 pos = n | |
129 n = tmpl.find('}', pos) | |
130 if n < 0: | |
131 # no closing | |
132 yield tmpl[pos:stop] | |
133 break | |
134 | |
135 expr = tmpl[pos + 1:n] | |
136 pos = n + 1 | |
137 | |
138 if '%' in expr: | |
139 yield self._format(expr, get, map) | |
140 elif '|' in expr: | |
141 yield self._filter(expr, get, map) | |
142 else: | |
143 yield get(expr) | |
144 | 164 |
145 engines = {'default': engine} | 165 engines = {'default': engine} |
146 | 166 |
147 class templater(object): | 167 class templater(object): |
148 | 168 |