I'm using sublime text for my HTML editing but I found that I needed to re-format my old code and sublime-text doesn't have that functionality built in.
Sublime-text does have rather nice python integration for easy plugin development so I did a little search, found this chap's website (http://www.bergspot.com/blog/2012/05/formatting-xml-in-sublime-text-2-xmllint/) and adapted his code, which makes use of xmllint (a unix tool but here's a windows version: http://code.google.com/p/xmllint/).
My version doesn't need the text to be selected (if text is selected, only that part will be beautified) and will shows a pop-up error message and also takes you to the error line.
Anyhow, here's the code:
import sublime, sublime_plugin, subprocess def find_lint_error_line(errString): startpos = errString.find("-:") endpos = -1 err_line = -1; if startpos != -1: startpos += 2 endpos = errString.find(":", startpos) if endpos != -1: numstr = errString[startpos:endpos] if numstr.isdigit(): err_line = int(numstr) return err_line class TidyXmlLintCommand(sublime_plugin.TextCommand): def run(self, edit): command = "XMLLINT_INDENT='\t' xmllint --format --encode utf-8 -" self.view.set_status('self', "") #xmllint.view.set_status('Hey there Tim', "Hey hey hey") # help from http://www.sublimetext.com/forum/viewtopic.php?f=2&p=12451 xmlRegion = sublime.Region(0, self.view.size()) p = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) sel_regions = self.view.sel() selection = sel_regions[0] sel_region_count = len(selection) if sel_region_count == 0: selection = xmlRegion result, err = p.communicate(self.view.substr(selection).encode('utf-8')) if err != "": self.view.set_status('xmllint', "xmllint: "+err) error_line = find_lint_error_line(err) #err.parse() #lines[] = parse("line {}", err) if error_line != -1: pt = self.view.text_point(error_line, 0) self.view.sel().clear() self.view.sel().add(sublime.Region(pt)) self.view.show_at_center(pt) #self.view.set_viewport_position((0, error_line * 16), True) else: sublime.message_dialog('could not find error line') sublime.message_dialog('xmllint, error at line: '+ str(error_line) + " \n" + 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('xmllint')
And if you're wondering how I did that nice syntax colouring on the python code, check this out:
SyntaxHighlighter