From 9503c332f552e874899ea0ce7801516d4b30bba2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Wed, 22 Aug 2012 00:52:17 +0100 Subject: [PATCH] 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. --- yasnippet-tests.el | 10 +++++++++ yasnippet.el | 54 ++++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/yasnippet-tests.el b/yasnippet-tests.el index 9af244b9e..62653b090 100644 --- a/yasnippet-tests.el +++ b/yasnippet-tests.el @@ -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) diff --git a/yasnippet.el b/yasnippet.el index d03f4286b..c65aa2f7d 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -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)." -- 2.39.2