[PATCH] formatter: allow json to handle more levels of depth
Kostia Balytskyi
ikostia at fb.com
Fri Mar 4 14:14:24 UTC 2016
# HG changeset patch
# User Kostia Balytskyi <ikostia at fb.com>
# 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")
More information about the Mercurial-devel
mailing list