;; (should (string= (yas--buffer-contents)
;; "brother from another mother!"))))
+(ert-deftest dont-clear-on-partial-deletion-issue-515 ()
+ "Ensure fields are not cleared when user doesn't really mean to."
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (yas-expand-snippet "my ${1:kid brother} from another ${2:mother}")
+
+ (ert-simulate-command '(kill-word 1))
+ (ert-simulate-command '(delete-char 1))
+
+ (should (string= (yas--buffer-contents)
+ "my brother from another mother"))
+ (should (looking-at "brother"))
+
+ (ert-simulate-command '(yas-next-field))
+ (should (looking-at "mother"))
+ (ert-simulate-command '(yas-prev-field))
+ (should (looking-at "brother"))))
+
+(ert-deftest do-clear-on-yank-issue-515 ()
+ "A yank should clear an unmodified field."
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (yas-expand-snippet "my ${1:kid brother} from another ${2:mother}")
+ (yas-mock-yank "little sibling")
+ (should (string= (yas--buffer-contents)
+ "my little sibling from another mother"))
+ (ert-simulate-command '(yas-next-field))
+ (ert-simulate-command '(yas-prev-field))
+ (should (looking-at "little sibling"))))
+
\f
;;; Snippet expansion and character escaping
;;; Thanks to @zw963 (Billy) for the testing
(let ((last-command-event (aref string i)))
(ert-simulate-command '(self-insert-command 1)))))
+(defun yas-mock-yank (string)
+ (let ((interprogram-paste-function (lambda () string)))
+ (ert-simulate-command '(yank nil))))
+
(defun yas-make-file-or-dirs (ass)
(let ((file-or-dir-name (car ass))
(content (cdr ass)))
(defvaralias 'yas/root-directory 'yas-snippet-dirs)
(defcustom yas-new-snippet-default "\
-# -*- mode: snippet; require-final-newline: nil -*-
+# -*- mode: snippet -*-
# name: $1
-# key: ${2:${1:$(yas--key-from-desc yas-text)}}${3:
-# binding: ${4:direct-keybinding}}
+# key: ${2:${1:$(yas--key-from-desc yas-text)}}
# --
$0"
"Default snippet to use when creating a new snippet.
:type 'string
:group 'yasnippet)
-(defcustom yas-prompt-functions '(yas-x-prompt
- yas-dropdown-prompt
+(defcustom yas-prompt-functions '(yas-dropdown-prompt
yas-completing-prompt
yas-maybe-ido-prompt
yas-no-prompt)
(overlay-put yas--active-field-overlay 'insert-behind-hooks
'(yas--on-field-overlay-modification))))
-(defun yas--on-field-overlay-modification (overlay after? _beg _end &optional _length)
+(defun yas--skip-and-clear-field-p (field _beg _end &optional _length)
+ "Tell if newly modified FIELD should be cleared and skipped.
+BEG, END and LENGTH like overlay modification hooks."
+ (and (not (yas--field-modified-p field))
+ (= (point) (yas--field-start field))
+ (require 'delsel)
+ ;; `yank' sets `this-command' to t during execution.
+ (let* ((command (if (commandp this-command) this-command
+ this-original-command))
+ (clearp (if (symbolp command) (get command 'delete-selection))))
+ (when (and (not (memq clearp '(yank supersede kill)))
+ (functionp clearp))
+ (setq clearp (funcall clearp)))
+ clearp)))
+
+(defun yas--on-field-overlay-modification (overlay after? beg end &optional length)
"Clears the field and updates mirrors, conditionally.
Only clears the field if it hasn't been modified and point is at
(yas--field-update-display field))
(yas--update-mirrors snippet))
(field
- (when (and (eq this-command 'self-insert-command)
- (not (yas--field-modified-p field))
- (= (point) (yas--field-start field)))
+ (when (yas--skip-and-clear-field-p field beg end)
(yas--skip-and-clear field))
(setf (yas--field-modified-p field) t))))))
\f