Submitter | Yuya Nishihara |
---|---|
Date | Aug. 22, 2016, 2:44 p.m. |
Message ID | <22b19113435d7e2d0dd0.1471877074@mimosa> |
Download | mbox | patch |
Permalink | /patch/16380/ |
State | Accepted |
Headers | show |
Comments
> On Aug 22, 2016, at 07:44, Yuya Nishihara <yuya@tcha.org> wrote: > > # HG changeset patch > # User Yuya Nishihara <yuya@tcha.org> > # Date 1457866779 -32400 > # Sun Mar 13 19:59:39 2016 +0900 > # Node ID 22b19113435d7e2d0dd0eb8a515d131f2552b8ac > # Parent 194ac3287b843cad7bf3d21f4f17ac901b070dea > 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(): If there is always a begin and end call, should we be using a context manager? > > 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 > > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
On Mon, 22 Aug 2016 08:54:02 -0700, Gregory Szorc wrote: > > On Aug 22, 2016, at 07:44, Yuya Nishihara <yuya@tcha.org> wrote: > > # HG changeset patch > > # User Yuya Nishihara <yuya@tcha.org> > > # Date 1457866779 -32400 > > # Sun Mar 13 19:59:39 2016 +0900 > > # Node ID 22b19113435d7e2d0dd0eb8a515d131f2552b8ac > > # Parent 194ac3287b843cad7bf3d21f4f17ac901b070dea > > 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(): > > If there is always a begin and end call, should we be using a context manager? baseformatter could have __enter__ and __exit__, but I'm not tempted to use "with" statement there because doing that would add extra indent.
Patch
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