comparison mercurial/templater.py @ 1987:04c17fc39c84

add changelog style to command line template. to use, "hg log --style=changelog". makes different output with no flags, -q, -v, --debug. templater module has new template filters for this. email - committer email address fill68 - refill text to 68 colums fill76 - refill text to 76 colums tabindent - prefix every not empty line with tab shortdate - iso 8631 date, no time zone stringify - turn template iterator into string
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Tue, 21 Mar 2006 23:29:21 -0800
parents 6e1a8ea5d717
children a439b7b51530
comparison
equal deleted inserted replaced
1985:c577689006fa 1987:04c17fc39c84
6 # of the GNU General Public License, incorporated herein by reference. 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 import re 8 import re
9 from demandload import demandload 9 from demandload import demandload
10 from i18n import gettext as _ 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 esctable = { 13 esctable = {
14 '\\': '\\', 14 '\\': '\\',
15 'r': '\r', 15 'r': '\r',
16 't': '\t', 16 't': '\t',
179 for t, s in agescales: 179 for t, s in agescales:
180 n = delta / s 180 n = delta / s
181 if n >= 2 or s == 1: 181 if n >= 2 or s == 1:
182 return fmt(t, n) 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 def isodate(date): 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 return util.datestr(date, format='%Y-%m-%d %H:%M') 221 return util.datestr(date, format='%Y-%m-%d %H:%M')
187 222
188 def nl2br(text): 223 def nl2br(text):
189 '''replace raw newlines with xhtml line breaks.''' 224 '''replace raw newlines with xhtml line breaks.'''
190 return text.replace('\n', '<br/>\n') 225 return text.replace('\n', '<br/>\n')
199 author = author[f+1:] 234 author = author[f+1:]
200 f = author.find('>') 235 f = author.find('>')
201 if f >= 0: author = author[:f] 236 if f >= 0: author = author[:f]
202 return author 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 def person(author): 245 def person(author):
205 '''get name of author, or else username.''' 246 '''get name of author, or else username.'''
206 f = author.find('<') 247 f = author.find('<')
207 if f == -1: return util.shortuser(author) 248 if f == -1: return util.shortuser(author)
208 return author[:f].rstrip() 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 common_filters = { 268 common_filters = {
211 "addbreaks": nl2br, 269 "addbreaks": nl2br,
212 "age": age, 270 "age": age,
213 "date": lambda x: util.datestr(x), 271 "date": lambda x: util.datestr(x),
214 "domain": domain, 272 "domain": domain,
273 "email": email,
215 "escape": lambda x: cgi.escape(x, True), 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 "firstline": lambda x: x.splitlines(1)[0].rstrip('\r\n'), 277 "firstline": lambda x: x.splitlines(1)[0].rstrip('\r\n'),
278 "tabindent": lambda x: indent(x, '\t'),
217 "isodate": isodate, 279 "isodate": isodate,
218 "obfuscate": obfuscate, 280 "obfuscate": obfuscate,
219 "permissions": lambda x: x and "-rwxr-xr-x" or "-rw-r--r--", 281 "permissions": lambda x: x and "-rwxr-xr-x" or "-rw-r--r--",
220 "person": person, 282 "person": person,
221 "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"), 283 "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"),
222 "short": lambda x: x[:12], 284 "short": lambda x: x[:12],
285 "shortdate": shortdate,
286 "stringify": stringify,
223 "strip": lambda x: x.strip(), 287 "strip": lambda x: x.strip(),
224 "urlescape": lambda x: urllib.quote(x), 288 "urlescape": lambda x: urllib.quote(x),
225 "user": lambda x: util.shortuser(x), 289 "user": lambda x: util.shortuser(x),
226 } 290 }
227 291