Tuesday, August 10, 2010

How to use TextMate like snippets in vim?

SkyHi @ Tuesday, August 10, 2010

Snippet is a piece of text which can be pasted into the document. Parts of it can be parametrized or calculated while pasting. Snippets can increase your productivity by letting you to write common chunks of code faster and without mistakes. One of the most famous snippet implementations is included in TextMate editor. In vim we have some of TextMate's snippet features bundled in snipMate script.




Installation

Get snipMate from vim website and unpack it to your ~/.vim directory.

How does it work?

Basically you need to write a keyword (called trigger) and press the key to replace it with full snippet. For example typing 'for ' and pressing while editing a PHP file:

for

expands to:

for ($i=0; $i < count; $i++)
{
}

Pressing key continuously moves you to the next defined tab stop. In this case you are able to adapt all expressions in 'for' loop and the last moves you to the position inside it.

Creating custom snippets

SnipMate comes with many predefined snippets but once you start using it, you need more. Fortunately it's easy to extend. Snippets are stored in ~/.vim/snippets directory. I started with reviewing the existing ones and adapted them to my coding standards. While doing this I got the idea about the snippets' structure and started with creating my own ones.
vim html snippets
Snippets are grouped by the file type. It is specified by a prefix in the snippet file name or a directory it was placed in (php.snippets vs php/foreach.snippet). The first version lets you to keep all file type related snippets in one place. The later is used to split your snippets into separate files. Format is slightly different between these two, so to make it simple I'll stick to the first one.

To define a new PHP snippet which expands 'get' keyword into a getter method put the code below into your ~/.vim/snippets/php.snippets file:

snippet get
$this->get${1}();${2}

Note: Snippets are indented with hard tabs. First tab is not expanded in the actual snippet.

Our snippet is run by 'get' trigger and has two tab stops defined. Firstly cursor is placed after '$this->get' to let you fill the getter's name. Second tab moves the cursor after the completed statement.

Tab stops and placeholders

Tab stop is a place where cursor goes next after pressing key. The format is:

${1}

The number defines the order of navigation through the snippet.

Note: It's possible to go back to the previous position with +.

Tab stop can have a placeholder with default value:

${2:default}

Default value is pasted into the snippet. You can either change it or leave it by moving to the next position.

Placeholder's value can be copied throughout the snippet:

Value of ${1:value} is copied here: $1 and here: $1 and snippet ends here: ${2}

All occurrences of the $1 variable will be replaced by the provided value. It's also possible to use a variable in an another variable:

${3}

Once you fill in the id value, it is copied to the name attribute. However, you can still change it if you want.

Multiple matches

Sometimes its needed to have few versions of the snippet. Good example here is the PHP's foreach statement which I use at least in two variations:

  • in regular PHP code:
    foreach ($values as $key => $value)
    {
    // code here
    }
  • in templates:
     $value): ?>
    // code here

Taking into account that $key variable can be omitted, in fact I use four different variations of foreach statement. So I defined all four of them:

snippet fore value
foreach ($${1:variable} as $${2:value})
{
${3}
}

snippet fore key => value
foreach ($${1:variable} as $${2:key} => $${3:value})
{
${4}
}

snippet fore value (template)

${3}


snippet fore key => value (template)
$${3:value}): ?>
${4}

Once I run 'fore' trigger vim lets me to choose which version of snippet I would like to use.

vim multi choice snippet

Learn it

There are some things about snipMate I didn't mention. For more knowledge visit its homepage and read the documentation in ~/.vim/doc/snipMate.txt. There are also many snippets available on the Internet which are a good reference.

Make it your habit

Making usage of snippets a habit for sure will boost your productivity. To take full advantage of it you need to extend your snippet library. I think it's best to create a new snippet once you feel one is missing and directly start using it. Waiting till "next time" lasts through the eternity.

REFERENCES

http://www.zalas.eu/how-to-use-textmate-like-snippets-in-vim

http://www.zalas.eu/tag/vim

http://www.catonmat.net/blog/vim-plugins-snipmate-vim/