Search code examples
emacselispyasnippet

Emacs Yasnippet for Different Coding Styles


Just recently started using yasnippet for emacs and really like the way it works, however I've run into a minor nuisance I'd like some help to solve if possible.

One snippet I like in particular is the "for"-snippet, i.e.:

# -*- mode: snippet -*-
# name: for
# key: for
# --
for (${1:i = 0}; ${2:i < N}; ${3:i++}) {
    $0
}

However I recently started working on a project where we have a different coding style. Simply put the snippet above would be changed to place the starting brace position to:

# -*- mode: snippet -*-
# name: for
# key: for
# --
for (${1:i = 0}; ${2:i < N}; ${3:i++})
{
    $0
}

I would however like to easily switch between different projects and consequently between different coding styles without having to manually change the snippets or create many duplicates. So I figured it should be possible to write some elisp code in the snippet to automatically adapt to the currently active coding style.

Looking around at some of the Emacs/elisp documentation, I found the so called c-hanging-brace-alist (GNU doc) which I feel I should be able to use somehow. However I have never really done any programming in elisp, and I'm not really sure how to accomplish this. Any help or advice would be appreciated!


Solution

  • Here is a suggestion:

    1. Define a variable to hold the current coding style:

      (setq current-coding-style 'default)
      
    2. Define a command to toggle between the default style and the style used in your new project, and bind it to a key sequence of your choosing:

      (defun toggle-coding-style ()
        (interactive)
        (if (eq current-coding-style 'default)
            (setq current-coding-style 'special)
          (setq current-coding-style 'default)))
      
      (global-set-key (kbd "C-c t") 'toggle-coding-style) ;; Replace C-c t 
                                                          ;; with another binding
                                                          ;; if you like
      
    3. Define a function that places the opening brace according to the coding style that is currently "active":

      (defun place-brace ()
        (if (eq current-coding-style 'default) " {" "\n{"))
      
    4. Replace the opening brace in the for snippet with a call to this function (as explained here, arbitrary Elisp code can be embedded into snippets by enclosing it in backquotes):

      # -*- mode: snippet -*-
      # name: for
      # key: for
      # --
      for (${1:i = 0}; ${2:i < N}; ${3:i++})`(place-brace)`
          $0
      }
      

    With this in place all you need to do to switch between coding styles (and corresponding snippet expansions) is press C-c t.