From f5265b40a7056a661559821bf2ea098bc2e8bfc8 Mon Sep 17 00:00:00 2001 From: Nikolajus Date: Thu, 5 Jun 2014 09:58:00 +0200 Subject: [PATCH] Small code refactoring to re-use code blocks + readme slight change --- PrettyJson.py | 149 ++++++++++++++++++++++++++++---------------------- README.md | 12 ++-- 2 files changed, 89 insertions(+), 72 deletions(-) diff --git a/PrettyJson.py b/PrettyJson.py index 5bb5e31..295e13c 100644 --- a/PrettyJson.py +++ b/PrettyJson.py @@ -29,7 +29,9 @@ if sys.platform != 'win32' and '/usr/local/bin' not in os.environ['PATH']: try: # checking if ./jq tool is available so we can use it - s = subprocess.Popen(["jq", "--version"], stderr=subprocess.PIPE, stdout=subprocess.PIPE) + s = subprocess.Popen(["jq", "--version"], + stderr=subprocess.PIPE, + stdout=subprocess.PIPE) out, err = s.communicate() jq_version = err.decode("utf-8").replace("jq version ", "").strip() jq_exits = True @@ -42,9 +44,54 @@ except OSError: s = sublime.load_settings("Pretty JSON.sublime-settings") -class PrettyJsonCommand(sublime_plugin.TextCommand): +class PrettyJsonBaseCommand(sublime_plugin.TextCommand): json_error_matcher = re.compile(r"line (\d+) column (\d+) \(char (\d+)\)") + @staticmethod + def json_loads(selection): + return json.loads(selection, + object_pairs_hook=OrderedDict, + parse_float=decimal.Decimal) + + @staticmethod + def json_dumps(obj): + return json.dumps(obj, + indent=s.get("indent", 2), + ensure_ascii=s.get("ensure_ascii", False), + sort_keys=s.get("sort_keys", False), + separators=(',', ': '), + use_decimal=True) + + @staticmethod + def json_dumps_minified(obj): + return json.dumps(obj, + ensure_ascii=s.get("ensure_ascii", False), + sort_keys=s.get("sort_keys", False), + separators=(',', ':'), + use_decimal=True) + + def highlight_error(self, message): + m = self.json_error_matcher.search(message) + if m: + line = int(m.group(1)) - 1 + regions = [self.view.full_line(self.view.text_point(line, 0)), ] + self.view.add_regions('json_errors', regions, 'invalid', 'dot', + sublime.DRAW_OUTLINED) + self.view.set_status('json_errors', message) + + def show_exception(self): + exc = sys.exc_info()[1] + sublime.status_message(str(exc)) + self.highlight_error(str(exc)) + + def change_syntax(self): + """ Changes syntax to JSON if its in plain text """ + if "Plain text" in self.view.settings().get('syntax'): + self.view.set_syntax_file("Packages/JavaScript/JSON.tmLanguage") + + +class PrettyJsonCommand(PrettyJsonBaseCommand): + """ Pretty Print JSON """ def run(self, edit): self.view.erase_regions('json_errors') @@ -60,46 +107,20 @@ class PrettyJsonCommand(sublime_plugin.TextCommand): selection = region try: - obj = json.loads(self.view.substr(selection), - object_pairs_hook=OrderedDict, - parse_float=decimal.Decimal) - - self.view.replace(edit, selection, json.dumps(obj, - indent=s.get("indent", 2), - ensure_ascii=s.get("ensure_ascii", False), - sort_keys=s.get("sort_keys", False), - separators=(',', ': '), - use_decimal=True)) + obj = self.json_loads(self.view.substr(selection)) + self.view.replace(edit, selection, self.json_dumps(obj)) if selected_entire_file: self.change_syntax() except Exception: - exc = sys.exc_info()[1] - sublime.status_message(str(exc)) - self.highlight_error(str(exc)) - - def highlight_error(self, message): - m = self.json_error_matcher.search(message) - if m: - line = int(m.group(1)) - 1 - regions = [self.view.full_line(self.view.text_point(line, 0)), ] - self.view.add_regions('json_errors', regions, 'invalid', 'dot', sublime.DRAW_OUTLINED) - self.view.set_status('json_errors', message) - - def change_syntax(self): - """ Changes syntax to JSON if its in plain text """ - if "Plain text" in self.view.settings().get('syntax'): - self.view.set_syntax_file("Packages/JavaScript/JSON.tmLanguage") + self.show_exception() -class UnPrettyJsonCommand(PrettyJsonCommand): - """ - Compress/minify JSON - it makes json as one-liner - """ +class UnPrettyJsonCommand(PrettyJsonBaseCommand): + + """ Compress/minify JSON - it makes json as one-liner """ def run(self, edit): - """ overwriting base class run function to remove intent """ self.view.erase_regions('json_errors') for region in self.view.sel(): @@ -113,23 +134,14 @@ class UnPrettyJsonCommand(PrettyJsonCommand): selection = region try: - obj = json.loads(self.view.substr(selection), - object_pairs_hook=OrderedDict, - parse_float=decimal.Decimal) - - self.view.replace(edit, selection, json.dumps(obj, - ensure_ascii=s.get("ensure_ascii", False), - sort_keys=s.get("sort_keys", False), - separators=(',', ':'), - use_decimal=True)) + obj = self.json_loads(self.view.substr(selection)) + self.view.replace(edit, selection, self.json_dumps_minified(obj)) if selected_entire_file: self.change_syntax() except Exception: - exc = sys.exc_info()[1] - self.highlight_error(str(exc)) - sublime.status_message(str(exc)) + self.show_exception() class JqPrettyJson(sublime_plugin.WindowCommand): @@ -138,14 +150,13 @@ class JqPrettyJson(sublime_plugin.WindowCommand): """ def run(self): if jq_exits: - self.window.show_input_panel("Enter ./jq filter expression", ".", self.done, None, None) + self.window.show_input_panel("Enter ./jq filter expression", ".", + self.done, None, None) else: - sublime.status_message("./jq tool is not available on your system. http://stedolan.github.io/jq") + sublime.status_message('./jq tool is not available on your system. http://stedolan.github.io/jq') def get_content(self): - """ - returns content of active view or selected region - """ + """ returns content of active view or selected region """ view = self.window.active_view() selection = "" for region in view.sel(): @@ -158,7 +169,11 @@ class JqPrettyJson(sublime_plugin.WindowCommand): def done(self, query): try: - p = subprocess.Popen(["jq", query], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + p = subprocess.Popen(["jq", query], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.PIPE) + raw_json = self.get_content() if SUBLIME_MAJOR_VERSION < 3: @@ -176,7 +191,7 @@ class JqPrettyJson(sublime_plugin.WindowCommand): sublime.status_message(str(exc)) -class JsonToXml(PrettyJsonCommand): +class JsonToXml(PrettyJsonBaseCommand): """ converts Json to XML """ @@ -211,7 +226,8 @@ class JsonToXml(PrettyJsonCommand): xml_string += rtn - # for some reason python 2.6 shipped with ST2 does not have pyexpat + # for some reason python 2.6 shipped with ST2 + # does not have pyexpat if SUBLIME_MAJOR_VERSION >= 3: xml_string = minidom.parseString(xml_string).toprettyxml(encoding="UTF-8") @@ -224,11 +240,10 @@ class JsonToXml(PrettyJsonCommand): self.change_syntax() except Exception: - exc = sys.exc_info()[1] - self.highlight_error(str(exc)) - sublime.status_message(str(exc)) + self.show_exception() def indent_for_26(self, elem, level=0): + """ intent of ElementTree in case it's py26 without minidom/pyexpat """ i = "\n" + level*" " if len(elem): if not elem.text or not elem.text.strip(): @@ -243,22 +258,24 @@ class JsonToXml(PrettyJsonCommand): if level and (not elem.tail or not elem.tail.strip()): elem.tail = i - def traverse(self, el, ha): - if type(ha) is dict and ha.keys(): - for i in ha.keys(): + def traverse(self, element, json_dict): + """ recursive traverse through dict and build xml tree """ + if type(json_dict) is dict and json_dict.keys(): + for i in json_dict.keys(): e = ElementTree.Element(i) - el.append(self.traverse(e, ha[i])) - elif type(ha) is list: + element.append(self.traverse(e, json_dict[i])) + elif type(json_dict) is list: e_items = ElementTree.Element('items') - for i in ha: + for i in json_dict: e_items.append(self.traverse(ElementTree.Element('item'), i)) - el.append(e_items) + element.append(e_items) else: - el.set('value', str(ha)) + element.set('value', str(json_dict)) - return el + return element def change_syntax(self): + """ change syntax to xml """ self.view.set_syntax_file("Packages/XML/XML.tmLanguage") diff --git a/README.md b/README.md index edabfcd..210263d 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,22 @@ Prettify/Minify/Query JSON plugin for Sublime Text 2 & 3 ## Installation -Install this sublime text package via [Package Control](https://sublime.wbond.net) +Install this sublime text 2/3 package via [Package Control](https://sublime.wbond.net) -### or manual installation +### or manually install - `cd ` - `git clone https://github.com/dzhibas/SublimePrettyJson.git` ## Usage -To prettify JSON, make selection of json and press keys: +To prettify JSON, make selection of json (or else it will try to use full view buffer) and press keys: - Linux: ctrl+alt+j - Windows: ctrl+alt+j - OS X: cmd+ctrl+j -or through Command Palette Ctrl+Shift+P find "Pretty JSON: Format (Pretty Print) JSON" +or through Command Palette Ctrl+Shift+P find "Pretty JSON: Format (Pretty Print) JSON" (you can search for part of it like 'pretty format') If selection is empty and configuration entry **use_entire_file_if_no_selection** is true, tries to prettify whole file @@ -27,11 +27,11 @@ If JSON is not valid it will be displayed in status bar of Sublime Text ### Compress / Minify JSON -Using Command Palette Ctrl+Shift+P find "Pretty JSON: Minify (compress) JSON" this will make selection or full buffer as single line JSON which later you can use in command lines (curl/httpie) or somewhere else... +Using Command Palette Ctrl+Shift+P find "Pretty JSON: Minify (compress) JSON" (you can search for part of it like 'json minify') this will make selection or full buffer as single line JSON which later you can use in command lines (curl/httpie) or somewhere else... ### Convert JSON to XML -Using Command Palette Ctrl+Shift+P search fo "Pretty JSON: JSON 2 XML" this will convert your selected JSON of full buffer to XML and replace syntax and buffer to XML output +Using Command Palette Ctrl+Shift+P search fo "Pretty JSON: JSON 2 XML" (you can search for part of it like '2XML') this will convert your selected JSON of full buffer to XML and replace syntax and buffer to XML output ## ./jQ query/filter usage