Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/templater.py @ 3646:b4ad640a3bcf
templates: move changeset templating bits to cmdutils
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 13 Nov 2006 13:26:57 -0600 |
parents | b2c47652e8e3 |
children | 734e337cb816 |
comparison
equal
deleted
inserted
replaced
3645:b2c47652e8e3 | 3646:b4ad640a3bcf |
---|---|
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 from demandload import demandload | 8 from demandload import demandload |
9 from i18n import gettext as _ | 9 from i18n import gettext as _ |
10 from node import * | 10 from node import * |
11 demandload(globals(), "cStringIO cgi re sys os time urllib util textwrap") | 11 demandload(globals(), "cgi re sys os time urllib util textwrap") |
12 | 12 |
13 def parsestring(s, quoted=True): | 13 def parsestring(s, quoted=True): |
14 '''parse a string using simple c-like syntax. | 14 '''parse a string using simple c-like syntax. |
15 string must be in quotes if quoted is True.''' | 15 string must be in quotes if quoted is True.''' |
16 if quoted: | 16 if quoted: |
288 if name: fl.append(name) | 288 if name: fl.append(name) |
289 p = os.path.join(os.path.dirname(module), *fl) | 289 p = os.path.join(os.path.dirname(module), *fl) |
290 if (name and os.path.exists(p)) or os.path.isdir(p): | 290 if (name and os.path.exists(p)) or os.path.isdir(p): |
291 return os.path.normpath(p) | 291 return os.path.normpath(p) |
292 | 292 |
293 class changeset_templater(object): | |
294 '''format changeset information.''' | |
295 | |
296 def __init__(self, ui, repo, mapfile, dest=None): | |
297 self.t = templater(mapfile, common_filters, | |
298 cache={'parent': '{rev}:{node|short} ', | |
299 'manifest': '{rev}:{node|short}', | |
300 'filecopy': '{name} ({source})'}) | |
301 self.ui = ui | |
302 self.dest = dest | |
303 self.repo = repo | |
304 | |
305 def use_template(self, t): | |
306 '''set template string to use''' | |
307 self.t.cache['changeset'] = t | |
308 | |
309 def show(self, rev=0, changenode=None, brinfo=None, copies=[], **props): | |
310 '''show a single changeset or file revision''' | |
311 log = self.repo.changelog | |
312 if changenode is None: | |
313 changenode = log.node(rev) | |
314 elif not rev: | |
315 rev = log.rev(changenode) | |
316 | |
317 changes = log.read(changenode) | |
318 | |
319 def showlist(name, values, plural=None, **args): | |
320 '''expand set of values. | |
321 name is name of key in template map. | |
322 values is list of strings or dicts. | |
323 plural is plural of name, if not simply name + 's'. | |
324 | |
325 expansion works like this, given name 'foo'. | |
326 | |
327 if values is empty, expand 'no_foos'. | |
328 | |
329 if 'foo' not in template map, return values as a string, | |
330 joined by space. | |
331 | |
332 expand 'start_foos'. | |
333 | |
334 for each value, expand 'foo'. if 'last_foo' in template | |
335 map, expand it instead of 'foo' for last key. | |
336 | |
337 expand 'end_foos'. | |
338 ''' | |
339 if plural: names = plural | |
340 else: names = name + 's' | |
341 if not values: | |
342 noname = 'no_' + names | |
343 if noname in self.t: | |
344 yield self.t(noname, **args) | |
345 return | |
346 if name not in self.t: | |
347 if isinstance(values[0], str): | |
348 yield ' '.join(values) | |
349 else: | |
350 for v in values: | |
351 yield dict(v, **args) | |
352 return | |
353 startname = 'start_' + names | |
354 if startname in self.t: | |
355 yield self.t(startname, **args) | |
356 vargs = args.copy() | |
357 def one(v, tag=name): | |
358 try: | |
359 vargs.update(v) | |
360 except (AttributeError, ValueError): | |
361 try: | |
362 for a, b in v: | |
363 vargs[a] = b | |
364 except ValueError: | |
365 vargs[name] = v | |
366 return self.t(tag, **vargs) | |
367 lastname = 'last_' + name | |
368 if lastname in self.t: | |
369 last = values.pop() | |
370 else: | |
371 last = None | |
372 for v in values: | |
373 yield one(v) | |
374 if last is not None: | |
375 yield one(last, tag=lastname) | |
376 endname = 'end_' + names | |
377 if endname in self.t: | |
378 yield self.t(endname, **args) | |
379 | |
380 def showbranches(**args): | |
381 branch = changes[5].get("branch") | |
382 if branch: | |
383 yield showlist('branch', [branch], plural='branches', **args) | |
384 # add old style branches if requested | |
385 if brinfo and changenode in brinfo: | |
386 yield showlist('branch', brinfo[changenode], | |
387 plural='branches', **args) | |
388 | |
389 def showparents(**args): | |
390 parents = [[('rev', log.rev(p)), ('node', hex(p))] | |
391 for p in log.parents(changenode) | |
392 if self.ui.debugflag or p != nullid] | |
393 if (not self.ui.debugflag and len(parents) == 1 and | |
394 parents[0][0][1] == rev - 1): | |
395 return | |
396 return showlist('parent', parents, **args) | |
397 | |
398 def showtags(**args): | |
399 return showlist('tag', self.repo.nodetags(changenode), **args) | |
400 | |
401 def showextras(**args): | |
402 extras = changes[5].items() | |
403 extras.sort() | |
404 for key, value in extras: | |
405 args = args.copy() | |
406 args.update(dict(key=key, value=value)) | |
407 yield self.t('extra', **args) | |
408 | |
409 def showcopies(**args): | |
410 c = [{'name': x[0], 'source': x[1]} for x in copies] | |
411 return showlist('file_copy', c, plural='file_copies', **args) | |
412 | |
413 if self.ui.debugflag: | |
414 files = self.repo.status(log.parents(changenode)[0], changenode)[:3] | |
415 def showfiles(**args): | |
416 return showlist('file', files[0], **args) | |
417 def showadds(**args): | |
418 return showlist('file_add', files[1], **args) | |
419 def showdels(**args): | |
420 return showlist('file_del', files[2], **args) | |
421 def showmanifest(**args): | |
422 args = args.copy() | |
423 args.update(dict(rev=self.repo.manifest.rev(changes[0]), | |
424 node=hex(changes[0]))) | |
425 return self.t('manifest', **args) | |
426 else: | |
427 def showfiles(**args): | |
428 yield showlist('file', changes[3], **args) | |
429 showadds = '' | |
430 showdels = '' | |
431 showmanifest = '' | |
432 | |
433 defprops = { | |
434 'author': changes[1], | |
435 'branches': showbranches, | |
436 'date': changes[2], | |
437 'desc': changes[4], | |
438 'file_adds': showadds, | |
439 'file_dels': showdels, | |
440 'files': showfiles, | |
441 'file_copies': showcopies, | |
442 'manifest': showmanifest, | |
443 'node': hex(changenode), | |
444 'parents': showparents, | |
445 'rev': rev, | |
446 'tags': showtags, | |
447 'extras': showextras, | |
448 } | |
449 props = props.copy() | |
450 props.update(defprops) | |
451 | |
452 try: | |
453 dest = self.dest or self.ui | |
454 if self.ui.debugflag and 'header_debug' in self.t: | |
455 key = 'header_debug' | |
456 elif self.ui.quiet and 'header_quiet' in self.t: | |
457 key = 'header_quiet' | |
458 elif self.ui.verbose and 'header_verbose' in self.t: | |
459 key = 'header_verbose' | |
460 elif 'header' in self.t: | |
461 key = 'header' | |
462 else: | |
463 key = '' | |
464 if key: | |
465 dest.write_header(stringify(self.t(key, **props))) | |
466 if self.ui.debugflag and 'changeset_debug' in self.t: | |
467 key = 'changeset_debug' | |
468 elif self.ui.quiet and 'changeset_quiet' in self.t: | |
469 key = 'changeset_quiet' | |
470 elif self.ui.verbose and 'changeset_verbose' in self.t: | |
471 key = 'changeset_verbose' | |
472 else: | |
473 key = 'changeset' | |
474 dest.write(stringify(self.t(key, **props))) | |
475 except KeyError, inst: | |
476 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile, | |
477 inst.args[0])) | |
478 except SyntaxError, inst: | |
479 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0])) | |
480 | |
481 class stringio(object): | |
482 '''wrap cStringIO for use by changeset_templater.''' | |
483 def __init__(self): | |
484 self.fp = cStringIO.StringIO() | |
485 | |
486 def write(self, *args): | |
487 for a in args: | |
488 self.fp.write(a) | |
489 | |
490 write_header = write | |
491 | |
492 def __getattr__(self, key): | |
493 return getattr(self.fp, key) |