# HG changeset patch # User Yuya Nishihara # Date 1521120436 -32400 # Node ID 8bb3899a0f47d82bc6e9d246dbb070ede0600290 # Parent 75c13343cf381f0396f2c75350f319ac5bf00c03 formatter: make nested items somewhat readable in template output diff -r 75c13343cf38 -r 8bb3899a0f47 mercurial/commands.py --- a/mercurial/commands.py Sun Mar 18 23:36:52 2018 +0900 +++ b/mercurial/commands.py Thu Mar 15 22:27:16 2018 +0900 @@ -386,7 +386,7 @@ % ((pats and m.rel(abs)) or abs)) continue - fm = rootfm.nested('lines') + fm = rootfm.nested('lines', tmpl='{rev}: {line}') lines = fctx.annotate(follow=follow, skiprevs=skiprevs, diffopts=diffopts) if not lines: @@ -2506,7 +2506,7 @@ if not opts.get('text') and binary(): fm.plain(_(" Binary file matches")) else: - displaymatches(fm.nested('texts'), l) + displaymatches(fm.nested('texts', tmpl='{text}'), l) fm.plain(eol) found = True if opts.get('files_with_matches'): @@ -2848,7 +2848,7 @@ numoutput = ["%d" % p.rev() for p in parents] output.append("%s%s" % ('+'.join(numoutput), dirty)) - fn = fm.nested('parents') + fn = fm.nested('parents', tmpl='{rev}:{node|formatnode}', sep=' ') for p in parents: fn.startitem() fn.data(rev=p.rev()) @@ -5615,7 +5615,7 @@ names.append(name) vers.append(extensions.moduleversion(module) or None) isinternals.append(extensions.ismoduleinternal(module)) - fn = fm.nested("extensions") + fn = fm.nested("extensions", tmpl='{name}\n') if names: namefmt = " %%-%ds " % max(len(n) for n in names) places = [_("external"), _("internal")] diff -r 75c13343cf38 -r 8bb3899a0f47 mercurial/formatter.py --- a/mercurial/formatter.py Sun Mar 18 23:36:52 2018 +0900 +++ b/mercurial/formatter.py Thu Mar 15 22:27:16 2018 +0900 @@ -95,7 +95,7 @@ >>> def subrepos(ui, fm): ... fm.startitem() ... fm.write(b'reponame', b'[%s]\\n', b'baz') -... files(ui, fm.nested(b'files')) +... files(ui, fm.nested(b'files', tmpl=b'{reponame}')) ... fm.end() >>> show(subrepos) [baz] @@ -138,6 +138,10 @@ storecontext = False @staticmethod + def wrapnested(data, tmpl, sep): + '''wrap nested data by appropriate type''' + return data + @staticmethod def formatdate(date, fmt): '''convert date tuple to appropriate format''' return date @@ -210,9 +214,10 @@ def isplain(self): '''check for plain formatter usage''' return False - def nested(self, field): + def nested(self, field, tmpl=None, sep=''): '''sub formatter to store nested data in the specified field''' - self._item[field] = data = [] + data = [] + self._item[field] = self._converter.wrapnested(data, tmpl, sep) return _nestedformatter(self._ui, self._converter, data) def end(self): '''end output for the formatter''' @@ -243,6 +248,9 @@ storecontext = False @staticmethod + def wrapnested(data, tmpl, sep): + raise error.ProgrammingError('plainformatter should never be nested') + @staticmethod def formatdate(date, fmt): '''stringify date tuple in the given format''' return dateutil.datestr(date, fmt) @@ -290,7 +298,7 @@ self._write(text, **opts) def isplain(self): return True - def nested(self, field): + def nested(self, field, tmpl=None, sep=''): # nested data will be directly written to ui return self def end(self): @@ -350,6 +358,10 @@ storecontext = True @staticmethod + def wrapnested(data, tmpl, sep): + '''wrap nested data by templatable type''' + return templateutil.mappinglist(data, tmpl=tmpl, sep=sep) + @staticmethod def formatdate(date, fmt): '''return date tuple''' return date diff -r 75c13343cf38 -r 8bb3899a0f47 tests/test-annotate.t --- a/tests/test-annotate.t Sun Mar 18 23:36:52 2018 +0900 +++ b/tests/test-annotate.t Thu Mar 15 22:27:16 2018 +0900 @@ -90,6 +90,28 @@ > EOF $ hg ci -mb2 -d '2 0' +default output of '{lines}' should be readable + + $ hg annotate -T'{lines}' a + 0: a + 1: a + 1: a + $ hg annotate -T'{join(lines, "\n")}' a + 0: a + + 1: a + + 1: a + +several filters can be applied to '{lines}' + + $ hg annotate -T'{lines|stringify}' a + 0: a + 1: a + 1: a + $ hg annotate -T'{lines|count}\n' a + 3 + annotate multiple files (JSON) $ hg annotate -Tjson a b diff -r 75c13343cf38 -r 8bb3899a0f47 tests/test-extension.t --- a/tests/test-extension.t Sun Mar 18 23:36:52 2018 +0900 +++ b/tests/test-extension.t Thu Mar 15 22:27:16 2018 +0900 @@ -1407,6 +1407,11 @@ $ hg version -q --config extensions.throw=throw.py Mercurial Distributed SCM (version *) (glob) +Test template output: + + $ hg version --config extensions.strip= -T'{extensions}' + strip + Test JSON output of version: $ hg version -Tjson diff -r 75c13343cf38 -r 8bb3899a0f47 tests/test-grep.t --- a/tests/test-grep.t Sun Mar 18 23:36:52 2018 +0900 +++ b/tests/test-grep.t Thu Mar 15 22:27:16 2018 +0900 @@ -48,6 +48,11 @@ port:4:914fa752cdea:vaPORTight port:4:914fa752cdea:imPORT/exPORT + $ hg grep port -T '{file}:{rev}:{texts}\n' + port:4:export + port:4:vaportight + port:4:import/export + simple JSON (no "change" field) $ hg grep -Tjson port diff -r 75c13343cf38 -r 8bb3899a0f47 tests/test-identify.t --- a/tests/test-identify.t Sun Mar 18 23:36:52 2018 +0900 +++ b/tests/test-identify.t Thu Mar 15 22:27:16 2018 +0900 @@ -62,6 +62,8 @@ 2147483647 ffff $ hg id -T '{parents % "{rev} {node|shortest} {desc}\n"}' 0 cb9a a + $ hg id -T '{parents}\n' + 0:cb9a9f314b8b test nested template: '{tags}'/'{node}' constants shouldn't override the default keywords, but '{id}' persists because there's no default keyword