Virtual Developer Workshop: Containerized Development with Docker
One of the most intriguing new features of VB 2005 is IntelliSense Code Snippets. Code snippets make it easy to insert commonly used pieces of code into your project. They are also great for very valuable pieces of code whose syntax you never get the quite right without consulting the documentation or another code sample because you use them so infrequently. However, code snippets offer more than just a code library or a simple text substitution utility. They provide replaceable parameters that you can TAB between, tooltips, URLs that provide links to online documentation, and the ability to specify to what scope each snippet should be available. Over 200 snippets ship with VB Express, so you likely can find just the snippet you need or at least one you can easily modify to fit your needs.
How Do I Use Code Snippets?
As you might expect, you can insert a snippet in several ways. From the Visual Studio menu, click Edit | IntelliSense | Insert Snippet... to open the Code Snippet Picker. The Code Snippet Picker displays your entire snippet collection in a hierarchical listbox, where you can drill-down to the snippet you want. You can also right-click in the editor and select Insert Snippet... from the context menu. You'll also find options for the coder who never likes to leave the keyboard. Type a ? and press TAB to open the Code Snippet Picker. Or, if the snippet you want has a shortcut defined, you can type in the shortcut and press TAB to insert it immediately.
After inserting a snippet, the inserted code will look similar to the code in Figure 1.
Figure 1: Snippet Inserted into CodeThe highlighted pieces of text are fields where you can enter the appropriate values for your code. You can move between the highlighted fields using the TAB key. Part of the beauty of snippets is that you have to change pieces of code in only one place, and they will automatically change throughout the snippet. For example, if you change the private member "newPropertyValue" to "myProperty", the snippet will automatically change all references to "newPropertyValue" within the snippet.
What Might I Create?
Since code snippets are just XML files, you can use any text editor to create them. You could also use the Visual Studio editor or download an open-source snippet editor from MSDN. (It is still in beta, so all the standard disclaimers apply. However, I found it very stable and useful for creating snippets.)
For demonstration, this article builds a new snippet from the ground up. One piece of code that I use several times in every project is a comment block at the top of all my code files, functions, and subs. It includes the name of the file/function/sub, a description, my name, and the date I wrote the code. It generally looks something like this:
' ------------------------------------------------------------------ ' NAME : GetEmployeeName ' DESCRIPTION : Lookup the employee name. ' PROGRAMMER : Josh Fitzgerald ' DATE : 2006-01-01 ' ------------------------------------------------------------------
But before you write your snippet, take a look at its file format and the code it contains.
The IntelliSense Code Snippet File Format
Code snippets are simply XML files with a .snippet extension. The snippet format is composed of several elements, child elements, and attributes. To see a code snippet schema reference, click here.
Every .snippet file begins with this code:
<?xml version="1.0" encoding="UTF-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0">
The first element is <Header>, which has several child elements to describe the snippet. The <Author>, <Description>, and <Title> elements are pretty self-explanatory. The <HelpUrl> element allows you to include a URL that links to more information about the snippet. The <Keywords> element provides a way to add custom <Keyword> child elements, which can be useful for searching and categorization. Using the <Shortcut> element, you can define an abbreviation to be used as a shortcut for inserting the snippet into your code. Finally, the <SnippetTypes> element has a <SnippetType> child element that defines whether the snippet is an "Expansion" or "SurroundsWith" snippet. All of these elements are optional, except for the <Title> element. The following is an example snippet:
<Header> <Author>Microsoft Corporation</Author> <Description>Defines a Property with a backing field.</Description> <HelpUrl>www.microsoft.com</HelpUrl> <Keywords> <Keyword>property</Keyword> <Keyword>class</Keyword> </Keywords> <Title>Define a Property</Title> <Shortcut>Property</Shortcut> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> </Header>
The Snippet: Imports, References, Declarations, and Code
The <Snippet> element contains the snippet code and has four child elements.
The <Imports> element, which specifies any namespaces that are to be imported, is optional. You can use zero or more <Import> elements, each specifying a namespace the code snippet uses:
<Imports> <Import> <Namespace>System</Namespace> </Import> <Import> <Namespace>Microsoft.VisualBasic</Namespace> </Import> </Imports>
The <References> element is optional and contains information about assembly references. It has two child elements, <Assembly> and &lUrl>. The <Assembly> element contains the name of the assembly referenced, and the <Url> element provides a link to more information about the referenced assembly. You can use exactly one <Assembly> element and zero or more <Url> elements in a <Reference> element:
<References> <Reference> <Assembly>System.dll</Assembly> <Url>www.microsoft.com</Url> </Reference> </References>
The <Declarations> element has two child elements that are used to specify the parts, or fields, of a code snippet that you can edit.
The <Literal> element has a boolean attribute named Editable that is used to specify whether the literal can be edited after insertion into your code. The Editable attribute defaults to true, so you can leave it out unless you want it set to false. The <Literal> element also has four child elements:
- The <Default> element is required and is used to specify the default value when code snippet is inserted.
- The <ID> element is also required and is used to specify a unique identifier for the literal.
- The <Function> element is optional, and since it is supported only in Visual C# and Visual J#, this article doesn't cover it.
- The <Tooltip> element is optional and, as one might expect, provides the expected value and usage of the literal in a tooltip.
The following is an example of the <Declarations> element:
<Declarations> <Literal> <ID>fileName</ID> <Tooltip>The String variable that stores the filename to be written to.</Tooltip> <Default>"TheFile.txt"</Default> </Literal> </Declarations>
The <Object> element is very similar to the <Literal> element. It has the same attribute and child elements. The <Object> element is used to identify items that are defined outside of the snippet itself, such as Windows Forms controls, ASP.NET controls, object instances, and type instances. The <Object> element has one additional child element, the <Type> element, which is used to specify the type of the object:
<Declarations> <Object> <ID>PrivateVariable</ID> <Type>Object</Type> <Tooltip>Replace this with the private variable name.</Tooltip> <Default>newPropertyValue</Default> </Object> </Declarations>
The final child element of the <Snippet> element is the <Code> element. The <Code> element specifies the code that is to be inserted by the snippet. It has just three attributes (Delimiter, Kind, and Language) and no child elements:
- The Delimiter attribute is optional and can be used to specify the delimiter used to describe literals and objects. The default delimiter is a "$".
- The Kind attribute is also optional and is used to specify the kind of code the snippet contains and where it can be inserted. The Kind attribute has six possible values: method body, method decl, type decl, page, file, and any. The default value is "any".
- The Language attribute is required and specifies which Visual Studio language can use the code snippet. It has four possible values: VB, CSharp, VJSharp, and XML.
All of the actual code to be inserted is placed inside of a <![CDATA]> element. The literal names enclosed within $ will become editable fields when the snippet is invoked:
<Code Language="VB" Kind="method body"> <![CDATA[My.Computer.FileSystem.WriteAllText($fileName$, $textContents$, $append$)]]> </Code>
Writing Your Snippet
First, insert the standard XML that begins the .snippet file:
<?xml version="1.0"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0">
Next, define your header. The <Title> element is the only child element that is required, but this example includes all of the child elements just to be complete:
<Header> <Author>Josh Fitzgerald</Author> <Description>A standard Function/Sub comment header</Description> <HelpUrl></HelpUrl> <Keywords> <Keyword>Comment</Keyword> <Keyword>Sub</Keyword> <Keyword>Function</Keyword> </Keywords> <Shortcut>cmt</Shortcut> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>Function/Sub Comment Header</Title> </Header>
Now comes the snippet code definition. First, begin the snippet using the <Snippet> element and then define your <Literal> elements. These will be the pieces of your comment header that will be editable by the user. You'll have a total of four fields, one each for the function/sub name, the function/sub description, the programmer name, and the date:
<Snippet> <Declarations> <Literal> <ID>Name</ID> <Tooltip>The name of the function/sub</Tooltip> <Default>Replace with the Function/Sub Name</Default> </Literal> <Literal> <ID>Description</ID> <Tooltip>A description of what actions the function/sub performs</Tooltip> <Default>Replace with a description of this function/sub/</Default> </Literal> <Literal> <ID>Programmer</ID> <Tooltip>The name of the programmer who created this function/sub</Tooltip> <Default>Replace with your name</Default> </Literal> <Literal> <ID>Date</ID> <Tooltip>The date this function/sub was created</Tooltip> <Default>Replace with the creation date YYYY-MM-DD format</Default> </Literal> </Declarations>
The last piece of your snippet file is the code definition. This is where you will define the format of your comment header and specify where the editable fields should be:
<Code Kind="any" Language="VB"> <![CDATA[' ------------------------------------------------------------------------ ' NAME : $Name$ ' DESCRIPTION : $Description$ ' PROGRAMMER : $Programmer$ ' DATE : $Date$ ' ------------------------------------------------------------------------------]]> </Code>
Finally, you insert the closing tags to finish up your snippet:
</Snippet> </CodeSnippet> </CodeSnippets>
Sharing Your Snippet
Once you've completed your snippet, you'll probably want to share it with your friends and co-workers. You could just email or give them a copy of the .snippet file, but then they would have to locate their snippet folders and manually copy the file.
Wouldn't it be nice if you could make a nice installer that would let them choose where to store the snippet and then copy it there for them? Well, actually, you can package your snippet for easier distribution. You can create a .vsi package (a .zip file with the extension renamed to .vsi) that contains one or more snippets. The .vsi file contains a .snippet file and a config file with a .vscontent extension. The .vscontent file is just an XML file that describes the contents of the .vsi package.
The .vscontent file for your .vsi package will look like this:
<VSContent xmlns="http://schemas.microsoft.com/developer/vscontent/2005"> <Content> <FileName>CommentHeader.snippet</FileName> <DisplayName>Function/Sub Comment Header</DisplayName> <FileContentType>Code Snippet</FileContentType> <ContentVersion>1.0</ContentVersion> <Attributes> <Attribute name="lang" value="vb"/> </Attributes> </Content> </VSContent>
With your two files, CommentHeader.snippet and CommentHeader.vscontent, in hand, you can create a standard .zip file containing them. Once you create the zip file, you just need to change the extension from .zip to .vsi.
The Snippet Editor mentioned earlier also will create .vsi files for you. All you have to do is select your snippet and click a button.
A Snippet in Time Saves...
You have explored the snippet format top to bottom. You've learned to build your own snippets and how to package them for easy distribution. Now, all that remains is to go forth and create all the snippets you can imagine.
Download the Code
To download the accompanying source code for the example, click here.
About the Author
Josh Fitzgerald is an applications development group leader for a large medical device company in Warsaw, Indiana. Designing and developing Visual Basic .NET applications is only one of his responsibilities, but it is his favorite part of his job. You can reach Josh at firstname.lastname@example.org.