Tidy HTML, PHP, C++ in Komodo February 12, 2010

Komodo Edit is my favourite editor for PHP, Python, HTML and CSS. It recognises Django Template Language, offers auto-completion for the Zend Framework, and displays the colour in a tooltip when you mouseover the CSS colour code. And it allows you to write macros in JavaScript or Python. It’s lovely.

Yesterday a colleague asked how to clean up some ugly HTML. I knew about “tidy”, the W3C’s HTML syntax checker and reformatter, but I was sure someone had done something similar for Komodo.

And they have. The nicest seems to be a macro written by Michael Cartmell at the Komodo Forum over here. I followed the thread, which contributed several good ideas, like tidying just a selection, and how to add support for other languages like C, C# and PHP. Credit goes to all who added code: hefebia, jeffg, jonathaneunice, oozypal, toddw, and especially michael.cartmell; and all who participated in the thread to iron out issues and show appreciation: davegaramond, ericp, Florent V., GroessterNehmer, keanzu, unixguy, wendymcf, znmeb.

I collated all the suggestions, and I’ve put them below. Here is how to create the macro.

First, install the software that the macro uses to tidy code.

In Debian, Ubuntu, Mint, etc. that’ll be:


$ sudo apt-get install astyle # For C, C++, C# and Java
$ sudo apt-get install perltidy # For Perl
$ sudo apt-get install tidy # For HTML, XML, XSLT, XUL
$ sudo apt-get install csstidy # For CSS
$ sudo apt-get install php-pear # For PHP ...
$ sudo pear install channel://pear.php.net/php_beautifier-0.1.14

Then in Komodo …

Show the Toolbox if it isn’t showing already. To do that, click View | Tabs & Sidebars and make sure Toolbox is checked.

In Toolbox, click on the Add Item To Toolbox icon. Choose New Macro…

Give your new macro a name. I called mine “Tidy”.

Confirm that the language is set to JavaScript.

Then copy and paste the following:

komodo.assertMacroVersion(2);
if (komodo.view.scintilla) { komodo.view.scintilla.focus(); } // bug 67103

var formatter;
var language = komodo.document.language;
var cannot_tidy_selection = false;
switch (language) {
    case 'C':
        formatter = 'astyle --style=linux';
        break;
    case 'C++':
        formatter = 'astyle --style=kr';
        break;
    case 'C#':
        formatter = 'astyle --style=ansi';
        break;
    case 'HTML':
        cannot_tidy_selection = true;
        formatter = 'tidy -q -utf8 -asxhtml -i -w 80';
        break;
    case 'CSS':
        formatter = 'csstidy - --preserve_css=true --lowercase_s=true --case_properties=true --sort_properties=true --template=low --remove_bslash=false';
        break;
    case 'Java':
        formatter = 'astyle --style=java';
        break;
    case 'Perl':
        formatter = 'perltidy';
        break;
    case 'PHP':
        formatter = 'php_beautifier -s4 -l"Pear(newline_class=false,newline_function=false)"';
        break;
    case 'XLST':
    case 'XML':
    case 'XUL':
        cannot_tidy_selection = true;
        formatter = 'tidy -q -utf8 -xml -i -w 80';
        break;
    default:
        alert("I don't know how to tidy " + language);
        exit(1);
}

//save current cursor position
var currentPos = komodo.editor.currentPos;

try {
    // Save the file.  After the operation you can check what changes where made by
    // File -> Show Unsaved Changes
    komodo.doCommand('cmd_save');

    // Group operations into a single undo
    komodo.editor.beginUndoAction();

    // Select entire buffer & pipe it into formatter.
    //komodo.doCommand('cmd_selectAll');
    //Run_RunEncodedCommand(window, formatter + " {'insertOutput': True, 'operateOnSelection': True}");

    //var text_not_selected = komodo.editor.selText == "";
    var text_not_selected = cannot_tidy_selection
                     || komodo.editor.selText == "";
    if (text_not_selected) {
        komodo.doCommand('cmd_selectAll');
    }
    Run_RunEncodedCommand(window, formatter + " {'insertOutput': True, 'operateOnSelection': True}");

    if (text_not_selected) {
        komodo.editor.gotoPos(currentPos);
    }

     // Restore cursor.  It will be close to the where it started depending on how the text was modified.
     komodo.editor.gotoPos(currentPos);

    // On windows, when the output of a command is inserted into an edit buffer it has unix line ends.
    komodo.doCommand('cmd_cleanLineEndings');

} catch (e) {
    alert(e);

} finally {
    // Must end undo action or may corrupt edit buffer
    komodo.editor.endUndoAction();
}

(I’ve left some of the original code commented out, so you can see where the later changes have been made. I’ve also added the -utf8 parameter to tidy as suggested at the end of the thread. And of course, if you don’t like my choice of styles, modify accordingly. The man pages for tidy and astyle are very helpful. You might also want to check Wikipedia to see the differences in indent styles.)

Click OK. Your new macro will appear in your toolbox.

Now all that remains is to open some messy code, and double-click the macro. Whoohoo!

Leave a Reply