--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/templatefilters.py Thu Jan 31 14:44:19 2008 -0600
@@ -0,0 +1,155 @@
+# template-filters.py - common template expansion filters
+#
+# Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+import cgi, re, os, time, urllib, textwrap
+import util, templater
+
+agescales = [("second", 1),
+ ("minute", 60),
+ ("hour", 3600),
+ ("day", 3600 * 24),
+ ("week", 3600 * 24 * 7),
+ ("month", 3600 * 24 * 30),
+ ("year", 3600 * 24 * 365)]
+
+agescales.reverse()
+
+def age(date):
+ '''turn a (timestamp, tzoff) tuple into an age string.'''
+
+ def plural(t, c):
+ if c == 1:
+ return t
+ return t + "s"
+ def fmt(t, c):
+ return "%d %s" % (c, plural(t, c))
+
+ now = time.time()
+ then = date[0]
+ delta = max(1, int(now - then))
+
+ for t, s in agescales:
+ n = delta / s
+ if n >= 2 or s == 1:
+ return fmt(t, n)
+
+para_re = None
+space_re = None
+
+def fill(text, width):
+ '''fill many paragraphs.'''
+ global para_re, space_re
+ if para_re is None:
+ para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
+ space_re = re.compile(r' +')
+
+ def findparas():
+ start = 0
+ while True:
+ m = para_re.search(text, start)
+ if not m:
+ w = len(text)
+ while w > start and text[w-1].isspace(): w -= 1
+ yield text[start:w], text[w:]
+ break
+ yield text[start:m.start(0)], m.group(1)
+ start = m.end(1)
+
+ return "".join([space_re.sub(' ', textwrap.fill(para, width)) + rest
+ for para, rest in findparas()])
+
+def firstline(text):
+ '''return the first line of text'''
+ try:
+ return text.splitlines(1)[0].rstrip('\r\n')
+ except IndexError:
+ return ''
+
+def isodate(date):
+ '''turn a (timestamp, tzoff) tuple into an iso 8631 date and time.'''
+ return util.datestr(date, format='%Y-%m-%d %H:%M')
+
+def hgdate(date):
+ '''turn a (timestamp, tzoff) tuple into an hg cset timestamp.'''
+ return "%d %d" % date
+
+def nl2br(text):
+ '''replace raw newlines with xhtml line breaks.'''
+ return text.replace('\n', '<br/>\n')
+
+def obfuscate(text):
+ text = unicode(text, util._encoding, 'replace')
+ return ''.join(['&#%d;' % ord(c) for c in text])
+
+def domain(author):
+ '''get domain of author, or empty string if none.'''
+ f = author.find('@')
+ if f == -1: return ''
+ author = author[f+1:]
+ f = author.find('>')
+ if f >= 0: author = author[:f]
+ return author
+
+def person(author):
+ '''get name of author, or else username.'''
+ f = author.find('<')
+ if f == -1: return util.shortuser(author)
+ return author[:f].rstrip()
+
+def shortdate(date):
+ '''turn (timestamp, tzoff) tuple into iso 8631 date.'''
+ return util.datestr(date, format='%Y-%m-%d', timezone=False)
+
+def indent(text, prefix):
+ '''indent each non-empty line of text after first with prefix.'''
+ lines = text.splitlines()
+ num_lines = len(lines)
+ def indenter():
+ for i in xrange(num_lines):
+ l = lines[i]
+ if i and l.strip():
+ yield prefix
+ yield l
+ if i < num_lines - 1 or text.endswith('\n'):
+ yield '\n'
+ return "".join(indenter())
+
+def permissions(flags):
+ if "l" in flags:
+ return "lrwxrwxrwx"
+ if "x" in flags:
+ return "-rwxr-xr-x"
+ return "-rw-r--r--"
+
+filters = {
+ "addbreaks": nl2br,
+ "basename": os.path.basename,
+ "age": age,
+ "date": lambda x: util.datestr(x),
+ "domain": domain,
+ "email": util.email,
+ "escape": lambda x: cgi.escape(x, True),
+ "fill68": lambda x: fill(x, width=68),
+ "fill76": lambda x: fill(x, width=76),
+ "firstline": firstline,
+ "tabindent": lambda x: indent(x, '\t'),
+ "hgdate": hgdate,
+ "isodate": isodate,
+ "obfuscate": obfuscate,
+ "permissions": permissions,
+ "person": person,
+ "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"),
+ "rfc3339date": lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S", True, "%+03d:%02d"),
+ "short": lambda x: x[:12],
+ "shortdate": shortdate,
+ "stringify": templater.stringify,
+ "strip": lambda x: x.strip(),
+ "urlescape": lambda x: urllib.quote(x),
+ "user": lambda x: util.shortuser(x),
+ "stringescape": lambda x: x.encode('string_escape'),
+ }
+