diff --git a/lisp/oc.el b/lisp/oc.el index b31ee92cc..5735f5486 100644 --- a/lisp/oc.el +++ b/lisp/oc.el @@ -792,6 +792,39 @@ INFO is a plist used as a communication channel." (cons (org-not-nil (car global)) (or (cdr local) (cdr global))))))) +(defun org-cite-read-processor-declaration (s) + "Read processor declaration from string S. + +Return (NAME BIBLIOGRAPHY-STYLE CITATION-STYLE) triplet, when +NAME is the processor name, as a symbol, and both +BIBLIOGRAPHY-STYLE and CITATION-STYLE are strings or nil. Those +strings may contain spaces if they are enclosed within double +quotes. + +String S is expected to contain between 1 and 3 tokens. The +function raises an error when it contains too few or too many +tokens. Spurious spaces are ignored." + (with-temp-buffer + (save-excursion (insert s)) + (let ((result (list (read (current-buffer))))) + (dotimes (_ 2) + (skip-chars-forward " \t") + (cond + ((eobp) (push nil result)) + ((char-equal ?\" (char-after)) + (push (org-not-nil (read (current-buffer))) + result)) + (t + (let ((origin (point))) + (skip-chars-forward "^ \t") + (push (org-not-nil (buffer-substring origin (point))) + result))))) + (skip-chars-forward " \t") + (unless (eobp) + (error "Trailing garbage following cite export processor declaration %S" + s)) + (nreverse result)))) + (defun org-cite-bibliography-style (info) "Return expected bibliography style. INFO is a plist used as a communication channel." @@ -1194,40 +1227,22 @@ INFO is the communication channel, as a plist. It is modified by side-effect." Export processor is stored as a triplet, or nil. -When non-nil, it is defined as (NAME BIBLIOGRAPHY-STYLE CITATION-STYLE) where -NAME is a symbol, whereas BIBLIOGRAPHY-STYLE and CITATION-STYLE are strings, -or nil. +When non-nil, it is defined as (NAME BIBLIOGRAPHY-STYLE +CITATION-STYLE) where NAME is a symbol, whereas +BIBLIOGRAPHY-STYLE and CITATION-STYLE are strings, or nil. -INFO is the communication channel, as a plist. It is modified by side-effect." +INFO is the communication channel, as a plist. It is modified by +side-effect." (let* ((err (lambda (s) - (user-error "Invalid cite export processor definition: %S" s))) + (user-error "Invalid cite export processor declaration: %S" s))) (processor (pcase (plist-get info :cite-export) ((or "" `nil) nil) ;; Value is a string. It comes from a "cite_export" - ;; keyword. It may contain between 1 and 3 tokens, the - ;; first one being a symbol and the other (optional) two, - ;; strings. + ;; keyword. ((and (pred stringp) s) - (with-temp-buffer - (save-excursion (insert s)) - (let ((result (list (read (current-buffer))))) - (dotimes (_ 2) - (skip-chars-forward " \t") - (cond - ((eobp) (push nil result)) - ((char-equal ?\" (char-after)) - (condition-case _ - (push (org-not-nil (read (current-buffer))) result) - (error (funcall err s)))) - (t - (let ((origin (point))) - (skip-chars-forward "^ \t") - (push (org-not-nil (buffer-substring origin (point))) - result))))) - (unless (eobp) (funcall err s)) - (nreverse result)))) + (org-cite-read-processor-declaration s)) ;; Value is an alist. It must come from ;; `org-cite-export-processors' variable. Find the most ;; appropriate processor according to current export diff --git a/testing/lisp/test-oc.el b/testing/lisp/test-oc.el index 896870303..722b0fb9a 100644 --- a/testing/lisp/test-oc.el +++ b/testing/lisp/test-oc.el @@ -763,6 +763,41 @@ :export-citation (lambda (_ s _ _) (throw :exit s))) (org-export-as (org-export-create-backend)))))))) +(ert-deftest test-org-cite/read-processor-declaration () + "Test `org-cite-read-processor-declaration'." + ;; Argument should contain 1-3 tokens. + (should-error + (org-cite-read-processor-declaration "")) + (should + (equal '(foo nil nil) + (org-cite-read-processor-declaration "foo"))) + (should + (equal '(foo "bar" nil) + (org-cite-read-processor-declaration "foo bar"))) + (should + (equal '(foo "bar" "baz") + (org-cite-read-processor-declaration "foo bar baz"))) + (should-error + (org-cite-read-processor-declaration "foo bar baz qux")) + ;; nil in second and third arguments is read as `nil'. + (should + (equal '(foo nil "baz") + (org-cite-read-processor-declaration "foo nil baz"))) + (should + (equal '(foo "bar" nil) + (org-cite-read-processor-declaration "foo bar nil"))) + ;; Second and third arguments may contain spaces if they are quoted. + (should + (equal '(foo "bar baz" nil) + (org-cite-read-processor-declaration "foo \"bar baz\""))) + (should + (equal '(foo "bar" "baz qux") + (org-cite-read-processor-declaration "foo bar \"baz qux\""))) + ;; Spurious spaces are ignored. + (should + (equal '(foo "bar" "baz") + (org-cite-read-processor-declaration " foo bar baz ")))) + (ert-deftest test-org-cite/list-citations () "Test `org-cite-list-citations'." (should