Documents






Documents

Document objects are used to represent an open document in the IDE. To contrast this abstraction with that provided by the Window object: A Window object is used to represent the physical UI aspects of a document window, whereas a Document object is used to represent the physical document that is being displayed within that document window.

A document could be a designer, such as the Windows Forms designer, or it could be a text-based document such as a readme file or a C# code file open in an editor.

Just as you get a list of all open windows using the DTE.Windows collection, you can use the DTE.Documents collection to retrieve a list of all open documents:

Dim documents As Documents = DTE.Documents

The Documents collection is indexed by the document's Name property, which is, in effect, the document's filename without the path information. This makes it easy to quickly retrieve a Document instance:

Dim documents As Documents = DTE.Documents
Dim readme As Document = documents.Item("ReadMe.txt")

Using the Document object, you can

  • Close the document (and optionally save changes)

  • Retrieve the filename and path of the document

  • Determine whether the document has been modified since the last time it was saved

  • Determine what, if anything, is currently selected within the document

  • Obtain a ProjectItem instance representing the project item that is associated with the document

  • Read and edit the contents of text documents

Figure contains the member descriptions for the Document object.

Figure Document Members

Property

Description

ActiveWindow

The currently active window associated with the document (null or Nothing value indicates that there is no active window).

Collection

The collection of Document objects to which this instance belongs.

DTE

The root-level DTE object.

Extender

Returns a Document extender object.

ExtenderCATID

The extender category ID for the object.

ExtenderNames

A list of extenders available for the current Document object.

FullName

The full path and filename of the document.

Kind

A GUID representing the kind of document.

Name

The name (essentially, the filename without path information) for the document.

Path

The path of the document's file excluding the filename.

ProjectItem

The ProjectItem instance associated with the document.

Saved

Indicates whether the solution has been saved since the last modification.

Selection

An object representing the current selection in the document (if any).

Windows

The Windows collection containing the window displaying the document.


Method

Description

Activate

Moves the focus to the document.

Close

Closes the document. You can indicate, with a vsSaveChanges enum value, whether the window's hosted document should be saved or not saved, or whether the IDE should prompt the user to make that decision.

NewWindow

Opens the document in a new window and returns the new window's Window object.

Object

Returns an object proxy that represents the window and can be referenced by name.

Redo

Re-executes the last user action in the document.

Save

Saves the document.

Undo

Reverses the last used action in the document.


Text Documents

As we mentioned, documents can have textual or nontextual content. For those documents with textual content, a separate objectTextdocumentexists. The TexTDocument object provides access to control functions specifically related to text content.

If you have a valid Document object to start with, and if that document object refers to a text document, then a Textdocument instance can be referenced from the Document.Object property like this:

Dim doc As TextDocument
doc = myDocument.Object

Figure contains the Textdocument members.

Figure Textdocument Members

Property

Description

DTE

The root-level DTE object

EndPoint

A TextPoint object positioned at the end of the document

Parent

Gets the parent object of the text document

Selection

Returns a TextSelection object representing the currently selected text in the document

StartPoint

A TextPoint object positioned at the start of the document


Method

Description

ClearBookmarks

Removes any unnamed bookmarks present in the document

CreateEditPoint

Returns an edit point at the specific location (if no location is specified, the beginning of the document is assumed)

MarkText

Bookmarks lines in the document that match the specified string pattern

ReplacePattern

Replaces any text in the document that matches the pattern


Tip

A text document will be represented by both a Document instance and a Textdocument instance. Nontext documents, such as a Windows form open in a Windows Forms designer window, will have a Document representation but no corresponding Textdocument representation. Unfortunately, there isn't a great way to distinguish whether a document is text based or not during runtime. One approach is to attempt a cast or assignment to a Textdocument object and catch any exceptions that might occur during the assignment.


Two Textdocument methods are useful for manipulating bookmarks within the document: ClearBookmarks will remove any unnamed bookmarks from the document, and MarkText will perform a string pattern search and place bookmarks against the resulting document lines. A simple macro to bookmark For loops in a VB document is presented in Listing 10.10.

