Speed up development using keyboard-triggered snippets in Sublime Text 2

So I just installed the Sublime Text 2 beta on the promise of it being a much prettier and more usable Notepad++. So far, it's living up to my expectations, with one minor caveat that the documentation thus far is pretty uneven, and some of the most powerful features aren't well explained. To help fix that somewhat, I want to explain how you can go about creating snippets within Sublime Text, and then how to bind those snippets to a keyboard shortcut.

So what is a snippet? A snippet is a small piece of code that you re-use many times in a project. Some examples of snippets might be:

  1. A doxygen-esque comment block:
  2. A JavaScript for-loop:
  3. A C++ Class

Each of the above examples are similar to code that you might write 10, 20, or 100 times in a project. Rather than manually typing out all of that code each time, you can instead convert each one to a snippet and have a keyboard shortcut automatically insert the whole block of code into your document.

But what about the elements that you might want to change on a per-usage basis, like the the function description, class name, or the for-loop max value? Not to worry, there are several ways that we can make that data customizable too.

Let's get to it!

Create the new snippet

The first thing we'll need to do is create a new snippet. A snippet is just an XML file, so you could start fresh from a blank document if you wanted, but Sublime Text provides an easier way that pre-fills the file with a bunch of required scaffolding.

Select the Tools menu from the menu bar at the top of screen and choose the New Snippet... item. This will open a fresh document in a new tab and load it up with everything you need for a snippet.

There are three key pieces to the 'anatomy' of a snippet:

  1. Hello, ${1:this} is a ${2:snippet} This is the actual text that will be inserted into the document. There are some special characters and formatting in the default example that we'll talk about in the next section, but for now you should know that whatever you put in this section will be what's inserted into your document
  2. <!-- <tabTrigger>hello</tabTrigger> --> This is an optional configuration parameter that allows you to insert your snippet into a document by typing a certain set of characters and hitting the Tab key. This is commented out (and thus disabled) by default, but you can remove the '<!--' and '-->' to enable the functionality. The content inbetween the <tabTrigger> tags ("hello") is the phrase that Sublime Text will use to recognize where to insert your snippet. E.g., typing the characters "hello" (without the quotes) and hitting the Tab key will trigger your snippet.
  3. <!-- <scope>source.python</scope> --> This is also an optional configuration parameter that allows you to Sublime Text to only acknowledge the <tabTrigger> when in a certain context. The example provided would only permit the <tabTrigger> characters to trigger the snippet if you're currently editing a Python file. As a sidenote, this appears to be apply to any file identified by Sublime Text as a Python file, not just files with the .python extension. The same should be true of any other filetypes.

Save the file

Before we get going and customize our snippet, we should save it first.

Select the File menu and then the Save item, or press Ctrl+s on your keyboard.

A dialogue box will appear asking you to name the file. It's very important (and not readily documented) that your snippet must have the file extension '.sublime-snippet'. You can name the file anything you like, but it absolutely must end with '.sublime-snippet' in order for Sublime Text to recognize it as such. For now, call it myFunction.sublime-snippet.

Save the file in the default directory (which on Windows is the Application direction plus "/Packages/User"), which will make it easy to bind to a keyboard shortcut later on.

With the file saved, you should be able to test the <tabTrigger> functionality mentioned in the previous step. Try uncommenting the <tabTrigger> block and re-saving the file, then open a new document and type 'hello' followed by the Tab key. You should see the default text appear on the screen. If everything's working, re-comment the block since we won't be using it again.

Modify the snippet

Now that we know how a snippet file is organized, and ours is loaded properly in the system, let's get to the fun part and finally create our snippet. In this case, we want to create a snippet that allows the user to highlight a piece of text and use it as the name of an empty PHP function. So, if the user invoked the snippet after highlighting the text "myfunctionname", the result would be:

/**
  * My Function Description
  *
  * @return Array An array of numbers
  */
function my_function_name() {

}

