Promote yas--snippets-at-point to a public API

* yasnippet.el (yas-active-snippets): Rename from
yas--snippets-at-point, adjust callers.  Handle arbitrary positions and
ranges as a parameter.
* yasnippet-tests.el (nested-snippet-expansion): New test.
This commit is contained in:
Noam Postavsky 2016-08-14 15:30:53 -04:00
parent c485d13995
commit 2ca6321b47
2 changed files with 41 additions and 21 deletions

View File

@ -145,7 +145,7 @@
(ert-simulate-command '(yas-next-field-or-maybe-expand)) (ert-simulate-command '(yas-next-field-or-maybe-expand))
(ert-simulate-command '(yas-skip-and-clear-or-delete-char)) (ert-simulate-command '(yas-skip-and-clear-or-delete-char))
(should (looking-at "ble")) (should (looking-at "ble"))
(should (null (yas--snippets-at-point))))) (should (null (yas-active-snippets)))))
(ert-deftest ignore-trailing-whitespace () (ert-deftest ignore-trailing-whitespace ()
(should (equal (should (equal
@ -523,6 +523,17 @@ TODO: correct this bug!"
(yas-should-expand '(("foo-barbaz" . "OKfoo-barbazOK") (yas-should-expand '(("foo-barbaz" . "OKfoo-barbazOK")
("foo " . "foo ")))))))) ("foo " . "foo "))))))))
(ert-deftest nested-snippet-expansion ()
(with-temp-buffer
(yas-minor-mode +1)
(let ((yas-triggers-in-field t))
(yas-expand-snippet "Parent $1 Snippet")
(yas-expand-snippet "(Child $1 $2 Snippet)")
(let ((snippets (yas-active-snippets)))
(should (= (length snippets) 2))
(should (= (length (yas--snippet-fields (nth 0 snippets))) 2))
(should (= (length (yas--snippet-fields (nth 1 snippets))) 1))))))
;;; Loading ;;; Loading
;;; ;;;

View File