Listing 10.10. Bookmarking For Loops in a VB Document

Imports EnvDTE
Imports EnvDTE80
Imports Microsoft.VisualStudio.CommandBars
Imports System.Diagnostics
Imports System.Windows.Forms


Public Module MacroExamples

    ' Bookmark all 'For' tokens in the current
    ' document
    Public Sub BookmarkFor()
        Dim doc As Document
        Dim txtDoc As TextDocument

        ' Reference the current document
        doc = DTE.ActiveDocument

        ' Retrieve a TextDocument instance from
        ' the document
        txtDoc = doc.Object

        ' Call the MarkText method with the 'For' string
        Dim found As Boolean = _
            txtDoc.MarkText("For", vsFindOptions.vsFindOptionsFromStart)

        ' MarkText returns a boolean flag indicating whether or not
        ' the search pattern was found in the textdocument
        If found Then
            MessageBox.Show("All instances of 'For' have been bookmarked.")
        Else
            MessageBox.Show("No instances of 'For' were found.")
        End If
    End Sub
End Module

The other key functionality exposed by the Textdocument object is the capability to read and edit the text within the document.

Editing Text Documents

From a Visual Studio perspective, text in a text document actually has two distinct "representations": a virtual one and a physical one. The physical representation is the straight, unadulterated code file that sits on disk. The virtual representation is what Visual Studio presents on the screen: It is an interpreted view of the text in the code file that takes into account various editor document features such as code outlining/regions, virtual spacing, word wrapping, and so on.

Figure shows this relationship. When displaying a text document, Visual Studio reads the source file into a text buffer, and then the text editor presents one view of that text file to you (based on options you have configured for the editor).

7. Presentation of text documents within the IDE.


Text in a document is manipulated or read either on the buffered text or on the "view" text that you see in the editor. There are four different automation objects that allow you to affect text; two work on the text buffer and two work on the editor view.

For the text buffer:

  • TextPoint objects are used to locate specific points within a text document. By querying the TextPoint properties, you can determine the line number of the text point, the number of characters it is offset from the start of a line, the number of characters it is offset from the start of the document, and its display column within the text editor window. You can also retrieve a reference to a CodeModel object representing the code at the text point's current location.

  • The EditPoint object inherits from the TextPoint object; this is the primary object used for manipulating text in the text buffer. You can add, delete, or move text using edit points, and they can be moved around within the text buffer.

And, for the editor view:

  • The VirtualPoint object is equivalent to the TextPoint object except that it can be used to query text locations that reside in the "virtual" space of the text view (virtual space is the whitespace that exists after the last character in a document line). VirtualPoint instances are returned through the TextSelection object.

  • The TextSelection object operates on text within the text editor view as opposed to the text buffer and is equivalent to the EditPoint interface. When you use the TextSelection object, you are actively affecting the text that is being displayed within the text editor. The methods and properties of this object, therefore, end up being programmatic approximations of the various ways that you would manually affect text: You can page up or page down within the view; cut, copy, and paste text; select a range of text; or even outline and expand or collapse regions of text.

Because the VirtualPoint object is nearly identical to the TextPoint object, and the TextSelection object is nearly identical to the EditPoint object, we won't bother to cover each of these four objects in detail. Instead, we will focus on text buffer operations using EditPoint and TextPoint. You should be able to easily apply the concepts here to the text view.

Because EditPoint objects expose the most functionality and play the central role with text editing, we have provided a list of their type members in Figure.

Figure EditPoint2 Members

Property

Description

AbsoluteCharOffset

The number of characters from the start of the document to the current location of the edit point

AtEndOfDocument

Boolean flag indicating whether the point is at the end of the document

AtEndOfLine

Boolean flag indicating whether the point is at the end of a line in the document

AtStartOfDocument

Boolean flag indicating whether the point is at the beginning of the document

AtStartOfLine

Boolean flag indicating whether the point is at the start of a line in the document

CodeElement

Returns the code element that maps to the edit point's current location

