Suppose how nice it would be to use #region directive when writing javascript code.
Javascript is becoming more and more complicated, and it is hard to scroll up and down every time we want to find needed function name and see what parameters it accepts.
I was so tired with this scrolling that started to search some alternative small IDE-s or highlighting text editors which would allow me to use collapsible regions in js files, but in this case I would lose javascript intellisense in VS 2008. I even thought about creating my own text editor plug-in for VS, but again - what about intellisense.
Earlier or later, I found one nice
solution to the problem on Microsoft forums. Yes - it's so simple. The solution uses simple macros which parses current document and creates collapsible regions for
//#region
//#endregion
pairs.
So simple :)
Thanks to the author!
And because I don't not find it to be easily detectable in the internet, I decided to blog this.
Just do the following steps to support //#region directive:
1) Open Macro explorer:
2) Create new macro:
3) Name it "OutlineRegions":
4) Click "Edit" macro and paste the following VB code into it:
Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports System.Collections
Public Module JsMacros
Sub OutlineRegions()
Dim selection As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
Const REGION_START As String = "//#region"
Const REGION_END As String = "//#endregion"
selection.SelectAll()
Dim text As String = selection.Text
selection.StartOfDocument(True)
Dim startIndex As Integer
Dim endIndex As Integer
Dim lastIndex As Integer = 0
Dim startRegions As Stack = New Stack()
Do
startIndex = text.IndexOf(REGION_START, lastIndex)
endIndex = text.IndexOf(REGION_END, lastIndex)
If startIndex = -1 AndAlso endIndex = -1 Then
Exit Do
End If
If startIndex <> -1 AndAlso startIndex < endIndex Then
startRegions.Push(startIndex)
lastIndex = startIndex + 1
Else
' Outline region ...
selection.MoveToLineAndOffset(CalcLineNumber(text, CInt(startRegions.Pop())), 1)
selection.MoveToLineAndOffset(CalcLineNumber(text, endIndex) + 1, 1, True)
selection.OutlineSection()
lastIndex = endIndex + 1
End If
Loop
selection.StartOfDocument()
End Sub
Private Function CalcLineNumber(ByVal text As String, ByVal index As Integer)
Dim lineNumber As Integer = 1
Dim i As Integer = 0
While i < index
If text.Chars(i) = vbCr Then
lineNumber += 1
i += 1
End If
i += 1
End While
Return lineNumber
End Function
End Module
5) Save the macro and close the editor.
6) Now let's assign shortcut to the macro. Go to Tools->Options->Environment->Keyboard and search for your macro in "show commands containing" textbox:
7) now in textbox under the "Press shortcut keys" you can enter the desired shortcut. I use Ctrl+M+E. I don't know why - I just entered it first time and use it now :)
That's it, now if you write the following javascript code:
/// <reference name="MicrosoftAjax.debug.js" />
/// <reference name="MicrosoftAjaxTimer.debug.js" />
/// <reference name="MicrosoftAjaxWebForms.debug.js" />
// KWB.BaseWizard class constructor
//#region
Type.registerNamespace("KWB");
KWB.BaseWizard = function(field) {
// call base constructor
KWB.BaseWizard.initializeBase(this);
this._state = null;
}
//#endregion
// KWB.BaseWizard Class Body
//#region
KWB.BaseWizard.prototype = {
// Sys.Component Overrides
//#region
dispose : function () {
this._state = null;
this._stateField = null;
this.lastClicked = null;
Sys.Application.remove_load(this.appLoad);
KWB.BaseWizard.callBaseMethod(this, 'dispose');
},
initialize : function() {
KWB.BaseWizard.callBaseMethod(this, 'initialize');
},
//#endregion
// Properties
//#region
get_state : function() {
return this._state;
},
set_state : function(value) {
this._state = value;
},
//#endregion
// Methods
//#region
getNext : function(current) {
/// <summary>
/// Override. Called when 'next' is called. Determines next frame to display
/// </summary>
/// <param name="current">current SelectedIndex</param>
return current + 1;
},
getPrevious : function(current) {
/// <summary>
/// Override. Called when 'previous' is called. Determines previous frame to display
/// </summary>
/// <param name="current">current SelectedIndex</param>
return current - 1;
},
finish : function() {
/// <summary>
/// Override. Called when 'finish' is pressed
/// </summary>
return true;
},
//#endregion
// Event handlers
//#region
nextClick : function() {
//TODO: add contents later
}
//#endregion
};
KWB.BaseWizard.registerClass('KWB.BaseWizard', Sys.Component);
//#endregion
// WizardStepType enumeration
//#region
KWB.WSType = function(){};
KWB.WSType.prototype =
{
Server : 1,
Client : 2,
Service : 4
}
KWB.WSType.registerEnum("KWB.WSType", false);
//#endregion
if(typeof(Sys) !== "undefined")Sys.Application.notifyScriptLoaded();
Now click Ctrl+M+E and you will see:
Veeery handy !