Show More
@@ -70,6 +70,28 b' class _hybrid(object):' | |||||
70 | raise AttributeError(name) |
|
70 | raise AttributeError(name) | |
71 | return getattr(self._values, name) |
|
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 | def hybriddict(data, key='key', value='value', fmt='%s=%s', gen=None): |
|
95 | def hybriddict(data, key='key', value='value', fmt='%s=%s', gen=None): | |
74 | """Wrap data to support both dict-like and string-like operations""" |
|
96 | """Wrap data to support both dict-like and string-like operations""" | |
75 | return _hybrid(gen, data, lambda k: {key: k, value: data[k]}, |
|
97 | return _hybrid(gen, data, lambda k: {key: k, value: data[k]}, | |
@@ -86,6 +108,12 b' def unwraphybrid(thing):' | |||||
86 | return thing |
|
108 | return thing | |
87 | return thing.gen |
|
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 | def showdict(name, data, mapping, plural=None, key='key', value='value', |
|
117 | def showdict(name, data, mapping, plural=None, key='key', value='value', | |
90 | fmt='%s=%s', separator=' '): |
|
118 | fmt='%s=%s', separator=' '): | |
91 | c = [{key: k, value: v} for k, v in data.iteritems()] |
|
119 | c = [{key: k, value: v} for k, v in data.iteritems()] | |
@@ -543,10 +571,14 b' def showmanifest(**args):' | |||||
543 | if mnode is None: |
|
571 | if mnode is None: | |
544 | # just avoid crash, we might want to use the 'ff...' hash in future |
|
572 | # just avoid crash, we might want to use the 'ff...' hash in future | |
545 | return |
|
573 | return | |
|
574 | mrev = repo.manifestlog._revlog.rev(mnode) | |||
|
575 | mhex = hex(mnode) | |||
546 | args = args.copy() |
|
576 | args = args.copy() | |
547 |
args.update({r'rev': |
|
577 | args.update({r'rev': mrev, r'node': mhex}) | |
548 | r'node': hex(mnode)}) |
|
578 | f = templ('manifest', **args) | |
549 | return 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 | def shownames(namespace, **args): |
|
583 | def shownames(namespace, **args): | |
552 | """helper method to generate a template keyword for a namespace""" |
|
584 | """helper method to generate a template keyword for a namespace""" |
@@ -307,6 +307,7 b' def evalrawexp(context, mapping, arg):' | |||||
307 | def evalfuncarg(context, mapping, arg): |
|
307 | def evalfuncarg(context, mapping, arg): | |
308 | """Evaluate given argument as value type""" |
|
308 | """Evaluate given argument as value type""" | |
309 | thing = evalrawexp(context, mapping, arg) |
|
309 | thing = evalrawexp(context, mapping, arg) | |
|
310 | thing = templatekw.unwrapvalue(thing) | |||
310 | # evalrawexp() may return string, generator of strings or arbitrary object |
|
311 | # evalrawexp() may return string, generator of strings or arbitrary object | |
311 | # such as date tuple, but filter does not want generator. |
|
312 | # such as date tuple, but filter does not want generator. | |
312 | if isinstance(thing, types.GeneratorType): |
|
313 | if isinstance(thing, types.GeneratorType): | |
@@ -323,6 +324,7 b' def evalboolean(context, mapping, arg):' | |||||
323 | thing = util.parsebool(data) |
|
324 | thing = util.parsebool(data) | |
324 | else: |
|
325 | else: | |
325 | thing = func(context, mapping, data) |
|
326 | thing = func(context, mapping, data) | |
|
327 | thing = templatekw.unwrapvalue(thing) | |||
326 | if isinstance(thing, bool): |
|
328 | if isinstance(thing, bool): | |
327 | return thing |
|
329 | return thing | |
328 | # other objects are evaluated as strings, which means 0 is True, but |
|
330 | # other objects are evaluated as strings, which means 0 is True, but | |
@@ -768,6 +770,7 b' def join(context, mapping, args):' | |||||
768 | # TODO: perhaps this should be evalfuncarg(), but it can't because hgweb |
|
770 | # TODO: perhaps this should be evalfuncarg(), but it can't because hgweb | |
769 | # abuses generator as a keyword that returns a list of dicts. |
|
771 | # abuses generator as a keyword that returns a list of dicts. | |
770 | joinset = evalrawexp(context, mapping, args[0]) |
|
772 | joinset = evalrawexp(context, mapping, args[0]) | |
|
773 | joinset = templatekw.unwrapvalue(joinset) | |||
771 | joinfmt = getattr(joinset, 'joinfmt', pycompat.identity) |
|
774 | joinfmt = getattr(joinset, 'joinfmt', pycompat.identity) | |
772 | joiner = " " |
|
775 | joiner = " " | |
773 | if len(args) > 1: |
|
776 | if len(args) > 1: |
@@ -3119,6 +3119,20 b' Test new-style inline templating:' | |||||
3119 | hg: parse error: None is not iterable |
|
3119 | hg: parse error: None is not iterable | |
3120 | [255] |
|
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 | Test the sub function of templating for expansion: |
|
3136 | Test the sub function of templating for expansion: | |
3123 |
|
3137 | |||
3124 |
$ |
|
3138 | $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n' |
General Comments 0
You need to be logged in to leave comments.
Login now