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.
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.
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-/
.
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).
" " style comments are added
preserving the current indentation. Comments are removed from either the beginning of the line
or the beginning of the indented text.
|
Multiple Line Selection
|
When multiple lines are selected, " " style comments are placed at the beginning of the line.
This style of comment is useful for commenting out a large block of text. " " style comments
are used instead of " " style comments so that embedded comments do not produce errors.
|
|
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.
" " style comments are added surrounding the selected text. If the selection has already
been commented, the comments are removed. The selection of commented text can include the comments or
just the text within the comments.
|
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. control-shift-/ ).
|
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.
Sub CustomCommentOut ()
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)
If TypeOfFile > 0 And TypeOfFile < 6 Then
If TypeOfFile > 3 Then
CommentType = "'"
CommentWidth = 1
Else
CommentType = "//"
CommentWidth = 2
End If
StartLine = ActiveDocument.Selection.TopLine
EndLine = ActiveDocument.Selection.BottomLine
If EndLine < StartLine Then
Temp = StartLine
StartLine = EndLine
EndLine = Temp
End If
If EndLine = StartLine And Len(ActiveDocument.Selection) > 0 Then
s = ActiveDocument.Selection.Text
n = Len(ActiveDocument.Selection)
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
If left(s2,2) = "/*" and Right(s2,2) = "*/" Then
ActiveDocument.Selection = s
Else
ActiveDocument.Selection.CharLeft
ActiveDocument.Selection.CharRight dsMove, 2
ActiveDocument.Selection.CharRight dsExtend, n
ActiveDocument.Selection = "/*" & s & "*/"
End If
End If
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
Else
CommentLoc = dsFirstColumn
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
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.
Sub CommentLineToggle()
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
If ActiveDocument.Selection = "//" Then
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
If StartLine = ActiveDocument.Selection.CurrentLine Then
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
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