Bind field skip and clear command conditionally

Rather than embedding the conditionality inside the function body, and
hardcoding fallback to `delete-char'.  This allows users who want, for
example, to use backspace for field skipping to simply do

    (define-key yas-minor-mode-map (kbd "DEL")
      yas-maybe-skip-and-clear-field)

* yasnippet.el (yas-skip-and-clear-field, yas-current-field)
(yas--maybe-clear-field-filter): New command and function, extracted
from yas-skip-and-clear-or-delete-char.
(yas-skip-and-clear-or-delete-char): Mark obsolete.
(yas-maybe-skip-and-clear-field): New constant, for conditional
binding.
(yas-keymap): Bind it to `C-d' instead of
`yas-skip-and-clear-or-delete-char'.
* yasnippet-tests.el (delete-numberless-inner-snippet-issue-562): Use
`yas-skip-and-clear-field' instead of
`yas-skip-and-clear-or-delete-char'.
This commit is contained in:
Noam Postavsky 2018-01-20 20:27:21 -05:00
parent 074d670be4
commit ba73f20bc3
2 changed files with 36 additions and 13 deletions

View File

@ -274,7 +274,7 @@ attention to case differences."
(ert-simulate-command '(yas-next-field-or-maybe-expand)) (ert-simulate-command '(yas-next-field-or-maybe-expand))
(should (looking-at "testblable")) (should (looking-at "testblable"))
(ert-simulate-command '(yas-next-field-or-maybe-expand)) (ert-simulate-command '(yas-next-field-or-maybe-expand))
(ert-simulate-command '(yas-skip-and-clear-or-delete-char)) (ert-simulate-command '(yas-skip-and-clear-field))
(should (looking-at "ble")) (should (looking-at "ble"))
(should (null (yas-active-snippets))))) (should (null (yas-active-snippets)))))

View File

@ -396,13 +396,21 @@ It must be set to nil before loading yasnippet to take effect."
;;; User-visible variables ;;; User-visible variables
(defconst yas-maybe-skip-and-clear-field
'(menu-item "" yas-skip-and-clear-field
:filter yas--maybe-clear-field-filter)
"A conditional key definition.
This can be used as a key definition in keymaps to bind a key to
`yas-skip-and-clear-field' only when at the beginning of an
unmodified snippey field.")
(defvar yas-keymap (let ((map (make-sparse-keymap))) (defvar yas-keymap (let ((map (make-sparse-keymap)))
(define-key map [(tab)] 'yas-next-field-or-maybe-expand) (define-key map [(tab)] 'yas-next-field-or-maybe-expand)
(define-key map (kbd "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 [(shift tab)] 'yas-prev-field)
(define-key map [backtab] 'yas-prev-field) (define-key map [backtab] 'yas-prev-field)
(define-key map (kbd "C-g") 'yas-abort-snippet) (define-key map (kbd "C-g") 'yas-abort-snippet)
(define-key map (kbd "C-d") 'yas-skip-and-clear-or-delete-char) (define-key map (kbd "C-d") yas-maybe-skip-and-clear-field)
map) map)
"The active keymap while a snippet expansion is in progress.") "The active keymap while a snippet expansion is in progress.")
@ -3547,22 +3555,37 @@ holds the keymap."
(overlay-put overlay 'yas--snippet snippet) (overlay-put overlay 'yas--snippet snippet)
overlay)) overlay))
(defun yas-current-field ()
"Return the currently active field."
(and yas--active-field-overlay
(overlay-buffer yas--active-field-overlay)
(overlay-get yas--active-field-overlay 'yas--field)))
(defun yas--maybe-clear-field-filter (cmd)
"Return CMD if at start of unmodified snippet field.
Use as a `:filter' argument for a conditional keybinding."
(let ((field (yas-current-field)))
(when (and field
(not (yas--field-modified-p field))
(eq (point) (marker-position (yas--field-start field))))
cmd)))
(defun yas-skip-and-clear-field (&optional field)
"Clears unmodified FIELD if at field start, skips to next tab."
(interactive)
(yas--skip-and-clear (or field (yas-current-field)))
(yas-next-field 1))
(defun yas-skip-and-clear-or-delete-char (&optional field) (defun yas-skip-and-clear-or-delete-char (&optional field)
"Clears unmodified field if at field start, skips to next tab. "Clears unmodified field if at field start, skips to next tab.
Otherwise deletes a character normally by calling `delete-char'." Otherwise deletes a character normally by calling `delete-char'."
(interactive) (interactive)
(let ((field (or field (declare (obsolete "Bind to `yas-maybe-skip-and-clear-field' instead." "0.13"))
(and yas--active-field-overlay (cond ((yas--maybe-clear-field-filter t)
(overlay-buffer yas--active-field-overlay) (yas--skip-and-clear (or field (yas-current-field)))
(overlay-get yas--active-field-overlay 'yas--field))))) (yas-next-field 1))
(cond ((and field (t (call-interactively 'delete-char))))
(not (yas--field-modified-p field))
(eq (point) (marker-position (yas--field-start field))))
(yas--skip-and-clear field)
(yas-next-field 1))
(t
(call-interactively 'delete-char)))))
(defun yas--skip-and-clear (field &optional from) (defun yas--skip-and-clear (field &optional from)
"Deletes the region of FIELD and sets it's modified state to t. "Deletes the region of FIELD and sets it's modified state to t.