diff --git a/lisp/oc-biblatex.el b/lisp/oc-biblatex.el index 36c0ee7e5..5e900a446 100644 --- a/lisp/oc-biblatex.el +++ b/lisp/oc-biblatex.el @@ -376,61 +376,47 @@ INFO is the export state, as a property list." (other (user-error "Invalid entry %S in `org-cite-biblatex-styles'" other)))))) -(defun org-cite-biblatex-prepare-preamble (output _keys files style &rest _) - "Prepare document preamble for \"biblatex\" usage. +(defun org-cite-biblatex--generate-latex-usepackage (info) + "Ensure that the biblatex package is loaded. +This is performed by extracting relevant information from the +INFO export plist, and modifying any existing +\\usepackage{biblatex} statement in the LaTeX header." + (let ((style (org-cite-bibliography-style info)) + (usepackage-rx (rx "\\usepackage" + (opt (group "[" (*? anything) "]")) + "{biblatex}"))) + (concat + (if (string-match usepackage-rx (plist-get info :latex-full-header)) + ;; "biblatex" package loaded, but with none (or different) options. + ;; Replace with style-including command. + (plist-put info :latex-full-header + (replace-match + (format "\\usepackage%s{biblatex}" + (save-match-data + (org-cite-biblatex--package-options nil style))) + t t + (plist-get info :latex-full-header))) + ;; No "biblatex" package loaded. Insert "usepackage" command + ;; with appropriate options, including style. + (format "\\usepackage%s{biblatex}\n" + (org-cite-biblatex--package-options + org-cite-biblatex-options style)))))) -OUTPUT is the final output of the export process. FILES is the list of file -names used as the bibliography. - -This function ensures \"biblatex\" package is required. It also adds resources -to the document, and set styles." - (with-temp-buffer - (save-excursion (insert output)) - (when (search-forward "\\begin{document}" nil t) - ;; Ensure there is a \usepackage{biblatex} somewhere or add one. - ;; Then set options. - (goto-char (match-beginning 0)) - (let ((re (rx "\\usepackage" - (opt (group "[" (*? anything) "]")) - "{biblatex}"))) - (cond - ;; No "biblatex" package loaded. Insert "usepackage" command - ;; with appropriate options, including style. - ((not (re-search-backward re nil t)) - (save-excursion - (insert - (format "\\usepackage%s{biblatex}\n" - (org-cite-biblatex--package-options - org-cite-biblatex-options style))))) - ;; "biblatex" package loaded, but without any option. - ;; Include style only. - ((not (match-beginning 1)) - (search-forward "{" nil t) - (insert (org-cite-biblatex--package-options nil style))) - ;; "biblatex" package loaded with some options set. Override - ;; style-related options with ours. - (t - (replace-match - (save-match-data - (org-cite-biblatex--package-options (match-string 1) style)) - nil nil nil 1)))) - ;; Insert resources below. - (forward-line) - (insert (mapconcat (lambda (f) - (format "\\addbibresource%s{%s}" - (if (org-url-p f) "[location=remote]" "") - f)) - files - "\n") - "\n")) - (buffer-string))) +(defun org-cite-biblatex--generate-latex-bibresources (info) + "From INFO generate LaTeX that loads the relevant bibliography resource files." + (let ((files (plist-get info :bibliography))) + (mapconcat (lambda (f) + (format "\\addbibresource%s{%s}" + (if (org-url-p f) "[location=remote]" "") + f)) + files + "\n"))) ;;; Register `biblatex' processor (org-cite-register-processor 'biblatex :export-bibliography #'org-cite-biblatex-export-bibliography :export-citation #'org-cite-biblatex-export-citation - :export-finalizer #'org-cite-biblatex-prepare-preamble :cite-styles #'org-cite-biblatex-list-styles) (provide 'oc-biblatex) diff --git a/lisp/oc-csl.el b/lisp/oc-csl.el index becdaed81..67dd8548a 100644 --- a/lisp/oc-csl.el +++ b/lisp/oc-csl.el @@ -847,27 +847,11 @@ INFO is the export state, as a property list." ;; process. (org-cite-parse-elements output))))) -(defun org-cite-csl-finalizer (output _keys _files _style _backend info) - "Add \"hanging\" package if missing from LaTeX output. -OUTPUT is the export document, as a string. INFO is the export state, as a -property list." - (org-cite-csl--barf-without-citeproc) - (if (not (eq 'org-latex (org-cite-csl--output-format info))) - output - (with-temp-buffer - (save-excursion (insert output)) - (when (search-forward "\\begin{document}" nil t) - (goto-char (match-beginning 0)) - ;; Insert the CSL-specific parts of the LaTeX preamble. - (insert (org-cite-csl--generate-latex-preamble info))) - (buffer-string)))) - ;;; Register `csl' processor (org-cite-register-processor 'csl :export-citation #'org-cite-csl-render-citation :export-bibliography #'org-cite-csl-render-bibliography - :export-finalizer #'org-cite-csl-finalizer :cite-styles '((("author" "a") ("bare" "b") ("caps" "c") ("full" "f") ("bare-caps" "bc") ("caps-full" "cf") ("bare-caps-full" "bcf")) (("noauthor" "na") ("bare" "b") ("caps" "c") ("bare-caps" "bc")) diff --git a/lisp/oc-natbib.el b/lisp/oc-natbib.el index e6b971c05..99c97aa2a 100644 --- a/lisp/oc-natbib.el +++ b/lisp/oc-natbib.el @@ -168,32 +168,25 @@ state, as a property list." (org-cite-natbib--build-optional-arguments citation info) (org-cite-natbib--build-arguments citation))) -(defun org-cite-natbib-use-package (output &rest _) - "Ensure output requires \"natbib\" package. -OUTPUT is the final output of the export process." - (with-temp-buffer - (save-excursion (insert output)) - (when (search-forward "\\begin{document}" nil t) - ;; Ensure there is a \usepackage{natbib} somewhere or add one. - (goto-char (match-beginning 0)) - (let ((re (rx "\\usepackage" (opt "[" (*? nonl) "]") "{natbib}"))) - (unless (re-search-backward re nil t) - (insert - (format "\\usepackage%s{natbib}\n" - (if (null org-cite-natbib-options) - "" - (format "[%s]" - (mapconcat #'symbol-name - org-cite-natbib-options - ",")))))))) - (buffer-string))) +(defun org-cite-natbib--generate-latex-preamble (info) + "Ensure that the \"natbib\" package is loaded. +INFO is a plist used as a communication channel." + (and (not (string-match + (rx "\\usepackage" (opt "[" (*? nonl) "]") "{natbib}") + (plist-get info :latex-full-header))) + (format "\\usepackage%s{natbib}\n" + (if (null org-cite-natbib-options) + "" + (format "[%s]" + (mapconcat #'symbol-name + org-cite-natbib-options + ",")))))) ;;; Register `natbib' processor (org-cite-register-processor 'natbib :export-bibliography #'org-cite-natbib-export-bibliography :export-citation #'org-cite-natbib-export-citation - :export-finalizer #'org-cite-natbib-use-package :cite-styles '((("author" "a") ("caps" "a") ("full" "f")) (("noauthor" "na") ("bare" "b")) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 080408b7d..bbec65554 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1460,6 +1460,22 @@ default values of which are given by `org-latex-engraved-preamble' and "% WARNING syntax highlighting unavailable as engrave-faces-latex was missing.\n") "\n"))) +;; Citation features + +(org-export-update-features 'latex + (bibliography-csl + :condition (eq (org-cite-processor info) 'csl) + :when bibliography + :snippet org-cite-csl--generate-latex-preamble) + (bibliography-biblatex + :condition (eq (org-cite-processor info) 'biblatex) + :when bibliography + :snippet org-cite-biblatex--generate-latex-preamble) + (bibliography-natbib + :condition (eq (org-cite-processor info) 'natbib) + :when bibliography + :snippet org-cite-natbib--generate-latex-preamble)) + ;;;; Compilation (defcustom org-latex-compiler-file-string "%% Intended LaTeX compiler: %s\n"