Telerik blogs

I recently blogged about using code snippets as a shortcut to writing more code in less time. In this post, I'm going to walk you through the steps to create custom snippets that you can install into Visual Studio for use in your own projects

To get started, let's take a look at the anatomy of a snippet. A snippet is nothing more than an XML file, with a .snippet extension, containing configuration settings. If you open up the file foreach.snippet (located in "<Visual Studio installation directory>\VC#\Snippets\1033\Visual C#") you'll find the following XML, which defines the foreach snippet:

1

As you can see, the XML used to define the snippet is fairly straight-forward. I'll go over it section by section and explain how each setting is used.

Anatomy of a Code Snippet

After the XML declaration element, a <CodeSnippets> element acts as the root element and contains all the code snippet definitions in the file. While there can certainly be more than one snippet per file, it is usually considered good practice to only define one snippet per file. The parent <CodeSnippets> element also contains a namespace definition, http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet, which is required if you want Visual Studio intellisense when designing your own code snippets.

2

Inside the <CodeSnippets> element, each snippet is defined by its own <CodeSnippet> element. This element contains a Format attribute, which is used to define the version of snippet. While the version of the snippet is up to the developer, the Format attribute is required.

3

Each <CodeSnippet> element contains two inner elements, <Header> and <Snippet>. The <Header> element contains all of the snippet's details, such as title, description, author, etc. The <Snippet> element contains the literal, references, and code definitions.

4

The <Header> element contains any or all of the following elements:

  • <Title>: Contains the title of the snippet. This element is required.
  • <Shortcut>: The shortcut by which the snippet can be inserted in Visual Studio. This shortcut appears in Visual Studio's intellisense. This element is not required, but the code snippet will not appear in intellisense if it is not defined.
  • <Description>: A brief description of the snippet's purpose.
  • <Author>: The author of the code snippet.
  • <SnippetTypes>: Contains a collection of <SnippetType> elements, each of which describes how the snippet is inserted into the code. A <SnippetType> element is not required, and leaving it out will cause Visual Studio to insert the code snippet wherever the cursor is. When used, this element can have the following values:
    • Expansion: Allows the code snippet to be inserted at the cursor.
    • SurroundsWith: Allows the code snippet to be placed around a selected piece of code.
    • Refactoring: This SnippetType specifies that the code snippet is used during refactoring. However, it cannot be used in custom code snippets.
  • <Keywords>: Contains a list of <Keyword> elements, each of which represent a standard way for online content providers to add custom keywords for searching and categorization.
  • <HelpUrl>: A URL that provides information about the snippet.

5

The <Snippet> element contains any or all of the following elements:

  • <Code>: Specifies the parameterized code template that you want to insert into your source file. This element is required, and can contain the following attributes:
    • Language: Specifies the language of the snippet. This attribute is required and can have the following values: VB, CSharp, or XML.
    • Delimiter: Specifies the delimiter used to describe literals and objects in code. By default, the delimiter is $. As you will see, when defining a <Literal> element in the <Declarations> block, it will search through all code in the <Code> element and replace anything containing the literal's id, surrounded by the delimiter, defined here.
    • Kind: Specifies the kind of code the snippet contains, which indicates where the snippet must be inserted. This attribute can have the following values:
      • method body: Specifies that the code snippet is a method body, and therefore, must be inserted inside a method declaration.
      • method decl: Specifies that the code snippet is a method, and therefore, must be inserted inside a class or module.
      • type decl: Specifies that the code snippet is a type, and therefore, must be inserted inside a class, module, or namespace.
      • file: Specifies that the snippet is a full code file. These code snippets can be inserted alone into a code file, or inside a namespace.
      • any: Specifies that the snippet can be inserted anywhere.
  • <Declarations>: Specifies the literals and objects that make up the parts of a code snippet that you can edit when it inserted into your source file. Can contain the following elements:
    • <Literal>: Identifies a replacement for a piece of code that is contained entirely within the snippet, but will probably be changed after the snippet is inserted into code. The literal end ($end$) is reserved, and is used to mark where the cursor should be placed after the code snippet is inserted. Can contain the following elements:
      • <ID>: A unique identifier for the literal. This is a required element.
      • <Tooltip>: Described how the literal should be used.
      • <Function>: Specifies a function to execute when the literal receives focus in Visual Studio.
      • <Default>: The literal's default value when the code snippet is inserted. This is a required element.
    • <Object>: Identifies an item that is required by the code snippet but will likely be defined outside of the snippet. Can contain the following elements:
      • <ID>: A unique identifier for the object. This is a required element.
      • <Type>: Specifies the type of the object. This is a required element.
      • <Function>: Specifies a function to execute when the object receives focus in Visual Studio.
      • <Tooltip>: Described how the object should be used.
      • <Default>: The object's default value when the code snippet is inserted. This is a required element.
  • <Imports>: Contains a collection of <Import> elements, each of which declares a namespace which must be imported. The <Imports> element is used for Visual Basic snippets only. Each <Import> element can contain the following element:
    • <Namespace>: Specifies the namespace used by the code snippet. This element is required.
  • <References>: Contains a collection of <Reference> elements, each of which specifies information about the assembly references required by the code project. Each <Reference> element can contain the following elements:
    • <Assembly>: Contains the name of the assembly referenced by the code snippet. This element is required.
    • <Url>: Contains a URL that provides more information about the referenced assembly.

