mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 13:13:03 +00:00
* Redesigned direct keybinding slightly
* Fixed some bugs * Added fancy docs for functions redefining bindings
This commit is contained in:
parent
14a8eb22fc
commit
493c923b40
206
yasnippet.el
206
yasnippet.el
@ -512,23 +512,11 @@ snippet itself contains a condition that returns the symbol
|
|||||||
|
|
||||||
;;; Internal variables
|
;;; Internal variables
|
||||||
|
|
||||||
(defvar yas/version "0.6.1b")
|
(defvar yas/version "0.7.0")
|
||||||
|
|
||||||
(defvar yas/menu-table (make-hash-table)
|
(defvar yas/menu-table (make-hash-table)
|
||||||
"A hash table of MAJOR-MODE symbols to menu keymaps.")
|
"A hash table of MAJOR-MODE symbols to menu keymaps.")
|
||||||
|
|
||||||
(defvar yas/snippet-keymap-alist nil
|
|
||||||
"Local one-element alist supporting for direct snippet keybindings.
|
|
||||||
|
|
||||||
This variable is automatically buffer local and placed in
|
|
||||||
`emulation-mode-map-alists'.
|
|
||||||
|
|
||||||
Its only element looks like (t . KEYMAP) and is calculated when
|
|
||||||
entering `yas/minor-mode' or loading snippet definitions. KEYMAP
|
|
||||||
binds key sequences to the sole `yas/expand-from-keymap', which
|
|
||||||
acts similarly to `yas/expand'")
|
|
||||||
(make-variable-buffer-local 'yas/snippet-keymap-alist)
|
|
||||||
|
|
||||||
(defun teste ()
|
(defun teste ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(message "AHAHA!"))
|
(message "AHAHA!"))
|
||||||
@ -719,19 +707,38 @@ With optional UNBIND-KEY, try to unbind that key from
|
|||||||
(not (string= yas/trigger-key "")))
|
(not (string= yas/trigger-key "")))
|
||||||
(define-key yas/minor-mode-map (read-kbd-macro yas/trigger-key) 'yas/expand)))
|
(define-key yas/minor-mode-map (read-kbd-macro yas/trigger-key) 'yas/expand)))
|
||||||
|
|
||||||
(defun yas/snippet-keybindings-reload ()
|
|
||||||
(setq yas/snippet-keymap-alist
|
;; (defvar yas/snippet-keymaps nil
|
||||||
(list
|
;; "")
|
||||||
`(t . ,(let ((map (make-sparse-keymap)))
|
;; (make-variable-buffer-local 'yas/snippet-keymaps)
|
||||||
(mapc #'(lambda (table)
|
;; (defun yas/snippet-keymaps-reload ()
|
||||||
(maphash #'(lambda (k v)
|
;; (setq yas/snippet-keymaps nil)
|
||||||
(if (and (vectorp k)
|
;; (mapc #'(lambda (table)
|
||||||
(hash-table-p v)
|
;; (push (cons t
|
||||||
(> (hash-table-count v) 0))
|
;; (yas/snippet-table-keymap table))
|
||||||
(define-key map k 'yas/expand-from-keymap)))
|
;; yas/snippet-keymaps))
|
||||||
(yas/snippet-table-hash table)))
|
;; (yas/get-snippet-tables)))
|
||||||
(yas/get-snippet-tables))
|
|
||||||
map)))))
|
(defvar yas/snippet-keymaps nil
|
||||||
|
"Keymap alist supporting direct snippet keybindings.
|
||||||
|
|
||||||
|
This variable is is placed `emulation-mode-map-alists'.
|
||||||
|
|
||||||
|
Its elements looks like (TABLE-NAME . KEYMAP) and are
|
||||||
|
calculated when loading snippets. TABLE-NAME is a variable
|
||||||
|
set buffer-locally when entering `yas/minor-mode'. KEYMAP binds
|
||||||
|
all defined direct keybindings to the command
|
||||||
|
`yas/expand-from-keymap', which acts similarly to `yas/expand'")
|
||||||
|
(defun yas/snippet-keymaps-reload ()
|
||||||
|
(interactive)
|
||||||
|
(setq yas/snippet-keymaps nil)
|
||||||
|
(maphash #'(lambda (name table)
|
||||||
|
(mapc #'(lambda (table)
|
||||||
|
(push (cons name
|
||||||
|
(yas/snippet-table-keymap table))
|
||||||
|
yas/snippet-keymaps))
|
||||||
|
(cons table (yas/snippet-table-get-all-parents table))))
|
||||||
|
yas/snippet-tables))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(define-minor-mode yas/minor-mode
|
(define-minor-mode yas/minor-mode
|
||||||
@ -752,17 +759,34 @@ Key bindings:
|
|||||||
;; The indicator for the mode line.
|
;; The indicator for the mode line.
|
||||||
" yas"
|
" yas"
|
||||||
:group 'yasnippet
|
:group 'yasnippet
|
||||||
(if yas/minor-mode
|
(cond (yas/minor-mode
|
||||||
(progn
|
;; Reload the trigger key
|
||||||
(add-hook 'emulation-mode-map-alists 'yas/snippet-keymap-alist nil 'local)
|
;;
|
||||||
(yas/snippet-keybindings-reload)
|
(yas/trigger-key-reload)
|
||||||
(yas/trigger-key-reload)
|
;; 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/root-directory)
|
||||||
(> (hash-table-count yas/snippet-tables) 0))
|
(> (hash-table-count yas/snippet-tables) 0))
|
||||||
(yas/reload-all)))
|
(yas/reload-all))
|
||||||
(remove-hook 'emulation-mode-map-alists 'yas/snippet-keymap-alist 'local)))
|
;; Install the direct keymaps in `emulation-mode-map-alists'
|
||||||
|
;; (we use `add-hook' even though it's not technically a hook,
|
||||||
|
;; but it works). Then define variables named after modes to
|
||||||
|
;; index `yas/snippet-keymaps'.
|
||||||
|
;;
|
||||||
|
(add-hook 'emulation-mode-map-alists 'yas/snippet-keymaps nil 'local)
|
||||||
|
(let ((modes-to-activate (list major-mode))
|
||||||
|
(mode major-mode))
|
||||||
|
(while (setq mode (get mode 'derived-mode-parent))
|
||||||
|
(push mode modes-to-activate))
|
||||||
|
(dolist (mode modes-to-activate)
|
||||||
|
(unless (and (boundp mode)
|
||||||
|
(symbol-value mode))
|
||||||
|
(set (make-local-variable mode) t)))))
|
||||||
|
(t
|
||||||
|
;; Uninstall the direct keymaps.
|
||||||
|
;;
|
||||||
|
(remove-hook 'emulation-mode-map-alists 'yas/snippet-keymaps 'local))))
|
||||||
|
|
||||||
(defvar yas/dont-activate #'(lambda ()
|
(defvar yas/dont-activate #'(lambda ()
|
||||||
(and yas/root-directory
|
(and yas/root-directory
|
||||||
@ -774,7 +798,6 @@ this effectively lets you define exceptions to the \"global\"
|
|||||||
behaviour.")
|
behaviour.")
|
||||||
(make-variable-buffer-local 'yas/dont-activate)
|
(make-variable-buffer-local 'yas/dont-activate)
|
||||||
|
|
||||||
|
|
||||||
(defun yas/minor-mode-on ()
|
(defun yas/minor-mode-on ()
|
||||||
"Turn on YASnippet minor mode.
|
"Turn on YASnippet minor mode.
|
||||||
|
|
||||||
@ -883,10 +906,19 @@ Has the following fields:
|
|||||||
`yas/snippet-table-parents'
|
`yas/snippet-table-parents'
|
||||||
|
|
||||||
A list of tables considered parents of this table: i.e. when
|
A list of tables considered parents of this table: i.e. when
|
||||||
searching for expansions they are searched as well."
|
searching for expansions they are searched as well.
|
||||||
|
|
||||||
|
`yas/snippet-keymap'
|
||||||
|
|
||||||
|
A keymap for the snippets in this table that have direct
|
||||||
|
keybindings. This is kept in sync with the keyhash, i.e., all
|
||||||
|
the elements of the keyhash that are vectors appear here as
|
||||||
|
bindings to `yas/expand-from-keymap'.
|
||||||
|
"
|
||||||
name
|
name
|
||||||
(hash (make-hash-table :test 'equal))
|
(hash (make-hash-table :test 'equal))
|
||||||
(parents nil))
|
(parents nil)
|
||||||
|
(keymap (make-sparse-keymap)))
|
||||||
|
|
||||||
;; Apropos storing/updating, this is works with two steps:
|
;; Apropos storing/updating, this is works with two steps:
|
||||||
;;
|
;;
|
||||||
@ -926,19 +958,23 @@ Has the following fields:
|
|||||||
"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 template type-fn)
|
||||||
(dolist (existing-namehash (remove nil (list (gethash key (yas/snippet-table-hash table))
|
(let ((key-and-namehash-alist '())
|
||||||
(when yas/better-guess-for-replacements
|
(namehash-for-key (gethash key (yas/snippet-table-hash table))))
|
||||||
(let (a)
|
(when namehash-for-key
|
||||||
;; "cand" means "candidate for removal"
|
(push (cons key namehash-for-key) key-and-namehash-alist))
|
||||||
(maphash #'(lambda (cand namehash)
|
(when yas/better-guess-for-replacements
|
||||||
(when (and (gethash name namehash)
|
;; "cand" means "candidate for removal"
|
||||||
(funcall type-fn cand))
|
(maphash #'(lambda (cand namehash)
|
||||||
(setq a namehash)))
|
(when (and (gethash name namehash)
|
||||||
(yas/snippet-table-hash table))
|
(funcall type-fn cand))
|
||||||
a)))))
|
(push (cons cand namehash) key-and-namehash-alist)))
|
||||||
(let ((existing-template (gethash name existing-namehash)))
|
(yas/snippet-table-hash table)))
|
||||||
(when existing-template
|
(dolist (elem key-and-namehash-alist)
|
||||||
(remhash name existing-namehash)))))
|
(remhash name (cdr elem))
|
||||||
|
(when (= 0 (hash-table-count (cdr elem)))
|
||||||
|
(remhash (car elem) (yas/snippet-table-hash table))
|
||||||
|
(when (vectorp (car elem))
|
||||||
|
(define-key (yas/snippet-table-keymap table) (car elem) nil))))))
|
||||||
|
|
||||||
(defun yas/add-snippet (table name key template)
|
(defun yas/add-snippet (table name key template)
|
||||||
"Store in TABLE the snippet NAME indexed by KEY and expanding TEMPLATE.
|
"Store in TABLE the snippet NAME indexed by KEY and expanding TEMPLATE.
|
||||||
@ -955,7 +991,9 @@ keybinding)."
|
|||||||
(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)
|
||||||
|
(define-key (yas/snippet-table-keymap table) key 'yas/expand-from-keymap))))
|
||||||
|
|
||||||
(defun yas/fetch (table key)
|
(defun yas/fetch (table key)
|
||||||
"Fetch snippets in TABLE by KEY. "
|
"Fetch snippets in TABLE by KEY. "
|
||||||
@ -1034,6 +1072,7 @@ conditions to filter out potential expansions."
|
|||||||
(eq requirement result)))))
|
(eq requirement result)))))
|
||||||
|
|
||||||
(defun yas/snippet-table-get-all-parents (table)
|
(defun yas/snippet-table-get-all-parents (table)
|
||||||
|
"Returns a list of all parent tables of TABLE"
|
||||||
(let ((parents (yas/snippet-table-parents table)))
|
(let ((parents (yas/snippet-table-parents table)))
|
||||||
(when parents
|
(when parents
|
||||||
(append (copy-list parents)
|
(append (copy-list parents)
|
||||||
@ -1456,7 +1495,7 @@ content of the file is the template."
|
|||||||
(dolist (dir (yas/subdirs directory))
|
(dolist (dir (yas/subdirs directory))
|
||||||
(yas/load-directory-1 dir nil 'no-hierarchy-parents))
|
(yas/load-directory-1 dir nil 'no-hierarchy-parents))
|
||||||
(when (interactive-p)
|
(when (interactive-p)
|
||||||
(message "done.")))
|
(message "[yas] Loaded snippets from %s." 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. "
|
||||||
@ -1490,7 +1529,9 @@ content of the file is the template."
|
|||||||
(yas/load-directory directory))
|
(yas/load-directory directory))
|
||||||
(yas/load-directory yas/root-directory))
|
(yas/load-directory yas/root-directory))
|
||||||
(call-interactively 'yas/load-directory))
|
(call-interactively 'yas/load-directory))
|
||||||
|
;; Reload the direct keybindings
|
||||||
|
;;
|
||||||
|
(yas/snippet-keymaps-reload)
|
||||||
;; Restore the mode configuration
|
;; Restore the mode configuration
|
||||||
;;
|
;;
|
||||||
(when restore-minor-mode
|
(when restore-minor-mode
|
||||||
@ -1740,7 +1781,7 @@ not need to be a real mode."
|
|||||||
;; The trigger key (key can be null if we removed the key)
|
;; The trigger key (key can be null if we removed the key)
|
||||||
(yas/remove-snippet snippet-table name key template #'stringp)
|
(yas/remove-snippet snippet-table name key template #'stringp)
|
||||||
(when key
|
(when key
|
||||||
(yas/add-snippet snippet-table name keybinding template)))
|
(yas/add-snippet snippet-table name key template)))
|
||||||
|
|
||||||
;; Setup the menu groups, reorganizing from group to group if
|
;; Setup the menu groups, reorganizing from group to group if
|
||||||
;; necessary
|
;; necessary
|
||||||
@ -1859,7 +1900,7 @@ object satisfying `yas/field-p' to restrict the expansion to."
|
|||||||
(yas/fallback 'trigger-key))))
|
(yas/fallback 'trigger-key))))
|
||||||
|
|
||||||
(defun yas/expand-from-keymap ()
|
(defun yas/expand-from-keymap ()
|
||||||
"Directly expand some snippets, searching `yas/snippet-keymap-alist'.
|
"Directly expand some snippets, searching `yas/snippet-keymaps'.
|
||||||
|
|
||||||
If expansion fails, execute the previous binding for this key"
|
If expansion fails, execute the previous binding for this key"
|
||||||
(interactive)
|
(interactive)
|
||||||
@ -1897,7 +1938,7 @@ Common gateway for `yas/expand-from-trigger-key' and
|
|||||||
nil)
|
nil)
|
||||||
((eq yas/fallback-behavior 'call-other-command)
|
((eq yas/fallback-behavior 'call-other-command)
|
||||||
(let* ((yas/minor-mode nil)
|
(let* ((yas/minor-mode nil)
|
||||||
(yas/snippet-keymap-alist nil)
|
(yas/snippet-keymaps nil)
|
||||||
(keys-1 (this-command-keys-vector))
|
(keys-1 (this-command-keys-vector))
|
||||||
(keys-2 (and yas/trigger-key
|
(keys-2 (and yas/trigger-key
|
||||||
from-trigger-key-p
|
from-trigger-key-p
|
||||||
@ -3512,6 +3553,50 @@ When multiple expressions are found, only the last one counts."
|
|||||||
((not (yas/undo-in-progress))
|
((not (yas/undo-in-progress))
|
||||||
;; When not in an undo, check if we must commit the snippet (use exited it).
|
;; When not in an undo, check if we must commit the snippet (use exited it).
|
||||||
(yas/check-commit-snippet))))
|
(yas/check-commit-snippet))))
|
||||||
|
|
||||||
|
;;; Fancy docs:
|
||||||
|
|
||||||
|
(put 'yas/expand 'function-documentation '(yas/expand-from-trigger-key-doc))
|
||||||
|
(defun yas/expand-from-trigger-key-doc ()
|
||||||
|
"A doc synthethizer for `yas/expand-from-trigger-key-doc'."
|
||||||
|
(let ((which-means (cond ((eq yas/fallback-behavior 'call-other-command)
|
||||||
|
(concat ", which means that if no snippets are eligible then this\nfalls back to "
|
||||||
|
(let* ((yas/minor-mode nil)
|
||||||
|
(fallback (key-binding (read-kbd-macro yas/trigger-key))))
|
||||||
|
(or (and fallback
|
||||||
|
(format "the command `%s'." (pp-to-string fallback)))
|
||||||
|
"nothing, in this case."))))
|
||||||
|
((eq yas/fallback-behavior 'return-nil)
|
||||||
|
", which means nothing is done if no snippets are eligible.")
|
||||||
|
(t
|
||||||
|
", which means I hope you know what you're doing :-)"))))
|
||||||
|
(concat "Expand a snippet before point.
|
||||||
|
|
||||||
|
If no snippet expansion is possible, fall back to the behaviour
|
||||||
|
defined in `yas/fallback-behavior' which in this case would be:\n\n"
|
||||||
|
(pp-to-string yas/fallback-behavior)
|
||||||
|
"\n\n"
|
||||||
|
which-means
|
||||||
|
"\n\nOptional argument FIELD is for non-interactive use and is an
|
||||||
|
object satisfying `yas/field-p' to restrict the expansion to.")))
|
||||||
|
|
||||||
|
(put 'yas/expand-from-keymap 'function-documentation '(yas/expand-from-keymap-doc))
|
||||||
|
(defun yas/expand-from-keymap-doc ()
|
||||||
|
"A doc synthethizer for `yas/expand-from-keymap-doc'."
|
||||||
|
(concat "Expand some snippets from keymaps.\n\n"
|
||||||
|
(when (eq this-command 'describe-key)
|
||||||
|
(let* ((vec (this-single-command-keys))
|
||||||
|
(templates (mapcan #'(lambda (table)
|
||||||
|
(yas/fetch table vec))
|
||||||
|
(yas/get-snippet-tables))))
|
||||||
|
(concat "In this particular case my guess it is would expand the snippets:\n\n"
|
||||||
|
(mapconcat #'car templates "\n"))))
|
||||||
|
"\n\nIf no snippet expansion is possible then this falls back to \n"
|
||||||
|
(let* ((yas/minor-mode nil)
|
||||||
|
(fallback (key-binding (read-kbd-macro yas/trigger-key))))
|
||||||
|
(or (and fallback
|
||||||
|
(format "the command `%s'." (pp-to-string fallback)))
|
||||||
|
"nothing, in this case."))))
|
||||||
|
|
||||||
|
|
||||||
;;; Debug functions. Use (or change) at will whenever needed.
|
;;; Debug functions. Use (or change) at will whenever needed.
|
||||||
@ -3724,3 +3809,6 @@ handle the end-of-buffer error fired in it by calling
|
|||||||
(provide 'yasnippet)
|
(provide 'yasnippet)
|
||||||
|
|
||||||
;;; yasnippet.el ends here
|
;;; yasnippet.el ends here
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user