Show More
@@ -70,6 +70,28 b' class _hybrid(object):' | |||
|
70 | 70 | raise AttributeError(name) |
|
71 | 71 | return getattr(self._values, name) |
|
72 | 72 | |
|
73 | class _mappable(object): | |
|
74 | """Wrapper for non-list/dict object to support map operation | |
|
75 | ||
|
76 | This class allows us to handle both: | |
|
77 | - "{manifest}" | |
|
78 | - "{manifest % '{rev}:{node}'}" | |
|
79 | ||
|
80 | Unlike a _hybrid, this does not simulate the behavior of the underling | |
|
81 | value. Use unwrapvalue() or unwraphybrid() to obtain the inner object. | |
|
82 | """ | |
|
83 | ||
|
84 | def __init__(self, gen, value, makemap): | |
|
85 | self.gen = gen | |
|
86 | self._value = value # may be generator of strings | |
|
87 | self._makemap = makemap | |
|
88 | ||
|
89 | def tomap(self): | |
|
90 | return self._makemap() | |
|
91 | ||
|
92 | def itermaps(self): | |
|
93 | yield self.tomap() | |
|
94 | ||
|
73 | 95 | def hybriddict(data, key='key', value='value', fmt='%s=%s', gen=None): |
|
74 | 96 | """Wrap data to support both dict-like and string-like operations""" |
|
75 | 97 | return _hybrid(gen, data, lambda k: {key: k, value: data[k]}, |
@@ -86,6 +108,12 b' def unwraphybrid(thing):' | |||
|
86 | 108 | return thing |
|
87 | 109 | return thing.gen |
|
88 | 110 | |
|
111 | def unwrapvalue(thing): | |
|
112 | """Move the inner value object out of the wrapper""" | |
|
113 | if not util.safehasattr(thing, '_value'): | |
|
114 | return thing | |
|
115 | return thing._value | |
|
116 | ||
|
89 | 117 | def showdict(name, data, mapping, plural=None, key='key', value='value', |
|
90 | 118 | fmt='%s=%s', separator=' '): |
|
91 | 119 | c = [{key: k, value: v} for k, v in data.iteritems()] |
@@ -543,10 +571,14 b' def showmanifest(**args):' | |||
|
543 | 571 | if mnode is None: |
|
544 | 572 | # just avoid crash, we might want to use the 'ff...' hash in future |
|
545 | 573 | return |
|
574 | mrev = repo.manifestlog._revlog.rev(mnode) | |
|
575 | mhex = hex(mnode) | |
|
546 | 576 | args = args.copy() |
|
547 |
args.update({r'rev': |
|
|
548 | r'node': hex(mnode)}) | |
|
549 | return templ('manifest', **args) | |
|
577 | args.update({r'rev': mrev, r'node': mhex}) | |
|
578 | f = templ('manifest', **args) | |
|
579 | # TODO: perhaps 'ctx' should be dropped from mapping because manifest | |
|
580 | # rev and node are completely different from changeset's. | |
|
581 | return _mappable(f, f, lambda: {'rev': mrev, 'node': mhex}) | |
|
550 | 582 | |
|
551 | 583 | def shownames(namespace, **args): |
|
552 | 584 | """helper method to generate a template keyword for a namespace""" |
@@ -307,6 +307,7 b' def evalrawexp(context, mapping, arg):' | |||
|
307 | 307 | def evalfuncarg(context, mapping, arg): |
|
308 | 308 | """Evaluate given argument as value type""" |
|
309 | 309 | thing = evalrawexp(context, mapping, arg) |
|
310 | thing = templatekw.unwrapvalue(thing) | |
|
310 | 311 | # evalrawexp() may return string, generator of strings or arbitrary object |
|
311 | 312 | # such as date tuple, but filter does not want generator. |
|
312 | 313 | if isinstance(thing, types.GeneratorType): |
@@ -323,6 +324,7 b' def evalboolean(context, mapping, arg):' | |||
|
323 | 324 | thing = util.parsebool(data) |
|
324 | 325 | else: |
|
325 | 326 | thing = func(context, mapping, data) |
|
327 | thing = templatekw.unwrapvalue(thing) | |
|
326 | 328 | if isinstance(thing, bool): |
|
327 | 329 | return thing |
|
328 | 330 | # other objects are evaluated as strings, which means 0 is True, but |
@@ -768,6 +770,7 b' def join(context, mapping, args):' | |||
|
768 | 770 | # TODO: perhaps this should be evalfuncarg(), but it can't because hgweb |
|
769 | 771 | # abuses generator as a keyword that returns a list of dicts. |
|
770 | 772 | joinset = evalrawexp(context, mapping, args[0]) |
|
773 | joinset = templatekw.unwrapvalue(joinset) | |
|
771 | 774 | joinfmt = getattr(joinset, 'joinfmt', pycompat.identity) |
|
772 | 775 | joiner = " " |
|
773 | 776 | if len(args) > 1: |
@@ -3119,6 +3119,20 b' Test new-style inline templating:' | |||
|
3119 | 3119 | hg: parse error: None is not iterable |
|
3120 | 3120 | [255] |
|
3121 | 3121 | |
|
3122 | Test new-style inline templating of non-list/dict type: | |
|
3123 | ||
|
3124 | $ hg log -R latesttag -r tip -T '{manifest}\n' | |
|
3125 | 11:2bc6e9006ce2 | |
|
3126 | $ hg log -R latesttag -r tip -T 'string length: {manifest|count}\n' | |
|
3127 | string length: 15 | |
|
3128 | $ hg log -R latesttag -r tip -T '{manifest % "{rev}:{node}"}\n' | |
|
3129 | 11:2bc6e9006ce29882383a22d39fd1f4e66dd3e2fc | |
|
3130 | ||
|
3131 | Test manifest can be join()-ed as before, though it's silly: | |
|
3132 | ||
|
3133 | $ hg log -R latesttag -r tip -T '{join(manifest, "")}\n' | |
|
3134 | 11:2bc6e9006ce2 | |
|
3135 | ||
|
3122 | 3136 | Test the sub function of templating for expansion: |
|
3123 | 3137 | |
|
3124 | 3138 |
$ |
General Comments 0
You need to be logged in to leave comments.
Login now