Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make Sublime Text's "Improved Native for-loop" increment like a normal for-loop?

Premise

In Sublime Text 3, when writing JavaScript, typing "for" triggers the insertion of one of two possible code snippets:

for (... {... (Improved Native For-Loop)

for (var i = Things.length - 1; i >= 0; i--) {
    Things[i]
};

and

for (...) {...}

for (var i = 0; i < Things.length; i++) {
    Things[i]
};

Because Reasons

It has been known for a while that reverse iteration through for loops has better performance. But doing this means that every array-based action has to be done backwards, and it causes the code to become less readable. All of that hassle is for only minimal performance improvements in most cases.

Unfortunately, the "Improved Native For-Loop" is the first suggestion and can result in some annoying situations when accidentally chosen instead of the normal, readable loop that does not mess with typical conventions of array iteration.

Questions

  • So, how does one change the behavior of Sublime Text to not automatically add these weird for loops? I.e., how can I remove that snippet suggestion?
  • Is there a way to keep the slight performance gains while using a more traditional for loop structure? How can I use that as a Sublime Text snippet?
like image 688
Jonathan Voss Avatar asked Dec 25 '22 17:12

Jonathan Voss


1 Answers

Purging the Heretical Snippet

To remove the "Improved" for-loop snippet, create a folder named "JavaScript" inside your packages folder (Preferences>Browse Packages), and then create a file named "for-()-{}-(faster).sublime-snippet" within the JavaScript folder. Inside this file, place these contents:

<snippet>
    <content><![CDATA[$1]]></content>
</snippet>

Save and restart Sublime. This will disable the built-in bass-ackwards "Improved" loop snippet suggestion. At this point, only the normal for (...) {...} snippet will be active.

Concerning the Reverse For-loop

Decrementing does not provide any performance increases. The performance increase is due only to decreasing the number of times the array length has to be calculated: with for(i=0;i<Things.length;++i), Things.length is calculated for every iteration; with for(i=Things.length-1; i>=0; --i), Things.length is calculated only once. (See here.)

This mild performance increase can be gained by declaring a new variable to hold the value of Things.length with the following syntax:

for (var i = 0, l = Things.length; i < l; ++i) {}

Creating the Replacement Snippet

To replace the default, bundled "Improved" for-loop, we add the above syntax into the for-()-{}-(faster).sublime-snippet file. To make sure that both Things placeholders are selected, we use ${1:Things}. The new snippet file contents should look like this:

<snippet>
    <content><![CDATA[for (var i=0, il=${1:Things}.length; i<il; ++i) {
    ${1:Things}[i];
}]]>
    </content>
    <tabTrigger>for</tabTrigger>
    <scope>source.js</scope>
    <description>for (... {... Custom Improved For-Loop</description>
</snippet>

Be sure that the snippet is properly indented. Note that you must use tabs and not spaces for indenting. Save and restart Sublime.

If you want to create the a similar loop for another language, copy the contents to a new file and adapt the content and scope to that language. Happy coding.

Edit: Some More Advanced Snippets

These are some snippets I currently use, which are more advanced because they use multiple fields (hit tab to switch between fields). Also, there is a nested loop snippet accessed by typing forfor.

File name: for-()-{}-(faster).sublime-snippet

<snippet>
    <content><![CDATA[for (var ${1:i}=0, ${1:i}l=${2:Things}.length; ${1:i}<${1:i}l; ++${1:i}) {
    ${2:Things}[${1:i}];
}]]>
    </content>
    <tabTrigger>for</tabTrigger>
    <scope>source.js</scope>
    <description>for (... {... Custom Improved For-Loop</description>
</snippet>

File name: for-nested-js-(faster).sublime-snippet

<snippet>
    <content><![CDATA[for (var ${1:i}=0, ${1:i}l=${2:condition}; ${1:i}<${1:i}l; ++${1:i}) {
     for (var ${3:j}=0, ${3:j}l=${4:condition}; ${3:j}<${3:j}l; ++${3:j}) {
        ${5:statement};
     }
}]]>
    </content>
    <tabTrigger>forfor</tabTrigger>
    <scope>source.js</scope>
    <description>for(..){for... Faster Nested For-Loop</description>
</snippet>
like image 141
Jonathan Voss Avatar answered Jan 17 '23 14:01

Jonathan Voss