Patchwork [3,of,4] formatter: provide hint of context keys required by template

login
register
mail settings
Submitter Yuya Nishihara
Date June 18, 2018, 1:37 p.m.
Message ID <e669b5c1e8a6d4d36d38.1529329027@mimosa>
Download mbox | patch
Permalink /patch/32280/
State Accepted
Headers show

Comments

Yuya Nishihara - June 18, 2018, 1:37 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1528463422 -32400
#      Fri Jun 08 22:10:22 2018 +0900
# Node ID e669b5c1e8a6d4d36d38b0f9c525cfd05846cec8
# Parent  21015eb08c98d12fa2060e8d1414e9f557a448d7
formatter: provide hint of context keys required by template

This allows us to create ctx objects only if necessary.

I tried another idea which is to populate ctx from 'repo' and 'node' value
on demand. It worked, but seemed unnecessarily complicated. So I chose a
simpler one.

The datafields argument is a space-separated string for consistency with
fm.write() API.

Patch

diff --git a/mercurial/formatter.py b/mercurial/formatter.py
--- a/mercurial/formatter.py
+++ b/mercurial/formatter.py
@@ -124,6 +124,7 @@  from . import (
     error,
     pycompat,
     templatefilters,
+    templatefuncs,
     templatekw,
     templater,
     templateutil,
@@ -192,6 +193,9 @@  class baseformatter(object):
         # name is mandatory argument for now, but it could be optional if
         # we have default template keyword, e.g. {item}
         return self._converter.formatlist(data, name, fmt, sep)
+    def contexthint(self, datafields):
+        '''set of context object keys to be required given datafields set'''
+        return set()
     def context(self, **ctxs):
         '''insert context objects to be used to render template keywords'''
         ctxs = pycompat.byteskwargs(ctxs)
@@ -418,6 +422,24 @@  class templateformatter(baseformatter):
     def _symbolsused(self):
         return self._t.symbolsuseddefault()
 
+    def contexthint(self, datafields):
+        '''set of context object keys to be required by the template, given
+        datafields overridden by immediate values'''
+        requires = set()
+        ksyms, fsyms = self._symbolsused
+        ksyms = ksyms - set(datafields.split())  # exclude immediate fields
+        symtables = [(ksyms, templatekw.keywords),
+                     (fsyms, templatefuncs.funcs)]
+        for syms, table in symtables:
+            for k in syms:
+                f = table.get(k)
+                if not f:
+                    continue
+                requires.update(getattr(f, '_requires', ()))
+        if 'repo' in requires:
+            requires.add('ctx')  # there's no API to pass repo to formatter
+        return requires & {'ctx', 'fctx'}
+
     def datahint(self):
         '''set of field names to be referenced from the template'''
         return self._symbolsused[0]