diff --git a/jsonian-tests.el b/jsonian-tests.el index c558c0d..e04aa96 100644 --- a/jsonian-tests.el +++ b/jsonian-tests.el @@ -858,5 +858,24 @@ If START and END are provided, they are set as point and mark." (should (eq major-mode 'jsonian-mode)) (remove-hook 'jsonian-edit-string-hook hook-fn)))) +(ert-deftest jsonian-special-chars () + "Test `jsonian--intern-special-chars' and `jsonian--unintern-special-chars' translate properly" + (with-temp-buffer + (mapc (lambda (testcase) + (let ((raw (car testcase)) + (escaped (cdr testcase))) + (insert escaped) + (jsonian--unintern-special-chars (current-buffer)) + (should (equal (buffer-string) raw)) + (jsonian--intern-special-chars (current-buffer)) + (should (equal (buffer-string) escaped)) + (delete-region (point-min) (point-max)))) + '(("\t" . "\\t") + ("\n" . "\\n") + ("\"" . "\\\"") + ("\\" . "\\\\") + ("\\\n" . "\\\\\\n")))) + nil) + (provide 'jsonian-tests) ;;; jsonian-tests.el ends here diff --git a/jsonian.el b/jsonian.el index 7723a06..94e766e 100644 --- a/jsonian.el +++ b/jsonian.el @@ -1136,10 +1136,13 @@ BUFFER defaults to the current buffer." (defun jsonian--intern-special-chars (buffer) "Translates whitespace operators to their ansi equivalents in BUFFER. -This means replacing '\n' with '\\n', '\t' with '\\t'." +This means replacing '\n' with '\\n', '\t' with '\\t', and escaping quotes and backslashes" (with-current-buffer buffer (save-excursion (goto-char (point-min)) + (while (search-forward "\\" nil t) + (replace-match "\\\\\\\\")) + (goto-char (point-min)) (while (search-forward "\n" nil t) (replace-match "\\\\n")) (goto-char (point-min)) @@ -1151,18 +1154,18 @@ This means replacing '\n' with '\\n', '\t' with '\\t'." (defun jsonian--unintern-special-chars (buffer) "Translate special characters to their unescaped equivalents in BUFFER. -This means replacing '\\n' with '\n' and '\\t' with '\t'." +This means replacing '\\n' with '\n' and '\\t' with '\t' and unescaping escaped characters." (with-current-buffer buffer (save-excursion (goto-char (point-min)) - (while (search-forward "\\n" nil t) - (replace-match "\n")) - (goto-char (point-min)) - (while (search-forward "\\t" nil t) - (replace-match "\t")) - (goto-char (point-min)) - (while (search-forward "\\\"" nil t) - (replace-match "\""))))) + (while (search-forward "\\" nil t) + (let ((c (char-after))) + (delete-region (1- (point)) (1+ (point))) + (insert + (cond + ((eql c ?t) ?\t) + ((eql c ?n) ?\n) + (t c)))))))) (defun jsonian-edit-mode-return () "Jump back from `json-edit-string', actualizing the change made."