mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 21:13:04 +00:00
* less akward snippet management when working with multiple snippet dirs.
This commit is contained in:
parent
8233317a5e
commit
9f8fab6bc6
423
yasnippet.el
423
yasnippet.el
@ -35,8 +35,8 @@
|
|||||||
;; (require 'yasnippet)
|
;; (require 'yasnippet)
|
||||||
;; 2. Place the `snippets' directory somewhere. E.g: ~/.emacs.d/snippets
|
;; 2. Place the `snippets' directory somewhere. E.g: ~/.emacs.d/snippets
|
||||||
;; 3. In your .emacs file
|
;; 3. In your .emacs file
|
||||||
;; (setq yas/root-directory "~/.emacs/snippets")
|
;; (setq yas/snippet-dirs "~/.emacs/snippets")
|
||||||
;; (yas/load-directory yas/root-directory)
|
;; (yas/load-directory yas/snippet-dirs)
|
||||||
;; 4. To enable the YASnippet menu and tab-trigger expansion
|
;; 4. To enable the YASnippet menu and tab-trigger expansion
|
||||||
;; M-x yas/minor-mode
|
;; M-x yas/minor-mode
|
||||||
;; 5. To globally enable the minor mode in *all* buffers
|
;; 5. To globally enable the minor mode in *all* buffers
|
||||||
@ -47,12 +47,12 @@
|
|||||||
;;
|
;;
|
||||||
;; Interesting variables are:
|
;; Interesting variables are:
|
||||||
;;
|
;;
|
||||||
;; `yas/root-directory'
|
;; `yas/snippet-dirs'
|
||||||
;;
|
;;
|
||||||
;; The directory where user-created snippets are to be
|
;; The directory where user-created snippets are to be
|
||||||
;; stored. Can also be a list of directories that
|
;; stored. Can also be a list of directories that
|
||||||
;; `yas/reload-all' will use for bulk-reloading snippets. In
|
;; `yas/reload-all' will use for bulk-reloading snippets. In
|
||||||
;; that case the first directory the default for storing new
|
;; that case the first directory is the default for storing new
|
||||||
;; snippets.
|
;; snippets.
|
||||||
;;
|
;;
|
||||||
;; `yas/mode-symbol'
|
;; `yas/mode-symbol'
|
||||||
@ -60,7 +60,7 @@
|
|||||||
;; A local variable that you can set in a hook to override
|
;; A local variable that you can set in a hook to override
|
||||||
;; snippet-lookup based on major mode. It is a a symbol (or
|
;; snippet-lookup based on major mode. It is a a symbol (or
|
||||||
;; list of symbols) that correspond to subdirectories of
|
;; list of symbols) that correspond to subdirectories of
|
||||||
;; `yas/root-directory' and is used for deciding which
|
;; `yas/snippet-dirs' and is used for deciding which
|
||||||
;; snippets to consider for the active buffer.
|
;; snippets to consider for the active buffer.
|
||||||
;;
|
;;
|
||||||
;; Major commands are:
|
;; Major commands are:
|
||||||
@ -84,7 +84,7 @@
|
|||||||
;; M-x yas/find-snippets
|
;; M-x yas/find-snippets
|
||||||
;;
|
;;
|
||||||
;; Lets you find the snippet files in the correct
|
;; Lets you find the snippet files in the correct
|
||||||
;; subdirectory of `yas/root-directory', according to the
|
;; subdirectory of `yas/snippet-dirs', according to the
|
||||||
;; active major mode (if it exists) like
|
;; active major mode (if it exists) like
|
||||||
;; `find-file-other-window'.
|
;; `find-file-other-window'.
|
||||||
;;
|
;;
|
||||||
@ -98,7 +98,7 @@
|
|||||||
;; M-x yas/new-snippet
|
;; M-x yas/new-snippet
|
||||||
;;
|
;;
|
||||||
;; Lets you create a new snippet file in the correct
|
;; Lets you create a new snippet file in the correct
|
||||||
;; subdirectory of `yas/root-directory', according to the
|
;; subdirectory of `yas/snippet-dirs', according to the
|
||||||
;; active major mode.
|
;; active major mode.
|
||||||
;;
|
;;
|
||||||
;; M-x yas/load-snippet-buffer
|
;; M-x yas/load-snippet-buffer
|
||||||
@ -128,7 +128,7 @@
|
|||||||
;; M-x customize-group RET yasnippet RET
|
;; M-x customize-group RET yasnippet RET
|
||||||
;;
|
;;
|
||||||
;; If you use the customization group to set variables
|
;; If you use the customization group to set variables
|
||||||
;; `yas/root-directory' or `yas/global-mode', make sure the path to
|
;; `yas/snippet-dirs' or `yas/global-mode', make sure the path to
|
||||||
;; "yasnippet.el" is present in the `load-path' *before* the
|
;; "yasnippet.el" is present in the `load-path' *before* the
|
||||||
;; `custom-set-variables' is executed in your .emacs file.
|
;; `custom-set-variables' is executed in your .emacs file.
|
||||||
;;
|
;;
|
||||||
@ -144,14 +144,13 @@
|
|||||||
|
|
||||||
;;; User customizable variables
|
;;; User customizable variables
|
||||||
|
|
||||||
|
|
||||||
(defgroup yasnippet nil
|
(defgroup yasnippet nil
|
||||||
"Yet Another Snippet extension"
|
"Yet Another Snippet extension"
|
||||||
:group 'editing)
|
:group 'editing)
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defcustom yas/root-directory nil
|
(defcustom yas/snippet-dirs nil
|
||||||
"Root directory that stores the snippets for each major mode.
|
"Directory or list of snippet dirs for each major mode.
|
||||||
|
|
||||||
If you set this from your .emacs, can also be a list of strings,
|
If you set this from your .emacs, can also be a list of strings,
|
||||||
for multiple root directories. If you make this a list, the first
|
for multiple root directories. If you make this a list, the first
|
||||||
@ -169,6 +168,7 @@ directories are used for bulk reloading of all snippets using
|
|||||||
(unless (or (not (fboundp 'yas/reload-all))
|
(unless (or (not (fboundp 'yas/reload-all))
|
||||||
(equal old new))
|
(equal old new))
|
||||||
(yas/reload-all)))))
|
(yas/reload-all)))))
|
||||||
|
(defvaralias 'yas/root-directory 'yas/snippet-dirs)
|
||||||
|
|
||||||
(defcustom yas/prompt-functions '(yas/x-prompt
|
(defcustom yas/prompt-functions '(yas/x-prompt
|
||||||
yas/dropdown-prompt
|
yas/dropdown-prompt
|
||||||
@ -764,7 +764,7 @@ Key bindings:
|
|||||||
;; Load all snippets definitions unless we still don't have a
|
;; Load all snippets definitions unless we still don't have a
|
||||||
;; root-directory or some snippets have already been loaded.
|
;; root-directory or some snippets have already been loaded.
|
||||||
;;
|
;;
|
||||||
(unless (or (null yas/root-directory)
|
(unless (or (null yas/snippet-dirs)
|
||||||
(> (hash-table-count yas/snippet-tables) 0))
|
(> (hash-table-count yas/snippet-tables) 0))
|
||||||
(yas/reload-all))
|
(yas/reload-all))
|
||||||
;; Install the direct keymaps in `emulation-mode-map-alists'
|
;; Install the direct keymaps in `emulation-mode-map-alists'
|
||||||
@ -785,7 +785,7 @@ Key bindings:
|
|||||||
(remove-hook 'emulation-mode-map-alists 'yas/direct-keymaps))))
|
(remove-hook 'emulation-mode-map-alists 'yas/direct-keymaps))))
|
||||||
|
|
||||||
(defvar yas/dont-activate #'(lambda ()
|
(defvar yas/dont-activate #'(lambda ()
|
||||||
(and yas/root-directory
|
(and yas/snippet-dirs
|
||||||
(null (yas/get-snippet-tables))))
|
(null (yas/get-snippet-tables))))
|
||||||
"If non-nil don't let `yas/minor-mode-on' active yas for this buffer.
|
"If non-nil don't let `yas/minor-mode-on' active yas for this buffer.
|
||||||
|
|
||||||
@ -929,9 +929,10 @@ Has the following fields:
|
|||||||
;; as KEY. This latter detail enables independent changes in
|
;; as KEY. This latter detail enables independent changes in
|
||||||
;; the trigger key and direct keybinding for a snippet.
|
;; the trigger key and direct keybinding for a snippet.
|
||||||
;;
|
;;
|
||||||
;; Search b) is only performed if
|
;; Search b) is only performed if a) failed and
|
||||||
;; `yas/better-guess-for-replacements' is non-nil, which happens
|
;; `yas/better-guess-for-replacements' is non-nil. The latter is
|
||||||
;; when the user is interactively loading the snippet buffer.
|
;; now on by default, but I vaguely recall some situation where we
|
||||||
|
;; needed it to be nil....
|
||||||
;;
|
;;
|
||||||
;; If any existing namesomething is found it is deleted, and is
|
;; If any existing namesomething is found it is deleted, and is
|
||||||
;; maybe added later on:
|
;; maybe added later on:
|
||||||
@ -946,18 +947,26 @@ Has the following fields:
|
|||||||
;; TODO: This is still not ideal. A well designed system (like
|
;; TODO: This is still not ideal. A well designed system (like
|
||||||
;; TextMate's) indexes the snippets by UUID or filename or something
|
;; TextMate's) indexes the snippets by UUID or filename or something
|
||||||
;; that uniquely identify a snippet. I.e. this replacement strategy
|
;; that uniquely identify a snippet. I.e. this replacement strategy
|
||||||
;; fails if both the key and the name have changed. In that case,
|
;; fails if we have lost the original key and name, in that case it's
|
||||||
;; it's as if a brand new snippet had been created.
|
;; as if a brand new snippet has been created.
|
||||||
;;
|
;;
|
||||||
(defvar yas/better-guess-for-replacements nil
|
;; UPDATE: `yas/visit-snippet-file' attempts to circumvent this using
|
||||||
|
;; `yas/current-template' and seems to work quite nicely.
|
||||||
|
;;
|
||||||
|
(defvar yas/better-guess-for-replacements t
|
||||||
"If non-nil `yas/store' guesses snippet replacements \"better\".")
|
"If non-nil `yas/store' guesses snippet replacements \"better\".")
|
||||||
|
|
||||||
(defun yas/remove-snippet (table name key template type-fn)
|
(defun yas/remove-snippet (table name key type-fn)
|
||||||
|
"Attempt to remove from TABLE a template with NAME and KEY.
|
||||||
|
|
||||||
|
TYPE-FN indicates if KEY is a trigger key (string) or a
|
||||||
|
keybinding (vector)."
|
||||||
(let ((key-and-namehash-alist '())
|
(let ((key-and-namehash-alist '())
|
||||||
(namehash-for-key (gethash key (yas/snippet-table-hash table))))
|
(namehash-for-key (gethash key (yas/snippet-table-hash table))))
|
||||||
(when namehash-for-key
|
(when namehash-for-key
|
||||||
(push (cons key namehash-for-key) key-and-namehash-alist))
|
(push (cons key namehash-for-key) key-and-namehash-alist))
|
||||||
(when yas/better-guess-for-replacements
|
(when (and (null key-and-namehash-alist)
|
||||||
|
yas/better-guess-for-replacements)
|
||||||
;; "cand" means "candidate for removal"
|
;; "cand" means "candidate for removal"
|
||||||
(maphash #'(lambda (cand namehash)
|
(maphash #'(lambda (cand namehash)
|
||||||
(when (and (gethash name namehash)
|
(when (and (gethash name namehash)
|
||||||
@ -971,37 +980,34 @@ Has the following fields:
|
|||||||
(when (vectorp (car elem))
|
(when (vectorp (car elem))
|
||||||
(define-key (yas/snippet-table-direct-keymap table) (car elem) nil))))))
|
(define-key (yas/snippet-table-direct-keymap table) (car elem) nil))))))
|
||||||
|
|
||||||
(defun yas/add-snippet (table name key template)
|
(defun yas/add-snippet (table template)
|
||||||
"Store in TABLE the snippet NAME indexed by KEY and expanding TEMPLATE.
|
"Store in TABLE the snippet template TEMPLATE.
|
||||||
|
|
||||||
KEY can be a string (trigger key) of a vector (direct
|
KEY can be a string (trigger key) of a vector (direct
|
||||||
keybinding)."
|
keybinding)."
|
||||||
|
(let ((name (yas/template-name template))
|
||||||
;; Now store the new template independent of the previous steps.
|
(keys (remove nil (list (yas/template-key template)
|
||||||
;;
|
(yas/template-keybinding template)))))
|
||||||
(when key
|
(dolist (key keys)
|
||||||
(puthash name
|
(puthash name
|
||||||
template
|
template
|
||||||
(or (gethash key
|
(or (gethash key
|
||||||
(yas/snippet-table-hash table))
|
(yas/snippet-table-hash table))
|
||||||
(puthash key
|
(puthash key
|
||||||
(make-hash-table :test 'equal)
|
(make-hash-table :test 'equal)
|
||||||
(yas/snippet-table-hash table))))
|
(yas/snippet-table-hash table))))
|
||||||
(when (vectorp key)
|
(when (vectorp key)
|
||||||
(define-key (yas/snippet-table-direct-keymap table) key 'yas/expand-from-keymap))))
|
(define-key (yas/snippet-table-direct-keymap table) key 'yas/expand-from-keymap)))))
|
||||||
|
|
||||||
(defun yas/update-snippet (snippet-table template name key keybinding)
|
(defun yas/update-snippet (snippet-table template name key keybinding)
|
||||||
"Update TEMPLATE in SNIPPET-TABLE, according to new props.
|
"Add TEMPLATE to SNIPPET-TABLE, first removing existing according to remaining args.
|
||||||
|
|
||||||
TEMPLATE, NAME, KEY and KEYBINDING."
|
TEMPLATE, NAME, KEY and KEYBINDING."
|
||||||
;; The direct keybinding
|
;; The direct keybinding
|
||||||
(yas/remove-snippet snippet-table name keybinding template #'vectorp)
|
(yas/remove-snippet snippet-table name keybinding #'vectorp)
|
||||||
(when keybinding
|
(yas/remove-snippet snippet-table name key #'stringp)
|
||||||
(yas/add-snippet snippet-table name keybinding template))
|
|
||||||
;; The trigger key (key can be null if we removed the key)
|
(yas/add-snippet snippet-table template))
|
||||||
(yas/remove-snippet snippet-table name key template #'stringp)
|
|
||||||
(when key
|
|
||||||
(yas/add-snippet snippet-table name key template)))
|
|
||||||
|
|
||||||
(defun yas/fetch (table key)
|
(defun yas/fetch (table key)
|
||||||
"Fetch snippets in TABLE by KEY. "
|
"Fetch snippets in TABLE by KEY. "
|
||||||
@ -1255,7 +1261,6 @@ Here's a list of currently recognized variables:
|
|||||||
* contributor
|
* contributor
|
||||||
* condition
|
* condition
|
||||||
* key
|
* key
|
||||||
* group
|
|
||||||
* expand-env
|
* expand-env
|
||||||
* binding
|
* binding
|
||||||
|
|
||||||
@ -1326,39 +1331,13 @@ Here's a list of currently recognized variables:
|
|||||||
(directory-file-name extra-dir)))))
|
(directory-file-name extra-dir)))))
|
||||||
group))
|
group))
|
||||||
|
|
||||||
;; (defun yas/glob-files (directory &optional recurse-p append)
|
|
||||||
;; "Returns files under DIRECTORY ignoring dirs and hidden files.
|
|
||||||
|
|
||||||
;; If RECURSE in non-nil, do that recursively."
|
|
||||||
;; (let (ret
|
|
||||||
;; (default-directory directory))
|
|
||||||
;; (dolist (entry (directory-files "."))
|
|
||||||
;; (cond ((or (string-match "^\\."
|
|
||||||
;; (file-name-nondirectory entry))
|
|
||||||
;; (string-match "~$"
|
|
||||||
;; (file-name-nondirectory entry)))
|
|
||||||
;; nil)
|
|
||||||
;; ((and recurse-p
|
|
||||||
;; (file-directory-p entry))
|
|
||||||
;; (setq ret (nconc ret
|
|
||||||
;; (yas/glob-files (expand-file-name entry)
|
|
||||||
;; recurse-p
|
|
||||||
;; (if append
|
|
||||||
;; (concat append "/" entry)
|
|
||||||
;; entry)))))
|
|
||||||
;; ((file-directory-p entry)
|
|
||||||
;; nil)
|
|
||||||
;; (t
|
|
||||||
;; (push (if append
|
|
||||||
;; (concat append "/" entry)
|
|
||||||
;; entry) ret))))
|
|
||||||
;; ret))
|
|
||||||
|
|
||||||
(defun yas/subdirs (directory &optional file?)
|
(defun yas/subdirs (directory &optional file?)
|
||||||
"Return subdirs or files of DIRECTORY according to FILE?."
|
"Return subdirs or files of DIRECTORY according to FILE?."
|
||||||
(remove-if (lambda (file)
|
(remove-if (lambda (file)
|
||||||
(or (string-match "^\\."
|
(or (string-match "^\\."
|
||||||
(file-name-nondirectory file))
|
(file-name-nondirectory file))
|
||||||
|
(string-match "^#"
|
||||||
|
(file-name-nondirectory file))
|
||||||
(string-match "~$"
|
(string-match "~$"
|
||||||
(file-name-nondirectory file))
|
(file-name-nondirectory file))
|
||||||
(if file?
|
(if file?
|
||||||
@ -1524,13 +1503,23 @@ content of the file is the template."
|
|||||||
(interactive "DSelect the root directory: ")
|
(interactive "DSelect the root directory: ")
|
||||||
(unless (file-directory-p directory)
|
(unless (file-directory-p directory)
|
||||||
(error "Error %s not a directory" directory))
|
(error "Error %s not a directory" directory))
|
||||||
(unless yas/root-directory
|
(unless yas/snippet-dirs
|
||||||
(setq yas/root-directory directory))
|
(setq yas/snippet-dirs directory))
|
||||||
(dolist (dir (yas/subdirs directory))
|
(dolist (dir (yas/subdirs directory))
|
||||||
(yas/load-directory-1 dir))
|
(yas/load-directory-1 dir))
|
||||||
(when (interactive-p)
|
(when (interactive-p)
|
||||||
(message "[yas] Loaded snippets from %s." directory)))
|
(message "[yas] Loaded snippets from %s." directory)))
|
||||||
|
|
||||||
|
(defun yas/load-snippet-dirs ()
|
||||||
|
"Reload the directories listed in `yas/snippet-dirs' or
|
||||||
|
prompt the user to select one."
|
||||||
|
(if yas/snippet-dirs
|
||||||
|
(if (listp yas/snippet-dirs)
|
||||||
|
(dolist (directory (reverse yas/snippet-dirs))
|
||||||
|
(yas/load-directory directory))
|
||||||
|
(yas/load-directory yas/snippet-dirs))
|
||||||
|
(call-interactively 'yas/load-directory)))
|
||||||
|
|
||||||
(defun yas/reload-all (&optional reset-root-directory)
|
(defun yas/reload-all (&optional reset-root-directory)
|
||||||
"Reload all snippets and rebuild the YASnippet menu. "
|
"Reload all snippets and rebuild the YASnippet menu. "
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
@ -1552,16 +1541,16 @@ content of the file is the template."
|
|||||||
(cdr (yas/init-minor-keymap)))
|
(cdr (yas/init-minor-keymap)))
|
||||||
|
|
||||||
(when reset-root-directory
|
(when reset-root-directory
|
||||||
(setq yas/root-directory nil))
|
(setq yas/snippet-dirs nil))
|
||||||
|
|
||||||
;; Reload the directories listed in `yas/root-directory' or prompt
|
;; Reload the directories listed in `yas/snippet-dirs' or prompt
|
||||||
;; the user to select one.
|
;; the user to select one.
|
||||||
;;
|
;;
|
||||||
(if yas/root-directory
|
(if yas/snippet-dirs
|
||||||
(if (listp yas/root-directory)
|
(if (listp yas/snippet-dirs)
|
||||||
(dolist (directory yas/root-directory)
|
(dolist (directory yas/snippet-dirs)
|
||||||
(yas/load-directory directory))
|
(yas/load-directory directory))
|
||||||
(yas/load-directory yas/root-directory))
|
(yas/load-directory yas/snippet-dirs))
|
||||||
(call-interactively 'yas/load-directory))
|
(call-interactively 'yas/load-directory))
|
||||||
;; Reload the direct keybindings
|
;; Reload the direct keybindings
|
||||||
;;
|
;;
|
||||||
@ -1694,7 +1683,7 @@ Here's the default value for all the parameters:
|
|||||||
yasnippet-bundle))))
|
yasnippet-bundle))))
|
||||||
(insert (pp-to-string `(set-default 'yas/dont-activate
|
(insert (pp-to-string `(set-default 'yas/dont-activate
|
||||||
#'(lambda ()
|
#'(lambda ()
|
||||||
(and (or yas/root-directory
|
(and (or yas/snippet-dirs
|
||||||
(featurep ',(make-symbol bundle-feature-name)))
|
(featurep ',(make-symbol bundle-feature-name)))
|
||||||
(null (yas/get-snippet-tables)))))))
|
(null (yas/get-snippet-tables)))))))
|
||||||
(insert (pp-to-string `(provide ',(make-symbol bundle-feature-name)))))
|
(insert (pp-to-string `(provide ',(make-symbol bundle-feature-name)))))
|
||||||
@ -1731,10 +1720,16 @@ following form:
|
|||||||
|
|
||||||
(KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING)
|
(KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING)
|
||||||
|
|
||||||
Within these, only TEMPLATE is actually mandatory.
|
Within these, only KEY and TEMPLATE is actually mandatory.
|
||||||
|
|
||||||
All the elelements are strings, including CONDITION, EXPAND-ENV
|
TEMPLATE might be a lisp form or a string, depending on whether
|
||||||
and KEYBINDING which will be `read' and eventually `eval'-ed.
|
this is a snippet or a snippet-command.
|
||||||
|
|
||||||
|
CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
|
||||||
|
been `yas/read-lisp'-ed and will eventually be
|
||||||
|
`yas/eval-lisp'-ed.
|
||||||
|
|
||||||
|
The remaining elements are strings.
|
||||||
|
|
||||||
FILE is probably of very little use if you're programatically
|
FILE is probably of very little use if you're programatically
|
||||||
defining snippets.
|
defining snippets.
|
||||||
@ -2107,10 +2102,10 @@ visited file in `snippet-mode'."
|
|||||||
|
|
||||||
(defun yas/visit-snippet-file-1 (template)
|
(defun yas/visit-snippet-file-1 (template)
|
||||||
(let ((file (yas/template-file template)))
|
(let ((file (yas/template-file template)))
|
||||||
(cond ((and file (file-exists-p file))
|
(cond ((and file (file-readable-p file))
|
||||||
(find-file-other-window file)
|
(find-file-other-window file)
|
||||||
(setq (make-local-variable 'yas/current-template) template)
|
(snippet-mode)
|
||||||
(snippet-mode))
|
(setq yas/current-template template))
|
||||||
(file
|
(file
|
||||||
(message "Original file %s no longer exists!" file))
|
(message "Original file %s no longer exists!" file))
|
||||||
(t
|
(t
|
||||||
@ -2131,31 +2126,28 @@ visited file in `snippet-mode'."
|
|||||||
(insert (if (eq type 'command)
|
(insert (if (eq type 'command)
|
||||||
(pp-to-string (yas/template-content template))
|
(pp-to-string (yas/template-content template))
|
||||||
(yas/template-content template))))
|
(yas/template-content template))))
|
||||||
(setq (make-local-variable 'yas/current-template) template)
|
(snippet-mode)
|
||||||
(snippet-mode)))))
|
(setq yas/current-template template)))))
|
||||||
|
|
||||||
(defun yas/guess-snippet-directories-1 (table &optional suffix)
|
(defun yas/guess-snippet-directories-1 (table)
|
||||||
"Guesses possible snippet subdirsdirectories for TABLE."
|
"Guesses possible snippet subdirectories for TABLE."
|
||||||
(unless suffix
|
(cons (yas/snippet-table-name table)
|
||||||
(setq suffix (yas/snippet-table-name table)))
|
|
||||||
(cons suffix
|
|
||||||
(mapcan #'(lambda (parent)
|
(mapcan #'(lambda (parent)
|
||||||
(yas/guess-snippet-directories-1
|
(yas/guess-snippet-directories-1
|
||||||
parent
|
parent))
|
||||||
(concat (yas/snippet-table-name parent) "/" suffix)))
|
|
||||||
(yas/snippet-table-parents table))))
|
(yas/snippet-table-parents table))))
|
||||||
|
|
||||||
(defun yas/guess-snippet-directories (&optional table)
|
(defun yas/guess-snippet-directories (&optional table)
|
||||||
"Try to guess suitable directories based on the current active
|
"Try to guess suitable directories based on the current active
|
||||||
tables or optional TABLE.
|
tables (or optional TABLE).
|
||||||
|
|
||||||
Returns a a list of options alist TABLE -> DIRS where DIRS are
|
Returns a a list of options alist TABLE -> DIRS where DIRS are
|
||||||
all the possibly directories where snippets of table might be
|
all the possibly directories where snippets of table might be
|
||||||
lurking."
|
lurking."
|
||||||
(let ((main-dir (or (and (listp yas/root-directory)
|
(let ((main-dir (or (and (listp yas/snippet-dirs)
|
||||||
(first yas/root-directory))
|
(first yas/snippet-dirs))
|
||||||
yas/root-directory
|
yas/snippet-dirs
|
||||||
(setq yas/root-directory "~/.emacs.d/snippets")))
|
(setq yas/snippet-dirs "~/.emacs.d/snippets")))
|
||||||
(tables (or (and table
|
(tables (or (and table
|
||||||
(list table))
|
(list table))
|
||||||
(yas/get-snippet-tables))))
|
(yas/get-snippet-tables))))
|
||||||
@ -2204,8 +2196,7 @@ lurking."
|
|||||||
(yas/snippet-table-name (car (first guessed-directories)))
|
(yas/snippet-table-name (car (first guessed-directories)))
|
||||||
"unknown mode")))
|
"unknown mode")))
|
||||||
(snippet-mode)
|
(snippet-mode)
|
||||||
(set (make-local-variable 'yas/guessed-directories)
|
(setq yas/guessed-directories guessed-directories)
|
||||||
guessed-directories)
|
|
||||||
(unless (and choose-instead-of-guess
|
(unless (and choose-instead-of-guess
|
||||||
(not (y-or-n-p "Insert a snippet with useful headers? ")))
|
(not (y-or-n-p "Insert a snippet with useful headers? ")))
|
||||||
(yas/expand-snippet "\
|
(yas/expand-snippet "\
|
||||||
@ -2246,9 +2237,9 @@ there, otherwise, proposes to create the first option returned by
|
|||||||
(rest guessed-directories)))))
|
(rest guessed-directories)))))
|
||||||
(unless chosen
|
(unless chosen
|
||||||
(when (y-or-n-p "Having trouble... go to snippet root dir? ")
|
(when (y-or-n-p "Having trouble... go to snippet root dir? ")
|
||||||
(setq chosen (if (listp yas/root-directory)
|
(setq chosen (if (listp yas/snippet-dirs)
|
||||||
(first yas/root-directory)
|
(first yas/snippet-dirs)
|
||||||
yas/root-directory))))
|
yas/snippet-dirs))))
|
||||||
(if chosen
|
(if chosen
|
||||||
(let ((default-directory chosen))
|
(let ((default-directory chosen))
|
||||||
(setq buffer (call-interactively (if same-window
|
(setq buffer (call-interactively (if same-window
|
||||||
@ -2283,103 +2274,133 @@ there, otherwise, proposes to create the first option returned by
|
|||||||
(when major-mode-sym
|
(when major-mode-sym
|
||||||
(cons major-mode-sym parents))))
|
(cons major-mode-sym parents))))
|
||||||
|
|
||||||
|
(defvar yas/current-template nil
|
||||||
|
"Supporting variable for `yas/load-snippet-buffer' and `yas/visit-snippet'")
|
||||||
|
(make-variable-buffer-local 'yas/current-template)
|
||||||
|
|
||||||
|
(defvar yas/guessed-directories nil
|
||||||
|
"Supporting variable for `yas/load-snippet-buffer' and `yas/new-snippet'")
|
||||||
|
(make-variable-buffer-local 'yas/guessed-directories)
|
||||||
|
|
||||||
(defun yas/load-snippet-buffer (&optional kill)
|
(defun yas/load-snippet-buffer (&optional kill)
|
||||||
"Parse and load current buffer's snippet definition.
|
"Parse and load current buffer's snippet definition.
|
||||||
|
|
||||||
With optional prefix argument KILL quit the window and buffer."
|
With optional prefix argument KILL quit the window and buffer."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(cond ( ;; X) Option 1: We have a file name, consider this as being
|
(cond
|
||||||
;; a brand new snippet and calculate name, groups, etc from
|
;; X) Option 2: We have `yas/current-template', this buffer's
|
||||||
;; the current file-name and buffer content
|
;; content comes from a template which is already loaded and
|
||||||
;;
|
;; neatly positioned,...
|
||||||
buffer-file-name
|
;;
|
||||||
(let ((major-mode-and-parent (yas/compute-major-mode-and-parents buffer-file-name)))
|
((and (boundp 'yas/current-template)
|
||||||
(if major-mode-and-parent
|
yas/current-template
|
||||||
(let* ((yas/ignore-filenames-as-triggers (or yas/ignore-filenames-as-triggers
|
(yas/template-p yas/current-template))
|
||||||
(locate-dominating-file buffer-file-name ".yas-ignore-filenames-as-triggers")))
|
|
||||||
(parsed (yas/parse-template buffer-file-name))
|
|
||||||
(name (and parsed
|
|
||||||
(third parsed))))
|
|
||||||
(when name
|
|
||||||
(let ((yas/better-guess-for-replacements t))
|
|
||||||
(yas/define-snippets (car major-mode-and-parent)
|
|
||||||
(list parsed)
|
|
||||||
(cdr major-mode-and-parent))))
|
|
||||||
(when (and (buffer-modified-p)
|
|
||||||
(y-or-n-p "Save snippet buffer? "))
|
|
||||||
(save-buffer))
|
|
||||||
(if kill
|
|
||||||
(quit-window kill)
|
|
||||||
(message "[yas] Snippet \"%s\" loaded for %s."
|
|
||||||
name
|
|
||||||
(car major-mode-and-parent))))
|
|
||||||
(message (format "[yas] Unknown major mode for snippet at %s" buffer-file-name)))))
|
|
||||||
;; X) Option 2: We have `yas/current-template', this buffer's
|
|
||||||
;; content comes from a template which is already loaded and
|
|
||||||
;; neatly positioned,...
|
|
||||||
;;
|
|
||||||
((and (boundp 'yas/current-template)
|
|
||||||
yas/current-template
|
|
||||||
(yas/template-p yas/current-template))
|
|
||||||
|
|
||||||
(let ((parsed ((yas/parse-template))))
|
(let ((parsed (yas/parse-template (yas/template-file yas/current-template)))
|
||||||
;; ... just change its template, expand-env, condition, key,
|
(old-key (yas/template-key yas/current-template))
|
||||||
;; keybinding and name. The group cannot be changed.
|
(old-keybinding (yas/template-keybinding yas/current-template))
|
||||||
(setf (yas/template-content yas/current-template) (second parsed))
|
(old-name (yas/template-name yas/current-template)))
|
||||||
(setf (yas/template-key yas/current-template) (first parsed))
|
;; ... just change its template, expand-env, condition, key,
|
||||||
(setf (yas/template-name yas/current-template) (third parsed))
|
;; keybinding and name. The group cannot be changed.
|
||||||
(setf (yas/template-condition yas/current-template) (fourth parsed))
|
(setf (yas/template-content yas/current-template) (second parsed))
|
||||||
(setf (yas/template-expand-env yas/current-template) (sixth parsed))
|
(setf (yas/template-key yas/current-template) (first parsed))
|
||||||
(setf (yas/template-keybinding yas/current-template) (eighth parsed))
|
(setf (yas/template-name yas/current-template) (third parsed))
|
||||||
(yas/update-snippet (yas/template-table yas/current-template)
|
(setf (yas/template-condition yas/current-template) (fourth parsed))
|
||||||
yas/current-template
|
(setf (yas/template-expand-env yas/current-template) (sixth parsed))
|
||||||
(yas/template-name yas/current-template)
|
(setf (yas/template-keybinding yas/current-template) (eighth parsed))
|
||||||
(yas/template-key yas/current-template)
|
(yas/update-snippet (yas/template-table yas/current-template)
|
||||||
(yas/template-keybinding yas/current-template)))
|
yas/current-template
|
||||||
;; ..., if an original file is found offer to overwrite that
|
old-name
|
||||||
;; file. If the file cannot be found, prompt user for
|
old-key
|
||||||
;; creation much like `yas/new-snippet'.
|
old-keybinding))
|
||||||
;;
|
;; Now, prompt for new file creation much like
|
||||||
(if (and (yas/template-file yas/current-template)
|
;; `yas/new-snippet' if one of the following is true:
|
||||||
(file-writable-p (yas/template-file yas/current-template))
|
;;
|
||||||
(y-or-n-p (format "[yas] Save snippet buffer and overwrite %s?"
|
;; 1) `yas/snippet-dirs' is a list and its first element does not
|
||||||
(yas/template-file yas/current-template))))
|
;; match this template's file (i.e. this is a library snippet, not
|
||||||
(write-file (yas/template-file yas/current-template))
|
;; a user snippet).
|
||||||
(let* ((guess (first (yas/guess-snippet-directories (yas/template-table yas/current-template))))
|
;;
|
||||||
(chosen (and guess
|
;; 2) yas/current-template comes from a file that we cannot write to...
|
||||||
(yas/make-directory-maybe option))))
|
;;
|
||||||
(when chosen
|
(when (or (and (listp yas/snippet-dirs)
|
||||||
(let ((default-directory chosen))
|
(second yas/snippet-dirs)
|
||||||
(call-interactively 'write-file))))))
|
(not (string-match (expand-file-name (first yas/snippet-dirs))
|
||||||
;; X) Option 3: We have `yas/guessed-directories', this
|
(yas/template-file yas/current-template))))
|
||||||
;; buffer's content comes from `yas/new-snippet' call. Prompt
|
(and (yas/template-file yas/current-template)
|
||||||
;; user for dir and name in guessed dirs, then call
|
(not (file-writable-p (yas/template-file yas/current-template)))))
|
||||||
;; `yas/load-snippet-buffer' (ourselves) again to load the
|
(when (y-or-n-p "[yas] Also save snippet buffer to new file? ")
|
||||||
;; snippet based on the file-name.
|
(let* ((option (first (yas/guess-snippet-directories (yas/template-table yas/current-template))))
|
||||||
;;
|
(chosen (and option
|
||||||
((and (boundp 'yas/guessed-directories)
|
(yas/make-directory-maybe option))))
|
||||||
yas/guessed-directories)
|
(when chosen
|
||||||
(let* ((guessed-directories yas/guessed-directories)
|
(condition-case quit
|
||||||
(option (or (and (second guessed-directories)
|
(let ((default-directory (concat chosen "/" (yas/template-name yas/current-template)))
|
||||||
(some #'(lambda (fn)
|
(ido-mode nil))
|
||||||
(funcall fn "Choose a snippet table: "
|
(call-interactively 'write-file)
|
||||||
guessed-directories
|
(setf (yas/template-file yas/current-template) buffer-file-name))
|
||||||
#'(lambda (option)
|
(quit nil))))))
|
||||||
(yas/snippet-table-name (car option)))))
|
(when kill
|
||||||
yas/prompt-functions))
|
(quit-window kill))
|
||||||
(first guessed-directories)))
|
(message "[yas] Snippet \"%s\" loaded for %s."
|
||||||
(chosen))
|
(yas/template-name yas/current-template)
|
||||||
(setq chosen (yas/make-directory-maybe option))
|
(yas/snippet-table-name (yas/template-table yas/current-template))))
|
||||||
(unless chosen
|
( ;; X) Option 1: We have a file name, consider this as being
|
||||||
(when (y-or-n-p "Having trouble... use snippet root dir? ")
|
;; a brand new snippet and calculate name, groups, etc from
|
||||||
(setq chosen (if (listp yas/root-directory)
|
;; the current file-name and buffer content
|
||||||
(first yas/root-directory)
|
;;
|
||||||
yas/root-directory))))
|
buffer-file-name
|
||||||
(when chosen
|
(let ((major-mode-and-parent (yas/compute-major-mode-and-parents buffer-file-name)))
|
||||||
(let ((default-directory chosen))
|
(if major-mode-and-parent
|
||||||
(call-interactively 'write-file))
|
(let* ((yas/ignore-filenames-as-triggers (or yas/ignore-filenames-as-triggers
|
||||||
(setq yas/guessed-directories nil)
|
(locate-dominating-file buffer-file-name ".yas-ignore-filenames-as-triggers")))
|
||||||
(yas/load-snippet-buffer))))))
|
(parsed (yas/parse-template buffer-file-name))
|
||||||
|
(name (and parsed
|
||||||
|
(third parsed))))
|
||||||
|
(when name
|
||||||
|
(let ((yas/better-guess-for-replacements t))
|
||||||
|
(yas/define-snippets (car major-mode-and-parent)
|
||||||
|
(list parsed)
|
||||||
|
(cdr major-mode-and-parent))))
|
||||||
|
(when (and (buffer-modified-p)
|
||||||
|
(y-or-n-p "Also save snippet buffer? "))
|
||||||
|
(save-buffer))
|
||||||
|
(when kill
|
||||||
|
(quit-window kill))
|
||||||
|
(message "[yas] Snippet \"%s\" loaded for %s."
|
||||||
|
name
|
||||||
|
(car major-mode-and-parent)))
|
||||||
|
(message (format "[yas] Unknown major mode for snippet at %s" buffer-file-name)))))
|
||||||
|
|
||||||
|
;; X) Option 3: We have `yas/guessed-directories', this
|
||||||
|
;; buffer's content comes from `yas/new-snippet' call. Prompt
|
||||||
|
;; user for dir and name in guessed dirs, then call
|
||||||
|
;; `yas/load-snippet-buffer' (ourselves) again to load the
|
||||||
|
;; snippet based on the file-name.
|
||||||
|
;;
|
||||||
|
((and (boundp 'yas/guessed-directories)
|
||||||
|
yas/guessed-directories)
|
||||||
|
(let* ((guessed-directories yas/guessed-directories)
|
||||||
|
(option (or (and (second guessed-directories)
|
||||||
|
(some #'(lambda (fn)
|
||||||
|
(funcall fn "Choose a snippet table: "
|
||||||
|
guessed-directories
|
||||||
|
#'(lambda (option)
|
||||||
|
(yas/snippet-table-name (car option)))))
|
||||||
|
yas/prompt-functions))
|
||||||
|
(first guessed-directories)))
|
||||||
|
(chosen))
|
||||||
|
(setq chosen (yas/make-directory-maybe option))
|
||||||
|
(unless chosen
|
||||||
|
(when (y-or-n-p "Having trouble... use snippet root dir? ")
|
||||||
|
(setq chosen (if (listp yas/snippet-dirs)
|
||||||
|
(first yas/snippet-dirs)
|
||||||
|
yas/snippet-dirs))))
|
||||||
|
(when chosen
|
||||||
|
(let ((default-directory chosen))
|
||||||
|
(call-interactively 'write-file))
|
||||||
|
(setq yas/guessed-directories nil)
|
||||||
|
(setq yas/current-template nil)
|
||||||
|
(yas/load-snippet-buffer))))))
|
||||||
|
|
||||||
|
|
||||||
(defun yas/tryout-snippet (&optional debug)
|
(defun yas/tryout-snippet (&optional debug)
|
||||||
@ -3949,9 +3970,9 @@ object satisfying `yas/field-p' to restrict the expansion to.")))
|
|||||||
|
|
||||||
(defun yas/debug-test (&optional quiet)
|
(defun yas/debug-test (&optional quiet)
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(yas/load-directory (or (and (listp yas/root-directory)
|
(yas/load-directory (or (and (listp yas/snippet-dirs)
|
||||||
(first yas/root-directory))
|
(first yas/snippet-dirs))
|
||||||
yas/root-directory
|
yas/snippet-dirs
|
||||||
"~/Source/yasnippet/snippets/"))
|
"~/Source/yasnippet/snippets/"))
|
||||||
(set-buffer (switch-to-buffer "*YAS TEST*"))
|
(set-buffer (switch-to-buffer "*YAS TEST*"))
|
||||||
(mapc #'yas/commit-snippet (yas/snippets-at-point 'all-snippets))
|
(mapc #'yas/commit-snippet (yas/snippets-at-point 'all-snippets))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user