Show More
@@ -0,0 +1,15 | |||
|
1 | changeset = '{date|shortdate} {author|person} <{author|email}> ({node|short}{tags})\n\n\t* {files|stringify|fill68|tabindent}{desc|fill68|tabindent|strip}\n\n' | |
|
2 | changeset_quiet = '{date|shortdate} {author|person} <{author|email}>\n\n\t* {desc|firstline|fill68|tabindent|strip}\n\n' | |
|
3 | changeset_verbose = '{date|isodate} {author|person} <{author|email}> ({node|short}{tags})\n\n\t* {file_adds|stringify|fill68|tabindent}{file_dels|stringify|fill68|tabindent}{files|stringify|fill68|tabindent}{desc|fill68|tabindent|strip}\n\n' | |
|
4 | start_tags = ' [' | |
|
5 | tag = '{tag}, ' | |
|
6 | last_tag = '{tag}]' | |
|
7 | start_files = '(' | |
|
8 | file = '{file}, ' | |
|
9 | last_file = '{file}):\n\t' | |
|
10 | start_file_adds = '(' | |
|
11 | file_add = '{file_add}, ' | |
|
12 | last_file_add = '{file_add}): new file.\n* ' | |
|
13 | start_file_dels = '(' | |
|
14 | file_del = '{file_del}, ' | |
|
15 | last_file_del = '{file_del}): deleted file.\n* ' |
@@ -8,7 +8,7 | |||
|
8 | 8 | import re |
|
9 | 9 | from demandload import demandload |
|
10 | 10 | from i18n import gettext as _ |
|
11 | demandload(globals(), "cStringIO cgi sys os time urllib util") | |
|
11 | demandload(globals(), "cStringIO cgi re sys os time urllib util textwrap") | |
|
12 | 12 | |
|
13 | 13 | esctable = { |
|
14 | 14 | '\\': '\\', |
@@ -181,8 +181,43 def age(date): | |||
|
181 | 181 | if n >= 2 or s == 1: |
|
182 | 182 | return fmt(t, n) |
|
183 | 183 | |
|
184 | def stringify(thing): | |
|
185 | '''turn nested template iterator into string.''' | |
|
186 | cs = cStringIO.StringIO() | |
|
187 | def walk(things): | |
|
188 | for t in things: | |
|
189 | if hasattr(t, '__iter__'): | |
|
190 | walk(t) | |
|
191 | else: | |
|
192 | cs.write(t) | |
|
193 | walk(thing) | |
|
194 | return cs.getvalue() | |
|
195 | ||
|
196 | para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M) | |
|
197 | space_re = re.compile(r' +') | |
|
198 | ||
|
199 | def fill(text, width): | |
|
200 | '''fill many paragraphs.''' | |
|
201 | def findparas(): | |
|
202 | start = 0 | |
|
203 | while True: | |
|
204 | m = para_re.search(text, start) | |
|
205 | if not m: | |
|
206 | w = len(text) | |
|
207 | while w > start and text[w-1].isspace(): w -= 1 | |
|
208 | yield text[start:w], text[w:] | |
|
209 | break | |
|
210 | yield text[start:m.start(0)], m.group(1) | |
|
211 | start = m.end(1) | |
|
212 | ||
|
213 | fp = cStringIO.StringIO() | |
|
214 | for para, rest in findparas(): | |
|
215 | fp.write(space_re.sub(' ', textwrap.fill(para, width))) | |
|
216 | fp.write(rest) | |
|
217 | return fp.getvalue() | |
|
218 | ||
|
184 | 219 | def isodate(date): |
|
185 | '''turn a (timestamp, tzoff) tuple into an iso 8631 date.''' | |
|
220 | '''turn a (timestamp, tzoff) tuple into an iso 8631 date and time.''' | |
|
186 | 221 | return util.datestr(date, format='%Y-%m-%d %H:%M') |
|
187 | 222 | |
|
188 | 223 | def nl2br(text): |
@@ -201,25 +236,54 def domain(author): | |||
|
201 | 236 | if f >= 0: author = author[:f] |
|
202 | 237 | return author |
|
203 | 238 | |
|
239 | def email(author): | |
|
240 | '''get email of author.''' | |
|
241 | r = author.find('>') | |
|
242 | if r == -1: r = None | |
|
243 | return author[author.find('<')+1:r] | |
|
244 | ||
|
204 | 245 | def person(author): |
|
205 | 246 | '''get name of author, or else username.''' |
|
206 | 247 | f = author.find('<') |
|
207 | 248 | if f == -1: return util.shortuser(author) |
|
208 | 249 | return author[:f].rstrip() |
|
209 | 250 | |
|
251 | def shortdate(date): | |
|
252 | '''turn (timestamp, tzoff) tuple into iso 8631 date.''' | |
|
253 | return util.datestr(date, format='%Y-%m-%d', timezone=False) | |
|
254 | ||
|
255 | def indent(text, prefix): | |
|
256 | '''indent each non-empty line of text after first with prefix.''' | |
|
257 | fp = cStringIO.StringIO() | |
|
258 | lines = text.splitlines() | |
|
259 | num_lines = len(lines) | |
|
260 | for i in xrange(num_lines): | |
|
261 | l = lines[i] | |
|
262 | if i and l.strip(): fp.write(prefix) | |
|
263 | fp.write(l) | |
|
264 | if i < num_lines - 1 or text.endswith('\n'): | |
|
265 | fp.write('\n') | |
|
266 | return fp.getvalue() | |
|
267 | ||
|
210 | 268 | common_filters = { |
|
211 | 269 | "addbreaks": nl2br, |
|
212 | 270 | "age": age, |
|
213 | 271 | "date": lambda x: util.datestr(x), |
|
214 | 272 | "domain": domain, |
|
273 | "email": email, | |
|
215 | 274 | "escape": lambda x: cgi.escape(x, True), |
|
275 | "fill68": lambda x: fill(x, width=68), | |
|
276 | "fill76": lambda x: fill(x, width=76), | |
|
216 | 277 | "firstline": lambda x: x.splitlines(1)[0].rstrip('\r\n'), |
|
278 | "tabindent": lambda x: indent(x, '\t'), | |
|
217 | 279 | "isodate": isodate, |
|
218 | 280 | "obfuscate": obfuscate, |
|
219 | 281 | "permissions": lambda x: x and "-rwxr-xr-x" or "-rw-r--r--", |
|
220 | 282 | "person": person, |
|
221 | 283 | "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"), |
|
222 | 284 | "short": lambda x: x[:12], |
|
285 | "shortdate": shortdate, | |
|
286 | "stringify": stringify, | |
|
223 | 287 | "strip": lambda x: x.strip(), |
|
224 | 288 | "urlescape": lambda x: urllib.quote(x), |
|
225 | 289 | "user": lambda x: util.shortuser(x), |
@@ -744,15 +744,16 def makedate(): | |||
|
744 | 744 | tz = time.timezone |
|
745 | 745 | return time.mktime(lt), tz |
|
746 | 746 | |
|
747 | def datestr(date=None, format='%a %b %d %H:%M:%S %Y'): | |
|
747 | def datestr(date=None, format='%a %b %d %H:%M:%S %Y', timezone=True): | |
|
748 | 748 | """represent a (unixtime, offset) tuple as a localized time. |
|
749 | 749 | unixtime is seconds since the epoch, and offset is the time zone's |
|
750 |
number of seconds away from UTC. |
|
|
750 | number of seconds away from UTC. if timezone is false, do not | |
|
751 | append time zone to string.""" | |
|
751 | 752 | t, tz = date or makedate() |
|
752 | return ("%s %+03d%02d" % | |
|
753 | (time.strftime(format, time.gmtime(float(t) - tz)), | |
|
754 | -tz / 3600, | |
|
755 | ((-tz % 3600) / 60))) | |
|
753 | s = time.strftime(format, time.gmtime(float(t) - tz)) | |
|
754 | if timezone: | |
|
755 | s += " %+03d%02d" % (-tz / 3600, ((-tz % 3600) / 60)) | |
|
756 | return s | |
|
756 | 757 | |
|
757 | 758 | def shortuser(user): |
|
758 | 759 | """Return a short representation of a user name or email address.""" |
General Comments 0
You need to be logged in to leave comments.
Login now