@ -2842,7 +2842,7 @@ Otherwise throw exception."
"Get the string for field with NUMBER. "Get the string for field with NUMBER.
Use this in primary and mirror transformations to tget." Use this in primary and mirror transformations to tget."
(let* ((snippet (car (yas--snippets-at-point))) (let* ((snippet (car (yas-active-snippets)))
(field (and snippet (field (and snippet
(yas--snippet-find-field snippet number)))) (yas--snippet-find-field snippet number))))
(when field (when field
@ -3039,18 +3039,27 @@ through the field's start point"
(not (and (yas--field-number field) (not (and (yas--field-number field)
(zerop (yas--field-number field)))))) (zerop (yas--field-number field))))))
(defun yas--snippets-at-point (&optional all-snippets) (defun yas-active-snippets (&optional beg end)
"Return a sorted list of snippets at point. "Return a sorted list of active snippets.
The most recently-inserted snippets are returned first.
The most recently-inserted snippets are returned first." Only snippets overlapping the region BEG ... END are returned.
(sort Overlapping has the same meaning as described in `overlays-in'.
(delq nil (delete-dups If END is omitted, it defaults to (1+ BEG). If BEG is omitted,
(mapcar (lambda (ov) (overlay-get ov 'yas--snippet)) it defaults to point. A non-nil, non-buffer position BEG is
(if all-snippets (overlays-in (point-min) (point-max)) equivalent to a range covering the whole buffer."
(nconc (overlays-at (point)) (unless beg
(overlays-at (1- (point)))))))) (setq beg (point)))
#'(lambda (s1 s2) (cond ((not (or (integerp beg) (markerp beg)))
(<= (yas--snippet-id s2) (yas--snippet-id s1))))) (setq beg (point-min) end (point-max)))
((not end)
(setq end (1+ beg))))
(cl-sort
(delete-dups ;; Snippets have multiple overlays.
(delq nil
(mapcar (lambda (ov) (overlay-get ov 'yas--snippet))
(overlays-in beg end))))
#'>= :key #'yas--snippet-id))
(defun yas-next-field-or-maybe-expand () (defun yas-next-field-or-maybe-expand ()
"Try to expand a snippet at a key before point. "Try to expand a snippet at a key before point.
@ -3067,7 +3076,7 @@ Otherwise delegate to `yas-next-field'."
(defun yas-next-field-will-exit-p (&optional arg) (defun yas-next-field-will-exit-p (&optional arg)
"Return non-nil if (yas-next-field ARG) would exit the current snippet." "Return non-nil if (yas-next-field ARG) would exit the current snippet."
(let ((snippet (car (yas--snippets-at-point))) (let ((snippet (car (yas-active-snippets)))
(active (overlay-get yas--active-field-overlay 'yas--field))) (active (overlay-get yas--active-field-overlay 'yas--field)))
(when snippet (when snippet
(not (yas--find-next-field arg snippet active))))) (not (yas--find-next-field arg snippet active)))))
@ -3087,7 +3096,7 @@ Otherwise delegate to `yas-next-field'."
If there's none, exit the snippet." If there's none, exit the snippet."
(interactive) (interactive)
(unless arg (setq arg 1)) (unless arg (setq arg 1))
(let* ((snippet (car (yas--snippets-at-point))) (let* ((snippet (car (yas-active-snippets)))
(active-field (overlay-get yas--active-field-overlay 'yas--field)) (active-field (overlay-get yas--active-field-overlay 'yas--field))
(target-field (yas--find-next-field arg snippet active-field))) (target-field (yas--find-next-field arg snippet active-field)))
;; Apply transform to active field. ;; Apply transform to active field.
@ -3136,13 +3145,13 @@ Also create some protection overlays"
(defun yas-abort-snippet (&optional snippet) (defun yas-abort-snippet (&optional snippet)
(interactive) (interactive)
(let ((snippet (or snippet (let ((snippet (or snippet
(car (yas--snippets-at-point))))) (car (yas-active-snippets)))))
(when snippet (when snippet
(setf (yas--snippet-force-exit snippet) t)))) (setf (yas--snippet-force-exit snippet) t))))
(defun yas-exit-snippet (snippet) (defun yas-exit-snippet (snippet)
"Goto exit-marker of SNIPPET." "Goto exit-marker of SNIPPET."
(interactive (list (cl-first (yas--snippets-at-point)))) (interactive (list (cl-first (yas-active-snippets))))
(when snippet (when snippet
(setf (yas--snippet-force-exit snippet) t) (setf (yas--snippet-force-exit snippet) t)
(goto-char (if (yas--snippet-exit snippet) (goto-char (if (yas--snippet-exit snippet)
@ -3155,7 +3164,7 @@ Also create some protection overlays"
(mapc #'(lambda (snippet) (mapc #'(lambda (snippet)
(yas-exit-snippet snippet) (yas-exit-snippet snippet)
(yas--check-commit-snippet)) (yas--check-commit-snippet))
(yas--snippets-at-point 'all-snippets))) (yas-active-snippets 'all)))
;;; Some low level snippet-routines: ;;; Some low level snippet-routines:
@ -3222,7 +3231,7 @@ This renders the snippet as ordinary text."
"Check if point exited the currently active field of the snippet. "Check if point exited the currently active field of the snippet.
If so cleans up the whole snippet up." If so cleans up the whole snippet up."
(let* ((snippets (yas--snippets-at-point 'all-snippets)) (let* ((snippets (yas-active-snippets 'all))
(snippets-left snippets) (snippets-left snippets)
(snippet-exit-transform)) (snippet-exit-transform))
(dolist (snippet snippets) (dolist (snippet snippets)
@ -3474,7 +3483,7 @@ Move the overlays, or create them if they do not exit."
(not after?) (not after?)
(= length (- end beg)) ; deletion or insertion (= length (- end beg)) ; deletion or insertion
(yas--undo-in-progress)) (yas--undo-in-progress))
(let ((snippets (yas--snippets-at-point))) (let ((snippets (yas-active-snippets)))
(yas--message 2 "Committing snippets. Action would destroy a protection overlay.") (yas--message 2 "Committing snippets. Action would destroy a protection overlay.")
(cl-loop for snippet in snippets (cl-loop for snippet in snippets
do (yas--commit-snippet snippet))))) do (yas--commit-snippet snippet)))))
@ -4324,7 +4333,7 @@ When multiple expressions are found, only the last one counts."
;; After undo revival the correct field is sometimes not ;; After undo revival the correct field is sometimes not
;; restored correctly, this condition handles that ;; restored correctly, this condition handles that
;; ;;
(let* ((snippet (car (yas--snippets-at-point))) (let* ((snippet (car (yas-active-snippets)))
(target-field (target-field
(and snippet (and snippet
(cl-find-if-not (cl-find-if-not