mercurial/templater.py
changeset 28547 73d01cba5810
parent 28546 1987ed32efca
child 28628 ed1d90f6e921
equal deleted inserted replaced
28546:1987ed32efca 28547:73d01cba5810
   175 
   175 
   176     if quote:
   176     if quote:
   177         raise error.ParseError(_("unterminated string"), start)
   177         raise error.ParseError(_("unterminated string"), start)
   178     return parsed, pos
   178     return parsed, pos
   179 
   179 
       
   180 def _unnesttemplatelist(tree):
       
   181     """Expand list of templates to node tuple
       
   182 
       
   183     >>> def f(tree):
       
   184     ...     print prettyformat(_unnesttemplatelist(tree))
       
   185     >>> f(('template', []))
       
   186     ('string', '')
       
   187     >>> f(('template', [('string', 'foo')]))
       
   188     ('string', 'foo')
       
   189     >>> f(('template', [('string', 'foo'), ('symbol', 'rev')]))
       
   190     (template
       
   191       ('string', 'foo')
       
   192       ('symbol', 'rev'))
       
   193     >>> f(('template', [('symbol', 'rev')]))  # template(rev) -> str
       
   194     (template
       
   195       ('symbol', 'rev'))
       
   196     >>> f(('template', [('template', [('string', 'foo')])]))
       
   197     ('string', 'foo')
       
   198     """
       
   199     if not isinstance(tree, tuple):
       
   200         return tree
       
   201     op = tree[0]
       
   202     if op != 'template':
       
   203         return (op,) + tuple(_unnesttemplatelist(x) for x in tree[1:])
       
   204 
       
   205     assert len(tree) == 2
       
   206     xs = tuple(_unnesttemplatelist(x) for x in tree[1])
       
   207     if not xs:
       
   208         return ('string', '')  # empty template ""
       
   209     elif len(xs) == 1 and xs[0][0] == 'string':
       
   210         return xs[0]  # fast path for string with no template fragment "x"
       
   211     else:
       
   212         return (op,) + xs
       
   213 
   180 def parse(tmpl):
   214 def parse(tmpl):
   181     """Parse template string into tree"""
   215     """Parse template string into tree"""
   182     parsed, pos = _parsetemplate(tmpl, 0, len(tmpl))
   216     parsed, pos = _parsetemplate(tmpl, 0, len(tmpl))
   183     assert pos == len(tmpl), 'unquoted template should be consumed'
   217     assert pos == len(tmpl), 'unquoted template should be consumed'
   184     return ('template', parsed)
   218     return _unnesttemplatelist(('template', parsed))
       
   219 
       
   220 def prettyformat(tree):
       
   221     return parser.prettyformat(tree, ('integer', 'string', 'symbol'))
   185 
   222 
   186 def compiletemplate(tmpl, context):
   223 def compiletemplate(tmpl, context):
   187     """Parse and compile template string to (func, data) pair"""
   224     """Parse and compile template string to (func, data) pair"""
   188     return compileexp(parse(tmpl), context, methods)
   225     return compileexp(parse(tmpl), context, methods)
   189 
   226 
   279     if callable(v):
   316     if callable(v):
   280         return v(**mapping)
   317         return v(**mapping)
   281     return v
   318     return v
   282 
   319 
   283 def buildtemplate(exp, context):
   320 def buildtemplate(exp, context):
   284     ctmpl = [compileexp(e, context, methods) for e in exp[1]]
   321     ctmpl = [compileexp(e, context, methods) for e in exp[1:]]
   285     if len(ctmpl) == 1:
       
   286         return ctmpl[0]  # fast path for string with no template fragment
       
   287     return (runtemplate, ctmpl)
   322     return (runtemplate, ctmpl)
   288 
   323 
   289 def runtemplate(context, mapping, template):
   324 def runtemplate(context, mapping, template):
   290     for func, data in template:
   325     for func, data in template:
   291         yield func(context, mapping, data)
   326         yield func(context, mapping, data)