Yet another snippet mode for Emacs

While reading gnu.emacs.help, I came across yasnippet (yet another snippet extension for Emacs). It provides interactive templates for text or code entry. It’s similar to SkeletonMode, but with TextMate-type syntax, simpler prompting for information, and more focus on expanding mode-sensitive text in the buffer.

Here’s what I did to get started with it on my system:

  1. Download http://yasnippet.googlecode.com/files/yasnippet-0.5.5.tar.bz2 and unpack it as ~/elisp/snippets.
  2. Download http://yasnippet.googlecode.com/files/yasnippet-bundle-0.5.5.el.tgz and unpack it as ~/elisp/yasnippet-bundle.el .
  3. Symlink lisp-interaction-mode to emacs-lisp-mode with the command
    ln -s ~/elisp/snippets/emacs-lisp-mode ~/elisp/snippets/lisp-interaction-mode
    
  4. Add the following lines to ~/.emacs
    (require 'yasnippet-bundle)
    (yas/initialize)
    (yas/load-directory "~/elisp/snippets")
    ;; I don't like using partial words for completion
    (setq yas/key-syntaxes '("w_" "w_." "^ "))
    

So far, so good. M-x yas/minor-mode lets me use TAB as the completion key, and I can use TAB and S-TAB to navigate between the fields of a snippet as well. I think it’s a decent snippets mode if you don’t need the complexity of skeleton.el.

After some experimentation, I see how this might make me even happier working on Drupal. I’ve put together this first try at a template for Drupal modules. Drupal code has a lot of repetitive typing and/or search-and-replacing because all the hook functions need to start with the module name. With yasnippet, I can type in the module name once, and all the other functions will be updated. I often find myself looking up the argument lists for the hook functions, too, and the template includes the hooks I tend to use. I think this snippet will save me a lot of start-up time.

You know what would be even cooler? If I could create snippets that dynamically calculate values using Emacs Lisp. Then I could create, for example, a hook_user abbreviation that automatically picked up the module name from the filename or from the other functions. Wouldn’t that be cool?

UPDATE: Putting Emacs Lisp in templates is awesome. With this function in my ~/.emacs:

(defun sacha/drupal-module-name ()
  "Return the Drupal module name for .module and .install files."
  (file-name-sans-extension (file-name-nondirectory (buffer-file-name))))

I can make templates like this one for hook_user. Sweet!

2 Pingbacks/Trackbacks

  • weber

    yasnippet supports embedded elisp. I do that for using the current buffer name to declare a “class function” in lua.

    see here:
    http://code.google.com/p/yasnippet/wiki/HowtoDefineSnippet

  • http://sachachua.com Sacha Chua

    That makes me so happy. =)

  • http://denoted.dyndns.org/ploidy/ shadytrees

    I think you have error with the right parentheses with “${1:module)” in the Drupal module snippets file.

  • http://www.sethmason.com seth

    Yeah, yasnippet rocks. Between it and js2-mode, coding javascript is almost dreamy.

    Have you gotten it to work with org-mode though? The way org-mode redefines the TAB keys seems to screw with yasnippet in ways that I couldn’t figure out with my weak emacs-lisp fu.

  • Robert

    What I’d love to know is how one chooses a single template mode to commit to. I’m shopping because I’ve used tempo mode heavily in the past and it seems to doubleplus unwork on Aquamacs.

    So how does one sift through all the snippet modes?

    Thanks!

  • http://www.jeffstautz.com Jeff

    @seth:

    Yeah, I’m having the same issue using YAsnippet in org-mode. When I do a C-h k , it looks like Tab is bound to org-cycle, no matter what I do. YAsnippet is definitely running as a minor mode, but org seems to be hogging the tab key.

    Sacha, have you had any luck using YAsnippet in org-mode?

    –Jeff

    • http://sachachua.com Sacha Chua

      It might be a good idea to bind yas/expand to a different key, then… =) Maybe M-?, to make it like an enhanced version of M-/ (dabbrev-expand)?

      • http://www.jeffstautz.com Jeff

        Thanks for the suggestion, Sacha. Luckily I didn’t need to use that workaround. Here’s the fix:


        (add-hook 'org-mode-hook
        '(lambda ()
        (make-variable-buffer-local 'yas/trigger-key)
        (setq yas/trigger-key [tab])))

        Worked perfectly for me…

        –Jeff

  • http://alexott.blogspot.com Alex Ott

    i’m currently using msf-abbrevs mode – it also supports asking for parameters, mode-dependent snippets, and so on – but it much simple from my point of view

  • Pingback: Drupal, Emacs, and templates: Module update functions | sacha chua :: enterprise 2.0 consultant, storyteller, geek

  • Pingback: things to look at (November 20th - November 24th) | stimulant - changing things around. . .

  • http://www.judahshkye.com/ John Storey

    Sacha,

    The Drupal module example did not use mirroring in the YASnippet template to minimize typing. I made a quick change and posted it to my blog here.

    It’s almost identical to your original version, but now you can type the module name once and all the hook implementations are changed to the correct value.

  • Bao Haojun

    Sacha,

    I have wrote a more free-style completion script, skeleton-complete.el, could you please try it?