Closes #290: problem when advancing the start of a mirror-in-field

* Rewrote 'yas--update-mirrors'
* Added unit test
* Advancing is done exceptionally in 'yas--update-mirrors'
  not 'yas--mirror-update-display' and just before we need to
  re-update the mirror-in-field.
* Alternative to prior point would be to have fields carry a reference
  to their child mirrors.
This commit is contained in:
João Távora 2012-08-22 00:52:17 +01:00
parent 8a26ab0a31
commit 9503c332f5
2 changed files with 43 additions and 21 deletions

View File

@ -95,6 +95,16 @@
(should (string= (yas--buffer-contents)
"brother from another bla!"))))
(ert-deftest mirrors-adjacent-to-fields-with-nested-mirrors ()
(with-temp-buffer)
(yas-minor-mode 1)
(yas-expand-snippet "<%= f.submit \"${1:Submit}\"${2:$(and (yas-text) \", :disable_with => '\")}${2:$1ing...}${2:$(and (yas-text) \"'\")} %>")
(should (string= (yas--buffer-contents)
"<%= f.submit \"Submit\", :disable_with => 'Submiting...' %>"))
(ert-simulate-command `(yas-mock-insert "Send"))
(should (string= (yas--buffer-contents)
"<%= f.submit \"Send\", :disable_with => 'Sending...' %>")))
;; (ert-deftest in-snippet-undo ()
;; (with-temp-buffer
;; (yas-minor-mode 1)

View File

@ -4139,27 +4139,39 @@ When multiple expressions are found, only the last one counts."
(defun yas--update-mirrors (snippet)
"Updates all the mirrors of SNIPPET."
(save-excursion
(let* ((fields (copy-list (yas--snippet-fields snippet)))
(field (car fields)))
(while field
(dolist (mirror (yas--field-mirrors field))
(let ((mirror-parent-field (yas--mirror-parent-field mirror)))
;; updatte this mirror
;;
(yas--mirror-update-display mirror field)
;; for mirrors-in-fields: schedule a possible
;; parent field for reupdting later on
;;
(when mirror-parent-field
(add-to-list 'fields mirror-parent-field 'append #'eq))
;; `yas--place-overlays' is needed if the active field and
;; protected overlays have been changed because of insertions
;; in `yas--mirror-update-display'
;;
(when (eq field (yas--snippet-active-field snippet))
(yas--place-overlays snippet field))))
(setq fields (cdr fields))
(setq field (car fields))))))
(dolist (field-and-mirror (sort
;; make a list of ((F1 . M1) (F1 . M2) (F2 . M3) (F2 . M4) ...)
;; where F is the field that M is mirroring
;;
(mapcan #'(lambda (field)
(mapcar #'(lambda (mirror)
(cons field mirror))
(yas--field-mirrors field)))
(yas--snippet-fields snippet))
;; then sort this list so that entries with mirrors with parent
;; fields appear before. This was important for fixing #290, and
;; luckily also handles the case where a mirror in a field causes
;; another mirror to need reupdating
;;
#'(lambda (field-and-mirror1 field-and-mirror2)
(yas--mirror-parent-field (cdr field-and-mirror1)))))
(let* ((field (car field-and-mirror))
(mirror (cdr field-and-mirror))
(parent-field (yas--mirror-parent-field mirror)))
;; before updating a mirror with a parent-field, maybe advance
;; its start (#290)
;;
(when parent-field
(yas--advance-start-maybe mirror (yas--fom-start parent-field)))
;; update this mirror
;;
(yas--mirror-update-display mirror field)
;; `yas--place-overlays' is needed if the active field and
;; protected overlays have been changed because of insertions
;; in `yas--mirror-update-display'
;;
(when (eq field (yas--snippet-active-field snippet))
(yas--place-overlays snippet field))))))
(defun yas--mirror-update-display (mirror field)
"Update MIRROR according to FIELD (and mirror transform)."