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.
This commit is contained in:
João Távora 2018-01-23 16:37:33 +00:00
parent 16c2b38bce
commit ff26e3ba7f
2 changed files with 40 additions and 22 deletions

View File

@ -278,6 +278,17 @@ attention to case differences."
(should (looking-at "ble")) (should (looking-at "ble"))
(should (null (yas-active-snippets))))) (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 () (ert-deftest ignore-trailing-whitespace ()
(should (equal (should (equal
(with-temp-buffer (with-temp-buffer

View File

@ -3996,22 +3996,27 @@ has to be called before the $-constructs are deleted."
(when soup (when soup
(cl-reduce link-foms soup))))) (cl-reduce link-foms soup)))))
(defun yas--calculate-mirrors-in-fields (snippet mirror) (defun yas--calculate-simple-fom-parentage (snippet fom)
"Attempt to assign a parent field of SNIPPET to the mirror MIRROR. "Discover if FOM is parented by some field in SNIPPET.
Use the tightest containing field if more than one field contains Use the tightest containing field if more than one field contains
the mirror. Intended to be called *before* the dollar-regions are the mirror. Intended to be called *before* the dollar-regions are
deleted." deleted."
(let ((min (point-min)) (let ((min (point-min))
(max (point-max))) (max (point-max)))
(dolist (field (yas--snippet-fields snippet)) (dolist (field (remq fom (yas--snippet-fields snippet)))
(when (and (<= (yas--field-start field) (yas--mirror-start mirror)) (when (and (<= (yas--field-start field) (yas--fom-start fom))
(<= (yas--mirror-end mirror) (yas--field-end field)) (<= (yas--fom-end fom) (yas--field-end field))
(< min (yas--field-start field)) (< min (yas--field-start field))
(< (yas--field-end field) max)) (< (yas--field-end field) max))
(setq min (yas--field-start field) (setq min (yas--field-start field)
max (yas--field-end 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) (defun yas--advance-end-maybe (fom newend)
"Maybe advance FOM's end to NEWEND if it needs it. "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) (goto-char parse-start)
(yas--field-parse-create snippet) ; Parse fields with {}. (yas--field-parse-create snippet) ; Parse fields with {}.
(goto-char parse-start) (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) (goto-char parse-start)
(yas--transform-mirror-parse-create snippet) ; Parse mirror transforms. (yas--transform-mirror-parse-create snippet) ; Parse mirror transforms.
;; Invalidate any syntax-propertizing done while ;; Invalidate any syntax-propertizing done while
@ -4487,10 +4492,10 @@ When multiple expressions are found, only the last one counts."
(when brand-new-mirror (when brand-new-mirror
(push brand-new-mirror (push brand-new-mirror
(yas--field-mirrors field)) (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))))) (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." "Parse the simple \"$n\" fields/mirrors/exitmarkers in SNIPPET."
(while (re-search-forward yas--simple-mirror-regexp nil t) (while (re-search-forward yas--simple-mirror-regexp nil t)
(let ((number (string-to-number (match-string-no-properties 1)))) (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))) (push (cons (match-beginning 0) (yas--exit-marker (yas--snippet-exit snippet)))
yas--dollar-regions)) yas--dollar-regions))
(t (t
(let ((field (yas--snippet-find-field snippet number))) (let ((field (yas--snippet-find-field snippet number))
(fom))
(if field (if field
(let ((brand-new-mirror (yas--make-mirror (push
(yas--make-marker (match-beginning 0)) (setq fom (yas--make-mirror
(yas--make-marker (match-beginning 0)) (yas--make-marker (match-beginning 0))
nil))) (yas--make-marker (match-beginning 0))
(push brand-new-mirror nil))
(yas--field-mirrors field)) (yas--field-mirrors field))
(yas--calculate-mirrors-in-fields snippet brand-new-mirror)) (push
(push (yas--make-field number (setq fom (yas--make-field number
(yas--make-marker (match-beginning 0)) (yas--make-marker (match-beginning 0))
(yas--make-marker (match-beginning 0)) (yas--make-marker (match-beginning 0))
nil) nil))
(yas--snippet-fields snippet)))) (yas--snippet-fields snippet)))
(yas--calculate-simple-fom-parentage snippet fom))
(push (cons (match-beginning 0) (match-end 0)) (push (cons (match-beginning 0) (match-end 0))
yas--dollar-regions)))))) yas--dollar-regions))))))