Browse Source

oc: Factor out string to cite export processor triplet conversion

* lisp/oc.el (org-cite-read-processor-declaration): New function.
(org-cite-store-export-processor): Use new function.
* testing/lisp/test-oc.el (test-org-cite/read-processor-declaration):
New test.
Nicolas Goaziou 3 years ago
parent
commit
5d2e2cd1bc
2 changed files with 76 additions and 26 deletions
  1. 41 26
      lisp/oc.el
  2. 35 0
      testing/lisp/test-oc.el

+ 41 - 26
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

+ 35 - 0
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