Change yas-lookup-snippet to return a yas--template struct

This allows proper handling of a snippet's expand-env field when doing

    (yas-expand-snippet (yas-lookup-snippet NAME))

* yasnippet.el (yas-expand-snippet): Return the yas--template struct
instead of snippet body.
(yas-expand-snippet): Let first argument be a yas--template struct.
* yasnippet-tests.el (snippet-lookup, snippet-load-uuid): Update tests
accordingly.
(yas-lookup-snippet-with-env): New test.
This commit is contained in:
Noam Postavsky 2018-02-03 11:07:01 -05:00
parent 05ac1da894
commit c9277d326e
2 changed files with 77 additions and 55 deletions

View File

@ -1031,11 +1031,28 @@ hello ${1:$(when (stringp yas-text) (funcall func yas-text))} foo${1:$$(concat \
"Test `yas-lookup-snippet'."
(yas-with-some-interesting-snippet-dirs
(yas-reload-all 'no-jit)
(should (equal (yas-lookup-snippet "printf" 'c-mode) "printf($1);"))
(should (equal (yas-lookup-snippet "def" 'c-mode) "# define"))
(should (equal (yas--template-content (yas-lookup-snippet "printf" 'c-mode))
"printf($1);"))
(should (equal (yas--template-content (yas-lookup-snippet "def" 'c-mode))
"# define"))
(should-not (yas-lookup-snippet "no such snippet" nil 'noerror))
(should-not (yas-lookup-snippet "printf" 'emacs-lisp-mode 'noerror))))
(ert-deftest yas-lookup-snippet-with-env ()
(with-temp-buffer
(yas-with-snippet-dirs
'((".emacs.d/snippets"
("emacs-lisp-mode"
("foo" . "\
# expand-env: ((foo \"bar\"))
# --
`foo`"))))
(yas-reload-all)
(emacs-lisp-mode)
(yas-minor-mode +1)
(yas-expand-snippet (yas-lookup-snippet "foo"))
(should (equal (buffer-string) "bar")))))
(ert-deftest basic-jit-loading ()
"Test basic loading and expansion of snippets"
(yas-with-some-interesting-snippet-dirs
@ -1063,13 +1080,15 @@ hello ${1:$(when (stringp yas-text) (funcall func yas-text))} foo${1:$$(concat \
(with-temp-buffer
(text-mode)
(yas-minor-mode +1)
(should (equal (yas-lookup-snippet "one") "one"))
(should (equal (yas--template-content (yas-lookup-snippet "one"))
"one"))
(should (eq (yas--key-binding "\C-c1") 'yas-expand-from-keymap))
(yas-define-snippets
'text-mode '(("_1" "one!" "won" nil nil nil nil nil "uuid-1")))
(should (null (yas-lookup-snippet "one" nil 'noerror)))
(should (null (yas--key-binding "\C-c1")))
(should (equal (yas-lookup-snippet "won") "one!")))))
(should (equal (yas--template-content(yas-lookup-snippet "won"))
"one!")))))
(ert-deftest snippet-save ()
"Make sure snippets can be saved correctly."

View File

@ -2412,18 +2412,17 @@ Honours `yas-choose-tables-first', `yas-choose-keys-first' and
:key #'yas--template-name :test #'string=)))
(defun yas-lookup-snippet (name &optional mode noerror)
"Get the snippet content for the snippet NAME in MODE's tables.
"Get the snippet named NAME in MODE's tables.
MODE defaults to the current buffer's `major-mode'. If NOERROR
is non-nil, then don't signal an error if there isn't any snippet
called NAME.
Honours `yas-buffer-local-condition'."
(let ((snippet (yas--lookup-snippet-1 name mode)))
(cond
(snippet (yas--template-content snippet))
(noerror nil)
(t (error "No snippet named: %s" name)))))
(cond
((yas--lookup-snippet-1 name mode))
(noerror nil)
(t (error "No snippet named: %s" name))))
(defun yas-insert-snippet (&optional no-condition)
"Choose a snippet to expand, pop-up a list of choices according
@ -3783,12 +3782,17 @@ Move the overlays, or create them if they do not exit."
;; running, but if managed correctly (including overlay priorities)
;; they should account for all situations...
(defun yas-expand-snippet (content &optional start end expand-env)
"Expand snippet CONTENT at current point.
(defun yas-expand-snippet (snippet &optional start end expand-env)
"Expand SNIPPET at current point.
Text between START and END will be deleted before inserting
template. EXPAND-ENV is a list of (SYM VALUE) let-style dynamic bindings
considered when expanding the snippet."
template. EXPAND-ENV is a list of (SYM VALUE) let-style dynamic
bindings considered when expanding the snippet. If omitted, use
SNIPPET's expand-env field.
SNIPPET may be a snippet structure (e.g., as returned by
`yas-lookup-snippet'), or just a string representing a snippet's
body text."
(cl-assert (and yas-minor-mode
(memq 'yas--post-command-handler post-command-hook))
nil
@ -3820,56 +3824,55 @@ considered when expanding the snippet."
(cond (yas-selected-text)
((and (region-active-p)
(not clear-field))
to-delete)))
snippet)
to-delete))))
(goto-char start)
(setq yas--indent-original-column (current-column))
;; Delete the region to delete, this *does* get undo-recorded.
(when to-delete
(delete-region start end))
(cond ((listp content)
;; x) This is a snippet-command
;;
(yas--eval-for-effect content))
(t
;; x) This is a snippet-snippet :-)
(setq yas--start-column (current-column))
;; Stacked expansion: also shoosh the overlay modification hooks.
(let ((yas--inhibit-overlay-hooks t))
(setq snippet
(yas--snippet-create content expand-env start (point))))
(let ((content (if (stringp snippet) snippet
(yas--template-content snippet))))
(when (and (not expand-env) (yas--template-p snippet))
(setq expand-env (yas--template-expand-env snippet)))
(cond ((listp content)
;; x) This is a snippet-command.
(yas--eval-for-effect content))
(t
;; x) This is a snippet-snippet :-)
(setq yas--start-column (current-column))
;; Stacked expansion: also shoosh the overlay modification hooks.
(let ((yas--inhibit-overlay-hooks t))
(setq snippet
(yas--snippet-create content expand-env start (point))))
;; stacked-expansion: This checks for stacked expansion, save the
;; `yas--previous-active-field' and advance its boundary.
;;
(let ((existing-field (and yas--active-field-overlay
(overlay-buffer yas--active-field-overlay)
(overlay-get yas--active-field-overlay 'yas--field))))
(when existing-field
(setf (yas--snippet-previous-active-field snippet) existing-field)
(yas--advance-end-maybe existing-field (overlay-end yas--active-field-overlay))))
;; Stacked-expansion: This checks for stacked expansion, save the
;; `yas--previous-active-field' and advance its boundary.
(let ((existing-field (and yas--active-field-overlay
(overlay-buffer yas--active-field-overlay)
(overlay-get yas--active-field-overlay 'yas--field))))
(when existing-field
(setf (yas--snippet-previous-active-field snippet) existing-field)
(yas--advance-end-maybe existing-field (overlay-end yas--active-field-overlay))))
;; Exit the snippet immediately if no fields
;;
(unless (yas--snippet-fields snippet)
(yas-exit-snippet snippet))
;; Exit the snippet immediately if no fields.
(unless (yas--snippet-fields snippet)
(yas-exit-snippet snippet))
;; Now, schedule a move to the first field
;;
(let ((first-field (car (yas--snippet-fields snippet))))
(when first-field
(sit-for 0) ;; fix issue 125
(yas--letenv (yas--snippet-expand-env snippet)
(yas--move-to-field snippet first-field))
(when (and (eq (yas--field-number first-field) 0)
(> (length (yas--field-text-for-display
first-field))
0))
;; Keep region for ${0:exit text}.
(setq deactivate-mark nil))))
(yas--message 4 "snippet %d expanded." (yas--snippet-id snippet))
t))))
;; Now, schedule a move to the first field.
(let ((first-field (car (yas--snippet-fields snippet))))
(when first-field
(sit-for 0) ;; fix issue 125
(yas--letenv (yas--snippet-expand-env snippet)
(yas--move-to-field snippet first-field))
(when (and (eq (yas--field-number first-field) 0)
(> (length (yas--field-text-for-display
first-field))
0))
;; Keep region for ${0:exit text}.
(setq deactivate-mark nil))))
(yas--message 4 "snippet %d expanded." (yas--snippet-id snippet))
t)))))
(defun yas--take-care-of-redo (snippet)
"Commits SNIPPET, which in turn pushes an undo action for reviving it.