Reputation: 57169
Generally I've no complaints about the speed of Visual Studio, but if I write a macro that writes out about 100 lines of code, it takes 1-2 minutes to complete.
That doesn't sound right. Is there another more convenient way to write code blocks?
For one thing, I noticed it fills the undo buffer as if I'm just typing the text by hand. Could I mimic copy/paste behavior, which is much faster?
Here's a somewhat contrived example I tried to test my case:
Sub WriteManyLines()
DTE.Commands.Raise("{AA61C329-D559-468F-8F0F-4F03896F704D}", 2, Customin, Customout)
DTE.Commands.Raise("{AA61C329-D559-468F-8F0F-4F03896F704D}", 5, Customin, Customout)
Dim sb As New StringBuilder()
For i As Integer = 1 To 100
sb.AppendFormat("public string Method{0:000}() {{ return ""Method{0:000}""; }}", i)
sb.AppendLine()
Next i
DTE.ActiveDocument.Selection.Text = sb.ToString()
End Sub
Upvotes: 2
Views: 1325
Reputation: 774
'' SLOOOW!
' DTE.ActiveDocument.Selection.Text = str
'' LIGHTNING FAST
Dim txtSel As TextSelection
txtSel = DTE.ActiveDocument.Selection
txtSel.Delete()
txtSel.Insert(str, vsInsertFlags.vsInsertFlagsInsertAtEnd)
Upvotes: 2
Reputation: 1050
I was facing the same problem as Abel, And thanks to JaredPar hints I was able to fix it in this way: Instead of using IVsTextLines
(Which seem to be only available when you have VS-SDK installed) I just use TextDocument
and get the 'EditPoint' object from that. My code look like this:
Dim vsTextDoc As TextDocument = DTE.ActiveDocument.Object("TextDocument")
Dim epoint As EditPoint = vsTextDoc.StartPoint.CreateEditPoint
Dim strBuilder As StringBuilder = New StringBuilder
'append everything to the strBuilder and then
strBuilder.AppendLine("This is a line")
epoint.Insert(strBuilder.ToString())
And Now it feel like lighting fast compare to whatever was happening before with that DTE.ActiveDocument.Selection.Text
thing! Hope it will help someone in future :)
Upvotes: 1
Reputation: 754923
This API is very deceptive in that it appears that you are replacing the selected text with the actual result of the StringBuilder
. Or in short, a copy / paste. But what you're really doing is typing the result of the StringBuilder
(this is why you seen the undo buffer filling up with data).
This type of behavior is true for much of the editing experience which comes from the DTE namespace. If you're interested in the esoteric details I wrote a blog experience about this general problem some time ago.
In order to fix it though you'll want to abandon DTE and get down into IVsTextLines
or ITextBuffer
(the latter is preferred as it's the newer managed API). To get out of DTE you should be able to execute the following
var vsTextLines = DTE.ActiveDocument.Object("TextDocument") as IVsTextLines;
Edits on an IVsTextLines
will go directly to the buffer and avoid the overhead of typing.
If you want to avoid DTE and COM entirely you can use IVsEditorAdaptersFactoryService
to map from the COM layer to the new 2010 managed APIs. This interface is typically queried via MEF but I believe you can also use IServiceProvider
(which DTE implements) and do a QueryService
call for it.
Upvotes: 3