Merge pull request #408 from joepin/pretty-json-print-lines

Add logic to print diff between expected and actual JSON
diff --git a/pre_commit_hooks/pretty_format_json.py b/pre_commit_hooks/pretty_format_json.py
index e734ca8..cbc1b19 100644
--- a/pre_commit_hooks/pretty_format_json.py
+++ b/pre_commit_hooks/pretty_format_json.py
@@ -5,6 +5,7 @@
 import json
 import sys
 from collections import OrderedDict
+from difflib import unified_diff
 from typing import List
 from typing import Mapping
 from typing import Optional
@@ -55,6 +56,13 @@
     return s.split(',')
 
 
+def get_diff(source, target, file):  # type: (str, str, str) -> str
+    source_lines = source.splitlines(True)
+    target_lines = target.splitlines(True)
+    diff = unified_diff(source_lines, target_lines, fromfile=file, tofile=file)
+    return ''.join(diff)
+
+
 def main(argv=None):  # type: (Optional[Sequence[str]]) -> int
     parser = argparse.ArgumentParser()
     parser.add_argument(
@@ -96,7 +104,6 @@
         default=[],
         help='Ordered list of keys to keep at the top of JSON hashes',
     )
-
     parser.add_argument('filenames', nargs='*', help='Filenames to fix')
     args = parser.parse_args(argv)
 
@@ -113,10 +120,19 @@
             )
 
             if contents != pretty_contents:
-                print('File {} is not pretty-formatted'.format(json_file))
+                print(
+                    'File {} is not pretty-formatted'.format(json_file),
+                    file=sys.stderr,
+                )
+                sys.stderr.flush()
 
                 if args.autofix:
                     _autofix(json_file, pretty_contents)
+                else:
+                    print(
+                        get_diff(contents, pretty_contents, json_file),
+                        end='',
+                    )
 
                 status = 1
         except ValueError:
diff --git a/tests/pretty_format_json_test.py b/tests/pretty_format_json_test.py
index 3b7b9a2..6cfe772 100644
--- a/tests/pretty_format_json_test.py
+++ b/tests/pretty_format_json_test.py
@@ -1,3 +1,4 @@
+import os
 import shutil
 
 import pytest
@@ -105,3 +106,36 @@
 def test_badfile_main():
     ret = main([get_resource_path('ok_yaml.yaml')])
     assert ret == 1
+
+
+def test_diffing_output(capsys):
+    resource_path = get_resource_path('not_pretty_formatted_json.json')
+    expected_retval = 1
+    a = os.path.join('a', resource_path)
+    b = os.path.join('b', resource_path)
+    expected_out = '''\
+--- {}
++++ {}
+@@ -1,6 +1,9 @@
+ {{
+-    "foo":
+-    "bar",
+-        "alist": [2, 34, 234],
+-  "blah": null
++  "alist": [
++    2,
++    34,
++    234
++  ],
++  "blah": null,
++  "foo": "bar"
+ }}
+'''.format(a, b)
+    expected_err = 'File {} is not pretty-formatted\n'.format(resource_path)
+
+    actual_retval = main([resource_path])
+    actual_out, actual_err = capsys.readouterr()
+
+    assert actual_retval == expected_retval
+    assert actual_out == expected_out
+    assert actual_err == expected_err