Tabs and snippets: when 4 + 8 still gives you 8

[Blogging while the ActiveState web site goes through a bit more reorganization...]

First, Komodo snippets let you prepare boilerplate snippets of code that you can quickly insert into programs while writing them. For example, if you're writing a JavaScript component, you can type 'namespace', press Ctrl-T (default binding), and end up with this:

/**
 * namespace «name» */

if(typeof(«name») == 'undefined') {
    var «name» = {};
}

(function() {
    «»
}).apply(«name»)

While fixing some bugs in this area, I stumbled on an old one reporting that snippets weren't working for people who prefer to map spaces to tabs in their buffers.  The snippet looked like this:

if (test1) {
....if (test2) {
[8SPTAB]do_something();
....}
}

and it was inserted in this context:

sub foo {
....<|>
}

This was the result:

sub foo {
....if (test1) {
[8SPTAB]if (test2) {
[8SPTAB]do_something();
[8SPTAB]}
....}
}

You might wonder why the "do_something" line didn't have an extra 4 spaces of indentation.

This is because the leading four spaces before the final tab don't add anything to it, and the white-space algorithm ignores them. You can try this with any tab-aware editor (such as Komodo), or even an old Remington, if you've got one. The leading spaces are redundant.

Some might say the solution would be to avoid using tabs altogether, but this is not always an option.  A simple all-purpose approach, good even if you plan on making your snippets available to others, is to never insert tabs in a snippet definition. Just use spaces, and let Komodo decide at insertion-time whether to map some of the leading spaces to tabs or not.