Closes #296: No longer use customizable yas-trigger-key and friends.

Use keymaps that the user can customise with `define-key` like all the
other modes
This commit is contained in:
João Távora 2012-11-06 14:12:18 +00:00
parent f836621480
commit cd70010b83
2 changed files with 49 additions and 146 deletions

View File

@ -444,21 +444,19 @@ TODO: be meaner"
(yas-minor-mode 1) (yas-minor-mode 1)
(should (eq (key-binding (yas--read-keybinding "<tab>")) 'yas-expand)) (should (eq (key-binding (yas--read-keybinding "<tab>")) 'yas-expand))
(yas-expand-snippet "$1 $2 $3") (yas-expand-snippet "$1 $2 $3")
(dolist (k (if (listp yas-next-field-key) (should (eq (key-binding [(tab)]) 'yas-next-field-or-maybe-expand))
yas-next-field-key (should (eq (key-binding (kbd "TAB")) 'yas-next-field-or-maybe-expand))
(list yas-next-field-key))) (should (eq (key-binding [(shift tab)]) 'yas-prev-field))
(should (eq (key-binding (yas--read-keybinding k)) 'yas-next-field-or-maybe-expand))) (should (eq (key-binding [backtab]) 'yas-prev-field))))
(dolist (k (if (listp yas-prev-field-key)
yas-prev-field-key
(list yas-prev-field-key)))
(should (eq (key-binding (yas--read-keybinding k)) 'yas-prev-field)))))
(ert-deftest test-yas-in-org () (ert-deftest test-yas-in-org ()
(with-temp-buffer (with-temp-buffer
(org-mode) (org-mode)
(yas-minor-mode 1) (yas-minor-mode 1)
(should (eq (key-binding (yas--read-keybinding "<tab>")) 'yas-expand)))) (should (eq (key-binding [(tab)]) 'yas-expand))
(should (eq (key-binding (kbd "TAB")) 'yas-expand))))
;;; Helpers ;;; Helpers
;;; ;;;
(defun yas/ert () (defun yas/ert ()

View File

@ -63,7 +63,8 @@
;; M-x yas-expand ;; M-x yas-expand
;; ;;
;; Try to expand snippets before point. In `yas-minor-mode', ;; Try to expand snippets before point. In `yas-minor-mode',
;; this is bound to `yas-trigger-key' which you can customize. ;; this is normally bound to TAB, but you can customize it in
;; `yas-minor-mode-map'.
;; ;;
;; M-x yas-load-directory ;; M-x yas-load-directory
;; ;;
@ -236,81 +237,20 @@ Naturally this is only valid when `yas-indent-line' is `auto'"
:type 'boolean :type 'boolean
:group 'yasnippet) :group 'yasnippet)
(defcustom yas-trigger-key "<tab>"
"The key bound to `yas-expand' when `yas-minor-mode' is active.
Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'."
:type 'string
:group 'yasnippet
:set #'(lambda (symbol key)
(let ((old (and (boundp symbol)
(symbol-value symbol))))
(set-default symbol key)
;; On very first loading of this defcustom,
;; `yas-trigger-key' is *not* loaded.
(if (fboundp 'yas--trigger-key-reload)
(yas--trigger-key-reload old)))))
(defcustom yas-next-field-key '("TAB" "<tab>")
"The key to navigate to next field when a snippet is active.
Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'.
Can also be a list of strings."
:type '(choice (string :tag "String")
(repeat :args (string) :tag "List of strings"))
:group 'yasnippet
:set #'(lambda (symbol val)
(set-default symbol val)
(if (fboundp 'yas--init-yas-in-snippet-keymap)
(yas--init-yas-in-snippet-keymap))))
(defcustom yas-prev-field-key '("<backtab>" "<S-tab>")
"The key to navigate to previous field when a snippet is active.
Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'.
Can also be a list of strings."
:type '(choice (string :tag "String")
(repeat :args (string) :tag "List of strings"))
:group 'yasnippet
:set #'(lambda (symbol val)
(set-default symbol val)
(if (fboundp 'yas--init-yas-in-snippet-keymap)
(yas--init-yas-in-snippet-keymap))))
(defcustom yas-skip-and-clear-key '("C-d" "<delete>" "<deletechar>")
"The key to clear the currently active field.
Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'.
Can also be a list of strings."
:type '(choice (string :tag "String")
(repeat :args (string) :tag "List of strings"))
:group 'yasnippet
:set #'(lambda (symbol val)
(set-default symbol val)
(if (fboundp 'yas--init-yas-in-snippet-keymap)
(yas--init-yas-in-snippet-keymap))))
(defcustom yas-triggers-in-field nil (defcustom yas-triggers-in-field nil
"If non-nil, `yas-next-field-key' can trigger stacked expansions. "If non-nil, allow stacked expansions (snippets inside snippets).
Otherwise, `yas-next-field-key' just tries to move on to the next Otherwise `yas-next-field-or-maybe-expand' just moves on to the
field" next field"
:type 'boolean :type 'boolean
:group 'yasnippet) :group 'yasnippet)
(defcustom yas-fallback-behavior 'call-other-command (defcustom yas-fallback-behavior 'call-other-command
"How to act when `yas-trigger-key' does *not* expand a snippet. "How to act when `yas-expand' does *not* expand a snippet.
- `call-other-command' means try to temporarily disable YASnippet - `call-other-command' means try to temporarily disable YASnippet
and call the next command bound to `yas-trigger-key'. and call the next command bound to whatever key was used to
invoke `yas-expand'.
- nil or the symbol `return-nil' mean do nothing. (and - nil or the symbol `return-nil' mean do nothing. (and
`yas-expand' returns nil) `yas-expand' returns nil)
@ -417,28 +357,15 @@ the trigger key itself."
:group 'yasnippet) :group 'yasnippet)
;;; User can also customize the next defvars (defvar yas-keymap (let ((map (make-sparse-keymap)))
(define-key map [(tab)] 'yas-next-field-or-maybe-expand)
(defun yas--define-some-keys (keys keymap definition) (define-key map (kbd "TAB") 'yas-next-field-or-maybe-expand)
"Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'." (define-key map [(shift tab)] 'yas-prev-field)
(let ((keys (or (and (listp keys) keys) (define-key map [backtab] 'yas-prev-field)
(list keys)))) (define-key map (kbd "C-g") 'yas-abort-snippet)
(dolist (key keys) (define-key map (kbd "C-d") 'yas-skip-and-clear-or-delete-char)
(define-key keymap (read-kbd-macro key) definition)))) map)
"The active keymap while a snippet expansion is in progress.")
(defun yas--init-yas-in-snippet-keymap ()
(setq yas-keymap
(let ((map (make-sparse-keymap)))
(mapc #'(lambda (binding)
(yas--define-some-keys (car binding) map (cdr binding)))
`((,yas-next-field-key . yas-next-field-or-maybe-expand)
(,yas-prev-field-key . yas-prev-field)
("C-g" . yas-abort-snippet)
(,yas-skip-and-clear-key . yas-skip-and-clear-or-delete-char)))
map)))
(defvar yas-keymap (yas--init-yas-in-snippet-keymap)
"The keymap active while a snippet expansion is in progress.")
(defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ") (defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ")
"List of character syntaxes used to find a trigger key before point. "List of character syntaxes used to find a trigger key before point.
@ -694,6 +621,8 @@ snippet itself contains a condition that returns the symbol
;; Now for the stuff that has direct keybindings ;; Now for the stuff that has direct keybindings
;; ;;
(define-key map [(tab)] 'yas-expand)
(define-key map (kbd "TAB") 'yas-expand)
(define-key map "\C-c&\C-s" 'yas-insert-snippet) (define-key map "\C-c&\C-s" 'yas-insert-snippet)
(define-key map "\C-c&\C-n" 'yas-new-snippet) (define-key map "\C-c&\C-n" 'yas-new-snippet)
(define-key map "\C-c&\C-v" 'yas-visit-snippet-file) (define-key map "\C-c&\C-v" 'yas-visit-snippet-file)
@ -702,20 +631,6 @@ snippet itself contains a condition that returns the symbol
(defvar yas-minor-mode-map (yas--init-minor-keymap) (defvar yas-minor-mode-map (yas--init-minor-keymap)
"The keymap used when `yas-minor-mode' is active.") "The keymap used when `yas-minor-mode' is active.")
(defun yas--trigger-key-reload (&optional unbind-key)
"Rebind `yas-expand' to the new value of `yas-trigger-key'.
With optional UNBIND-KEY, try to unbind that key from
`yas-minor-mode-map'."
(when (and unbind-key
(stringp unbind-key)
(not (string= unbind-key "")))
(define-key yas-minor-mode-map (read-kbd-macro unbind-key) nil))
(when (and yas-trigger-key
(stringp yas-trigger-key)
(not (string= yas-trigger-key "")))
(define-key yas-minor-mode-map (read-kbd-macro yas-trigger-key) 'yas-expand)))
(defvar yas--tables (make-hash-table) (defvar yas--tables (make-hash-table)
"A hash table of mode symbols to `yas--table' objects.") "A hash table of mode symbols to `yas--table' objects.")
@ -774,15 +689,14 @@ and friends."
(define-minor-mode yas-minor-mode (define-minor-mode yas-minor-mode
"Toggle YASnippet mode. "Toggle YASnippet mode.
When YASnippet mode is enabled, the `yas-trigger-key' key expands When YASnippet mode is enabled, `yas-expand', normally bound to
snippets of code depending on the major mode. the TAB key, expands snippets of code depending on the major
mode.
With no argument, this command toggles the mode. With no argument, this command toggles the mode.
positive prefix argument turns on the mode. positive prefix argument turns on the mode.
Negative prefix argument turns off the mode. Negative prefix argument turns off the mode.
You can customize the key through `yas-trigger-key'.
Key bindings: Key bindings:
\\{yas-minor-mode-map}" \\{yas-minor-mode-map}"
nil nil
@ -790,9 +704,6 @@ Key bindings:
" yas" " yas"
:group 'yasnippet :group 'yasnippet
(cond (yas-minor-mode (cond (yas-minor-mode
;; Reload the trigger key
;;
(yas--trigger-key-reload)
;; Install the direct keymaps in `emulation-mode-map-alists' ;; Install the direct keymaps in `emulation-mode-map-alists'
;; (we use `add-hook' even though it's not technically a hook, ;; (we use `add-hook' even though it's not technically a hook,
;; but it works). Then define variables named after modes to ;; but it works). Then define variables named after modes to
@ -1800,9 +1711,6 @@ loading."
;; Reload the direct keybindings ;; Reload the direct keybindings
;; ;;
(yas-direct-keymaps-reload) (yas-direct-keymaps-reload)
;; Reload the trigger-key (shoudn't be needed, but see issue #237)
;;
(yas--trigger-key-reload)
(yas--message 3 "Reloaded everything%s...%s." (yas--message 3 "Reloaded everything%s...%s."
(if interactive "" " (snippets will load just-in-time)") (if interactive "" " (snippets will load just-in-time)")
@ -2259,12 +2167,10 @@ expand immediately. Common gateway for
;; Apropos the trigger key and the fallback binding: ;; Apropos the trigger key and the fallback binding:
;; ;;
;; When `yas-trigger-key' is <tab> it correctly overrides ;; When `yas-minor-mode-map' binds <tab>, that correctly overrides
;; org-mode's <tab>, for example and searching for fallbacks ;; org-mode's <tab>, for example and searching for fallbacks correctly
;; correctly returns `org-cycle'. However, most other modes bind ;; returns `org-cycle'. However, most other modes bind "TAB". TODO,
;; "TAB" (which is translated from <tab>), and calling ;; improve this explanation.
;; (key-binding "TAB") does not place return that command into
;; our command-2 local. So we cheat.
;; ;;
(defun yas--fallback (&optional from-trigger-key-p) (defun yas--fallback (&optional from-trigger-key-p)
"Fallback after expansion has failed. "Fallback after expansion has failed.
@ -2275,15 +2181,11 @@ Common gateway for `yas-expand-from-trigger-key' and
;; return nil ;; return nil
nil) nil)
((eq yas-fallback-behavior 'call-other-command) ((eq yas-fallback-behavior 'call-other-command)
(let* ((yas-minor-mode nil) (let* ((beyond-yasnippet (yas--keybinding-beyond-yasnippet)))
(yas--direct-keymaps nil)
(keys (this-single-command-keys))
(beyond-yasnippet (or (key-binding keys t)
(key-binding (yas--fallback-translate-input keys) t))))
(yas--message 4 "Falling back to %s" beyond-yasnippet) (yas--message 4 "Falling back to %s" beyond-yasnippet)
(when (commandp beyond-yasnippet) (assert (or (null beyond-yasnippet) (commandp beyond-yasnippet)))
(setq this-original-command beyond-yasnippet) (setq this-original-command beyond-yasnippet)
(call-interactively beyond-yasnippet)))) (call-interactively beyond-yasnippet)))
((and (listp yas-fallback-behavior) ((and (listp yas-fallback-behavior)
(cdr yas-fallback-behavior) (cdr yas-fallback-behavior)
(eq 'apply (car yas-fallback-behavior))) (eq 'apply (car yas-fallback-behavior)))
@ -2297,11 +2199,19 @@ Common gateway for `yas-expand-from-trigger-key' and
;; also return nil if all the other fallbacks have failed ;; also return nil if all the other fallbacks have failed
nil))) nil)))
(defun yas--keybinding-beyond-yasnippet ()
"Returns the "
(let* ((yas-minor-mode nil)
(yas--direct-keymaps nil)
(keys (this-single-command-keys)))
(or (key-binding keys t)
(key-binding (yas--fallback-translate-input keys) t))))
(defun yas--fallback-translate-input (keys) (defun yas--fallback-translate-input (keys)
"Emulate `read-key-sequence', at least what I think it does. "Emulate `read-key-sequence', at least what I think it does.
Keys should be an untranslated key vector. Returns a translated Keys should be an untranslated key vector. Returns a translated
vector of keys. XXX not working yet" vector of keys. FIXME not thoroughly tested"
(let ((retval []) (let ((retval [])
(i 0)) (i 0))
(while (< i (length keys)) (while (< i (length keys))
@ -4259,15 +4169,14 @@ When multiple expressions are found, only the last one counts."
"A doc synthethizer for `yas--expand-from-trigger-key-doc'." "A doc synthethizer for `yas--expand-from-trigger-key-doc'."
(let ((fallback-description (let ((fallback-description
(cond ((eq yas-fallback-behavior 'call-other-command) (cond ((eq yas-fallback-behavior 'call-other-command)
(let* ((yas-minor-mode nil) (let* ((fallback (yas--keybinding-beyond-yasnippet)))
(fallback (key-binding (read-kbd-macro (yas--trigger-key-for-fallback)))))
(or (and fallback (or (and fallback
(format " call command `%s'." (pp-to-string fallback))) (format " call command `%s'." (pp-to-string fallback)))
" do nothing."))) " do nothing (`yas-expand' doesn't shadow\nanything)")))
((eq yas-fallback-behavior 'return-nil) ((eq yas-fallback-behavior 'return-nil)
", do nothing.") ", do nothing.")
(t (t
", defer to `yas--fallback-behaviour' :-)")))) ", defer to `yas-fallback-behaviour' (which see)"))))
(concat "Expand a snippet before point. If no snippet (concat "Expand a snippet before point. If no snippet
expansion is possible," expansion is possible,"
fallback-description fallback-description
@ -4446,10 +4355,6 @@ handle the end-of-buffer error fired in it by calling
yas-indent-line yas-indent-line
yas-also-auto-indent-first-line yas-also-auto-indent-first-line
yas-snippet-revival yas-snippet-revival
yas-trigger-key
yas-next-field-key
yas-prev-field-key
yas-skip-and-clear-key
yas-triggers-in-field yas-triggers-in-field
yas-fallback-behavior yas-fallback-behavior
yas-choose-keys-first yas-choose-keys-first