6

Creating a Custom Code Snippet

By way of example, let's create a code snippet which checks the existence of a query string on an ASP.NET page, and redirects a user if the query string does not exist. When designing ASP.NET pages, I often use this piece of code when the page is displaying some sort of data and requires a query string with a value which is used to look up the data in a database. Since I use the same block of code often, having it as a snippet will save me some time when I need to use it in the future.

For starters, let's see how the code should look. I want it to first check if a particular element in the Request.QueryString collection contains a value. If it is null or empty, I want to redirect the user to another page. Here is the code I want to implement:

14

Now that we know what code we want, we need to determine which pieces of the code are dynamic. That is, which parts of the code can change each time we insert it into a file. In this code block, the only elements that will change are the string literals inside the Request.QueryString indexer and the Response.Redirect method. We will need to define these two items as Literals in our code snippet.

Once we know the basic requirements for our snippet, we can go ahead and create a new snippet file. In Visual Studio, click File | New | File..., select Xml File, and click Open. (Note: you do not have to have a project or solution open, nor do you have to close out of an open project or solution, to create a new snippet)

7

Once the new XML file has opened in the IDE, we want to save it with a .snippet extension, so click File | Save <XML Filename>.xml As... and enter a new name for the snippet. I am going to call this one querystring. Choose the .snippet file extension from the Save as type: drop down list and click Save.

8

Now in our querystring.snippet file we should have nothing more than an XML declaration. First we'll go ahead and add the basic structure to our snippet with the following XML elements:

9

Since this is our first crack at the new snippet, we'll keep the default version by leaving Format's value at 1.0.0. Next we'll add some basic information to our header. We will give the <Title> and <Shortcut> elements a value of querystring, then we'll add a description and author as well. Finally, let's add a single <SnippetType> of Expansion. Remember that this <SnippetType> causes the snippet to be inserted at the current cursor position.

10

Next we will define the elements in our <Snippet> element. We'll first need to declare two <Literal> elements in the <Declarations> section which will define the two dynamic pieces of our snippet. We'll call the first querystring, since it will be used to define the name of the query string our code will check for, and we will give it a default value of id. The second <Literal> will be called page, since it will be used to define the name of the page we will redirect users to if the query string doesn't exist, and we'll give it a default value of Default.aspx. Finally, we'll add the code block itself within the <Code> element. This element must have a Language attribute with a value of csharp, and its contents will be embedded in a CDATA element. The code is wrapped in this element in case its content breaks the structure of the XML document.

11

And here is what our finalized code snippet looks like:

12

The Code Snippets Manager

To insert the newly created code snippet, we can use Visual Studio's Code Snippets Manager. To open the manager, click Tools | Code Snippets Manager or type Ctrl + K, Ctrl + B. In the manager, snippets are separated by language, and then further by category. Notice the Location bar near the top of the window. This shows the location where each snippet can be found, allowing users to navigate to and edit pre-installed snippets themselves. As you can see, there are tons of snippets built in to Visual Studio right out of the box.

15

You can add a folder to hold your own snippets by clicking the Add... button and selecting the folder of your choice. This folder will then appear in the Code Snippets Manager and can be used to store imported snippets. To import your code snippet, make sure the correct Language is selected, then click the Import... button. Navigate to the location of your .snippet file, highlight it, and hit the Open button. A new window will appear, asking you to select the folder into which the snippet should be imported.

16

Choose an existing folder, or a folder you have created on your own, and click Finish. Congratulations! You have created your first code snippet. You can now try it out by simply typing its shortcut in your code and selecting it from the intellisense menu.

17

18


About the Author

Kevin Babcock

Kevin Babcock

Comments

Comments are disabled in preview mode.