branch: master commit c9277d326e9c8b6052bbb35eb86467e43a7e9424 Author: Noam Postavsky <npost...@users.sourceforge.net> Commit: Noam Postavsky <npost...@users.sourceforge.net>
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. --- yasnippet-tests.el | 27 +++++++++++-- yasnippet.el | 111 +++++++++++++++++++++++++++-------------------------- 2 files changed, 80 insertions(+), 58 deletions(-) diff --git a/yasnippet-tests.el b/yasnippet-tests.el index 3d92183..0f9dcdc 100644 --- a/yasnippet-tests.el +++ b/yasnippet-tests.el @@ -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." diff --git a/yasnippet.el b/yasnippet.el index 01b39dd..3c16536 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -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)))) - - ;; 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)) - - ;; 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)))) + (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)))) + + ;; 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))))) (defun yas--take-care-of-redo (snippet) "Commits SNIPPET, which in turn pushes an undo action for reviving it.