oc-csl.el: Add support for sub-bibliographies

* lisp/oc-csl.el (org-cite-csl--rendered-bibliographies): New function
to collect all #+print_bibliography keywords with their properties and
call Citeproc to render all sub-bibliographies in one go as required
by the API.  Return the formatted bibliographies as values in an alist
in which keys are the #+print_bibliography keyword options as plists.
Cache the return value in the export communication channel.
(org-cite-csl--bibliography-filter): New helper function to convert
plists representing #+print_bibliography options to the alist filter
form expected by Citeproc.
(org-cite-csl--rendered-citations): Call
`org-cite-csl--rendered-bibliographies' before rendering citations to
make sure that the complete sub-bibliography information is added to
the processor and, therefore, citation numbers are correct.
(org-cite-csl--render-bibliography): Instead of directly calling
Citeproc to render the bibliography, call
`org-cite-csl--rendered-bibliographies' and retrieve the formatted
bibliography from its return value based on the options passed as the
`props' argument.
This commit is contained in:
András Simonyi 2022-07-11 19:13:48 +02:00 committed by Ihor Radchenko
parent 785f003de5
commit 7e07611844
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
2 changed files with 88 additions and 8 deletions

View File

@ -239,7 +239,7 @@ This behaviour can be changed by supplying a =:align= parameter.
The tabbing environment can be useful when generating simple tables which The tabbing environment can be useful when generating simple tables which
can be span multiple pages and when table cells are allowed to overflow. can be span multiple pages and when table cells are allowed to overflow.
*** Support for =nocite= citations in the "csl" export processor *** Support for =nocite= citations and sub-bibliographies in the "csl" export processor
The "csl" citation export processor now supports =nocite= style The "csl" citation export processor now supports =nocite= style
citations that add items to the printed bibliography without visible citations that add items to the printed bibliography without visible
@ -251,6 +251,17 @@ instance,
#+end_src #+end_src
includes all available items in the printed bibliography. includes all available items in the printed bibliography.
The "csl" export processor now also supports sub-bibliographies that
show only a subset of the references based on some criterion. For
example,
#+begin_src org
#+print_bibliography: :type book :keyword ai
#+end_src
prints a sub-bibliography containing the book entries with =ai= among
their keywords.
** New functions and changes in function arguments ** New functions and changes in function arguments
*** ~org-fold-show-entry~ does not fold drawers by default anymore *** ~org-fold-show-entry~ does not fold drawers by default anymore

View File

@ -90,11 +90,23 @@
;; The part of the suffix before the locator is appended to reference's prefix. ;; The part of the suffix before the locator is appended to reference's prefix.
;; If no locator term is used, but a number is present, then "page" is assumed. ;; If no locator term is used, but a number is present, then "page" is assumed.
;; Filtered sub-bibliographies can be printed by passing filtering
;; options to the "print_bibliography" keywords. E.g.,
;;
;; #+print_bibliography: :type book keyword: emacs
;;
;; If you need to use a key multiple times, you can separate its
;; values with commas, but without any space in-between:
;;
;; #+print_bibliography: :keyword abc,xyz :type article
;; This library was heavily inspired by and borrows from András Simonyi's ;; This library was heavily inspired by and borrows from András Simonyi's
;; Citeproc Org (<https://github.com/andras-simonyi/citeproc-org>) library. ;; Citeproc Org (<https://github.com/andras-simonyi/citeproc-org>) library.
;; Many thanks to him! ;; Many thanks to him!
;;; Code: ;;; Code:
(require 'cl-lib)
(require 'map)
(require 'bibtex) (require 'bibtex)
(require 'json) (require 'json)
(require 'oc) (require 'oc)
@ -559,6 +571,10 @@ OUTPUT using Citeproc."
(citeproc-append-citations structures processor)) (citeproc-append-citations structures processor))
(when nocite-ids (when nocite-ids
(citeproc-add-uncited nocite-ids processor)) (citeproc-add-uncited nocite-ids processor))
;; All bibliographies have to be rendered in order to have
;; correct citation numbers even if there are several
;; sub-bibliograhies.
(org-cite-csl--rendered-bibliographies info)
(let (result (let (result
(rendered (citeproc-render-citations (rendered (citeproc-render-citations
processor processor
@ -572,6 +588,62 @@ OUTPUT using Citeproc."
(plist-put info :cite-citeproc-rendered-citations result) (plist-put info :cite-citeproc-rendered-citations result)
result)))) result))))
(defun org-cite-csl--bibliography-filter (bib-props)
"Return the sub-bibliography filter corresponding to bibliography properties.
BIB-PROPS should be a plist representing the properties
associated with a \"print_bibliography\" keyword, as returned by
`org-cite-bibliography-properties'."
(let (result
(remove-keyword-colon (lambda (x) (intern (substring (symbol-name x) 1)))))
(map-do
(lambda (key value)
(pcase key
((or :keyword :notkeyword :nottype :notcsltype :filter)
(dolist (v (split-string value ","))
(push (cons (funcall remove-keyword-colon key) v) result)))
((or :type :csltype)
(if (string-match-p "," value)
(user-error "The \"%s\" print_bibliography option does not support comma-separated values" key)
(push (cons (funcall remove-keyword-colon key) value) result)))))
bib-props)
result))
(defun org-cite-csl--rendered-bibliographies (info)
"Return the rendered bibliographies.
INFO is the export state, as a property list.
Return an (OUTPUTS PARAMETERS) list where OUTPUTS is an alist
of (BIB-PROPS . OUTPUT) pairs where each key is a property list
of a \"print_bibliography\" keyword and the corresponding OUTPUT
value is the bibliography as rendered by Citeproc."
(or (plist-get info :cite-citeproc-rendered-bibliographies)
(let (bib-plists bib-filters)
;; Collect bibliography property lists and the corresponding
;; Citeproc sub-bib filters.
(org-element-map (plist-get info :parse-tree) 'keyword
(lambda (keyword)
(when (equal "PRINT_BIBLIOGRAPHY" (org-element-property :key keyword))
(let ((bib-plist (org-cite-bibliography-properties keyword)))
(push bib-plist bib-plists)
(push (org-cite-csl--bibliography-filter bib-plist) bib-filters)))))
(setq bib-filters (nreverse bib-filters)
bib-plists (nreverse bib-plists))
;; Render and return all bibliographies.
(let ((processor (org-cite-csl--processor info)))
(citeproc-add-subbib-filters bib-filters processor)
(pcase-let* ((format (org-cite-csl--output-format info))
(`(,rendered-bibs . ,parameters)
(citeproc-render-bib
(org-cite-csl--processor info)
format
(org-cite-csl--no-citelinks-p info)))
(outputs (cl-mapcar #'cons bib-plists rendered-bibs))
(result (list outputs parameters)))
(plist-put info :cite-citeproc-rendered-bibliographies result)
result)))))
;;; Export capability ;;; Export capability
(defun org-cite-csl-render-citation (citation _style _backend info) (defun org-cite-csl-render-citation (citation _style _backend info)
@ -585,16 +657,13 @@ INFO is the export state, as a property list."
;; process. ;; process.
(org-cite-parse-objects output)))) (org-cite-parse-objects output))))
(defun org-cite-csl-render-bibliography (_keys _files _style _props _backend info) (defun org-cite-csl-render-bibliography (_keys _files _style props _backend info)
"Export bibliography. "Export bibliography.
INFO is the export state, as a property list." INFO is the export state, as a property list."
(org-cite-csl--barf-without-citeproc) (org-cite-csl--barf-without-citeproc)
(pcase-let* ((format (org-cite-csl--output-format info)) (pcase-let* ((format (org-cite-csl--output-format info))
(`(,output . ,parameters) (`(,outputs ,parameters) (org-cite-csl--rendered-bibliographies info))
(citeproc-render-bib (output (cdr (assoc props outputs))))
(org-cite-csl--processor info)
format
(org-cite-csl--no-citelinks-p info))))
(pcase format (pcase format
('html ('html
(concat (concat