mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 21:13:04 +00:00
* Redesigned directory-guessing mechanism, but kept backward
compatibility * A mode can now have multiple parent modes using a hidden ".yas-parents" file. * Fixed issue 70. * Removed a useless condition-case. * More fixes
This commit is contained in:
parent
ad3c307bbc
commit
d42e5a3189
392
yasnippet.el
392
yasnippet.el
@ -44,6 +44,23 @@
|
|||||||
;; Steps 4. and 5. are optional, you don't have to use the minor
|
;; Steps 4. and 5. are optional, you don't have to use the minor
|
||||||
;; mode to use YASnippet.
|
;; mode to use YASnippet.
|
||||||
;;
|
;;
|
||||||
|
;; Interesting variables are:
|
||||||
|
;;
|
||||||
|
;; `yas/root-directory'
|
||||||
|
;;
|
||||||
|
;; The directory where user-created snippets are to be
|
||||||
|
;; stored. Can also be a list of directories that
|
||||||
|
;; `yas/reload-all' will use for bulk-reloading snippets. In
|
||||||
|
;; that case the first directory the default for storing new
|
||||||
|
;; snippets.
|
||||||
|
;;
|
||||||
|
;; `yas/mode-symbol'
|
||||||
|
;;
|
||||||
|
;; A local variable that you can set in a hook to override
|
||||||
|
;; snippet-lookup based on major mode. It is a a symbol (or
|
||||||
|
;; list of symbols) that correspond to subdirectories of
|
||||||
|
;; `yas/root-directory' and is used for deciding which
|
||||||
|
;; snippets to consider for the active buffer.
|
||||||
;;
|
;;
|
||||||
;; Major commands are:
|
;; Major commands are:
|
||||||
;;
|
;;
|
||||||
@ -65,8 +82,9 @@
|
|||||||
;;
|
;;
|
||||||
;; M-x yas/find-snippets
|
;; M-x yas/find-snippets
|
||||||
;;
|
;;
|
||||||
;; Lets you find the snippet file in the directory the
|
;; Lets you find the snippet files in the correct
|
||||||
;; snippet was loaded from (if it exists) like
|
;; subdirectory of `yas/root-directory', according to the
|
||||||
|
;; active major mode (if it exists) like
|
||||||
;; `find-file-other-window'.
|
;; `find-file-other-window'.
|
||||||
;;
|
;;
|
||||||
;; M-x yas/visit-snippet-file
|
;; M-x yas/visit-snippet-file
|
||||||
@ -76,6 +94,12 @@
|
|||||||
;; you directly to the snippet definition's file, if it
|
;; you directly to the snippet definition's file, if it
|
||||||
;; exists.
|
;; exists.
|
||||||
;;
|
;;
|
||||||
|
;; M-x yas/new-snippet
|
||||||
|
;;
|
||||||
|
;; Lets you create a new snippet file in the correct
|
||||||
|
;; subdirectory of `yas/root-directory', according to the
|
||||||
|
;; active major mode
|
||||||
|
;;
|
||||||
;; M-x yas/load-snippet-buffer
|
;; M-x yas/load-snippet-buffer
|
||||||
;;
|
;;
|
||||||
;; When editing a snippet, this loads the snippet. This is
|
;; When editing a snippet, this loads the snippet. This is
|
||||||
@ -121,7 +145,11 @@
|
|||||||
(defcustom yas/root-directory nil
|
(defcustom yas/root-directory nil
|
||||||
"Root directory that stores the snippets for each major mode.
|
"Root directory that stores the snippets for each major mode.
|
||||||
|
|
||||||
Can also be a list of strings, for multiple root directories."
|
Can also be a list of strings, for multiple root directories. If
|
||||||
|
you make this a list, the first element is always the
|
||||||
|
user-created snippets directory. Other directories are used for
|
||||||
|
bulk reloading of all snippets using `yas/reload-all'"
|
||||||
|
|
||||||
:type '(string)
|
:type '(string)
|
||||||
:group 'yasnippet)
|
:group 'yasnippet)
|
||||||
|
|
||||||
@ -220,10 +248,21 @@ to expand.
|
|||||||
:group 'yasnippet)
|
:group 'yasnippet)
|
||||||
|
|
||||||
(defcustom yas/choose-keys-first t
|
(defcustom yas/choose-keys-first t
|
||||||
"If non-nil, `yas/insert-snippet' prompts for key, then for template.
|
"If non-nil, prompts for key first, then for template if more than one.
|
||||||
|
|
||||||
Otherwise `yas/insert-snippet' prompts for all possible
|
Otherwise prompts for all possible templates
|
||||||
templates and inserts the selected one."
|
|
||||||
|
This affects `yas/insert-snippet' and `yas/visit-snippet-file'."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'yasnippet)
|
||||||
|
|
||||||
|
(defcustom yas/choose-tables-first nil
|
||||||
|
"If non-nil, and multiple eligible snippet tables, prompts user for tables first.
|
||||||
|
|
||||||
|
Otherwise, user chooses between the merging together of all
|
||||||
|
eligible tables.
|
||||||
|
|
||||||
|
This affects `yas/insert-snippet', `yas/visit-snippet-file'"
|
||||||
:type 'boolean
|
:type 'boolean
|
||||||
:group 'yasnippet)
|
:group 'yasnippet)
|
||||||
|
|
||||||
@ -240,21 +279,6 @@ mode will be listed under the menu \"yasnippet\"."
|
|||||||
:type 'string
|
:type 'string
|
||||||
:group 'yasnippet)
|
:group 'yasnippet)
|
||||||
|
|
||||||
(defcustom yas/show-all-modes-in-menu nil
|
|
||||||
"Display \"artificial\" major modes in menu bar as well.
|
|
||||||
|
|
||||||
Currently, YASnippet only all \"real modes\" to menubar. For
|
|
||||||
example, you define snippets for \"cc-mode\" and make it the
|
|
||||||
parent of `c-mode', `c++-mode' and `java-mode'. There's really
|
|
||||||
no such mode like \"cc-mode\". So we don't show it in the yasnippet
|
|
||||||
menu to avoid the menu becoming too big with strange modes. The
|
|
||||||
snippets defined for \"cc-mode\" can still be accessed from
|
|
||||||
menu-bar->c-mode->parent (or c++-mode, java-mode, all are ok).
|
|
||||||
However, if you really like to show all modes in the menu, set
|
|
||||||
this variable to t."
|
|
||||||
:type 'boolean
|
|
||||||
:group 'yasnippet)
|
|
||||||
|
|
||||||
(defcustom yas/wrap-around-region nil
|
(defcustom yas/wrap-around-region nil
|
||||||
"If non-nil, snippet expansion wraps around selected region.
|
"If non-nil, snippet expansion wraps around selected region.
|
||||||
|
|
||||||
@ -378,12 +402,6 @@ Here's an example:
|
|||||||
t))))")
|
t))))")
|
||||||
(make-variable-buffer-local 'yas/buffer-local-condition)
|
(make-variable-buffer-local 'yas/buffer-local-condition)
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Utility functions for transformations
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Internal variables
|
;; Internal variables
|
||||||
;;
|
;;
|
||||||
@ -543,11 +561,11 @@ Key bindings:
|
|||||||
env
|
env
|
||||||
file)
|
file)
|
||||||
|
|
||||||
(defstruct (yas/snippet-table (:constructor yas/make-snippet-table ()))
|
(defstruct (yas/snippet-table (:constructor yas/make-snippet-table (name)))
|
||||||
"A table to store snippets for a perticular mode."
|
"A table to store snippets for a perticular mode."
|
||||||
|
name
|
||||||
(hash (make-hash-table :test 'equal))
|
(hash (make-hash-table :test 'equal))
|
||||||
(default-directory nil)
|
(parents nil))
|
||||||
(parent nil))
|
|
||||||
|
|
||||||
(defun yas/template-condition-predicate (condition)
|
(defun yas/template-condition-predicate (condition)
|
||||||
(condition-case err
|
(condition-case err
|
||||||
@ -583,26 +601,23 @@ This function implements the rules described in
|
|||||||
templates))))
|
templates))))
|
||||||
|
|
||||||
(defun yas/snippet-table-fetch (table key)
|
(defun yas/snippet-table-fetch (table key)
|
||||||
"Fetch a snippet binding to KEY from TABLE. If not found,
|
"Fetch a snippet binding to KEY from TABLE."
|
||||||
fetch from parent if any."
|
|
||||||
(when table
|
(when table
|
||||||
(let* ((unfiltered (gethash key (yas/snippet-table-hash table)))
|
(yas/filter-templates-by-condition (gethash key (yas/snippet-table-hash table)))))
|
||||||
(templates (yas/filter-templates-by-condition unfiltered)))
|
|
||||||
(when (and (null templates)
|
|
||||||
(not (null (yas/snippet-table-parent table))))
|
|
||||||
(setq templates (yas/snippet-table-fetch
|
|
||||||
(yas/snippet-table-parent table)
|
|
||||||
key)))
|
|
||||||
templates)))
|
|
||||||
|
|
||||||
(defun yas/snippet-table-all-templates (table)
|
(defun yas/snippet-table-get-all-parents (table)
|
||||||
|
(let ((parents (yas/snippet-table-parents table)))
|
||||||
|
(when parents
|
||||||
|
(append parents
|
||||||
|
(mapcan #'yas/snippet-table-get-all-parents parents)))))
|
||||||
|
|
||||||
|
(defun yas/snippet-table-templates (table)
|
||||||
(when table
|
(when table
|
||||||
(let ((acc))
|
(let ((acc))
|
||||||
(maphash #'(lambda (key templates)
|
(maphash #'(lambda (key templates)
|
||||||
(setq acc (append acc templates)))
|
(setq acc (append acc templates)))
|
||||||
(yas/snippet-table-hash table))
|
(yas/snippet-table-hash table))
|
||||||
(append (yas/filter-templates-by-condition acc)
|
(yas/filter-templates-by-condition acc))))
|
||||||
(yas/snippet-table-all-templates (yas/snippet-table-parent table))))))
|
|
||||||
|
|
||||||
(defun yas/snippet-table-all-keys (table)
|
(defun yas/snippet-table-all-keys (table)
|
||||||
(when table
|
(when table
|
||||||
@ -611,8 +626,7 @@ fetch from parent if any."
|
|||||||
(when (yas/filter-templates-by-condition templates)
|
(when (yas/filter-templates-by-condition templates)
|
||||||
(push key acc)))
|
(push key acc)))
|
||||||
(yas/snippet-table-hash table))
|
(yas/snippet-table-hash table))
|
||||||
(append acc
|
acc)))
|
||||||
(yas/snippet-table-all-keys (yas/snippet-table-parent table))))))
|
|
||||||
|
|
||||||
(defun yas/snippet-table-store (table full-key key template)
|
(defun yas/snippet-table-store (table full-key key template)
|
||||||
"Store a snippet template in the TABLE."
|
"Store a snippet template in the TABLE."
|
||||||
@ -627,16 +641,6 @@ fetch from parent if any."
|
|||||||
;; Internal functions
|
;; Internal functions
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(defun yas/ensure-minor-mode-priority ()
|
|
||||||
"Ensure that the key binding of yas/minor-mode takes priority."
|
|
||||||
(unless (eq 'yas/minor-mode
|
|
||||||
(caar minor-mode-map-alist))
|
|
||||||
(setq minor-mode-map-alist
|
|
||||||
(cons
|
|
||||||
(cons 'yas/minor-mode yas/minor-mode-map)
|
|
||||||
(assq-delete-all 'yas/minor-mode
|
|
||||||
minor-mode-map-alist)))))
|
|
||||||
|
|
||||||
(defun yas/real-mode? (mode)
|
(defun yas/real-mode? (mode)
|
||||||
"Try to find out if MODE is a real mode. The MODE bound to
|
"Try to find out if MODE is a real mode. The MODE bound to
|
||||||
a function (like `c-mode') is considered real mode. Other well
|
a function (like `c-mode') is considered real mode. Other well
|
||||||
@ -668,7 +672,11 @@ a list of modes like this to help the judgement."
|
|||||||
(error (cdr retval)))
|
(error (cdr retval)))
|
||||||
retval))
|
retval))
|
||||||
|
|
||||||
(defun yas/snippet-table-get-create (mode &optional directory)
|
(defvar yas/mode-symbol nil
|
||||||
|
"If non-nil, lookup snippets using this instead of `major-mode'.")
|
||||||
|
(make-variable-buffer-local 'yas/mode-symbol)
|
||||||
|
|
||||||
|
(defun yas/snippet-table-get-create (mode)
|
||||||
"Get the snippet table corresponding to MODE.
|
"Get the snippet table corresponding to MODE.
|
||||||
|
|
||||||
Optional DIRECTORY gets recorded as the default directory to
|
Optional DIRECTORY gets recorded as the default directory to
|
||||||
@ -677,24 +685,35 @@ already have such a property."
|
|||||||
(let ((table (gethash mode
|
(let ((table (gethash mode
|
||||||
yas/snippet-tables)))
|
yas/snippet-tables)))
|
||||||
(unless table
|
(unless table
|
||||||
(setq table (yas/make-snippet-table))
|
(setq table (yas/make-snippet-table (symbol-name mode)))
|
||||||
(puthash mode table yas/snippet-tables))
|
(puthash mode table yas/snippet-tables))
|
||||||
(unless (or (not directory) (yas/snippet-table-default-directory table))
|
|
||||||
(setf (yas/snippet-table-default-directory table)
|
|
||||||
directory))
|
|
||||||
table))
|
table))
|
||||||
|
|
||||||
(defun yas/current-snippet-table (&optional mode-symbol dont-search-parents)
|
(defun yas/get-snippet-tables (&optional mode-symbol dont-search-parents)
|
||||||
"Get the snippet table for current major-mode."
|
"Get snippet tables for current buffer.
|
||||||
(let ((mode (or mode-symbol
|
|
||||||
major-mode)))
|
|
||||||
(or (gethash mode
|
|
||||||
yas/snippet-tables)
|
|
||||||
(and (not dont-search-parents)
|
|
||||||
(get mode 'derived-mode-parent)
|
|
||||||
(yas/current-snippet-table (get mode 'derived-mode-parent))))))
|
|
||||||
|
|
||||||
(defun yas/menu-keymap-for-mode (mode)
|
Return tables in this order: optional MODE-SYMBOL, then
|
||||||
|
`yas/mode-symbol', then `major-mode' then, unless
|
||||||
|
DONT-SEARCH-PARENTS is non-nil, the guessed parent mode of either
|
||||||
|
MODE-SYMBOL or `major-mode'."
|
||||||
|
(let ((mode-tables
|
||||||
|
(mapcar #'(lambda (mode)
|
||||||
|
(gethash mode yas/snippet-tables))
|
||||||
|
(append (list mode-symbol)
|
||||||
|
(if (listp yas/mode-symbol)
|
||||||
|
yas/mode-symbol
|
||||||
|
(list yas/mode-symbol))
|
||||||
|
(list major-mode
|
||||||
|
(and (not dont-search-parents)
|
||||||
|
(get (or mode-symbol major-mode)
|
||||||
|
'derived-mode-parent))))))
|
||||||
|
(all-tables))
|
||||||
|
(dolist (table (remove nil mode-tables))
|
||||||
|
(push table all-tables)
|
||||||
|
(nconc all-tables (yas/snippet-table-get-all-parents table)))
|
||||||
|
(remove-duplicates all-tables)))
|
||||||
|
|
||||||
|
(defun yas/menu-keymap-get-create (mode)
|
||||||
"Get the menu keymap correspondong to MODE."
|
"Get the menu keymap correspondong to MODE."
|
||||||
(let ((keymap (gethash mode yas/menu-table)))
|
(let ((keymap (gethash mode yas/menu-table)))
|
||||||
(unless keymap
|
(unless keymap
|
||||||
@ -717,9 +736,9 @@ the template of a snippet in the current snippet-table."
|
|||||||
(skip-syntax-backward syntax)
|
(skip-syntax-backward syntax)
|
||||||
(setq start (point)))
|
(setq start (point)))
|
||||||
(setq templates
|
(setq templates
|
||||||
(yas/snippet-table-fetch
|
(mapcan #'(lambda (table)
|
||||||
(yas/current-snippet-table)
|
(yas/snippet-table-fetch table (buffer-substring-no-properties start end)))
|
||||||
(buffer-substring-no-properties start end)))
|
(yas/get-snippet-tables)))
|
||||||
(if templates
|
(if templates
|
||||||
(setq done t)
|
(setq done t)
|
||||||
(setq start end)))
|
(setq start end)))
|
||||||
@ -826,20 +845,28 @@ Here's a list of currently recognized variables:
|
|||||||
"Interactively choose a template from the list TEMPLATES.
|
"Interactively choose a template from the list TEMPLATES.
|
||||||
|
|
||||||
TEMPLATES is a list of `yas/template'."
|
TEMPLATES is a list of `yas/template'."
|
||||||
(let ((template (some #'(lambda (fn)
|
(when templates
|
||||||
|
(some #'(lambda (fn)
|
||||||
(funcall fn (or prompt "Choose a snippet: ")
|
(funcall fn (or prompt "Choose a snippet: ")
|
||||||
templates #'(lambda (template)
|
templates
|
||||||
(yas/template-name template))))
|
#'yas/template-name))
|
||||||
yas/prompt-functions)))
|
yas/prompt-functions)))
|
||||||
template))
|
|
||||||
|
|
||||||
(defun yas/prompt-for-keys (keys &optional prompt)
|
(defun yas/prompt-for-keys (keys &optional prompt)
|
||||||
"Interactively choose a template key from the list KEYS."
|
"Interactively choose a template key from the list KEYS."
|
||||||
(if keys
|
(when keys
|
||||||
(some #'(lambda (fn)
|
(some #'(lambda (fn)
|
||||||
(funcall fn (or prompt "Choose a snippet key: ") keys))
|
(funcall fn (or prompt "Choose a snippet key: ") keys))
|
||||||
yas/prompt-functions)))
|
yas/prompt-functions)))
|
||||||
|
|
||||||
|
(defun yas/prompt-for-table (tables &optional prompt)
|
||||||
|
(when tables
|
||||||
|
(some #'(lambda (fn)
|
||||||
|
(funcall fn (or prompt "Choose a snippet table: ")
|
||||||
|
tables
|
||||||
|
#'yas/snippet-table-name))
|
||||||
|
yas/prompt-functions)))
|
||||||
|
|
||||||
(defun yas/x-prompt (prompt choices &optional display-fn)
|
(defun yas/x-prompt (prompt choices &optional display-fn)
|
||||||
(when (and window-system choices)
|
(when (and window-system choices)
|
||||||
(let ((keymap (cons 'keymap
|
(let ((keymap (cons 'keymap
|
||||||
@ -909,24 +936,32 @@ TEMPLATES is a list of `yas/template'."
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Loading snippets from files
|
;; Loading snippets from files
|
||||||
;;
|
;;
|
||||||
(defun yas/load-directory-1 (directory &optional parent)
|
(defun yas/load-directory-1 (directory &optional parents)
|
||||||
|
|
||||||
"Recursively load snippet templates from DIRECTORY."
|
"Recursively load snippet templates from DIRECTORY."
|
||||||
|
|
||||||
(let ((mode-sym (intern (file-name-nondirectory directory)))
|
(let ((mode-sym (intern (file-name-nondirectory directory)))
|
||||||
(snippet-defs nil))
|
(snippet-defs nil)
|
||||||
|
(parent-file-name (concat directory "/.yas-parents"))
|
||||||
|
more-parents)
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
(dolist (file (yas/subdirs directory 'no-subdirs-just-files))
|
(dolist (file (yas/subdirs directory 'no-subdirs-just-files))
|
||||||
(when (file-readable-p file)
|
(when (file-readable-p file)
|
||||||
(insert-file-contents file nil nil nil t)
|
(insert-file-contents file nil nil nil t)
|
||||||
(push (yas/parse-template file)
|
(push (yas/parse-template file)
|
||||||
snippet-defs))))
|
snippet-defs))))
|
||||||
|
(when (file-readable-p parent-file-name)
|
||||||
|
(setq more-parents
|
||||||
|
(mapcar #'intern
|
||||||
|
(split-string
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert-file parent-file-name)
|
||||||
|
(buffer-substring-no-properties (point-min)
|
||||||
|
(point-max)))))))
|
||||||
(yas/define-snippets mode-sym
|
(yas/define-snippets mode-sym
|
||||||
snippet-defs
|
snippet-defs
|
||||||
parent
|
(append parents more-parents))
|
||||||
directory)
|
|
||||||
(dolist (subdir (yas/subdirs directory))
|
(dolist (subdir (yas/subdirs directory))
|
||||||
(yas/load-directory-1 subdir mode-sym))))
|
(yas/load-directory-1 subdir (list mode-sym)))))
|
||||||
|
|
||||||
(defun yas/load-directory (directory)
|
(defun yas/load-directory (directory)
|
||||||
"Load snippet definition from a directory hierarchy.
|
"Load snippet definition from a directory hierarchy.
|
||||||
@ -990,7 +1025,7 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\""
|
|||||||
t)
|
t)
|
||||||
"\""))
|
"\""))
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;; Yasnipept Bundle
|
;;; Yasnippet Bundle
|
||||||
|
|
||||||
(defun yas/initialize ()
|
(defun yas/initialize ()
|
||||||
"For backward compatibility, enable `yas/minor-mode' globally"
|
"For backward compatibility, enable `yas/minor-mode' globally"
|
||||||
@ -1097,7 +1132,7 @@ Here's the default value for all the parameters:
|
|||||||
(save-buffer))))
|
(save-buffer))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;; User level functions
|
;;; Some user level functions
|
||||||
;;;
|
;;;
|
||||||
|
|
||||||
(defun yas/about ()
|
(defun yas/about ()
|
||||||
@ -1106,37 +1141,35 @@ Here's the default value for all the parameters:
|
|||||||
yas/version
|
yas/version
|
||||||
") -- pluskid <pluskid@gmail.com>/joaotavora <joaotavora@gmail.com>")))
|
") -- pluskid <pluskid@gmail.com>/joaotavora <joaotavora@gmail.com>")))
|
||||||
|
|
||||||
(defun yas/define-snippets (mode snippets &optional parent-mode directory)
|
(defun yas/define-snippets (mode snippets &optional parent-mode)
|
||||||
"Define snippets for MODE. SNIPPETS is a list of
|
"Define snippets for MODE. SNIPPETS is a list of
|
||||||
snippet definitions, each taking the following form:
|
snippet definitions, each taking the following form:
|
||||||
|
|
||||||
(KEY TEMPLATE NAME CONDITION GROUP)
|
(KEY TEMPLATE NAME CONDITION GROUP)
|
||||||
|
|
||||||
NAME, CONDITION or GROUP may be omitted. Optional PARENT-MODE
|
NAME, CONDITION or GROUP may be omitted.
|
||||||
can be used to specify the parent mode of MODE. That is, when
|
|
||||||
looking a snippet in MODE failed, it can refer to its parent
|
|
||||||
mode. The PARENT-MODE does not need to be a real mode.
|
|
||||||
|
|
||||||
Optional DIRECTORY is recorded in the `yas/snippet-table' if it
|
Optional PARENT-MODE can be used to specify the parent modes of
|
||||||
is created for the first time. Then, it becomes the default
|
MODE. It can be a mode symbol of a list of mode symbols. It does
|
||||||
directory to find snippet files.
|
not need to be a real mode.
|
||||||
|
|
||||||
|
That is, when looking a snippet in MODE failed, it can refer to
|
||||||
"
|
its parent modes."
|
||||||
(let ((snippet-table (yas/snippet-table-get-create mode directory))
|
(let ((snippet-table (yas/snippet-table-get-create mode))
|
||||||
(parent-table (if parent-mode
|
(parent-tables (mapcar #'yas/snippet-table-get-create
|
||||||
(yas/snippet-table-get-create parent-mode)
|
(if (listp parent-mode)
|
||||||
nil))
|
parent-mode
|
||||||
|
(list parent-mode))))
|
||||||
(keymap (if yas/use-menu
|
(keymap (if yas/use-menu
|
||||||
(yas/menu-keymap-for-mode mode)
|
(yas/menu-keymap-get-create mode)
|
||||||
nil)))
|
nil)))
|
||||||
(when parent-table
|
(when parent-tables
|
||||||
(setf (yas/snippet-table-parent snippet-table)
|
(setf (yas/snippet-table-parents snippet-table)
|
||||||
parent-table)
|
parent-tables)
|
||||||
(when yas/use-menu
|
(when yas/use-menu
|
||||||
(define-key keymap (vector 'parent-mode)
|
(define-key keymap (vector 'parent-mode)
|
||||||
`(menu-item "parent mode"
|
`(menu-item "parent mode"
|
||||||
,(yas/menu-keymap-for-mode parent-mode)))))
|
,(yas/menu-keymap-get-create parent-mode)))))
|
||||||
(when (and yas/use-menu
|
(when (and yas/use-menu
|
||||||
(yas/real-mode? mode))
|
(yas/real-mode? mode))
|
||||||
(define-key yas/minor-mode-menu (vector mode)
|
(define-key yas/minor-mode-menu (vector mode)
|
||||||
@ -1213,23 +1246,13 @@ Skip any submenus named \"parent mode\""
|
|||||||
(setf (nthcdr pos-in-keymap keymap)
|
(setf (nthcdr pos-in-keymap keymap)
|
||||||
(nthcdr (+ 1 pos-in-keymap) keymap))))))
|
(nthcdr (+ 1 pos-in-keymap) keymap))))))
|
||||||
|
|
||||||
(defun yas/set-mode-parent (mode parent)
|
|
||||||
"Set parent mode of MODE to PARENT."
|
|
||||||
(setf (yas/snippet-table-parent
|
|
||||||
(yas/snippet-table-get-create mode))
|
|
||||||
(yas/snippet-table-get-create parent))
|
|
||||||
(when yas/use-menu
|
|
||||||
(define-key (yas/menu-keymap-for-mode mode) (vector 'parent-mode)
|
|
||||||
`(menu-item "parent mode"
|
|
||||||
,(yas/menu-keymap-for-mode parent)))))
|
|
||||||
|
|
||||||
(defun yas/define (mode key template &optional name condition group)
|
(defun yas/define (mode key template &optional name condition group)
|
||||||
"Define a snippet. Expanding KEY into TEMPLATE.
|
"Define a snippet. Expanding KEY into TEMPLATE.
|
||||||
NAME is a description to this template. Also update
|
|
||||||
the menu if `yas/use-menu' is `t'. CONDITION is the
|
NAME is a description to this template. Also update the menu if
|
||||||
condition attached to this snippet. If you attach a
|
`yas/use-menu' is `t'. CONDITION is the condition attached to
|
||||||
condition to a snippet, then it will only be expanded
|
this snippet. If you attach a condition to a snippet, then it
|
||||||
when the condition evaluated to non-nil."
|
will only be expanded when the condition evaluated to non-nil."
|
||||||
(yas/define-snippets mode
|
(yas/define-snippets mode
|
||||||
(list (list key template name condition group))))
|
(list (list key template name condition group))))
|
||||||
|
|
||||||
@ -1280,6 +1303,23 @@ conditions to filter out potential expansions."
|
|||||||
(setq this-command command)
|
(setq this-command command)
|
||||||
(call-interactively command)))))))
|
(call-interactively command)))))))
|
||||||
|
|
||||||
|
(defun yas/all-templates (tables)
|
||||||
|
"Return all snippet tables applicable for the current buffer.
|
||||||
|
|
||||||
|
Honours `yas/choose-tables-first', `yas/choose-keys-first' and
|
||||||
|
`yas/buffer-local-condition'"
|
||||||
|
(when yas/choose-tables-first
|
||||||
|
(setq tables (list (yas/prompt-for-table tables))))
|
||||||
|
(mapcar #'cdr
|
||||||
|
(if yas/choose-keys-first
|
||||||
|
(let ((key (yas/prompt-for-keys
|
||||||
|
(mapcan #'yas/snippet-table-all-keys tables))))
|
||||||
|
(when key
|
||||||
|
(mapcan #'(lambda (table)
|
||||||
|
(yas/snippet-table-fetch table key))
|
||||||
|
tables)))
|
||||||
|
(mapcan #'yas/snippet-table-templates tables))))
|
||||||
|
|
||||||
(defun yas/insert-snippet (&optional no-condition)
|
(defun yas/insert-snippet (&optional no-condition)
|
||||||
"Choose a snippet to expand, pop-up a list of choices according
|
"Choose a snippet to expand, pop-up a list of choices according
|
||||||
to `yas/prompt-function'.
|
to `yas/prompt-function'.
|
||||||
@ -1290,12 +1330,7 @@ by condition."
|
|||||||
(let* ((yas/buffer-local-condition (or (and no-condition
|
(let* ((yas/buffer-local-condition (or (and no-condition
|
||||||
'always)
|
'always)
|
||||||
yas/buffer-local-condition))
|
yas/buffer-local-condition))
|
||||||
(templates (mapcar #'cdr
|
(templates (yas/all-templates (yas/get-snippet-tables)))
|
||||||
(if yas/choose-keys-first
|
|
||||||
(let ((key (yas/prompt-for-keys (yas/snippet-table-all-keys (yas/current-snippet-table)))))
|
|
||||||
(when key
|
|
||||||
(yas/snippet-table-fetch (yas/current-snippet-table) key)))
|
|
||||||
(yas/snippet-table-all-templates (yas/current-snippet-table)))))
|
|
||||||
(template (and templates
|
(template (and templates
|
||||||
(or (and (rest templates) ;; more than one template for same key
|
(or (and (rest templates) ;; more than one template for same key
|
||||||
(yas/prompt-for-template templates))
|
(yas/prompt-for-template templates))
|
||||||
@ -1317,13 +1352,7 @@ Only success if selected snippet was loaded from a file. Put the
|
|||||||
visited file in `snippet-mode'."
|
visited file in `snippet-mode'."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((yas/buffer-local-condition 'always)
|
(let* ((yas/buffer-local-condition 'always)
|
||||||
(templates (mapcar #'cdr
|
(templates (yas/all-templates (yas/get-snippet-tables)))
|
||||||
(if yas/choose-keys-first
|
|
||||||
(let ((key (yas/prompt-for-keys (yas/snippet-table-all-keys (yas/current-snippet-table))
|
|
||||||
"Choose a snippet key to edit: ")))
|
|
||||||
(when key
|
|
||||||
(yas/snippet-table-fetch (yas/current-snippet-table) key)))
|
|
||||||
(yas/snippet-table-all-templates (yas/current-snippet-table)))))
|
|
||||||
(template (and templates
|
(template (and templates
|
||||||
(or (and (rest templates) ;; more than one template for same key
|
(or (and (rest templates) ;; more than one template for same key
|
||||||
(yas/prompt-for-template templates
|
(yas/prompt-for-template templates
|
||||||
@ -1341,46 +1370,62 @@ visited file in `snippet-mode'."
|
|||||||
(message "This snippet was not loaded from a file!")))))))
|
(message "This snippet was not loaded from a file!")))))))
|
||||||
|
|
||||||
(defun yas/guess-snippet-directory ()
|
(defun yas/guess-snippet-directory ()
|
||||||
"Try to guess the suitable yassnippet based on `major-mode'"
|
"Try to guess suitable directories based on `major-mode' and
|
||||||
(let ((loaded-root (or (and (listp yas/root-directory)
|
also the current active tables."
|
||||||
|
(let ((main-dir (or (and (listp yas/root-directory)
|
||||||
(first yas/root-directory))
|
(first yas/root-directory))
|
||||||
yas/root-directory))
|
yas/root-directory
|
||||||
|
"~/.emacs.d/snippets"))
|
||||||
(mode major-mode)
|
(mode major-mode)
|
||||||
(path))
|
(options))
|
||||||
(when loaded-root
|
;; Lookup main mode and add that to the options
|
||||||
(while mode
|
;;
|
||||||
(setq path (format "%s/%s"
|
(push (format "%s/%s" main-dir mode) options)
|
||||||
mode
|
;; Next lookup the main active table
|
||||||
(or path
|
;;
|
||||||
"")))
|
(let ((active-tables (first (yas/get-snippet-tables)))
|
||||||
(setq mode (get mode 'derived-mode-parent)))
|
(other-path-alternative main-dir))
|
||||||
(concat loaded-root
|
(when active-tables
|
||||||
(unless (string-match "/$" loaded-root) "/")
|
(setq active-tables (cons active-tables
|
||||||
path))))
|
(yas/snippet-table-get-all-parents active-tables))))
|
||||||
|
(dolist (table (reverse active-tables))
|
||||||
|
(setq other-path-alternative
|
||||||
|
(concat other-path-alternative "/" (yas/snippet-table-name table))))
|
||||||
|
(push other-path-alternative options))
|
||||||
|
;; Finally add to the options the guessed parent of major-mode
|
||||||
|
;; (this is almost never works out)
|
||||||
|
(when (get mode 'derived-mode-parent)
|
||||||
|
(push (format "%s/%s" main-dir (get mode 'derived-mode-parent)) options))
|
||||||
|
(reverse options)))
|
||||||
|
|
||||||
|
(defun yas/find-snippets (&optional same-window file)
|
||||||
|
"Look for user snippets in guessed current mode's directory.
|
||||||
|
|
||||||
(defun yas/find-snippets (&optional same-window)
|
Calls `find-file' interactively in the guessed directory.
|
||||||
"Looks for snippets file in the current mode's directory.
|
|
||||||
|
|
||||||
This can be used to create new snippets for the currently active
|
With prefix arg SAME-WINDOW opens the buffer in the same window.
|
||||||
major mode."
|
|
||||||
|
With optional FILE, finds the file directly, i.e. `find-file' is
|
||||||
|
called non-interactively.
|
||||||
|
|
||||||
|
Because snippets can be loaded from many different locations,
|
||||||
|
this has to guess the correct directory using
|
||||||
|
`yas/guess-directory', which returns a list of options. If any
|
||||||
|
one of these exists, it is taken and `find-file' is called there,
|
||||||
|
otherwise, proposes to create the first option returned by
|
||||||
|
`yas/guess-directory'."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(let* ((current-table (yas/current-snippet-table major-mode 'dont-search-parents))
|
(let* ((guessed-directories (yas/guess-snippet-directory))
|
||||||
(parents-table (yas/current-snippet-table major-mode))
|
(target-directory (first (remove-if-not #'file-exists-p guessed-directories)))
|
||||||
(parents-directory (and parents-table
|
|
||||||
(yas/snippet-table-default-directory parents-table)))
|
|
||||||
(guessed-directory (or (and current-table
|
|
||||||
(yas/snippet-table-default-directory current-table))
|
|
||||||
(yas/guess-snippet-directory)
|
|
||||||
default-directory))
|
|
||||||
(buffer))
|
(buffer))
|
||||||
(unless (file-exists-p guessed-directory)
|
|
||||||
(if (y-or-n-p (format "Guessed directory (%s) does not exist! Create? " guessed-directory))
|
(unless target-directory
|
||||||
(make-directory guessed-directory 'also-make-parents)
|
(when (y-or-n-p (format "Guessed directory (%s) does not exist! Create? " (first guessed-directories)))
|
||||||
(if parents-directory
|
(setq target-directory (first guessed-directories))
|
||||||
(setq guessed-directory parents-directory)
|
(make-directory target-directory 'also-make-parents)))
|
||||||
(setq guessed-directory default-directory))))
|
|
||||||
(let ((default-directory guessed-directory))
|
(when target-directory
|
||||||
|
(let ((default-directory target-directory))
|
||||||
(setq buffer (call-interactively (if same-window
|
(setq buffer (call-interactively (if same-window
|
||||||
'find-file
|
'find-file
|
||||||
'find-file-other-window)))
|
'find-file-other-window)))
|
||||||
@ -1388,8 +1433,7 @@ major mode."
|
|||||||
(save-excursion
|
(save-excursion
|
||||||
(set-buffer buffer)
|
(set-buffer buffer)
|
||||||
(when (eq major-mode 'fundamental-mode)
|
(when (eq major-mode 'fundamental-mode)
|
||||||
(snippet-mode)))))))
|
(snippet-mode))))))))
|
||||||
|
|
||||||
|
|
||||||
(defun yas/compute-major-mode-and-parent (file &optional prompt-if-failed)
|
(defun yas/compute-major-mode-and-parent (file &optional prompt-if-failed)
|
||||||
(let* ((file-dir (and file
|
(let* ((file-dir (and file
|
||||||
@ -1515,6 +1559,11 @@ Otherwise throw exception."
|
|||||||
(when field
|
(when field
|
||||||
(yas/field-text-for-display field))))
|
(yas/field-text-for-display field))))
|
||||||
|
|
||||||
|
(defun yas/oni (text oni-regexp)
|
||||||
|
"Runs ruby to parse TEXT with Oniguruma regexp ONI-REGEXP."
|
||||||
|
(shell-command-to-string (format "ruby -e 'print \"%s\".gsub(\"a\",\"b\")'" "aha")))
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;; Snippet expansion and field management
|
;;; Snippet expansion and field management
|
||||||
|
|
||||||
@ -2248,7 +2297,8 @@ has to be called before the $-constructs are deleted."
|
|||||||
(setq soup
|
(setq soup
|
||||||
(sort soup
|
(sort soup
|
||||||
#'yas/compare-fom-begs))
|
#'yas/compare-fom-begs))
|
||||||
(reduce #'yas/link-foms soup))))
|
(when soup
|
||||||
|
(reduce #'yas/link-foms soup)))))
|
||||||
|
|
||||||
(defun yas/advance-end-maybe (fom newend)
|
(defun yas/advance-end-maybe (fom newend)
|
||||||
"Maybe advance FOM's end to NEWEND if it needs it.
|
"Maybe advance FOM's end to NEWEND if it needs it.
|
||||||
@ -2263,8 +2313,8 @@ If it does, also:
|
|||||||
(set-marker (yas/fom-end fom) newend)
|
(set-marker (yas/fom-end fom) newend)
|
||||||
(yas/advance-start-maybe (yas/fom-next fom) newend)
|
(yas/advance-start-maybe (yas/fom-next fom) newend)
|
||||||
(if (and (yas/field-p fom)
|
(if (and (yas/field-p fom)
|
||||||
(yas/field-parent-field field))
|
(yas/field-parent-field fom))
|
||||||
(yas/advance-end-maybe (yas/field-parent-field field) newend))))
|
(yas/advance-end-maybe (yas/field-parent-field fom) newend))))
|
||||||
|
|
||||||
(defun yas/advance-start-maybe (fom newstart)
|
(defun yas/advance-start-maybe (fom newstart)
|
||||||
"Maybe advance FOM's start to NEWSTART if it needs it.
|
"Maybe advance FOM's start to NEWSTART if it needs it.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user