Exploring my Emacs packages - yasnippet

Project homepage : http://joaotavora.github.io/yasnippet/

yasnippet is a template expansion library for Emacs. It's a great way to quickly insert code without doing a lot of typing. For example:

Simple expansion example

yasnippet also supports user-entered variables in snippets. They look a little bit like this:

Snippet expansion with variables

Previous versions of the extension came bundled with snippets, but they are no longer included with the main package. The yasnippet-snippets repository on GitHub contains templates for over 50 major modes.

Basic snippet development

Every snippet is contained in a file of its own. To create a new snippet, call M-x yas-new-snippet to open a new buffer that is set up for snippet development. C-c C-c will save the new snippet.

The snippet code for the second screenshot looks like this:

# -*- mode: snippet -*-
# name: Wrap a helper or model
# key: wrap_helper
# group: templates
# --
protected function $1() {
	if ( empty( $this->$1 ) ) {
		$this->$1 = new ${2:ClassName}();
	}

	return $this->$1;
}
$0

The $1 and ${2:ClassName} are replaced by user input when the snippet is expanded. ClassName is inserted as a placeholder until replaced by the user.

Snippet files start with a small amount of metadata, most of which is for organization. There is also an optional condition field that executes elisp to check if the snippet should be expanded or not. This can be helpful to prevent snippet insertion in certain places.

Complex snippets using elisp

Snippets can also execute elisp code contained between ` characters. For example, the current time can be inserted in a template by using `(current-time-string)`.

It takes a little while to get the hang of, but it can be used for a lot of different things:

  • Inserting the name of the current file.
  • Transforming user input. This can be used to generate ID's.
  • Prompting for input from a set list of choices via yas-choose-value.
  • Using when and unless to insert additional content depending on user input.

A very simple example of when snippet logic looks a little like this:

# key: how_am_i
Current emotion: $1

${1:$(when (string= ":D" yas-text) "You are VERY happy")}
${1:$(when (string= ":)" yas-text) "You are happy")}
${1:$(when (string= ":(" yas-text) "You are sad")}

and does this:

Snippet expansion with elisp logic

By using embedded elisp, the original snippet from screenshot 2 can be changed to a single input that is formatted automatically:

# -*- mode: snippet -*-
# name: Wrap a helper or model
# key: wrap_helper
# group: template
# --
protected function ${1:$(string-inflection-underscore-function yas-text)} {
	if ( empty( $this->${1:$(string-inflection-underscore-function yas-text)} ) ) {
		$this->${1:$(string-inflection-underscore-function yas-text)} = new ${1:ClassName}();
	}

	return $this->${1:$(string-inflection-underscore-function yas-text)};
}
$0

The ClassName parameter (which can be accessed in elisp via yas-text) is automatically converted to underscores using string-inflection-underscore-function.

Snippet expansion with embedded elisp

There are also functions for working with regions, fields and user input. The yasnippet homepage contains a in-depth guide to snippet development along with a complete function reference.


This post is part of the "Exploring my Emacs packages" series.

Posted in: Emacs | Comments (0)

Post a comment

org-mode tags allowed: /italic/, *bold* and =code=