comparison mercurial/templater.py @ 1896:f8f818a04f5b

move hgweb template code out to templater
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Sun, 26 Feb 2006 12:59:28 -0800
parents
children 58b6784cf9f1
comparison
equal deleted inserted replaced
1800:414e81ae971f 1896:f8f818a04f5b
1 from demandload import demandload
2 demandload(globals(), "cgi os re time urllib util")
3
4 class templater(object):
5 def __init__(self, mapfile, filters={}, defaults={}):
6 self.cache = {}
7 self.map = {}
8 self.base = os.path.dirname(mapfile)
9 self.filters = filters
10 self.defaults = defaults
11
12 for l in file(mapfile):
13 m = re.match(r'(\S+)\s*=\s*"(.*)"$', l)
14 if m:
15 self.cache[m.group(1)] = m.group(2)
16 else:
17 m = re.match(r'(\S+)\s*=\s*(\S+)', l)
18 if m:
19 self.map[m.group(1)] = os.path.join(self.base, m.group(2))
20 else:
21 raise LookupError(_("unknown map entry '%s'") % l)
22
23 def __call__(self, t, **map):
24 m = self.defaults.copy()
25 m.update(map)
26 try:
27 tmpl = self.cache[t]
28 except KeyError:
29 tmpl = self.cache[t] = file(self.map[t]).read()
30 return self.template(tmpl, self.filters, **m)
31
32 def template(self, tmpl, filters={}, **map):
33 while tmpl:
34 m = re.search(r"#([a-zA-Z0-9]+)((%[a-zA-Z0-9]+)*)((\|[a-zA-Z0-9]+)*)#", tmpl)
35 if m:
36 yield tmpl[:m.start(0)]
37 v = map.get(m.group(1), "")
38 v = callable(v) and v(**map) or v
39
40 format = m.group(2)
41 fl = m.group(4)
42
43 if format:
44 q = v.__iter__
45 for i in q():
46 lm = map.copy()
47 lm.update(i)
48 yield self(format[1:], **lm)
49
50 v = ""
51
52 elif fl:
53 for f in fl.split("|")[1:]:
54 v = filters[f](v)
55
56 yield v
57 tmpl = tmpl[m.end(0):]
58 else:
59 yield tmpl
60 return
61
62 def age(x):
63 def plural(t, c):
64 if c == 1:
65 return t
66 return t + "s"
67 def fmt(t, c):
68 return "%d %s" % (c, plural(t, c))
69
70 now = time.time()
71 then = x[0]
72 delta = max(1, int(now - then))
73
74 scales = [["second", 1],
75 ["minute", 60],
76 ["hour", 3600],
77 ["day", 3600 * 24],
78 ["week", 3600 * 24 * 7],
79 ["month", 3600 * 24 * 30],
80 ["year", 3600 * 24 * 365]]
81
82 scales.reverse()
83
84 for t, s in scales:
85 n = delta / s
86 if n >= 2 or s == 1:
87 return fmt(t, n)
88
89 def nl2br(text):
90 return text.replace('\n', '<br/>\n')
91
92 def obfuscate(text):
93 return ''.join(['&#%d;' % ord(c) for c in text])
94
95 common_filters = {
96 "escape": lambda x: cgi.escape(x, True),
97 "urlescape": urllib.quote,
98 "strip": lambda x: x.strip(),
99 "age": age,
100 "date": lambda x: util.datestr(x),
101 "addbreaks": nl2br,
102 "obfuscate": obfuscate,
103 "short": (lambda x: x[:12]),
104 "firstline": (lambda x: x.splitlines(1)[0]),
105 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"),
106 "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"),
107 }