Snippets are small pieces of code that can be inserted via the completion box. Based on a trigger a piece of code is inserted that can have one or more areas that can be filled by the user using [TAB] to switch between them.

The following example shows a snippet that is triggered by typing ife[TAB].

snippet ife
	if (${1:true}) {
		${2}
	} else {
		${0}
	}

It inserts the if else construct and starts by selecting the word true. After changing that and pressing [TAB] the cursor moves to the body of the if. The last [TAB] will move the cursor to the body of the else.

Creating a Snippets File

Snippets work in a similar way as those for TextMate and Sublime Text

A snippets file is a collection of multiple snippets for a specific mode. It consists of a header with some meta data and a list of snippets below that. Currently, the only way to add custom snippets to a project is to create a plugin (as described here).

Header

The header specifies the scope for the snippets. The scope is a string that specifies the name of the mode to which these snippets are applied.

# scope: javascript

Use _ to specify snippets for all scopes. Use a comma separated list if these snippets apply to several modes.

Snippets

The rest of the file contains snippets. Snippets start with a list of variable definitions and then a list of lines that contain the code of the snippet itself.

# Comment
<field> <value>
<field> <value>
<tab>snippetcontents
<tab>snippetcontents
snippet ended

A file can contain any number of these underneath each other.

Creating a Snippet

Insertion Points

After inserting the snippet text the cursor will move to the first position after the inserted text, when there are no insertion points specified. Specifying insertion points using the $ character and a number to specify their sequence.

    ${1}
    ${2}
    etc

The ${0} insertion point is always last in line. You can specify the text that is selected when jumping from one insertion point to the next one.

    ${1:some_text}

In addition, it's possible to reuse the same variable multiple times. All instances will be selected using multiple cursors and changed at the same time when the user types.

    for (var ${1:i}=0; $1 < ${2}; $1++) {
        ${0}
    }

Using Special Variables

When triggering a snippet through a menu or command you can configure it to use the text selected prior to inserting the snippet in the resulting code.

	(function(${1}) {
		${0:${SELECTED_TEXT:/* code */}}
	}(${1}));

Similarly the following variables can be used to insert other special text.

CURRENT_WORDThe word at the cursor at the.
SELECTIONThe selected text.
SELECTED_TEXTThe selected text.
CURRENT_LINEThe current line.
PREV_LINEThe previous line.
LINE_INDEXThe index of the current line.
LINE_NUMBERThe line number (index + 1).
SOFT_TABS"YES" or "NO".
TAB_SIZEThe tab size.

Formatting Strings

Variables that are inserted can be formatted using the following command:

${«int»/«regexp»/«format»/«options»}

The following example comes from the markdown snippets and takes the contents of the previous line transforming each character into a =. That results in a line full of === exactly matching the length of the line above it.

snippet ===
regex /^/=+/=*//
	${PREV_LINE/./=/g}
	
	${0}

In addition the following characters can be used to toggle case.

\u uppercase next letter
\l lowercase  next letter
\U uppercase until \ULE
\E ends \U or \L

Triggers & Guards

The examples above used a simple string of characters to define how a snippet is triggered. The snippet definition allows for more control in triggering snippets, introducing two concepts; triggers and guards. Both have a beginning marker called trigger and guard and an end marker called endTrigger and endGuard. These are all optional.

Guards are pieces of a regular expression (regex) that define the context in which a trigger is allowed. Whatever is matched by a guard remains after insertion of the snippet - guards are not replaced.

Triggers are also pieces of a regex that define the start (before the cursor) and end (after the cursor) of the text that will be replaced by the snippet contents.

Lets start with a simple example.

snippet for

This can also be written like this.

guard \b
trigger for
endGuard
endTrigger

Of course since the endGuard and endTrigger are empty they can be left out.

Here's a more advanced example using a trigger to match (f(|) or f(|) or f(| where | is the cursor.

# Immediate function
trigger \(?f\(
endTrigger \)?
snippet f(
    (function(${1}) {
        ${0:${SELECTED_TEXT:/* code */}}
    }(${1}));

Using a RegEx

It's possible to replace the guards and trigger fields with a single regex that describes each.

This regex below matches the start of a line (allowing white spaces) as a guard. It then is triggered by the for characters and textafter after the cursor, requiring at least 1 white space character, guarding the end of the sequence.

regex /^\s*/for/textafter/\s+/

Use the regex capture groups to allow variables inserted in snippets. The captured items are available as variables M1, M2, etc.

${M1?$M1: ${1:functionName}} 

This allows you to create snippets with arguments; for 1 5| -> for (var i| = 1 i < 5; i++) {}. (| is the cursor again).

Scope

Finally it's possible to set a different scope for each snippet in a file, overwriting the main mode set in the header. Use the scope variable to do this.

scope markdown

Adding Snippets to a Bundle

A bundle can contain one or more snippet files. Each snippet file must be placed in the snippets directory.

Suppose your snippets file is called markdown.snippets. Your file structure will look something like this:

└─ your.plugin
    ├─ snippets
    |    └─ markdown.snippets
    ├─ package.json
    └─ README.md

Using snippets inside a project

To load the snippets you created inside a project, add it's name to the `package.json.

package.json

{
  "name":"your.plugin",
  "plugins": {}
}

Then open the init script from the cloud9 menu and add your.plugin to the plugins loaded at startup.

  services.pluginManager.loadPackage([
      "~/.c9/plugins/your.plugin/package.json"
  ])