templater: provide loop counter as "index" keyword
authorYuya Nishihara <yuya@tcha.org>
Fri, 22 Apr 2016 21:46:33 +0900
changeset 31807 e6eb86b154c5
parent 31806 8f203b491bb5
child 31808 ca3b4a2b7e54
templater: provide loop counter as "index" keyword This was originally written for JSON templating where we would have to be careful to not add extra comma, but seems generally useful. Inner loop started by % operator has its own counter.
mercurial/cmdutil.py
mercurial/formatter.py
mercurial/templatekw.py
mercurial/templater.py
tests/test-command-template.t
--- a/mercurial/cmdutil.py	Fri Apr 22 21:45:06 2016 +0900
+++ b/mercurial/cmdutil.py	Fri Apr 22 21:46:33 2016 +0900
@@ -8,6 +8,7 @@
 from __future__ import absolute_import
 
 import errno
+import itertools
 import os
 import re
 import tempfile
@@ -1452,6 +1453,7 @@
             self.t = formatter.maketemplater(ui, 'changeset', tmpl,
                                              cache=defaulttempl)
 
+        self._counter = itertools.count()
         self.cache = {}
 
         # find correct templates for current mode
@@ -1490,6 +1492,7 @@
         props['ctx'] = ctx
         props['repo'] = self.repo
         props['ui'] = self.repo.ui
+        props['index'] = next(self._counter)
         props['revcache'] = {'copies': copies}
         props['cache'] = self.cache
 
--- a/mercurial/formatter.py	Fri Apr 22 21:45:06 2016 +0900
+++ b/mercurial/formatter.py	Fri Apr 22 21:46:33 2016 +0900
@@ -103,6 +103,7 @@
 
 from __future__ import absolute_import
 
+import itertools
 import os
 
 from .i18n import _
@@ -338,6 +339,7 @@
         self._topic = topic
         self._t = gettemplater(ui, topic, opts.get('template', ''),
                                cache=templatekw.defaulttempl)
+        self._counter = itertools.count()
         self._cache = {}  # for templatekw/funcs to store reusable data
     def context(self, **ctxs):
         '''insert context objects to be used to render template keywords'''
@@ -350,6 +352,7 @@
         props = {}
         if 'ctx' in self._item:
             props.update(templatekw.keywords)
+        props['index'] = next(self._counter)
         # explicitly-defined fields precede templatekw
         props.update(self._item)
         if 'ctx' in self._item:
--- a/mercurial/templatekw.py	Fri Apr 22 21:45:06 2016 +0900
+++ b/mercurial/templatekw.py	Fri Apr 22 21:46:33 2016 +0900
@@ -7,6 +7,7 @@
 
 from __future__ import absolute_import
 
+from .i18n import _
 from .node import hex, nullid
 from . import (
     encoding,
@@ -422,6 +423,12 @@
     else:
         return 'o'
 
+@templatekeyword('index')
+def showindex(**args):
+    """Integer. The current iteration of the loop. (0 indexed)"""
+    # just hosts documentation; should be overridden by template mapping
+    raise error.Abort(_("can't use index in this context"))
+
 @templatekeyword('latesttag')
 def showlatesttag(**args):
     """List of strings. The global tags on the most recent globally
--- a/mercurial/templater.py	Fri Apr 22 21:45:06 2016 +0900
+++ b/mercurial/templater.py	Fri Apr 22 21:46:33 2016 +0900
@@ -411,8 +411,9 @@
             else:
                 raise error.ParseError(_("%r is not iterable") % d)
 
-    for v in diter:
+    for i, v in enumerate(diter):
         lm = mapping.copy()
+        lm['index'] = i
         if isinstance(v, dict):
             lm.update(v)
             lm['originalnode'] = mapping.get('node')
--- a/tests/test-command-template.t	Fri Apr 22 21:45:06 2016 +0900
+++ b/tests/test-command-template.t	Fri Apr 22 21:46:33 2016 +0900
@@ -2683,6 +2683,16 @@
   $ hg log -l 1 --template '{if(author, author)|user}\n'
   test
 
+Test index keyword:
+
+  $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n'
+  10 0:a 1:b 2:fifth 3:fourth 4:third
+  11 0:a
+
+  $ hg branches -T '{index} {branch}\n'
+  0 default
+  1 foo
+
 Test diff function:
 
   $ hg diff -c 8