From 2028bb15cda35be49f759793ade45b8a1e6861ce Mon Sep 17 00:00:00 2001 From: Ihor Radchenko Date: Fri, 3 May 2024 15:04:52 +0300 Subject: [PATCH] org-babel-read: Fix reading multiple quoted strings * lisp/ob-core.el (org-babel-read): Fix naive regexp for matching escaped quotes. Instead, check if `read' can read the whole CELL in one go. * testing/lisp/test-ob.el (test-ob/org-babel-read): Add tests. Reported-by: Max Nikulin Link: https://orgmode.org/list/v10k4s$et9$1@ciao.gmane.io --- lisp/ob-core.el | 8 +++++- testing/lisp/test-ob.el | 56 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lisp/ob-core.el b/lisp/ob-core.el index 73fb70c26..470db9fe6 100644 --- a/lisp/ob-core.el +++ b/lisp/ob-core.el @@ -3362,7 +3362,13 @@ situations in which is it not appropriate." (eval (read cell) t)) ((save-match-data (and (string-match "^[[:space:]]*\"\\(.*\\)\"[[:space:]]*$" cell) - (not (string-match "[^\\]\"" (match-string 1 cell))))) + ;; CELL is a single string + (with-temp-buffer + (insert cell) + (goto-char 1) + (read (current-buffer)) + (skip-chars-forward "[:space:]") + (eobp)))) (read cell)) (t (org-no-properties cell)))) diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el index c088af7c8..054f08075 100644 --- a/testing/lisp/test-ob.el +++ b/testing/lisp/test-ob.el @@ -2545,6 +2545,62 @@ abc (lambda (&rest _) (error "No warnings should occur")))) (org-babel-import-elisp-from-file (buffer-file-name)))))) +(ert-deftest test-ob/org-babel-read () + "Test `org-babel-read' specifications." + (dolist (inhibit '(t nil)) + ;; A number + (should (equal 1 (org-babel-read "1" inhibit))) + (should (equal -1 (org-babel-read "-1" inhibit))) + (should (equal 1.2 (org-babel-read "1.2" inhibit))) + ;; Allow whitespace + (should (equal 1 (org-babel-read " 1 " inhibit))) + ;; Not a number + (should-not (equal 1 (org-babel-read "1foo" inhibit))) + ;; Empty string + (should (equal "" (org-babel-read "" inhibit))) + (should (equal " " (org-babel-read " " inhibit))) + ;; Elisp function call + (should + (equal (if inhibit + ;; Verbatim string, with spaces + "(+ 1 2) " + ;; Result of evaluation + 3) + (org-babel-read "(+ 1 2) " inhibit))) + ;; Elisp function call must start from ( + (should-not (equal 3 (org-babel-read " (+ 1 2)" nil))) + (should + (equal (if inhibit + "'(1 2)" + ;; Result of evaluation + '(1 2)) + (org-babel-read "'(1 2)" inhibit))) + ;; `(...) + (should + (equal (if inhibit + "`(1 ,(+ 1 2))" + ;; Result of evaluation + '(1 3)) + (org-babel-read "`(1 ,(+ 1 2))" inhibit))) + ;; [...] + (should + (equal (if inhibit + "[1 2 (foo)]" + ;; Result of evaluation + [1 2 (foo)]) + (org-babel-read "[1 2 (foo)]" inhibit))) + ;; Special case: *this* literal is evaluated + (dlet ((*this* 100)) + (should + (equal + (if inhibit "*this*" 100) + (org-babel-read "*this*" inhibit)))) + ;; Special case: data inside quotes + (should (equal "foo" (org-babel-read " \"foo\" " inhibit))) + (should (equal "foo with\" inside" (org-babel-read " \"foo with\\\" inside\" " inhibit))) + ;; Unpaired quotes + (should (equal "\"foo\"\"bar\"" (org-babel-read "\"foo\"\"bar\"" inhibit))))) + (ert-deftest test-ob/demarcate-block-split-duplication () "Test duplication of language, body, switches, and headers in splitting." (let ((caption "#+caption: caption.")