Francesco's blog

 Sunday, October 30, 2005

I often need to paste a text fragment as a comment in my source code. Unfortunately I can't simply paste the text and then use the Edit-Comment Selectio command. because the Visual Studio editor - at least when working with VB.NET - tries to interpret the pasted text as code and it ruins its formatting, adds or deletes characters, and so forth. In addition to this problem, when I am preparing samples for my books I need to revise all CR-LFs in the text, to wrap longer lines, because Microsoft Press standards mandate that lines aren't longer than 92 characters. All in all, it's a real nuisance.

 

A few weeks ago I decided to avoid this waste of time and wrote a macro that would do the pasting and the formatting for me. It's a simple and tiny way to increase productivity, that allows me to focus on the things that really matter. If you like tidy code listings, I am sure you'll find this macro useful.

 

The first problem I had to solve is a limitation of the Clipboard.GetObjectData method. When invoked from a macro, this method always returns Nothing, thus I needed a different way to read the text in the Clipboard. I can surely do this with an API call or by calling a method in a separate DLL, but I thought that reading the Clipboard from a macro shouldn't be that difficult. My next attempt was based on the Paste method of the TextBox control:

 

' Retrieve the text in the clipboard

Dim tb As New TextBox

tb.Multiline = True

tb.WordWrap = False

tb.ScrollBars = ScrollBars.Both

tb.Paste()

Dim text As String = tb.Text

 

This approach works nearly always. Every now and then, in fact, the Paste method fails with a cryptic message: "Class already exists". I noticed that this error occurs only if the macro editor is open, therefore during the normal use it doesn't cause much trouble. However, once you get this error, the only way to get rid of it is by restarting Visual Studio. When I posted this first solution on my Italian blog, reader Andrea Ferendeles suggested a different approach, based on the Paste method of the TextSelection object:

 

' Read the text in the clipbard, through the Selection.Paste method. 
Dim sel As TextSelection = DirectCast(DTE.ActiveDocument.Selection, TextSelection)
Dim sp As EditPoint = sel.ActivePoint.CreateEditPoint()
sel.Paste()
' Select and read the text just pasted, then delete it

sel.MoveToPoint(sp, True)
Dim text As String = sel.Text
sel.Delete()

 

Once I solved this problem, writing the macro was relatively simple:

 

Imports EnvDTE
Imports System.Text.RegularExpressions

 

Imports CodeArchitectsMacros

 

   Public Sub PasteAsComment()
    
PasteAsComment("80")
   End Sub

   Public Sub PasteAsComment(ByVal lineLength As String)
     
Dim maxLength As Integer = CInt(lineLength)

      ' Read the text in the clipbard, through the Selection.Paste method. 
      Dim sel As TextSelection = DirectCast(DTE.ActiveDocument.Selection, TextSelection)
      Dim sp As EditPoint = sel.ActivePoint.CreateEditPoint()
      sel.Paste()
      ' Select and read the text just pasted, then delete it

      sel.MoveToPoint(sp, True)
      Dim text As String = sel.Text
      sel.Delete()

      ' Split in lines not longer than MaxLength
     
Dim result As String = ""
     
Dim currLineLength As Integer = 0
     
For Each m As Match In Regex.Matches(text, "\S+\s*")
        
If currLineLength + m.Length > maxLength Then
           
result &= ControlChars.CrLf
           
currLineLength = 0
        
End If
        
result &= m.Value
        
currLineLength += m.Length
        
If m.Value.IndexOf(ControlChars.CrLf) > 0 Then
           
currLineLength = 0
        
End If
      Next
    
  result &= ControlChars.CrLf

      ' Paste the text in the code editor
     
sp = sel.ActivePoint.CreateEditPoint()
     
sel.Insert(result)
     
sel.MoveToPoint(sp,
True)

      ' Comment and reformat it
      DTE.ExecuteCommand("Edit.CommentSelection")
     
sel.SmartFormat()
   End Sub

End Module

As you see, there are actually two macros. The version with zero arguments creates comments lines that are 80 characters or shorter; this is likely to be the version that you'll use more often and you may want to associate it with a keyboard shortcut. The version with one argument allows you to specify the line length and can be used only from the Command window. For example, the following command pastes the current Clipboard content as comments not longer than 60 characters:

 

Macros.MyMacros.UsefulMacros.PasteAsComment 60

 

You don't really have to type all these characters each time, because you can associate the command to an alias. using this command:

 

alias PasteCom Macros.MyMacros.UsefulMacros.PasteAsComment

 

Once you've created the alias, you can recall the macro as follows:

 

PasteCom 60

 


NOTE: In case you never wrote a macro in your programming life, this is how to proceed:

 

1) run the Tools-Macros-Macros IDE command (or just press Alt+F11) to bring up the Macro IDE

2) in the Macro IDE, select the MyMacros project, then issue the Projects-Add Module to create a new module that stores all your custom macros then paste the macro code inside this module. (As in previous code, most of my macros are gathered in the CodeArchitectsMacros module.)

3) Go back to Visual Studio and display the Macro Explorer window, by means of the Tools-Macros.Macro Explorer menu command (or just press Alt+F8); in the Macro Explorer window, expand the MyMacros node and then expand the CodeArchitectsMacros module

4) optionally, go to the Tools-Options dialog box to assign a keyboard shortcut to the PasteComment macro

 

You're now ready to test the macro. Switch to Notepad or Word or wherever the text is, copy it into the clipboard, switch back to Visual Studio, place the caret where you want to insert the comment, and run the macro. You can run the macro by double-clicking its node in the Macro Explorer window, by typing the keyboard shortcut (if you assigned one), or by typing the macro's name inside the Commands window (with or without its alias, see above).

 

3/6/2008 5:38:56 PM (GMT Standard Time, UTC+00:00)
Cheap Wellbutrin Medicine
3/6/2008 5:42:49 PM (GMT Standard Time, UTC+00:00)
order mexican wellbutrin
3/6/2008 5:46:02 PM (GMT Standard Time, UTC+00:00)
Generic prozac overnight
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

 
Get RSS/Atom Feed
RSS 2.0 | Atom 1.0
Search in the blog
Archive
<July 2008>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
Categories

Powered by: newtelligence dasBlog 1.8.5223.1