Tweaking Emacs: Snippets

Using snippets with Emacs has dramatically increased my productivity. I’m using YASnippet, and am thoroughly impressed by it.

Setup is easy, so I won’t repeat that here.

I put my own snippets in ~/.emacs.d/lisp/yasnippets/snippets/java-mode and …/ruby-mode, and you can see them here.

The obvious benefit with snippets is their brevity, usually replacing unnecessary or redundant boilerplate code, such as this one for creating a list in Java:

# name : List<String> list = new ArrayList<String>();
# key: list
# --
List<${1:String}> ${2:list} = new ArrayList<$1>();$0

So creating a list of Integers, named “numbers” is done with “listIntegernumbers”.

Naturally, since this is Emacs, there is a real programming language available for use, so snippets can call Emacs Lisp code, such as this for creating a constructor in Java, which assumes the constructor name is the basename of the current file:

# name: constructor
# contributor:
# key: init
# --
public `(file-name-nondirectory
	  (or (buffer-file-name)
	   (buffer-name (current-buffer)))))`($1) {

This is simply applying the principle of automating work as much as possible. In the words of Larry Wall: “The computer should be doing the hard work. That’s what it’s paid to do, after all.”

There are two other aspects about using snippets that I think are overlooked. At least I hadn’t expected them when I began using snippets.

The first is that snippets can essentially provide their own documentation. That is, the syntax ${1:String} above means that the default text “String” will be displayed, until and unless the programmer overwrites it with the different variable type. This is especially beneficial for what often confuses me, the order of the iterated variable, and the accumulator variable (injection below, and I’ve also seen it called memo).

With snippets, the default text describes the variable functionality. Voila and viola, no more confusion:

# name: inject(...) { |...| ... }
# key: inject
# --
inject(${1:0}) { |${2:injection}, ${3:element}| $0 }

The third benefit of snippets is that they add consistency across programming languages. My two primary languages are Java and Ruby (day job, night job), and I’ve added snippets to Java and Ruby mode for common functionality. For example, the Java snippet “constructor” above has the shortcut “init”, as does my snippet for Ruby mode:

# name : initialize
# key: init
# --
def initialize $1

Thus when I’m writing a constructor in either language, all I need to type is “init”. I’ve done the same for initializing instance variables with the same name as a constructor parameter, these two “svar” snippets (“svar” == “set variable”):

# name : set_variable
# key: svar
# --
@$1 = $1
# name : set instance variable
# key: svar
# --
this.$1 = $1;

What drove me somewhat crazy when editing snippets was that Emacs defaults to adding a final newline at the end of a buffer when saving it. Thus when I used one of my snippets, an extra line would be added. (For some snippets, I do want a newline, such as shortcuts for adding methods and constructors, which should be separated from other methods by a blank line.)

I knew of one solution, changing mode-require-final-newline to nil, but I didn’t want to change the global settings. I figured that YASnippet might have its own mode for editing snippets, and indeed it does, and even better, in that mode, a final newline isn’t written.

I set snippet-mode for my snippets with this:

(add-to-list 'auto-mode-alist '("\\.emacs.d/lisp/yasnippet/snippets" . snippet-mode))

Please do yourself a favor and check out YASnippet.


2 thoughts on “Tweaking Emacs: Snippets

  1. I’ve been using YASnippet a lot lately but it never “clicked” to include Lisp code into the snippet itself. That is a very cool tip.

    • Many thanks for your comment.

      That snippet was copied from the near-equivalent in Ruby-mode, by, in the “cls” snippet.

      As a follow-up to my post, I realized that I didn’t mention my surprise that there are no Java snippets in the Github project at YASnippet, and that I plan to mirror/copy (as I did with init) as many similar Java/Ruby idioms as I can find, and add them here.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s