From patchwork Fri Mar 4 14:14:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: formatter: allow json to handle more levels of depth From: Kostia Balytskyi X-Patchwork-Id: 13595 Message-Id: <0d64a8a89cb33fb67704.1457100864@dev1902.lla1.facebook.com> To: Date: Fri, 4 Mar 2016 06:14:24 -0800 # HG changeset patch # User Kostia Balytskyi # Date 1457099048 28800 # Fri Mar 04 05:44:08 2016 -0800 # Node ID 0d64a8a89cb33fb677047e3b9357389b52015294 # Parent 4f7a5e4f2daff0a65aa470d9f70365ad55aaa100 formatter: allow json to handle more levels of depth Only the topmost level gets pretty-printed, further ones are printed on the same line. I feel this is good since humans reading json output will have better separation between items. Sample output looks somewhat like this: ``` $ ./hg tf [ { "l1": {"l2": [1, 2]} } ] ``` achieved through the following formatter use ``` @command('tf', [] + formatteropts) def tf(ui, repo, **opts): obj = {'l1': {'l2': [1,2]}} fm = ui.formatter('tf', {'template': 'json'}) fm.startitem() fm.data(l1=obj['l1']) fm.end() ``` diff --git a/mercurial/formatter.py b/mercurial/formatter.py --- a/mercurial/formatter.py +++ b/mercurial/formatter.py @@ -109,8 +109,22 @@ class pickleformatter(baseformatter): baseformatter.end(self) self._ui.write(cPickle.dumps(self._data)) +def _getjsonbody(obj, sep=',', indent=''): + r = [] + first = True + for key, val in sorted(obj.items()): + if first: + first = False + else: + r.append(sep) + r.append(indent) + r.append('"%s": %s' % (key, _jsonifyobj(val))) + return ''.join(r) + def _jsonifyobj(v): - if isinstance(v, tuple): + if isinstance(v, dict): + return '{' + _getjsonbody(v) + '}' + elif isinstance(v, tuple) or isinstance(v, list): return '[' + ', '.join(_jsonifyobj(e) for e in v) + ']' elif v is None: return 'null' @@ -133,16 +147,8 @@ class jsonformatter(baseformatter): self._ui._first = False else: self._ui.write(",") - - self._ui.write("\n {\n") - first = True - for k, v in sorted(self._item.items()): - if first: - first = False - else: - self._ui.write(",\n") - self._ui.write(' "%s": %s' % (k, _jsonifyobj(v))) - self._ui.write("\n }") + body = _getjsonbody(self._item, sep=",\n", indent=' ') + self._ui.write("\n {\n" + body + "\n }") def end(self): baseformatter.end(self) self._ui.write("\n]\n")