+(ert-deftest escape-dollar ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (yas-expand-snippet "bla\\${1:bla}ble")
+ (should (string= (yas--buffer-contents) "bla${1:bla}ble"))))
+
+(ert-deftest escape-closing-brace ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (yas-expand-snippet "bla${1:bla\\}}ble")
+ (should (string= (yas--buffer-contents) "blabla}ble"))
+ (should (string= (yas-field-value 1) "bla}"))))
+
+(ert-deftest escape-backslashes ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (yas-expand-snippet "bla\\ble")
+ (should (string= (yas--buffer-contents) "bla\\ble"))))
+
+(ert-deftest escape-backquotes ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (yas-expand-snippet "bla`(upcase \"foo\\`bar\")`ble")
+ (should (string= (yas--buffer-contents) "blaFOO`BARble"))))
+
+(ert-deftest escape-some-elisp-with-strings ()
+ "elisp with strings and unbalance parens inside it"
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ ;; The rules here is: to output a literal `"' you need to escape
+ ;; it with one backslash. You don't need to escape them in
+ ;; embedded elisp.
+ (yas-expand-snippet "soon \\\"`(concat (upcase \"(my arms\")\"\\\" were all around her\")`")
+ (should (string= (yas--buffer-contents) "soon \"(MY ARMS\" were all around her"))))
+
+(ert-deftest escape-some-elisp-with-backslashes ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ ;; And the rule here is: to output a literal `\' inside a string
+ ;; inside embedded elisp you need a total of six `\'
+ (yas-expand-snippet "bla`(upcase \"hey\\\\\\yo\")`ble")
+ (should (string= (yas--buffer-contents) "blaHEY\\YOble"))))
+
+(ert-deftest be-careful-when-escaping-in-yas-selected-text ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (let ((yas-selected-text "He\\\\o world!"))
+ (yas-expand-snippet "Look ma! `(yas-selected-text)`")
+ (should (string= (yas--buffer-contents) "Look ma! He\\\\o world!")))
+ (yas-exit-all-snippets)
+ (erase-buffer)
+ (let ((yas-selected-text "He\"o world!"))
+ (yas-expand-snippet "Look ma! `(yas-selected-text)`")
+ (should (string= (yas--buffer-contents) "Look ma! He\"o world!")))
+ (yas-exit-all-snippets)
+ (erase-buffer)
+ (let ((yas-selected-text "He\"\)\\o world!"))
+ (yas-expand-snippet "Look ma! `(yas-selected-text)`")
+ (should (string= (yas--buffer-contents) "Look ma! He\"\)\\o world!")))
+ (yas-exit-all-snippets)
+ (erase-buffer)))
+
+(ert-deftest be-careful-when-escaping-in-yas-selected-text-2 ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (let ((yas-selected-text "He)}o world!"))
+ (yas-expand-snippet "Look ma! ${1:`(yas-selected-text)`} OK?")
+ (should (string= (yas--buffer-contents) "Look ma! He)}o world! OK?")))))
+
+(ert-deftest example-for-issue-271 ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (let ((yas-selected-text "aaa")
+ (snippet "if ${1:condition}\n`yas-selected-text`\nelse\n$3\nend"))
+ (yas-expand-snippet snippet)
+ (yas-next-field)
+ (ert-simulate-command `(yas-mock-insert "bbb"))
+ (should (string= (yas--buffer-contents) "if condition\naaa\nelse\nbbb\nend")))))
+
+(defmacro yas--with-font-locked-temp-buffer (&rest body)
+ "Like `with-temp-buffer', but ensure `font-lock-mode'."
+ (declare (indent 0) (debug t))
+ (let ((temp-buffer (make-symbol "temp-buffer")))
+ ;; NOTE: buffer name must not start with a space, otherwise
+ ;; `font-lock-mode' doesn't turn on.
+ `(let ((,temp-buffer (generate-new-buffer "*yas-temp*")))
+ (with-current-buffer ,temp-buffer
+ ;; pretend we're interactive so `font-lock-mode' turns on
+ (let ((noninteractive nil)
+ ;; turn on font locking after major mode change
+ (change-major-mode-after-body-hook #'font-lock-mode))
+ (unwind-protect
+ (progn (require 'font-lock)
+ ;; turn on font locking before major mode change
+ (font-lock-mode +1)
+ ,@body)
+ (and (buffer-name ,temp-buffer)
+ (kill-buffer ,temp-buffer))))))))
+
+(ert-deftest example-for-issue-474 ()
+ (yas--with-font-locked-temp-buffer
+ (c-mode)
+ (yas-minor-mode 1)
+ (insert "#include <foo>\n")
+ (let ((yas-good-grace nil)) (yas-expand-snippet "`\"TODO: \"`"))
+ (should (string= (yas--buffer-contents) "#include <foo>\nTODO: "))))
+
+(ert-deftest example-for-issue-404 ()
+ (yas--with-font-locked-temp-buffer
+ (c++-mode)
+ (yas-minor-mode 1)
+ (insert "#include <foo>\n")
+ (let ((yas-good-grace nil)) (yas-expand-snippet "main"))
+ (should (string= (yas--buffer-contents) "#include <foo>\nmain"))))
+
+(ert-deftest example-for-issue-404-c-mode ()
+ (yas--with-font-locked-temp-buffer
+ (c-mode)
+ (yas-minor-mode 1)
+ (insert "#include <foo>\n")
+ (let ((yas-good-grace nil)) (yas-expand-snippet "main"))
+ (should (string= (yas--buffer-contents) "#include <foo>\nmain"))))
+
+(ert-deftest middle-of-buffer-snippet-insertion ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (insert "beginning")
+ (save-excursion (insert "end"))
+ (yas-expand-snippet "-middle-")
+ (should (string= (yas--buffer-contents) "beginning-middle-end"))))
+
+(ert-deftest another-example-for-issue-271 ()
+ ;; expect this to fail in batch mode since `region-active-p' doesn't
+ ;; used by `yas-expand-snippet' doesn't make sense in that context.
+ ;;
+ :expected-result (if noninteractive
+ :failed
+ :passed)
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ (let ((snippet "\\${${1:1}:`yas-selected-text`}"))
+ (insert "aaabbbccc")
+ (set-mark 4)
+ (goto-char 7)
+ (yas-expand-snippet snippet)
+ (should (string= (yas--buffer-contents) "aaa${1:bbb}ccc")))))
+
+(ert-deftest string-match-with-subregexp-in-embedded-elisp ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ ;; the rule here is: To use regexps in embedded `(elisp)` expressions, write
+ ;; it like you would normal elisp, i.e. no need to escape the backslashes.
+ (let ((snippet "`(if (string-match \"foo\\\\(ba+r\\\\)foo\" \"foobaaaaaaaaaarfoo\")
+ \"ok\"
+ \"fail\")`"))
+ (yas-expand-snippet snippet))
+ (should (string= (yas--buffer-contents) "ok"))))
+
+(ert-deftest string-match-with-subregexp-in-mirror-transformations ()
+ (with-temp-buffer
+ (yas-minor-mode 1)
+ ;; the rule here is: To use regexps in embedded `(elisp)` expressions,
+ ;; escape backslashes once, i.e. to use \\( \\) constructs, write \\\\( \\\\).
+ (let ((snippet "$1${1:$(if (string-match \"foo\\\\\\\\(ba+r\\\\\\\\)baz\" yas-text)
+ \"ok\"
+ \"fail\")}"))
+ (yas-expand-snippet snippet)
+ (should (string= (yas--buffer-contents) "fail"))
+ (ert-simulate-command `(yas-mock-insert "foobaaar"))
+ (should (string= (yas--buffer-contents) "foobaaarfail"))
+ (ert-simulate-command `(yas-mock-insert "baz"))
+ (should (string= (yas--buffer-contents) "foobaaarbazok")))))