mercurial/formatter.py
changeset 43101 1d12ae5096d1
parent 43100 90b9a7e06c2c
child 43106 d783f945a701
equal deleted inserted replaced
43100:90b9a7e06c2c 43101:1d12ae5096d1
   473 
   473 
   474         return templateutil.hybridlist(data, name=name, fmt=fmt, gen=f)
   474         return templateutil.hybridlist(data, name=name, fmt=fmt, gen=f)
   475 
   475 
   476 
   476 
   477 class templateformatter(baseformatter):
   477 class templateformatter(baseformatter):
   478     def __init__(self, ui, out, topic, opts, spec):
   478     def __init__(self, ui, out, topic, opts, spec, overridetemplates=None):
   479         baseformatter.__init__(self, ui, topic, opts, _templateconverter)
   479         baseformatter.__init__(self, ui, topic, opts, _templateconverter)
   480         self._out = out
   480         self._out = out
   481         self._tref = spec.ref
   481         self._tref = spec.ref
   482         self._t = loadtemplater(
   482         self._t = loadtemplater(
   483             ui,
   483             ui,
   484             spec,
   484             spec,
   485             defaults=templatekw.keywords,
   485             defaults=templatekw.keywords,
   486             resources=templateresources(ui),
   486             resources=templateresources(ui),
   487             cache=templatekw.defaulttempl,
   487             cache=templatekw.defaulttempl,
   488         )
   488         )
       
   489         if overridetemplates:
       
   490             self._t.cache.update(overridetemplates)
   489         self._parts = templatepartsmap(
   491         self._parts = templatepartsmap(
   490             spec, self._t, [b'docheader', b'docfooter', b'separator']
   492             spec, self._t, [b'docheader', b'docfooter', b'separator']
   491         )
   493         )
   492         self._counter = itertools.count()
   494         self._counter = itertools.count()
   493         self._renderitem(b'docheader', {})
   495         self._renderitem(b'docheader', {})
   521 @attr.s(frozen=True)
   523 @attr.s(frozen=True)
   522 class templatespec(object):
   524 class templatespec(object):
   523     ref = attr.ib()
   525     ref = attr.ib()
   524     tmpl = attr.ib()
   526     tmpl = attr.ib()
   525     mapfile = attr.ib()
   527     mapfile = attr.ib()
       
   528     refargs = attr.ib(default=None)
   526 
   529 
   527 
   530 
   528 def lookuptemplate(ui, topic, tmpl):
   531 def lookuptemplate(ui, topic, tmpl):
   529     """Find the template matching the given -T/--template spec 'tmpl'
   532     """Find the template matching the given -T/--template spec 'tmpl'
   530 
   533 
   553         return templatespec(b'', tmpl, None)
   556         return templatespec(b'', tmpl, None)
   554 
   557 
   555     # a reference to built-in (formatter) template
   558     # a reference to built-in (formatter) template
   556     if tmpl in {b'cbor', b'json', b'pickle', b'debug'}:
   559     if tmpl in {b'cbor', b'json', b'pickle', b'debug'}:
   557         return templatespec(tmpl, None, None)
   560         return templatespec(tmpl, None, None)
       
   561 
       
   562     # a function-style reference to built-in template
       
   563     func, fsep, ftail = tmpl.partition(b'(')
       
   564     if func in {b'cbor', b'json'} and fsep and ftail.endswith(b')'):
       
   565         templater.parseexpr(tmpl)  # make sure syntax errors are confined
       
   566         return templatespec(func, None, None, refargs=ftail[:-1])
   558 
   567 
   559     # perhaps a stock style?
   568     # perhaps a stock style?
   560     if not os.path.split(tmpl)[0]:
   569     if not os.path.split(tmpl)[0]:
   561         mapname = templater.templatepath(
   570         mapname = templater.templatepath(
   562             b'map-cmdline.' + tmpl
   571             b'map-cmdline.' + tmpl
   717         b'ctx': _loadctx,
   726         b'ctx': _loadctx,
   718         b'fctx': _loadfctx,
   727         b'fctx': _loadfctx,
   719     }
   728     }
   720 
   729 
   721 
   730 
       
   731 def _internaltemplateformatter(
       
   732     ui,
       
   733     out,
       
   734     topic,
       
   735     opts,
       
   736     spec,
       
   737     tmpl,
       
   738     docheader=b'',
       
   739     docfooter=b'',
       
   740     separator=b'',
       
   741 ):
       
   742     """Build template formatter that handles customizable built-in templates
       
   743     such as -Tjson(...)"""
       
   744     templates = {spec.ref: tmpl}
       
   745     if docheader:
       
   746         templates[b'%s:docheader' % spec.ref] = docheader
       
   747     if docfooter:
       
   748         templates[b'%s:docfooter' % spec.ref] = docfooter
       
   749     if separator:
       
   750         templates[b'%s:separator' % spec.ref] = separator
       
   751     return templateformatter(
       
   752         ui, out, topic, opts, spec, overridetemplates=templates
       
   753     )
       
   754 
       
   755 
   722 def formatter(ui, out, topic, opts):
   756 def formatter(ui, out, topic, opts):
   723     spec = lookuptemplate(ui, topic, opts.get(b'template', b''))
   757     spec = lookuptemplate(ui, topic, opts.get(b'template', b''))
   724     if spec.ref == b"cbor":
   758     if spec.ref == b"cbor" and spec.refargs is not None:
       
   759         return _internaltemplateformatter(
       
   760             ui,
       
   761             out,
       
   762             topic,
       
   763             opts,
       
   764             spec,
       
   765             tmpl=b'{dict(%s)|cbor}' % spec.refargs,
       
   766             docheader=cborutil.BEGIN_INDEFINITE_ARRAY,
       
   767             docfooter=cborutil.BREAK,
       
   768         )
       
   769     elif spec.ref == b"cbor":
   725         return cborformatter(ui, out, topic, opts)
   770         return cborformatter(ui, out, topic, opts)
       
   771     elif spec.ref == b"json" and spec.refargs is not None:
       
   772         return _internaltemplateformatter(
       
   773             ui,
       
   774             out,
       
   775             topic,
       
   776             opts,
       
   777             spec,
       
   778             tmpl=b'{dict(%s)|json}' % spec.refargs,
       
   779             docheader=b'[\n ',
       
   780             docfooter=b'\n]\n',
       
   781             separator=b',\n ',
       
   782         )
   726     elif spec.ref == b"json":
   783     elif spec.ref == b"json":
   727         return jsonformatter(ui, out, topic, opts)
   784         return jsonformatter(ui, out, topic, opts)
   728     elif spec.ref == b"pickle":
   785     elif spec.ref == b"pickle":
       
   786         assert spec.refargs is None, r'function-style not supported'
   729         return pickleformatter(ui, out, topic, opts)
   787         return pickleformatter(ui, out, topic, opts)
   730     elif spec.ref == b"debug":
   788     elif spec.ref == b"debug":
       
   789         assert spec.refargs is None, r'function-style not supported'
   731         return debugformatter(ui, out, topic, opts)
   790         return debugformatter(ui, out, topic, opts)
   732     elif spec.ref or spec.tmpl or spec.mapfile:
   791     elif spec.ref or spec.tmpl or spec.mapfile:
       
   792         assert spec.refargs is None, r'function-style not supported'
   733         return templateformatter(ui, out, topic, opts, spec)
   793         return templateformatter(ui, out, topic, opts, spec)
   734     # developer config: ui.formatdebug
   794     # developer config: ui.formatdebug
   735     elif ui.configbool(b'ui', b'formatdebug'):
   795     elif ui.configbool(b'ui', b'formatdebug'):
   736         return debugformatter(ui, out, topic, opts)
   796         return debugformatter(ui, out, topic, opts)
   737     # deprecated config: ui.formatjson
   797     # deprecated config: ui.formatjson