diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -3671,8 +3671,12 @@ def debugtemplate(ui, repo, tmpl, **opts raise error.Abort(_('malformed keyword definition: %s') % d) if ui.verbose: + aliases = ui.configitems('templatealias') tree = templater.parse(tmpl) ui.note(templater.prettyformat(tree), '\n') + newtree = templater.expandaliases(tree, aliases) + if newtree != tree: + ui.note("* expanded:\n", templater.prettyformat(newtree), '\n') mapfile = None if revs is None: diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -872,6 +872,25 @@ exprmethods = { methods = exprmethods.copy() methods["integer"] = exprmethods["symbol"] # '{1}' as variable +class _aliasrules(parser.basealiasrules): + """Parsing and expansion rule set of template aliases""" + _section = _('template alias') + _parse = staticmethod(_parseexpr) + + @staticmethod + def _trygetfunc(tree): + """Return (name, args) if tree is func(...) or ...|filter; otherwise + None""" + if tree[0] == 'func' and tree[1][0] == 'symbol': + return tree[1][1], getlist(tree[2]) + if tree[0] == '|' and tree[2][0] == 'symbol': + return tree[2][1], [tree[1]] + +def expandaliases(tree, aliases): + """Return new tree of aliases are expanded""" + aliasmap = _aliasrules.buildmap(aliases) + return _aliasrules.expand(aliasmap, tree) + # template engine stringify = templatefilters.stringify diff --git a/tests/test-command-template.t b/tests/test-command-template.t --- a/tests/test-command-template.t +++ b/tests/test-command-template.t @@ -3654,6 +3654,100 @@ json filter should escape HTML tags so t $ hg log -T "{''|json}\n" -R a -l1 "\u003cfoo@example.org\u003e" +Templater supports aliases of symbol and func() styles: + + $ hg clone -q a aliases + $ cd aliases + $ cat <> .hg/hgrc + > [templatealias] + > r = rev + > rn = "{r}:{node|short}" + > status(c, files) = files % "{c} {file}\n" + > utcdate(d) = localdate(d, "UTC") + > EOF + + $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n' + (template + ('symbol', 'rn') + ('string', ' ') + (| + (func + ('symbol', 'utcdate') + ('symbol', 'date')) + ('symbol', 'isodate')) + ('string', '\n')) + * expanded: + (template + (template + ('symbol', 'rev') + ('string', ':') + (| + ('symbol', 'node') + ('symbol', 'short'))) + ('string', ' ') + (| + (func + ('symbol', 'localdate') + (list + ('symbol', 'date') + ('string', 'UTC'))) + ('symbol', 'isodate')) + ('string', '\n')) + hg: parse error: unknown function 'utcdate' + [255] + + $ hg debugtemplate -vr0 '{status("A", file_adds)}' + (template + (func + ('symbol', 'status') + (list + ('string', 'A') + ('symbol', 'file_adds')))) + * expanded: + (template + (% + ('symbol', 'file_adds') + (template + ('string', 'A') + ('string', ' ') + ('symbol', 'file') + ('string', '\n')))) + hg: parse error: unknown function 'status' + [255] + +A unary function alias can be called as a filter: + + $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n' + (template + (| + (| + ('symbol', 'date') + ('symbol', 'utcdate')) + ('symbol', 'isodate')) + ('string', '\n')) + * expanded: + (template + (| + (func + ('symbol', 'localdate') + (list + ('symbol', 'date') + ('string', 'UTC'))) + ('symbol', 'isodate')) + ('string', '\n')) + hg: parse error: unknown function 'utcdate' + [255] + +Unparsable alias: + + $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}' + (template + ('symbol', 'bad')) + abort: failed to parse the definition of template alias "bad": at 2: not a prefix: end + [255] + + $ cd .. + Set up repository for non-ascii encoding tests: $ hg init nonascii