branch: master commit 9cedd596ecd41ebf1cc8c854fc22b2de755e926e Author: Noam Postavsky <npost...@users.sourceforge.net> Commit: Noam Postavsky <npost...@users.sourceforge.net>
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