This is part of the Emacs Starter Kit.
yasnippet is yet another snippet expansion system for Emacs. It is inspired by TextMate’s templating syntax.
- watch the video on YouTube
- see the intro and tutorial
;; 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)
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")
(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))
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)
(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))
(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)
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.