DisplayColumn

The column number of the edit point

DTE

Returns the root automation DTE object

Line

The line number where the point is positioned

LineCharOffset

The character offset, within a line, of the edit point

LineLength

The length of the line where the edit point is positioned

Parent

Returns the parent object of the EditPoint2 object


Method

Description

ChangeCase

Changes the case of a range of text

CharLeft

Moves the edit point to the left the specified number of characters

CharRight

Moves the edit point to the right the specified number of characters

ClearBookmark

Clears any unnamed bookmarks that exist on the point's current line location

Copy

Copies a range of text to the Clipboard

CreateEditPoint

Creates a new EditPoint2 object at the same location as the current EditPoint2 object

Cut

Cuts a range of text and places it on the Clipboard

Delete

Deletes a range of text from the document

DeleteWhitespace

Deletes any whitespace found around the edit point

EndOfDocument

Moves the edit point to the end of the document

EndOfLine

Moves the edit point to the end of the current line

EqualTo

A Boolean value indicating whether the edit point's AbsoluteCharOffset value is equal to another edit point's offset

FindPattern

Finds any matching string patterns in the document

GetLines

A string representing the text between two lines in the document

GetText

A string representing the text between the edit point and another location in the document

GreaterThan

A Boolean value indicating whether the edit point's AbsoluteCharOffset value is greater than another edit point's offset

Indent

Indents the selected lines by the given number of levels

Insert

Inserts a string into the document, starting at the edit point's current location

InsertFromFile

Inserts the entire contents of a text file into the document starting at the edit point's current location

LessThan

Returns a Boolean value indicating whether the edit point's AbsoluteCharOffset value is less than another edit point's offset

LineDown

Moves the point down one or more lines

LineUp

Moves the point up one or more lines

MoveToAbsoluteOffset

Moves the edit point to the given character offset

MoveToLineAndOffset

Moves the edit point to the given line and to the character offset within that line

MoveToPoint

Moves the edit point to the location of another EditPoint or TextPoint object

NextBookmark

Moves the edit point to the next available bookmark in the document

OutlineSection

Creates an outline section between the point's current location and another location in the document

PadToColumn

Pads spaces in the current line up to the indicated column number

Paste

Pastes the contents of the Clipboard to the edit point's current location

PreviousBookmark

Moves the edit point to the previous bookmark

ReadOnly

Returns a Boolean flag indicating whether a text range in the document is read only

ReplacePattern

Replaces any text that matches the provided pattern

ReplaceText

Replaces a range of text with the provided string

SetBookmark

Creates an unnamed bookmark on the edit point's current line in the document

StartOfDocument

Moves the edit point to the start of the document

StartOfLine

Moves the edit point to the beginning of the line where it is positioned

TRyToShow

Attempts to display the point's current location within the text editor window

Unindent

Removes the given number of indentation levels from a range of lines in the document

WordLeft

Moves the edit point to the left the given number of words

WordRight

Moves the edit point to the right the given number of words


Now let's look at various text manipulation scenarios.

Adding Text

EditPoint objects are the key to adding text, and you create them either by using a Textdocument object or by using a TextPoint object.

A TextPoint instance can create an EditPoint instance in its same exact location by calling TextPoint.CreateInstance. With the Textdocument type, you can call the CreateEditPoint method and pass in a valid TextPoint.

Because TextPoint objects are used to locate specific points in a document, a TextPoint object is leveraged as an input parameter to CreateEditPoint. In essence, the TextPoint object tells the method where to create the edit point. If you do not provide a TextPoint object, the edit point will be created at the start of the document.

This code snippet shows an edit point being created at the end of a document:

Dim doc As Document = DTE.ActiveDocument
Dim txtDoc As TextDocument = doc.Object

Dim tp As TextPoint = txtDoc.EndPoint
Dim ep As EditPoint2 = txtDoc.CreateEditPoint(tp)
' This line of code would have the same effect
ep = tp.CreateEditPoint

