comparison mercurial/formatter.py @ 32840:57c13c0d1cde

formatter: put topic in templatespec tuple This will allow us to change the initial template reference depending on how the template is looked up. For example, -Tdefault => (ref='changeset', tmpl=None, mapfile='map-cmdline.default') -T'{rev}' => (ref='', tmpl='{rev}', mapfile=None) A literal template given by -T option will be stored as an unnamed template, which will free up the template namespace so that we can load named templates from [templates] section of user config.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 22 Apr 2017 19:07:00 +0900
parents 615ec3f14aa9
children 883adaea9e80
comparison
equal deleted inserted replaced
32839:b425ec7fb7f6 32840:57c13c0d1cde
347 def __init__(self, ui, out, topic, opts): 347 def __init__(self, ui, out, topic, opts):
348 baseformatter.__init__(self, ui, topic, opts, _templateconverter) 348 baseformatter.__init__(self, ui, topic, opts, _templateconverter)
349 self._out = out 349 self._out = out
350 self._topic = topic 350 self._topic = topic
351 spec = lookuptemplate(ui, topic, opts.get('template', '')) 351 spec = lookuptemplate(ui, topic, opts.get('template', ''))
352 self._t = loadtemplater(ui, topic, spec, cache=templatekw.defaulttempl) 352 self._t = loadtemplater(ui, spec, cache=templatekw.defaulttempl)
353 self._counter = itertools.count() 353 self._counter = itertools.count()
354 self._cache = {} # for templatekw/funcs to store reusable data 354 self._cache = {} # for templatekw/funcs to store reusable data
355 def context(self, **ctxs): 355 def context(self, **ctxs):
356 '''insert context objects to be used to render template keywords''' 356 '''insert context objects to be used to render template keywords'''
357 assert all(k == 'ctx' for k in ctxs) 357 assert all(k == 'ctx' for k in ctxs)
373 props['revcache'] = {} 373 props['revcache'] = {}
374 g = self._t(self._topic, ui=self._ui, cache=self._cache, **props) 374 g = self._t(self._topic, ui=self._ui, cache=self._cache, **props)
375 self._out.write(templater.stringify(g)) 375 self._out.write(templater.stringify(g))
376 376
377 templatespec = collections.namedtuple(r'templatespec', 377 templatespec = collections.namedtuple(r'templatespec',
378 r'tmpl mapfile') 378 r'ref tmpl mapfile')
379 379
380 def lookuptemplate(ui, topic, tmpl): 380 def lookuptemplate(ui, topic, tmpl):
381 """Find the template matching the given -T/--template spec 'tmpl' 381 """Find the template matching the given -T/--template spec 'tmpl'
382 382
383 'tmpl' can be any of the following: 383 'tmpl' can be any of the following:
393 loaded from user config. 393 loaded from user config.
394 """ 394 """
395 395
396 # looks like a literal template? 396 # looks like a literal template?
397 if '{' in tmpl: 397 if '{' in tmpl:
398 return templatespec(tmpl, None) 398 return templatespec(topic, tmpl, None)
399 399
400 # perhaps a stock style? 400 # perhaps a stock style?
401 if not os.path.split(tmpl)[0]: 401 if not os.path.split(tmpl)[0]:
402 mapname = (templater.templatepath('map-cmdline.' + tmpl) 402 mapname = (templater.templatepath('map-cmdline.' + tmpl)
403 or templater.templatepath(tmpl)) 403 or templater.templatepath(tmpl))
404 if mapname and os.path.isfile(mapname): 404 if mapname and os.path.isfile(mapname):
405 return templatespec(None, mapname) 405 return templatespec(topic, None, mapname)
406 406
407 # perhaps it's a reference to [templates] 407 # perhaps it's a reference to [templates]
408 t = ui.config('templates', tmpl) 408 t = ui.config('templates', tmpl)
409 if t: 409 if t:
410 return templatespec(templater.unquotestring(t), None) 410 return templatespec(topic, templater.unquotestring(t), None)
411 411
412 if tmpl == 'list': 412 if tmpl == 'list':
413 ui.write(_("available styles: %s\n") % templater.stylelist()) 413 ui.write(_("available styles: %s\n") % templater.stylelist())
414 raise error.Abort(_("specify a template")) 414 raise error.Abort(_("specify a template"))
415 415
416 # perhaps it's a path to a map or a template 416 # perhaps it's a path to a map or a template
417 if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl): 417 if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl):
418 # is it a mapfile for a style? 418 # is it a mapfile for a style?
419 if os.path.basename(tmpl).startswith("map-"): 419 if os.path.basename(tmpl).startswith("map-"):
420 return templatespec(None, os.path.realpath(tmpl)) 420 return templatespec(topic, None, os.path.realpath(tmpl))
421 with util.posixfile(tmpl, 'rb') as f: 421 with util.posixfile(tmpl, 'rb') as f:
422 tmpl = f.read() 422 tmpl = f.read()
423 return templatespec(tmpl, None) 423 return templatespec(topic, tmpl, None)
424 424
425 # constant string? 425 # constant string?
426 return templatespec(tmpl, None) 426 return templatespec(topic, tmpl, None)
427 427
428 def loadtemplater(ui, topic, spec, cache=None): 428 def loadtemplater(ui, spec, cache=None):
429 """Create a templater from either a literal template or loading from 429 """Create a templater from either a literal template or loading from
430 a map file""" 430 a map file"""
431 assert not (spec.tmpl and spec.mapfile) 431 assert not (spec.tmpl and spec.mapfile)
432 if spec.mapfile: 432 if spec.mapfile:
433 return templater.templater.frommapfile(spec.mapfile, cache=cache) 433 return templater.templater.frommapfile(spec.mapfile, cache=cache)
434 return maketemplater(ui, topic, spec.tmpl, cache=cache) 434 return maketemplater(ui, spec.ref, spec.tmpl, cache=cache)
435 435
436 def maketemplater(ui, topic, tmpl, cache=None): 436 def maketemplater(ui, topic, tmpl, cache=None):
437 """Create a templater from a string template 'tmpl'""" 437 """Create a templater from a string template 'tmpl'"""
438 aliases = ui.configitems('templatealias') 438 aliases = ui.configitems('templatealias')
439 t = templater.templater(cache=cache, aliases=aliases) 439 t = templater.templater(cache=cache, aliases=aliases)