1. Improving Python Development in Emacs with YASnippet

    Sun 2013-03-31 10:31

    Kurt Schwehr just showed me how he uses the YASnippet template system to improve his productivity in Emacs. This seems like a really great tool.

    Here's an example. With YASnippet installed, if you're editing a Python file in Emacs and you type the word class then hit [TAB], it will expand to the skeleton of a Python class definition:

    class ClassName(object):
        """
        """
    
        def __init__(self, ):
            """
            """
    

    That's not all. After expansion, your cursor is left sitting on ClassName so you can immediately edit the class name to what you want, and each time you hit [TAB] after that, it will advance the cursor to logical edit points, skipping over the boilerplate pieces you wouldn't want to change. Some snippets also call out to other Emacs functions to do things like auto-fill a current timestamp.

    YASnippet is not just for Python. You can define mode-specific snippets for any mode. YASnippet ships with a few pre-defined snippets for several modes, including the class snippet for Python mode that we just used.

    If you're interested in using YASnippet, here's the basic process for setting it up:

    • Install YASnippet
    • Try out its pre-defined snippets in your favorite Emacs mode
    • Look around the web for additional snippet collections specific to your needs
    • Write your own snippets

    Let's go through the specifics of setting up YASnippet for Python/Django development. First grab the library.

    cd ~/.emacs.d/plugins
    git clone https://github.com/capitaomorte/yasnippet.git
    

    Then add this to your ~/.emacs init file.

    (add-to-list 'load-path
                  "~/.emacs.d/plugins/yasnippet")
    (require 'yasnippet)
    (setq yas-snippet-dirs
          '("~/.emacs.d/plugins/yasnippet/snippets"))
    (yas-global-mode 1)
    

    (Note: You may want to compare this with the latest version of the YASnippet README in case the init file setup directions have changed. I had trouble at first due to version skew with old init file examples.)

    At this point you can fire up Emacs and try out the class tab-completion example above. Now let's add an additional snippet collection for Python/Django development.

    cd ~/lib/elisp
    git clone https://github.com/gabrielelanaro/emacs-for-python.git
    

    The emacs-for-python package is an enormous kitchen sink of every possible Python/Emacs tool you could think of. I've barely scratched the surface of what's in there. But for now we're just interested in its snippet collection. To tell YASnippet how to find the new collection, edit your init file:

    (setq yas-snippet-dirs
          '("~/lib/elisp/emacs-for-python/snippets/django"
            "~/.emacs.d/plugins/yasnippet/snippets")
    

    This gives us a bunch of snippets for Django, like model in Python mode and block in HTML mode (for editing Django templates).

    Finally, let's set up a trivial snippet of our own just to see how it's done. We'll keep our own personal snippet collection in the suggested location ~/.emacs.d/snippets. Edit your init file:

    (setq yas-snippet-dirs
          '("~/.emacs.d/snippets"
            "~/lib/elisp/emacs-for-python/snippets/django"
            "~/.emacs.d/plugins/yasnippet/snippets")
    

    Notice our personal snippets area is first in the list. Order is significant--this way you can override a built-in snippet by defining a personal snippet with the same name.

    Our trivial example snippet will expand foo into foobar in Python mode. To set it up, create the file ~/.emacs.d/snippets/python-mode/foo with these contents:

    # -*- mode: snippet -*-
    # name: foo
    # key: foo
    # --
    foobar
    

    To test it out, restart Emacs, edit a Python file, type foo and hit [TAB]. You should be good to go. If you'd like to make more interesting snippets, you can model them on examples from one of the existing snippet collections. Have fun!