Better Keyboard Support for #region ... #endregion

Of all the elements that can be collapsed in the VS.Net editor (namespaces, classes, methods, comments, ...), only regions are of actual importance for my everyday work. Here are three macros that are quite helpful for expanding/collapsing regions using the keyboard:

Macro Purpose Keys (example)
ExpandAllRegions expands all regions in the current document Ctrl-Shift-'+'
CollapseAllRegions collapses all regions in the current document Ctrl-Shift-'-'
ToggleParentRegion expands/collapses the region the cursor is currently in Ctrl-'+' and Ctrl-'-'

Installation:

 

  • Open the Macros IDE (Tools - Macros - Macros IDE)
  • Create a new module, replace the code in the created file with the posted source code, save file
  • Assign keys in VS.Net (Tools - Options - Keyboard).

Tip: type "Region" in the input field under "show commands containing" to limit the list of shown commands (don't laugh, it's always amazing how many people don't know about this rather obvious feature...)

Known Issues

  • The code runs fine in VS.Net 2003; in VS.Net 2002 I had strange problems with "Selection.FindText" not working reliably.
  • ToggleParentRegion is "good enough", but not perfect; e.g. when the cursor is at the end of a line containing a collapsed region, it won't expand the region, but move the cursor to the start of the line (where a second invocation will work fine).
  • (Update 14.08.2003): The macro ExpandAllRegions does not work in VB.Net (see comments below). The macro ToggleParentRegion didn't work correctly, either, but could be fixed (see "Updated" comment in code).

Source Code

Imports EnvDTE
Imports System.Diagnostics
' Macros for improving keyboard support for "#region ... #endregion"
Public Module RegionTools
' Toggles the current region surrounding the cursor
Sub ToggleParentRegion()
Dim objSelection As TextSelection
objSelection = DTE.ActiveDocument.Selection
Dim objPosition As EnvDTE.TextPoint
objPosition = objSelection.AnchorPoint
objSelection.SelectLine()
If (InStr(objSelection.Text.ToLower(), "#region") <> 0) Then ' Updated 14.08.2003
objSelection.MoveToPoint(objPosition)
DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
ElseIf (objSelection.FindText("#region", vsFindOptions.vsFindOptionsBackwards)) Then
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
Else
objSelection.MoveToPoint(objPosition)
End If
End Sub

' Expands all regions in the current document
Sub ExpandAllRegions()
DTE.ExecuteCommand("Edit.StopOutlining")
DTE.ExecuteCommand("Edit.StartAutomaticOutlining")
End Sub

' Collapses all regions in the current document
Sub CollapseAllRegions()
ExpandAllRegions()
Dim objSelection As TextSelection
objSelection = DTE.ActiveDocument.Selection
objSelection.StartOfDocument()
While (objSelection.FindText("#region"))
objSelection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
objSelection.StartOfDocument()
End While
DTE.ActiveDocument.Selection.StartOfDocument()
End Sub
End Module

22 Comments

  • I think you have the same functionality with the built in shortcuts in vs.NET:





    CTRL+M CTRL+M (that's two key presses!) - collapse/open the current parent region





    CTRL+M CTRL+L - Collpase/Open all regions in document recursively (meaning you might get only one line in the codument - one big namespace region which is collapsed or you'll see the entrie page code uncollapsed





    CTRL+M CTRL+O - Collpase all regions not recursively - you'll see all child region but thee'll be collapsed





  • &gt; I think you have the same functionality with the built in shortcuts in vs.NET





    Not quite. The built-in shortcuts affect all collapsible elements (namespaces, classes, etc.). What I needed were commands affecting only &quot;#region ... #endregion&quot; blocks, that's why I wrote the macros.

  • The exapand all regions macro does not work for me. The code below only does what it states and that does not cause all regions to be expanded. Does this code work for you? Any thoughts?



    Sub ExpandAllRegions()

    DTE.ExecuteCommand(&quot;Edit.StopOutlining&quot;)

    DTE.ExecuteCommand(&quot;Edit.StartAutomaticOutlining&quot;)

    End Sub

  • &gt; The exapand all regions macro does not work for me.

    &gt; [...]

    &gt; Does this code work for you?

    Yes. I use it every day. I also re-checked that I published the correct version.



    Could you please

    - open the macro IDE

    - put a breakpoint on the line

    DTE.ExecuteCommand(&quot;Edit.StopOutlining&quot;)

    - go back to the VS.Net IDE

    - press the key you assigned inside the text editor

    - single step through the macro in the macro IDE, describing me what you see after each of the two lines?

    This would help me a lot.



    BTW: Which version of VS.Net are you using?



    Roland

  • I am using VS.NET 2003.



    I did what you asked.



    To start, I have all my regions closed, and automatic outlining on, for simplicity.



    DTE.ExecuteCommand(&quot;Edit.StopOutlining&quot;)

    Does what I would expect. It turns off automatic outlining. My regions are still closed at this point.



    DTE.ExecuteCommand(&quot;Edit.StartAutomaticOutlining&quot;)

    This turns the automatic outlineing back on. Regions are still closed.



    It appears that I am not seeing some side effect of toggling automatic outlining that you do. Does this work for you when you toggle it through the context menu (right click)?

  • &gt; DTE.ExecuteCommand(&quot;Edit.StopOutlining&quot;)

    &gt; Does what I would expect. It turns off automatic outlining. My regions are still closed at this point.

    Wow. This command expands everything in my text file and removes the [-] and [+] icons.



    &gt; DTE.ExecuteCommand(&quot;Edit.StartAutomaticOutlining&quot;)

    &gt; This turns the automatic outlineing back on. Regions are still closed.

    On my system, this only show the icons again.



    &gt; It appears that I am not seeing some side effect of toggling automatic outlining that you do.

    &gt; Does this work for you when you toggle it through the context menu (right click)?

    Just tried it - yes.



    This is really weird. I tested it on 4 machines (2x Win2k, 1x WinXp, 1x Win2k3) and it runs fine. I use VS.Net US and Win US.



    Roland

  • Ok, looks like neither of us is crazy. It appears the editor acts differently based on the language its editing. I was using vb.net code and the steps that you use do not work. I opened up a C# file, and everything you do works.



    Why there is a difference I will never know.

  • I took a quick look at the ExpandAllRegions macro inside VB.Net and couldn't find a *quick* solution to fix the problem. Seems like a working solution would involve searching for #Region statements.

    I must admit that my motivation for actually implementing this is very low (I'm a &quot;curly braces&quot; language guy). If somebody has a fix, I will include it in the code with full credits, but right now, I will leave things the way they are and include this in the &quot;Known issues&quot; section.



    Roland

  • And yes...



    'DTE.ExecuteCommand(&quot;Edit.ToggleOutliningExpansion&quot;)



    is intentionally commented out since the .FindText function performs this for us.

  • For some reason in Visual Studio .NET 2003 it appears that CTRL+M, CTRL+L doesn't appear to work in at least the VB IDE -- it used to in the original Visual Studio .NET release.



    As such, I'm glad, since this afforded me the opportunity to learn how macros work and actually improve on what Roland did. Thanks for pointing me in the right direction Roland - the VB guys should thank you a ton for this until MS fixes this.

  • Oh, and Roland, might want to point new users that haven't ever used macros to some quick tutorials as to how to get them set up / mapped.



    A little no-no I found was that the module file name has to be the same name as the actual &quot;Public Module Blah&quot; block in code or the macro picker doesn't see any sub-routines under it.

  • Cool stuff, Andrew!



    I'll look into this over the weekend and will post an article (including some screenshots showing how to set up the macros).



    Roland

  • the code actually looks &quot;prettier&quot; on my side, but the weblog rips out white space... ;(

  • Hi Andrew, if you're reading this:

    a) can I reach you by email (please use the contact link in the upper left corner so you don't have to post your email address publicly)

    b) What is the idea behind the reimplementation of CollapseAllRegions? I did only a few quick tests in VB.Net, so I surely did miss some special case when the original CollapseAllRegions didn't work. At first sight, searching over and over again from the end of the document seems a bit inefficient (although performance doesn't seem to be a factor here -- I couldn't detect an actual difference, at least with the not-so-big source files it tried)



    Roland

  • Hello! Thanks so much for this! I'm using vs.net along with visual sourcesafe and sourcesafe keeps collapsing all my regions - very annoying! Now with only a few presses on the keyboard they're all open! Thanks!

  • re Opening all regions in VB.net.

    I'm using VS Professional 2003.



    This is a little scary, but with one or more regions closed, try Ctrl-Y, then Undo (the curly back arrow)



    The cursor can be anywhere on the screen. The ctrl-y deletes everything, but undo brings it all back with the regions open.

  • Hi Susan,



    this is weird... I tried to reproduce the behaviour in VS.Net, both using VB.Net and C#. At first nothing strange happened (Opening all regions, hitting Ctrl-Y, closing regions, hitting Ctrl-Y again). I finally gave up in VB.Net and tried it in C# a couple of times.

    At some point I had the behaviour you described, too - but now I cannot reproduce it.

  • Thank's for the great tool. I guess it very usefull, unfortunately i wasn't able to check it out, because i can't assign key's in VS.Net.



    Has anyone a hint for me??



    The Macro is simply not listed in the Listbox (VS.NET Menu - Tools, Options - Keyboard). I added a new module, inserted the code and saved the file. I can debug den function in the Macro IDE.



    I am using VS.NET 2003 German.



    Thanks



    Anton

  • Hi Anton,



    just guessing: Do module name and filename match (i.e. &quot;RegionTools&quot;)?



    Roland

  • Thank you, Roland. Now everything works fine...



    Anton

  • Don't know if this is too old information, but in response to Susan (from 2/17/2004) Ctrl-Y does the &quot;Redo&quot; command, so if you by any chance deleted everything, then did an &quot;Undo&quot; (which is Ctrl-Z) then Ctrl-Y would in fact delete everything, but that's only because it was redo-ing the previous delete. Just trying to clear up any confusion.

  • Aaahhhhhhh!!!


    Very nice!

Comments have been disabled for this content.