branch: master
commit 9cedd596ecd41ebf1cc8c854fc22b2de755e926e
Author: Noam Postavsky <[email protected]>
Commit: Noam Postavsky <[email protected]>
Allow disabling snippet keybindings from hook
* yasnippet.el (yas-keymap-disable-hook): New hook.
(yas-filtered-definition): New function.
(yas-keymap): Use it.
* doc/faq.org: Update key redefinition example.
---
doc/faq.org | 29 ++++++++++++++++-------------
yasnippet.el | 40 ++++++++++++++++++++++++++++++----------
2 files changed, 46 insertions(+), 23 deletions(-)
diff --git a/doc/faq.org b/doc/faq.org
index cac9068..ebee06a 100644
--- a/doc/faq.org
+++ b/doc/faq.org
@@ -49,21 +49,24 @@ or the [[Github issue
tracker][https://github.com/joaotavora/yasnippet/issues/]]
* How do I use alternative keys, i.e. not TAB?
-Edit the keymaps [[sym:yas-minor-mode-map][=yas-minor-mode-map=]] and
-[[sym:yas-keymap][=yas-keymap=]] as you would any other keymap:
+Edit the keymaps [[sym:yas-minor-mode-map][=yas-minor-mode-map=]] and
[[sym:yas-keymap][=yas-keymap=]] as you would
+any other keymap, but use
[[sym:yas-filtered-definition][=yas-filtered-definition=]] on the definition
+if you want to respect
[[sym:yas-keymap-disable-hook][=yas-keymap-disable-hook=]]:
#+begin_src emacs-lisp :exports code
- (define-key yas-minor-mode-map (kbd "<tab>") nil)
- (define-key yas-minor-mode-map (kbd "TAB") nil)
- (define-key yas-minor-mode-map (kbd "<the new key>") yas-maybe-expand)
-
- ;;keys for navigation
- (define-key yas-keymap [(tab)] nil)
- (define-key yas-keymap (kbd "TAB") nil)
- (define-key yas-keymap [(shift tab)] nil)
- (define-key yas-keymap [backtab] nil)
- (define-key yas-keymap (kbd "<new-next-field-key>")
'yas-next-field-or-maybe-expand)
- (define-key yas-keymap (kbd "<new-prev-field-key>") 'yas-prev)
+ (define-key yas-minor-mode-map (kbd "<tab>") nil)
+ (define-key yas-minor-mode-map (kbd "TAB") nil)
+ (define-key yas-minor-mode-map (kbd "<the new key>") yas-maybe-expand)
+
+ ;;keys for navigation
+ (define-key yas-keymap [(tab)] nil)
+ (define-key yas-keymap (kbd "TAB") nil)
+ (define-key yas-keymap [(shift tab)] nil)
+ (define-key yas-keymap [backtab] nil)
+ (define-key yas-keymap (kbd "<new-next-field-key>")
+ (yas-keymap-disable-hook 'yas-next-field-or-maybe-expand))
+ (define-key yas-keymap (kbd "<new-prev-field-key>")
+ (yas-keymap-disable-hook 'yas-prev))
#+end_src
* How do I define an abbrev key containing characters not supported by the
filesystem?
diff --git a/yasnippet.el b/yasnippet.el
index cc11e8f..ac1c23f 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -413,15 +413,25 @@ This can be used as a key definition in keymaps to bind a
key to
`yas-clear-field' only when at the beginning of an
unmodified snippet field.")
-(defvar yas-keymap (let ((map (make-sparse-keymap)))
- (define-key map [(tab)]
'yas-next-field-or-maybe-expand)
- (define-key map (kbd "TAB")
'yas-next-field-or-maybe-expand)
- (define-key map [(shift tab)] 'yas-prev-field)
- (define-key map [backtab] 'yas-prev-field)
- (define-key map (kbd "C-g") 'yas-abort-snippet)
- (define-key map (kbd "C-d")
yas-maybe-skip-and-clear-field)
- (define-key map (kbd "DEL") yas-maybe-clear-field)
- map)
+(defun yas-filtered-definition (def)
+ "Return a condition key definition.
+The condition will respect the value of `yas-keymap-disable-hook'."
+ `(menu-item "" ,def
+ :filter ,(lambda (cmd) (unless (run-hook-with-args-until-success
+ 'yas-keymap-disable-hook)
+ cmd))))
+
+(defvar yas-keymap
+ (let ((map (make-sparse-keymap)))
+ (define-key map [(tab)] (yas-filtered-definition
'yas-next-field-or-maybe-expand))
+ (define-key map (kbd "TAB") (yas-filtered-definition
'yas-next-field-or-maybe-expand))
+ (define-key map [(shift tab)] (yas-filtered-definition 'yas-prev-field))
+ (define-key map [backtab] (yas-filtered-definition 'yas-prev-field))
+ (define-key map (kbd "C-g") (yas-filtered-definition 'yas-abort-snippet))
+ ;; Yes, filters can be chained!
+ (define-key map (kbd "C-d") (yas-filtered-definition
yas-maybe-skip-and-clear-field))
+ (define-key map (kbd "DEL") (yas-filtered-definition
yas-maybe-clear-field))
+ map)
"The active keymap while a snippet expansion is in progress.")
(defvar yas-key-syntaxes (list #'yas-try-key-from-whitespace
@@ -545,10 +555,16 @@ conditions.
(const :tag "Disable all snippet expansion" nil)
sexp))
+(defcustom yas-keymap-disable-hook nil
+ "The `yas-keymap' bindings are disabled if any function in this list returns
non-nil.
+This is useful to control whether snippet navigation bindings
+override bindings from other packages (e.g., `company-mode')."
+ :type 'hook)
+
(defcustom yas-overlay-priority 100
"Priority to use for yasnippets overlays.
This is useful to control whether snippet navigation bindings
-override bindings from other packages (e.g., `company-mode')."
+override `keymap' overlay property bindings from other packages."
:type 'integer)
@@ -2346,6 +2362,10 @@ object satisfying `yas--field-p' to restrict the
expansion to."
(yas--fallback))))
(defun yas--maybe-expand-from-keymap-filter (cmd)
+ "Check whether a snippet may be expanded.
+If there are expandable snippets, return CMD (this is useful for
+conditional keybindings) or the list of expandable snippet
+template objects if CMD is nil (this is useful as a more general predicate)."
(let* ((yas--condition-cache-timestamp (current-time))
(vec (cl-subseq (this-command-keys-vector)
(if current-prefix-arg