# HG changeset patch # User Yuya Nishihara # Date 2016-03-13 10:59:39 # Node ID 5b886289a1ca8fa6716dff4c7b7b80d691c06ca3 # Parent 18bac830eef3ebe6b1f9753db4bcf1b1cc8ec765 formatter: add fm.nested(field) to either write or build sub items We sometimes need to build nested items by formatter, but there was no convenient way other than building and putting them manually by fm.data(): exts = [] for n, v in extensions: fm.plain('%s %s\n' % (n, v)) exts.append({'name': n, 'ver': v}) fm.data(extensions=exts) This should work for simple cases, but doing this would make it harder to change the underlying data type for better templating support. So this patch provides fm.nested(field), which returns new nested formatter (or self if items aren't structured and just written to ui.) A nested formatter stores items which will later be rendered by the parent formatter. fn = fm.nested('extensions') for n, v in extensions: fn.startitem() fn.write('name ver', '%s %s\n', n, v) fn.end() Nested items are directly exported to a template for now: {extensions % "{name} {ver}\n"} There's no {extensions} nor {join(extensions, sep)} yet. I have a plan for them by extending fm.nested() API, but I want to revisit it after trying out this API in the real world. diff --git a/mercurial/formatter.py b/mercurial/formatter.py --- a/mercurial/formatter.py +++ b/mercurial/formatter.py @@ -91,11 +91,23 @@ class baseformatter(object): def plain(self, text, **opts): '''show raw text for non-templated mode''' pass + def nested(self, field): + '''sub formatter to store nested data in the specified field''' + self._item[field] = data = [] + return _nestedformatter(self._ui, self._converter, data) def end(self): '''end output for the formatter''' if self._item is not None: self._showitem() +class _nestedformatter(baseformatter): + '''build sub items and store them in the parent formatter''' + def __init__(self, ui, converter, data): + baseformatter.__init__(self, ui, topic='', opts={}, converter=converter) + self._data = data + def _showitem(self): + self._data.append(self._item) + def _iteritems(data): '''iterate key-value pairs in stable order''' if isinstance(data, dict): @@ -139,6 +151,9 @@ class plainformatter(baseformatter): self._ui.write(deftext % fielddata, **opts) def plain(self, text, **opts): self._ui.write(text, **opts) + def nested(self, field): + # nested data will be directly written to ui + return self def end(self): pass