branch: master
commit ff26e3ba7f44209413a7bcf62c7ff84ce0aa8143
Author: João Távora <[email protected]>
Commit: João Távora <[email protected]>
Close #824: Simple fields can be parented like other fields or mirrors
The fact that they didn't prevented a deletion of the parent field to
also delete the child, confusing snippet navigation.
* yasnippet-tests.el (delete-nested-simple-field-issue-824): Add a
test for this issue.
* yasnippet.el (yas--calculate-simple-fom-parentage): Renamed from
yas--calculate-mirrors-in-fields. Generalize to FOMs.
(yas--transform-mirror-parse-create): Call yas--simple-fom-create
and yas--calculate-simple-fom-parentage.
(yas--simple-fom-create): Rename from
yas--simple-mirror-parse-create. Call
yas--calculate-simple-fom-parentage also for fields.
---
yasnippet-tests.el | 11 +++++++++++
yasnippet.el | 51 +++++++++++++++++++++++++++++----------------------
2 files changed, 40 insertions(+), 22 deletions(-)
diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 1b62fa6..e40c6fd 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -278,6 +278,17 @@ attention to case differences."
(should (looking-at "ble"))
(should (null (yas-active-snippets)))))
+(ert-deftest delete-nested-simple-field-issue-824 ()
+ "Test deleting a field with a nested simple field in it."
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (yas-expand-snippet "${3:so-$4and}$0${2:-so}")
+ (ert-simulate-command '(yas-next-field-or-maybe-expand))
+ (should (looking-at "so-and-so"))
+ (ert-simulate-command '(yas-skip-and-clear-or-delete-char))
+ (should (looking-at "-so"))
+ (should (null (yas-active-snippets)))))
+
(ert-deftest ignore-trailing-whitespace ()
(should (equal
(with-temp-buffer
diff --git a/yasnippet.el b/yasnippet.el
index ac8a01d..43bc860 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -3996,22 +3996,27 @@ has to be called before the $-constructs are deleted."
(when soup
(cl-reduce link-foms soup)))))
-(defun yas--calculate-mirrors-in-fields (snippet mirror)
- "Attempt to assign a parent field of SNIPPET to the mirror MIRROR.
+(defun yas--calculate-simple-fom-parentage (snippet fom)
+ "Discover if FOM is parented by some field in SNIPPET.
Use the tightest containing field if more than one field contains
the mirror. Intended to be called *before* the dollar-regions are
deleted."
(let ((min (point-min))
(max (point-max)))
- (dolist (field (yas--snippet-fields snippet))
- (when (and (<= (yas--field-start field) (yas--mirror-start mirror))
- (<= (yas--mirror-end mirror) (yas--field-end field))
+ (dolist (field (remq fom (yas--snippet-fields snippet)))
+ (when (and (<= (yas--field-start field) (yas--fom-start fom))
+ (<= (yas--fom-end fom) (yas--field-end field))
(< min (yas--field-start field))
(< (yas--field-end field) max))
(setq min (yas--field-start field)
max (yas--field-end field))
- (setf (yas--mirror-parent-field mirror) field)))))
+ (cond ((yas--field-p fom)
+ (setf (yas--field-parent-field fom) field))
+ ((yas--mirror-p fom)
+ (setf (yas--mirror-parent-field fom) field))
+ (t ; it's an exit, so noop
+ nil ))))))
(defun yas--advance-end-maybe (fom newend)
"Maybe advance FOM's end to NEWEND if it needs it.
@@ -4082,7 +4087,7 @@ Meant to be called in a narrowed buffer, does various
passes"
(goto-char parse-start)
(yas--field-parse-create snippet) ; Parse fields with {}.
(goto-char parse-start)
- (yas--simple-mirror-parse-create snippet) ; Parse simple mirrors &
fields.
+ (yas--simple-fom-create snippet) ; Parse simple mirrors & fields.
(goto-char parse-start)
(yas--transform-mirror-parse-create snippet) ; Parse mirror transforms.
;; Invalidate any syntax-propertizing done while
@@ -4487,10 +4492,10 @@ When multiple expressions are found, only the last one
counts."
(when brand-new-mirror
(push brand-new-mirror
(yas--field-mirrors field))
- (yas--calculate-mirrors-in-fields snippet brand-new-mirror)
+ (yas--calculate-simple-fom-parentage snippet brand-new-mirror)
(push (cons (match-beginning 0) real-match-end-0)
yas--dollar-regions)))))
-(defun yas--simple-mirror-parse-create (snippet)
+(defun yas--simple-fom-create (snippet)
"Parse the simple \"$n\" fields/mirrors/exitmarkers in SNIPPET."
(while (re-search-forward yas--simple-mirror-regexp nil t)
(let ((number (string-to-number (match-string-no-properties 1))))
@@ -4500,20 +4505,22 @@ When multiple expressions are found, only the last one
counts."
(push (cons (match-beginning 0) (yas--exit-marker
(yas--snippet-exit snippet)))
yas--dollar-regions))
(t
- (let ((field (yas--snippet-find-field snippet number)))
+ (let ((field (yas--snippet-find-field snippet number))
+ (fom))
(if field
- (let ((brand-new-mirror (yas--make-mirror
- (yas--make-marker (match-beginning
0))
- (yas--make-marker (match-beginning
0))
- nil)))
- (push brand-new-mirror
- (yas--field-mirrors field))
- (yas--calculate-mirrors-in-fields snippet
brand-new-mirror))
- (push (yas--make-field number
- (yas--make-marker (match-beginning 0))
- (yas--make-marker (match-beginning 0))
- nil)
- (yas--snippet-fields snippet))))
+ (push
+ (setq fom (yas--make-mirror
+ (yas--make-marker (match-beginning 0))
+ (yas--make-marker (match-beginning 0))
+ nil))
+ (yas--field-mirrors field))
+ (push
+ (setq fom (yas--make-field number
+ (yas--make-marker
(match-beginning 0))
+ (yas--make-marker
(match-beginning 0))
+ nil))
+ (yas--snippet-fields snippet)))
+ (yas--calculate-simple-fom-parentage snippet fom))
(push (cons (match-beginning 0) (match-end 0))
yas--dollar-regions))))))