After creating an edit point, you can use it to add text into the document (remember, you are editing the buffered text whenever you use an EditPoint object). To inject a string into the document, you use the Insert method:

' Insert a C# comment line
ep.Insert("// some comment")

You can even grab the contents of a file and throw that into the document with the EditPoint.InsertFromFile method:

' Insert comments from a comments file
ep.InsertFromFile("C:\Contoso\std comments.txt")

Editing Text

The EditPoint object supports deleting, replacing, cutting, copying, and pasting text in a document.

Some of these operations require more than a single point to operate. For instance, if you wanted to cut a word or an entire line of code from a document, you would need to specify a start point and end point that define that range of text (see Figure).

8. Using points within a document to select text.


This snippet uses two end points, one at the start of a document and one at the end, to delete the entire contents of the document:

Dim doc As Document = DTE.ActiveDocument
Dim txtDoc As TextDocument = doc.Object

Dim tpStart As TextPoint = txtDoc.StartPoint
Dim tpEnd As TextPoint = txtDoc.EndPoint

Dim epStart As EditPoint2 = txtDoc.CreateEditPoint(tpStart)
Dim epEnd As EditPoint2 = txtDoc.CreateEditPoint(tpEnd)
epStart.Delete(epEnd)

Besides accepting a second EditPoint, the methods that operate on a range of text will also accept an integer identifying a count of characters. This also has the effect of defining a select. For example, this snippet cuts the first 10 characters from a document:

epStart.Cut(10)

Repositioning an EditPoint

After establishing an EditPoint, you can move it to any given location in the document by using various methods. The CharLeft and CharRight methods will move the point any number of characters to the left or right, while the WordLeft and WordRight methods perform the same operation with words:

' Move the edit point 4 words to the right
epStart.WordRight(4)

The LineUp and LineDown methods will jog the point up or down the specified number of lines. You can also move EditPoints to any given line within a document by using MoveToLineAndOffset. This method will also position the point any number of characters into the line:

' Move the edit point to line 100, and then
' in 5 characters to the right
epStart.MoveToLineAndOffset(100, 5)

The macro code in Listing 10.11 pulls together some of the areas that we have covered with editing text documents. This macro and its supporting functions illustrate the use of EditPoints to write text into a document. In this case, the macro automatically inserts a comment "flowerbox" immediately preceding a routine. To accomplish this, the macro goes through the following process:

  1. A reference is obtained for the current document in the IDE.

  2. The active cursor location in that document is obtained via the Textdocument.Selection.ActivePoint property.

  3. An EditPoint is created using the VirtualPoint returned from the ActivePoint.

  4. A second EditPoint is then created; these two points are used to obtain the entire content of the routine definition line.

  5. The routine definition is then parsed to try to ferret out items such as its name, return value, and parameter list.

  6. A string is built using the routine information and is inserted into the text document using an EditPoint.

Inserting Comments into a Text Window

Imports EnvDTE
Imports EnvDTE80
Imports Microsoft.VisualStudio.CommandBars
Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Text
Imports System.Windows.Forms


