public
Last active

simple scripts to prettify your xml and json in sublime text 2

  • Download Gist
Default (Linux).sublime-keymap
JSON
1 2 3 4
[
{ "keys": ["ctrl+shift+x"], "command": "tidy_xml" },
{ "keys": ["ctrl+shift+j"], "command": "prettify_json" }
]
prettify_json.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import sublime, sublime_plugin, subprocess
 
class PrettifyJsonCommand(sublime_plugin.TextCommand):
def run(self, edit):
command = 'python -mjson.tool'
 
# help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451
p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
result, err = p.communicate(self.view.substr(self.view.sel()[0]).encode('utf-8'))
 
# gave up trying this approach: result always has '\n' strings in it that refuse to render
#result = json.dumps( self.view.substr(self.view.sel()[0]), indent=2)
 
# http://code.activestate.com/recipes/65211/ seems to say that Python "ruins" non-raw strings by
# actually placing '\','n' in the friggin string unless it's marked 'raw'? Is that true? Shouldn't a string be a string
# and the raw/not raw output be a function of the runtime? Why does "print" have some magic to reescape these strings and
# yet there are no other buffer objects that seem to do it (aka StringIO or BytesIO).
 
if result != "":
self.view.replace(edit, self.view.sel()[0], result.decode('utf-8'))
sublime.set_timeout(self.clear,0)
else:
self.view.set_status('tidyjson', "tidyjson: "+err)
sublime.set_timeout(self.clear,10000)
 
def clear(self):
self.view.erase_status('tidyjson')
tidy_xml.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
import sublime, sublime_plugin, subprocess
 
class TidyXmlCommand(sublime_plugin.TextCommand):
def run(self, edit):
command = 'tidy -xml -i -utf8 -w -q'
 
# help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451
p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
result, err = p.communicate(self.view.substr(self.view.sel()[0]).encode('utf-8'))
 
if err != "":
self.view.set_status('tidyxml', "tidyxml: "+err)
sublime.set_timeout(self.clear,10000)
else:
self.view.replace(edit, self.view.sel()[0], result.decode('utf-8'))
sublime.set_timeout(self.clear,0)
 
def clear(self):
self.view.erase_status('tidyxml')

XML and JSON Tidy for Sublime Text 2

Have you ever had a chunk of xml or json output that you were trying to format in Sublime Text 2? Well here are some easy plugin macros that will take any text selection and replace it inline with formatted output from tidy or prettify_json.rb. Note: some setup required to get these tools running -- I got them running on my system without too much trouble, you may have to tweak.

To use with Sublime Text 2, copy these files into ~/.config/sublime-text-2/Packages/User. If you already have a keymap, edit these values or your own into it. Then use CTRL+SHIFT+X to tidy xml selections and CTRL+SHIFT+J to tidy JSON selections.

On Mac, copy into ~/Library/Application Support/Sublime Text 2/Packages/User.

Ah, I have another gist for perforce that does this via windows update. Let me see if I can put that code in here...

Ok, updated both of these scripts. Switched the json prettifier to python -- which should be in scope automatically if you have sublime... I don't know, this works on my mac. I tried to internalize it completely, but Python has some whacked out notion of strings that I don't understand. Feel free to tinker and let me know if you find a solution for the json object.

Worked for me too. Great job.

Works great - thanks!

Super Cool. Helped me a lot. Thanx :)

Is is expected that you have to select the text you want to format?

Yep, select the text and then it replaces it with formatted text. At work, I get XML service responses with embedded JSON and it is a complete mess to look through that much data when any part of it can be the cause of an error, so this is quite handy because I can select all and format xml and then select just the inner CDATA JSON and format that... sooo much easier.

Thanks for the reply, I finally ended up using JsFormat

Cool, didn't know about that.

Great tools. Thanks for sharing. Anyway to make it parse and format the code in the current file without having to select the text ?

I'm getting an error "tidyxml: tidy is not recognized as an internal or external command" after following the instructions.

These were my steps:
1 - Copied the scripts to the directory (I noticed they were automagically compiled as soon as I copied them and a .pyc was created for both)
2 - Added the suggested key bindings through Preferences > Key Bindings - User
3 - Restarted Sublime
4 - Created a new document with well-formed XML
5 - Tried CTRL+SHIFT+X, then I saw the error on the bottom status pane

Machine: PC
Script directory: C:\Users\ozmosis\AppData\Roaming\Sublime Text 2\Packages\User

What did I miss?

Ah, @ozzieperez, you're running on windows.... you'll need HTMLTidy installed to use this (I forgot about windows -- it comes on most macs and linux distros) -- You can download a windows binary here: http://tidy.sourceforge.net/#binaries Don't forget to add the install location to your path. Try it out and see if that works.

An alternate would be the pure python plugin JsFormat as pointed out by @danielimb above.

@samo9789, good idea! I've been swamped so haven't had a chance to tinker with this again, but I think it wouldn't be hard to do. I'll take a look this weekend if I can.

@coldnebo Great, thanks.

Thanks @coldnebo. I downloaded the executable from from http://www.paehl.com/open_source/?download=tidy.zip , added the Path to it to in my system variables, and it's all good now. Thanks again!

Thanks a lot for the script, @coldnebo.

For some reason I am getting extra carriage returns... Not sure if this is linked to the '\n' issue you talked about in the comments.

