[PATCH 2 of 5] formatter: make nested items somewhat readable in template output

Yuya Nishihara yuya at tcha.org
Sat Apr 7 05:05:41 EDT 2018


# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1521120436 -32400
#      Thu Mar 15 22:27:16 2018 +0900
# Node ID 8a79a82137c6a5af4d88e32ec6646db6539e6d60
# Parent  1f9fba66207ee223814feb4e9702d09522542f3d
formatter: make nested items somewhat readable in template output

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -386,7 +386,7 @@ def annotate(ui, repo, *pats, **opts):
                          % ((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:
@@ -2505,7 +2505,7 @@ def grep(ui, repo, pattern, *pats, **opt
                 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'):
@@ -2847,7 +2847,7 @@ def identify(ui, repo, source=None, rev=
                 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())
@@ -5608,7 +5608,7 @@ def version_(ui, **opts):
         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")]
diff --git a/mercurial/formatter.py b/mercurial/formatter.py
--- a/mercurial/formatter.py
+++ b/mercurial/formatter.py
@@ -95,7 +95,7 @@ Nested example:
 >>> 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 @@ class _nullconverter(object):
     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 @@ class baseformatter(object):
     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 @@ class _plainconverter(object):
     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 @@ class plainformatter(baseformatter):
         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 @@ class _templateconverter(object):
     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
diff --git a/tests/test-annotate.t b/tests/test-annotate.t
--- a/tests/test-annotate.t
+++ b/tests/test-annotate.t
@@ -90,6 +90,28 @@ log-like templating
   > 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
diff --git a/tests/test-extension.t b/tests/test-extension.t
--- a/tests/test-extension.t
+++ b/tests/test-extension.t
@@ -1407,6 +1407,11 @@ Test version number support in 'hg versi
   $ 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
diff --git a/tests/test-grep.t b/tests/test-grep.t
--- a/tests/test-grep.t
+++ b/tests/test-grep.t
@@ -48,6 +48,11 @@ simple templated
   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
diff --git a/tests/test-identify.t b/tests/test-identify.t
--- a/tests/test-identify.t
+++ b/tests/test-identify.t
@@ -62,6 +62,8 @@ test template keywords and functions whi
   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


More information about the Mercurial-devel mailing list