branch: master commit e67592ce1bd4ccc533107765bdfebfa02e9fb945 Author: Noam Postavsky <npost...@users.sourceforge.net> Commit: Noam Postavsky <npost...@users.sourceforge.net>
Don't use overlays to find active snippets * yasnippet.el (yas--active-snippets): New buffer-local variable. (yas-active-snippets): Use it, when asked for all active snippets. (yas--commit-snippet): Remove finished snippet from list of active snippets. (yas--snippet-create): Add new snippet to list of active snippets. (yas--check-commit-snippet): Consult list of active snippetes. --- yasnippet.el | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/yasnippet.el b/yasnippet.el index b6e3d0e..d06165f 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -3070,6 +3070,10 @@ other fields." (defvar yas--active-field-overlay nil "Overlays the currently active field.") +(defvar yas--active-snippets nil + "List of currently active snippets") +(make-variable-buffer-local 'yas--active-snippets) + (defvar yas--field-protection-overlays nil "Two overlays protect the current active field.") @@ -3273,19 +3277,19 @@ equivalent to a range covering the whole buffer." (setq beg (point-min) end (point-max))) ((not end) (setq end (1+ beg)))) - - ;; Note: don't use `mapcar' here, since it would allocate in - ;; proportion to the amount of overlays, even though the list of - ;; active snippets should be very small. That is important because - ;; this function is called in the post-command hook (via - ;; `yas--check-commit-snippet'). - (let ((snippets nil)) - (dolist (ov (overlays-in beg end)) - (let ((snippet (overlay-get ov 'yas--snippet))) - ;; Snippets have multiple overlays, so check for dups. - (when (and snippet (not (memq snippet snippets))) - (push snippet snippets)))) - (cl-sort snippets #'>= :key #'yas--snippet-id))) + (if (and (eq beg (point-min)) + (eq end (point-max))) + yas--active-snippets + ;; Note: don't use `mapcar' here, since it would allocate in + ;; proportion to the amount of overlays, even though the list of + ;; active snippets should be very small. + (let ((snippets nil)) + (dolist (ov (overlays-in beg end)) + (let ((snippet (overlay-get ov 'yas--snippet))) + ;; Snippets have multiple overlays, so check for dups. + (when (and snippet (not (memq snippet snippets))) + (push snippet snippets)))) + (cl-sort snippets #'>= :key #'yas--snippet-id)))) (define-obsolete-function-alias 'yas--snippets-at-point 'yas-active-snippets "0.12") @@ -3445,6 +3449,9 @@ This renders the snippet as ordinary text." ;; (yas--markers-to-points snippet) + ;; It's no longer an active snippet. + (cl-callf2 delq snippet yas--active-snippets) + ;; Take care of snippet revival on undo. (if (and yas-snippet-revival (listp buffer-undo-list)) (push `(apply yas--snippet-revive ,yas-snippet-beg ,yas-snippet-end ,snippet) @@ -3538,13 +3545,12 @@ HOOK should be a symbol, a hook variable, as in `run-hooks'." "Check if point exited the currently active field of the snippet. If so cleans up the whole snippet up." - (let* ((snippets (yas-active-snippets 'all)) - (snippets-left snippets) - (snippet-exit-transform) + (let* ((snippet-exit-transform nil) + (exited-snippets-p nil) ;; Record the custom snippet `yas-after-exit-snippet-hook' ;; set in the expand-env field. (snippet-exit-hook yas-after-exit-snippet-hook)) - (dolist (snippet snippets) + (dolist (snippet yas--active-snippets) (let ((active-field (yas--snippet-active-field snippet))) (yas--letenv (yas--snippet-expand-env snippet) ;; Note: the `force-exit' field could be a transform in case of @@ -3552,10 +3558,10 @@ If so cleans up the whole snippet up." (setq snippet-exit-transform (yas--snippet-force-exit snippet)) (cond ((or snippet-exit-transform (not (and active-field (yas--field-contains-point-p active-field)))) - (setq snippets-left (delete snippet snippets-left)) (setf (yas--snippet-force-exit snippet) nil) (setq snippet-exit-hook yas-after-exit-snippet-hook) - (yas--commit-snippet snippet)) + (yas--commit-snippet snippet) + (setq exited-snippets-p t)) ((and active-field (or (not yas--active-field-overlay) (not (overlay-buffer yas--active-field-overlay)))) @@ -3569,7 +3575,7 @@ If so cleans up the whole snippet up." (yas--update-mirrors snippet))) (t nil))))) - (unless (or (null snippets) snippets-left) + (unless (or yas--active-snippets (not exited-snippets-p)) (when snippet-exit-transform (yas--eval-for-effect snippet-exit-transform)) (let ((yas-after-exit-snippet-hook snippet-exit-hook)) @@ -4062,6 +4068,7 @@ Returns the newly created snippet." ;; Move to end (goto-char (point-max)) + (push snippet yas--active-snippets) snippet))))