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