Skip to content

Latest commit

 

History

History
146 lines (125 loc) · 4.62 KB

starter-kit-yasnippet.org

File metadata and controls

146 lines (125 loc) · 4.62 KB

Starter Kit Yasnippet

This is part of the Emacs Starter Kit.

Starter Kit Yasnippet

yasnippet is yet another snippet expansion system for Emacs. It is inspired by TextMate’s templating syntax.

yas everywhere

;; Only use snippets distributed with the Starter Kit
(setq yas-snippet-dirs (expand-file-name "snippets" starter-kit-dir))
;; Auto indentation is too slow
(setq yas-indent-line 'fixed)
;; Don't re-activate snippet fields after undo/redo
(setq yas-snippet-revival nil)
;; so snippet can be triggered inside snippet
(setq yas-triggers-in-field t)
;; disable tab for `yas-minor-mode' and `yas-keymap' for that each mode has
;; its own tab
(with-eval-after-load 'yasnippet
  (require 'warnings)
  (add-to-list 'warning-suppress-types '(yasnippet backquote-change))
  (define-key yas-minor-mode-map (kbd "<tab>") nil)
  (define-key yas-minor-mode-map (kbd "TAB") nil)
  (define-key yas-keymap [(tab)] nil)
  (define-key yas-keymap (kbd "TAB") nil))
(yas-global-mode 1)

Snippet mode

Snippet for snippet

The original snippet for snippet is too long too ugly. What I want are only name and key directives.

(setq yas-new-snippet-default "\
# -*- coding: utf-8; mode: snippet; require-final-newline: nil -*-
# name: $1
# key: ${2:$1}
# --
$0")

Tab for snippet mode

(defun snippet-mode-setup ()
  (define-key yas-keymap (read-kbd-macro "TAB") 'yas-next-field))
(with-eval-after-load 'yasnippet
  (add-hook 'snippet-mode-hook 'snippet-mode-setup))

Configure Yasnippets for Org Mode

The latest version of yasnippets doesn’t play well with Org-mode, the following function allows these two to play nicely together.

(defun yas/org-expand-or-next-field ()
  (let ((yas-fallback-behavior 'return-nil))
    (cond ((and
            (not (evil-normal-state-p))
            (not (org-at-heading-p))
            (yas-expand)))
          ((yas--snippets-at-point)
           (yas-next-field)
           t))))

(defun yas/org-setup ()
  ;; yasnippet (using the new org-cycle hooks)
  (add-to-list 'org-tab-first-hook 'yas/org-expand-or-next-field))

(add-hook 'org-mode-hook #'yas/org-setup)

Use popup

(defun yas-popup-isearch-prompt (prompt choices &optional display-fn)
  (unless (featurep 'popup)
    (require 'popup))
  (popup-menu*
   (mapcar
    (lambda (choice)
      (popup-make-item
       (or (and display-fn (funcall display-fn choice))
           choice)
       :value choice))
    choices)
   :prompt prompt
   ;; start isearch mode immediately
   :isearch t))

(setq yas-prompt-functions
      '(yas-popup-isearch-prompt
        yas-no-prompt))

Combine yasnippet with auto insert

(setq-default auto-insert-query nil)
(setq-default auto-insert 'other)
(setq-default auto-insert-directory (expand-file-name "~/.emacs.d/autoinsert/"))

(defun my-autoinsert-yas-expand()
  "Replace text in yasnippet template."
  (yas-expand-snippet (buffer-string) (point-min) (point-max)))

(with-eval-after-load 'autoinsert
  (setq auto-insert-alist
        '((("\\.\\([Hh]\\|hh\\|hpp\\)\\'" . "C / C++ header")
           . ["template_h" c++-mode my-autoinsert-yas-expand])
          (("\\.tex\\'" . "TeX/LaTeX")
           . ["template_tex" my-autoinsert-yas-expand]))))

(defun lazy-load-auto-insert-mode ()
  (unless auto-insert-mode
    (auto-insert-mode 1)
    (remove-hook 'find-file-hook 'lazy-load-auto-insert-mode)))
(add-hook 'find-file-hook 'lazy-load-auto-insert-mode)

How to write snippets

Mirrors with transformation

Sometimes you want to determine content of a field according to content of another. The simple example is c header inclusion statement where system headers are quoted by <> while user headers are quoted by ””. In this case yas-text can be used to obtain the content of a mirror field.

#include ${1:`(yas-choose-value '("<" "\""))`}$0${1:$(yas-c-include-system-or-user yas-text)}

Note that:

  • The value of an ${n:$( means that it is interperted as a mirror for field n with a transformation.
  • For some reason yas-text should be the first argument of first lisp function.
  • yas-c-include-system-or-user is defined in .yas-setup.el in the snippets directory.