diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -8,6 +8,7 @@ from __future__ import absolute_import import errno +import itertools import os import re import tempfile @@ -1452,6 +1453,7 @@ class changeset_templater(changeset_prin 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 @@ class changeset_templater(changeset_prin 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 diff --git a/mercurial/formatter.py b/mercurial/formatter.py --- a/mercurial/formatter.py +++ b/mercurial/formatter.py @@ -103,6 +103,7 @@ baz: foo, bar from __future__ import absolute_import +import itertools import os from .i18n import _ @@ -338,6 +339,7 @@ class templateformatter(baseformatter): 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 @@ class templateformatter(baseformatter): 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: diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -7,6 +7,7 @@ from __future__ import absolute_import +from .i18n import _ from .node import hex, nullid from . import ( encoding, @@ -422,6 +423,12 @@ def showgraphnode(repo, ctx, **args): 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 diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -411,8 +411,9 @@ def runmap(context, mapping, data): 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') 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 @@ -2683,6 +2683,16 @@ Pass generator object created by templat $ 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