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 (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

View File

@ -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))))))