comparison mercurial/templater.py @ 3641:7b064d8bac5e

template: fold template() into __call__, minor optimizations - use non-grouping operator to avoid some extra processing - avoid copying and updating defaults - unnest main template body - avoid returning extra empty string if format
author Matt Mackall <mpm@selenic.com>
date Mon, 13 Nov 2006 13:26:57 -0600
parents e7639888bb2f
children 5c9a36210662
comparison
equal deleted inserted replaced
3640:e7639888bb2f 3641:7b064d8bac5e
41 format uses key to expand each item in list. syntax is 41 format uses key to expand each item in list. syntax is
42 {key%format}. 42 {key%format}.
43 43
44 filter uses function to transform value. syntax is 44 filter uses function to transform value. syntax is
45 {key|filter1|filter2|...}.''' 45 {key|filter1|filter2|...}.'''
46
47 template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))"
48 r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]")
46 49
47 def __init__(self, mapfile, filters={}, defaults={}, cache={}): 50 def __init__(self, mapfile, filters={}, defaults={}, cache={}):
48 '''set up template engine. 51 '''set up template engine.
49 mapfile is name of file to read map definitions from. 52 mapfile is name of file to read map definitions from.
50 filters is dict of functions. each transforms a value into another. 53 filters is dict of functions. each transforms a value into another.
82 85
83 def __call__(self, t, **map): 86 def __call__(self, t, **map):
84 '''perform expansion. 87 '''perform expansion.
85 t is name of map element to expand. 88 t is name of map element to expand.
86 map is added elements to use during expansion.''' 89 map is added elements to use during expansion.'''
87 m = self.defaults.copy()
88 m.update(map)
89 if not self.cache.has_key(t): 90 if not self.cache.has_key(t):
90 try: 91 try:
91 self.cache[t] = file(self.map[t]).read() 92 self.cache[t] = file(self.map[t]).read()
92 except IOError, inst: 93 except IOError, inst:
93 raise IOError(inst.args[0], _('template file %s: %s') % 94 raise IOError(inst.args[0], _('template file %s: %s') %
94 (self.map[t], inst.args[1])) 95 (self.map[t], inst.args[1]))
95 return self.template(self.cache[t], **m) 96 tmpl = self.cache[t]
96 97
97 template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))"
98 r"(\w+)((%\w+)*)((\|\w+)*)[#}]")
99
100 def template(self, tmpl, **map):
101 while tmpl: 98 while tmpl:
102 m = self.template_re.search(tmpl) 99 m = self.template_re.search(tmpl)
103 if m: 100 if not m:
104 start, end = m.span(0) 101 yield tmpl
105 key = m.group(1) 102 break
106 format = m.group(2) 103
107 fl = m.group(4) 104 start, end = m.span(0)
108 105 key, format, fl = m.groups()
109 if start: 106
110 yield tmpl[:start] 107 if start:
111 108 yield tmpl[:start]
112 v = map.get(key, "") 109 tmpl = tmpl[end:]
113 if callable(v): 110
114 v = v(**map) 111 if key in map:
115 112 v = map[key]
116 if format: 113 else:
117 if not hasattr(v, '__iter__'): 114 v = self.defaults.get(key, "")
118 raise SyntaxError(_("Error expanding '%s%s'") 115 if callable(v):
119 % (key, format)) 116 v = v(**map)
120 lm = map.copy() 117 if format:
121 for i in v: 118 if not hasattr(v, '__iter__'):
122 lm.update(i) 119 raise SyntaxError(_("Error expanding '%s%s'")
123 yield self(format[1:], **lm) 120 % (key, format))
124 121 lm = map.copy()
125 v = "" 122 for i in v:
126 123 lm.update(i)
127 elif fl: 124 yield self(format, **lm)
125 else:
126 if fl:
128 for f in fl.split("|")[1:]: 127 for f in fl.split("|")[1:]:
129 v = self.filters[f](v) 128 v = self.filters[f](v)
130
131 yield v 129 yield v
132 tmpl = tmpl[end:]
133 else:
134 yield tmpl
135 break
136 130
137 agescales = [("second", 1), 131 agescales = [("second", 1),
138 ("minute", 60), 132 ("minute", 60),
139 ("hour", 3600), 133 ("hour", 3600),
140 ("day", 3600 * 24), 134 ("day", 3600 * 24),