Comment/Uncomment Macro and more





5.00/5 (18 votes)
Dec 5, 2000

127864

1214
Useful Visual Studio macros to simplify commenting code
The macros presented here act as a comment "toggle". With a single keystroke, it will add comment text to the selected code or it will remove the comment if already present. It correctly handles selected words, single lines or multiple selected lines. It also handles several special cases. All editing is performed in memory so that the editor can provide a single "undo" for the operation. This macro has proved useful for many programmers and can greatly simplify the common, tedious programming task of enabling or disabling blocks of code.
Overview and Requirements
Providing useful comments in your source code is very important for understanding the code and
for future maintenance. Comments are also useful during development to enable or disable code
that is being tested. The basic act of editing text to enter or remove comments can be tedious.
This is especially
true if you have a large quantity of lines to comment or you have to deal with embedded /* */
style comments.
My solution to simplify entering comments is to let the editor do most of the work. The editor does
not provide this functionality (probably because it would have to enforce a particular style). We can
easily add this functionality with a few macros.
Adding comments to code is somewhat dependent on the programmer's preferred coding style. Naturally my macro
adheres to my preferred style, but the style choices also have practical advantages. In general,
I prefer //
style comments. Here is the required functionality I desired from the macro:
- Comment based upon the current selection
- Assignable to a single keystroke
- Should "toggle", e.g. add or remove a comment depending on the presence of a comment
- Not break due to the presence of existing comments
- Handle single lines and multiple lines
- Comment selected words
- Allow the user to "undo" the comment/un-comment action
Finally, there is a special case editing action I find myself performing frequently. I often add a comment at the end of the line explaining what the line does. Over time, perhaps, this single line of code expands to multiple lines or deserves better white space separation, so I move the comment above the line. I have provided a macro that toggles between each comment location.
Installation
Install the macro by unzipping the solesby.dsm
file to a desired location.
Choose the Tools->Macros menu option, expand the dialog with the Options button, and
then load the macro file. You may need to use the Browse button if you save the file
outside your Visual Studio macro directory.
You will also want to map the macro to a key to make it useful. I map the CustomCommentOut
macro to the keystroke control-/
. This combination is not used in the default Visual
Studio configuration and is also intuitive for C/C++ programmers. I then map the CommentLineToggle
macro to the keystroke control-shift-/
.
Details of Operation
The macro behaves differently under different conditions. The operation is determined by the current selection as well as the text itself. If the text has already been commented, then the macro will remove the comments. If it has not been commented, comments will be added. The selection determines the style of comments used. Hopefully the varying operations will be intuitive, but each is demonstrated below.
Single Line Selection
![]() |
The most basic operation is commenting a single line. This situation is identified by the lack of a
selection (i.e. the cursor is on the desired line without any words selected).
" |
Multiple Line Selection
![]() |
When multiple lines are selected, " |
![]() |
The macro's decision to add or remove comments is based on the last line of the selection rather than the first. This allows you to easily comment out a logical block of code, which often has a comment on the line preceding it. When you remove the comment, the documentation comment(s) will remain intact. |
Word Selection
![]() |
If text is selected within a single line, then the assumption is that you wish to control comments
for the selected text.
" |
End-of-line Comments
![]() |
This macro moves comments from the end of the line to the line above and vice versa.
This is a separate macro and should be assigned to a different keystroke (e.g. |
Code for Macros
CustomCommentOut
Here is the key part of the comment macro. Note: this code is dependent on other functions and has older methods also present. You should download the file instead of copying this sample code directly.
'----------------------------------------------------------------------------------
' This will comment/uncomment out single lines or blocks. Single lines are commented
' with the same indention level. Blocks are commented at the beginning of the line.
' Assign this to a key (e.g. ctrl-/) and it will toggle the current line/block of code.
' This will handle both "//" and "'" style comments
'----------------------------------------------------------------------------------
Sub CustomCommentOut ()
'DESCRIPTION: Comments out a selected block of text. (ctrl-/)
' [ by Adam Solesby -- http://solesby.com ]
Dim win
set win = ActiveWindow
If win.type <> "Text" Then
MsgBox "This macro can only be run when a text editor window is active."
Else
TypeOfFile = FileType(ActiveDocument)
' MsgBox "Type: " + CStr(TypeOfFile)
If TypeOfFile > 0 And TypeOfFile < 6 Then
If TypeOfFile > 3 Then
CommentType = "'" ' VB
CommentWidth = 1
Else
CommentType = "//" ' C++ and java style comments
CommentWidth = 2
End If
StartLine = ActiveDocument.Selection.TopLine
EndLine = ActiveDocument.Selection.BottomLine
If EndLine < StartLine Then
Temp = StartLine
StartLine = EndLine
EndLine = Temp
End If
' single line with words selected
If EndLine = StartLine And Len(ActiveDocument.Selection) > 0 Then
s = ActiveDocument.Selection.Text
n = Len(ActiveDocument.Selection)
' convert "/*sample text*/" => "sample text" ("/*sample text*/" selected)
If left(s,2) = "/*" and Right(s,2) = "*/" Then
ActiveDocument.Selection = Mid(s,3,n-4)
Else
ActiveDocument.Selection.CharLeft
ActiveDocument.Selection.CharLeft dsMove, 2
ActiveDocument.Selection.CharRight dsExtend, n + 4
s2 = ActiveDocument.Selection.Text
' convert "/*sample text*/" => "sample text" ("sample text" selected)
If left(s2,2) = "/*" and Right(s2,2) = "*/" Then
ActiveDocument.Selection = s
' convert "sample text" => "/*sample text*/" ("sample text" selected)
Else
ActiveDocument.Selection.CharLeft
ActiveDocument.Selection.CharRight dsMove, 2
ActiveDocument.Selection.CharRight dsExtend, n
ActiveDocument.Selection = "/*" & s & "*/"
End If
End If
' Single line -- comment at start of text
' have to check for comments at start of line and start of text
ElseIf EndLine = StartLine Then
ActiveDocument.Selection.StartOfLine dsFirstColumn
ActiveDocument.Selection.CharRight dsExtend, CommentWidth
If ActiveDocument.Selection = CommentType Then
ActiveDocument.Selection.Delete
Else
ActiveDocument.Selection.StartOfLine dsFirstText
ActiveDocument.Selection.CharRight dsExtend, CommentWidth
If ActiveDocument.Selection = CommentType Then
ActiveDocument.Selection.CharLeft
ActiveDocument.Selection.EndOfLine dsExtend
s = ActiveDocument.Selection.Text
s = LTrim( Mid ( s, 3 ) )
Do While Left(s,1) = vbTab
s = LTrim( Mid( s, 2 ) )
Loop
ActiveDocument.Selection = s
Else
ActiveDocument.Selection.StartOfLine dsFirstText
ActiveDocument.Selection = CommentType + vbTab + ActiveDocument.Selection
End If
End If
ActiveDocument.Selection.StartOfLine dsFirstText
' Multi-line -- comment at start of line
Else
CommentLoc = dsFirstColumn ' or dsFirstText if you prefer
' check whether commenting on or off based on the _last_ line of selection
ActiveDocument.Selection.GoToLine EndLine
ActiveDocument.Selection.StartOfLine CommentLoc
ActiveDocument.Selection.CharRight dsExtend, CommentWidth
If ActiveDocument.Selection = CommentType Then
bAddComment = False
Else
bAddComment = True
End If
' work with strings so that we can do a single undo in editor
ActiveDocument.Selection.MoveTo StartLine, 1
ActiveDocument.Selection.MoveTo EndLine, dsEndOfLine, dsExtend
s = ActiveDocument.Selection.Text
If bAddComment Then
s = CommentType & Replace( s, vbNewLine , vbNewLine & CommentType )
Else
s = Replace( s, vbNewLine & CommentType, vbNewLine )
s = Mid( s, Len(CommentType)+1 )
End If
ActiveDocument.Selection = s
End If
Else
MsgBox("Unable to comment out the highlighted text" + vbLf + _
"because the file type was unrecognized." + vbLf + _
"If the file has not yet been saved, " + vbLf + _
"please save it and try again.")
End If
End If
End Sub
CommentLineToggle
Below is the implementation for the end-of-line comment toggle.
'----------------------------------------------------------------------------------
' This function toggles between end-of-line comments and line-before comment
'
' // comment here
' void function(); <==> void function(); // comment here
'
'----------------------------------------------------------------------------------
Sub CommentLineToggle()
'DESCRIPTION: This toggles between end-of-line comments and line-before comment (ctrl-shift-/)
' [ by Adam Solesby -- http://solesby.com ]
StartLine = ActiveDocument.Selection.TopLine
EndLine = ActiveDocument.Selection.BottomLine
StartColumn = ActiveDocument.Selection.CurrentColumn
If StartLine <> EndLine Then Exit Sub
ActiveDocument.Selection.StartOfLine dsFirstText
ActiveDocument.Selection.CharRight dsExtend, 2
' Check for comment-only line
If ActiveDocument.Selection = "//" Then
' Found a previous-line comment, e.g.:
' // this is a comment above the line
' void function();
' cut and paste on line below
ActiveDocument.Selection.SelectLine
ActiveDocument.Selection.Cut
ActiveDocument.Selection.EndOfLine
ActiveDocument.Selection.Paste
ActiveDocument.Selection.Backspace
bFound = ActiveDocument.Selection.FindText("//", dsMatchBackward)
If bFound Then
ActiveDocument.Selection.CharLeft
ActiveDocument.Selection.DeleteWhitespace dsHorizontal
ActiveDocument.Selection = " "
End If
Else
ActiveDocument.Selection.EndOfLine
ActiveDocument.Selection.SelectLine
bFound = ActiveDocument.Selection.FindText("//", dsMatchBackward)
If bFound Then
' Found an end-of-line comment, e.g.:
' void function() // this is a comment
If StartLine = ActiveDocument.Selection.CurrentLine Then
' cut and paste on line above
ActiveDocument.Selection.CharLeft
ActiveDocument.Selection.NewLine
ActiveDocument.Selection.DeleteWhitespace dsHorizontal
ActiveDocument.Selection.LineDown dsExtend
ActiveDocument.Selection.Cut
ActiveDocument.Selection.LineUp
ActiveDocument.Selection.Paste
ActiveDocument.Selection.WordRight dsExtend
ActiveDocument.Selection.Copy
ActiveDocument.Selection.LineUp
ActiveDocument.Selection.StartOfLine dsFirstColumn
ActiveDocument.Selection.Paste
Else
ActiveDocument.Selection.MoveTo StartLine, StartColumn
End If
End If
End If
End Sub
History
Quite a while ago I posted early versions of some of my Visual Studio macros. The most useful and popular of these macros was one that could toggle comments for a single line or multiple lines of code. Since then I have received several suggestions from users of the code as well as enhanced the macros for my own purposes. This article presents the new and improved macros. It also provides a little more explanation that will hopefully let more people see how they might be able to use them. Thank you to all who have sent suggestions.
The original macro simply looped through each line and toggled the comment for the line. This had several disadvantages: (a) If you tried to "undo" the action, you would simply undo the last line affected. Undoing the action on many lines was annoying. (b) Each line was toggled individually. This could leave a mix of commented and un-commented lines.
As described above, the macro now performs the text operation on a string in memory and only provides
a single editor selection update. This allows the entire comment toggle operation to be undone. Also
the decision to comment or un-comment is based on the block (actually the last line of the block) and
performs the same operation on every line in the selection. Finally, several users requested the
handling of selected words using /* */
style comments.
For more information, please visit my website: http://www.solesby.com