templater: add debugtemplate command
This is useful for debugging template parsing. Several tests are ported to
this command.
--- a/mercurial/commands.py Sat Feb 13 23:20:47 2016 +0900
+++ b/mercurial/commands.py Sun Feb 14 01:06:12 2016 +0900
@@ -68,6 +68,7 @@
sshserver,
streamclone,
templatekw,
+ templater,
treediscovery,
ui as uimod,
util,
@@ -2757,7 +2758,6 @@
fm.condwrite(err, 'extensionserror', " %s\n", err)
# templates
- from . import templater
p = templater.templatepaths()
fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
fm.condwrite(not p, '', _(" no template directories found\n"))
@@ -3592,6 +3592,54 @@
ui.write(node2str(node))
ui.write('\n')
+@command('debugtemplate',
+ [('r', 'rev', [], _('apply template on changesets'), _('REV')),
+ ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
+ _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
+ optionalrepo=True)
+def debugtemplate(ui, repo, tmpl, **opts):
+ """parse and apply a template
+
+ If -r/--rev is given, the template is processed as a log template and
+ applied to the given changesets. Otherwise, it is processed as a generic
+ template.
+
+ Use --verbose to print the parsed tree.
+ """
+ revs = None
+ if opts['rev']:
+ if repo is None:
+ raise error.RepoError(_('there is no Mercurial repository here '
+ '(.hg not found)'))
+ revs = scmutil.revrange(repo, opts['rev'])
+
+ props = {}
+ for d in opts['define']:
+ try:
+ k, v = (e.strip() for e in d.split('=', 1))
+ if not k:
+ raise ValueError
+ props[k] = v
+ except ValueError:
+ raise error.Abort(_('malformed keyword definition: %s') % d)
+
+ if ui.verbose:
+ tree = templater.parse(tmpl)
+ ui.note(templater.prettyformat(tree), '\n')
+
+ mapfile = None
+ if revs is None:
+ k = 'debugtemplate'
+ t = templater.templater(mapfile)
+ t.cache[k] = tmpl
+ ui.write(templater.stringify(t(k, **props)))
+ else:
+ displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
+ mapfile, buffered=False)
+ for r in revs:
+ displayer.show(repo[r], **props)
+ displayer.close()
+
@command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
def debugwalk(ui, repo, *pats, **opts):
"""show how files match on given patterns"""
--- a/tests/test-command-template.t Sat Feb 13 23:20:47 2016 +0900
+++ b/tests/test-command-template.t Sun Feb 14 01:06:12 2016 +0900
@@ -2861,27 +2861,55 @@
Test integer literal:
- $ hg log -Ra -r0 -T '{(0)}\n'
+ $ hg debugtemplate -v '{(0)}\n'
+ (template
+ (group
+ ('integer', '0'))
+ ('string', '\n'))
0
- $ hg log -Ra -r0 -T '{(123)}\n'
+ $ hg debugtemplate -v '{(123)}\n'
+ (template
+ (group
+ ('integer', '123'))
+ ('string', '\n'))
123
- $ hg log -Ra -r0 -T '{(-4)}\n'
+ $ hg debugtemplate -v '{(-4)}\n'
+ (template
+ (group
+ ('integer', '-4'))
+ ('string', '\n'))
-4
- $ hg log -Ra -r0 -T '{(-)}\n'
+ $ hg debugtemplate '{(-)}\n'
hg: parse error at 2: integer literal without digits
[255]
- $ hg log -Ra -r0 -T '{(-a)}\n'
+ $ hg debugtemplate '{(-a)}\n'
hg: parse error at 2: integer literal without digits
[255]
top-level integer literal is interpreted as symbol (i.e. variable name):
- $ hg log -Ra -r0 -T '{1}\n'
-
- $ hg log -Ra -r0 -T '{if("t", "{1}")}\n'
-
- $ hg log -Ra -r0 -T '{1|stringify}\n'
-
+ $ hg debugtemplate -D 1=one -v '{1}\n'
+ (template
+ ('integer', '1')
+ ('string', '\n'))
+ one
+ $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
+ (template
+ (func
+ ('symbol', 'if')
+ (list
+ ('string', 't')
+ (template
+ ('integer', '1'))))
+ ('string', '\n'))
+ one
+ $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
+ (template
+ (|
+ ('integer', '1')
+ ('symbol', 'stringify'))
+ ('string', '\n'))
+ one
unless explicit symbol is expected:
@@ -2894,13 +2922,29 @@
Test string literal:
- $ hg log -Ra -r0 -T '{"string with no template fragment"}\n'
+ $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
+ (template
+ ('string', 'string with no template fragment')
+ ('string', '\n'))
string with no template fragment
- $ hg log -Ra -r0 -T '{"template: {rev}"}\n'
+ $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
+ (template
+ (template
+ ('string', 'template: ')
+ ('symbol', 'rev'))
+ ('string', '\n'))
template: 0
- $ hg log -Ra -r0 -T '{r"rawstring: {rev}"}\n'
+ $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
+ (template
+ ('string', 'rawstring: {rev}')
+ ('string', '\n'))
rawstring: {rev}
- $ hg log -Ra -r0 -T '{files % r"rawstring: {file}"}\n'
+ $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
+ (template
+ (%
+ ('symbol', 'files')
+ ('string', 'rawstring: {file}'))
+ ('string', '\n'))
rawstring: {file}
Test string escaping:
--- a/tests/test-completion.t Sat Feb 13 23:20:47 2016 +0900
+++ b/tests/test-completion.t Sun Feb 14 01:06:12 2016 +0900
@@ -108,6 +108,7 @@
debugsetparents
debugsub
debugsuccessorssets
+ debugtemplate
debugwalk
debugwireargs
@@ -272,6 +273,7 @@
debugsetparents:
debugsub: rev
debugsuccessorssets:
+ debugtemplate: rev, define
debugwalk: include, exclude
debugwireargs: three, four, five, ssh, remotecmd, insecure
files: rev, print0, include, exclude, template, subrepos
--- a/tests/test-help.t Sat Feb 13 23:20:47 2016 +0900
+++ b/tests/test-help.t Sun Feb 14 01:06:12 2016 +0900
@@ -861,6 +861,8 @@
debugsub (no help text available)
debugsuccessorssets
show set of successors for revision
+ debugtemplate
+ parse and apply a template
debugwalk show how files match on given patterns
debugwireargs
(no help text available)