formatter: add support for docheader and docfooter templates
authorYuya Nishihara <yuya@tcha.org>
Sat, 22 Apr 2017 21:46:14 +0900
changeset 32949 13eebc189ff3
parent 32948 12a0794fa2e3
child 32950 5100ce217dfa
formatter: add support for docheader and docfooter templates templatepartsmap() is a minimal copy of changeset_templater.__init__(). I tried to factor out a common function, but it was unnecessarily complicated.
mercurial/formatter.py
tests/test-branches.t
--- a/mercurial/formatter.py	Sat Apr 22 21:38:08 2017 +0900
+++ b/mercurial/formatter.py	Sat Apr 22 21:46:14 2017 +0900
@@ -350,8 +350,12 @@
         spec = lookuptemplate(ui, topic, opts.get('template', ''))
         self._tref = spec.ref
         self._t = loadtemplater(ui, spec, cache=templatekw.defaulttempl)
+        self._parts = templatepartsmap(spec, self._t,
+                                       ['docheader', 'docfooter'])
         self._counter = itertools.count()
         self._cache = {}  # for templatekw/funcs to store reusable data
+        self._renderitem('docheader', {})
+
     def context(self, **ctxs):
         '''insert context objects to be used to render template keywords'''
         ctxs = pycompat.byteskwargs(ctxs)
@@ -363,7 +367,11 @@
         item['index'] = next(self._counter)
         self._renderitem(self._tref, item)
 
-    def _renderitem(self, ref, item):
+    def _renderitem(self, part, item):
+        if part not in self._parts:
+            return
+        ref = self._parts[part]
+
         # TODO: add support for filectx. probably each template keyword or
         # function will have to declare dependent resources. e.g.
         # @templatekeyword(..., requires=('ctx',))
@@ -381,6 +389,10 @@
         g = self._t(ref, ui=self._ui, cache=self._cache, **props)
         self._out.write(templater.stringify(g))
 
+    def end(self):
+        baseformatter.end(self)
+        self._renderitem('docfooter', {})
+
 templatespec = collections.namedtuple(r'templatespec',
                                       r'ref tmpl mapfile')
 
@@ -434,6 +446,13 @@
     # constant string?
     return templatespec('', tmpl, None)
 
+def templatepartsmap(spec, t, partnames):
+    """Create a mapping of {part: ref}"""
+    partsmap = {spec.ref: spec.ref}  # initial ref must exist in t
+    if spec.mapfile:
+        partsmap.update((p, p) for p in partnames if p in t)
+    return partsmap
+
 def loadtemplater(ui, spec, cache=None):
     """Create a templater from either a literal template or loading from
     a map file"""
--- a/tests/test-branches.t	Sat Apr 22 21:38:08 2017 +0900
+++ b/tests/test-branches.t	Sat Apr 22 21:46:14 2017 +0900
@@ -530,6 +530,19 @@
   a: Adding b branch head 2
   default: Adding root node
 
+  $ cat <<'EOF' > "$TESTTMP/map-myjson"
+  > docheader = '\{\n'
+  > docfooter = '\n}\n'
+  > branches = '{ifeq(index, 0, "", ",\n")} {dict(branch, node|short)|json}'
+  > EOF
+  $ hg branches -T "$TESTTMP/map-myjson"
+  {
+   {"branch": "b", "node": "e23b5505d1ad"},
+   {"branch": "a branch *", "node": "10ff5895aa57"}, (glob)
+   {"branch": "a", "node": "d8cbc61dbaa6"},
+   {"branch": "default", "node": "19709c5a4e75"}
+  }
+
 Tests of revision branch name caching
 
 We rev branch cache is updated automatically. In these tests we use a trick to