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 <manikulin@gmail.com>
Link: https://orgmode.org/list/v10k4s$et9$1@ciao.gmane.io
This commit is contained in:
Ihor Radchenko 2024-05-03 15:04:52 +03:00
parent 5da0eb6ea7
commit 2028bb15cd
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
2 changed files with 63 additions and 1 deletions

View File

@ -3362,7 +3362,13 @@ situations in which is it not appropriate."
(eval (read cell) t)) (eval (read cell) t))
((save-match-data ((save-match-data
(and (string-match "^[[:space:]]*\"\\(.*\\)\"[[:space:]]*$" cell) (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)) (read cell))
(t (org-no-properties cell)))) (t (org-no-properties cell))))

View File

@ -2545,6 +2545,62 @@ abc
(lambda (&rest _) (error "No warnings should occur")))) (lambda (&rest _) (error "No warnings should occur"))))
(org-babel-import-elisp-from-file (buffer-file-name)))))) (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 () (ert-deftest test-ob/demarcate-block-split-duplication ()
"Test duplication of language, body, switches, and headers in splitting." "Test duplication of language, body, switches, and headers in splitting."
(let ((caption "#+caption: caption.") (let ((caption "#+caption: caption.")