--- a/mercurial/formatter.py Sat Oct 05 23:20:35 2019 -0400
+++ b/mercurial/formatter.py Sat Oct 05 23:30:09 2019 -0400
@@ -475,7 +475,7 @@
class templateformatter(baseformatter):
- def __init__(self, ui, out, topic, opts, spec):
+ def __init__(self, ui, out, topic, opts, spec, overridetemplates=None):
baseformatter.__init__(self, ui, topic, opts, _templateconverter)
self._out = out
self._tref = spec.ref
@@ -486,6 +486,8 @@
resources=templateresources(ui),
cache=templatekw.defaulttempl,
)
+ if overridetemplates:
+ self._t.cache.update(overridetemplates)
self._parts = templatepartsmap(
spec, self._t, [b'docheader', b'docfooter', b'separator']
)
@@ -523,6 +525,7 @@
ref = attr.ib()
tmpl = attr.ib()
mapfile = attr.ib()
+ refargs = attr.ib(default=None)
def lookuptemplate(ui, topic, tmpl):
@@ -556,6 +559,12 @@
if tmpl in {b'cbor', b'json', b'pickle', b'debug'}:
return templatespec(tmpl, None, None)
+ # a function-style reference to built-in template
+ func, fsep, ftail = tmpl.partition(b'(')
+ if func in {b'cbor', b'json'} and fsep and ftail.endswith(b')'):
+ templater.parseexpr(tmpl) # make sure syntax errors are confined
+ return templatespec(func, None, None, refargs=ftail[:-1])
+
# perhaps a stock style?
if not os.path.split(tmpl)[0]:
mapname = templater.templatepath(
@@ -719,17 +728,68 @@
}
+def _internaltemplateformatter(
+ ui,
+ out,
+ topic,
+ opts,
+ spec,
+ tmpl,
+ docheader=b'',
+ docfooter=b'',
+ separator=b'',
+):
+ """Build template formatter that handles customizable built-in templates
+ such as -Tjson(...)"""
+ templates = {spec.ref: tmpl}
+ if docheader:
+ templates[b'%s:docheader' % spec.ref] = docheader
+ if docfooter:
+ templates[b'%s:docfooter' % spec.ref] = docfooter
+ if separator:
+ templates[b'%s:separator' % spec.ref] = separator
+ return templateformatter(
+ ui, out, topic, opts, spec, overridetemplates=templates
+ )
+
+
def formatter(ui, out, topic, opts):
spec = lookuptemplate(ui, topic, opts.get(b'template', b''))
- if spec.ref == b"cbor":
+ if spec.ref == b"cbor" and spec.refargs is not None:
+ return _internaltemplateformatter(
+ ui,
+ out,
+ topic,
+ opts,
+ spec,
+ tmpl=b'{dict(%s)|cbor}' % spec.refargs,
+ docheader=cborutil.BEGIN_INDEFINITE_ARRAY,
+ docfooter=cborutil.BREAK,
+ )
+ elif spec.ref == b"cbor":
return cborformatter(ui, out, topic, opts)
+ elif spec.ref == b"json" and spec.refargs is not None:
+ return _internaltemplateformatter(
+ ui,
+ out,
+ topic,
+ opts,
+ spec,
+ tmpl=b'{dict(%s)|json}' % spec.refargs,
+ docheader=b'[\n ',
+ docfooter=b'\n]\n',
+ separator=b',\n ',
+ )
elif spec.ref == b"json":
return jsonformatter(ui, out, topic, opts)
elif spec.ref == b"pickle":
+ assert spec.refargs is None, r'function-style not supported'
return pickleformatter(ui, out, topic, opts)
elif spec.ref == b"debug":
+ assert spec.refargs is None, r'function-style not supported'
return debugformatter(ui, out, topic, opts)
elif spec.ref or spec.tmpl or spec.mapfile:
+ assert spec.refargs is None, r'function-style not supported'
return templateformatter(ui, out, topic, opts, spec)
# developer config: ui.formatdebug
elif ui.configbool(b'ui', b'formatdebug'):
--- a/tests/test-template-map.t Sat Oct 05 23:20:35 2019 -0400
+++ b/tests/test-template-map.t Sat Oct 05 23:30:09 2019 -0400
@@ -736,6 +736,18 @@
}
]
+ $ hg log -r . -T'cbor(rev, node|short)' | "$PYTHON" "$TESTTMP/decodecborarray.py"
+ [
+ {
+ 'node': '95c24699272e',
+ 'rev': 8
+ }
+ ]
+
+ $ hg log -r . -T'cbor()' | "$PYTHON" "$TESTTMP/decodecborarray.py"
+ [
+ {}
+ ]
Test JSON style:
@@ -1101,6 +1113,17 @@
}
]
+ $ hg log -l2 -T'json(rev, parents)'
+ [
+ {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8},
+ {"parents": ["0000000000000000000000000000000000000000"], "rev": 7}
+ ]
+
+ $ hg log -r. -T'json()'
+ [
+ {}
+ ]
+
Other unsupported formatter styles:
$ hg log -qr . -Tpickle
@@ -1110,6 +1133,24 @@
abort: "debug" not in template map
[255]
+Unparsable function-style references:
+
+ $ hg log -qr . -T'json(-)'
+ hg: parse error at 6: not a prefix: )
+ (json(-)
+ ^ here)
+ [255]
+
+For backward compatibility, the following examples are not parsed as
+function-style references:
+
+ $ hg log -qr . -T'cbor(rev'
+ cbor(rev (no-eol)
+ $ hg log -qr . -T'json (rev)'
+ json (rev) (no-eol)
+ $ hg log -qr . -T'json(x="{rev}")'
+ json(x="8") (no-eol)
+
Error if style not readable:
#if unix-permissions no-root