Show More
@@ -383,9 +383,7 b' class templateformatter(baseformatter):' | |||||
383 | return |
|
383 | return | |
384 | ref = self._parts[part] |
|
384 | ref = self._parts[part] | |
385 |
|
385 | |||
386 |
# TODO: add support for filectx |
|
386 | # TODO: add support for filectx | |
387 | # function will have to declare dependent resources. e.g. |
|
|||
388 | # @templatekeyword(..., requires=('ctx',)) |
|
|||
389 | props = {} |
|
387 | props = {} | |
390 | # explicitly-defined fields precede templatekw |
|
388 | # explicitly-defined fields precede templatekw | |
391 | props.update(item) |
|
389 | props.update(item) |
@@ -283,6 +283,14 b' class templatekeyword(_templateregistrar' | |||||
283 |
|
283 | |||
284 | templatekeyword = registrar.templatekeyword() |
|
284 | templatekeyword = registrar.templatekeyword() | |
285 |
|
285 | |||
|
286 | # new API (since Mercurial 4.6) | |||
|
287 | @templatekeyword('mykeyword', requires={'repo', 'ctx'}) | |||
|
288 | def mykeywordfunc(context, mapping): | |||
|
289 | '''Explanation of this template keyword .... | |||
|
290 | ''' | |||
|
291 | pass | |||
|
292 | ||||
|
293 | # old API | |||
286 | @templatekeyword('mykeyword') |
|
294 | @templatekeyword('mykeyword') | |
287 | def mykeywordfunc(repo, ctx, templ, cache, revcache, **args): |
|
295 | def mykeywordfunc(repo, ctx, templ, cache, revcache, **args): | |
288 | '''Explanation of this template keyword .... |
|
296 | '''Explanation of this template keyword .... | |
@@ -291,6 +299,11 b' class templatekeyword(_templateregistrar' | |||||
291 |
|
299 | |||
292 | The first string argument is used also in online help. |
|
300 | The first string argument is used also in online help. | |
293 |
|
301 | |||
|
302 | Optional argument 'requires' should be a collection of resource names | |||
|
303 | which the template keyword depends on. This also serves as a flag to | |||
|
304 | switch to the new API. If 'requires' is unspecified, all template | |||
|
305 | keywords and resources are expanded to the function arguments. | |||
|
306 | ||||
294 | 'templatekeyword' instance in example above can be used to |
|
307 | 'templatekeyword' instance in example above can be used to | |
295 | decorate multiple functions. |
|
308 | decorate multiple functions. | |
296 |
|
309 | |||
@@ -301,6 +314,9 b' class templatekeyword(_templateregistrar' | |||||
301 | Otherwise, explicit 'templatekw.loadkeyword()' is needed. |
|
314 | Otherwise, explicit 'templatekw.loadkeyword()' is needed. | |
302 | """ |
|
315 | """ | |
303 |
|
316 | |||
|
317 | def _extrasetup(self, name, func, requires=None): | |||
|
318 | func._requires = requires | |||
|
319 | ||||
304 | class templatefilter(_templateregistrarbase): |
|
320 | class templatefilter(_templateregistrarbase): | |
305 | """Decorator to register template filer |
|
321 | """Decorator to register template filer | |
306 |
|
322 |
@@ -341,21 +341,14 b' defaulttempl = {' | |||||
341 | # filecopy is preserved for compatibility reasons |
|
341 | # filecopy is preserved for compatibility reasons | |
342 | defaulttempl['filecopy'] = defaulttempl['file_copy'] |
|
342 | defaulttempl['filecopy'] = defaulttempl['file_copy'] | |
343 |
|
343 | |||
344 | # keywords are callables like: |
|
344 | # keywords are callables (see registrar.templatekeyword for details) | |
345 | # fn(repo, ctx, templ, cache, revcache, **args) |
|
|||
346 | # with: |
|
|||
347 | # repo - current repository instance |
|
|||
348 | # ctx - the changectx being displayed |
|
|||
349 | # templ - the templater instance |
|
|||
350 | # cache - a cache dictionary for the whole templater run |
|
|||
351 | # revcache - a cache dictionary for the current revision |
|
|||
352 | keywords = {} |
|
345 | keywords = {} | |
353 |
|
||||
354 | templatekeyword = registrar.templatekeyword(keywords) |
|
346 | templatekeyword = registrar.templatekeyword(keywords) | |
355 |
|
347 | |||
356 | @templatekeyword('author') |
|
348 | @templatekeyword('author', requires={'ctx'}) | |
357 |
def showauthor( |
|
349 | def showauthor(context, mapping): | |
358 | """String. The unmodified author of the changeset.""" |
|
350 | """String. The unmodified author of the changeset.""" | |
|
351 | ctx = context.resource(mapping, 'ctx') | |||
359 | return ctx.user() |
|
352 | return ctx.user() | |
360 |
|
353 | |||
361 | @templatekeyword('bisect') |
|
354 | @templatekeyword('bisect') |
@@ -436,12 +436,18 b' def runsymbol(context, mapping, key, def' | |||||
436 | v = context.process(key, safemapping) |
|
436 | v = context.process(key, safemapping) | |
437 | except TemplateNotFound: |
|
437 | except TemplateNotFound: | |
438 | v = default |
|
438 | v = default | |
439 | if callable(v): |
|
439 | if callable(v) and getattr(v, '_requires', None) is None: | |
440 | # TODO: templatekw functions will be updated to take (context, mapping) |
|
440 | # old templatekw: expand all keywords and resources | |
441 | # pair instead of **props |
|
|||
442 | props = context._resources.copy() |
|
441 | props = context._resources.copy() | |
443 | props.update(mapping) |
|
442 | props.update(mapping) | |
444 | return v(**pycompat.strkwargs(props)) |
|
443 | return v(**pycompat.strkwargs(props)) | |
|
444 | if callable(v): | |||
|
445 | # new templatekw | |||
|
446 | try: | |||
|
447 | return v(context, mapping) | |||
|
448 | except ResourceUnavailable: | |||
|
449 | # unsupported keyword is mapped to empty just like unknown keyword | |||
|
450 | return None | |||
445 | return v |
|
451 | return v | |
446 |
|
452 | |||
447 | def buildtemplate(exp, context): |
|
453 | def buildtemplate(exp, context): |
@@ -214,6 +214,8 b' Never crash on internal resource not ava' | |||||
214 | abort: template resource not available: ctx |
|
214 | abort: template resource not available: ctx | |
215 | [255] |
|
215 | [255] | |
216 |
|
216 | |||
|
217 | $ hg config -T '{author}' | |||
|
218 | ||||
217 | Quoting for ui.logtemplate |
|
219 | Quoting for ui.logtemplate | |
218 |
|
220 | |||
219 | $ hg tip --config "ui.logtemplate={rev}\n" |
|
221 | $ hg tip --config "ui.logtemplate={rev}\n" |
@@ -9,6 +9,15 b'' | |||||
9 | > self._defaults = defaults |
|
9 | > self._defaults = defaults | |
10 | > self._resources = resources |
|
10 | > self._resources = resources | |
11 | > |
|
11 | > | |
|
12 | > def symbol(self, mapping, key): | |||
|
13 | > return mapping[key] | |||
|
14 | > | |||
|
15 | > def resource(self, mapping, key): | |||
|
16 | > v = self._resources[key] | |||
|
17 | > if v is None: | |||
|
18 | > v = mapping[key] | |||
|
19 | > return v | |||
|
20 | > | |||
12 | > def process(self, t, map): |
|
21 | > def process(self, t, map): | |
13 | > tmpl = self.loader(t) |
|
22 | > tmpl = self.loader(t) | |
14 | > props = self._defaults.copy() |
|
23 | > props = self._defaults.copy() | |
@@ -16,10 +25,12 b'' | |||||
16 | > for k, v in props.items(): |
|
25 | > for k, v in props.items(): | |
17 | > if k in ('templ', 'ctx', 'repo', 'revcache', 'cache', 'troubles'): |
|
26 | > if k in ('templ', 'ctx', 'repo', 'revcache', 'cache', 'troubles'): | |
18 | > continue |
|
27 | > continue | |
19 | > if hasattr(v, '__call__'): |
|
28 | > if callable(v) and getattr(v, '_requires', None) is None: | |
20 | > props = self._resources.copy() |
|
29 | > props = self._resources.copy() | |
21 | > props.update(map) |
|
30 | > props.update(map) | |
22 | > v = v(**props) |
|
31 | > v = v(**props) | |
|
32 | > elif callable(v): | |||
|
33 | > v = v(self, props) | |||
23 | > v = templater.stringify(v) |
|
34 | > v = templater.stringify(v) | |
24 | > tmpl = tmpl.replace('{{%s}}' % k, v) |
|
35 | > tmpl = tmpl.replace('{{%s}}' % k, v) | |
25 | > yield tmpl |
|
36 | > yield tmpl |
General Comments 0
You need to be logged in to leave comments.
Login now