--- a/mercurial/commands.py Sun Mar 18 23:36:52 2018 +0900
+++ b/mercurial/commands.py Thu Mar 15 22:27:16 2018 +0900
@@ -386,7 +386,7 @@
% ((pats and m.rel(abs)) or abs))
continue
- fm = rootfm.nested('lines')
+ fm = rootfm.nested('lines', tmpl='{rev}: {line}')
lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
diffopts=diffopts)
if not lines:
@@ -2506,7 +2506,7 @@
if not opts.get('text') and binary():
fm.plain(_(" Binary file matches"))
else:
- displaymatches(fm.nested('texts'), l)
+ displaymatches(fm.nested('texts', tmpl='{text}'), l)
fm.plain(eol)
found = True
if opts.get('files_with_matches'):
@@ -2848,7 +2848,7 @@
numoutput = ["%d" % p.rev() for p in parents]
output.append("%s%s" % ('+'.join(numoutput), dirty))
- fn = fm.nested('parents')
+ fn = fm.nested('parents', tmpl='{rev}:{node|formatnode}', sep=' ')
for p in parents:
fn.startitem()
fn.data(rev=p.rev())
@@ -5615,7 +5615,7 @@
names.append(name)
vers.append(extensions.moduleversion(module) or None)
isinternals.append(extensions.ismoduleinternal(module))
- fn = fm.nested("extensions")
+ fn = fm.nested("extensions", tmpl='{name}\n')
if names:
namefmt = " %%-%ds " % max(len(n) for n in names)
places = [_("external"), _("internal")]
--- a/mercurial/formatter.py Sun Mar 18 23:36:52 2018 +0900
+++ b/mercurial/formatter.py Thu Mar 15 22:27:16 2018 +0900
@@ -95,7 +95,7 @@
>>> def subrepos(ui, fm):
... fm.startitem()
... fm.write(b'reponame', b'[%s]\\n', b'baz')
-... files(ui, fm.nested(b'files'))
+... files(ui, fm.nested(b'files', tmpl=b'{reponame}'))
... fm.end()
>>> show(subrepos)
[baz]
@@ -138,6 +138,10 @@
storecontext = False
@staticmethod
+ def wrapnested(data, tmpl, sep):
+ '''wrap nested data by appropriate type'''
+ return data
+ @staticmethod
def formatdate(date, fmt):
'''convert date tuple to appropriate format'''
return date
@@ -210,9 +214,10 @@
def isplain(self):
'''check for plain formatter usage'''
return False
- def nested(self, field):
+ def nested(self, field, tmpl=None, sep=''):
'''sub formatter to store nested data in the specified field'''
- self._item[field] = data = []
+ data = []
+ self._item[field] = self._converter.wrapnested(data, tmpl, sep)
return _nestedformatter(self._ui, self._converter, data)
def end(self):
'''end output for the formatter'''
@@ -243,6 +248,9 @@
storecontext = False
@staticmethod
+ def wrapnested(data, tmpl, sep):
+ raise error.ProgrammingError('plainformatter should never be nested')
+ @staticmethod
def formatdate(date, fmt):
'''stringify date tuple in the given format'''
return dateutil.datestr(date, fmt)
@@ -290,7 +298,7 @@
self._write(text, **opts)
def isplain(self):
return True
- def nested(self, field):
+ def nested(self, field, tmpl=None, sep=''):
# nested data will be directly written to ui
return self
def end(self):
@@ -350,6 +358,10 @@
storecontext = True
@staticmethod
+ def wrapnested(data, tmpl, sep):
+ '''wrap nested data by templatable type'''
+ return templateutil.mappinglist(data, tmpl=tmpl, sep=sep)
+ @staticmethod
def formatdate(date, fmt):
'''return date tuple'''
return date
--- a/tests/test-annotate.t Sun Mar 18 23:36:52 2018 +0900
+++ b/tests/test-annotate.t Thu Mar 15 22:27:16 2018 +0900
@@ -90,6 +90,28 @@
> EOF
$ hg ci -mb2 -d '2 0'
+default output of '{lines}' should be readable
+
+ $ hg annotate -T'{lines}' a
+ 0: a
+ 1: a
+ 1: a
+ $ hg annotate -T'{join(lines, "\n")}' a
+ 0: a
+
+ 1: a
+
+ 1: a
+
+several filters can be applied to '{lines}'
+
+ $ hg annotate -T'{lines|stringify}' a
+ 0: a
+ 1: a
+ 1: a
+ $ hg annotate -T'{lines|count}\n' a
+ 3
+
annotate multiple files (JSON)
$ hg annotate -Tjson a b
--- a/tests/test-extension.t Sun Mar 18 23:36:52 2018 +0900
+++ b/tests/test-extension.t Thu Mar 15 22:27:16 2018 +0900
@@ -1407,6 +1407,11 @@
$ hg version -q --config extensions.throw=throw.py
Mercurial Distributed SCM (version *) (glob)
+Test template output:
+
+ $ hg version --config extensions.strip= -T'{extensions}'
+ strip
+
Test JSON output of version:
$ hg version -Tjson
--- a/tests/test-grep.t Sun Mar 18 23:36:52 2018 +0900
+++ b/tests/test-grep.t Thu Mar 15 22:27:16 2018 +0900
@@ -48,6 +48,11 @@
port:4:914fa752cdea:vaPORTight
port:4:914fa752cdea:imPORT/exPORT
+ $ hg grep port -T '{file}:{rev}:{texts}\n'
+ port:4:export
+ port:4:vaportight
+ port:4:import/export
+
simple JSON (no "change" field)
$ hg grep -Tjson port
--- a/tests/test-identify.t Sun Mar 18 23:36:52 2018 +0900
+++ b/tests/test-identify.t Thu Mar 15 22:27:16 2018 +0900
@@ -62,6 +62,8 @@
2147483647 ffff
$ hg id -T '{parents % "{rev} {node|shortest} {desc}\n"}'
0 cb9a a
+ $ hg id -T '{parents}\n'
+ 0:cb9a9f314b8b
test nested template: '{tags}'/'{node}' constants shouldn't override the
default keywords, but '{id}' persists because there's no default keyword