Public Module MacroExamples

    ' This routine demonstrates various text editing scenarios
    ' using the EditPoint and TextPoint types. If you place your
    ' cursor on a subroutine or function, it will build a default
    ' "flower box" comment area, insert it immediately above the
    ' sub/function, and outline it.
    '
    ' To use:
    '   1) put cursor anywhere on the Sub/Function line
    '   2) run macro
    '   The macro will fail silently (e.g., will not insert any
    '   comments) if it is unable to determine the start
    '   of the Sub/Function
    '
    Public Sub InsertTemplateFlowerbox()

        ' Get reference to the active document
        Dim doc As Document = DTE.ActiveDocument
        Dim txtDoc As TextDocument = doc.Object
        Dim isFunc As Boolean

        Try
            Dim ep As EditPoint2 = txtDoc.Selection.ActivePoint.CreateEditPoint()
            ep.StartOfLine()
            Dim ep2 As EditPoint2 = ep.CreateEditPoint()
            ep2.EndOfLine()

            Dim lineText As String = ep.GetText(ep2).Trim()

            If InStr(lineText, " Function ") > 0 Then
                isFunc = True
            ElseIf InStr(lineText, " Sub ") > 0 Then
                isFunc = False
            Else
                Exit Sub
            End If

            ' Parse out info that we can derive from the routine
            ' definition: the return value type (if this is a function),
            ' the names of the parameters, and the name of the routine.
            Dim returnType As String = ""
            If isFunc Then
                returnType = ParseRetValueType(lineText)
            End If

            Dim parameters As String() = ParseParameters(lineText)
            Dim name As String = ParseRoutineName(lineText)
            Dim commentBlock As String = BuildCommentBlock(isFunc, name, _
returnType, parameters)

            ' Move the edit point up one line (to position
            ' immediately preceding the routine)
            ep.LineUp(1)

            ' Give us some room by inserting a new blank line
            ep.InsertNewLine()

            ' Insert our comment block
            ep.Insert(commentBlock.ToString())

        Catch ex As Exception

        End Try

    End Sub
    Private Function BuildCommentBlock(ByVal isFunc As Boolean, _
        ByVal name As String, _
        ByVal returnType As String, ByVal parameters As String())

        Try
            Dim comment As StringBuilder = New StringBuilder()

            ' Build up a sample comment block using the passed in info
            comment.Append("''''''''''''''''''''''''''''''''''''''''''''''''")
            comment.Append(vbCrLf)
            comment.Append("' Routine: " + name)
            comment.Append(vbCrLf)
            comment.Append("' Description: [insert routine desc here]")
            comment.Append(vbCrLf)
            comment.Append("'")
            comment.Append(vbCrLf)
            If isFunc Then
                comment.Append("' Returns: A " & returnType & _
" [insert return value description here]")
            End If
            comment.Append(vbCrLf)
            comment.Append("'")
            comment.Append(vbCrLf)
            comment.Append("' Parameters:")
            comment.Append(vbCrLf)
            For i As Integer = 0 To parameters.GetUpperBound(0)
                comment.Append("'     ")
                comment.Append(parameters(i))
                comment.Append(": [insert parameter description here]")
                comment.Append(vbCrLf)
            Next
            comment.Append("''''''''''''''''''''''''''''''''''''''''''''''''")

            Return comment.ToString()

        Catch ex As Exception
            Return ""
        End Try

    End Function
    Private Function ParseRetValueType(ByVal code As String) As String
        Try
            ' Parse out the return value of a function (VB)
            ' Search for 'As', starting from the end of the string
            Dim length As Integer = code.Length
            Dim index As Integer = code.LastIndexOf(" As ")

            Dim retVal As String = code.Substring(index + 3, length - (index + 3))

            Return retVal.Trim()

        Catch ex As Exception

            Return ""
        End Try
    End Function
    Private Function ParseParameters(ByVal code As String) As String()
        Try
            ' Parse out the parameters specified (if any) for
            ' a VB sub/func definition
            Dim length As Integer = code.Length
            Dim indexStart As Integer = code.IndexOf("(")
            Dim indexEnd As Integer = code.LastIndexOf(")")

            Dim params As String = code.Substring(indexStart + 1, _
indexEnd - (indexStart + 1))

            Return params.Split(",")

        Catch ex As Exception
            Return Nothing
        End Try
    End Function
    Private Function ParseRoutineName(ByVal code As String) As String
        Try
            Dim name As String
            Dim length As Integer = code.Length
            Dim indexStart As Integer = code.IndexOf(" Sub ")
            Dim indexEnd As Integer = code.IndexOf("(")

            If indexStart = -1 Then
                indexStart = code.IndexOf(" Function ")
                If indexStart <> -1 Then
                    indexStart = indexStart + 9
                End If
            Else
                indexStart = indexStart + 5
            End If

            name = code.Substring(indexStart, indexEnd - indexStart)

            Return name.Trim()

        Catch ex As Exception
            Return ""
        End Try
    End Function
End Module



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows