Mercurial > hg
comparison mercurial/templatefilters.py @ 5976:9f1e6ab76069
templates: move filters to their own module
This eliminates just about all Mercurial dependencies in templater.py
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 31 Jan 2008 14:44:19 -0600 |
parents | |
children | 7b937b26adf7 |
comparison
equal
deleted
inserted
replaced
5975:75d9fe70c654 | 5976:9f1e6ab76069 |
---|---|
1 # template-filters.py - common template expansion filters | |
2 # | |
3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms | |
6 # of the GNU General Public License, incorporated herein by reference. | |
7 | |
8 import cgi, re, os, time, urllib, textwrap | |
9 import util, templater | |
10 | |
11 agescales = [("second", 1), | |
12 ("minute", 60), | |
13 ("hour", 3600), | |
14 ("day", 3600 * 24), | |
15 ("week", 3600 * 24 * 7), | |
16 ("month", 3600 * 24 * 30), | |
17 ("year", 3600 * 24 * 365)] | |
18 | |
19 agescales.reverse() | |
20 | |
21 def age(date): | |
22 '''turn a (timestamp, tzoff) tuple into an age string.''' | |
23 | |
24 def plural(t, c): | |
25 if c == 1: | |
26 return t | |
27 return t + "s" | |
28 def fmt(t, c): | |
29 return "%d %s" % (c, plural(t, c)) | |
30 | |
31 now = time.time() | |
32 then = date[0] | |
33 delta = max(1, int(now - then)) | |
34 | |
35 for t, s in agescales: | |
36 n = delta / s | |
37 if n >= 2 or s == 1: | |
38 return fmt(t, n) | |
39 | |
40 para_re = None | |
41 space_re = None | |
42 | |
43 def fill(text, width): | |
44 '''fill many paragraphs.''' | |
45 global para_re, space_re | |
46 if para_re is None: | |
47 para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M) | |
48 space_re = re.compile(r' +') | |
49 | |
50 def findparas(): | |
51 start = 0 | |
52 while True: | |
53 m = para_re.search(text, start) | |
54 if not m: | |
55 w = len(text) | |
56 while w > start and text[w-1].isspace(): w -= 1 | |
57 yield text[start:w], text[w:] | |
58 break | |
59 yield text[start:m.start(0)], m.group(1) | |
60 start = m.end(1) | |
61 | |
62 return "".join([space_re.sub(' ', textwrap.fill(para, width)) + rest | |
63 for para, rest in findparas()]) | |
64 | |
65 def firstline(text): | |
66 '''return the first line of text''' | |
67 try: | |
68 return text.splitlines(1)[0].rstrip('\r\n') | |
69 except IndexError: | |
70 return '' | |
71 | |
72 def isodate(date): | |
73 '''turn a (timestamp, tzoff) tuple into an iso 8631 date and time.''' | |
74 return util.datestr(date, format='%Y-%m-%d %H:%M') | |
75 | |
76 def hgdate(date): | |
77 '''turn a (timestamp, tzoff) tuple into an hg cset timestamp.''' | |
78 return "%d %d" % date | |
79 | |
80 def nl2br(text): | |
81 '''replace raw newlines with xhtml line breaks.''' | |
82 return text.replace('\n', '<br/>\n') | |
83 | |
84 def obfuscate(text): | |
85 text = unicode(text, util._encoding, 'replace') | |
86 return ''.join(['&#%d;' % ord(c) for c in text]) | |
87 | |
88 def domain(author): | |
89 '''get domain of author, or empty string if none.''' | |
90 f = author.find('@') | |
91 if f == -1: return '' | |
92 author = author[f+1:] | |
93 f = author.find('>') | |
94 if f >= 0: author = author[:f] | |
95 return author | |
96 | |
97 def person(author): | |
98 '''get name of author, or else username.''' | |
99 f = author.find('<') | |
100 if f == -1: return util.shortuser(author) | |
101 return author[:f].rstrip() | |
102 | |
103 def shortdate(date): | |
104 '''turn (timestamp, tzoff) tuple into iso 8631 date.''' | |
105 return util.datestr(date, format='%Y-%m-%d', timezone=False) | |
106 | |
107 def indent(text, prefix): | |
108 '''indent each non-empty line of text after first with prefix.''' | |
109 lines = text.splitlines() | |
110 num_lines = len(lines) | |
111 def indenter(): | |
112 for i in xrange(num_lines): | |
113 l = lines[i] | |
114 if i and l.strip(): | |
115 yield prefix | |
116 yield l | |
117 if i < num_lines - 1 or text.endswith('\n'): | |
118 yield '\n' | |
119 return "".join(indenter()) | |
120 | |
121 def permissions(flags): | |
122 if "l" in flags: | |
123 return "lrwxrwxrwx" | |
124 if "x" in flags: | |
125 return "-rwxr-xr-x" | |
126 return "-rw-r--r--" | |
127 | |
128 filters = { | |
129 "addbreaks": nl2br, | |
130 "basename": os.path.basename, | |
131 "age": age, | |
132 "date": lambda x: util.datestr(x), | |
133 "domain": domain, | |
134 "email": util.email, | |
135 "escape": lambda x: cgi.escape(x, True), | |
136 "fill68": lambda x: fill(x, width=68), | |
137 "fill76": lambda x: fill(x, width=76), | |
138 "firstline": firstline, | |
139 "tabindent": lambda x: indent(x, '\t'), | |
140 "hgdate": hgdate, | |
141 "isodate": isodate, | |
142 "obfuscate": obfuscate, | |
143 "permissions": permissions, | |
144 "person": person, | |
145 "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"), | |
146 "rfc3339date": lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S", True, "%+03d:%02d"), | |
147 "short": lambda x: x[:12], | |
148 "shortdate": shortdate, | |
149 "stringify": templater.stringify, | |
150 "strip": lambda x: x.strip(), | |
151 "urlescape": lambda x: urllib.quote(x), | |
152 "user": lambda x: util.shortuser(x), | |
153 "stringescape": lambda x: x.encode('string_escape'), | |
154 } | |
155 |