Pārlūkot izejas kodu

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.
András Simonyi 2 gadi atpakaļ
vecāks
revīzija
7e07611844
2 mainītis faili ar 88 papildinājumiem un 8 dzēšanām
  1. 12 1
      etc/ORG-NEWS
  2. 76 7
      lisp/oc-csl.el

+ 12 - 1
etc/ORG-NEWS

@@ -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
 
 

+ 76 - 7
lisp/oc-csl.el

@@ -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))
-               (`(,output . ,parameters)
-                (citeproc-render-bib
-                 (org-cite-csl--processor info)
-                 format
-                 (org-cite-csl--no-citelinks-p info))))
+  (pcase-let*  ((format (org-cite-csl--output-format info))
+		(`(,outputs ,parameters) (org-cite-csl--rendered-bibliographies info))
+		(output (cdr (assoc props outputs))))
     (pcase format
     (pcase format
       ('html
       ('html
        (concat
        (concat