Crank Out Boiler Plate Code Like a Boss with YASnippet

Let me explain the above demo.

I sometimes work in Angular which happens to have a moderate amount of boiler plate code. For example, creating a new component means importing the Component decorator, passing in a config object with metadata to the component decorator and then exporting the class so it can be imported elsewhere.

In this example, I just type comp followed by M-/ to expand out the component (I’m using Spacemacs. In Emacs, use TAB to expand). The cursor is automically dropped at the position where I need to name the component’s selector (line 4). As I type the selector name, it is copied and appended styleUrls file name (line 5), as well as camel cased on the export line (line 8). When done with the selector name, I hit TAB which places me on line 6 where I can add the template. Now I am ready to build my component. Let’s see how this works.

Since I’m using Spacemacs my examples use SPC SPC , which for emacs is M-x .

Creating a Snippet

Where are snippets stored?

First a quick note on where snippets are stored. When you save a YASnippet, it’s going to be placed in ~/.emacs.d/private/snippets/ in a sub directory that corresponds to the mode the snippet is for. For exmaple, the Typescript snippet in the demo above is in .emacs.d/private/snippets/typescript/ .

Just remember that the stuff you put in the .emacs.d/private is git ignored. I like to manage this folder the way I do with my dotfiles so they get are added to version control.

Create the template

I like to start in the file type of the mode for which I am building the snippet (in this case a .ts file). That way the snippet will automically be placed in the right mode directory. For me, this happens naturally because I usually get inspired to make a snippet while coding.

SPC SPC yas-new-snippet creates a new empty snippet that looks like this:

1 2 3 4 # -*- mode: snippet -*- # name: Angular component # key: comp # --

name is the description of the snippet - usefull when listing snippets with SPC i s .

is the description of the snippet - usefull when listing snippets with . key is the string you want to type that will be expanded with M-/

is the string you want to type that will be expanded with everthing below the metadata block (line 4) is where you write the snippet.

Here is a an simple example snippet that justs adds a Angular component import line:

1 2 3 4 5 # -*- mode: snippet -*- # name: Angular component # key: comp # -- import { Component } from '@angular/core ' ;

When your finished with the snippet, just SPC f s to save it in the .emacs.d/private/snippets/ directory. Recall from above that it should go in a subfolder that is the name of mode.

Using Tabstops

But why stop there? Let’s scaffold an entire Angular component and drop the cursor at locations where we need to make edits. Use $ followed by a number. After expanding the snippet, the cursor is placed at $1 . Pressing TAB takes the cursor to $2 . TAB again and go to $3 , etc. $0 is the last stop, which also exits the snippet mode.

Exapanding on the previous example:

1 2 3 4 5 6 7 8 9 10 11 12 13 # -*- mode: snippet -*- # name: Angular component # key: comp # -- import { Component } from '@angular/core ' ; @Component ( { selector: 'app-$2', styleUrls: [ '$3.component.scss'], $0 } ) export class $1Component {}

After we expand the snippet, in order as we TAB through:

Start by naming the exported class (line 13) name the selector (line 8) finish the stylesheet file name (line 9) exit inside the config object where we’re likely to start the componet’s template (line 10).

Mirrors and text transformations

If we follow certain naming convetions, we might end up typing the same thing several times in the above example. We can use mirrors and text transformations to save us the hassle. A field like $1 can be repeated in the template where what we type at that tabstop will also be inserted at another locations. We can also use Elisp to perform text transformations on the mirrors - like upcasing, capitalizing, etc.

Here is the snippet that I used to make the Angular component in the animated gif at the start of this post.

1 2 3 4 5 6 7 8 9 10 11 12 13 # -*- mode: snippet -*- # name: Angular component # key: comp # -- import { Component } from '@angular/core ' ; @Component ( { selector: 'app-$1', styleUrls: [ '$1.component.scss'], $0 } ) export class ${1:$ ( replace-regexp-in-string "-" "" ( capitalize yas-text )) }Component {}

Now all we need to do is type the selector name at the first $1 and TAB out to the exit point. The following now happens automatically:

the name is copied to the styleUrls

the name is copied to the class name. the class name is using a tabstop with a placeholder the syntax of which looks like this: %{N:placeholder_value}

The class name, represented by yas-text is transformed from kebab case to camel case using a bit of Elisp.

Conclusion

YASnippet is great to cranking out boiler plates or code that is strucurally predictive by virture of following convetions. It’s highly customizable with tabstops, mirros and transformations.

The is by no means at all exhaustive. There’s a lot more you can do with YASnippet. Check out the resouces below to learn more.

Resources

Lean more with these awesome resources!