Mercurial > hg
changeset 29676:c3a9cd78b151
formatter: add function to convert list to appropriate format (issue5217)
Before, it wasn't possible for formatter to handle array structure other
than date tuple. We've discussed that at the last sprint, which ended we
would probably want to allow only templatable data structure, i.e. a list
of dicts:
data(tags=[{'tag': a}, {'tag': b}, ...])
Unfortunately, it turned out not working well with template functions:
"{ifcontains(a, tags, ...)}"
^^^^^^^^^^^^^^^^^^
"a in tags", where tags should be a plain list/set of tags
So the formatter must at least know if the type [{}] was constructed from
a plain list or was actually a list of dicts.
This patch introduces new explicit interface to convert an array structure
to an appropriate data type for the current formatter, which can be used
as follows:
fm.write('tags', _('tags: %s\n'), fm.formatlist(tags, name='tag'))
No separate fm.data() call should be necessary.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 10 Jul 2016 21:03:06 +0900 |
parents | 12f04946053c |
children | 69890b5dd32b |
files | mercurial/formatter.py |
diffstat | 1 files changed, 20 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/formatter.py Sun Jul 31 16:38:16 2016 +0900 +++ b/mercurial/formatter.py Sun Jul 10 21:03:06 2016 +0900 @@ -18,6 +18,7 @@ from . import ( encoding, error, + templatekw, templater, util, ) @@ -45,6 +46,10 @@ if self._item is not None: self._showitem() self._item = {} + @staticmethod + def formatlist(data, name, fmt='%s', sep=' '): + '''convert iterable to appropriate list format''' + return list(data) def data(self, **data): '''insert data into item that's not shown in default output''' self._item.update(data) @@ -78,6 +83,10 @@ return False def startitem(self): pass + @staticmethod + def formatlist(data, name, fmt='%s', sep=' '): + '''stringify iterable separated by sep''' + return sep.join(fmt % e for e in data) def data(self, **data): pass def write(self, fields, deftext, *fielddata, **opts): @@ -112,7 +121,7 @@ self._ui.write(pickle.dumps(self._data)) def _jsonifyobj(v): - if isinstance(v, tuple): + if isinstance(v, (list, tuple)): return '[' + ', '.join(_jsonifyobj(e) for e in v) + ']' elif v is None: return 'null' @@ -157,6 +166,16 @@ def _showitem(self): g = self._t(self._topic, ui=self._ui, **self._item) self._ui.write(templater.stringify(g)) + @staticmethod + def formatlist(data, name, fmt='%s', sep=' '): + '''build object that can be evaluated as either plain string or list''' + # name is mandatory argument for now, but it could be optional if + # we have default template keyword, e.g. {item} + data = list(data) + def f(): + yield plainformatter.formatlist(data, name, fmt, sep) + return templatekw._hybrid(f(), data, lambda x: {name: x}, + lambda d: fmt % d[name]) def lookuptemplate(ui, topic, tmpl): # looks like a literal template?