From 70bd6bcf11597d9865dba107a44030e1da17154b Mon Sep 17 00:00:00 2001 From: TEC Date: Mon, 6 Feb 2023 00:01:41 +0800 Subject: [PATCH 4/6] oc-*: Make use of conditional preamble for export * lisp/oc-natbib.el (org-cite-natbib-use-package): Refactor to make use of the conditional/generated preamble. * lisp/oc-csl.el (org-cite-csl-finalizer): Refactor to make use of the conditional/generated preamble. * lisp/oc-biblatex.el (org-cite-biblatex-prepare-preamble): Refactor to make use of the conditional/generated preamble. --- lisp/oc-biblatex.el | 82 ++++++++++++++++++--------------------------- lisp/oc-csl.el | 16 --------- lisp/oc-natbib.el | 33 +++++++----------- lisp/ox-latex.el | 15 +++++++++ 4 files changed, 61 insertions(+), 85 deletions(-) diff --git a/lisp/oc-biblatex.el b/lisp/oc-biblatex.el index b2d31f0f6..e8e420891 100644 --- a/lisp/oc-biblatex.el +++ b/lisp/oc-biblatex.el @@ -375,61 +375,45 @@ (defun org-cite-biblatex-export-citation (citation style _ info) (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. - -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-preamble (info) + "Ensure that the biblatex package is loaded, and the necessary resources. +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)) + (files (plist-get info :bibliography)) + (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))) + ;; Load resources. + (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 432738a97..f85646379 100644 --- a/lisp/oc-csl.el +++ b/lisp/oc-csl.el @@ -840,27 +840,11 @@ (defun org-cite-csl-render-bibliography (_keys _files _style props _backend info ;; 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 855be2a5c..b5cb193e7 100644 --- a/lisp/oc-natbib.el +++ b/lisp/oc-natbib.el @@ -157,32 +157,25 @@ (defun org-cite-natbib-export-citation (citation style _ info) (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 9794e6ecd..040824f45 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1468,6 +1468,21 @@ (defcustom org-latex-feature-implementations (choice (string :tag "Verbatim content") (variable :tag "Content variable") (function :tag "Generating function")))) +;; 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 -- 2.39.0