Patchwork [5,of,5] templater: add parsing and expansion rules to process "templatealias" section

login
register
mail settings
Submitter Yuya Nishihara
Date April 14, 2016, 3:42 p.m.
Message ID <08da136a18335f677751.1460648574@mimosa>
Download mbox | patch
Permalink /patch/14625/
State Accepted
Headers show

Comments

Yuya Nishihara - April 14, 2016, 3:42 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1459078316 -32400
#      Sun Mar 27 20:31:56 2016 +0900
# Node ID 08da136a18335f677751512883156d3f246bb3c7
# Parent  6e60bc44a476c227925491d6cf3ac1571016574e
templater: add parsing and expansion rules to process "templatealias" section

The debugtemplate command is updated to show expanded tree, but still the
template engine doesn't support alias expansion. That's why the test says
"parse error" for now.
Sean Farley - April 14, 2016, 6 p.m.
Yuya Nishihara <yuya@tcha.org> writes:

> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1459078316 -32400
> #      Sun Mar 27 20:31:56 2016 +0900
> # Node ID 08da136a18335f677751512883156d3f246bb3c7
> # Parent  6e60bc44a476c227925491d6cf3ac1571016574e
> templater: add parsing and expansion rules to process "templatealias" section
>
> The debugtemplate command is updated to show expanded tree, but still the
> template engine doesn't support alias expansion. That's why the test says
> "parse error" for now.

After going through this a few times, I really like it. Unifying the
engine implementation is noble and I don't see any problems from this
series.
Pierre-Yves David - April 15, 2016, 8:33 a.m.
On 04/14/2016 11:00 AM, Sean Farley wrote:
> Yuya Nishihara <yuya@tcha.org> writes:
>
>> # HG changeset patch
>> # User Yuya Nishihara <yuya@tcha.org>
>> # Date 1459078316 -32400
>> #      Sun Mar 27 20:31:56 2016 +0900
>> # Node ID 08da136a18335f677751512883156d3f246bb3c7
>> # Parent  6e60bc44a476c227925491d6cf3ac1571016574e
>> templater: add parsing and expansion rules to process "templatealias" section
>>
>> The debugtemplate command is updated to show expanded tree, but still the
>> template engine doesn't support alias expansion. That's why the test says
>> "parse error" for now.
> After going through this a few times, I really like it. Unifying the
> engine implementation is noble and I don't see any problems from this
> series.

This looks good to me to. Pushed, thanks.

Thanks also go to seam for double checking this complex code change.

Cheers,

Patch

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 "{'<foo@example.org>'|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 <<EOF >> .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