##// END OF EJS Templates
add doc comments to template code.
Vadim Gelfer -
r1909:37b9f80a default
parent child Browse files
Show More
@@ -338,15 +338,20 b' def trimuser(ui, name, rev, revcache):'
338 return user
338 return user
339
339
340 class changeset_templater(object):
340 class changeset_templater(object):
341 '''use templater module to format changeset information.'''
342
341 def __init__(self, ui, repo, mapfile):
343 def __init__(self, ui, repo, mapfile):
342 self.t = templater.templater(mapfile, templater.common_filters)
344 self.t = templater.templater(mapfile, templater.common_filters)
343 self.ui = ui
345 self.ui = ui
344 self.repo = repo
346 self.repo = repo
345
347
346 def use_template(self, t):
348 def use_template(self, t):
349 '''set template string to use'''
347 self.t.cache['template'] = t
350 self.t.cache['template'] = t
348
351
349 def write(self, thing):
352 def write(self, thing):
353 '''write expanded template.
354 uses in-order recursive traverse of iterators.'''
350 for t in thing:
355 for t in thing:
351 if hasattr(t, '__iter__'):
356 if hasattr(t, '__iter__'):
352 self.write(t)
357 self.write(t)
@@ -354,7 +359,7 b' class changeset_templater(object):'
354 self.ui.write(t)
359 self.ui.write(t)
355
360
356 def show(self, rev=0, changenode=None, brinfo=None):
361 def show(self, rev=0, changenode=None, brinfo=None):
357 """show a single changeset or file revision"""
362 '''show a single changeset or file revision'''
358 log = self.repo.changelog
363 log = self.repo.changelog
359 if changenode is None:
364 if changenode is None:
360 changenode = log.node(rev)
365 changenode = log.node(rev)
@@ -364,6 +369,25 b' class changeset_templater(object):'
364 changes = log.read(changenode)
369 changes = log.read(changenode)
365
370
366 def showlist(name, values, plural=None, **args):
371 def showlist(name, values, plural=None, **args):
372 '''expand set of values.
373 name is name of key in template map.
374 values is list of strings or dicts.
375 plural is plural of name, if not simply name + 's'.
376
377 expansion works like this, given name 'foo'.
378
379 if values is empty, expand 'no_foos'.
380
381 if 'foo' not in template map, return values as a string,
382 joined by space.
383
384 expand 'start_foos'.
385
386 for each value, expand 'foo'. if 'last_foo' in template
387 map, expand it instead of 'foo' for last key.
388
389 expand 'end_foos'.
390 '''
367 if plural: names = plural
391 if plural: names = plural
368 else: names = name + 's'
392 else: names = name + 's'
369 if not values:
393 if not values:
@@ -371,13 +395,13 b' class changeset_templater(object):'
371 if noname in self.t:
395 if noname in self.t:
372 yield self.t(noname, **args)
396 yield self.t(noname, **args)
373 return
397 return
374 vargs = args.copy()
375 if name not in self.t:
398 if name not in self.t:
376 yield ' '.join(values)
399 yield ' '.join(values)
377 return
400 return
378 startname = 'start_' + names
401 startname = 'start_' + names
379 if startname in self.t:
402 if startname in self.t:
380 yield self.t(startname, **args)
403 yield self.t(startname, **args)
404 vargs = args.copy()
381 def one(v, tag=name):
405 def one(v, tag=name):
382 try:
406 try:
383 vargs.update(v)
407 vargs.update(v)
@@ -464,12 +488,14 b' class changeset_templater(object):'
464 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
488 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
465
489
466 class changeset_printer(object):
490 class changeset_printer(object):
491 '''show changeset information when templating not requested.'''
492
467 def __init__(self, ui, repo):
493 def __init__(self, ui, repo):
468 self.ui = ui
494 self.ui = ui
469 self.repo = repo
495 self.repo = repo
470
496
471 def show(self, rev=0, changenode=None, brinfo=None):
497 def show(self, rev=0, changenode=None, brinfo=None):
472 """show a single changeset or file revision"""
498 '''show a single changeset or file revision'''
473 log = self.repo.changelog
499 log = self.repo.changelog
474 if changenode is None:
500 if changenode is None:
475 changenode = log.node(rev)
501 changenode = log.node(rev)
@@ -530,6 +556,9 b' class changeset_printer(object):'
530 self.ui.status("\n")
556 self.ui.status("\n")
531
557
532 def show_changeset(ui, repo, opts):
558 def show_changeset(ui, repo, opts):
559 '''show one changeset. uses template or regular display. caller
560 can pass in 'map_file' and 'template' options in opts.'''
561
533 tmpl = opts.get('template')
562 tmpl = opts.get('template')
534 if tmpl:
563 if tmpl:
535 tmpl = templater.parsestring(tmpl, quoted=False)
564 tmpl = templater.parsestring(tmpl, quoted=False)
@@ -1,3 +1,10 b''
1 # templater.py - template expansion for output
2 #
3 # Copyright 2005, 2006 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
1 import re
8 import re
2 from demandload import demandload
9 from demandload import demandload
3 from i18n import gettext as _
10 from i18n import gettext as _
@@ -12,6 +19,8 b' esctable = {'
12 }
19 }
13
20
14 def parsestring(s, quoted=True):
21 def parsestring(s, quoted=True):
22 '''parse a string using simple c-like syntax.
23 string must be in quotes if quoted is True.'''
15 fp = cStringIO.StringIO()
24 fp = cStringIO.StringIO()
16 if quoted:
25 if quoted:
17 first = s[0]
26 first = s[0]
@@ -31,7 +40,30 b' def parsestring(s, quoted=True):'
31 return fp.getvalue()
40 return fp.getvalue()
32
41
33 class templater(object):
42 class templater(object):
43 '''template expansion engine.
44
45 template expansion works like this. a map file contains key=value
46 pairs. if value is quoted, it is treated as string. otherwise, it
47 is treated as name of template file.
48
49 templater is asked to expand a key in map. it looks up key, and
50 looks for atrings like this: {foo}. it expands {foo} by looking up
51 foo in map, and substituting it. expansion is recursive: it stops
52 when there is no more {foo} to replace.
53
54 expansion also allows formatting and filtering.
55
56 format uses key to expand each item in list. syntax is
57 {key%format}.
58
59 filter uses function to transform value. syntax is
60 {key|filter1|filter2|...}.'''
61
34 def __init__(self, mapfile, filters={}, defaults={}):
62 def __init__(self, mapfile, filters={}, defaults={}):
63 '''set up template engine.
64 mapfile is name of file to read map definitions from.
65 filters is dict of functions. each transforms a value into another.
66 defaults is dict of default map definitions.'''
35 self.mapfile = mapfile or 'template'
67 self.mapfile = mapfile or 'template'
36 self.cache = {}
68 self.cache = {}
37 self.map = {}
69 self.map = {}
@@ -64,6 +96,9 b' class templater(object):'
64 return key in self.cache
96 return key in self.cache
65
97
66 def __call__(self, t, **map):
98 def __call__(self, t, **map):
99 '''perform expansion.
100 t is name of map element to expand.
101 map is added elements to use during expansion.'''
67 m = self.defaults.copy()
102 m = self.defaults.copy()
68 m.update(map)
103 m.update(map)
69 try:
104 try:
@@ -127,7 +162,9 b' agescales = [("second", 1),'
127
162
128 agescales.reverse()
163 agescales.reverse()
129
164
130 def age(x):
165 def age(date):
166 '''turn a (timestamp, tzoff) tuple into an age string.'''
167
131 def plural(t, c):
168 def plural(t, c):
132 if c == 1:
169 if c == 1:
133 return t
170 return t
@@ -136,7 +173,7 b' def age(x):'
136 return "%d %s" % (c, plural(t, c))
173 return "%d %s" % (c, plural(t, c))
137
174
138 now = time.time()
175 now = time.time()
139 then = x[0]
176 then = date[0]
140 delta = max(1, int(now - then))
177 delta = max(1, int(now - then))
141
178
142 for t, s in agescales:
179 for t, s in agescales:
@@ -145,15 +182,18 b' def age(x):'
145 return fmt(t, n)
182 return fmt(t, n)
146
183
147 def isodate(date):
184 def isodate(date):
185 '''turn a (timestamp, tzoff) tuple into an iso 8631 date.'''
148 return util.datestr(date, format='%Y-%m-%d %H:%M')
186 return util.datestr(date, format='%Y-%m-%d %H:%M')
149
187
150 def nl2br(text):
188 def nl2br(text):
189 '''replace raw newlines with xhtml line breaks.'''
151 return text.replace('\n', '<br/>\n')
190 return text.replace('\n', '<br/>\n')
152
191
153 def obfuscate(text):
192 def obfuscate(text):
154 return ''.join(['&#%d;' % ord(c) for c in text])
193 return ''.join(['&#%d;' % ord(c) for c in text])
155
194
156 def domain(author):
195 def domain(author):
196 '''get domain of author, or empty string if none.'''
157 f = author.find('@')
197 f = author.find('@')
158 if f == -1: return ''
198 if f == -1: return ''
159 author = author[f+1:]
199 author = author[f+1:]
@@ -162,6 +202,7 b' def domain(author):'
162 return author
202 return author
163
203
164 def person(author):
204 def person(author):
205 '''get name of author, or else username.'''
165 f = author.find('<')
206 f = author.find('<')
166 if f == -1: return util.shortuser(author)
207 if f == -1: return util.shortuser(author)
167 return author[:f].rstrip()
208 return author[:f].rstrip()
@@ -185,6 +226,8 b' common_filters = {'
185 }
226 }
186
227
187 def templatepath(name=None):
228 def templatepath(name=None):
229 '''return location of template file or directory (if no name).
230 returns None if not found.'''
188 for f in 'templates', '../templates':
231 for f in 'templates', '../templates':
189 fl = f.split('/')
232 fl = f.split('/')
190 if name: fl.append(name)
233 if name: fl.append(name)
General Comments 0
You need to be logged in to leave comments. Login now