branch: master commit caf3dba32006acd9196b06e0d9845786915f7b6d Author: Noam Postavsky <npost...@users.sourceforge.net> Commit: Noam Postavsky <npost...@users.sourceforge.net>
Don't use global variable for backquote expression locations * yasnippet.el (yas--backquote-markers-and-strings): Remove. (yas--save-backquotes): Return list of backquote expressions. (yas--restore-backquotes): Receive it as a parameter. (yas--snippet-parse-create): Keep it in a local variable. * yasnippet-tests.el (yas-no-memory-of-bad-snippet): New test. --- yasnippet-tests.el | 11 +++++++++++ yasnippet.el | 55 ++++++++++++++++++++++++++---------------------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/yasnippet-tests.el b/yasnippet-tests.el index c82d1b0..85be3b1 100644 --- a/yasnippet-tests.el +++ b/yasnippet-tests.el @@ -683,6 +683,17 @@ mapconcat #'(lambda (arg) (yas-mock-insert "bbb") (should (string= (yas--buffer-contents) "if condition\naaa\nelse\nbbb\nend"))))) +(ert-deftest yas-no-memory-of-bad-snippet () + "Check that expanding an incorrect has no influence on future expansions." + ;; See https://github.com/joaotavora/yasnippet/issues/800. + (with-temp-buffer + (yas-minor-mode 1) + (should-error (yas-expand-snippet "```foo\n\n```")) + (erase-buffer) ; Bad snippet may leave wrong text. + ;; But expanding the corrected snippet should work fine. + (yas-expand-snippet "\\`\\`\\`foo\n\n\\`\\`\\`") + (should (equal (buffer-string) "```foo\n\n```")))) + (defmacro yas--with-font-locked-temp-buffer (&rest body) "Like `with-temp-buffer', but ensure `font-lock-mode'." (declare (indent 0) (debug t)) diff --git a/yasnippet.el b/yasnippet.el index 94d8632..01b39dd 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -4087,11 +4087,6 @@ next FOM. Works its way up recursively for parents of parents." "When expanding the snippet the \"parse-create\" functions add cons cells to this var.") -(defvar yas--backquote-markers-and-strings nil - "List of (MARKER . STRING) marking where the values from -backquoted Lisp expressions should be inserted at the end of -expansion.") - (defvar yas--indent-markers nil "List of markers for manual indentation.") @@ -4100,15 +4095,16 @@ expansion.") necessary fields, mirrors and exit points. Meant to be called in a narrowed buffer, does various passes" - (let ((parse-start (point))) + (let ((saved-quotes nil) + (parse-start (point))) ;; Avoid major-mode's syntax propertizing function, since we ;; change the syntax-table while calling `scan-sexps'. (let ((syntax-propertize-function nil)) (setq yas--dollar-regions nil) ; Reset the yas--dollar-regions. (yas--protect-escapes nil '(?`)) ; Protect just the backquotes. (goto-char parse-start) - (yas--save-backquotes) ; Replace all backquoted expressions. - (yas--protect-escapes) ; Protect escaped characters. + (setq saved-quotes (yas--save-backquotes)) ; `expressions`. + (yas--protect-escapes) ; Protect escaped characters. (goto-char parse-start) (yas--indent-parse-create) ; Parse indent markers: `$>'. (goto-char parse-start) @@ -4138,7 +4134,7 @@ Meant to be called in a narrowed buffer, does various passes" (get-register yas-wrap-around-region)) (insert (prog1 (get-register yas-wrap-around-region) (set-register yas-wrap-around-region nil))))) - (yas--restore-backquotes) ; Restore backquoted expression values. + (yas--restore-backquotes saved-quotes) ; Restore `expression` values. (goto-char parse-start) (yas--restore-escapes) ; Restore escapes. (yas--update-mirrors snippet) ; Update mirrors for the first time. @@ -4353,9 +4349,11 @@ With optional string TEXT do it in string instead of the buffer." changed-text)) (defun yas--save-backquotes () - "Save all the \"\\=`(lisp-expression)\\=`\"-style expressions -with their evaluated value into `yas--backquote-markers-and-strings'." - (let* ((yas--snippet-buffer (current-buffer)) + "Save all \"\\=`(lisp-expression)\\=`\"-style expressions. +Return a list of (MARKER . STRING) entires for each backquoted +Lisp expression." + (let* ((saved-quotes nil) + (yas--snippet-buffer (current-buffer)) (yas--change-detected nil) (detect-change (lambda (_beg _end) (when (eq (current-buffer) yas--snippet-buffer) @@ -4378,29 +4376,28 @@ with their evaluated value into `yas--backquote-markers-and-strings'." (insert "Y") ;; quite horrendous, I love it :) (set-marker marker (point)) (insert "Y")) - (push (cons marker transformed) yas--backquote-markers-and-strings))))) + (push (cons marker transformed) saved-quotes))))) (when yas--change-detected (lwarn '(yasnippet backquote-change) :warning "`%s' modified buffer in a backquote expression. To hide this warning, add (yasnippet backquote-change) to `warning-suppress-types'." (if yas--current-template (yas--template-name yas--current-template) - "Snippet"))))) - -(defun yas--restore-backquotes () - "Replace markers in `yas--backquote-markers-and-strings' with their values." - (while yas--backquote-markers-and-strings - (let* ((marker-and-string (pop yas--backquote-markers-and-strings)) - (marker (car marker-and-string)) - (string (cdr marker-and-string))) - (save-excursion - (goto-char marker) - (save-restriction - (widen) - (delete-char -1) - (insert string) - (delete-char 1)) - (set-marker marker nil))))) + "Snippet"))) + saved-quotes)) + +(defun yas--restore-backquotes (saved-quotes) + "Replace markers in SAVED-QUOTES with their values. +SAVED-QUOTES is the in format returned by `yas--save-backquotes'." + (cl-loop for (marker . string) in saved-quotes do + (save-excursion + (goto-char marker) + (save-restriction + (widen) + (delete-char -1) + (insert string) + (delete-char 1)) + (set-marker marker nil)))) (defun yas--scan-sexps (from count) (ignore-errors