Mercurial > hg
changeset 28547:73d01cba5810
templater: expand list of parsed templates to template node
This patch eliminates a nested data structure other than the parsed tree.
('template', [(op, data), ..]) -> ('template', (op, data), ..)
New expanded tree can be processed by common parser functions. This change
will help implementing template aliases.
Because a (template ..) node should have at least one child node, an empty
template (template []) is mapped to (string ''). Also a trivial string
(template [(string ..)]) node is unwrapped to (string ..) at parsing phase,
instead of compiling phase.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 13 Feb 2016 23:20:47 +0900 |
parents | 1987ed32efca |
children | b7a31068cc80 |
files | mercurial/templater.py |
diffstat | 1 files changed, 39 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/templater.py Sun Feb 14 15:42:49 2016 +0900 +++ b/mercurial/templater.py Sat Feb 13 23:20:47 2016 +0900 @@ -177,11 +177,48 @@ raise error.ParseError(_("unterminated string"), start) return parsed, pos +def _unnesttemplatelist(tree): + """Expand list of templates to node tuple + + >>> def f(tree): + ... print prettyformat(_unnesttemplatelist(tree)) + >>> f(('template', [])) + ('string', '') + >>> f(('template', [('string', 'foo')])) + ('string', 'foo') + >>> f(('template', [('string', 'foo'), ('symbol', 'rev')])) + (template + ('string', 'foo') + ('symbol', 'rev')) + >>> f(('template', [('symbol', 'rev')])) # template(rev) -> str + (template + ('symbol', 'rev')) + >>> f(('template', [('template', [('string', 'foo')])])) + ('string', 'foo') + """ + if not isinstance(tree, tuple): + return tree + op = tree[0] + if op != 'template': + return (op,) + tuple(_unnesttemplatelist(x) for x in tree[1:]) + + assert len(tree) == 2 + xs = tuple(_unnesttemplatelist(x) for x in tree[1]) + if not xs: + return ('string', '') # empty template "" + elif len(xs) == 1 and xs[0][0] == 'string': + return xs[0] # fast path for string with no template fragment "x" + else: + return (op,) + xs + def parse(tmpl): """Parse template string into tree""" parsed, pos = _parsetemplate(tmpl, 0, len(tmpl)) assert pos == len(tmpl), 'unquoted template should be consumed' - return ('template', parsed) + return _unnesttemplatelist(('template', parsed)) + +def prettyformat(tree): + return parser.prettyformat(tree, ('integer', 'string', 'symbol')) def compiletemplate(tmpl, context): """Parse and compile template string to (func, data) pair""" @@ -281,9 +318,7 @@ return v def buildtemplate(exp, context): - ctmpl = [compileexp(e, context, methods) for e in exp[1]] - if len(ctmpl) == 1: - return ctmpl[0] # fast path for string with no template fragment + ctmpl = [compileexp(e, context, methods) for e in exp[1:]] return (runtemplate, ctmpl) def runtemplate(context, mapping, template):