@@ -383,9 +383,7 @@ class templateformatter(baseformatter):
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',))
+ # TODO: add support for filectx
props = {}
# explicitly-defined fields precede templatekw
props.update(item)
@@ -283,6 +283,14 @@ class templatekeyword(_templateregistrar
templatekeyword = registrar.templatekeyword()
+ # new API (since Mercurial 4.6)
+ @templatekeyword('mykeyword', requires={'repo', 'ctx'})
+ def mykeywordfunc(context, mapping):
+ '''Explanation of this template keyword ....
+ '''
+ pass
+
+ # old API
@templatekeyword('mykeyword')
def mykeywordfunc(repo, ctx, templ, cache, revcache, **args):
'''Explanation of this template keyword ....
@@ -291,6 +299,11 @@ class templatekeyword(_templateregistrar
The first string argument is used also in online help.
+ Optional argument 'requires' should be a collection of resource names
+ which the template keyword depends on. This also serves as a flag to
+ switch to the new API. If 'requires' is unspecified, all template
+ keywords and resources are expanded to the function arguments.
+
'templatekeyword' instance in example above can be used to
decorate multiple functions.
@@ -301,6 +314,9 @@ class templatekeyword(_templateregistrar
Otherwise, explicit 'templatekw.loadkeyword()' is needed.
"""
+ def _extrasetup(self, name, func, requires=None):
+ func._requires = requires
+
class templatefilter(_templateregistrarbase):
"""Decorator to register template filer
@@ -341,21 +341,14 @@ defaulttempl = {
# filecopy is preserved for compatibility reasons
defaulttempl['filecopy'] = defaulttempl['file_copy']
-# keywords are callables like:
-# fn(repo, ctx, templ, cache, revcache, **args)
-# with:
-# repo - current repository instance
-# ctx - the changectx being displayed
-# templ - the templater instance
-# cache - a cache dictionary for the whole templater run
-# revcache - a cache dictionary for the current revision
+# keywords are callables (see registrar.templatekeyword for details)
keywords = {}
-
templatekeyword = registrar.templatekeyword(keywords)
-@templatekeyword('author')
-def showauthor(repo, ctx, templ, **args):
+@templatekeyword('author', requires={'ctx'})
+def showauthor(context, mapping):
"""String. The unmodified author of the changeset."""
+ ctx = context.resource(mapping, 'ctx')
return ctx.user()
@templatekeyword('bisect')
@@ -436,12 +436,18 @@ def runsymbol(context, mapping, key, def
v = context.process(key, safemapping)
except TemplateNotFound:
v = default
- if callable(v):
- # TODO: templatekw functions will be updated to take (context, mapping)
- # pair instead of **props
+ if callable(v) and getattr(v, '_requires', None) is None:
+ # old templatekw: expand all keywords and resources
props = context._resources.copy()
props.update(mapping)
return v(**pycompat.strkwargs(props))
+ if callable(v):
+ # new templatekw
+ try:
+ return v(context, mapping)
+ except ResourceUnavailable:
+ # unsupported keyword is mapped to empty just like unknown keyword
+ return None
return v
def buildtemplate(exp, context):
@@ -214,6 +214,8 @@ Never crash on internal resource not ava
abort: template resource not available: ctx
[255]
+ $ hg config -T '{author}'
+
Quoting for ui.logtemplate
$ hg tip --config "ui.logtemplate={rev}\n"
@@ -9,6 +9,15 @@
> self._defaults = defaults
> self._resources = resources
>
+ > def symbol(self, mapping, key):
+ > return mapping[key]
+ >
+ > def resource(self, mapping, key):
+ > v = self._resources[key]
+ > if v is None:
+ > v = mapping[key]
+ > return v
+ >
> def process(self, t, map):
> tmpl = self.loader(t)
> props = self._defaults.copy()
@@ -16,10 +25,12 @@
> for k, v in props.items():
> if k in ('templ', 'ctx', 'repo', 'revcache', 'cache', 'troubles'):
> continue
- > if hasattr(v, '__call__'):
+ > if callable(v) and getattr(v, '_requires', None) is None:
> props = self._resources.copy()
> props.update(map)
> v = v(**props)
+ > elif callable(v):
+ > v = v(self, props)
> v = templater.stringify(v)
> tmpl = tmpl.replace('{{%s}}' % k, v)
> yield tmpl