##// END OF EJS Templates
templatekw: add new-style template expansion to {manifest}...
Yuya Nishihara -
r34331:89aec183 default
parent child Browse files
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': repo.manifestlog._revlog.rev(mnode),
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 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
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