Syntax Tricks: Region Blocks

One thing I really miss from Visual Studio is the ability to fold entire regions of code under a meaningful description. This allowed developers to hide code they weren’t particularly concerned with at a given moment. I work on several large projects, and the lack of regions has been driving me nuts, but I think I’ve stumbled on a clever way to organise JavaScript code…

Most IDEs and text editors support code folding. The detection algorithm for code folding usually comes down to “blocks” which are defined with curly braces: { … }. For example, a multi-line if statement requires a block to be defined:

[js]
if (true) {
doStuff();
doMoreStuff();
}
[/js]

Most editors will allow you to “fold” the if statement’s block here. However, it’s perfectly legal to define arbitrary blocks almost anywhere else in your code where a statement is typically valid:

[js]
var foo = 1;
{ // start block
doStuff();
} // end block
doMoreStuff();
[/js]

We can now “fold” the block and hide doStuff();

Finally, we’re now able to hide arbitrary pieces of code in JavaScript! However, we can go even further…

The grammar specifies that each block can be prefixed with an identifier. This is known as a “label.” Labels were originally designed to enable us to refer to a statement inside break/continue. For example:

[js]myLoop: for (;;) break myLoop;[/js]

I first came up with this technique when I needed to organise code for the JavaScript++ compiler. As you can see, this is extremely helpful when building larger applications:

region-blocks-2

This project is composed of thousands of lines of code (as evidenced by the screenshot). Being able to fold/unfold arbitrary sections of code is extremely helpful in this case. “case” statements do not require a block ({ … }) to be defined, but, since the syntax is still legal, it’s a clever way to organise code in large projects.

In order for the larger JavaScript community to easily reference this technique, I’m naming it “region blocks.”

The standard convention is:

[js]
// ### Region_Name ### //
{{
// Code goes here
}}
[/js]

The ### is used to improve readability so we can quickly identify region blocks and distinguish them from generic comments. To further increase readability, we use “double curlies.” This makes it very easy to distinguish the end of a region block from other curly braces that could be the end of a function declaration, if statement, etc. Here’s some pseudo-code with nested region blocks:

[js]
// ### Initialize ### //
{{
resetScore();

// ### Setup Player Object ### //
{{
function foo() {
if (true) {
player.hp = 100;
player.speed = 10;
}
}
}}

// ### Connect to server… ### //
{{
login();
doStuff();
doStuff2();
}}
}}
[/js]

I want to enforce a standard convention for consistency, but there are other ways to use region blocks if you’re curious:

[js]
/* ### REGION NAME ### */ {
// …
}

"You can also use strings…"; {
// … as long as you remember the semicolon after the string
}

SOME_CLEVER_LABEL: {
}
[/js]

I personally don’t like using the string technique as you’ve got to remember your semicolons and sometimes it’s necessary to escape. I don’t like using labels as we’re restricted to valid identifiers. (e.g. No spaces!) The multi-line comment works well if you want to place your curly brace on the same line and does not differ too much from the proposed single-line comment style. However, it’s my personal opinion that the single-line comment is easier to type. Practically, it doesn’t matter if you’re using the single-line comment style or multi-line comment style. For the sake of consistency, if you choose to adopt this technique, please choose one comment style and stick with it!

To further illustrate the usefulness of the “double curly”, sometimes you may be scrolling through large blocks of code, and the beginning of the block is not within view, and all you see are:

[js]
}

doStuff();
}
}}
}
[/js]

It should be very clear where the end of the region block is in the above code. You can further enhance this by adding a comment such as // ### END REGION_NAME ### //, but I’m not keen to standardise such a practise as it would be too verbose, and it’s a judgement call based on region size, screen resolution, nesting levels, and personal preference.

The best part is that all of this is valid ECMAScript 3 – the standard JavaScript is based on published back in December 1999. It will work fine in your code for the latest Firefox all the way back to your code for IE6 and other legacy browsers.