When I try to format the following

{"test":"hello world"}

I get

{

    "test": "hello world"

}

After the opening curly brace and before the closing curly brace I get 0d 0d 0a which is carriage return, carriage return, new line.

Has anybody been able to solve this minor problem?

I'm using Windows XP, Python 2.7.2 and Sublime Text 2 build 2181.

Not sure, I've seen copy/paste issues between mac/linux and windows that are similar... maybe some setting in sublime to control line endings?

Forgive the newbie question, but how can I run this from the Command Palette instead of from a key binding?

@dserodio, you know, that's a really great question and I don't know the answer either. There's got to be a way to add this to the list of commands... I'll take a look when I get some time.

@coldnebo I asked on the Sublime forums and got a very nice reply. Basically:

To add a command to the Command Palette you need define it in a .sublime-commands file.

The linked forum post contains links to the documentation and a one-liner to add this command to the Command Pallete.

ah, figured it was something simple. I love Sublime. Thanks for posting this!

I've got the same CR CR LF problem. I haven't been able to figure it out. A shame.

I ended up replacing all \r\n with \n. I'm not sure if this is a windows only fix. I'll have to test on my macbook later tonight.

self.view.replace(edit, self.view.sel()[0], result.decode('utf-8').replace('\r\n', '\n'))

I also made one more tweak by replacing self.view.sel()[0] with sublime.Region(0, self.view.size()). So now I don't have to select anything and it will format my whole document. I could make this smarter so it only formats text selections when the region is not empty, but 99.9% of the time I just want to format the whole document anyways.

Thanks for the snippets mate.

jtmille3's update gist sorted out carriage return problems for me on windows.. but thanks for all of this.. also i got confused and added HTMLTidy through Sublime Text 2 package control - no no no.. yes the windows binary were the right thing to download from http://tidy.sourceforge.net/#binaries and then where i put the exe file i added that location to the environment PATH variable by right clicking computer -> properties -> advanced system settings -> environment variables -> system variables -> PATH -> edit -> and adding the path to my exe in there.. on windows 7 x64.. thanks again for this it's great to have nice xml

jtmille3's update gist sorted out carriage return problems for me on windows.. but thanks for all of this.. also i got confused and added HTMLTidy through Sublime Text 2 package control - no no no.. yes the windows binary were the right thing to download from http://tidy.sourceforge.net/#binaries and then where i put the exe file i added that location to the environment PATH variable by right clicking computer -> properties -> advanced system settings -> environment variables -> system variables -> PATH -> edit -> and adding the path to my exe in there.. on windows 7 x64.. thanks again for this it's great to have nice xml

jtmille3's update gist sorted out carriage return problems for me on windows.. but thanks for all of this.. also i got confused and added HTMLTidy through Sublime Text 2 package control - no no no.. yes the windows binary were the right thing to download and then where i put the exe file i added that location to the environment PATH variable by right clicking computer -> properties -> advanced system settings -> environment variables -> system variables -> PATH -> edit -> and adding the path to my exe in there.. on windows 7 x64.. thanks again for this it's great to have nice xml

thanks for this.. jtmille3's version sorted the carriage return problems for on windows 7 x64.. nice to have pretty xml again.. thanks!

Really appreciate the time you put into this, man. Thanks.

Thank You! Works great on Windows with http://tidy.sourceforge.net/#binaries as specified.

Woot! Works great so far...thanks!

Tidy actually edits CDATA value and then wrongly handles what is after it.
e.g., The following "one-lined" XML. 'y = 3;' has got 2 tabulations before and one LF after. 'x * y = ?' has got 2 tabulations.

<?xml version="1.0" encoding="utf-8"?>
<report><bob>aze<![CDATA[ x = 2;
        y = 3;
        x * y = ?]]><alice>qsd</alice></bob></report>

After running tidy_xml.py, the output is the following

<?xml version="1.0" encoding="utf-8"?>
<report>
  <bob>aze
<![CDATA[ x = 2;
                y = 3;
                x * y = ?]]>
<alice>qsd</alice></bob>
</report>

The CDATA value is not considered as a whole. The tabulations before 'y = 3;' and 'x * y = ?' are replaced with spaces from indentation.

xmllint handles that a little better, the CDATA value remains untouched, but still fail after that.

<?xml version="1.0" encoding="utf-8"?>
<report>
    <bob>aze<![CDATA[ x = 2;
        y = 3;
        x * y = ?]]><alice>qsd</alice></bob>
</report>

thanks! help me a lot.

This is brilliant - thanks!

Thanks a lot... working perfectly fine.

I'm getting 'broken pipe' error. Any ideas?

Traceback (most recent call last):
  File ".\sublime_plugin.py", line 362, in run_
  File ".\tidy_xml.py", line 10, in run
  File ".\subprocess.py", line 701, in communicate
  File ".\subprocess.py", line 911, in _communicate
IOError: [Errno 32] Broken pipe

pretty_json is working, but tiny_xml isn't and there is no response when i use the key "ctrl+shift+x". i don't know why.

i know, there isn't libtidy. The tool is very good and thank you very much!

Changed Tidy xml to work with Sublime Text 3 Beta 3047
Added some error output to the console

https://gist.github.com/skat-delayed/5923717

nice, work perfect to me.

Thx!

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.