To start, replace the Hello, ${1:this} is a ${2:snippet} text with the above function template.

Next, we need to replace the parts that should change each time the snippet is invoked (the function description, the @return info, the function name, and the final cursor position. How can we achieve that?

The developers of Sublime Text are using exactly the same syntax for snippet customization and replacement as the developers who created TextMate, and you can see the TextMate Snippet documentation here.

Rather than re-explain the fairly straightforward syntax myself, I'll post the final version of our snippet text below and indicate which parts of the TextMate documentation apply to each change.

/**
 * ${1:My Function Description}
 *
 * @return ${2:type} ${3:description}
 */
function ${$TM_SELECTED_TEXT:function_name}() {
  $0
}
  1. Line 2 uses a "Placeholder", as described in section 7.5 of the TextMate snippet documentation. This first item will be automatically "selected" after the snippet is inserted so that the developer can either type overtop of the default text ("My Function Description") or hit the Tab key to move the selection to the next placeholder. You can see the same behaviour twice in the fourth line of the snippet text (first for the return type, second for the return value description
  2. Line 6 uses the ${TM_SELECTED_TEXT:function_name} variable, which is explained in section 7.2 of the TextMate snippet docs. This variable is replaced with whatever the user highlighted when the snippet was invoked. If the user hasn't highlighted anything, the default string "function_name" is used instead.
  3. Line 7 uses the $0 tab stop as described by section 7.4 of the TextMate snippet docs to place the user's cursor inside of the function after the placeholders described above have all been replaced or tabbed through. This will make it easy for the user to quickly fill in the necessary parts of the function comment and then immediately proceed to the inner part of the function.

If you save the snippet now and try to invoke it using the <tabTrigger> command we used earlier, you should see our new function snippet in (almost) all its glory.

Only one issue remains: How can we highlight the text and then invoke the snippet?

We can't use the <tabTrigger> method because the text that we're trying to trigger on (the function name, in this case) will be different every time! We could presumably invoke the snippet by visiting the Tools menu and finding our snippet in the Snippets sub-menu (although at the time of this writing, the User sub-menu that houses our snippet is not displaying in my Snippets menu. Could be a bug with the Sublime Text 2 beta).

But we're trying to save time here, and navigating a series of menus is not exactly quick. So, instead, we'll bind our snippet to a keyboard shortcut.

Bind the snippet to a keyboard shortcut

What we need to do is specify a combination of keys that we'll use to trigger our snippet whenever we need it. For the purposes of our example, we'll use Ctrl + 1 to invoke the snippet.

To set the keyboard shortcut, we'll need to edit the key bindings file.

Select the "Preferences -> Key Bindings - User" menu item and paste the below text on a new line in between the square brackets

{ "keys": ["ctrl+1"], "command": "insert_snippet", "args": {"name": "Packages/User/myFunction.sublime-snippet"} }

This text is fairly straightforward, so I'll only briefly explain the key pieces below:

  1. "keys": ["ctrl+1"]. This defines the actual keys that will trigger the command that follows. Almost any combination of keys is valid here, so there should be lots of empty bindings that you can use.
  2. "command": "insertsnippet". This sets the command name to be triggered when the keys are pressed. In our case, we'll use the insertsnippet command to trigger our snippet.
  3. "args": {"name": "Packages/User/myFunction.sublime-snippet"}. This supplies any arguments to the command described above. For our purposes, we're passing it the name of the file (assigned to the "name" parameter) that contains our snippet. The path is relative to the Sublime Text installation directory.

For other examples (including different types of commands, limiting the shortcut to only work in specific contexts, etc.), see the default key bindings by visiting the "Preferences -> Key Bindings - Default" menu item.

Save the key-binding file, and your new snippet should be good to go.

Try it out, and let me know in the comments how it works for you!

Christopher Millward

Web engineer, lover of chiptunes, hobbyist game developer living in Ottawa, Ontario. @ChrisMillward


comments powered by Disqus