]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
add org-ref and citeproc
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Thu, 11 May 2023 15:39:37 +0000 (17:39 +0200)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Thu, 11 May 2023 15:39:37 +0000 (17:39 +0200)
Signed-off-by: Andreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
71 files changed:
elpa/citeproc-20230228.1414/citeproc-autoloads.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-biblatex.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-bibtex.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-choose.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-cite.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-context.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-date.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-disamb.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-formatters.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-generic-elements.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-itemdata.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-itemgetters.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-lib.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-locale.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-macro.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-name.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-number.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-pkg.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-prange.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-proc.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-rt.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-s.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-sort.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-style.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-subbibs.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-term.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc-test-human.el [new file with mode: 0644]
elpa/citeproc-20230228.1414/citeproc.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/citeproc/csl-locales/locales-en-US.xml [new file with mode: 0644]
elpa/org-ref-20230507.1420/citeproc/csl-styles/apa-5th-edition.csl [new file with mode: 0644]
elpa/org-ref-20230507.1420/citeproc/csl-styles/apa-numeric-superscript-brackets.csl [new file with mode: 0644]
elpa/org-ref-20230507.1420/citeproc/csl-styles/chicago-author-date-16th-edition.csl [new file with mode: 0644]
elpa/org-ref-20230507.1420/citeproc/csl-styles/elsevier-harvard.csl [new file with mode: 0644]
elpa/org-ref-20230507.1420/citeproc/csl-styles/elsevier-with-titles.csl [new file with mode: 0644]
elpa/org-ref-20230507.1420/contrib.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/doi-utils.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/nist-webbook.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/openalex.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-arxiv.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-autoloads.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-bibliography-links.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-bibtex.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-citation-links.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-compat.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-core.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-export.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-glossary.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-helm.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-isbn.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-ivy.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-label-link.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-latex.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-misc-links.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-natbib-bbl-citeproc.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-pdf.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-pgk.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-pkg.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-pubmed.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-ref-links.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-refproc.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-sci-id.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-scifinder.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-scopus.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-url-utils.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-utils.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-worldcat.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref-wos.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref.bib [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref.el [new file with mode: 0644]
elpa/org-ref-20230507.1420/org-ref.org [new file with mode: 0644]
elpa/org-ref-20230507.1420/x2bib.el [new file with mode: 0644]

diff --git a/elpa/citeproc-20230228.1414/citeproc-autoloads.el b/elpa/citeproc-20230228.1414/citeproc-autoloads.el
new file mode 100644 (file)
index 0000000..e34bfe7
--- /dev/null
@@ -0,0 +1,217 @@
+;;; citeproc-autoloads.el --- automatically extracted autoloads  -*- lexical-binding: t -*-
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+                         (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "citeproc" "citeproc.el" (0 0 0 0))
+;;; Generated autoloads from citeproc.el
+
+(register-definition-prefixes "citeproc" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-biblatex" "citeproc-biblatex.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from citeproc-biblatex.el
+
+(register-definition-prefixes "citeproc-biblatex" '("citeproc-blt-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-bibtex" "citeproc-bibtex.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from citeproc-bibtex.el
+
+(register-definition-prefixes "citeproc-bibtex" '("citeproc-bt-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-choose" "citeproc-choose.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from citeproc-choose.el
+
+(register-definition-prefixes "citeproc-choose" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-cite" "citeproc-cite.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-cite.el
+
+(register-definition-prefixes "citeproc-cite" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-context" "citeproc-context.el" (0
+;;;;;;  0 0 0))
+;;; Generated autoloads from citeproc-context.el
+
+(register-definition-prefixes "citeproc-context" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-date" "citeproc-date.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-date.el
+
+(register-definition-prefixes "citeproc-date" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-disamb" "citeproc-disamb.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from citeproc-disamb.el
+
+(register-definition-prefixes "citeproc-disamb" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-formatters" "citeproc-formatters.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from citeproc-formatters.el
+
+(register-definition-prefixes "citeproc-formatters" '("citeproc-f"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-generic-elements" "citeproc-generic-elements.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from citeproc-generic-elements.el
+
+(register-definition-prefixes "citeproc-generic-elements" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-itemdata" "citeproc-itemdata.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from citeproc-itemdata.el
+
+(register-definition-prefixes "citeproc-itemdata" '("citeproc-itd-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-itemgetters" "citeproc-itemgetters.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from citeproc-itemgetters.el
+
+(register-definition-prefixes "citeproc-itemgetters" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-lib" "citeproc-lib.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-lib.el
+
+(register-definition-prefixes "citeproc-lib" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-locale" "citeproc-locale.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from citeproc-locale.el
+
+(register-definition-prefixes "citeproc-locale" '("citeproc-locale-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-macro" "citeproc-macro.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from citeproc-macro.el
+
+(register-definition-prefixes "citeproc-macro" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-name" "citeproc-name.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-name.el
+
+(register-definition-prefixes "citeproc-name" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-number" "citeproc-number.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from citeproc-number.el
+
+(register-definition-prefixes "citeproc-number" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-prange" "citeproc-prange.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from citeproc-prange.el
+
+(register-definition-prefixes "citeproc-prange" '("citeproc-prange-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-proc" "citeproc-proc.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-proc.el
+
+(register-definition-prefixes "citeproc-proc" '("citeproc-proc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-rt" "citeproc-rt.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-rt.el
+
+(register-definition-prefixes "citeproc-rt" '("citeproc-rt-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-s" "citeproc-s.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-s.el
+
+(register-definition-prefixes "citeproc-s" '("citeproc-s-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-sort" "citeproc-sort.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-sort.el
+
+(register-definition-prefixes "citeproc-sort" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-style" "citeproc-style.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from citeproc-style.el
+
+(register-definition-prefixes "citeproc-style" '("citeproc-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-subbibs" "citeproc-subbibs.el" (0
+;;;;;;  0 0 0))
+;;; Generated autoloads from citeproc-subbibs.el
+
+(register-definition-prefixes "citeproc-subbibs" '("citeproc-sb-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-term" "citeproc-term.el" (0 0 0 0))
+;;; Generated autoloads from citeproc-term.el
+
+(register-definition-prefixes "citeproc-term" '("citeproc-term-"))
+
+;;;***
+\f
+;;;### (autoloads nil "citeproc-test-human" "citeproc-test-human.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from citeproc-test-human.el
+
+(register-definition-prefixes "citeproc-test-human" '("citeproc-test-human-"))
+
+;;;***
+\f
+;;;### (autoloads nil nil ("citeproc-pkg.el") (0 0 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; citeproc-autoloads.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-biblatex.el b/elpa/citeproc-20230228.1414/citeproc-biblatex.el
new file mode 100644 (file)
index 0000000..decb145
--- /dev/null
@@ -0,0 +1,521 @@
+;;; citeproc-biblatex.el --- convert biblatex entries to CSL -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Convert biblatex bibliography entries to CSL.
+
+;;; Code:
+
+(require 'parse-time)
+(require 'citeproc-bibtex)
+
+(defvar citeproc-blt-to-csl-types-alist
+  '((article . "article-journal")
+    (book . "book")
+    (periodical . "book")
+    (booklet . "pamphlet")
+    (bookinbook . "chapter")
+    (misc . "article")
+    (other . "article")
+    (standard . "legislation")
+    (collection . "book")
+    (conference . "paper-conference")
+    (dataset . "dataset")
+    (electronic . "webpage")
+    (inbook . "chapter")
+    (incollection . "chapter")
+    (inreference . "entry-encyclopedia")
+    (inproceedings . "paper-conference")
+    (manual . "book")
+    (mastersthesis . "thesis")
+    (mvbook . "book")
+    (mvcollection . "book")
+    (mvproceedings . "book")
+    (mvreference . "book")
+    (online . "webpage")
+    (patent . "patent")
+    (phdthesis . "thesis")
+    (proceedings . "book")
+    (reference . "book")
+    (report . "report")
+    (software . "software")
+    (suppbook . "chapter")
+    (suppcollection . "chapter")
+    (techreport . "report")
+    (thesis . "thesis")
+    (unpublished . "manuscript")
+    (www . "webpage")
+    (artwork . "graphic")
+    (audio . "song")
+    (commentary . "book")
+    (image . "figure")
+    (jurisdiction . "legal_case")
+    (legislation . "bill") ?
+    (legal . "treaty")
+    (letter . "personal_communication")
+    (movie . "motion_picture")
+    (music . "song")
+    (performance . "speech")
+    (review . "review")
+    (standard . "legislation")
+    (video . "motion_picture")
+    (data . "dataset")
+    (letters . "personal_communication")
+    (newsarticle . "article-newspaper"))
+  "Alist mapping biblatex item types to CSL item types.")
+
+(defun citeproc-blt--to-csl-type (type entrysubtype)
+  "Return the CSL type corresponding to blt TYPE and ENTRYSUBTYPE."
+  (pcase type
+    ((or 'article 'periodical 'supperiodical)
+     (pcase entrysubtype
+       ("magazine" "article-magazine")
+       ("newspaper" "article-newspaper")
+       (_ "article-journal")))
+    (_ (assoc-default type citeproc-blt-to-csl-types-alist))))
+
+(defvar citeproc-blt-reftype-to-genre
+  '(("mastersthesis" . "Master's thesis")
+    ("phdthesis" . "PhD thesis")
+    ("mathesis" . "Master's thesis")
+    ("resreport" . "research report")
+    ("techreport" . "technical report")
+    ("patreqfr" . "French patent request")
+    ("patenteu" . "European patent")
+    ("patentus" . "U.S. patent"))
+  "Alist mapping biblatex reftypes to CSL genres.")
+
+(defvar citeproc-blt-article-types
+  '(article periodical suppperiodical review)
+  "Article-like biblatex types.")
+
+(defvar citeproc-blt-chapter-types
+ '(inbook incollection inproceedings inreference bookinbook)
+  "Chapter-like biblatex types.")
+
+(defvar citeproc-blt-collection-types
+  '(book collection proceedings reference
+    mvbook mvcollection mvproceedings mvreference
+    bookinbook inbook incollection inproceedings
+    inreference suppbook suppcollection)
+  "Collection or collection part biblatex types.")
+
+(defvar citeproc-blt-to-csl-names-alist
+  '((author . author)
+    (editor . editor)
+    (bookauthor . container-author)
+    (translator . translator))
+  "Alist mapping biblatex name fields to the corresponding CSL ones.")
+
+(defvar citeproc-blt-editortype-to-csl-name-alist
+  '(("organizer" . organizer)
+    ("director" . director)
+    ("compiler" . compiler)
+    ("editor" . editor)
+    ("collaborator" . contributor))
+  "Alist mapping biblatex editortypes to CSL fields.")
+
+(defvar citeproc-blt-to-csl-dates-alist
+  '((eventdate . event-date)
+    (origdate . original-date)
+    (urldate . accessed))
+  "Alist mapping biblatex date fields to the corresponding CSL ones.")
+
+(defconst citeproc-blt--publisher-fields
+  '(school institution organization howpublished publisher)
+  "Biblatex fields containing publisher-related information.")
+
+(defconst citeproc-blt--etype-to-baseurl-alist
+  '(("arxiv" . "https://arxiv.org/abs/")
+    ("jstor" . "https://www.jstor.org/stable/")
+    ("pubmed" ."https://www.ncbi.nlm.nih.gov/pubmed/")
+    ("googlebooks" . "https://books.google.com?id="))
+  "Alist mapping biblatex date fields to the corresponding CSL ones.")
+
+(defvar citeproc-blt-to-csl-standard-alist
+  '(;; locators
+    (volume . volume)
+    (part .  part)
+    (edition . edition)
+    (version . version)
+    (volumes . number-of-volumes)
+    (pagetotal . number-of-pages)
+    (chapter . chapter-number)
+    (pages . page)
+    ;; publisher
+    (origpublisher . original-publisher)
+    ;; places
+    (venue . event-place)
+    (origlocation . original-publisher-place)
+    (address . publisher-place)
+    ;; doi etcetera
+    (doi . DOI)
+    (isbn . ISBN)
+    (issn . ISSN)
+    (pmid . PMID)
+    (pmcid . PMCID)
+    (library . call-number)
+    ;; notes
+    (abstract . abstract)
+    (annotation . annote)
+    (annote . annote)                  ; alias for jurabib compatibility
+    ;; else
+    (pubstate . status)
+    (language . language)
+    (version . version)
+    (keywords . keyword)
+    (label . citation-label))
+  "Alist mapping biblatex standard fields to the corresponding CSL ones.
+Only those fields are mapped that do not require further processing.")
+
+(defvar citeproc-blt-to-csl-title-alist
+  '((eventtitle . event-title)
+    (origtitle . original-title)
+    (series . collection-title))
+  "Alist mapping biblatex title fields to the corresponding CSL ones.
+Only those fields are mapped that do not require further
+processing.")
+
+(defun citeproc-blt--parse-date (d)
+  "Parse single biblatex date-time expression D."
+  ;; Remove time part, if present.
+  (-when-let (time-sep-pos (cl-position ?T d))
+    (setq d (substring d 0 time-sep-pos)))
+  (--map (let ((converted (string-to-number it)))
+          (if (not (= converted 0))
+              converted
+            (error "Couldn't parse '%s' as a date" d)))
+        (split-string d "-")))
+
+(defun citeproc-blt--to-csl-date (d)
+  "Return a CSL version of the biblatex date field given by D."
+  (let* ((interval-strings (split-string d "/"))
+        (interval-date-parts
+         (mapcar #'citeproc-blt--parse-date interval-strings)))
+    (list (cons 'date-parts interval-date-parts))))
+
+(defun citeproc-blt--get-standard (v b &optional with-nocase)
+  "Return the CSL-normalized value of var V from item B.
+V is a biblatex var name as a string, B is a biblatex entry as an
+alist. If optional WITH-NOCASE is non-nil then convert BibTeX
+no-case brackets to the corresponding CSL XML spans. Return nil
+if V is undefined in B."
+  (-when-let (blt-val (alist-get v b))
+    (citeproc-bt--to-csl blt-val with-nocase)))
+
+(defun citeproc-blt--get-title (v b &optional with-nocase sent-case)
+  "Return the CSL-normalized value of a title var V from item B.
+If optional WITH-NOCASE is non-nil then convert BibTeX no-case
+brackets to the corresponding CSL XML spans, and if optional
+SENT-CASE is non-nil the convert to sentence-case. Return nil if
+V is undefined in B."
+  (-when-let (blt-val (alist-get v b))
+    (citeproc-blt--to-csl-title blt-val with-nocase sent-case)))
+
+(defun citeproc-blt--to-csl-title (s with-nocase sent-case)
+  "Return the CSL-normalized value of a title string S.
+If optional WITH-NOCASE is non-nil then convert BibTeX no-case
+brackets to the corresponding CSL XML spans, and if optional
+SENT-CASE is non-nil the convert to sentence-case."
+  (if sent-case
+      (citeproc-s-sentence-case-title (citeproc-bt--to-csl s t) (not with-nocase))
+    (citeproc-bt--to-csl s with-nocase)))
+
+(defconst citeproc-blt--titlecase-langids
+  '("american" "british" "canadian" "english" "australian" "newzealand"
+    "USenglish" "UKenglish")
+  "List of biblatex langids with title-cased title fields.")
+
+(defconst citeproc-blt--langid-to-lang-alist
+  '(("english" . "en-US")
+    ("USenglish" . "en-US")
+    ("american" . "en-US")
+    ("british" . "en-GB")
+    ("UKenglish" . "en-GB")
+    ("canadian" . "en-US")
+    ("australian" . "en-GB")
+    ("newzealand" . "en-GB")
+    ("afrikaans" . "af-ZA")
+    ("arabic" . "ar")
+    ("basque" . "eu")
+    ("bulgarian" . "bg-BG")
+    ("catalan" . "ca-AD")
+    ("croatian" . "hr-HR")
+    ("czech" . "cs-CZ")
+    ("danish" . "da-DK")
+    ("dutch" . "nl-NL")
+    ("estonian" . "et-EE")
+    ("finnish" . "fi-FI")
+    ("canadien" . "fr-CA")
+    ("acadian" . "fr-CA")
+    ("french" . "fr-FR")
+    ("francais" . "fr-FR")
+    ("austrian" . "de-AT")
+    ("naustrian" . "de-AT")
+    ("german" . "de-DE")
+    ("germanb" . "de-DE")
+    ("ngerman" . "de-DE")
+    ("greek" . "el-GR")
+    ("polutonikogreek" . "el-GR")
+    ("hebrew" . "he-IL")
+    ("hungarian" . "hu-HU")
+    ("icelandic" . "is-IS")
+    ("italian" . "it-IT")
+    ("japanese" . "ja-JP")
+    ("latvian" . "lv-LV")
+    ("lithuanian" . "lt-LT")
+    ("magyar" . "hu-HU")
+    ("mongolian" . "mn-MN")
+    ("norsk" . "nb-NO")
+    ("nynorsk" . "nn-NO")
+    ("farsi" . "fa-IR")
+    ("polish" . "pl-PL")
+    ("brazil" . "pt-BR")
+    ("brazilian" . "pt-BR")
+    ("portugues" . "pt-PT")
+    ("portuguese" . "pt-PT")
+    ("romanian" . "ro-RO")
+    ("russian" . "ru-RU")
+    ("serbian" . "sr-RS")
+    ("serbianc" . "sr-RS")
+    ("slovak" . "sk-SK")
+    ("slovene" . "sl-SL")
+    ("spanish" . "es-ES")
+    ("swedish" . "sv-SE")
+    ("thai" . "th-TH")
+    ("turkish" . "tr-TR")
+    ("ukrainian" . "uk-UA")
+    ("vietnamese" . "vi-VN")
+    ("latin" . "la"))
+  "Alist mapping biblatex langids to CSL language codes.")
+
+(defun citeproc-blt-entry-to-csl (b &optional omit-nocase no-sentcase-wo-langid)
+  "Return a CSL form of parsed biblatex entry B.
+If the optional OMIT-NOCASE is non-nil then no no-case XML
+markers are generated, and if the optional NO-SENTCASE-WO-LANGID
+is non-nil then title fields in items without a `langid' field
+are not converted to sentence-case.
+
+The processing logic follows the analogous
+function (itemToReference) in John MacFarlane's Pandoc, see
+<https://github.com/jgm/pandoc/blob/master/src/Text/Pandoc/Citeproc/BibTeX.hs>
+Many thanks to him.
+
+Note: in the code, var names starting with ~ refer to values of
+biblatex variables in B."
+  (let* ((b (cl-remove-if (lambda (x) (equal "" (cdr x))) b))
+        (b (mapcar (lambda (x) (cons (intern (downcase (car x))) (cdr x))) b))
+        (~type (intern (downcase (alist-get '=type= b))))
+        (~entrysubtype (alist-get 'entrysubtype b))
+        (type (citeproc-blt--to-csl-type ~type ~entrysubtype))
+        (is-article (memq ~type citeproc-blt-article-types))
+        (is-periodical (eq ~type 'periodical))
+        (is-chapter-like (memq ~type citeproc-blt-chapter-types))
+        (~langid (alist-get 'langid b))
+        (sent-case (or (member ~langid citeproc-blt--titlecase-langids)
+                       (and (null ~langid) (not no-sentcase-wo-langid))))
+        (with-nocase (not omit-nocase))
+        result)
+    ;; language
+    (when ~langid
+      (push (cons 'language (cdr (assoc ~langid citeproc-blt--langid-to-lang-alist)))
+           result))
+    ;; set type and genre
+    (push (cons 'type type) result)
+    (when-let ((~reftype (alist-get 'type b)))
+      (push (cons 'genre (or (assoc-default ~reftype citeproc-blt-reftype-to-genre)
+                            (citeproc-bt--to-csl ~reftype)))
+           result))
+    ;; We store the original bib(la)tex type for filtering purposes.
+    (push (cons 'blt-type (symbol-name ~type)) result)
+    ;; names
+    ;; TODO: handle  editorb and editorc as well...
+    (when-let ((~editortype (alist-get 'editortype b))
+              (~editor (alist-get 'editor b))
+              (csl-var (assoc-default ~editortype
+                                      citeproc-blt-editortype-to-csl-name-alist)))
+      (push (cons csl-var (citeproc-bt--to-csl-names ~editor))
+           result))
+    (when-let ((~editoratype (alist-get 'editoratype b))
+              (~editora (alist-get 'editora b))
+              (csl-var (assoc-default ~editoratype
+                                      citeproc-blt-editortype-to-csl-name-alist)))
+      (push (cons csl-var (citeproc-bt--to-csl-names ~editora))
+           result))
+    ;; dates
+    (-when-let (issued (-if-let (~issued (alist-get 'date b))
+                          (citeproc-blt--to-csl-date ~issued)
+                        (-when-let (~year (alist-get 'year b))
+                          (citeproc-bt--to-csl-date ~year
+                                                    (alist-get 'month b)))))
+      (push (cons 'issued issued) result))
+    ;; locators
+    (-if-let (~number (alist-get 'number b))
+       (cond ((memq ~type citeproc-blt-collection-types) ; collection
+              (push `(collection-number . ,~number) result))
+             (is-article               ; article
+              (push `(issue . ,(-if-let (~issue (alist-get 'issue b))
+                                   (concat ~number ", " ~issue)
+                                 ~number))
+                    result))
+             (t (push `(number . ,~number) result))))
+    ;; titles
+    (let* ((~maintitle (citeproc-blt--get-title 'maintitle b with-nocase sent-case))
+          (title
+           (cond (is-periodical (citeproc-blt--get-title 'issuetitle b with-nocase sent-case))
+                 ((and ~maintitle (not is-chapter-like)) ~maintitle)
+                 (t (citeproc-blt--get-title 'title b with-nocase sent-case))))
+          (subtitle (citeproc-blt--get-title
+                     (cond (is-periodical 'issuesubtitle)
+                           ((and ~maintitle (not is-chapter-like))
+                            'mainsubtitle)
+                           (t 'subtitle))
+                     b with-nocase sent-case))
+          (title-addon
+           (citeproc-blt--get-title
+            (if (and ~maintitle (not is-chapter-like))
+                'maintitleaddon 'titleaddon)
+            b with-nocase sent-case))
+          (volume-title
+           (when ~maintitle
+             (citeproc-blt--get-title
+              (if is-chapter-like 'booktitle 'title) b with-nocase sent-case)))
+          (volume-subtitle
+           (when ~maintitle
+             (citeproc-blt--get-title
+              (if is-chapter-like 'booksubtitle 'subtitle) b with-nocase sent-case)))
+          (volume-title-addon
+           (when ~maintitle
+             (citeproc-blt--get-title
+              (if is-chapter-like 'booktitleaddon 'titleaddon) b with-nocase sent-case)))
+          (container-title
+           (or (and is-periodical (citeproc-blt--get-title 'title b with-nocase sent-case))
+               (and is-chapter-like ~maintitle)
+               (and is-chapter-like (citeproc-blt--get-title
+                                     'booktitle b with-nocase sent-case))
+               (or (citeproc-blt--get-title 'journaltitle b with-nocase sent-case)
+                   ;; also accept `journal' for BibTeX compatibility
+                   (citeproc-blt--get-title 'journal b with-nocase sent-case))))
+          (container-subtitle
+           (or (and is-periodical (citeproc-blt--get-title
+                                   'subtitle b with-nocase sent-case))
+               (and is-chapter-like (citeproc-blt--get-title
+                                     'mainsubtitle b with-nocase sent-case))
+               (and is-chapter-like (citeproc-blt--get-title
+                                     'booksubtitle b with-nocase sent-case))
+               (citeproc-blt--get-title 'journalsubtitle b with-nocase sent-case)))
+          (container-title-addon
+           (or (and is-periodical (citeproc-blt--get-title
+                                   'titleaddon b with-nocase sent-case))
+               (and is-chapter-like (citeproc-blt--get-title
+                                     'maintitleaddon b with-nocase sent-case))
+               (and is-chapter-like
+                    (citeproc-blt--get-title 'booktitleaddon b with-nocase sent-case))))
+          (container-title-short
+           (or (and is-periodical (not ~maintitle)
+                    (citeproc-blt--get-title 'titleaddon b with-nocase sent-case))
+               (citeproc-blt--get-title 'shortjournal b with-nocase sent-case)))
+          (title-short
+           (or (and (or (not ~maintitle) is-chapter-like)
+                    (citeproc-blt--get-title 'shorttitle b with-nocase sent-case))
+               (and (or subtitle title-addon)
+                    (not ~maintitle)
+                    title))))
+      (when title
+       (push (cons 'title
+                   (concat title
+                           (when subtitle (concat ": " subtitle))
+                           (when title-addon (concat ". " title-addon))))
+             result))
+      (when title-short
+       (push (cons 'title-short title-short) result))
+      (when volume-title
+       (push (cons 'volume-title
+                   (concat volume-title
+                           (when volume-subtitle (concat ": " volume-subtitle))
+                           (when volume-title-addon (concat ". " volume-title-addon))))
+             result))
+      (when container-title
+       (push (cons 'container-title
+                   (concat container-title
+                           (when container-subtitle (concat ": " container-subtitle))
+                           (when container-title-addon (concat ". " container-title-addon))))
+             result))
+      (when container-title-short
+       (push (cons 'container-title-short container-title-short) result)))
+    ;; publisher
+    (-when-let (values (-non-nil (--map (citeproc-blt--get-standard it b)
+                                       citeproc-blt--publisher-fields)))
+      (push `(publisher . ,(mapconcat #'identity values "; ")) result))
+    ;; places
+    (let ((csl-place-var
+          (if (eq ~type 'patent) 'jurisdiction 'publisher-place)))
+      (-when-let (~location (or (citeproc-blt--get-standard 'location b)
+                               (citeproc-blt--get-standard 'address b)))
+       (push (cons csl-place-var ~location) result)))
+    ;; url
+    (-when-let (url (or (let ((u (alist-get 'url b))) (and u (citeproc-s-replace "\\" "" u)))
+                       (when-let ((~eprinttype (or (alist-get 'eprinttype b)
+                                                   (alist-get 'archiveprefix b)))
+                                  (~eprint (alist-get 'eprint b))
+                                  (base-url
+                                   (assoc-default ~eprinttype
+                                                  citeproc-blt--etype-to-baseurl-alist)))
+                         (concat base-url ~eprint))))
+      (push (cons 'URL url) result))
+    ;; notes
+    (-when-let (note (let ((~note (citeproc-blt--get-standard 'note b))
+                          (~addendum (citeproc-blt--get-standard 'addendum b)))
+                      (cond ((and ~note ~addendum) (concat ~note ". " ~addendum))
+                            (~note ~note)
+                            (~addendum ~addendum)
+                            (t nil))))
+      (push (cons 'note note) result))
+    ;; rest
+    (let (rest)
+      (pcase-dolist (`(,blt-key . ,blt-value) b)
+       ;; remaining standard vars
+       (-when-let (csl-key
+                   (alist-get blt-key citeproc-blt-to-csl-standard-alist))
+         (unless (alist-get csl-key result)
+           (push (cons csl-key (citeproc-bt--to-csl blt-value)) rest)))
+       ;; remaining name vars
+       (-when-let (csl-key
+                   (alist-get blt-key citeproc-blt-to-csl-names-alist))
+         (unless (alist-get csl-key result)
+           (push (cons csl-key (citeproc-bt--to-csl-names blt-value)) rest)))
+       ;; remaining date vars
+       (-when-let (csl-key
+                   (alist-get blt-key citeproc-blt-to-csl-dates-alist))
+         (unless (alist-get csl-key result)
+           (push (cons csl-key (citeproc-blt--to-csl-date blt-value)) rest)))
+       ;; remaining title vars
+       (-when-let (csl-key
+                   (alist-get blt-key citeproc-blt-to-csl-title-alist))
+         (push (cons csl-key
+                     (citeproc-blt--to-csl-title blt-value with-nocase sent-case))
+               rest)))
+      (append result rest))))
+
+(provide 'citeproc-biblatex)
+
+;;; citeproc-biblatex.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-bibtex.el b/elpa/citeproc-20230228.1414/citeproc-bibtex.el
new file mode 100644 (file)
index 0000000..41092cc
--- /dev/null
@@ -0,0 +1,487 @@
+;;; citeproc-bibtex.el --- convert BibTeX entries to CSL -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Convert BibTeX bibliography entries to CSL.
+
+;;; Code:
+
+(require 'dash)
+(require 'subr-x)
+(require 'bibtex)
+(require 'cl-lib)
+(require 's)
+(require 'org)
+(require 'map)
+;; Handle the fact that org-bibtex has been renamed to ol-bibtex -- for the time
+;; being we support both feature names.
+(or (require 'ol-bibtex nil t)
+    (require 'org-bibtex))
+
+(require 'citeproc-s)
+
+;; Declare used ol-bibtex variables and functions to silence 'reference to free
+;; variable' and 'function is not known to be defined' warnings during
+;; compilation.
+(defvar org-bibtex-key-property)
+(defvar org-bibtex-type-property-name)
+(defvar org-bibtex-export-arbitrary-fields)
+(defvar org-bibtex-prefix)
+(defvar org-bibtex-types)
+(declare-function org-bibtex-get "ext:ol-bibtex")
+
+(defconst citeproc-bt--to-csl-types-alist
+  '(("article" . "article-journal") ("book" . "book") ("proceedings" . "book")
+    ("manual" . "book") ("periodical" . "book") ("booklet" . "pamphlet")
+    ("inbook" . "chapter") ("incollection" . "chapter") ("inproceedings" . "paper-conference")
+    ("conference" . "paper-conference") ("mastersthesis" . "thesis") ("phdthesis" . "thesis")
+    ("techreport" . "report") ("patent" . "patent") ("electronic" . "webpage")
+    ("misc" . "article") ("other" . "article") ("standard" . "legislation")
+    ("unpublished" . "manuscript") ("online" . "article-journal"))
+  "Alist mapping BibTeX item types to CSL item types.")
+
+(defconst citeproc-bt--to-csl-keys-alist
+  '(("=key=" . citation-label) ("address" . publisher-place)
+    ("booktitle" . container-title) ("journal" . container-title)
+    ("chapter" . title) ("location" . event-place) ("series" . collection-title)
+    ("keywords" . keyword) ("institution" . publisher) ("school" . publisher)
+    ("pages" . page) ("organization" . publisher) ("url" . URL)
+    ("doi" . DOI) ("pmid" . PMID) ("pmcid" . PMCID))
+  "Alist mapping BibTeX keys to CSL keys with different names.")
+
+(defconst citeproc-bt--mon-to-num-alist
+  '(("jan" . 1) ("feb" . 2) ("mar" . 3) ("apr" . 4) ("may" . 5) ("jun" . 6)
+    ("jul" . 7) ("aug" . 8) ("sep" . 9) ("oct" . 10) ("nov" . 11) ("dec" . 12))
+  "Alist mapping LaTeX abbreviated month names to ordinals.")
+
+(defconst citeproc-bt--pref-to-ucs-alist
+  '(("'" . "ACUTE") ("`" . "GRAVE") ("^" . "CIRCUMFLEX") ("~" . "TILDE")
+    ("=" . "MACRON") ("." . "WITH DOT ABOVE") ("\"" . "DIAERESIS")
+    ("''" . "DIAERESIS") ("H" . "DOUBLE ACUTE") ("r" . "WITH RING ABOVE")
+    ("u" . "BREVE") ("c" . "CEDILLA") ("k" . "OGONEK") ("v" . "CARON"))
+  "Alist mapping LaTeX prefixes to unicode name endings.")
+
+(defconst citeproc-bt--comm-letter-to-ucs-alist
+  '((("`" . "A") . "À")
+    (("'" . "A") . "Á")
+    (("^" . "A") . "Â")
+    (("~" . "A") . "Ã")
+    (("\"" . "A") . "Ä")
+    (("r" . "A") . "Å")
+    (("c" . "C") . "Ç")
+    (("v" . "C") . "Č")
+    (("'" . "C") . "Ć")
+    (("`" . "E") . "È")
+    (("'" . "E") . "É")
+    (("^" . "E") . "Ê")
+    (("\"" . "E") . "Ë")
+    (("`" . "I") . "Ì")
+    (("'" . "I") . "Í")
+    (("^" . "I") . "Î")
+    (("\"" . "I") . "Ï")
+    (("~" . "N") . "Ñ")
+    (("`" . "O") . "Ò")
+    (("'" . "O") . "Ó")
+    (("^" . "O") . "Ô")
+    (("~" . "O") . "Õ")
+    (("\"" . "O") . "Ö")
+    (("c" . "S") . "Ş")
+    (("v" . "S") . "Š")
+    (("`" . "U") . "Ù")
+    (("'" . "U") . "Ú")
+    (("^" . "U") . "Û")
+    (("\"" . "U") . "Ü")
+    (("'" . "Y") . "Ý")
+    (("`" . "a") . "à")
+    (("'" . "a") . "á")
+    (("^" . "a") . "â")
+    (("~" . "a") . "ã")
+    (("\"" . "a") . "ä")
+    (("r" . "a") . "å")
+    (("c" . "c") . "ç")
+    (("v" . "c") . "č")
+    (("'" . "c") . "ć")
+    (("`" . "e") . "è")
+    (("'" . "e") . "é")
+    (("^" . "e") . "ê")
+    (("\"" . "e") . "ë")
+    (("`" . "i") . "ì")
+    (("'" . "i") . "í")
+    (("^" . "i") . "î")
+    (("\"" . "i") . "ï")
+    (("~" . "n") . "ñ")
+    (("`" . "o") . "ò")
+    (("'" . "o") . "ó")
+    (("^" . "o") . "ô")
+    (("~" . "o") . "õ")
+    (("\"" . "o") . "ö")
+    (("v" . "r") . "ř")
+    (("c" . "s") . "ş")
+    (("v" . "s") . "š")
+    (("`" . "u") . "ù")
+    (("'" . "u") . "ú")
+    (("^" . "u") . "û")
+    (("\"" . "u") . "ü")
+    (("'" . "y") . "ý")
+    (("\"" . "y") . "ÿ")
+    (("H" . "o") . "ő")
+    (("H" . "O") . "Ő")
+    (("H" . "u") . "ű")
+    (("H" . "U") . "Ű")
+    (("v" . "z") . "ž")
+    (("v" . "Z") . "Ž"))
+  "Alist mapping LaTeX (SYMBOL-COMMAND . ASCII-CHAR) pairs to unicode characters.")
+
+(defconst citeproc-bt--to-ucs-alist
+  '(("l" . "ł") ("L" . "Ł") ("o" . "ø") ("O" . "Ø") ("AA" . "Å") ("aa" . "å")
+    ("AE" . "Æ") ("ae" . "æ") ("ss" . "ß") ("i" . "ı"))
+  "Alist mapping LaTeX commands to characters.")
+
+(defun citeproc-bt--to-ucs (ltx char)
+  "Return the unicode version of LaTeX command LTX applied to CHAR.
+LTX is a one-char LaTeX accenting command (e.g. \"'\"), CHAR is
+an ascii character. Return nil if no corresponding unicode
+character was found."
+  (or (assoc-default (cons ltx char) citeproc-bt--comm-letter-to-ucs-alist)
+      ;; If the combination is not in citeproc-bt--comm-letter-to-ucs-alist
+      ;; then, as a last resort, we try to assemble the canonical unicode name
+      ;; of the requested character and look it up in (usc-names). This process
+      ;; can be *very slow* on older Emacs versions in which (usc-names) returns
+      ;; an alist!
+
+      ;; NOTE: Because of a nasty interaction bug between `ucs-names' and
+      ;; `replace-regexp-in-string' we do the lookup only for Emacs versions
+      ;; earlier than 28.
+      (when-let* (((version< emacs-version "28" ))
+                 (case-name (if (s-lowercase-p char) "SMALL" "CAPITAL"))
+                 (combining-name (assoc-default ltx citeproc-bt--pref-to-ucs-alist))
+                 (name (concat "LATIN " case-name " LETTER "
+                               (upcase char) " " combining-name))
+                 (char-name (map-elt (ucs-names) name)))
+       (char-to-string char-name))))
+
+(defconst citeproc-bt--decode-rx
+  (rx (or
+       (seq "{\\" (group-n 1 (in "'" "`" "^" "~" "=" "." "\"")) (0+ space)
+           (group-n 2 letter) "}")
+       (seq "{\\" (group-n 1 (in "H" "r" "u" "c" "k" "v")) (1+ space)
+           (group-n 2 letter) "}")
+       (seq "{\\" (group-n 1 (or "l" "L" "o" "O" "AA" "aa" "ae" "AE" "ss" "i"))
+           (0+ space) "}")
+       (seq "\\" (group-n 1 (in "'" "`" "^" "~" "=" "." "\"" "H" "r" "u" "c" "k" "v"))
+           (0+ space) "{" (group-n 2 letter) "}")
+       (seq "\\" (group-n 1 (in "H" "r" "u" "c" "k" "v")) (1+ space)
+           (group-n 2 letter))
+       (seq "\\" (group-n 1 (in "'" "`" "^" "~" "=" "." "\"")) (0+ space)
+           (group-n 2 letter))
+       (seq "\\" (group-n 1 (or "l" "L" "o" "O" "AA" "aa" "ae" "AE" "ss" "i"))
+           word-boundary)))
+  "Regular expression matching BibTeX special character commands.")
+
+(defun citeproc-bt--decode (s)
+  "Decode a BibTeX encoded string."
+  (replace-regexp-in-string
+   citeproc-bt--decode-rx
+   (lambda (x)
+     (let ((command (match-string 1 x))
+          (letter (match-string 2 x)))
+       (if letter
+          (or (citeproc-bt--to-ucs command letter) (concat "\\" x))
+        (or (assoc-default command citeproc-bt--to-ucs-alist) x))))
+   s t t))
+
+(defun citeproc-bt--decode-buffer ()
+  "Decode BibTeX encoded characters in the current buffer."
+  (goto-char (point-min))
+  (while (re-search-forward citeproc-bt--decode-rx nil t)
+    (replace-match
+     (let ((replacement (let ((command (match-string 1))
+                             (letter (match-string 2)))
+                         (if letter
+                             (or (citeproc-bt--to-ucs command letter) (concat "\\" (match-string 0)))
+                           (assoc-default command citeproc-bt--to-ucs-alist)))))
+       replacement))))
+
+(defconst citeproc-bt--command-rx
+  (rx "\\" (1+ (any "a-z" "A-Z")) "{"  ; \TEX-COMMAND{
+      (group (*? anything))            ; ARGUMENT
+      "}"                              ; }
+      ))
+
+(defconst citeproc-bt--command-wo-arg-rx
+  (rx "\\" (1+ (any "a-z" "A-Z")) word-end)) ; \TEX-COMMAND + word-end
+
+(defconst citeproc-bt--braces-rx
+  (rx "{" (group (*? anything)) "}"))  ; {TEXT}
+
+(defun citeproc-bt--process-brackets (s &optional lhb rhb)
+  "Process LaTeX curly brackets in string S.
+Optional LHB and RHB specify what to substitute for left and
+right braces when they are not enclosing command arguments.
+The default is to remove them."
+  (let* ((result s)
+        (match t))
+    (while match
+      (cond ((string-match citeproc-bt--command-rx result)
+            (setq result (replace-match "\\1" t nil result)
+                  match t))
+           ((string-match citeproc-bt--command-wo-arg-rx result)
+            (setq result (replace-match "" t nil result)
+                  match t))
+           ((string-match citeproc-bt--braces-rx result)
+            (setq result (replace-match
+                          (concat lhb "\\1" rhb)
+                          t nil result)
+                  match t))
+           (t (setq match nil))))
+    result))
+
+(defun citeproc-bt--preprocess-for-decode (s)
+  "Preprocess field S before decoding.
+Remove flanking dumb quotes from string S and make some
+replacements."
+  (let ((wo-quotes (if (and (string= (substring s 0 1) "\"")
+                           (string= (substring s -1) "\""))
+                      (substring s 1 -1) s)))
+    (citeproc-s-replace "\\&" "&" wo-quotes)))
+
+(defun citeproc-bt--to-csl (s &optional with-nocase)
+  "Convert a BibTeX field S to a CSL one.
+If optional WITH-NOCASE is non-nil then convert BibTeX no-case
+brackets to the corresponding CSL XML spans."
+  (if (> (length s) 0)
+      (--> s
+          (citeproc-bt--preprocess-for-decode it)
+          (citeproc-bt--decode it)
+          (citeproc-bt--process-brackets
+           it
+           (when with-nocase "<span class=\"nocase\">")
+           (when with-nocase "</span>"))
+          (citeproc-s-replace-all-seq it '(("\n" . " ") ("~" . " ") ("--" . "–")))
+          (s-trim it))
+    s))
+
+(defun citeproc-bt--to-csl-names (n)
+  "Return a CSL version of BibTeX names field N."
+  (let ((name-fields (s-split "\\band\\b" n)))
+    (mapcar
+     (lambda (x)
+       (let ((trimmed (s-trim x)))
+        (cond
+         ((string= trimmed "") '((family . "")))
+         ;; Presence of equal sign signals extended specification.
+         ((string-match "=" trimmed) (citeproc-bt--ext-desc-to-csl-name trimmed))
+         ;; Brackets indicate corporate entities without name parts.
+         ((and (string= "{" (substring trimmed 0 1))
+               (string= "}" (substring trimmed -1)))
+          `((literal . ,(citeproc-bt--to-csl (substring trimmed 1 -1)))))
+         ;; Else standard bib(la)tex name field processing.
+         (t (citeproc-bt--to-csl-name (citeproc-bt--to-csl trimmed))))))
+     name-fields)))
+
+(defvar citeproc-bt-dropping-particles
+  '("dela" "il" "sen" "z" "ze")
+  "List containing dropping particles. Particles whose first word
+is not on this list are classified as non-dropping.")
+
+(defun citeproc-bt--parse-family (f)
+  "Parse family name tokens F into a csl name-part alist."
+  (let (family result particle)
+    (-if-let (firsts (butlast f))
+       (progn
+         (while (and firsts (s-lowercase-p (car firsts)))
+           (push (pop firsts) particle))
+         (when particle
+           (push (cons (if (member (car particle) citeproc-bt-dropping-particles)
+                           'dropping-particle
+                         'non-dropping-particle)
+                       (nreverse particle))
+                 result))
+         (setq family (-concat firsts (last f))))
+      (setq family f))
+    (push `(family . ,family) result)
+    result))
+
+(defun citeproc-bt--parse-attr-val-field (f)
+  "Parse biblatex key-val field F into an alist."
+  (let* ((bracketless (replace-regexp-in-string "[{}]" "" f))
+        (equal-split (split-string bracketless "=" t " "))
+        (first-attr (intern (string-trim (pop equal-split) "[ \"]+" "[ \"]+")))
+        (reversed (nreverse equal-split))
+        (result (list (string-trim (pop reversed) "[ \"]+" "[ \"]+"))))
+    (dolist (elt reversed)
+      (let ((pos (- (length elt) 2))
+           found)
+       (while (and (< 0 pos) (null found))
+         (if (= (aref elt pos) ?,)
+             (setq found t)
+           (cl-decf pos)))
+       (unless found (error "Could not parse biblatex key-value list \"%s\"" f))
+       (let ((key (intern (s-trim (substring elt (1+ pos)))))
+             (val (string-trim (substring elt 0 pos) "[ \"]+" "[ \"]+")))
+         (push key (car result))
+         (push val result))))
+    (push first-attr (car result))
+    result))
+
+(defun citeproc-bt--ext-desc-to-csl-name (name)
+  "Return a CSL version of extended biblatex description NAME."
+  (let* ((parsed (citeproc-bt--parse-attr-val-field name))
+        (dropping (string= (alist-get 'useprefix parsed) "false")))
+    (--keep (pcase (car it)
+             ((or 'family 'given 'suffix) it)
+             ('prefix (cons (if dropping 'dropping-particle 'non-dropping-particle)
+                            (cdr it)))
+             (_ nil))
+           parsed)))
+
+(defun citeproc-bt--to-csl-name (name)
+  "Return a CSL version of BibTeX name string NAME."
+  (let* (result
+        family
+        (tokens (-remove #'s-blank-str-p
+                         (citeproc-s-slice-by-matches name "\\(,\\|[[:space:]]+\\)")))
+        (parts (-split-on "," tokens)))
+    (pcase (length parts)
+      ;; No commas in the name
+      (1 (let ((name (car parts)))
+          (-if-let (1st-downcased-idx (-find-index #'s-lowercase-p name))
+              (progn (setq family (-slice name 1st-downcased-idx))
+                     (when (> 1st-downcased-idx 0)
+                       (push `(given . ,(-slice name 0 1st-downcased-idx)) result)))
+            (setq family (last name))
+            (when (> (length name) 1)
+              (push `(given . ,(-slice name 0 -1)) result)))))
+      ;; A single comma separates family and last name
+      (2 (setq family (car parts))
+        (push `(given . ,(cadr parts)) result))
+      ;; More than one commas
+      (_ (setq family (car parts))
+        (push `(suffix . ,(cadr parts)) result)
+        (push `(given . ,(cl-caddr parts)) result)))
+    (setq result (nconc (citeproc-bt--parse-family family) result))
+    (--map (cons (car it) (s-join " " (cdr it)))
+          result)))
+
+(defun citeproc-bt--to-csl-date (year month)
+  "Return a CSL version of the date given by YEAR and MONTH.
+YEAR and MONTH are the values of the corresponding BibTeX fields,
+MONTH might be nil."
+  (condition-case nil
+      (let ((csl-year (string-to-number (car (s-match "[[:digit:]]+" year))))
+           (csl-month (when month
+                        (assoc-default (downcase month)
+                                       citeproc-bt--mon-to-num-alist)))
+           date)
+       (when csl-year
+         (when csl-month (push csl-month date))
+         (push csl-year date))
+       (list (cons 'date-parts (list date))))
+    (error
+     (error (concat "Couldn't parse year: '%s'"
+                   (when month " and month: '%s'")
+                   " as a date")
+           year month))))
+
+(defun citeproc-bt-entry-to-csl (b)
+  "Return a CSL form of normalized parsed BibTeX entry B."
+  (let ((type (assoc-default (downcase (assoc-default "=type=" b))
+                            citeproc-bt--to-csl-types-alist))
+       result year month)
+    (cl-loop for (key . value) in b do
+            (let ((key (downcase key))
+                  (value (citeproc-bt--to-csl value)))
+              (-if-let (csl-key (assoc-default key citeproc-bt--to-csl-keys-alist))
+                  ;; Vars mapped simply to a differently named CSL var
+                  (push (cons csl-key value) result)
+                (pcase key
+                  ((or "author" "editor") ; Name vars
+                   (push (cons (intern key) (citeproc-bt--to-csl-names value))
+                         result))
+                  ("=type=" (push (cons 'type type) result))
+                  ("number" (push (cons (if (string= type "article-journal") 'issue
+                                          'number)
+                                        value)
+                                  result))
+                  ;; Date vars that need further processing below
+                  ("year" (setq year value))
+                  ("month" (setq month value))
+                  ;; Remaining keys are mapped without change
+                  (_ (push (cons (intern key) value) result))))))
+    (when year
+      (push (cons 'issued (citeproc-bt--to-csl-date year month))
+           result))
+    result))
+
+;; This function is based on the function `org-bibtex-headline' in org-bibtex,
+;; written by Bastien Guerry <bzgNOSPAMgnu.org>, Carsten Dominik <carsten dot dominik
+;; at gmail dot com> and Eric Schulte <schulte dot eric at gmail dot com>.
+;; Copyright (C) 2007-2017 Free Software Foundation, Inc.
+(defun citeproc-bt-from-org-headline (&optional itemids)
+  "Return a (KEY . BIBTEX-ENTRY) pair from the headline at point.
+The returned BibTeX entry has the same form as produced by
+`bibtex-parse-entry'. Return nil if the headline has no
+associated bibtex data. If optional ITEMIDS is given then also
+return nil if the entry's key is not in ITEMIDS."
+  (letrec ((val (lambda (key lst) (cdr (assoc key lst))))
+          (to (lambda (string) (intern (concat ":" string))))
+          (from (lambda (key) (substring (symbol-name key) 1)))
+          (flatten (lambda (&rest lsts)
+                     (apply #'append (mapcar
+                                      (lambda (e)
+                                        (if (listp e) (apply flatten e) (list e)))
+                                      lsts))))
+          (id (org-bibtex-get org-bibtex-key-property))
+          (type (org-bibtex-get org-bibtex-type-property-name)))
+    (when (and type (or (null itemids) (member id itemids)))
+      `(,id . 
+           (("=type=" . ,type)
+            ,@(remove
+               nil
+               (if (and org-bibtex-export-arbitrary-fields
+                        org-bibtex-prefix)
+                   (mapcar
+                    (lambda (kv)
+                      (let ((key (car kv)) (val0 (cdr kv)))
+                        (when (and
+                               (string-match org-bibtex-prefix key)
+                               (not (string=
+                                     (downcase (concat org-bibtex-prefix
+                                                       org-bibtex-type-property-name))
+                                     (downcase key))))
+                          (cons (downcase (replace-regexp-in-string
+                                           org-bibtex-prefix "" key))
+                                val0))))
+                    (org-entry-properties nil 'standard))
+                 (mapcar
+                  (lambda (field)
+                    (let ((value (or (org-bibtex-get (funcall from field))
+                                     (and (eq :title field)
+                                          (nth 4 (org-heading-components))))))
+                      (when value (cons (funcall from field) value))))
+                  (funcall flatten
+                           (funcall val :required (funcall val (funcall to type) org-bibtex-types))
+                           (funcall val :optional (funcall val (funcall to type) org-bibtex-types)))))))))))
+
+(provide 'citeproc-bibtex)
+
+;;; citeproc-bibtex.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-choose.el b/elpa/citeproc-20230228.1414/citeproc-choose.el
new file mode 100644 (file)
index 0000000..ee390d5
--- /dev/null
@@ -0,0 +1,118 @@
+;; citeproc-choose.el --- conditionally rendered CSL elements -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; CSL supports conditional rendering via the cs:choose rendering element, which
+;; can contain cs:if, cs:else-if and cs:else elements as children. This file
+;; contains functions corresponding to all these elements with some auxiliary
+;; functions.
+
+;; In order to support conditional rendering by cs:choose, the functions
+;; corresponding to cs:if, cs:else-if and cs:else (`citeproc--if',
+;; `citeproc--else-if', `citeproc--else') return the generalized boolean value
+;; of their condition in addition to their rendered content in the form of a
+;; (BOOLEAN . CONTENT) pair.
+
+;;; Code:
+
+(require 's)
+
+(require 'citeproc-lib)
+(require 'citeproc-context)
+(require 'citeproc-date)
+
+(defun citeproc-choose-eval-conditions (attrs context)
+  "Eval (possibly complex) boolean conditions in ATTRS."
+  (-let* ((conditions (citeproc-choose--elementary-conditions
+                      (--remove (eq (car it) 'match) attrs)))
+         (match (or (alist-get 'match attrs) "all"))
+         (values (--map (citeproc-choose--eval-elementary-condition (car it)
+                                                                    (intern (cdr it))
+                                                                    context)
+                        conditions)))
+    (pcase match
+      ("all" (--all? it values))
+      ("any" (--any? it values))
+      ("none" (--none? it values)))))
+
+(defun citeproc-choose--elementary-conditions (attrs)
+  "Expand complex conditions in ATTRS into elementary ones.
+Return a list of elementary (CONDITION-TYPE . PARAM) pairs."
+  (cl-mapcan (lambda (x)
+              (--map (cons (car x) it)
+                     (s-split " " (cdr x))))
+            attrs))
+
+(defun citeproc-choose--eval-elementary-condition (type param context)
+  "Evaluate an elementary choose condition of TYPE with PARAM.
+TYPE is one of the symbols `variable', `type', `locator',
+`is-numeric', `is-uncertain-date', `position' and `disambiguate'.
+Return the result of evaluation, which is a generalized boolean."
+  (pcase type
+    ('variable (citeproc-var-value param context))
+    ('type (string= param (citeproc-var-value 'type context)))
+    ('locator (string= param (citeproc-var-value 'label context)))
+    ('is-numeric (let ((val (citeproc-var-value param context)))
+                  (citeproc-lib-numeric-p val)))
+    ;; We return t iff the first date is uncertain. A more complicated alternative
+    ;; would be to test the second date of date ranges as well.
+    ('is-uncertain-date (-when-let (dates (citeproc-var-value param context))
+                         (citeproc-date-circa (car dates))))
+    ('position (and (eq (citeproc-context-mode context) 'cite)
+                   (or (and (eq param 'near-note) (citeproc-var-value 'near-note context))
+                       (let ((pos (citeproc-var-value 'position context)))
+                         (or (eq param pos)
+                             (and (eq param 'subsequent)
+                                  (or (eq pos 'ibid) (eq pos 'ibid-with-locator)))
+                             (and (eq param 'ibid)
+                                  (eq pos 'ibid-with-locator)))))))
+    ('disambiguate (citeproc-var-value 'disambiguate context))))
+
+(defmacro citeproc--choose (_attrs _context &rest body)
+  "Return the content of the first element in BODY with t boolean value.
+Return the empty (nil . `text-only') content if there is no such
+element."
+  `(let ((first-true
+         (--first (car it) (list ,@body))))
+     (if first-true
+        (cdr first-true)
+       (cons nil (quote text-only)))))
+
+(defmacro citeproc--if (attrs context &rest body)
+  "If conditions in ATTRS eval to t return t with rendered BODY.
+Return nil otherwise."
+  `(if (citeproc-choose-eval-conditions ,attrs ,context)
+       (cons t (citeproc-lib-add-splice-tag
+               (citeproc-lib-splice-into (list ,@body) 'splice)
+               'splice))
+     nil))
+
+(defalias 'citeproc--else-if 'citeproc--if)
+
+(defun citeproc--else (_attrs _context &rest body)
+  "Always return t boolean plus rendered BODY"
+  (let ((spliced-body (citeproc-lib-splice-into body 'splice)))
+    (cons t (citeproc-lib-add-splice-tag spliced-body 'splice))))
+
+(provide 'citeproc-choose)
+
+;;; citeproc-choose.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-cite.el b/elpa/citeproc-20230228.1414/citeproc-cite.el
new file mode 100644 (file)
index 0000000..729ad13
--- /dev/null
@@ -0,0 +1,578 @@
+;;; citeproc-cite.el --- cite and citation rendering -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functionality to render citations and the cites they contain. (Terminology
+;; from the CSL standard: "citations consist of one or more cites to individual
+;; items".)
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'dash)
+(require 'queue)
+(require 's)
+
+(require 'citeproc-rt)
+(require 'citeproc-number)
+(require 'citeproc-itemdata)
+(require 'citeproc-style)
+(require 'citeproc-proc)
+(require 'citeproc-formatters)
+(require 'citeproc-sort)
+(require 'citeproc-subbibs)
+
+(cl-defstruct (citeproc-citation (:constructor citeproc-citation-create))
+  "A struct representing a citation.
+CITES is a list of alists describing individual cites,
+NOTE-INDEX is the note index of the citation if it occurs in a
+  note,
+MODE is either nil (for the default citation mode) or one
+  of the symbols `suppress-author', `textual', `author-only',
+  `year-only', `title-only', `bib-entry', `locator-only',
+SUPPRESS-AFFIXES is non-nil if the citation affixes should be
+  suppressed,
+CAPITALIZE-FIRST is non-nil if the first word of the rendered
+  citation should be capitalized,
+IGNORE-ET-AL is non-nil if et-al settings should be ignored for
+  the first cite.
+GROUPED is used internally to indicate whether the cites were
+  grouped by the csl processor."
+  cites note-index mode suppress-affixes capitalize-first
+  ignore-et-al grouped)
+
+(defconst citeproc-cite--from-mode-alist
+  '((textual . ((suppress-author . t)))
+    (suppress-author . ((suppress-author . t)))
+    (author-only . ((stop-rendering-at . names)))
+    (year-only . ((stop-rendering-at . issued)))
+    (title-only . ((stop-rendering-at . title) (bib-entry . t) (use-short-title . t)))
+    (bib-entry . ((bib-entry . t)))
+    (locator-only . ((locator-only . t))))
+  "Alist mapping citation modes to corresponding cite-level
+key-value pair representations.")
+
+(defvar citeproc-citation-postprocess-functions nil
+  "A list of functions to postprocess rendered citations.
+Each function takes a single argument, a rich-text, and returns a
+post-processed rich-text value. The functions are applied in the
+order they appear in the list.")
+
+(defun citeproc-cite--varlist (cite)
+  "Return the varlist belonging to CITE."
+  (let* ((itd (alist-get 'itd cite))
+        (item-vv (citeproc-itemdata-varvals itd))
+        ;; OPTIMIZE: Should we do this filtering?
+        (cite-vv
+         (--filter (memq (car it)
+                         '(label locator suppress-author suppress-date
+                                 stop-rendering-at position near-note
+                                 first-reference-note-number ignore-et-al
+                                 bib-entry locator-only use-short-title))
+                   cite)))
+    (nconc cite-vv item-vv)))
+
+(defun citeproc-cite--render (cite style &optional internal-links)
+  "Render CITE in STYLE, together with its affixes.
+If the prefix or suffix in CITE don't contain trailing and
+leading spaces then they are added. If the optional
+INTERNAL-LINKS is `bib-links' then link cites to the bibliography
+regardless of the style type, if `no-links' then don't add
+internal links, if nil or `auto' then add internal links based on
+the style type (cite-cite links for note styles and cite-bib
+links else). For legacy reasons, any other value is treated as
+`no-links'."
+  (-let* ((result nil)
+         ((&alist 'suffix suff
+                  'prefix pref
+                  'bib-entry bib-entry
+                  'locator-only locator-only
+                  'stop-rendering-at stop-rendering-at)
+          cite)
+         (rt-pref (citeproc-rt-from-str pref))
+         (plain-pref (citeproc-rt-to-plain rt-pref))
+         (rt-suff (citeproc-rt-from-str suff))
+         (plain-suff (citeproc-rt-to-plain rt-suff))
+         (mode (if bib-entry 'bib 'cite))
+         (varlist (citeproc-cite--varlist cite)))
+    ;; Remove cite-number when cite is the full bibliography entry.
+    (when (and (eq mode 'bib) (not stop-rendering-at))
+      (push '(citation-number) varlist))
+    (let ((rendered-varlist
+          (citeproc-render-varlist-in-rt
+           varlist style mode 'display
+           ;; No link-targets for bib-entry based citations.
+           (if (eq mode 'bib) 'no-links internal-links)
+           ;; No external limking for title-only citations, since we link to the
+           ;; corresponding bibliography entry.
+           (eq stop-rendering-at 'title))))
+      ;; Locator-only cites require extensive post-processing of full cite.
+      (when locator-only
+       (setq rendered-varlist (citeproc-rt-locator-w-label rendered-varlist)))
+      ;; Title-only cites
+      (when (eq stop-rendering-at 'title)
+       (when-let* ((cite-no-attr
+                    (citeproc-context-int-link-attrval
+                     style internal-links 'cite (alist-get 'position varlist)))
+                   (cite-no-attr-val (cons cite-no-attr
+                                           (alist-get 'citation-number varlist))))
+         ;; Add cited-item-no attr to link to the bibliography entry
+         (setf (car rendered-varlist)
+               (-snoc (car rendered-varlist) cite-no-attr-val))))
+      ;; Add cite prefix and suffix
+      (when (s-present-p plain-suff)
+       (push (citeproc-rt-from-str suff) result)
+       (unless (memql (aref plain-suff 0) '(?, ?\s))
+         (push " " result)))
+      (push rendered-varlist result)
+      (when (s-present-p plain-pref)
+       (unless (= (aref plain-pref (1- (length plain-pref))) ?\s)
+         (push " " result))
+       (push rt-pref result))
+      (citeproc-rt-join-formatted nil result nil))))
+
+(defun citeproc-cite-or-citegroup--render (c style internal-links top-dl gr-dl ys-dl ac-dl)
+  "Render cite or cite-group C with STYLE.
+For the INTERNAL-LINKS argument see `citeproc-cite--render'.
+TOP-DL is the top-, GR-DL the group-, YS-DL the year-suffix- and
+AC-DL the after-collapse-delimiter to use."
+  (cond ((and (car c) (memq (car c) '(top group year-suffix-collapsed)))
+        (let ((delimiter (pcase (car c)
+                           ('top top-dl)
+                           ('group gr-dl)
+                           ('year-suffix-collapsed ys-dl))))
+          (cons
+           nil                         ; empty attribute list
+           (nbutlast                   ; remove last delimiter
+            (--mapcat (list (citeproc-cite-or-citegroup--render
+                             it style internal-links top-dl gr-dl ys-dl ac-dl)
+                            (if (and (car it) (memq (car it) '(group year-suffix-collapsed)))
+                                ac-dl
+                              delimiter))
+                      (cdr c))))))
+       ((eq (car c) 'range)
+        (list nil (citeproc-cite--render (cl-second c) style internal-links)
+              "–" (citeproc-cite--render (cl-third c) style internal-links)))
+       (t (citeproc-cite--render c style internal-links))))
+
+(defun citeproc-citation--render (c proc &optional internal-links)
+  "Render citation C with CSL processor PROC.
+For the optional INTERNAL-LINKS argument see
+`citeproc-cite--render'."
+  (let* ((style (citeproc-proc-style proc))
+        (punct-in-quote
+         (string= (alist-get 'punctuation-in-quote (citeproc-style-locale-opts style))
+                  "true"))
+        (cites (citeproc-citation-cites c))
+        (cite-attrs (citeproc-style-cite-layout-attrs style))
+        (cite-layout-dl (alist-get 'delimiter cite-attrs)))
+    ;; Remove delimiters from cite-attrs -- they are rendered 'manually' because of
+    ;; the delimiter-after-collapse complications in rendering. Also remove affixes
+    ;; if requested.
+    (setq cite-attrs
+         (if (citeproc-citation-suppress-affixes c)
+             (--remove (memq (car it) '(delimiter prefix suffix)) cite-attrs)
+           (--remove (eq (car it) 'delimiter) cite-attrs)))
+    ;; Generate rendered cites
+    (let ((rendered-cites
+          (cond
+           ((citeproc-citation-grouped c)
+            (let ((gr-dl
+                   (alist-get 'cite-group-delimiter (citeproc-style-cite-opts style)))
+                  (ys-dl
+                   (alist-get 'year-suffix-delimiter (citeproc-style-cite-opts style)))
+                  (aft-coll-dl
+                   (alist-get
+                    'after-collapse-delimiter (citeproc-style-cite-opts style))))
+              (cdr (citeproc-cite-or-citegroup--render
+                    (cons 'top cites)  ; indicate top level input
+                    style internal-links cite-layout-dl gr-dl ys-dl aft-coll-dl))))
+           ((cdr cites)
+            (cdr (--mapcat
+                  (list cite-layout-dl (citeproc-cite--render it style internal-links))
+                  cites)))
+           (t
+            (list (citeproc-cite--render (car cites) style internal-links))))))
+      ;; Calculate inner and outer citation attrs (affixes go inside)
+      (let* ((non-affixes (--remove (memq (car it) '(prefix suffix delimiter)) cite-attrs))
+            (affixes (--filter (memq (car it) '(prefix suffix)) cite-attrs))
+            (outer-attrs (and affixes non-affixes))
+            (result
+             (citeproc-rt-cull-spaces-puncts
+              (citeproc-rt-finalize
+               (citeproc-rt-render-affixes
+                (citeproc-rt-join-formatted (if outer-attrs affixes cite-attrs)
+                                            rendered-cites nil)
+                t)
+               punct-in-quote))))
+       ;; Add outer (non-affix attrs) if needed
+       (when outer-attrs
+         (setq result (list outer-attrs result)))
+       ;; Prepend author to textual citations
+       (when (eq (citeproc-citation-mode c) 'textual)
+         (let* ((first-elt (car cites)) ;; First elt is either a cite or a cite group.
+                ;; If the latter then we need to locate the
+                ;; first cite as the 2nd element of the first
+                ;; cite group.
+                (first-cite (if (eq 'group (car first-elt))
+                                (cadr first-elt)
+                              first-elt))
+                (author-cite
+                 (append '((suppress-author . nil) (stop-rendering-at . names)
+                           (prefix) (suffix) (locator))
+                  first-cite))
+                (rendered-author (citeproc-cite--render author-cite style 'no-links)))
+           (when (listp rendered-author)
+             (setq result `(nil ,rendered-author " " ,result)))))
+       ;; Capitalize first
+       (when (citeproc-citation-capitalize-first c)
+         (setq result (citeproc-rt-change-case result #'citeproc-s-capitalize-first)))
+       ;; Run the citation postprocessing hook
+       (dolist (fn citeproc-citation-postprocess-functions)
+         (setq result (funcall fn result)))
+       result))))
+
+(defun citeproc-cites--collapse-indexed (cites index-getter no-span-pred)
+  "Collapse continuously indexed cites in CITES.
+INDEX-GETTER is a function from cites to numeric indices,
+NO-SPAN-PRED is a predicate that returns non-nil for cites that
+cannot be part of a span. Return the collapsed cites list or nil
+if no cites were collapsed."
+  (let (group-len start-cite prev-index end-cite result)
+    (dolist (cite cites)
+      (let* ((cur-index (funcall index-getter cite))
+            (no-span-elt (funcall no-span-pred cite))
+            (subsequent (and prev-index (= (1+ prev-index) cur-index))))
+       ;; Process ending current group
+       (when (and group-len (or no-span-elt (not subsequent)))
+         (setq result (nconc (citeproc-cite-range--collapse
+                              start-cite end-cite
+                              group-len)
+                             result)))
+       (cond (no-span-elt              ; Not only cite-no
+              (push cite result)
+              (setq group-len nil))
+             ((or (not group-len) (not subsequent)) ; New group starts
+              (setq group-len 1
+                    start-cite cite
+                    prev-index cur-index))
+             (t                        ; Group continues
+              (cl-incf group-len)
+              (setq end-cite cite
+                    prev-index cur-index)))))
+    ;; Process the last group
+    (when group-len
+      (setq result (nconc (citeproc-cite-range--collapse
+                          start-cite end-cite group-len)
+                         result)))
+    (if (/= (length cites) (length result))
+       (nreverse result)
+      nil)))
+
+(defun citeproc-cite-range--collapse (start-cite end-cite len)
+  "Collapse cite span with START-CITE, END-CITE of LEN length.
+START-CITE end END-CITE is the first and last rendered cites of
+the span."
+  (pcase len
+    (1 (list start-cite))
+    (2 (list end-cite start-cite))
+    (_ (list (list 'range start-cite end-cite)))))
+
+(defun citeproc-citation--collapse-num-citeranges (citation)
+  "Collapse numbered ranges in CITATION."
+  (let* ((cites (citeproc-citation-cites citation))
+        (cites-length (length cites)))
+    (when (> cites-length 2)
+      (-when-let (collapsed
+                 (citeproc-cites--collapse-indexed
+                  cites
+                  (lambda (x)
+                    (string-to-number
+                     (alist-get 'citation-number (citeproc-cite--varlist x))))
+                  (lambda (x) (alist-get 'locator (citeproc-cite--varlist x)))))
+       (setf (citeproc-citation-cites citation) collapsed
+             (citeproc-citation-grouped citation) t)))))
+
+(defun citeproc-cites--collapse-suff-citeranges (cites)
+  "Collapse continuously year-suffixed CITES."
+  (or (citeproc-cites--collapse-indexed
+       cites
+       (lambda (x)
+        (string-to-char (alist-get 'year-suffix (citeproc-cite--varlist x) " ")))
+       (lambda (_x) nil))
+      cites))
+
+(defun citeproc-citation--render-formatted-citation (c proc format &optional internal-links)
+  "Render citation C with csl processor PROC in FORMAT.
+For the optional INTERNAL-LINKS argument see
+`citeproc-cite--render'."
+  (let ((fmt (citeproc-formatter-for-format format)))
+    (funcall (citeproc-formatter-cite fmt)
+            (funcall (citeproc-formatter-rt fmt)
+                     (citeproc-citation--render c proc internal-links)))))
+
+(defun citeproc-citation--sort-cites (citation proc)
+  "Sort cites in CITATION for processor PROC."
+  (let ((cites (citeproc-citation-cites citation)))
+    (when (cdr cites)
+      (let* ((style (citeproc-proc-style proc))
+            (sort-orders (citeproc-style-cite-sort-orders style)))
+       (setf (citeproc-citation-cites citation)
+             (sort
+              (--map (cons (cons 'key  ; add keys to the cites as extra attr
+                                 (citeproc-sort--render-keys style (citeproc-cite--varlist it) 'cite))
+                           it)
+                     cites)
+              (lambda (x y) (citeproc-sort--compare-keylists (cdar x) (cdar y) sort-orders))))))))
+
+(defun citeproc-proc-sort-cites (proc)
+  "Sort cites in all citations of PROC."
+  (when (citeproc-style-cite-sort (citeproc-proc-style proc))
+    (dolist (citation (queue-head (citeproc-proc-citations proc)))
+      (citeproc-citation--sort-cites citation proc))))
+
+(defun citeproc-proc-apply-citation-modes (proc)
+  "Apply mode to the first cite in each citation in PROC."
+  (dolist (citation (queue-head (citeproc-proc-citations proc)))
+    (let ((mode (citeproc-citation-mode citation))
+         (cites (citeproc-citation-cites citation))
+         (ignore-et-al (citeproc-citation-ignore-et-al citation)))
+      (-when-let (mode-rep
+                 (alist-get mode citeproc-cite--from-mode-alist))
+       (setf (car cites) (nconc (car cites) mode-rep)))
+      (when ignore-et-al
+       (push '(ignore-et-al . t) (car cites))))))
+
+(defun citeproc-proc-group-and-collapse-cites (proc)
+  "Group and collapse cites in all citations of PROC."
+  (let* ((cite-opts (citeproc-style-cite-opts (citeproc-proc-style proc)))
+        (group-delim (alist-get 'cite-group-delimiter cite-opts))
+        (collapse-type (alist-get 'collapse cite-opts))
+        (collapse-year-type
+         (when collapse-type
+           (let ((cy (member collapse-type
+                             '("year" "year-suffix" "year-suffix-ranged"))))
+             (and cy (car cy))))))
+    ;; Collapse (and group) according to collapse type
+    (cond ((or group-delim collapse-year-type)
+          ;; Group and possibly collapse
+          (dolist (citation (queue-head (citeproc-proc-citations proc)))
+            (citeproc-citation--group-and-collapse-cites citation proc collapse-type)))
+         ;; Collapse numeric cites
+         ((string= collapse-type "citation-number")
+          (dolist (citation (queue-head (citeproc-proc-citations proc)))
+            (citeproc-citation--collapse-num-citeranges citation))))))
+
+(defun citeproc-citation--group-and-collapse-cites (c proc &optional collapse-type)
+  "Divide items in citation C in place into groups for PROC.
+Apart from movement necessary for grouping, the relative
+positions of cites in C is kept. If optional COLLAPSE-TYPE is
+given then collapse the groups accordingly."
+  (let ((cites (citeproc-citation-cites c)))
+    (when (cdr cites)
+      (let (groups)
+       (dolist (cite cites)
+         (let ((g-ind
+                ;; Cites are in the same group iff the cdrs of the rendered cite's first
+                ;; name-var are equal. The cdr is taken because we ignore attributes, in
+                ;; particular the cited-item-no attribute which is added when the cite consists
+                ;; entirely of the rendered name var
+                (--find-index (equal (cdr (citeproc-cite--first-namevar-cont cite proc))
+                                     (cdr (citeproc-cite--first-namevar-cont (car it) proc)))
+                              groups)))
+           (if g-ind
+               (push cite (nth g-ind groups))
+             (push (list cite) groups))))
+       (unless (= (length groups) (length cites))
+         (setf (citeproc-citation-cites c)
+               (nreverse
+                (--map (if (cdr it)
+                           (cons 'group
+                                 (pcase collapse-type
+                                   ("year"
+                                    (citeproc-citation-group--collapse-year (nreverse it)))
+                                   ("year-suffix"
+                                    (citeproc-citation-group--collapse-ys (nreverse it) proc nil))
+                                   ("year-suffix-ranged"
+                                    (citeproc-citation-group--collapse-ys (nreverse it) proc t))
+                                   (_ (nreverse it))))
+                         (car it))
+                       groups))
+               (citeproc-citation-grouped c) t))))))
+
+(defun citeproc-citation-group--collapse-year (cites)
+  "Collapse year in group CITES."
+  (cons (car cites)
+       (--map (cons '(suppress-author . t) it)
+              (cdr cites))))
+
+(defun citeproc-citation-group--collapse-ys (cites proc collapse-ranges)
+  "Collapse year and suffix in group CITES using PROC.
+If optional COLLAPSE-RANGES is non-nil then collapse year-suffix
+ranges."
+  (let ((first t) (groups (list (list (car cites))))
+       prev-datevar-cont prev-locator)
+    (dolist (cite cites)
+      (let* ((varlist (citeproc-cite--varlist cite))
+            (datevar-cont (cadr (citeproc-cite--first-datevar-cont cite proc)))
+            (locator (alist-get 'locator varlist)))
+       (cond (first
+              (setq first nil))
+             ((or prev-locator
+                  locator
+                  (not (alist-get 'year-suffix varlist))
+                  (not (equal datevar-cont prev-datevar-cont)))
+              (push (list (cons '(suppress-author . t)
+                                cite))
+                    groups))
+             (t
+              (push (cons '(suppress-date . t)
+                          (cons '(suppress-author . t)
+                                cite))
+                    (car groups))))
+       (setq prev-datevar-cont datevar-cont
+             prev-locator locator))
+      cites)
+    (nreverse
+     (--map (if (cdr it)
+               (cons 'year-suffix-collapsed
+                     (if (and collapse-ranges (> (length cites) 2))
+                         (citeproc-cites--collapse-suff-citeranges (nreverse it))
+                       (nreverse it)))
+             (car it))
+           groups))))
+
+(defun citeproc-citations--itd-referred-p (itd citations)
+  "Whether ITD is referred to in CITATIONS."
+  (let ((cites (--mapcat (citeproc-citation-cites it) citations)))
+    (--any-p (eq itd (alist-get 'itd it)) cites)))
+
+(defun citeproc-cite--update-nn-queue (q index nnd)
+  "Remove too distant citations from near-notes queue Q.
+INDEX is the actual note-index, NND is the near-note-distance."
+  (while (and (queue-head q)
+             (< nnd (- index
+                       (citeproc-citation-note-index (queue-first q)))))
+    (queue-dequeue q)))
+
+(defun citeproc-cite--loc-equal-p (s1 s2)
+  "Whether locator strings S1 and S2 refer to the same location."
+  (if (and (citeproc-lib-numeric-p s1) (citeproc-lib-numeric-p s2))
+      (equal (citeproc-number-extract s1) (citeproc-number-extract s2))
+    (string= (s-trim s1) (s-trim s2))))
+
+(defvar citeproc-disambiguation-cite-pos 'last
+  "Which cite position should be the basis of cite disambiguation.
+Possible values are `last', `first' and `subsequent'.")
+
+(defun citeproc-proc-update-positions (proc)
+  "Update all position-related fields in PROC."
+  (citeproc-proc-delete-occurrence-info proc)
+  (let* ((ctns (queue-head (citeproc-proc-citations proc)))
+        (cite-opts (citeproc-style-cite-opts (citeproc-proc-style proc)))
+        (nnd (string-to-number
+              (or (alist-get 'near-note-distance cite-opts)
+                  "5")))
+        (near-note-ctns (make-queue))
+        prev-itd prev-loc prev-label)
+    (unless (eq citeproc-disambiguation-cite-pos 'last)
+      (dolist (itd (hash-table-values
+                   (citeproc-proc-itemdata proc)))
+       (setf (citeproc-itemdata-disamb-pos itd) citeproc-disambiguation-cite-pos)))
+    (dolist (ctn ctns)
+      (let* ((note-ind (citeproc-citation-note-index ctn))
+            (cites (citeproc-citation-cites ctn))
+            (single-cite (not (cdr cites))))
+       (when note-ind (citeproc-cite--update-nn-queue near-note-ctns note-ind nnd))
+       (let (seen-itds)
+         (while cites
+           (let* ((cite (car cites))
+                  (itd (alist-get 'itd cite))
+                  (locator (alist-get 'locator cite))
+                  (label (alist-get 'label cite))
+                  (pos (if (citeproc-itemdata-occurred-before itd)
+                           (if (eq itd prev-itd)
+                               (if prev-loc
+                                   (if locator
+                                       (if (and (citeproc-cite--loc-equal-p prev-loc locator)
+                                                (string= prev-label label))
+                                           'ibid
+                                         'ibid-with-locator)
+                                     'subsequent)
+                                 (if locator 'ibid-with-locator 'ibid))
+                             'subsequent)
+                         'first)))
+             (when (and note-ind
+                        (or (citeproc-citations--itd-referred-p itd (queue-head near-note-ctns))
+                            (memq itd seen-itds)))
+               (setf (alist-get 'near-note (car cites)) t))
+             (setf (alist-get 'position (car cites)) pos
+                   prev-itd itd
+                   prev-loc locator
+                   prev-label label)
+             (when (eq citeproc-disambiguation-cite-pos 'last)
+               (citeproc-itd-update-disamb-pos itd pos))
+             (let ((prev-occurrence (citeproc-itemdata-occurred-before itd)))
+               (if prev-occurrence
+                   (unless (eq t prev-occurrence)
+                     (setf (alist-get 'first-reference-note-number (car cites))
+                           (number-to-string prev-occurrence)))
+                 (setf (citeproc-itemdata-occurred-before itd) (or note-ind t))))
+             (push itd seen-itds)
+             (pop cites))))
+       (unless single-cite
+         (setq prev-itd nil prev-loc nil prev-label nil))
+       (when note-ind (queue-append near-note-ctns ctn))))))
+
+(defun citeproc-proc-finalize (proc)
+  "Finalize processor PROC by sorting and disambiguating items."
+  (unless (citeproc-proc-finalized proc)
+    (citeproc-proc-process-uncited proc)
+    (citeproc-sb-add-subbib-info proc)
+    (citeproc-sb-prune-unrendered proc)
+    (citeproc-proc-update-sortkeys proc)
+    (citeproc-proc-sort-itds proc)
+    (citeproc-proc-update-positions proc)
+    (citeproc-proc-disamb proc)
+    (citeproc-proc-sort-cites proc)
+    (citeproc-proc-apply-citation-modes proc)
+    (citeproc-proc-group-and-collapse-cites proc)
+    (setf (citeproc-proc-finalized proc) t)))
+
+(defun citeproc-cite--first-namevar-cont (cite proc)
+  "Return the first raw name-var node of CITE rendered with PROC."
+  (citeproc-rt-find-first-node
+   (citeproc-itd-rt-cite (alist-get 'itd cite) (citeproc-proc-style proc))
+   (lambda (x)
+     (and (consp x) (memq (alist-get 'rendered-var (car x))
+                         citeproc--name-vars)))))
+
+(defun citeproc-cite--first-datevar-cont (cite proc)
+  "Return the first raw date-var node of CITE rendered with PROC."
+  (citeproc-rt-find-first-node
+   (citeproc-itd-rt-cite (alist-get 'itd cite) (citeproc-proc-style proc))
+   (lambda (x)
+     (and (consp x) (memq (alist-get 'rendered-var (car x))
+                         citeproc--date-vars)))))
+(provide 'citeproc-cite)
+
+;;; citeproc-cite.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-context.el b/elpa/citeproc-20230228.1414/citeproc-context.el
new file mode 100644 (file)
index 0000000..c32940e
--- /dev/null
@@ -0,0 +1,282 @@
+;;; citeproc-context.el --- rendering context for CSL elements -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Provides the `citeproc-context' CL-structure type to represent rendering
+;; contexts for CSL elements, and functions for accessing context-dependent
+;; information (variable and term values etc.). Also contains some functions
+;; that perform context-dependent formatting (e.g., quoting).
+
+;;; Code:
+
+(require 'let-alist)
+(require 'subr-x)
+
+(require 'citeproc-lib)
+(require 'citeproc-rt)
+(require 'citeproc-term)
+(require 'citeproc-prange)
+(require 'citeproc-style)
+
+(cl-defstruct (citeproc-context (:constructor citeproc-context--create))
+  "A struct representing the context for rendering CSL elements."
+  vars macros terms date-text date-numeric opts locale-opts
+  mode render-mode render-year-suffix no-external-links locale)
+
+(defun citeproc-context-create (var-alist style mode render-mode
+                                         &optional no-external-links)
+  "Create a citeproc-context struct from var-values VAR-ALIST and csl style STYLE.
+MODE is either `bib' or `cite', RENDER-MODE is `display' or `sort'."
+  (citeproc-context--create
+   :vars var-alist
+   :macros (citeproc-style-macros style)
+   :terms (citeproc-style-terms style)
+   :date-text (citeproc-style-date-text style)
+   :date-numeric (citeproc-style-date-numeric style)
+   :opts (citeproc-style-global-opts style mode)
+   :locale (citeproc-style-locale style)
+   :locale-opts (citeproc-style-locale-opts style)
+   :mode mode
+   :render-mode render-mode
+   :render-year-suffix (not (citeproc-style-uses-ys-var style))
+   :no-external-links no-external-links))
+
+(defconst citeproc--short-long-var-alist
+  '((title . title-short) (container-title . container-title-short))
+  "Alist mapping the long form of variables names to their short form.")
+
+(defun citeproc-var-value (var context &optional form)
+  "Return the value of csl variable VAR in CONTEXT.
+VAR is a symbol, CONTEXT is a `citeproc-context' struct, and the
+optional FORM can be nil, `short' or `long'."
+  (let ((var-vals (citeproc-context-vars context)))
+    (if (or (eq form 'short)
+           ;; Also use the short form of title when the cite contains the
+           ;; (use-short-title . t) pair. This is used for title-only citations.
+           (and (eq var 'title) (alist-get 'use-short-title var-vals)))
+       (-if-let* ((short-var (alist-get var citeproc--short-long-var-alist))
+                  (short-var-val (alist-get short-var var-vals)))
+           short-var-val
+         (alist-get var var-vals))
+      (let ((var-val (alist-get var var-vals)))
+       (if (and var-val (or (and (eq var 'locator)
+                                 (string= (citeproc-var-value 'label context) "page"))
+                            (eq var 'page)))
+           (let ((prange-format (citeproc-lib-intern (alist-get 'page-range-format
+                                                                (citeproc-context-opts context))))
+                 (sep (or (citeproc-term-text-from-terms "page-range-delimiter"
+                                                         (citeproc-context-terms context))
+                          "–")))
+             (citeproc-rt-from-str (citeproc-prange-render var-val prange-format sep)))
+         var-val)))))
+
+(defun citeproc-locator-label (context)
+  "Return the current locator label variable from CONTEXT."
+  (citeproc-var-value 'label context))
+
+(defun citeproc-rt-quote (rt context)
+  "Return the quoted version of rich-text RT using CONTEXT."
+  (let ((oq (citeproc-term-get-text "open-quote" context))
+       (cq (citeproc-term-get-text "close-quote" context))
+       (oiq (citeproc-term-get-text "open-inner-quote" context))
+       (ciq (citeproc-term-get-text "close-inner-quote" context)))
+    `(,oq ,@(citeproc-rt-replace-all-sim `((,oq . ,oiq) (,cq . ,ciq)
+                                          (,oiq . ,oq) (,ciq . ,cq))
+                                        (format "\\(%s\\|%s\\|%s\\|%s\\)" oq cq oiq ciq)
+                                        rt)
+         ,cq)))
+
+(defun citeproc-rt-textcased (rts case context)
+  "Return rich-text content RTS in text-case CASE using CONTEXT.
+CASE is one of the following: `lowercase', `uppercase',
+`capitalize-first', `capitalize-all', `sentence', `title'."
+  (pcase case
+    ('uppercase
+     (citeproc-rt-map-strings #'upcase rts t))
+    ('lowercase
+     (citeproc-rt-map-strings #'downcase rts t))
+    ('capitalize-first
+     (--map (citeproc-rt-change-case it #'citeproc-s-capitalize-first) rts))
+    ('capitalize-all
+     (--map (citeproc-rt-change-case it #'citeproc-s-capitalize-all) rts))
+    ('sentence
+     (--map (citeproc-rt-change-case it #'citeproc-s-sentence-case) rts))
+    ('title
+     (let ((locale (citeproc-context-locale context))
+          (language (citeproc-var-value 'language context)))
+       (if (or (and language (string-prefix-p "en" language))
+              (and (null language)
+                   (or (and locale (string-prefix-p "en" locale))
+                       (null locale))))
+          (--map (citeproc-rt-change-case it #'citeproc-s-title-case) rts)
+        rts)))))
+
+(defun citeproc-rt-join-formatted (attrs rts context)
+  "Join and format according to ATTRS the rich-texts in RTS."
+  (let-alist attrs
+    (let ((result (delq nil rts)))
+      (when .text-case
+       (setq result (citeproc-rt-textcased result (intern .text-case) context)))
+      (when (string= .strip-periods "true") (setq result (citeproc-rt-strip-periods result)))
+      (when (string= .quotes "true") (setq result (citeproc-rt-quote result context)))
+      (push (citeproc-rt-select-attrs attrs citeproc-rt-ext-format-attrs) result)
+      (if (and .delimiter
+              (> (length result) 2))
+         result
+       (citeproc-rt-simplify-shallow result)))))
+
+(defun citeproc-rt-format-single (attrs rt context)
+  "Format according to ATTRS rich-text RT using CONTEXT."
+  (if (or (not rt) (and (char-or-string-p rt) (string= rt "")))
+      nil
+    (citeproc-rt-join-formatted attrs (list rt) context)))
+
+(defun citeproc-rt-typed-join (attrs typed-rts context)
+  "Join and format according to ATTRS contents in list TYPED-RTS.
+TYPED RTS is a list of (RICH-TEXT . TYPE) pairs"
+  (-let* ((types (--map (cdr it) typed-rts))
+         (type (cond ((--all? (eq it 'text-only) types)
+                      'text-only)
+                     ((--any? (eq it 'present-var) types)
+                      'present-var)
+                     (t 'empty-vars))))
+    (cons (citeproc-rt-join-formatted attrs
+                                     (--map (car it) typed-rts)
+                                     context)
+         type)))
+
+(defun citeproc-term-get-text (term context)
+  "Return the first text associated with TERM in CONTEXT."
+  (citeproc-term-text-from-terms term (citeproc-context-terms context)))
+
+(defun citeproc-term-inflected-text (term form number context)
+  "Return the text associated with TERM having FORM and NUMBER."
+  (let ((matches
+        (--select (string= term (citeproc-term-name it))
+                  (citeproc-context-terms context))))
+    (cond ((not matches) nil)
+         ((= (length matches) 1)
+          (citeproc-term-text (car matches)))
+         (t (citeproc-term--inflected-text-1 matches form number)))))
+
+(defconst citeproc--term-form-fallback-alist
+  '((verb-short . verb)
+    (symbol . short)
+    (verb . long)
+    (short . long))
+  "Alist containing the fallback form for each term form.")
+
+(defun citeproc-term--inflected-text-1 (matches form number)
+  (let ((match (--first (and (eq form (citeproc-term-form it))
+                            (or (not (citeproc-term-number it))
+                                (eq number (citeproc-term-number it))))
+                       matches)))
+    (if match
+       (citeproc-term-text match)
+      (citeproc-term--inflected-text-1
+       matches
+       (alist-get form citeproc--term-form-fallback-alist)
+       number))))
+
+(defun citeproc-term-get-gender (term context)
+  "Return the gender of TERM or nil if none is given."
+  (-if-let (match
+           (--first (and (string= (citeproc-term-name it) term)
+                         (citeproc-term-gender it)
+                         (eq (citeproc-term-form it) 'long))
+                    (citeproc-context-terms context)))
+      (citeproc-term-gender match)
+    nil))
+
+(defun citeproc-context-int-link-attrval (style internal-links mode cite-pos)
+  "Return an appropriate attribute to represent internal linking info.
+INTERNAL-LINKS is the internal linking mode, see the
+documentation of `citeproc-render-varlist-in-rt', while MODE is
+the rendering mode, `bib' or `cite', and CITE-POS is a cite
+position. Returns an appropriate attribute to be added or nil if
+no internal links should be produced."
+  (let ((note-style (citeproc-style-cite-note style)))
+    (unless (or (and internal-links (not (memq internal-links '(auto bib-links))))
+               (and note-style (eq mode 'bib) (or (null internal-links)
+                                                  (eq internal-links 'auto))))
+      (if (and note-style (not (eq internal-links 'bib-links)))
+         ;; For note styles link subsequent cites to the first ones.
+         (if (eq cite-pos 'first) 'bib-item-no 'cited-item-no)
+       ;; Else link each cite to the corresponding bib item.
+       (if (eq mode 'cite) 'cited-item-no 'bib-item-no)))))
+
+(defun citeproc-render-varlist-in-rt (var-alist style mode render-mode &optional
+                                               internal-links no-external-links)
+  "Render an item described by VAR-ALIST with STYLE in rich-text.
+Does NOT finalize the rich-text rendering. MODE is either `bib'
+or `cite', RENDER-MODE is `display' or `sort'.
+  If the optional INTERNAL-LINKS is `bib-links' then link cites
+to the bibliography regardless of the style type, if `no-links'
+then don't add internal links, if nil or `auto' then add internal
+links based on the style type (cite-cite links for note styles
+and cite-bib links else). For legacy reasons, any other value is
+treated as `no-links'.
+  If the optional NO-EXTERNAL-LINKS is non-nil then don't add
+external links."
+  (-if-let (unprocessed-id (alist-get 'unprocessed-with-id var-alist))
+      ;; Itemid received no associated csl fields from the getter!
+      (list nil (concat "NO_ITEM_DATA:" unprocessed-id))
+    (let* ((context (citeproc-context-create var-alist style mode render-mode
+                                            no-external-links))
+          (layout-fun-accessor (if (eq mode 'cite) 'citeproc-style-cite-layout
+                                 'citeproc-style-bib-layout))
+          (layout-fun (funcall layout-fun-accessor style)))
+      (if (null layout-fun) "[NO BIBLIOGRAPHY LAYOUT IN CSL STYLE]"
+       (let ((rendered (catch 'stop-rendering
+                         (funcall layout-fun context))))
+         ;; Finalize external linking by linking the title if needed
+         (when (and (eq mode 'bib) (not no-external-links))
+           (-when-let ((var . val) (--any (assoc it var-alist)
+                                          citeproc--linked-vars))
+             (unless (cl-intersection (citeproc-rt-rendered-vars rendered)
+                                      citeproc--linked-vars)
+               (citeproc-rt-link-title rendered
+                                       (concat (alist-get var citeproc--link-prefix-alist
+                                                          "")
+                                               (alist-get var var-alist))))))
+         ;; Add appropriate item-no information
+         (when-let* ((cite-no-attr
+                      (citeproc-context-int-link-attrval
+                       style internal-links mode (alist-get 'position var-alist)))
+                     (cite-no-attr-val (cons cite-no-attr
+                                            (alist-get 'citation-number var-alist))))
+           (cond ((consp rendered) (setf (car rendered)
+                                         (-snoc (car rendered) cite-no-attr-val)))
+                 ((stringp rendered) (setq rendered
+                                           (list (list cite-no-attr-val) rendered)))))
+         ;; Add year-suffix if needed
+         (-if-let (year-suffix (alist-get 'year-suffix var-alist))
+             (car (citeproc-rt-add-year-suffix
+                   rendered
+                   ;; year suffix is empty if already rendered by var just to delete the
+                   ;; suppressed date
+                   (if (citeproc-style-uses-ys-var style) "" year-suffix)))
+           rendered))))))
+
+(provide 'citeproc-context)
+
+;;; citeproc-context.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-date.el b/elpa/citeproc-20230228.1414/citeproc-date.el
new file mode 100644 (file)
index 0000000..abf166f
--- /dev/null
@@ -0,0 +1,280 @@
+;;; citeproc-date.el --- CSL date rendering -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Structure type and functions to render CSL date elements.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'cl-lib)
+(require 'dash)
+(require 'let-alist)
+(require 's)
+
+(require 'citeproc-lib)
+(require 'citeproc-rt)
+(require 'citeproc-context)
+
+(cl-defstruct (citeproc-date (:constructor citeproc-date-create))
+  "Struct for representing dates.
+Slots YEAR, MONTH, DAY are integers, while SEASON and CIRCA are
+booleans. SEASON indicates whether the integer in slot MONTH is
+to be interpreted as a season number."
+  (year nil) (month nil) (day nil) (season nil) (circa nil))
+
+(defun citeproc-date-parse (date-rep)
+  "Parse CSL json date repr. DATE-REP into an internal one."
+  (let-alist date-rep
+    (--map (citeproc-date--conv it .season .circa) .date-parts)))
+
+(defun citeproc-date--conv (dates &optional season circa)
+  "Convert date-part list DATES to a citeproc-date struct.
+Set the remaining slots to the values SEASON and CIRCA."
+  (-let* ((numeric
+          (--map (if (stringp it) (string-to-number it) it) dates))
+         ((year month day) numeric))
+    (citeproc-date-create :year year :month month :day day
+                         :season season :circa circa)))
+
+(defun citeproc-date--partattrs-for-sort (part-attrs)
+  "Return a sort-key version of PART-ATTRS."
+  (let (result)
+    (when (assoc 'day part-attrs)
+      (push '(day . ((form . "numeric-leading-zeros"))) result))
+    (when (assoc 'month part-attrs)
+      (push '(month . ((form . "numeric-leading-zeros"))) result))
+    (when (assoc 'year part-attrs)
+      (push '(year . ((form . "long"))) result))
+    result))
+
+(defun citeproc--date (attrs context &rest body)
+  "Function corresponding to the date CSL element."
+  (-let* (((&alist 'variable var
+                  'form form)
+          attrs)
+         (var-sym (intern var))
+         (parsed-dates (citeproc-var-value var-sym context))
+         ((d1 d2) parsed-dates)
+         (result
+          (if d1
+              (progn
+                (when form
+                  (let ((localized (citeproc-date--localized-attrs attrs body context)))
+                    (setq attrs (car localized)
+                          body (cdr localized))))
+                (when (eq (citeproc-context-render-mode context) 'sort)
+                  (setq body (citeproc-date--partattrs-for-sort body)))
+                (if (citeproc-date--renders-with-attrs-p d1 body)
+                    (progn
+                      (push `(rendered-var . ,(intern var)) attrs)
+                      (cons (if d2
+                                (citeproc-date--render-range d1 d2 attrs body context)
+                              (citeproc-date--render d1 attrs body context))
+                            'present-var))
+                  (cons nil 'empty-vars)))
+            (cons nil 'empty-vars))))
+    ;; Handle `year' citation mode by stopping if needed
+    (citeproc-lib-maybe-stop-rendering 'issued context result var-sym)))
+
+(defun citeproc--date-part (attrs _context &rest _body)
+  "Function corresponding to the date-part CSL element."
+  (cons (intern (alist-get 'name attrs))
+       attrs))
+
+(defun citeproc-date--renders-with-attrs-p (date part-attrs)
+  "Whether DATE contains date-parts corresponding to PART-ATTRS."
+  (let ((date-parts (mapcar #'car part-attrs)))
+    (or (memq 'year date-parts)                ; All dates contain a year
+       (and (memq 'month date-parts) (citeproc-date-month date))
+       (and (memq 'day date-parts) (citeproc-date-day date)))))
+
+(defun citeproc-date--localized-attrs (attrs part-attrs context)
+  "Return the localized date attrs merged with date ATTRS and date PART-ATTRS."
+  (-let* (((&alist 'form form
+                  'date-parts date-parts)
+          attrs)
+         ((loc-attrs . loc-part-attrs)
+          (if (string= form "text") (citeproc-context-date-text context)
+            (citeproc-context-date-numeric context))))
+    (pcase (citeproc-lib-intern date-parts)
+      ('year
+       (setq loc-part-attrs
+            (--select (eq (car it) 'year) loc-part-attrs)))
+      ('year-month
+       (setq loc-part-attrs
+            (--select (memq (car it) '(year month)) loc-part-attrs))))
+    (cons (-concat attrs loc-attrs)
+         (--map (cons (car it)
+                      (-concat (alist-get (car it) part-attrs) (cdr it)))
+                loc-part-attrs))))
+
+(defun citeproc-date--render (d attrs part-attrs context)
+  "Render citeproc-date D according to formatting in ATTRS and PART-ATTRS.
+Return a rich-text content."
+  (if (citeproc-var-value 'suppress-date context)
+      (citeproc-rt-format-single attrs "<suppressed-date>" context)
+    (let ((rendered-date (citeproc-date--render-parts d part-attrs context)))
+      (citeproc-rt-join-formatted attrs rendered-date context))))
+
+(defun citeproc-date--render-parts (d part-attrs context &optional no-last-suffix)
+  "Render the parts of citeproc-date D according to PART-ATTRS.
+Return a list of rich-text contents. If optional NO-LAST-SUFFIX
+is non-nil then remove the suffix attribute of the last rendered
+element (used for date range rendering)."
+  (let ((result (--map (pcase (car it)
+                        ('year (citeproc-date--render-year d (cdr it) context))
+                        ('month (citeproc-date--render-month d (cdr it) context))
+                        ('day (citeproc-date--render-day d (cdr it) context)))
+                      part-attrs)))
+    (-if-let* ((n-l-s no-last-suffix)
+              (last (car (last result)))
+              (wo-suffix (and (consp last)
+                              (cons (--remove (eq 'suffix (car it)) (car last))
+                                    (cdr last)))))
+       (-snoc (butlast result) wo-suffix)
+      result)))
+
+(defun citeproc-date--render-range-parts (d1 d2 part-attrs sep context)
+  "Render the parts of citeproc-dates D1 and D2 according to PART-ATTRS.
+PART-ATTRS is a list containing either part-attrs or lists of part-attrs.
+The formers are only rendered for D1, while the latters are rendered for both
+D1 and D2. Return a list of rich-text contents."
+  (--mapcat (pcase (car it)
+             ('year (list (citeproc-date--render-year d1 (cdr it) context)))
+             ('month (list (citeproc-date--render-month d1 (cdr it) context)))
+             ('day (list (citeproc-date--render-day d1 (cdr it) context)))
+             (_ (-concat (citeproc-date--render-parts d1 it context t)
+                         (list sep)
+                         (citeproc-date--render-parts d2 it context))))
+           part-attrs))
+
+(defun citeproc-date--render-range (d1 d2 attrs part-attrs context)
+  "Render the range given by dates D1 D2 according to attrs."
+  (if (citeproc-var-value 'suppress-date context)
+      (citeproc-rt-format-single attrs "" context)
+    (let* ((gran (min (citeproc-date--gran d1)
+                     (citeproc-date--attrs-gran part-attrs)))
+          (range-sep (or (alist-get 'range-delimiter
+                                    (alist-get (elt '(year month day) gran)
+                                               part-attrs))
+                         "–"))
+          (range-p-attrs
+           (cond ((/= (citeproc-date-year d1) (citeproc-date-year d2))
+                  (list part-attrs))
+                 ((/= (citeproc-date-month d1) (citeproc-date-month d2))
+                  (let ((year-part (--find (eq 'year (car it))
+                                           part-attrs))
+                        (attrs-wo-year
+                         (--remove (eq 'year (car it))
+                                   part-attrs)))
+                    (cond ((eq (caar part-attrs) 'year)
+                           (list year-part attrs-wo-year))
+                          ((eq (caar (last part-attrs)) 'year)
+                           (list attrs-wo-year year-part))
+                          (t (list attrs-wo-year)))))
+                 (t (--map (if (eq (car it) 'day) (list it) it)
+                           part-attrs))))
+          (rendered-range (citeproc-date--render-range-parts d1 d2 range-p-attrs range-sep
+                                                             context)))
+      (citeproc-rt-join-formatted attrs rendered-range context))))
+
+(defun citeproc-date--attrs-gran (d-attrs)
+  "Return the granularity (smallest unit) of date-attrs alist D-ATTRS.
+The returned value is 0, 1 or 2, corresponding to a year, month
+or day granularity."
+  (cond ((assoc 'day d-attrs) 2)
+       ((assoc 'month d-attrs) 1)
+       (t 0)))
+
+(defun citeproc-date--gran (date)
+  "Return the granularity (smallest unit) in citeproc-date struct DATE.
+The returned value is 0, 1 or 2, corresponding to a year, month
+or day granularity."
+  (cond ((citeproc-date-day date) 2)
+       ((citeproc-date-month date) 1)
+       (t 0)))
+
+(defun citeproc-date--render-year (d attrs context)
+  "Render the year in date D according to formatting in ATTRS.
+D is a citeproc-date structure. Return a rich-text content."
+  (-let* ((form (alist-get 'form attrs))
+         (year (citeproc-date-year d))
+         (s (number-to-string (abs year)))
+         (era
+          (cond ((> year 999) "")
+                ((> year 0) (citeproc-term-get-text "ad" context))
+                (t (citeproc-term-get-text "bc" context)))))
+
+    (citeproc-rt-format-single attrs (concat (if (string= form "short")
+                                                (s-right 2 s)
+                                              s)
+                                            era)
+                              context)))
+
+(defun citeproc-date--render-month (d attrs context)
+  "Render the month in date D according to formatting in ATTRS.
+D is a citeproc-date structure. Return a rich-text content."
+  (-if-let (month (citeproc-date-month d))
+      (let ((form (alist-get 'form attrs))
+           (term-pref (if (citeproc-date-season d)
+                          "season-" "month-")))
+       (citeproc-rt-format-single
+        attrs
+        (pcase (citeproc-lib-intern form)
+          ('numeric (number-to-string month))
+          ('numeric-leading-zeros (format "%02d" month))
+          ('short (citeproc-term-inflected-text
+                   (concat term-pref (format "%02d" month))
+                   'short nil context))
+          (_ (citeproc-term-inflected-text
+              (concat term-pref (format "%02d" month))
+              'long nil context)))
+        context))
+    nil))
+
+(defun citeproc-date--render-day (d attrs context)
+  "Render the day in date D according to formatting in ATTRS.
+D is a citeproc-date structure. Return a rich-text content."
+  (-if-let (day (citeproc-date-day d))
+      (let ((form (alist-get 'form attrs))
+           (month (citeproc-date-month d)))
+       (citeproc-rt-format-single
+        attrs
+        (cond
+         ((string= form "numeric-leading-zeros")
+          (format "%02d" day))
+         ((and (string= form "ordinal")
+               (or (= day 1)
+                   (not (string= "true"
+                                 (alist-get 'limit-day-ordinals-to-day-1
+                                            (citeproc-context-locale-opts context))))))
+          (citeproc-number--format-as-ordinal (number-to-string day)
+                                              (concat "month-" (format "%02d" month))
+                                              context))
+         (t (number-to-string day)))
+        context))
+    nil))
+
+(provide 'citeproc-date)
+
+;;; citeproc-date.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-disamb.el b/elpa/citeproc-20230228.1414/citeproc-disamb.el
new file mode 100644 (file)
index 0000000..0f58510
--- /dev/null
@@ -0,0 +1,247 @@
+;;; citeproc-disamb.el --- disambiguate ambiguous cites -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions to disambiguate cites of different bibliography items that would
+;; have the same rendering. Disambiguation steps (e.g., adding more names,
+;; expanding names, adding year-suffixes) are performed according to the
+;; disambiguation rules specified by the CSL style in use.
+
+;;; Code:
+
+(require 'dash)
+(require 'cl-lib)
+(require 'subr-x)
+
+(require 'citeproc-itemdata)
+
+(defun citeproc-itd-inc-disamb-level (key itd type)
+  "Increment the disambiguation level of KEY in itemdata ITD.
+TYPE is either `add-names' or `show-given-names.'"
+  (let ((vv (citeproc-itemdata-varvals itd)))
+    (if (alist-get type vv)
+       (let* ((cur-level (alist-get key (alist-get type vv)))
+              (new-level (if cur-level (1+ cur-level) 1)))
+         (setf (alist-get key (alist-get type vv)) new-level))
+      (push `(,type . ((,key . 1))) (citeproc-itemdata-varvals itd))))
+  (setf (citeproc-itemdata-rc-uptodate itd) nil))
+
+(defun citeproc-itd-add-name (itd style &optional _first-step)
+  "Perform an add-name disambig. step on itemdata ITD with STYLE.
+FIRST-STEP is ignored -- it is there to get the same signature as
+the other two disamb. step functions. Return nil if no disambiguation
+could be performed and t otherwise. Disambiguation is performed
+from left to right: an item is attempted to be expanded only if
+no previous items to the left could be."
+  (let* ((vars (citeproc-itd-namevars itd style))
+        (cite (citeproc-itd-plain-cite itd style))
+        (vv (citeproc-itemdata-varvals itd))
+        (levels (alist-get 'add-names vv))
+        (remaining-vars (if levels (memq (caar levels) vars) vars))
+        (success nil))
+    (while (and (not success) remaining-vars)
+      (citeproc-itd-inc-disamb-level (car remaining-vars) itd 'add-names)
+      (if (string= cite (citeproc-itd-plain-cite itd style))
+         (pop remaining-vars)
+       (setq success t)))
+    success))
+
+(defun citeproc-itd-add-given (itd style &optional first-step)
+  "Perform an add-given disambig. step on itemdata ITD with STYLE.
+Unless FIRST-STEP is non-nil, remove the last previously added
+given name if the last added given name is shown in its entirety.
+Return nil if no disambig. step could be performed and t
+otherwise."
+  (let* ((nids (citeproc-itd-nameids itd style))
+        (cite (citeproc-itd-plain-cite itd style))
+        (vv (citeproc-itemdata-varvals itd))
+        (levels (alist-get 'show-given-names vv))
+        (remaining-nids (if levels (memq (caar levels) nids) nids))
+        (success nil))
+    (while (and (not success) remaining-nids)
+      (let* ((current-nid (car remaining-nids))
+            (vv (citeproc-itemdata-varvals itd))
+            (levels (alist-get 'show-given-names vv))
+            (current-level (alist-get current-nid levels)))
+       (if (and current-level (>= current-level 2))
+           (pop remaining-nids)
+         (citeproc-itd-inc-disamb-level current-nid itd 'show-given-names)
+         (unless (string= cite (citeproc-itd-plain-cite itd style))
+           (setq success t)
+           (unless (or first-step current-level)
+             (let ((ls (alist-get 'show-given-names vv)))
+               (setf (alist-get 'show-given-names vv)
+                     (cons (car ls) (cddr ls))))
+             (setf (citeproc-itemdata-rc-uptodate itd) nil))))))
+    success))
+
+(defun citeproc-itd-addgiven-with-addname (itd style &optional first-step)
+  "Perform a combined disambig. step on itemdata ITD with STYLE.
+If FIRST-STEP is non-nil then (i) add a new name even if the last
+add-given step showed only initials, (ii) don't remove the
+previously added given name. Return nil if no disambig. step
+could be performed and t otherwise."
+  (let* ((vv (citeproc-itemdata-varvals itd))
+        (gn (alist-get 'show-given-names vv))
+        (success nil)
+        (remaining-names t))
+    (if (and (not first-step) gn (= 1 (cdar gn)) (citeproc-itd-add-given itd style))
+       t
+      (while (and (not success) remaining-names)
+       (let ((nids (citeproc-itd-nameids itd style)))
+         (if (citeproc-itd-add-name itd style)
+             (let* ((new-nids (citeproc-itd-nameids itd style))
+                    (new-nid (car (cl-set-difference new-nids nids))))
+               ;;next sexp is to direct the add-given function to the just added name
+               (when first-step
+                 (setf (alist-get new-nid
+                                  (alist-get 'show-given-names
+                                             (citeproc-itemdata-varvals itd)))
+                       0))
+               (when (citeproc-itd-add-given itd style first-step)
+                 (setq success t)))
+           (setq remaining-names nil))))
+      success)))
+
+(defun citeproc-disamb--different-cites-p (itds style)
+  "Whether some itemdata in ITDS have different cites with STYLE."
+  (--any-p (not (string= (citeproc-itd-plain-cite it style)
+                        (citeproc-itd-plain-cite (car itds) style)))
+          (cdr itds)))
+
+(defun citeproc-disamb--with-method (itds style disamb-fun)
+  "Disambiguate itemdatas in ITDS for STYLE with DISAMB-FUN.
+Return t if the disambiguation was (at least partially)
+successful and nil otherwise."
+  (let ((orig-settings (copy-tree (citeproc-disamb--settings itds)))
+       success
+       (first-step t))
+    (while (and (not success)
+               (--all-p (funcall disamb-fun it style first-step) itds))
+      (setq first-step nil)
+      (when (citeproc-disamb--different-cites-p itds style)
+       (setq success t)))
+    (unless success
+      (citeproc-disamb--restore-settings itds orig-settings))
+    success))
+
+(defun citeproc-disamb--settings (itds)
+  "Return a list with the disamb settings of ITDS."
+  (--map (cons (citeproc-itd-getvar it 'add-names)
+              (citeproc-itd-getvar it 'show-given-names))
+        itds))
+
+(defun citeproc-disamb--restore-settings (itds settings)
+  "Restore the disamb settings of ITDS from SETTINGS.
+SETTINGS should have the structure produced by citeproc--disamb-settings."
+  (cl-loop for itd in itds
+          for (add-names-val . show-given-val) in settings do
+          (citeproc-itd-setvar itd 'add-names add-names-val)
+          (citeproc-itd-setvar itd 'show-given-names show-given-val)))
+
+(defun citeproc-disamb--num-to-yearsuffix (n)
+  "Return year-suffix no. N (starting from 0)."
+  (cond ((< n 26)
+        (char-to-string (+ 97 n)))
+       ((< n 702)
+        (let* ((rem (% n 26))
+               (d (/ (- n rem) 26)))
+          (concat (char-to-string (+ 96 d))
+                  (char-to-string (+ 97 rem)))))
+       (t (error "Number too large to convert into a year-suffix"))))
+
+(defun citeproc-disamb--add-yearsuffix (itds _style)
+  "Disambiguate itemdata in ITDS by adding year suffices.
+Return t (for the sake of consistency with other disamb methods)."
+  (--each-indexed (--sort (< (string-to-number (citeproc-itd-getvar it 'citation-number))
+                            (string-to-number (citeproc-itd-getvar other 'citation-number)))
+                         itds)
+    (citeproc-itd-setvar it 'year-suffix (citeproc-disamb--num-to-yearsuffix it-index))
+    (setf (citeproc-itemdata-rc-uptodate it) nil))
+  t)
+
+(defun citeproc-disamb--set-fields (itds)
+  "Disambiguate ITDS by setting their disambiguate fields."
+  (--each itds
+    (citeproc-itd-setvar it 'disambiguate t)))
+
+(defun citeproc-disamb-amb-itds (itds style name given yearsuff)
+  "Disambiguate ITDS ambigous for STYLE with the given methods.
+NAME, GIVEN and YEARSUFF are generalized booleans specifying
+whether or not the add-name, show-given or add-year-suffix
+disambiguation methods should be used. Return t if the
+disambiguation was (at least partially) successful, nil
+otherwise."
+  (or (and name (citeproc-disamb--with-method itds style 'citeproc-itd-add-name))
+      (and given (citeproc-disamb--with-method itds style 'citeproc-itd-add-given))
+      (and name given
+          (citeproc-disamb--with-method itds style 'citeproc-itd-addgiven-with-addname))
+      (progn
+       (citeproc-disamb--set-fields itds)
+       (citeproc-disamb--different-cites-p itds style))
+      (and yearsuff
+          (citeproc-disamb--add-yearsuffix itds style)
+          (citeproc-disamb--different-cites-p itds style))))
+
+(defun citeproc-amb-itds (itds style)
+  "Return a list of ambigous sets in ITDS for STYLE.
+The returned value is a (possibly empty) list of lists."
+  (let* ((sorted (-sort (lambda (x y)
+                         (string< (citeproc-itd-plain-cite x style)
+                                  (citeproc-itd-plain-cite y style)))
+                       itds))
+        (result nil)
+        (remaining (cdr sorted))
+        (act (car sorted))
+        (act-list (list act))
+        (ambig nil))
+    (while remaining
+      (let ((next (car remaining)))
+       (if (string= (citeproc-itd-plain-cite act style)
+                    (citeproc-itd-plain-cite next style))
+           (progn
+             (push next act-list)
+             (setq ambig t))
+         (when ambig (push act-list result))
+         (setq act-list (list next)
+               act next
+               ambig nil))
+       (pop remaining)))
+    (when ambig (push act-list result))
+    result))
+
+(defun citeproc-disamb-itds (itds style name given yearsuff)
+  "Disambiguate itemdatas in list ITDS for STYLE.
+NAME, GIVEN and YEARSUFF are generalized booleans specifying
+whether or not the add-name, show-given or add-year-suffix
+disambiguation methods should be used."
+  (let ((amb-itds (citeproc-amb-itds itds style)))
+    (while amb-itds
+      (let ((act-set (pop amb-itds)))
+       (citeproc-disamb-amb-itds act-set style name given yearsuff)
+       (when (citeproc-disamb--different-cites-p act-set style)
+         (-when-let (new-ambs (citeproc-amb-itds act-set style))
+           (setq amb-itds (nconc new-ambs amb-itds))))))))
+
+(provide 'citeproc-disamb)
+
+;;; citeproc-disamb.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-formatters.el b/elpa/citeproc-20230228.1414/citeproc-formatters.el
new file mode 100644 (file)
index 0000000..5897b26
--- /dev/null
@@ -0,0 +1,392 @@
+;; citeproc-formatters.el --- output formatters -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Provides a general framework for defining citeproc-el output formatters, and,
+;; using this framework, defines formatters for the formats `raw' (the rich-text
+;; internal representation), `plain' (plain-text), `html', `org' and `latex'.
+;; Further output formatters can easily be added.
+
+;;; Code:
+
+(require 'let-alist)
+(require 'subr-x)
+(require 's)
+(require 'cl-lib)
+
+  (cl-defstruct (citeproc-formatter (:constructor citeproc-formatter-create))
+    "Output formatter struct with slots RT, CITE, BIB-ITEM and BIB.
+RT is a one-argument function mapping a rich-text to its
+  formatted version,
+CITE is a one-argument function mapping the output of RT for a
+  citation rich-text to a fully formatted citation,
+BIB-ITEM is a two-argument function mapping the output of RT for
+  a bibliography-item rich-text and a BIB-FORMAT alist (see
+  below) to a fully formatted bibliography item,
+BIB is a two-argument function mapping a list of formatted
+  bibliography items and a FORMATTING-PARAMETERS alist (see
+  `citeproc-render-bib' for details) to a fully formatted
+  bibliography,
+NO-EXTERNAL-LINKS is non-nil if the formatter doesn't support
+  external linking."
+    rt (cite #'identity) (bib-item (lambda (x _) x))
+    (bib (lambda (x _) (mapconcat #'identity x "\n\n")))
+    (no-external-links nil))
+
+(defun citeproc-formatter-fun-create (fmt-alist)
+  "Return a rich-text formatter function based on FMT-ALIST.
+FMT-ALIST is an alist with some or all of the following symbols
+as keys:
+- `unformatted',
+- `font-style-italic', `font-style-oblique', `font-style-normal',
+- `font-variant-small-caps', `font-variant-normal',
+- `font-weight-bold', `font-weight-light', `font-weight-normal',
+- `text-decoration-underline', `text-decoration-normal',
+- `vertical-align-sub', `vertical-align-sup', `vertical-align-baseline',
+- `display-block', `display-left-margin', `display-right-inline',
+  `display-indent',
+- `href',
+- `cited-item-no', `bib-item-no'.
+
+With the exceptions listed below the values should be
+one-argument formatting functions that format the input string
+according to the attribute-value pair specified by the key.
+
+The exceptions are the keys
+`unformatted', for which the value should be a one-argument
+  function converting unformatted text into the required
+  format (e.g., by escaping);
+`href', here the value should be a two-argument function
+  mapping the first argument as anchor text and the second as
+  target URI to a hyperlink representation; and
+`cited-item-no' and `bib-item-no' whose associated values
+  should be two-argument functions, which are called with the
+  already formatted cites/bibliography item text and the number of
+  the bibliography item as a string."
+  (cl-labels
+      ((rt-fmt
+       (rt)
+       (pcase rt
+         ((pred stringp) (funcall (alist-get 'unformatted fmt-alist) rt))
+         ((pred consp)
+          (let ((attrs (car rt))
+                (result (mapconcat #'rt-fmt (cdr rt) "")))
+            (dolist (attr attrs)
+              (let ((key (car attr)))
+                (if (memq key '(href cited-item-no bib-item-no))
+                    (when-let ((fmt-fun (alist-get key fmt-alist)))
+                      (setq result (funcall fmt-fun result (cdr attr))))
+                  (when-let
+                      ((fmt-fun
+                        (alist-get
+                         (pcase attr
+                           ('(font-style . "italic") 'font-style-italic)
+                           ('(font-weight . "bold") 'font-weight-bold)
+                           ('(display . "indent") 'display-indent)
+                           ('(display . "left-margin") 'display-left-margin)
+                           ('(display . "right-inline") 'display-right-inline)
+                           ('(display . "block") 'display-block)
+                           ('(vertical-align . "sup") 'vertical-align-sup)
+                           ('(vertical-align . "baseline") 'vertical-align-baseline)
+                           ('(font-variant . "small-caps") 'font-variant-small-caps)
+                           ('(text-decoration . "underline") 'text-decoration-underline)
+                           ('(font-style . "oblique") 'font-style-oblique)
+                           ('(font-style . "normal") 'font-style-normal)
+                           ('(font-variant . "normal") 'font-variant-normal)
+                           ('(font-weight . "light") 'font-weight-light)
+                           ('(font-weight . "normal") 'font-weight-normal)
+                           ('(text-decoration . "normal") 'text-decoration-normal)
+                           ('(vertical-align . "sub") 'vertical-align-sub))
+                         fmt-alist)))
+                    (setq result (funcall fmt-fun result))))))
+            result))
+         (_ rt))))
+    #'rt-fmt))
+
+;;;; Specific formatters
+
+;; Org
+
+(defun citeproc-fmt--org-link (anchor target)
+  "Return an Org link with ANCHOR and TARGET.
+If ANCHOR is string= to TARGET then return ANCHOR."
+  (if (string= anchor target)
+      anchor
+    (concat "[[" target "][" anchor "]]")))
+
+(defconst citeproc-fmt--org-alist
+  `((unformatted . identity)
+    (href . ,#'citeproc-fmt--org-link)
+    (cited-item-no . ,(lambda (x y) (concat "[[citeproc_bib_item_" y "][" x "]]")))
+    (bib-item-no . ,(lambda (x y) (concat "<<citeproc_bib_item_" y ">>" x)))
+    ;; Warning: The next four formatter lines put protective zero-width spaces
+    ;; around the Org format characters ('/' etc.).
+    (font-style-italic . ,(lambda (x) (concat "​/" x "/​")))
+    (font-style-oblique . ,(lambda (x) (concat "​/" x "/​")))
+    (font-weight-bold . ,(lambda (x) (concat "​*" x "*​")))
+    (text-decoration-underline . ,(lambda (x) (concat "​_" x "_​")))
+    ;; End of zero-width space protected formatters.
+    (font-variant-small-caps . ,(lambda (x) (upcase x)))
+    (vertical-align-sub . ,(lambda (x) (concat "_{" x "}")))
+    (vertical-align-sup . ,(lambda (x) (concat "^{" x "}")))
+    (display-left-margin . ,(lambda (x) (concat x " ")))))
+
+(defvar citeproc-fmt--org-format-rt-1
+  (citeproc-formatter-fun-create citeproc-fmt--org-alist)
+  "Recursive rich-text Org formatter.
+Doesn't do finalization by removing zero-width spaces.")
+
+(defun citeproc-fmt--org-format-rt (rt)
+  "Convert rich-text RT into Org format.
+Performs finalization by removing unnecessary zero-width spaces."
+  (let ((result (funcall citeproc-fmt--org-format-rt-1 rt)))
+    (when (> (length result) 2)
+      ;; First we remove z-w spaces around spaces and before punctuation.
+      (setq result (citeproc-s-replace-all-seq
+                   result '((" ​" . " ") ("​ " . " ") ("​," . ",") ("​;" . ";")
+                            ("​:" . ":") ("​." . "."))))
+      ;; Starting and ending z-w spaces are also removed, but not before an
+      ;; asterisk to avoid creating an Org heading.
+      (when (and (= (aref result 0) 8203)
+                (not (= (aref result 1) ?*)))
+       (setq result (substring result 1)))
+      (when (= (aref result (- (length result) 1)) 8203)
+       (setq result (substring result 0 -1))))
+    result))
+
+;; HTML
+
+(defun citeproc-fmt--xml-escape (s)
+  "Return the xml-escaped version of string S.
+Only '&', '<' and '>' are escaped to keep compatibility with the
+CSL tests."
+  (citeproc-s-replace-all-seq s '(("&" . "&#38;") ("<" . "&#60;") (">" . "&#62;"))))
+
+(defconst citeproc-fmt--html-alist
+  `((unformatted . citeproc-fmt--xml-escape)
+    (href . ,(lambda (x y) (concat "<a href=\"" y "\">" x "</a>")))
+    (cited-item-no . ,(lambda (x y) (concat "<a href=\"#citeproc_bib_item_" y "\">"
+                                           x "</a>")))
+    (bib-item-no . ,(lambda (x y) (concat "<a id=\"citeproc_bib_item_" y "\"></a>"
+                                         x)))
+    (font-style-italic . ,(lambda (x) (concat "<i>" x "</i>")))
+    (font-style-oblique . ,(lambda (x)
+                            (concat "<span style=\"font-style:oblique;\"" x "</span>")))
+    (font-variant-small-caps . ,(lambda (x)
+                                 (concat
+                                  "<span style=\"font-variant:small-caps;\">" x "</span>")))
+    (font-weight-bold . ,(lambda (x) (concat "<b>" x "</b>")))
+    (text-decoration-underline .
+                              ,(lambda (x)
+                                 (concat
+                                  "<span style=\"text-decoration:underline;\">" x "</span>")))
+    (vertical-align-sub . ,(lambda (x) (concat "<sub>" x "</sub>")))
+    (vertical-align-sup . ,(lambda (x) (concat "<sup>" x "</sup>")))
+    (vertical-align-baseline . ,(lambda (x) (concat "<span style=\"baseline\">" x "</span>")))
+    (display-left-margin . ,(lambda (x) (concat "\n    <div class=\"csl-left-margin\">"
+                                               x "</div>")))
+    (display-right-inline . ,(lambda (x) (concat "<div class=\"csl-right-inline\">"
+                                                x "</div>\n  ")))
+    (display-block . ,(lambda (x) (concat "\n\n    <div class=\"csl-block\">"
+                                         x "</div>\n")))
+    (display-indent . ,(lambda (x) (concat "<div class=\"csl-indent\">" x "</div>\n  ")))))
+
+(defconst citeproc-fmt--csl-test-alist
+  `((unformatted . citeproc-fmt--xml-escape)
+    (cited-item-no . ,(lambda (x y) (concat "<a href=\"#citeproc_bib_item_" y "\">"
+                                           x "</a>")))
+    (bib-item-no . ,(lambda (x y) (concat "<a id=\"citeproc_bib_item_" y "\"></a>"
+                                         x)))
+    (font-style-italic . ,(lambda (x) (concat "<i>" x "</i>")))
+    (font-style-oblique . ,(lambda (x)
+                            (concat "<span style=\"font-style:oblique;\"" x "</span>")))
+    (font-variant-small-caps . ,(lambda (x)
+                                 (concat
+                                  "<span style=\"font-variant:small-caps;\">" x "</span>")))
+    (font-weight-bold . ,(lambda (x) (concat "<b>" x "</b>")))
+    (text-decoration-underline .
+     ,(lambda (x)
+       (concat
+        "<span style=\"text-decoration:underline;\">" x "</span>")))
+    (vertical-align-sub . ,(lambda (x) (concat "<sub>" x "</sub>")))
+    (vertical-align-sup . ,(lambda (x) (concat "<sup>" x "</sup>")))
+    (vertical-align-baseline . ,(lambda (x) (concat "<span style=\"baseline\">" x "</span>")))
+    (display-left-margin . ,(lambda (x) (concat "\n    <div class=\"csl-left-margin\">"
+                                               x "</div>")))
+    (display-right-inline . ,(lambda (x) (concat "<div class=\"csl-right-inline\">"
+                                                x "</div>\n  ")))
+    (display-block . ,(lambda (x) (concat "\n\n    <div class=\"csl-block\">"
+                                         x "</div>\n")))
+    (display-indent . ,(lambda (x) (concat "<div class=\"csl-indent\">" x "</div>\n  ")))))
+
+(defun citeproc-fmt--html-bib-formatter (items _bib-format)
+  "Return a html bibliography from already formatted ITEMS."
+  (concat "<div class=\"csl-bib-body\">\n"
+         (mapconcat (lambda (i)
+                      (concat "  <div class=\"csl-entry\">" i "</div>\n"))
+                    items
+                    "")
+         "</div>"))
+
+;; LaTeX
+
+(defconst citeproc-fmt--latex-esc-regex
+  (regexp-opt '("_" "&" "#" "%" "$"))
+  "Regular expression matching characters to be escaped in LaTeX output.")
+
+(defun citeproc-fmt--latex-escape (s)
+  "Return the LaTeX-escaped version of string S."
+  (replace-regexp-in-string citeproc-fmt--latex-esc-regex "\\\\\\&" s))
+
+(defun citeproc-fmt--latex-href (text uri)
+  (let ((escaped-uri (replace-regexp-in-string "%" "\\\\%" uri)))
+   (if (string-prefix-p "http" text)
+       (concat "\\url{" escaped-uri "}")
+     (concat "\\href{" escaped-uri "}{" text "}"))))
+
+(defconst citeproc-fmt--latex-alist
+  `((unformatted . ,#'citeproc-fmt--latex-escape)
+    (href . ,#'citeproc-fmt--latex-href)
+    (font-style-italic . ,(lambda (x) (concat "\\textit{" x "}")))
+    (font-weight-bold . ,(lambda (x) (concat "\\textbf{" x "}")))
+    (cited-item-no . ,(lambda (x y) (concat "\\citeprocitem{" y "}{" x "}")))
+    (bib-item-no . ,(lambda (x y) (concat "\\hypertarget{citeproc_bib_item_" y "}{"
+                                         x "}")))
+    (font-variant-small-caps . ,(lambda (x) (concat "\\textsc{" x "}")))
+    (text-decoration-underline . ,(lambda (x) (concat "\\underline{" x "}")))
+    (vertical-align-sup . ,(lambda (x) (concat "\\textsuperscript{" x "}")))
+    (display-left-margin . ,(lambda (x) (concat x " ")))
+    (vertical-align-sub . ,(lambda (x) (concat "\\textsubscript{" x "}")))
+    (font-style-oblique . ,(lambda (x) (concat "\\textsl{" x "}")))))
+
+;; Org-LaTeX
+
+(defconst citeproc-fmt--org-latex-alist
+  `((unformatted . ,#'citeproc-fmt--latex-escape)
+    (href . ,#'citeproc-fmt--latex-href)
+    (font-style-italic . ,(lambda (x) (concat "\\textit{" x "}")))
+    (font-weight-bold . ,(lambda (x) (concat "\\textbf{" x "}")))
+    (cited-item-no . ,(lambda (x y) (concat "\\cslcitation{" y "}{" x "}")))
+    (bib-item-no . ,(lambda (x y) (concat "\\cslbibitem{" y "}{" x "}")))
+    (font-variant-small-caps . ,(lambda (x) (concat "\\textsc{" x "}")))
+    (text-decoration-underline . ,(lambda (x) (concat "\\underline{" x "}")))
+    (vertical-align-sup . ,(lambda (x) (concat "\\textsuperscript{" x "}")))
+    (display-left-margin . ,(lambda (x) (concat "\\cslleftmargin{" x "}")))
+    (display-right-inline . ,(lambda (x) (concat "\\cslrightinline{" x "}")))
+    (display-block . ,(lambda (x) (concat "\\cslblock{" x "}")))
+    (display-indent . ,(lambda (x) (concat "\\cslindent{" x "}")))
+    (vertical-align-sub . ,(lambda (x) (concat "\\textsubscript{" x "}")))
+    (font-style-oblique . ,(lambda (x) (concat "\\textsl{" x "}")))))
+
+(defun citeproc-fmt--org-latex-bib-formatter (items bib-format)
+  "Return an Org LaTeX bibliography of ITEMS formatted in BIB-FORMAT."
+  (let-alist bib-format
+    (let ((hanging-indent (if .hanging-indent "1" "0"))
+         (entry-spacing (if (and .entry-spacing (<= 1 .entry-spacing))
+                            (number-to-string (- .entry-spacing 1))
+                          "0")))
+      (concat "\\begin{cslbibliography}{" hanging-indent "}{" entry-spacing "}\n"
+             (mapconcat #'identity items "\n\n")
+             "\n\n\\end{cslbibliography}\n"))))
+
+;; Org-ODT
+
+(defconst citeproc-fmt--org-odt-alist
+  `((unformatted . citeproc-fmt--xml-escape)
+    (href . ,(lambda (x y) (concat "<text:a xlink:type=\"simple\" xlink:href=\""
+                                  y "\">" x "</text:a>")))
+    (cited-item-no
+     . ,(lambda (x y) (concat "<text:a xlink:type=\"simple\" xlink:href=\"#citeproc_bib_item_"
+                             y "\">" x "</text:a>")))
+    (bib-item-no
+     . ,(lambda (x y)
+         (concat "<text:bookmark-start text:name=\"OrgXref.citeproc_bib_item_" y "\"/>"
+                 "<text:bookmark text:name=\"citeproc_bib_item_" y "\"/>"
+                 "<text:bookmark-end text:name=\"OrgXref.citeproc_bib_item_" y "\"/>" x)))
+    (font-style-italic
+     . ,(lambda (x) (concat "<text:span text:style-name=\"Emphasis\">" x "</text:span>")))
+    (font-style-oblique
+     . ,(lambda (x) (concat "<text:span text:style-name=\"Emphasis\">" x "</text:span>")))
+    ;; NOTE: small caps support requires the availability of the OrgSmallcaps ODT style
+    ;; this requires an addition to or replacement of the default OrgOdtStyles.xml
+    (font-variant-small-caps
+     . ,(lambda (x) (concat "<text:span text:style-name=\"OrgSmallCaps\">" x "</text:span>")))
+    (font-weight-bold
+     . ,(lambda (x) (concat "<text:span text:style-name=\"Bold\">" x "</text:span>")))
+    (text-decoration-underline
+     . ,(lambda (x) (concat "<text:span text:style-name=\"Underline\">" x "</text:span>")))
+    (vertical-align-sub
+     . ,(lambda (x) (concat "<text:span text:style-name=\"OrgSubscript\">" x "</text:span>")))
+    (vertical-align-sup
+     . ,(lambda (x)
+         (concat "<text:span text:style-name=\"OrgSuperscript\">" x "</text:span>")))
+    ;; TODO:
+    ;; - display-left-margin 
+    ;; - display-right-inline 
+    ;; - display-block 
+    ;; - display-indent 
+    ))
+
+(defun citeproc-fmt--org-odt-bib-formatter (items _bib-format)
+  "Return a html bibliography from already formatted ITEMS."
+  (mapconcat (lambda (i)
+              (concat "<text:p text:style-name=\"Text_20_body\">" i "</text:p>"))
+            items
+            "\n"))
+
+;; Define the formatters alist
+
+(defvar citeproc-fmt--formatters-alist
+  `((org-odt . ,(citeproc-formatter-create
+                :rt (citeproc-formatter-fun-create citeproc-fmt--org-odt-alist)
+                :bib #'citeproc-fmt--org-odt-bib-formatter
+                ))
+    (html . ,(citeproc-formatter-create
+             :rt (citeproc-formatter-fun-create citeproc-fmt--html-alist)
+             :bib #'citeproc-fmt--html-bib-formatter))
+    (csl-test . ,(citeproc-formatter-create
+                 :rt (citeproc-formatter-fun-create citeproc-fmt--csl-test-alist)
+                 :bib #'citeproc-fmt--html-bib-formatter
+                 :no-external-links t))
+    (raw . ,(citeproc-formatter-create :rt #'identity :bib (lambda (x _) x)))
+    (org . ,(citeproc-formatter-create :rt #'citeproc-fmt--org-format-rt))
+    (org-latex . ,(citeproc-formatter-create
+                  :rt (citeproc-formatter-fun-create citeproc-fmt--org-latex-alist)
+                  :bib #'citeproc-fmt--org-latex-bib-formatter))
+    (latex . ,(citeproc-formatter-create
+              :rt (citeproc-formatter-fun-create citeproc-fmt--latex-alist)
+              :bib (lambda (x _) (concat (mapconcat #'identity x "\n\n")
+                                         "\\bigskip"))))
+    (plain . ,(citeproc-formatter-create :rt #'citeproc-rt-to-plain
+                                        :no-external-links t)))
+  "Alist mapping supported output formats to formatter structs.")
+
+(defun citeproc-formatter-for-format (format)
+  "Return the formatter struct belonging to FORMAT.
+FORMAT is a symbol"
+  (if-let ((formatter (alist-get format citeproc-fmt--formatters-alist)))
+      formatter
+    (error "No formatter for citeproc format `%s'" format)))
+
+(provide 'citeproc-formatters)
+
+;;; citeproc-formatters.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-generic-elements.el b/elpa/citeproc-20230228.1414/citeproc-generic-elements.el
new file mode 100644 (file)
index 0000000..2d1a339
--- /dev/null
@@ -0,0 +1,151 @@
+;;; citeproc-generic-elements.el --- render generic CSL elements -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions corresponding to the generic CSL rendering elements cs:layout,
+;; cs:group and cs:text. With the exception of `citeproc--layout' they return a
+;; (CONTENT . CONTENT-TYPE) pair, where CONTENT is the rendered rich-text output
+;; and CONTENT-TYPE is one of the symbols `text-only', `empty-vars' and
+;; `present-var.' In contrast, `citeproc--layout' returns only the rendered
+;; rich-text content.
+
+;;; Code:
+
+(require 'dash)
+(require 'let-alist)
+(require 's)
+
+(require 'citeproc-rt)
+(require 'citeproc-context)
+(require 'citeproc-macro)
+
+(defun citeproc--layout (attrs context &rest body)
+  "Render the content of a layout element with ATTRS and BODY."
+  (let* ((attrs (if (eq (citeproc-context-mode context) 'bib) attrs
+                 nil)) ; No attrs if mode is cite -- they are used for citations
+        (spliced-body (citeproc-lib-splice-into body 'splice))
+        (suffix (alist-get 'suffix attrs))
+        (attrs-wo-suffix (--remove (eq (car it) 'suffix) attrs))
+        (rendered-body (--map (car it) spliced-body)))
+    ;; Handle second-field align
+    (when (and (alist-get 'second-field-align (citeproc-context-opts context))
+              (> (length rendered-body) 1))
+      (setq rendered-body `((((display . "left-margin")) ,(car rendered-body))
+                           (((display . "right-inline")) ,@(cdr rendered-body)))))
+    (let* ((affix-rendered (citeproc-rt-render-affixes
+                           (citeproc-rt-dedup (citeproc-rt-join-formatted attrs-wo-suffix rendered-body
+                                                                          context))))
+          (last-elt (and (listp affix-rendered) (-last-item affix-rendered)))
+          (last-display (and (consp last-elt) (car last-elt)
+                             (--any-p (eq (car it) 'display) (car last-elt)))))
+      (when suffix
+       (if last-display
+           ;; If the last element has a display attribute then we have to append the
+           ;; suffix string to this last element
+           (setf (nth (1- (length affix-rendered)) affix-rendered)
+                 (-snoc (-last-item affix-rendered) suffix))
+         ;; Else we simply append it to the already rendered content
+         (setq affix-rendered (if (listp affix-rendered)
+                                  (-snoc affix-rendered suffix)
+                                (concat affix-rendered suffix)))))
+      affix-rendered)))
+
+(defun citeproc--group (attrs context &rest body)
+  "Render the content of a group element with ATTRS and BODY."
+  (-let* ((spliced-body (citeproc-lib-splice-into body 'splice))
+         (types (--map (cdr it) spliced-body))
+         (type (cond ((--all? (eq it 'text-only) types)
+                      'text-only)
+                     ((--any? (eq it 'present-var) types)
+                      'present-var)
+                     (t 'empty-vars))))
+    (cons (if (or (eq type 'text-only)
+                 (eq type 'present-var))
+             (citeproc-rt-join-formatted attrs (--map (car it) spliced-body) context)
+           nil)
+         type)))
+
+(defconst citeproc-generic-elements--url-prefix-re "https?://\\S *\\'"
+  "Regex matching an URL prefix at the end of a string.")
+
+(defun citeproc--text (attrs context &rest _body)
+  "Render the content of a text element with ATTRS and BODY."
+  (let-alist attrs
+    (let ((content nil)
+         (type 'text-only)
+         (no-external-links (citeproc-context-no-external-links context)))
+      (cond (.value (setq content .value))
+           (.variable
+            (let ((val (citeproc-var-value (intern .variable) context (citeproc-lib-intern
+                                                                       .form))))
+              (setq content val)
+              (cond
+               (val (let ((var (intern .variable)))
+                      (setq type 'present-var)
+                      (push `(rendered-var . ,var) attrs)
+                      (when (and (not no-external-links)
+                                 (memq var citeproc--linked-vars))
+                        (let ((target
+                               (concat
+                                (alist-get var citeproc--link-prefix-alist
+                                           "")
+                                content)))
+                          (-when-let (match-pos
+                                      (and .prefix (s-matched-positions-all
+                                                     citeproc-generic-elements--url-prefix-re
+                                                     .prefix)))
+                            ;; If the prefix ends with an URL then it is moved
+                            ;; from the prefix to the rendered variable
+                            ;; content.
+                            (let ((start (caar match-pos)))
+                              (setq content (concat (substring .prefix start) content))
+                              (push (cons 'prefix (substring .prefix 0 start))
+                                    attrs)))
+                          (push (cons 'href target) attrs)))))
+               ;; Don't report empty var for year-suffix, see issue #70.
+               ((not (string= .variable "year-suffix")) (setq type 'empty-vars)))))
+           (.term (setq .form (if .form (intern .form) 'long)
+                         .plural (if (or (not .plural)
+                                          (string= .plural "false"))
+                                      'single 'multiple)
+                         content (let ((cont (citeproc-term-inflected-text
+                                              .term .form .plural context)))
+                                   ;; Annotate the 'no date' term as if it'd be
+                                   ;; the value of the 'issue' variable to
+                                   ;; handle implicit year suffix addition and
+                                   ;; suppression issues.
+                                   (if (string= .term "no date")
+                                       (progn
+                                         (setq type 'present-var)
+                                         `(((rendered-var . issued)) ,cont))
+                                     cont))))
+           (.macro (let ((macro-val (citeproc-macro-output .macro context)))
+                      (setq content (car macro-val))
+                      (setq type (cdr macro-val)))))
+      ;; We stop if only the title had to be rendered.
+      (let ((result (cons (citeproc-rt-format-single attrs content context) type)))
+       (citeproc-lib-maybe-stop-rendering
+        'title context result (or (and .variable (intern .variable)) t))))))
+
+(provide 'citeproc-generic-elements)
+
+;;; citeproc-generic-elements.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-itemdata.el b/elpa/citeproc-20230228.1414/citeproc-itemdata.el
new file mode 100644 (file)
index 0000000..bbb62f7
--- /dev/null
@@ -0,0 +1,102 @@
+;;; citeproc-itemdata.el --- represent and access bibliography items -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Structure type and functions to handle data about bibliography items.
+
+;;; Code:
+
+(require 'citeproc-rt)
+(require 'citeproc-context)
+
+(cl-defstruct (citeproc-itemdata (:constructor citeproc-itemdata-create))
+  "Struct for storing bibliography item data.
+VARVALS is an alist containg variable-name symbols as keys and
+  their values for the item as values,
+RAWCITE is the cached cite of the item in internal rich-text
+  format,
+RC-UPTODATE is t iff the RAWCITE field is up-to-date,
+RAWBIBITEM is the cached bibliograhy item in internal rich-text
+  format.
+SORT-KEY is the bibliography sort-key of the item,
+OCCURRED-BEFORE is used during bibliography generation to
+  indicate whether the item was referred to earlier. If the first
+  occurrence is in a note then the actual value is the
+  note-number,
+DISAMB-POS contains the position on which cite disambiguation is
+  based. Possible values are 'first, 'ibid and 'subsequent,
+SUBBIB-NOS is a list of numeric indexes of sub-bibliographies
+  in which the item occurs,
+UNCITED is t iff the item has no associated citation."
+  varvals rawcite rawbibitem rc-uptodate sort-key occurred-before
+  disamb-pos subbib-nos uncited)
+
+(defun citeproc-itd-getvar (itd var)
+  "Return itemdata ITD's value for VAR ."
+  (alist-get var (citeproc-itemdata-varvals itd)))
+
+(defun citeproc-itd-setvar (itd var val)
+  "Set itemdata ITD's value for VAR to VAL."
+  (setf (alist-get var (citeproc-itemdata-varvals itd) nil t) val
+       (citeproc-itemdata-rc-uptodate itd) nil))
+
+(defun citeproc-itd-rt-cite (itd style)
+  "Return the rich-text cite of itemdata ITD using STYLE."
+  (if (citeproc-itemdata-rc-uptodate itd)
+      (citeproc-itemdata-rawcite itd)
+    (let ((rc (citeproc-render-varlist-in-rt
+              (cons (cons 'position (citeproc-itemdata-disamb-pos itd))
+                    (citeproc-itemdata-varvals itd))
+              style
+              'cite 'display 'no-links t)))
+      (setf (citeproc-itemdata-rawcite itd) rc
+           (citeproc-itemdata-rc-uptodate itd) t)
+      rc)))
+
+(defun citeproc-itd-plain-cite (itd style)
+  "Return the plain text cite of itemdata ITD using STYLE."
+  (citeproc-rt-to-plain (citeproc-itd-rt-cite itd style)))
+
+(defun citeproc-itd-namevars (itd style)
+  "Rendered namevars in the cite of itemdata ITD using STYLE."
+  (citeproc-rt-rendered-name-vars (citeproc-itd-rt-cite itd style)))
+
+(defun citeproc-itd-nameids (itd style)
+  "Rendered name ids in the cite of itemdata ITD using STYLE."
+  (citeproc-rt-rendered-name-ids (citeproc-itd-rt-cite itd style)))
+
+(defun citeproc-itd-update-disamb-pos (itd pos)
+  "Update the highest position of ITD with position POS."
+  (let ((old (citeproc-itemdata-disamb-pos itd)))
+    (unless (eq old 'subsequent)
+      (let ((new (pcase pos
+                  ('first 'first)
+                  ((or 'ibid 'ibid-with-locator) 'ibid)
+                  (_ 'subsequent))))
+       (setf (citeproc-itemdata-disamb-pos itd)
+             (cond ((memq old '(nil first)) new)
+                   ((eq new 'subsequent) 'subsequent)
+                   (t 'ibid)))))))
+
+(provide 'citeproc-itemdata)
+
+;;; citeproc-itemdata.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-itemgetters.el b/elpa/citeproc-20230228.1414/citeproc-itemgetters.el
new file mode 100644 (file)
index 0000000..0d0a618
--- /dev/null
@@ -0,0 +1,188 @@
+;; citeproc-itemgetters.el --- functions for constructing itemgetters -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions for constructing various types of bibliographic itemgetter
+;; functions. The returned itemgetter functions can, in turn, be used to create
+;; `citeproc-style' and `citeproc-proc' structures.
+
+;;; Code:
+
+(require 'dash)
+(require 'org)
+;; Handle the fact that org-bibtex has been renamed to ol-bibtex -- for the time
+;; being we support both feature names.
+(or (require 'ol-bibtex nil t)
+    (require 'org-bibtex))
+(require 'json)
+(require 'bibtex)
+(require 'parsebib)
+
+(require 'citeproc-bibtex)
+(require 'citeproc-biblatex)
+
+(defun citeproc-itemgetters--parsebib-buffer (entries strings)
+  "Parse a BibTeX/biblatex buffer with Parsebib."
+  ;; Note: this is needed to support different Parsebib versions in use.
+  (cond ((fboundp 'parsebib-parse-buffer)
+        (parsebib-parse-buffer entries strings t t))
+       ((fboundp 'parsebib-parse-bib-buffer)
+        (parsebib-parse-bib-buffer :entries entries :strings strings
+                                   :expand-strings t :inheritance t))
+       (t (error "No Parsebib buffer parsing function is available"))))
+
+(defun citeproc-hash-itemgetter-from-csl-json (file)
+  "Return a hash-based getter for csl json bibliography FILE."
+  (let* ((json-array-type 'list)
+        (json-key-type 'symbol)
+        (item-list (json-read-file file))
+        (hash (make-hash-table :test 'equal)))
+    (--each item-list
+      (puthash (alist-get 'id it) it hash))
+    (lambda (itemids) (--map (cons it (gethash it hash))
+                            itemids))))
+
+(defun citeproc-itemgetter-from-csl-json (file)
+  "Return an item-getter for csl json bibliography FILE."
+  (lambda (itemids)
+    (let* ((json-array-type 'list)
+          (json-key-type 'symbol)
+          (item-list (json-read-file file))
+          result)
+      (dolist (item item-list result)
+       (let ((id (alist-get 'id item)))
+         (when (member id itemids)
+           (push (cons id item) result)))))))
+
+(defun citeproc-itemgetter-from-bibtex (file-or-files)
+  "Return a getter for BibTeX bibliography FILE-OR-FILES."
+  (if (listp file-or-files)
+      (lambda (itemids)
+       (let (result
+             (remaining-ids (cl-copy-list itemids))
+             (remaining-files file-or-files))
+         (while (and remaining-ids remaining-files)
+           (let ((file (pop remaining-files)))
+            (with-temp-buffer
+              (insert-file-contents file)
+              (goto-char (point-min))
+              (bibtex-set-dialect 'BibTeX t)
+              (bibtex-map-entries
+               (lambda (key _beg _end)
+                 (when (member key itemids)
+                   (push (cons key (citeproc-bt-entry-to-csl (bibtex-parse-entry)))
+                         result)
+                   (setq remaining-ids (delete key remaining-ids))))))))
+         result))
+    (lambda (itemids)
+      (let (result)
+       (with-temp-buffer
+         (insert-file-contents file-or-files)
+         (goto-char (point-min))
+         (bibtex-set-dialect 'BibTeX t)
+         (bibtex-map-entries
+          (lambda (key _beg _end)
+            (when (member key itemids)
+              (push (cons key (citeproc-bt-entry-to-csl (bibtex-parse-entry)))
+                    result)))))
+       result))))
+
+(defun citeproc-itemgetter-from-org-bibtex (file-or-files)
+  "Return a getter for org-bibtex bibliography FILE-OR-FILES."
+  (let ((files (if (listp file-or-files)
+                  file-or-files
+                (list file-or-files))))
+   (lambda (itemids)
+     (let (result)
+       (org-map-entries
+       (lambda ()
+         (-when-let (key-w-entry (citeproc-bt-from-org-headline itemids))
+           (push (cons (car key-w-entry)
+                       (citeproc-bt-entry-to-csl (cdr key-w-entry)))
+                 result)))
+       t files)
+       result))))
+
+(defun citeproc-hash-itemgetter-from-any (file-or-files &optional no-sentcase-wo-langid)
+  "Return a getter for FILE-OR-FILES in any supported format.
+The format is determined on the basis of file extensions.
+Supported formats:
+- CSL-JSON (.json extension) the recommended native format;
+- BibTeX/biblatex (.bib or .bibtex extension),
+- org-bibtex (.org extension).
+If NO-SENTCASE-WO-LANGID is non-nil then title fields in items
+without a `langid' field are not converted to sentence-case."
+  (let ((files (if (listp file-or-files)
+                  file-or-files
+                (list file-or-files)))
+       (cache (make-hash-table :test #'equal))
+       (bt-entries (make-hash-table :test #'equal))
+       (bt-strings (make-hash-table :test #'equal)))
+    (dolist (file files)
+      (pcase (file-name-extension file)
+        ("json"
+         (let ((json-array-type 'list)
+               (json-key-type 'symbol))
+           (dolist (item (json-read-file file))
+             (puthash (cdr (assq 'id item)) item cache))))
+        ((and (or "bib" "bibtex") ext)
+         (with-temp-buffer
+          (insert-file-contents file)
+          (bibtex-set-dialect (if (string= ext "bib") 'biblatex 'BibTeX) t)
+          (citeproc-itemgetters--parsebib-buffer bt-entries bt-strings)))
+       ("org"
+        (org-map-entries
+         (lambda ()
+           (-when-let (key-w-entry (citeproc-bt-from-org-headline))
+             (condition-case err
+                 (puthash (car key-w-entry) (citeproc-blt-entry-to-csl
+                                             (cdr key-w-entry))
+                          cache)
+               (error
+                (user-error
+                 "Couldn't parse the bib(la)tex entry with key '%s', the error was: %s" 
+                 (car key-w-entry) err)))))
+         t (list file)))
+        (ext
+         (user-error "Unknown bibliography extension: %S" ext))))
+    (maphash
+     (lambda (key entry)
+       (condition-case err
+          (puthash key (citeproc-blt-entry-to-csl entry nil no-sentcase-wo-langid)
+                   cache)
+        (error
+         (user-error
+          "Couldn't parse the bib(la)tex entry with key '%s', the error was: %s"
+          key err))))
+     bt-entries)
+    (lambda (x)
+      (pcase x
+       ('itemids
+        (hash-table-keys cache))
+       ((pred listp) (mapcar (lambda (id)
+                               (cons id (gethash id cache)))
+                             x))
+       (_ (error "Unsupported citeproc itemgetter retrieval method"))))))
+
+(provide 'citeproc-itemgetters)
+
+;;; citeproc-itemgetters.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-lib.el b/elpa/citeproc-20230228.1414/citeproc-lib.el
new file mode 100644 (file)
index 0000000..1d626c2
--- /dev/null
@@ -0,0 +1,164 @@
+;;; citeproc-lib.el --- misc functions and variables for citeproc-el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; General utility functions used in citeproc-el.
+
+;;; Code:
+
+(require 'dash)
+(require 's)
+
+(defconst citeproc--number-vars
+  '(chapter-number citation-number collection-number edition first-reference-note-number
+                  issue number number-of-pages number-of-volumes page page-first
+                  part-number printing-number section supplement-number version volume)
+  "CSL number variables."
+  ;; Note: `locator', which is also on the official list, is omitted because
+  ;; it's treated specially in the code.
+  )
+
+(defconst citeproc--date-vars
+  '(accessed available-date event-date issued original-date submitted)
+  "CSL date variables.")
+
+(defconst citeproc--name-vars
+  '(author chair collection-editor compiler composer container-author contributor
+          curator director editor editorial-director editor-translator executive-producer
+          guest host illustrator interviewer narrator organizer original-author
+          performer producer recipient reviewed-author script-writer series-creator
+          translator)
+  "CSL name variables.")
+
+(defconst citeproc--linked-vars
+  '(DOI PMCID PMID URL)
+  "Variables whose rendered content should be linked.
+The ordering is according to priority ")
+
+(defconst citeproc--link-prefix-alist
+  '((DOI .  "https://doi.org/")
+    (PMID . "https://www.ncbi.nlm.nih.gov/pubmed/")
+    (PMCID . "https://www.ncbi.nlm.nih.gov/pmc/articles/"))
+  "Alist mapping variable names to uri prefixes.")
+
+(defun citeproc-lib-parse-xml-file (file)
+  "Return the parsed xml representation of FILE."
+  (with-temp-buffer
+    (insert-file-contents file)
+    (libxml-parse-xml-region (point-min) (point-max))))
+
+(defun citeproc-lib-remove-xml-comments (tree)
+  "Remove comments from xml TREE."
+  (let ((head (car tree))
+       (attrs (cadr tree))
+       (body (cddr tree))
+       result)
+    (while body
+      (pcase (car body)
+       ((pred atom) (push (pop body) result))
+       (`(comment . ,_) (pop body))
+       (_ (push (citeproc-lib-remove-xml-comments (pop body)) result))))
+    (let ((full-result (cons head (cons attrs (nreverse result)))))
+      ;; Handle the problem of the top element added by the libxml parser when
+      ;; there is a comment after the xml declaration.
+      (if (eq (car full-result) 'top)
+         (caddr full-result)
+       full-result))))
+
+(defun citeproc-lib-parse-html-frag (s)
+  "Return the parsed representation of html in string S."
+  (with-temp-buffer
+    (insert s)
+    (libxml-parse-html-region (point-min) (point-max))))
+
+(defun citeproc-lib-intern (s)
+  "Intern S if it is a string, return nil if it is nil."
+  (cond ((not s) nil)
+       ((stringp s) (intern s))
+       (t (error "Function citeproc-lib-intern was called with an argument that is neither string nor nil"))))
+
+(defun citeproc-lib-named-parts-to-alist (e)
+  "Collect the attrs of parsed xml element E's enclosed elements.
+The attributes are collected into an alist consisting
+of (PARTNAME . ATTRS) pairs, where PARTNAME is the value of the
+enclosed element's `name' attr"
+  (--map (cons (intern (alist-get 'name it))
+              (assq-delete-all 'name it))
+        (mapcar #'cadr (-remove #'stringp (cddr e)))))
+
+(defun citeproc-lib-lex-compare (l1 l2 cmp-fun sort-orders)
+  "Whether list L1 lexicographically precedes list L2.
+CMP-FUN is a three-valued (1, 0, -1) comparator function,
+SORT-ORDERS is a list of sort orders (see the bib- and
+cite-sort-orders slots of `citeproc-style' for details). Return t
+iff L1 is strictly ordered before L2, nil otherwise."
+  (unless sort-orders
+    (setq sort-orders (make-list (length l1) t)))
+  (let (result)
+    (while (and l1 (not result))
+      (let ((comp
+            (funcall cmp-fun (pop l1) (pop l2) (not (pop sort-orders)))))
+       (unless (= comp 0)
+         (setq result comp))))
+    (equal result 1)))
+
+(defun citeproc-lib-splice-into (list tag)
+  "Splice elements with car TAG into LIST."
+  (let (result)
+    (dolist (elt list)
+      (if (and (consp elt) (eq tag (car elt)))
+         (dolist (e (cdr elt))
+           (push e result))
+       (push elt result)))
+    (nreverse result)))
+
+(defun citeproc-lib-add-splice-tag (list tag)
+  "Add TAG as car if LIST is not a singleton.
+Return the first element if LIST is singleton."
+  (if (cdr list) (cons tag list) (car list)))
+
+(defun citeproc-lib-numeric-p (val)
+  "Return whether VAL is numeric content.
+VAL has numeric content if it is a number or a string containing
+numeric content."
+  (or (numberp val)
+      (and (stringp val)
+          (s-matches-p "\\`[[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\(\\( *\\([,&-]\\|--\\) *\\)?[[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\)?\\'"
+                       val))))
+
+(defun citeproc-lib-maybe-stop-rendering
+    (trigger context result &optional var)
+  "Stop rendering if a (`stop-rendering-at'. TRIGGER) pair is present in CONTEXT.
+In case of stopping return with RESULT. If the optional VAR
+symbol is non-nil then rendering is stopped only if VAR is eq to
+TRIGGER."
+  (if (and (eq trigger (alist-get 'stop-rendering-at (citeproc-context-vars context)))
+          (or (not var) (eq var trigger))
+          (eq (cdr result) 'present-var))
+      (let ((rt-result (car result)))
+       (push '(stopped-rendering . t) (car rt-result))
+       (throw 'stop-rendering (citeproc-rt-render-affixes rt-result)))
+    result))
+
+(provide 'citeproc-lib)
+
+;;; citeproc-lib.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-locale.el b/elpa/citeproc-20230228.1414/citeproc-locale.el
new file mode 100644 (file)
index 0000000..aee1691
--- /dev/null
@@ -0,0 +1,93 @@
+;; citeproc-locale.el --- CSL locale related functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2022 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; In addition to some locale handling helpers, this file provides the function
+;; `citeproc-locale-getter-from-dir', which constructs locale getter functions
+;; that retrieve locales from a given directory.
+
+;;; Code:
+
+(require 'dash)
+(require 'f)
+(require 's)
+
+(require 'citeproc-lib)
+(require 'citeproc-term)
+
+(defconst citeproc-locale--default-variants-alist
+  '(("af" . "ZA") ("ca" . "AD") ("cs" . "CZ") ("cy" . "GB")
+    ("da" . "DK") ("en" . "US") ("el" . "GR") ("et" . "EE")
+    ("fa" . "IR") ("he" . "IR") ("ja" . "JP") ("km" . "KH")
+    ("ko" . "KR") ("nb" . "NO") ("nn" . "NO") ("sl" . "SI")
+    ("sr" . "RS") ("sv" . "SE") ("uk" . "UA") ("vi" . "VN")
+    ("zh" . "CN"))
+  "Alist mapping locales to their default variants.
+Only those locales are given for which the default variant is not
+simply the result of upcasing.")
+
+(defconst citeproc-locale--simple-locales
+  '("la" "eu" "ar")
+  "List of simple locale names (without dash).")
+
+(defun citeproc-locale--extend (loc)
+  "Extend simple locale LOC to default variant."
+  (let ((variant (assoc-default loc citeproc-locale--default-variants-alist)))
+    (concat loc "-" (or variant (s-upcase loc)))))
+
+(defun citeproc-locale--compatible-p (l1 l2)
+  "Whether locales L1 and L2 are compatible."
+  (or (not (and l1 l2))
+      (s-prefix-p l1 l2)
+      (s-prefix-p l2 l1)))
+
+(defun citeproc-locale-getter-from-dir (dir)
+  "Return a locale getter getting parsed locales from a local DIR.
+If the requested locale couldn't be read then return the parsed
+en-US locale, which must exist."
+  (let ((default-loc-file (f-join dir "locales-en-US.xml")))
+    (lambda (loc)
+      (let* ((ext-loc (if (or (member loc citeproc-locale--simple-locales)
+                             (s-contains-p "-" loc))
+                         loc
+                       (citeproc-locale--extend loc)))
+            (loc-file (concat dir "/locales-" ext-loc ".xml"))
+            (loc-available (f-readable-p loc-file)))
+       (citeproc-lib-remove-xml-comments
+        (citeproc-lib-parse-xml-file
+         (if loc-available loc-file
+          (if (not (f-readable-p default-loc-file))
+              (error
+               "The default CSL locale file %s doesn't exist or is unreadable"
+                     default-loc-file)   
+            default-loc-file))))))))
+
+(defun citeproc-locale-termlist-from-xml-frag (frag)
+  "Transform xml FRAG representing citeproc--terms into a citeproc-term list."
+  (--mapcat (if (eq 'term (car it))
+               (citeproc-term--from-xml-frag (cdr it))
+             nil)
+           frag))
+
+(provide 'citeproc-locale)
+
+;;; citeproc-locale.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-macro.el b/elpa/citeproc-20230228.1414/citeproc-macro.el
new file mode 100644 (file)
index 0000000..d4b6ddc
--- /dev/null
@@ -0,0 +1,58 @@
+;; citeproc-macro.el --- functions to render CSL macros -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions to render the output of CSL macros.
+
+;;; Code:
+
+(require 'citeproc-lib)
+(require 'citeproc-rt)
+(require 'citeproc-context)
+
+;;; For macro evaluation
+(defun citeproc--macro (attrs context &rest body)
+  "Render the content of a macro element with ATTRS and BODY."
+  (let* ((spliced-body (citeproc-lib-splice-into body 'splice))
+        (val (citeproc-rt-typed-join attrs spliced-body context)))
+    (if (eq 'empty-vars (cdr val))
+       (cons nil 'text-only)
+      val)))
+
+(defun citeproc-macro-output (macro context)
+  "Return the output of MACRO.
+MACRO is the macro's name as a string and the returned value is a
+(RICH-TEXT-CONTENT . CONTENT-TYPE) cons cell."
+  (let ((macro-fun (assoc-default macro (citeproc-context-macros context))))
+    (if macro-fun
+       (funcall macro-fun context)
+      (error "There is no macro called `%s' in style" macro))))
+
+(defun citeproc-macro-output-as-text (macro context)
+  "Return the output of MACRO as plain text.
+MACRO is the macro's name as a string."
+  (citeproc-rt-to-plain (citeproc-rt-render-affixes
+                        (car (citeproc-macro-output macro context)))))
+
+(provide 'citeproc-macro)
+
+;;; citeproc-macro.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-name.el b/elpa/citeproc-20230228.1414/citeproc-name.el
new file mode 100644 (file)
index 0000000..6825134
--- /dev/null
@@ -0,0 +1,452 @@
+;;; citeproc-name.el --- CSL name and label rendering -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions to render CSL name and label elements.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'let-alist)
+(require 'dash)
+(require 's)
+
+(require 'citeproc-lib)
+(require 'citeproc-s)
+(require 'citeproc-rt)
+(require 'citeproc-context)
+(require 'citeproc-term)
+
+(defvar citeproc-name-postprocess-functions nil
+  "A list of functions to postprocess rendered names.
+Each function takes three arguments:
+- the rich-text rendering of a name to be post-processed,
+- the rendered name as an alist with CSL name-part
+  keys (`family', `given' etc.), and
+- the rendering context, as a `citeproc-context' structure.
+The output of each function should be the post-processed
+rich-text, and the functions are applied in the order they appear
+in the list.")
+
+;; OPTIMIZE: Name count could be sped up by only counting the names to be
+;; rendered without actually rendering them
+(defun citeproc-name-render-vars
+    (varstring attrs name-attrs name-part-attrs et-al-attrs with-label
+              label-before-names label-attrs context)
+  "Render namevars contained in VARSTRING according to the given attrs.
+VARSTRING is a string containing variable names separated by
+spaces. Labels are also rendered (with formatting according to
+LABEL-ATTRS) if WITH-LABEL is t."
+  (let* ((vars (-map 'intern (s-split " " varstring)))
+        (present-vars (--filter (citeproc-var-value it context) vars))
+        ed-trans)
+    (when (and (memq 'editor present-vars)
+              (memq 'translator present-vars)
+              (= 2 (length present-vars))
+              (equal (--map (alist-get 'name-id it)
+                            (citeproc-var-value 'editor context))
+                     (--map (alist-get 'name-id it)
+                            (citeproc-var-value 'translator context))))
+      (setq present-vars '(editor)
+           ed-trans t))
+    (unless (alist-get 'delimiter attrs)
+      (-when-let (names-delim (alist-get 'names-delimiter (citeproc-context-opts context)))
+       (push (cons 'delimiter names-delim) attrs)))
+    (if present-vars
+       (cons (citeproc-rt-join-formatted
+              attrs
+              (--map (citeproc-name--render-var it name-attrs name-part-attrs
+                                                et-al-attrs with-label
+                                                label-before-names
+                                                label-attrs
+                                                context
+                                                ed-trans)
+                     present-vars)
+              context)
+             'present-var)
+      (cons nil 'empty-vars))))
+
+(defun citeproc-name--render-var (var attrs name-part-attrs et-al-attrs with-label
+                                     label-before-names
+                                     label-attrs context &optional ed-trans)
+  "Render the value of csl name variable VAR according to given attrs.
+VAR is a symbol.
+
+Note: The label (if there is one) is prepended to the name(s) if
+the form is verb and also when the label element was before the
+names element in the style. The latter is not allowed in the
+standard, so can be considered an extension. It's supported
+because some styles rely on it, notably that of the journal
+Nature."
+  ;; Push the current add-names offset for VAR to the ATTRS
+  (-when-let (add-names-alist (citeproc-var-value 'add-names context))
+    (-when-let (add-names-val (alist-get var add-names-alist))
+      (push `(add-names . ,add-names-val) attrs)))
+  (let* ((var-value (citeproc-var-value var context))
+        (rendered-names (citeproc-name--render-names
+                         var-value attrs et-al-attrs name-part-attrs
+                         context)))
+    (when (atom rendered-names) (setq rendered-names (list nil rendered-names)))
+    (push (list 'rendered-names) (car rendered-names))
+    (push `(variable . ,(if ed-trans "editortranslator" (symbol-name var)))
+         label-attrs)
+    (let ((plural-val (alist-get 'plural label-attrs)))
+      (when (or (not plural-val) (string= plural-val "contextual"))
+       (push `(plural . ,(if (> (length var-value) 1) "always" "never"))
+             label-attrs)))
+    (if with-label
+       (let ((rendered-label (car (citeproc--label label-attrs context))))
+         (citeproc-rt-join-formatted `((rendered-var . ,var))
+                                     (if label-before-names
+                                         (list rendered-label rendered-names)
+                                       (list rendered-names rendered-label))
+                                     context))
+      (push (cons 'rendered-var var) (car rendered-names))
+      rendered-names)))
+
+(defun citeproc-name--render-names (names attrs et-al-attrs name-part-attrs context)
+  "Render NAMES according to the given attrs."
+  (let* ((all-attrs (-concat attrs (citeproc-context-opts context)))
+        (rmode (citeproc-context-render-mode context))
+        (sort-o (if (eq rmode 'sort) "all" ;; special setting for sort mode
+                  (alist-get 'name-as-sort-order all-attrs)))
+        (names-count (length names))
+        (formatted-first (citeproc-name--render (car names) attrs name-part-attrs
+                                                sort-o context)))
+    (if (= 1 names-count) formatted-first
+      (let-alist all-attrs
+       (let ((delimiter (or .delimiter .name-delimiter ", "))
+             (add-names (or .add-names 0))
+             (position (citeproc-var-value 'position context)))
+         (unless (or (null position) (eq position 'first))
+           (setq .et-al-min (or .et-al-subsequent-min .et-al-min)
+                 .et-al-use-first (or .et-al-subsequent-use-first .et-al-use-first)))
+         (setq .et-al-min (or .names-min .et-al-min)
+               .et-al-use-first (or .names-use-first .et-al-use-first)
+               .et-al-use-last (or (string= .names-use-last "true")
+                                   (string= .et-al-use-last "true")))
+         (let* ((et-al-min-val
+                 ;; If et-al should be ignored then we set this to an unreachable number.
+                 (if (alist-get 'ignore-et-al (citeproc-context-vars context))
+                     100
+                   (citeproc-s-nil-or-s-to-num .et-al-min)))
+                (et-al-use-first-val (+ add-names
+                                        (citeproc-s-nil-or-s-to-num .et-al-use-first)))
+                (et-al (and .et-al-min .et-al-use-first
+                            (>= names-count et-al-min-val)
+                            (< et-al-use-first-val names-count)))
+                (middle-end-pos (if et-al et-al-use-first-val (- names-count 1)))
+                (sort-o-latters (string= sort-o "all"))
+                (formatted-middle
+                 (if (< middle-end-pos 2)
+                     nil
+                   (citeproc-rt-join-formatted
+                    `((delimiter . ,delimiter) (prefix . ,delimiter))
+                    (--map (citeproc-name--render it attrs name-part-attrs
+                                                  sort-o-latters context)
+                           (-slice names 1 middle-end-pos))
+                    context)))
+                (last-after-inverted (or sort-o-latters
+                                         (and (string= sort-o "first")
+                                              (null formatted-middle))))
+                (last-delim (citeproc-lib-intern (if et-al .delimiter-precedes-et-al
+                                                   .delimiter-precedes-last)))
+                (last-pref (if (or (and (or (not last-delim) (eq last-delim 'contextual))
+                                        (> middle-end-pos 1))
+                                   (eq last-delim 'always)
+                                   (and (eq last-delim 'after-inverted-name)
+                                        last-after-inverted))
+                               delimiter
+                             " "))
+                (formatted-last
+                 (cond (et-al (if .et-al-use-last
+                                  (citeproc-rt-join-formatted
+                                   nil
+                                   (list
+                                    delimiter "… "
+                                    (citeproc-name--render (-last-item names)
+                                                           attrs name-part-attrs
+                                                           sort-o-latters context))
+                                   context)
+                                (citeproc-name--render-et-al (cons `(prefix . ,last-pref)
+                                                                   et-al-attrs)
+                                                             context)))
+                       (.and
+                        (let ((and-str (if (string= .and "text")
+                                           (citeproc-term-get-text "and" context)
+                                         "&")))
+                          (citeproc-rt-join-formatted
+                           `((prefix . ,last-pref))
+                           (list and-str " "
+                                 (citeproc-name--render
+                                  (-last-item names) attrs
+                                  name-part-attrs sort-o-latters context))
+                           context)))
+                       (t
+                        (citeproc-rt-join-formatted
+                         nil
+                         (list delimiter
+                               (citeproc-name--render (-last-item names)
+                                                      attrs name-part-attrs
+                                                      sort-o-latters context))
+                         context)))))
+           (citeproc-rt-join-formatted
+            (--remove (eq 'delimiter (car it)) attrs)
+            (list formatted-first formatted-middle formatted-last)
+            context)))))))
+
+(defun citeproc-name--render (name attrs name-part-attrs sort-o context)
+  "Render NAME according to the given attributes."
+  (let* ((format-attrs
+         (--filter (memq (car it) (-concat '(prefix suffix) citeproc-rt-format-attrs))
+                   attrs))
+        (result (citeproc-rt-format-single
+                 (cons `(name-id . ,(alist-get 'name-id name)) format-attrs)
+                 (citeproc-name--render-formatted
+                  (citeproc-name--format-nameparts name name-part-attrs context)
+                  attrs sort-o context)
+                 context)))
+    (dolist (fn citeproc-name-postprocess-functions)
+      (setq result (funcall fn result name context)))
+    result)) 
+
+(defun citeproc-name--parts-w-sep (c1 c2 sep context)
+  "Join name-parts in lists C1 C2 with spaces and then with SEP."
+  (let ((joined-c1 (citeproc-rt-join-formatted '((delimiter . " ")) c1 context)))
+    (if (-none-p 'cadr c2)
+       joined-c1
+      (citeproc-rt-join-formatted
+       `((delimiter . ,sep))
+       (list joined-c1
+            (citeproc-rt-join-formatted '((delimiter . " ")) c2 context))
+       context))))
+
+(defun citeproc-name--render-formatted (name-alist attrs sort-o context)
+  "Render formatted name described by NAME-ALIST according to ATTRS.
+NAME-ALIST is an alist with symbol keys corresponding to
+name-parts like `family' etc. and values are simple rich-text
+contents of the form (ATTRS CONTENT) where content must be a
+single string. SORT-O is a boolean determining whether to use
+sort order."
+  (-let* ((global-opts (citeproc-context-opts context))
+         ((&alist 'family f
+                  'given g-uninited
+                  'suffix s
+                  'dropping-particle d
+                  'non-dropping-particle n
+                  'name-id nid)
+          name-alist)
+         ((&alist 'sort-separator sort-sep
+                  'initialize init
+                  'initialize-with init-with
+                  'form form
+                  'name-form name-form)
+          (-concat attrs global-opts))
+         (sort-sep (or sort-sep ", "))
+         (init (not (string= init "false")))
+         (d-n-d (intern (alist-get 'demote-non-dropping-particle global-opts)))
+         (id (cadr nid))
+         (show-given (citeproc-name-show-givenname-level id context))
+         (form (if show-given 'long
+                 (intern (or form name-form "long"))))
+         (rmode (citeproc-context-render-mode context)))
+    (if (citeproc-name--lat-cyr-greek-p name-alist)
+       (let ((g
+              (cond ((or (null g-uninited)
+                         (and show-given (= show-given 2)))
+                     g-uninited)
+                    ((and init-with init)
+                     (list (citeproc-rt-attrs g-uninited)
+                           (citeproc-name--initialize
+                            (citeproc-rt-first-content g-uninited)
+                            init-with
+                            (string= "false"
+                                     (alist-get 'initialize-with-hyphen
+                                                global-opts)))))
+                    (init-with
+                     (list (citeproc-rt-attrs g-uninited)
+                           (citeproc-name--initials-add-suffix
+                            init-with
+                            (citeproc-rt-first-content g-uninited))))
+                    (t g-uninited))))
+         (if (eq form 'long)
+             (if sort-o
+                 (if (or (eq d-n-d 'never)
+                         (and (eq d-n-d 'sort-only) (eq rmode 'display)))
+                     (citeproc-name--parts-w-sep
+                      (citeproc-name--conc-nps n f) (list g d s) sort-sep
+                      context)
+                   (citeproc-name--parts-w-sep (list f) (list g d n s) sort-sep context))
+               (citeproc-rt-join-formatted
+                '((delimiter . " ")) `(,g ,@(citeproc-name--conc-nps
+                                             d n f) ,s)
+                context))
+           (citeproc-rt-join-formatted
+            '((delimiter . " ")) (citeproc-name--conc-nps n f) context)))
+      (if (eq form 'long)
+         (citeproc-rt-join-formatted '((delimiter . " ")) (list f g-uninited) context)
+       f))))
+
+(defun citeproc-name--conc-nps (&rest nps)
+  "Concatenate particles in name-parts NPS if they end with apostrophe."
+  (let ((nonnils (delq nil nps)))
+    (if (cdr nonnils)
+       (let* ((len (length nonnils))
+              (particle (nth (- len 2) nonnils))
+              (particle-str (if (listp particle) (cadr particle) particle)))
+         (if (string= "ʼ" (substring particle-str -1))
+             (let* ((family (car (last nonnils)))
+                    (result (list (list nil particle family))))
+               (when (> 2 len) (push (car nonnils) result))
+               result)
+           nonnils))
+      nonnils)))
+
+(defun citeproc-name--lat-cyr-greek-p (name-alist)
+  "Return t if NAME-ALIST is cyrillic/latin/greek and nil otherwise.
+NAME-ALIST is like in `citeproc-name--render-formatted'"
+  (--all-p (or (not (stringp it)) (string-match "^\\(\\cl\\|\\cy\\|\\cg\\|ʼ\\)*$"
+                                               it))
+          (-map (lambda (x)
+                  (if (listp (cdr x)) (cl-caddr x)
+                    (cdr x)))
+                name-alist)))
+
+(defun citeproc-name--initialize (names suffix &optional remove-hyphens)
+  "Initialize NAMES and add SUFFIX.
+NAMES is a string containing one or more space-separated names,
+while SUFFIX is either nil or a string (e.g. \".\"). If the
+optional REMOVE-HYPHENS is non-nil then don't keep hyphens
+between initalized given names, e.g., initialize Jean-Paul to
+J.P. instead of the default J.-P."
+  (let ((trimmed-suffix (s-trim suffix)))
+    (concat (s-join
+            suffix
+            (--map
+             (if (s-match "-" it)
+                 (citeproc-name--initialize-hyphenated it suffix remove-hyphens)
+               (s-left 1 it))
+             (s-split " +" names)))
+           trimmed-suffix)))
+
+(defun citeproc-name--initialize-hyphenated (name suffix &optional remove-hyphens)
+  "Initialize space-less but hyphenated NAME with SUFFIX.
+If the optional REMOVE-HYPHENS is non-nil then don't keep hyphens
+between the initalized given names, e.g., initialize Jean-Paul to
+J.P. instead of the default J.-P."
+  (let ((inner-suffix (s-trim suffix)))
+    (s-join (if remove-hyphens inner-suffix
+             (concat inner-suffix "-"))
+           (--map (s-left 1 it)
+                  (s-split "-" name)))))
+
+(defun citeproc-name--initials-add-suffix (suffix names)
+  "Add SUFFIX to initials in NAMES.
+NAMES is a string containing one or more space-separated names,
+while SUFFIX is a string (e.g. \".\")."
+  (let ((suffix (s-trim suffix)))
+    (mapconcat (lambda (x)
+                (if (and (cdr x) (s-match "^[[:alpha:]]$" (car x)))
+                    (concat (car x) suffix)
+                  (car x)))
+              (citeproc-s-slice-by-matches names "[ \\-]" 0 t)
+              "")))
+
+(defun citeproc-name--format-nameparts (name-alist name-part-attrs context)
+  "Format nameparts in NAME-ALIST according to NAME-PART-ATTRS.
+Return a new name alist containg the same keys with formatted
+contents."
+  (-let (((&alist 'given given-attrs
+                 'family family-attrs)
+         name-part-attrs))
+    (--map (-let (((n-part . content) it))
+            (cons n-part
+                  (cond ((and given-attrs
+                              (memq n-part '(given dropping-particle)))
+                         (citeproc-rt-format-single given-attrs content context))
+                        ((and family-attrs
+                              (memq n-part '(family non-dropping-particle)))
+                         (citeproc-rt-format-single family-attrs content context))
+                        (t (list nil content)))))
+          name-alist)))
+
+(defun citeproc-name--render-et-al (attrs context)
+  "Render the `et al' part of a name acc. to ATTRS."
+  (let ((rmode (citeproc-context-render-mode context)))
+    (if (eq rmode 'sort) ""
+      (let ((term (or (alist-get 'term attrs)
+                     "et-al")))
+       (citeproc-rt-format-single attrs
+                                  (citeproc-term-get-text term context)
+                                  context)))))
+
+(defun citeproc-name-show-givenname-level (id context)
+  "Return the disambiguation level of name with ID."
+  (alist-get id (alist-get 'show-given-names (citeproc-context-vars context))))
+
+(defun citeproc--var-plural-p (var context)
+  "Return whether the content of variable VAR is plural.
+VAR is a symbol."
+  (let ((content (citeproc-rt-to-plain (citeproc-var-value var context))))
+    (if (or (string= var "number-of-pages")
+           (string= var "number-of-volumes"))
+       (> (string-to-number content) 1)
+      (string-match-p
+       (concat "[[:digit:]] *\\([-,;–&—―]+\\|[,;]? *"
+              (citeproc-term-get-text "and" context)
+              "\\) *[a-zA-Z]?[[:digit:]]")
+       content))))
+
+(defun citeproc--label (attrs context &rest _body)
+  "Render a CSL label element with the given ATTRS in CONTEXT."
+  (-let* (((&alist 'variable variable
+                  'form form
+                  'plural plural)
+          attrs)
+         (label (intern variable))
+         (number nil))
+    (if (or (eq label 'editortranslator)
+           (and label (citeproc-var-value label context)))
+       (progn
+         (if form (setq form (intern form))
+           (setq form 'long))
+         (when (string= variable "locator")
+           (setq variable (citeproc-locator-label context)))
+         (cond ((string= plural "never") (setq number 'single))
+               ((string= plural "always") (setq number 'multiple))
+               (t (setq number
+                        (if (citeproc--var-plural-p label context)
+                            'multiple
+                          'single))))
+         ;; Add rendered locator label info in cite mode.
+         (when (and (eq label 'locator)
+                    (eq (citeproc-context-mode context) 'cite))
+          (push '(rendered-locator-label . t) attrs))
+         (cons (citeproc-rt-format-single attrs (citeproc-term-inflected-text
+                                                 variable form number context)
+                                          context)
+               'text-only))
+      (cons nil 'text-only))))
+
+(provide 'citeproc-name)
+
+;;; citeproc-name.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-number.el b/elpa/citeproc-20230228.1414/citeproc-number.el
new file mode 100644 (file)
index 0000000..bf9897b
--- /dev/null
@@ -0,0 +1,160 @@
+;;; citeproc-number.el --- render CSL number elements -*- lexical-binding: t; -*-
+
+;; Copyright "(C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions to render CSL number elements.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'rst)
+(require 's)
+
+(require 'citeproc-context)
+(require 'citeproc-lib)
+(require 'citeproc-s)
+(require 'citeproc-rt)
+
+(defun citeproc-number-extract (val)
+  "Return the parse of string VAL holding numeric content."
+  (cdr (s-match
+       "\\`\\([[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\)\\(?:\\(?: *\\([,&-–—―]\\|--\\) *\\)\\([[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\)\\)?\\'"
+       val)))
+
+(defun citeproc--number (attrs context &rest _body)
+  "Render a cs:number element with the given ATTRS in CONTEXT."
+  (-let* (((&alist 'variable var
+                  'form form)
+          attrs)
+         (variable (intern var))
+         (value (citeproc-var-value variable context))
+         (form (citeproc-lib-intern form)))
+    (if (not value)
+       (cons nil 'empty-var)
+      (let ((result-attrs
+            (cons `(rendered-var . ,variable) attrs))
+           (result-cont
+            (citeproc-number-var-value value variable form context)))
+       (cons (citeproc-rt-format-single result-attrs result-cont context)
+             'present-var)))))
+
+(defconst citeproc--format-numsep-alist
+  '(("&" . " & ")
+    ("," . ", ")
+    ("-" . "-")
+    ("--" . "-")
+    ("—" . "-")
+    ("―" . "-"))
+  "Alist specifying the proper formatting of number-pair separators.")
+
+(defun citeproc-number-var-value (value variable form context)
+  "Return the numeric VALUE of VARIABLE formatted in FORM.
+VARIABLE is a symbol."
+  (cond ((not value) nil)
+       ((numberp value) (number-to-string value))
+       (t (--if-let (citeproc-number-extract value)
+              (let ((formatted-first
+                     (citeproc-number--format (car it) form variable context)))
+                (if (> (length it) 1)
+                    (concat
+                     formatted-first
+                     (assoc-default (cadr it) citeproc--format-numsep-alist)
+                     (citeproc-number--format (cl-caddr it) form variable context))
+                  formatted-first))
+            value))))
+
+(defun citeproc-number--format (s form term context)
+  "Render the number in string S for TERM in format FORM."
+  (if (s-matches-p "[[:alpha:]]" s) s
+    (pcase form
+      ('roman (downcase (rst-arabic-to-roman (string-to-number s))))
+      ('ordinal (citeproc-number--format-as-ordinal s term context))
+      ('long-ordinal (citeproc-number--format-as-long-ordinal s term context))
+      (_ s))))
+
+(defun citeproc-number--format-as-ordinal (s term context)
+  "Format numeric string S as ordinal agreeing with TERM."
+  (let* ((terms (citeproc-context-terms context))
+        (padded (if (= 1 (length s))
+                    (concat "0" s)
+                  s))
+        (gender (citeproc-term-get-gender term context))
+        (matches
+         (--filter (and (string= (s-left 8 (citeproc-term-name it)) "ordinal-")
+                        (citeproc-number--ordinal-matches-p padded gender it))
+                   terms))
+        (suffix
+         (citeproc-term-text
+          (if (not matches)
+              (-when-let (ordinal-matches
+                          (--filter (string= (citeproc-term-name it) "ordinal")
+                                    terms))
+                (-if-let (match (--first (eq (citeproc-term-gender-form it) gender)
+                                         ordinal-matches))
+                    match
+                  (car ordinal-matches)))
+            (let ((first-term (car matches)))
+              (-if-let (second-term (cadr matches))
+                  (if (= (elt (citeproc-term-name first-term) 8) ?0)
+                      second-term
+                    first-term)
+                first-term))))))
+    (concat s suffix)))
+
+(defconst citeproc-number--ordinal-match-alist
+  '((last-two-digits . 2)
+    (last-digit . 1)
+    (whole-number . nil))
+  "Alist mapping ordinal match attributes to the required match lengths.")
+
+(defun citeproc-number--ordinal-matches-p (s gender ord-term)
+  "Whether S term with GENDER matches ordinal-term ORD-TERM."
+  (and (eq gender (citeproc-term-gender-form ord-term))
+       (let ((match (citeproc-term-match ord-term))
+            (term-num (s-right 2 (citeproc-term-name ord-term))))
+        (unless match
+          (setq match
+                (if (= (elt (citeproc-term-name ord-term) 8) ?0)
+                    'last-digit
+                  'last-two-digits)))
+        (let ((l (assoc-default match citeproc-number--ordinal-match-alist)))
+          (string= (citeproc-s-tail s l)
+                   (citeproc-s-tail term-num l))))))
+
+(defun citeproc-number--format-as-long-ordinal (s term context)
+  "Format numeric string S as a long ordinal agreeing with TERM."
+  (let ((num-val (string-to-number s)))
+    (if (> num-val 10)
+       (citeproc-number--format-as-ordinal s term context)
+      (when (= 1 (length s)) (setq s (concat "0" s)))
+      (let* ((name (concat "long-ordinal-" s))
+            (gender (citeproc-term-get-gender term context))
+            (match (--first (and (string= (citeproc-term-name it) name)
+                                 (eq (citeproc-term-gender-form it) gender))
+                            (citeproc-context-terms context))))
+       (if match
+           (citeproc-term-text match)
+         (citeproc-term-get-text name context))))))
+
+(provide 'citeproc-number)
+
+;;; citeproc-number ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-pkg.el b/elpa/citeproc-20230228.1414/citeproc-pkg.el
new file mode 100644 (file)
index 0000000..980f8dd
--- /dev/null
@@ -0,0 +1,21 @@
+(define-package "citeproc" "20230228.1414" "A CSL 1.0.2 Citation Processor"
+  '((emacs "26")
+    (dash "2.13.0")
+    (s "1.12.0")
+    (f "0.18.0")
+    (queue "0.2")
+    (string-inflection "1.0")
+    (org "9")
+    (parsebib "2.4"))
+  :commit "290320fc579f886255f00d7268600df7fa5cc7e8" :authors
+  '(("András Simonyi" . "andras.simonyiNOSPAMgmail.com"))
+  :maintainers
+  '(("András Simonyi" . "andras.simonyiNOSPAMgmail.com"))
+  :maintainer
+  '("András Simonyi" . "andras.simonyi@gmail.com")
+  :keywords
+  '("bib")
+  :url "https://github.com/andras-simonyi/citeproc-el")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/elpa/citeproc-20230228.1414/citeproc-prange.el b/elpa/citeproc-20230228.1414/citeproc-prange.el
new file mode 100644 (file)
index 0000000..52a5fb3
--- /dev/null
@@ -0,0 +1,128 @@
+;;; citeproc-prange.el --- page-range rendering -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions to render CSL page-ranges.
+
+;;; Code:
+
+(defun citeproc-prange--end-significant (start end len)
+  "Return the significant digits of the end in page range START END.
+START and END are strings of equal length containing integers. If
+the significant part of END is shorter than LEN then add
+insignificant digits from END until the string is LEN long or
+there are no more digits left."
+  (let ((first (min (max 1 (1+ (- (length end) len)))
+                   (abs (compare-strings start nil nil end nil nil)))))
+    (substring end (1- first))))
+
+(defun citeproc-prange--end-complete (start end len)
+  "Complete the closing form of a START END pagerange to LEN."
+  (citeproc-prange--end-significant start (citeproc-s-fill-copy end start) len))
+
+(defun citeproc-prange--end-expanded (_start end end-pref)
+  "Render the end of range _START END in `expanded' format.
+END-PREF is an optional non-numeric prefix preceding END. All
+arguments are strings, END has the same length as START."
+  (concat end-pref end))
+
+(defun citeproc-prange--end-minimal (start end _end-pref)
+  "Render the end of range START END in `minimal' format.
+END-PREFIX is an optional non-numeric prefix preceding END. All
+arguments are strings, END has the same length as START."
+  (citeproc-prange--end-significant start end 1))
+
+(defun citeproc-prange--end-minimal-two (start end _end-pref)
+  "Render the end of range START END in `minimal-two' format.
+END-PREFIX is an optional non-numeric prefix preceding END. All
+arguments are strings, END has the same length as START."
+  (citeproc-prange--end-significant start end 2))
+
+(defun citeproc-prange--end-chicago (start end _end-pref &optional 15th-ed)
+  "Render the end of range START END in `chicago' format.
+END-PREFIX is an optional non-numeric prefix preceding END. All
+arguments are strings, END has the same length as START. If
+optional 15TH-ED is non-nil then use the special 4digit rule of
+the 15th edition."
+  (let ((len (length start))) 
+    (cond ((or (< len 3) (string= (substring start -2) "00"))
+          end)
+         ((string= (substring start -2 -1) "0")
+          (citeproc-prange--end-significant start end 1))
+         ((and 15th-ed (= 4 (length start)))
+          (let ((min-two (citeproc-prange--end-significant start end 2)))
+            (if (> (length min-two) 2) end min-two)))
+         (t (citeproc-prange--end-significant start end 2)))))
+
+(defconst citeproc-prange-formatters-alist
+  `((chicago . ,(lambda (start end end-pref)
+                 (citeproc-prange--end-chicago start end end-pref t)))
+    (chicago-15 . ,(lambda (start end end-pref)
+                    (citeproc-prange--end-chicago start end end-pref t)))
+    (chicago-16 . citeproc-prange--end-chicago)
+    (minimal . citeproc-prange--end-minimal)
+    (minimal-two . citeproc-prange--end-minimal-two)
+    (expanded . citeproc-prange--end-expanded))
+  "Alist mapping page range formats to formatter functions.")
+
+(defun citeproc-prange-render (p format sep)
+  "Render page range P in FORMAT with separator SEP."
+  (with-temp-buffer
+    (insert p)
+    (goto-char 0)
+    (while (search-forward-regexp
+           "\\([[:digit:]]*[[:alpha:]]\\)?\\([[:digit:]]+\\)\\( ?\\)\\([-–—]+\\)\\( ?\\)\\([[:digit:]]*[[:alpha:]]\\)?\\([[:digit:]]+\\)"
+           nil t)
+      (let* ((start-pref (match-string 1))
+            (start-num (match-string 2))
+            (orig-dash (match-string 4))
+            (orig-sep (concat (match-string 3) orig-dash (match-string 5)))
+            (end-pref (match-string 6))
+            (end-num (match-string 7))
+            (end (concat end-pref end-num))
+            (old-sep-w-end (concat orig-sep end))
+            ;; Note: To conform with the official CSL tests we don't replace the separating
+            ;; dash with SEP if collapse cannot be applied because of incompatible prefixes
+            ;; but we still remove spaces surrounding the dash. It would make far more
+            ;; sense to replace the dash as well.
+            (new-sep-w-end (cond ((not (string= start-pref end-pref))
+                                  (concat orig-dash end))
+                                 ;; Deal with degenerate single page "ranges"
+                                 ((string= start-num end-num)
+                                  "")
+                                 ((or (not format) (> (length end-num) (length start-num)))
+                                  (concat sep end))
+                                 (t (concat
+                                     sep
+                                     (funcall (alist-get format
+                                                         citeproc-prange-formatters-alist)
+                                              start-num
+                                              (citeproc-s-fill-copy end-num start-num)
+                                              end-pref))))))
+       (unless (string-equal new-sep-w-end old-sep-w-end)
+         (delete-char (- (length old-sep-w-end)))
+         (insert new-sep-w-end))))
+    (buffer-string)))
+
+(provide 'citeproc-prange)
+
+;;; citeproc-prange.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-proc.el b/elpa/citeproc-20230228.1414/citeproc-proc.el
new file mode 100644 (file)
index 0000000..9fd635b
--- /dev/null
@@ -0,0 +1,235 @@
+;;; citeproc-proc.el --- construct and manage citation processors -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Structure type and functions to construct citation processor objects, add or
+;; clear stored bibliography items, and disambiguate and finalize the rendering
+;; of the stored items.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'dash)
+(require 'cl-lib)
+(require 'queue)
+(require 's)
+
+(require 'citeproc-date)
+(require 'citeproc-itemdata)
+(require 'citeproc-disamb)
+
+(cl-defstruct (citeproc-proc (:constructor citeproc-proc--create))
+  "Citation processor struct.
+STYLE is a `citeproc-style' struct,
+GETTER is a bibliography item getter,
+ITEMDATA is a hash table that maps itemids to `citeproc-itemdata'
+  structs,
+CITATIONS is a queue containing citations,
+NAMES is hash table that maps name alists to ids,
+FINALIZED is non-nil iff the processor is finalized
+  (bibliography items are properly sorted, citation positions are
+  updated etc),
+UNCITED is a list of lists of uncited itemids to be added during
+  finalization,
+BIB-FILTERS is a list of filters defining sub-bibliographies."
+  style getter itemdata citations names finalized uncited bib-filters)
+
+(defun citeproc-proc--internalize-name (name proc)
+  "Find or add name-alist NAME in/to the names stored in PROC.
+Return an internalized version which contains the name-id, and is
+sorted."
+  (let* ((sorted (sort name (lambda (x y)
+                             (string< (car x) (car y)))))
+        (names (citeproc-proc-names proc))
+        (val (gethash sorted names)))
+    (cons (cons 'name-id
+               (or val (puthash sorted (hash-table-count names) names)))
+         sorted)))
+
+(defconst citeproc-proc--nonstd-csl-vars-alist
+  '((shortTitle . title-short) (journalAbbreviation . container-title-short))
+  "Alist mapping non-standard citeproc.js vars to their standard CSL peers.")
+
+(defun citeproc-proc--internalize-item (proc item)
+  "Return the internal form of a CSL json ITEM for PROC."
+  (let* (label
+        page-first
+        (result
+         (--map
+          (let* ((orig-var (car it))
+                 (var (-if-let (mapped (alist-get orig-var
+                                                  citeproc-proc--nonstd-csl-vars-alist))
+                          mapped
+                        orig-var))
+                 (value (citeproc-proc--parse-csl-var-val (cdr it) var proc)))
+            (pcase var
+              ('page (-when-let (page-first-match (s-match "[[:digit:]]+" value))
+                       (setq page-first (car page-first-match))))
+              ('label (setq label t)))
+            (cons var value))
+          item)))
+    (when page-first (push (cons 'page-first page-first) result))
+    (unless label (push (cons 'label "page") result))
+    ;; Generate the editor-translator variable if needed
+    ;; (required by CSL 1.02)
+    (when-let* (((null (alist-get 'editor-translator result)))
+               (editor (alist-get 'editor result))
+               (translator (alist-get 'translator result))
+               ((string= (alist-get 'name-id editor)
+                         (alist-get 'name-id translator))))
+      (push (cons 'editor-translator editor) result))
+    result))
+
+(defun citeproc-proc--put-item (proc item itemid &optional uncited)
+  "Put parsed csl-json ITEM with ITEMID into PROC.
+Return the added itemdata structure."
+  (let* ((int-vars (citeproc-proc--internalize-item proc item))
+        (itemdata (citeproc-itemdata-create :varvals int-vars :uncited uncited)))
+    (citeproc-proc-put-itd-put itemid itemdata proc)
+    (citeproc-itd-setvar itemdata 'citation-number
+                        (number-to-string (hash-table-count
+                                           (citeproc-proc-itemdata proc))))
+    (setf (citeproc-proc-finalized proc) nil)
+    itemdata))
+
+(defun citeproc-proc-put-item-by-id (proc itemid)
+  "Put item with ITEMID into the itemlist of PROC.
+Return the itemdata struct that was added."
+  (let ((item (cdar (funcall (citeproc-proc-getter proc)
+                            (list itemid)))))
+    (citeproc-proc--put-item proc
+                            (or item `((unprocessed-with-id . ,itemid)))
+                            itemid)))
+
+(defun citeproc-proc-put-items-by-id (proc itemids)
+  "Add items with ITEMIDS into the itemlist of PROC."
+  (let* ((received (funcall (citeproc-proc-getter proc) itemids))
+        ;; OPTIMIZE: putting the received items into the original order could/should be
+        ;; made more efficient
+        (items (--map (cons it (assoc-default it received))
+                      itemids)))
+    (cl-loop for (itemid . item) in items do
+            (citeproc-proc--put-item proc
+                                     (or item `((unprocessed-with-id . ,itemid)))
+                                     itemid))))
+
+(defun citeproc-proc-put-itd-put (id data proc)
+  "Put the DATA of item with ID in processor PROC."
+  (let ((itemdata (citeproc-proc-itemdata proc)))
+    (puthash id data itemdata)))
+
+(defun citeproc-proc-process-uncited (proc)
+  "Add uncited items to the itemdata in PROC."
+  (when-let ((unciteds (citeproc-proc-uncited proc)))
+   (let* ((itemids (cl-delete-duplicates (apply #'append unciteds))))
+     (when (member "*" itemids)
+       (setq itemids (funcall (citeproc-proc-getter proc) 'itemids)))
+     (let* ((itemdata (citeproc-proc-itemdata proc))
+           (new-ids (--remove (gethash it itemdata) itemids))
+           (id-items (funcall (citeproc-proc-getter proc) new-ids)))
+       (pcase-dolist (`(,id . ,item) id-items)
+        (citeproc-proc--put-item
+         proc
+         (or item `((unprocessed-with-id . ,id)))
+         id t))))))
+
+(defun citeproc-proc-delete-occurrence-info (proc)
+  "Remove all itemdata occurrence info from PROC."
+  (maphash (lambda (_ itd)
+            (setf (citeproc-itemdata-occurred-before itd) nil))
+          (citeproc-proc-itemdata proc)))
+
+(defun citeproc-proc--parse-csl-json-name (rep)
+  "Parse the json representation REP of a csl name variable."
+  (if-let ((literal (alist-get 'literal rep)))
+      (list (cons 'family (citeproc-s-smart-apostrophes literal)))
+    (let ((filtered (-remove (lambda (x) (eq (car x) 'isInstitution)) rep)))
+      (--map (cons
+             (car it)
+             (let ((text-field (cdr it)))
+               (if (stringp text-field)
+                   (citeproc-s-smart-apostrophes text-field)
+                 text-field)))
+            filtered))))
+
+(defun citeproc-proc--parse-csl-var-val (rep var proc)
+  "Parse the json representation REP of csl variable VAR.
+VAR is a csl variable as symbol;
+REP is its value in standard csl json representation as parsed by
+  the Emacs `json' library;
+PROC is the target citeproc-processor of the internal representation.
+Return the PROC-internal representation of REP."
+  (cond ((memq var citeproc--name-vars)
+        (--map (citeproc-proc--internalize-name
+                (citeproc-proc--parse-csl-json-name it)
+                proc)
+         rep))
+       ((memq var citeproc--date-vars)
+        (citeproc-date-parse rep))
+       ;;FIXME: We handle here the id... do we need it in the itemdata at all?
+       ((or (memq var citeproc--number-vars) (eq 'id var))
+        (citeproc-s-from-num-or-s rep))
+       ((stringp rep)
+        (let* ((w-aposts (citeproc-s-smart-apostrophes rep))
+               (rt (citeproc-rt-from-str w-aposts)))
+          (if (s-contains-p "\"" rep)
+              (let* ((terms (citeproc-style-terms (citeproc-proc-style proc)))
+                     (oq (citeproc-term-text-from-terms "open-quote" terms))
+                     (cq (citeproc-term-text-from-terms "close-quote" terms)))
+                (citeproc-rt-change-case
+                 rt (lambda (x) (citeproc-s-smart-quotes x oq cq))))
+            rt)))
+       (t rep)))
+
+(defun citeproc-proc-disamb (proc)
+  "Disambiguate the items stored in PROC."
+  (let* ((cite-opts (citeproc-style-cite-opts (citeproc-proc-style proc)))
+        (name (string= "true" (alist-get 'disambiguate-add-names cite-opts)))
+        (given (string= "true" (alist-get 'disambiguate-add-givenname cite-opts)))
+        (yearsuff (string= "true" (alist-get 'disambiguate-add-year-suffix cite-opts))))
+    (citeproc-disamb-itds (hash-table-values (citeproc-proc-itemdata proc))
+                         (citeproc-proc-style proc)
+                         name given yearsuff)))
+
+(defun citeproc-proc-byte-compile (proc)
+  "Byte-compile all lambdas in PROC."
+  (let* ((style (citeproc-proc-style proc))
+        (bib-sort (citeproc-style-bib-sort style))
+        (cite-sort (citeproc-style-cite-sort style)))
+    (setf (citeproc-style-macros style)
+         (--map (cons (car it) (byte-compile (cdr it)))
+                (citeproc-style-macros style))
+         (citeproc-style-cite-layout style)
+         (byte-compile (citeproc-style-cite-layout style))
+         (citeproc-style-bib-layout style)
+         (byte-compile (citeproc-style-bib-layout style)))
+    (when bib-sort (setf (citeproc-style-bib-sort style) (byte-compile bib-sort)))
+    (when cite-sort (setf (citeproc-style-cite-sort style) (byte-compile cite-sort)))))
+
+(defun citeproc-proc-filtered-bib-p (proc)
+  "Return whether PROC has nontrivial filters"
+  (let ((filters (citeproc-proc-bib-filters proc)))
+    (and filters (not (equal filters '(nil))))))
+
+(provide 'citeproc-proc)
+
+;;; citeproc-proc.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-rt.el b/elpa/citeproc-20230228.1414/citeproc-rt.el
new file mode 100644 (file)
index 0000000..9e36268
--- /dev/null
@@ -0,0 +1,650 @@
+;; citeproc-rt.el --- citeproc-el rich-text functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions operating on rich-text contents. In citeproc-el, rich-texts are
+;; represented either by strings or by lists of the form (ATTRS RT_1 RT_2...)
+;; where ATTRS is an alist consisting of (FORMAT-ATTR . VALUE) pairs and RT_1,
+;; RT_2... are all rich-texts. The constants `citeproc-rt-format-attrs' and
+;; `citeproc-rt-ext-format-attrs' define the list of normal and extended format
+;; attributes, respectively. As a degenerate case, nil is also a legitimate
+;; rich-text.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'dash)
+(require 'cl-lib)
+(require 'let-alist)
+(require 's)
+
+(require 'citeproc-s)
+(require 'citeproc-lib)
+
+(defconst citeproc-rt-format-attrs
+  '(font-variant font-style font-weight text-decoration vertical-align font-variant
+                display rendered-var name-id quotes cited-item-no bib-item-no
+                rendered-names href stopped-rendering rendered-locator-label)
+  "The rich-text content format attributes (used in raw output).")
+
+(defconst citeproc-rt-ext-format-attrs
+  (-concat '(prefix suffix delimiter subst quotes) citeproc-rt-format-attrs)
+  "The list of extended format attributes.")
+
+(defun citeproc-rt-to-plain (rt)
+  "Return the plain-text content of rich-text RT."
+  (if (listp rt)
+      (mapconcat 'citeproc-rt-to-plain
+                (cdr rt)
+                "")
+    rt))
+
+(defun citeproc-rt-attrs (rt)
+  "Return the attrs of rich content RT."
+  (if (listp rt) (car rt) nil))
+
+(defun citeproc-rt-first-content (rt)
+  "Return the first content element of rich content RT."
+  (if (listp rt) (cadr rt) rt))
+
+(defun citeproc-rt-select-attrs (attrs keep)
+  "Select attr-val pairs from alist ATTRS whose attr is in KEEP."
+  (--filter (memq (car it) keep)
+           attrs))
+
+(defun citeproc-rt-join-strings (rt)
+  "Concatenate consecutive strings in rich-text RT."
+  (cond ((< (length rt) 2)
+        rt)
+       ((and (char-or-string-p (car rt))
+             (char-or-string-p (cadr rt)))
+        (citeproc-rt-join-strings (cons (concat (car rt)
+                                                (cadr rt))
+                                        (cddr rt))))
+       (t (cons (car rt)
+                (citeproc-rt-join-strings (cdr rt))))))
+
+(defun citeproc-rt-splice-unformatted (rt)
+  "Splice the body of its unformatted elements into rich-text RT."
+  (if (and (consp rt) (not (alist-get 'delimiter (car rt))))
+      (cons (car rt)
+           (--mapcat (if (citeproc-rt-formatting-empty-p it)
+                         (cdr it)
+                       (list it))
+                     (cdr rt)))
+    rt))
+
+(defun citeproc-rt-formatting-empty-p (rt)
+  "Is the formatting of rich-text RT empty/redundant?"
+  (and (consp rt) (or (not (caar rt))
+                     (and (eq (cl-caaar rt) 'delimiter)
+                          (= (length (car rt)) 1)
+                          (= (length rt) 2)))))
+
+(defun citeproc-rt-reduce-content (rt)
+  "Reduce rich-text RT if it has no attributes or body.
+Return the original RT if it has non-empty attrs and content."
+  (cond ((not (cdr rt)) nil)
+       ((and (not (car rt)) (= (length rt) 2)) (cadr rt))
+       (t rt)))
+
+(defun citeproc-rt-simplify-shallow (rt)
+  "Simplify the first level of rich-text RT."
+  (citeproc-rt-reduce-content (citeproc-rt-join-strings
+                              (citeproc-rt-splice-unformatted rt))))
+
+(defun citeproc-rt-simplify-deep (rt)
+  "Simplify all levels of rich-text RT."
+  (if (not (consp rt)) rt
+    (-let* (((attrs . conts) rt)
+           (simplifieds (--map (citeproc-rt-simplify-deep it)
+                               conts)))
+      (citeproc-rt-reduce-content
+       (citeproc-rt-join-strings
+       (citeproc-rt-splice-unformatted (cons attrs simplifieds)))))))
+
+(defun citeproc-rt-map-strings (fun rts &optional skip-nocase)
+  "Map through FUN all strings in rich-texts RTS.
+Return a new rich-text with all S content strings replaced by the
+value of FUN applied to S. No formatting is changed. If optional
+SKIP-NOCASE is non-nil then skip spans with the `nocase'
+attribute set to non-nil."
+  (--map (citeproc-rt-format it fun skip-nocase) rts))
+
+(defun citeproc-rt-format (rt fun &optional skip-nocase)
+  "Format all plain text in RT with FUN.
+If optional SKIP-NOCASE is non-nil then skip spans with the
+`nocase' attribute set to non-nil."
+  (pcase rt
+    (`nil nil)
+    ((pred listp) (if (and skip-nocase (alist-get 'nocase (car rt)))
+                     rt
+                   (cons (car rt) (citeproc-rt-map-strings fun (cdr rt) skip-nocase))))
+    (_ (funcall fun rt))))
+
+(defun citeproc-rt-replace-all-sim (replacements regex rts)
+  "Make all REPLACEMENTS simultaneously in the strings of rich-texts RTS."
+  (citeproc-rt-map-strings (lambda (x) (citeproc-s-replace-all-sim x regex replacements))
+                          rts))
+
+(defun citeproc-rt-strip-periods (rts)
+  "Remove all periods from rich-texts RTS."
+  (citeproc-rt-map-strings (lambda (x) (citeproc-s-replace "." "" x)) rts))
+
+(defun citeproc-rt-length (rt)
+  "Return the length of rich-text RT as a string."
+  (if (listp rt)
+      (-sum (mapcar #'citeproc-rt-length (cdr rt)))
+    (length rt)))
+
+(defun citeproc-rt--update-from-plain-1 (rt p start &optional skip-nocase)
+  "Update rich-text RT from plain text P from position START in P.
+The length of the plain text content of RT must not be less than
+the length of P. If optional SKIP-NOCASE is non-nil then skip
+spans with the `nocase' attribute set to non-nil.
+  Return an (UPDATED . NEXT) pair where UPDATED is the updated
+rich-text and NEXT is the first position in P which was not used
+for the update."
+  (pcase rt
+    (`nil nil)
+    ((pred listp)
+     (if (and skip-nocase (alist-get 'nocase (car rt)))
+        (cons rt (+ start (citeproc-rt-length rt)))
+       (let ((act-start start))
+        (cons (cons (car rt)
+                    (--map (-let (((updated . next)
+                                   (citeproc-rt--update-from-plain-1
+                                    it p act-start skip-nocase)))
+                             (setq act-start next)
+                             updated)
+                           (cdr rt)))
+              act-start))))
+    (_ (let ((end (+ start (length rt))))
+        (cons (substring p start end) end)))))
+
+(defun citeproc-rt-update-from-plain (rt p &optional skip-nocase)
+  "Update rich-text RT from plain text P.
+The length of the plain text content of RT must not be less than
+the length of P. Return the updated rich-text. If optional
+SKIP-NOCASE is non-nil then skip spans with the `nocase'
+attribute set to non-nil."
+  (car (citeproc-rt--update-from-plain-1 rt p 0 skip-nocase)))
+
+(defun citeproc-rt-change-case (rt case-fun)
+  "Change the case of rich text RT with CASE-FUN.
+CASE-FUN is a function taking a string as its argument and
+returning a string of the same length."
+  (let ((plain (citeproc-rt-to-plain rt)))
+    (citeproc-rt-update-from-plain rt (funcall case-fun plain) t)))
+
+(defun citeproc-rt-pred-counts-tree (rt pred)
+  "Return a dominated count tree for rich text RT based on PRED.
+The returned tree has the same structure as RT but the car of
+each subtree is a number indicating the maximal number of nodes
+on any dominated branch for which PRED holds."
+  (if (consp rt)
+      (let ((children-vals (--map (citeproc-rt-pred-counts-tree it pred)
+                                 (cdr rt))))
+       (cons (-max (cl-mapcar (lambda (rich count)
+                                (+ (if (listp count) (car count) count)
+                                   (if (funcall pred rich) 1 0)))
+                              (cdr rt)
+                              children-vals))
+             children-vals))
+    0))
+
+(defun citeproc-rt-flip-italics (rt)
+  "Flip the italic attribute of rich text RT."
+  (if (listp rt)
+      (cons (if (citeproc-rt-in-italics-p rt)
+               (--remove (eq (car it) 'font-style) (car rt))
+             (cons '(font-style . "italic") (car rt)))
+           (cdr rt))
+    `(((font-style . "italic")) ,rt)))
+
+(defun citeproc-rt-in-italics-p (rt)
+  "Whether rich text RT has italic font style as attribute."
+  (and (listp rt)
+       (string= (alist-get 'font-style (car rt)) "italic")))
+
+(defun citeproc-rt-italics-flipflop (rt)
+  "Return a flipflopped italics version of rich text RT."
+  (if (and rt (listp rt))
+      (let ((italics-counts-tree
+            (citeproc-rt-pred-counts-tree rt 'citeproc-rt-in-italics-p)))
+       (if (> (+ (car italics-counts-tree)
+                 (if (citeproc-rt-in-italics-p rt) 1 0))
+              1)
+           (citeproc-rt--italics-flipflop-1 rt italics-counts-tree)
+         rt))
+    rt))
+
+(defun citeproc-rt--italics-flipflop-1 (rt italics-counts-tree)
+  "Flipflop italics in RT using info from ITALICS-COUNTS-TREE."
+  (let ((rt-italic (citeproc-rt-in-italics-p rt)))
+    (if (or (not (listp rt))
+           (not (listp italics-counts-tree))
+           (< (+ (car italics-counts-tree)
+                 (if rt-italic 1 0))
+              2)) rt
+      (if rt-italic
+         (cons (--remove (eq (car it) 'font-style) (car rt))
+               (cl-mapcar (lambda (r i)
+                            (citeproc-rt--italics-flipflop-1
+                             (citeproc-rt-flip-italics r) i))
+                          (cdr rt)
+                          (cdr italics-counts-tree)))
+       (cons (car rt)
+             (cl-mapcar (lambda (r i) (citeproc-rt--italics-flipflop-1 r i))
+                        (cdr rt)
+                        (cdr italics-counts-tree)))))))
+
+(defun citeproc-rt-from-str (s)
+  "Parse a html or plain text string S into rich text."
+  (if (and s (s-matches-p "</[[:alnum:]]+>" s))
+      (let* ((parsed (citeproc-lib-parse-html-frag s))
+            (body (cddr (cl-caddr parsed)))
+            (stripped (if (eq (caar body) 'p) (cl-cddar body) body)))
+       (if (= 1 (length stripped))
+           (citeproc-rt-from-html (car stripped))
+         (cons nil (mapcar 'citeproc-rt-from-html stripped))))
+    s))
+
+(defconst citeproc-rt-from-html-alist
+  '(((i . nil) . (font-style . "italic"))
+    ((b . nil) . (font-weight . "bold"))
+    ((span . ((style . "font-variant:small-caps;"))) . (font-variant . "small-caps"))
+    ((sc . nil) . (font-variant . "small-caps"))
+    ((sup . nil) . (vertical-align . "sup"))
+    ((sub . nil) . (vertical-align . "sub"))
+    ((span . ((class . "nocase"))) . (nocase . t))
+    ((span . ((class . "underline"))) . (text-decoration . "underline")))
+  "A mapping from html tags and attrs to rich text attrs.")
+
+(defun citeproc-rt-from-html (h)
+  "Convert simple html H to rich text."
+  (if (listp h)
+      (cons (-if-let (attr (assoc-default (cons (car h) (cadr h))
+                                         citeproc-rt-from-html-alist))
+               (list attr)
+             '(nil))
+           (mapcar #'citeproc-rt-from-html (cddr h)))
+    h))
+
+(defun citeproc-rt--cquote-pstns-1 (rt offset)
+  "Return closing quote positions in rich text RT with OFFSET.
+The positions are in the plain text of RT and only those
+positions are returned which are associated with a CSL
+`quotes'=\"yes\" attribute."
+  (if (listp rt)
+      (let ((inner (let ((act-offset offset)
+                        pstns)
+                    (--each (cdr rt)
+                      (-let (((p . next)
+                              (citeproc-rt--cquote-pstns-1 it act-offset)))
+                        (setq pstns (nconc pstns p)
+                              act-offset next)))
+                    (cons pstns act-offset))))
+       (if (string= (alist-get 'quotes (car rt)) "true")
+           (-let (((inner-pstns . inner-offset) inner))
+             (cons (cons (1- inner-offset) inner-pstns)
+                   inner-offset))
+         inner))
+    (cons nil (+ offset (length rt)))))
+
+(defun citeproc-rt--cquote-pstns (rt)
+  "Return a list of closing quote positions in RT.
+The positions are in the plain text of RT and only those
+positions are returned which are associated with a CSL
+`quotes'=\"yes\" attribute. Numbering starts from 1.
+The positions are in decreasing order."
+  (sort (car (citeproc-rt--cquote-pstns-1 rt 1)) '>))
+
+(defun citeproc-rt-punct-in-quote (rt)
+  "Put commas and periods inside quotes in rich text RT."
+  (-if-let (pstns (citeproc-rt--cquote-pstns rt))
+      (let ((plain (citeproc-rt-to-plain rt)))
+       (citeproc-rt-update-from-plain
+        rt
+        (with-temp-buffer
+          (insert plain)
+          (dolist (pos pstns)
+            (goto-char (1+ pos))
+            (when (memq (char-after) '(?, ?.))
+              (call-interactively 'transpose-chars)))
+          (buffer-string))))
+    rt))
+
+(defun citeproc-rt-find-first-node (rt pred)
+  "Return the first node of RT for which PRED holds.
+Return nil if no such node was found."
+  (if (funcall pred rt) rt
+    (pcase rt
+      ;; process further if internal node with content
+      (`(,_ . ,body)
+       (let (found)
+        (while (and (not found) body)
+          (setq found (citeproc-rt-find-first-node (car body) pred))
+          (pop body))
+        found))
+      ;; leaf or node with no content
+      (_ nil))))
+
+(defun citeproc-rt-transform-first (rt pred transform)
+  "Apply TRANSFORM to the first node of RT for which PRED is non-nil.
+PRED and TRANSFORM are functions taking a rich-text node as their
+sole argument. Return a (RESULT . SUCCESS) pair where RESULT is
+the resulting rich-text and SUCCESS is non-nil iff the
+transformation was successfully carried out (i.e., a node
+satisfying PRED was found)."
+  (if (funcall pred rt) (cons (funcall transform rt) t)
+    (pcase rt
+      ;; process further if internal node with content
+      (`(,attrs . ,body)
+       (let* (success
+             (new-body
+              (--map (if success it
+                       (-let (((it-res . it-success)
+                               (citeproc-rt-transform-first it pred transform)))
+                         (setq success it-success)
+                         it-res))
+                     body)))
+        (cons (cons attrs new-body) success)))
+      ;; leaf or node with no content
+      (_ (cons rt nil)))))
+
+(defun citeproc-rt-add-year-suffix (rt ys)
+  "Attempt to add year suffix YS to rich-text RT.
+Return an (RT . SUCCESS) pair, where RT is the resulting
+rich-text, and SUCCESS is non-nil iff the year-suffix has been
+successfully added."
+  (cl-flet ((rendered-date-var-p
+            (node)
+            (and (consp node)
+                 (memq (alist-get 'rendered-var (car node)) citeproc--date-vars)))
+           (add-suffix
+            (node)
+            (let ((content (cadr node)))
+             (if (equal content "<suppressed-date>")
+                 (list (car node) ys)
+               (let ((full-ys (if (or (not (stringp content))
+                                      (s-matches-p "[[:digit:]]$" content))
+                                  ys
+                                (concat "-" ys))))
+                (-snoc node `(((rendered-var . year-suffix)) ,full-ys)))))))
+    (citeproc-rt-transform-first rt #'rendered-date-var-p #'add-suffix)))
+
+(defun citeproc-rt-replace-first-names (rt replacement)
+  "Replace RT's first name-var content with REPLACEMENT.
+Return an (RT . SUCCESS) pair, where RT is the resulting
+rich-text, and SUCCESS is non-nil iff the replacement has been
+successful."
+  (cl-flet ((rendered-name-var-p
+            (node)
+            (and (consp node)
+                 (assoc 'rendered-names (car node))))
+           (replace (_node) replacement))
+    (citeproc-rt-transform-first rt #'rendered-name-var-p #'replace)))
+
+(defun citeproc-rt-count-names (rt)
+  "Return a count of the rendered names in RT."
+  (if (consp rt)
+      (if (alist-get 'name-id (car rt)) 1
+       (apply #'+ (mapcar #'citeproc-rt-count-names (cdr rt))))
+    0))
+
+(defun citeproc-rt-cull-spaces-puncts (rt)
+  "Remove unnecessary characters from rich-text RT."
+  (let* ((plain (citeproc-rt-to-plain rt))
+        (updated (citeproc-rt-update-from-plain
+                  rt (citeproc-s-cull-spaces-puncts plain))))
+    (citeproc-rt-format updated
+                       (lambda (x) (replace-regexp-in-string "\7f+" "" x)))))
+
+(defun citeproc-rt-render-affixes (rt &optional shallow)
+  "Render the affixes in rich-text RT.
+If SHALLOW is non-nil then render only the affixes for the first
+level."
+  (if (not (consp rt))
+      rt
+    (-let* (((attrs . contents) rt)
+           (rendered
+            (if shallow         ; We do the recursive call depending on SHALLOW
+                contents
+              (-non-nil (--map (citeproc-rt-render-affixes it) contents)))))
+      (if rendered
+         (let-alist attrs
+           (let ((delimited (if .delimiter
+                                (cdr (--mapcat (list .delimiter it) rendered))
+                              rendered)))
+             (if (or .suffix .prefix)
+                 (let (result
+                       outer-attrs
+                       (inner-attrs
+                        (citeproc-rt-select-attrs attrs citeproc-rt-format-attrs)))
+                   (when .display ; The display attribute should encompass affixes
+                     (setq outer-attrs (list (cons 'display .display))
+                           inner-attrs (--remove (eq (car it) 'display) inner-attrs)))
+                   (when .suffix (push .suffix result))
+                   (push (cons inner-attrs
+                               delimited)
+                         result)
+                   (when .prefix (push .prefix result))
+                   (cons outer-attrs result))
+               (cons (citeproc-rt-select-attrs attrs citeproc-rt-format-attrs)
+                     delimited))))
+       nil))))
+
+(defun citeproc-rt-dedup (rt)
+  "Remove duplicate substituted renderings from content RT."
+  (car (citeproc-rt--dedup-single rt nil)))
+
+(defun citeproc-rt--dedup-single (rt substs)
+  "Remove duplicate subst. var renderings from RT.
+SUBSTS contains an initial list of vars to be removed. Return
+a (<deduplicated content of RT> <substitued vars in RT> <vars in RT>) list."
+  (if (not (consp rt))
+      (list rt nil nil)
+    (-let* (((attrs . cs) rt)
+           ((&alist 'subst subst
+                    'rendered-var var)
+            attrs))
+      (if (and var (memq var substs))
+         (list nil nil nil)
+       (-let (((new-c s v) (citeproc-rt--dedup-multi cs substs)))
+         (list (cons (--reject (memq (car it) '(subst rendered-vars)) attrs)
+                     new-c)
+               (if subst
+                   (-concat v (when var (list var)))
+                 s)
+               (-concat v (if var
+                              (list var)
+                            nil))))))))
+
+(defun citeproc-rt--dedup-multi (cs substs)
+  (if cs
+      (-let* (((c s1 v1) (citeproc-rt--dedup-single (car cs) substs))
+             ((cs s2 v2) (citeproc-rt--dedup-multi (cdr cs) (-concat substs s1))))
+       (list (cons c cs)
+             (-concat s1 s2)
+             (-concat v1 v2)))
+    (list nil nil nil)))
+
+(defun citeproc-rt-finalize (rt &optional punct-in-quote)
+  "Finalize rich text RT.
+If the optional PUNCT-IN-QUOTE is non-nil then put punctuation
+inside quotes.
+
+Note: Finalization doesn't include culling, because some
+rich-text transformations require the state before culling (e.g.
+the replacement of subsequent authors)."
+  ;; The first step is to replace the internally used `modifier letter
+  ;; apostrophe' characters with the normal `right single quotation marks'
+  (citeproc-rt-format (citeproc-rt-simplify-deep
+                      (citeproc-rt-italics-flipflop
+                       (if punct-in-quote (citeproc-rt-punct-in-quote rt) rt)))
+                     (lambda (x) (s-replace "ʼ" "’" x))))
+
+(defun citeproc-rt--attr-values (r attr)
+  "Return the list of ATTR values in raw rich-text content R.
+The values are ordered depth-first."
+  (if (listp r)
+      (let ((val (alist-get attr (car r)))
+           (body-vals (--mapcat (citeproc-rt--attr-values it attr) (cdr r))))
+       (if val (cons val body-vals)
+         body-vals))
+    nil))
+
+(defun citeproc-rt-rendered-name-ids (r)
+  "Return the list of name ids in raw content R."
+  (citeproc-rt--attr-values r 'name-id))
+
+(defun citeproc-rt-rendered-vars (r)
+  "Return the list of rendered vars in raw content R."
+  (citeproc-rt--attr-values r 'rendered-var))
+
+(defun citeproc-rt-rendered-date-vars (r)
+  "Return the list of date vars in raw content R."
+  (--select (memq it citeproc--date-vars) (citeproc-rt-rendered-vars r)))
+
+(defun citeproc-rt-rendered-name-vars (r)
+  "Return the list of name vars in raw content R."
+  (--select (memq it citeproc--name-vars) (citeproc-rt-rendered-vars r)))
+
+;;; Helpers for bibliography rendering
+
+(defun citeproc-rt-max-offset (itemdata)
+  "Return the maximal first field width in rich-texts RTS."
+  (cl-loop for itd being the hash-values of itemdata
+          when (listp (citeproc-itemdata-rawbibitem itd)) maximize
+          (length (citeproc-rt-to-plain (cadr (citeproc-itemdata-rawbibitem itd))))))
+
+(defun citeproc-rt-subsequent-author-substitute (bib s)
+  "Substitute S for subsequent author(s) in BIB.
+BIB is a list of bib entries in rich-text format. Return the
+modified bibliography."
+  (let (prev-author)
+    (--map
+     (let ((author
+           (citeproc-rt-find-first-node
+            it
+            (lambda (x)
+              (and (consp x) (assoc 'rendered-names (car x)))))))
+       (if (equal author prev-author)
+          (car (citeproc-rt-replace-first-names it s))
+        (prog1 it (setq prev-author author))))
+     bib)))
+
+(defun citeproc-rt-link-title (r target)
+  "Link the rendered title var in rich-text R to TARGET."
+  (cl-flet ((rendered-var-title-p
+            (node)
+            (and (consp node)
+                 (eq (alist-get 'rendered-var (car node)) 'title)))
+           (add-link
+            (node)
+            (push (cons 'href target) (car node))))
+    (citeproc-rt-transform-first r #'rendered-var-title-p #'add-link)))
+
+(defun citeproc-rt-locator-p (r)
+  "Return whether rich-text R is a rendered locator."
+  (and (consp r) (string= (alist-get 'rendered-var (car r)) "locator")))
+
+(defun citeproc-rt-locator-label-p (r)
+  "Return whether rich-text R is a rendered locator label."
+  (and (consp r) (alist-get 'rendered-locator-label (car r))))
+
+(defun citeproc-rt-add-locator-label-position (r)
+  "Add information about locator-label position in rich-text R.
+Return value is one of `label', `locator', `label-first',
+`locator-first', `label-only', `locator-only' or nil. This
+information is also added to the tree node attributes."
+  (let ((result
+        (cond
+         ((not (consp r)) nil)
+         ((citeproc-rt-locator-p r) 'locator)
+         ((citeproc-rt-locator-label-p r) 'label)
+         (t (let ((content (cdr r))
+                  first second)
+              (while (and content (not (and first second)))
+                (let* ((cur (pop content))
+                       (cur-order (citeproc-rt-add-locator-label-position cur)))
+                  (pcase cur-order
+                    ('label-first (setq first 'label second 'locator))
+                    ('locator-first (setq first 'locator second 'label))
+                    ((or 'label-only 'label)
+                     (if first (setq second 'label)
+                       (setq first 'label)))
+                    ((or 'locator-only 'locator)
+                     (if first (setq second 'locator)
+                       (setq first 'locator))))))
+              (cond
+               ((not first) nil)
+               ((not second) (if (eq first 'locator) 'locator-only 'label-only))
+               (t (if (eq first 'locator) 'locator-first 'label-first))))))))
+    (when result (push (cons 'l-l-pos result) (car r)))
+    result))
+
+(defun citeproc-rt-locator-w-label (r)
+  "Return locator with label if found from rich-text R.
+Return R if no locator or locator label was found."
+  (let ((l-l-pos (citeproc-rt-add-locator-label-position r)))
+    (if l-l-pos
+       (citeproc-rt-locator-w-label-1 r l-l-pos)
+      ;; We return the full cite if no locator was found.
+      r)))
+
+(defun citeproc-rt-locator-w-label-1 (r l-l-pos)
+  "Return locator-label span from rich-text fragment R.
+L-L-POS is the global position of locator and label, see the
+documentation of `citeproc-rt-add-locator-label-position' for the
+possible values."
+  (if (or (citeproc-rt-locator-label-p r) (citeproc-rt-locator-p r)) r
+    (pcase-let* ((`(,attrs . ,content) r)
+                (local-llpos (alist-get 'l-l-pos attrs)))
+      (cons attrs
+           (let (result
+                 (n-boundaries (if (or (and (eq l-l-pos 'locator-first)
+                                            (eq local-llpos 'label-only))
+                                       (and (eq l-l-pos 'label-first)
+                                            (eq local-llpos 'locator-only)))
+                                   1   ; Fragment starts in a between position.
+                                 0)))  ; Fragment starts in a before position.
+             (while (and content (< n-boundaries 2))
+               (let* ((cur-rt (pop content))
+                      (cur-rt-llpos (and (consp cur-rt) (alist-get 'l-l-pos (car cur-rt)))))
+                 (cond (cur-rt-llpos
+                        ;; Element at boundary
+                        (cl-incf n-boundaries
+                                 (if (or (eq l-l-pos 'locator-only)
+                                         (memq cur-rt-llpos '(label-first locator-first)))
+                                     2
+                                   1))
+                        (push (citeproc-rt-locator-w-label-1 cur-rt l-l-pos) result))
+                       ;; Element in between position, simply pushing
+                       ((= n-boundaries 1)
+                        (push cur-rt result)))))
+             (nreverse result))))))
+
+(provide 'citeproc-rt)
+
+;;; citeproc-rt.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-s.el b/elpa/citeproc-20230228.1414/citeproc-s.el
new file mode 100644 (file)
index 0000000..bfb6208
--- /dev/null
@@ -0,0 +1,274 @@
+;;; citeproc-s.el --- citeproc-el string functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; String utility functions for citeproc-el.
+
+;;; Code:
+
+(require 'thingatpt)
+(require 's)
+
+;; Handle the unavailability of `string-replace' in early Emacs versions
+(if (fboundp 'string-replace)
+    (defalias 'citeproc-s-replace #'string-replace)
+  (defalias 'citeproc-s-replace #'s-replace))
+
+(defun citeproc-s-camelcase-p (s)
+  "Return whether string S is in camel case."
+  (let ((case-fold-search nil))
+    (and (< 1 (length s))
+        (s-matches-p "[[:upper:]]" (substring s 1))
+        (s-matches-p "[[:lower:]]" s))))
+
+(defun citeproc-s-fill-copy (s1 s2)
+  "Return a copy of string S1 filled by characters from string S2.
+If string S1 is shorter than string S2 then prepend enough
+characters from to beginning of S2 to the beginning of a copy of
+S2 to make their length equal, and return the filled copy."
+  (if (>= (length s1) (length s2)) s1
+    (concat (substring s2 0 (- (length s2) (length s1))) s1)))
+
+(defun citeproc-s-fill-left-to-len (s len &optional char)
+  "Fill string S to length LEN with CHAR from left."
+  (let ((len-s (length s))
+       (char (or char ?0)))
+    (if (>= len-s len) s
+      (concat (make-string (- len len-s) char) s))))
+
+(defun citeproc-s-nil-or-s-to-num (s)
+  "Convert S, which is a string or nil to a number.
+A nil value is converted to 0."
+  (if s (string-to-number s) 0))
+
+(defun citeproc-s-from-num-or-s (x)
+  "Return the content of string or number X as a number."
+  (if (numberp x) (number-to-string x) x))
+
+(defun citeproc-s-content (s)
+  "Return the string content of string or symbol or nil S.
+The string content of nil is defined as \"\"."
+  (pcase s
+    ((\` nil) "")
+    ((pred symbolp) (symbol-name s))
+    (_ s)))
+
+(defun citeproc-s-slice-by-matches (s regexp &optional start annot)
+  "Slice S up at the boundaries of each REGEXP match.
+Optionally start from index START. Matches are also included
+among the slices, but all zero-length slices are omitted. If
+optional ANNOT is non-nil then slices are given as (S . B) cons
+cells where S is the slice string, while B is nil if the S slice
+is a separating REGEXP match and t otherwise."
+  (unless start (setq start 0))
+  (save-match-data
+    (let ((begin (string-match regexp s start)))
+      (if begin
+         (let ((end (match-end 0)))
+           (if (and (= begin start) (= end start))
+               (citeproc-s-slice-by-matches s regexp (1+ start) annot)
+             (let ((result (citeproc-s-slice-by-matches (substring s end)
+                                                        regexp 0 annot)))
+               (unless (= begin end)
+                 (let ((slice (substring s begin end)))
+                   (push (if annot (list slice) slice) result)))
+               (unless (= 0 begin)
+                 (let ((slice (substring s 0 begin)))
+                   (push (if annot (cons slice t) slice) result)))
+               result)))
+       (list (if annot (cons s t) s))))))
+
+(defun citeproc-s-tail (s length)
+  "Return the closing substring of string S with length LENGTH.
+Return S if LENGTH is nil or not less than the length of S."
+  (let ((l (length s)))
+    (if (and length (< length l))
+       (substring s (- l length))
+      s)))
+
+(defun citeproc-s-capitalize-first (s)
+  "Capitalize the first word in string S.
+Return the capitalized version of S. If S contains no word or the
+first word is not in lowercase then return S."
+  (if (s-present-p s)
+      (with-temp-buffer
+       (insert s)
+       (goto-char 1)
+       (forward-word)
+       (backward-word)
+       (let ((word (word-at-point)))
+         (when (s-lowercase-p word)
+           (capitalize-word 1)))
+       (buffer-string))
+    s))
+
+(defun citeproc-s-capitalize-all (s)
+  "Capitalize all lowercase words in string S.
+Return the capitalized version of S. If S contains no word or the
+first word is not in lowercase then return S."
+  (if (s-present-p s)
+      (with-temp-buffer
+       (insert s)
+       (goto-char 1)
+       (while (forward-word)
+         (let ((word (word-at-point)))
+           (when (s-lowercase-p word)
+             (capitalize-word -1))))
+       (buffer-string))
+    s))
+
+(defun citeproc-s-sentence-case (s)
+  "Return a sentence-cased version of string S."
+  (if (s-present-p s)
+      (with-temp-buffer
+       (insert s)
+       (goto-char 1)
+       (let ((first t))
+         (while (forward-word)
+           (let ((word (word-at-point)))
+             (cond ((s-uppercase-p word) (capitalize-word -1))
+                   ((and first (s-lowercase-p word)) (capitalize-word -1))))
+           (when first (setq first nil))))
+       (buffer-string))
+    s))
+
+(defun citeproc-s-sentence-case-title (s omit-nocase)
+  "Return a sentence-cased version of title string S.
+If optional OMIT-NOCASE is non-nil then omit the nocase tags from the output."
+  (if (s-blank-p s) s
+    (let ((sliced (citeproc-s-slice-by-matches
+                  s "\\(<span class=\"nocase\">\\|</span>\\|: +\\w\\)"))
+         (protect-level 0)
+         (first t)
+         result)
+      (dolist (slice sliced)
+       (push
+        (pcase slice
+          ("<span class=\"nocase\">" (cl-incf protect-level) (if omit-nocase nil slice))
+          ("</span>" (cl-decf protect-level) (if omit-nocase nil slice))
+          ;; Don't touch the first letter after a colon since it is probably a subtitle.
+          ((pred (string-match-p "^:")) slice)
+          (_ (cond ((< 0 protect-level) (setq first nil) slice)
+                   ((not first) (downcase slice))
+                   (t (setq first nil)
+                      (concat (upcase (substring slice 0 1))
+                              (downcase (substring slice 1)))))))
+        result))
+      (apply #'concat (nreverse result)))))
+
+(defconst citeproc-s-english-stopwords
+  '("a" "according to" "across" "afore" "after" "against" "ahead of" "along" "alongside"
+    "amid" "amidst" "among" "amongst" "an" "and" "anenst" "apart from" "apropos"
+    "around" "as" "as regards" "aside" "astride" "at" "athwart" "atop" "back to"
+    "barring" "because of" "before" "behind" "below" "beneath" "beside" "besides"
+    "between" "beyond" "but" "by" "c" "ca" "circa" "close to" "d'" "de" "despite" "down"
+    "due to" "during" "et" "except" "far from" "for" "forenenst" "from" "given" "in"
+    "inside" "instead of" "into" "lest" "like" "modulo" "near" "next" "nor" "of" "off"
+    "on" "onto" "or" "out" "outside of" "over" "per" "plus" "prior to" "pro" "pursuant
+    to" "qua" "rather than" "regardless of" "sans" "since" "so" "such as" "than"
+    "that of" "the" "through" "throughout" "thru" "thruout" "till" "to" "toward" "towards"
+    "under" "underneath" "until" "unto" "up" "upon" "v." "van" "versus" "via" "vis-à-vis"
+    "von" "vs." "where as" "with" "within" "without" "yet"))
+
+(defun citeproc-s-title-case (s)
+  "Return a title-cased version of string S."
+  (if (s-present-p s)
+      (with-temp-buffer
+       (insert s)
+       (goto-char 1)
+       (let ((first t)
+             after-colon)
+         (while (forward-word)
+           (let ((word (word-at-point)))
+             (cond ((and (not (or first after-colon))
+                         (member (downcase word) citeproc-s-english-stopwords)
+                         ;; Don't downcase A before a period:
+                         (or (not (string= word "A"))
+                             (= (point) (point-max))
+                             (/= (char-after) ?.)))
+                    (downcase-word -1))
+                   ((s-lowercase-p word)
+                    (capitalize-word -1))))
+           (when first (setq first nil))
+           (when (< (point) (point-max))
+             (setq after-colon (or (= (char-after) ?:)
+                                   (= (char-after) ?.))))))
+       (buffer-string))
+    s))
+
+(defun citeproc-s-smart-quotes (s oq cq)
+  "Replace dumb quotes in string S with smart ones OQ and CQ.
+OQ is the opening quote, CQ is the closing quote to use."
+  (with-temp-buffer
+    (insert s)
+    (goto-char 1)
+    (while (search-forward "\"" nil 1)
+      (let ((w-a-p (word-at-point)))
+       (delete-char -1)
+       (insert (if w-a-p oq cq))))
+    (buffer-string)))
+
+(defun citeproc-s-replace-all-seq (s replacements)
+  "Make replacements in S according to REPLACEMENTS sequentially.
+REPLACEMENTS is an alist with (FROM . TO) elements."
+  (let ((result s))
+    (pcase-dolist (`(,from . ,to) replacements)
+      (setq result (citeproc-s-replace from to result)))
+    result))
+
+(defun citeproc-s-replace-all-sim (s regex replacements)
+  "Replace all matches of REGEX in S according to REPLACEMENTS simultaneously.
+REPLACEMENTS is an alist with (FROM . TO) elements."
+  (replace-regexp-in-string regex
+                           (lambda (match) (cdr (assoc-string match replacements)))
+                           s t t))
+
+(defun citeproc-s-smart-apostrophes (s)
+  "Replace dumb apostophes in string S with smart ones.
+The replacement character used is the unicode character `modifier
+letter apostrophe'."
+  (subst-char-in-string ?' ?ʼ (subst-char-in-string ?’ ?ʼ s t) t))
+
+(defconst citeproc-s--cull-spaces-alist
+  '(("  " . " \7f") (";;" . ";\7f") ("..." . ".\7f\7f") (",," . ",\7f") (".." . ".\7f"))
+  "Alist describing replacements for space and punct culling.")
+
+(defconst citeproc-s--cull-spaces-alist-rx
+  (regexp-opt (mapcar #'car citeproc-s--cull-spaces-alist)))
+
+(defun citeproc-s-cull-spaces-puncts (s)
+  "Replace unnecessary characters with delete chars in string S."
+  (let ((result (citeproc-s-replace-all-seq s citeproc-s--cull-spaces-alist)))
+    (dolist (match-rep '(("\\([:;!?]\\):" . "\\1\7f")
+                        ("\\([:.;!?]\\)\\." . "\\1\7f")
+                        ("\\([:;!]\\)!" . "\7f!")
+                        ("\\([:;?]\\)\\?" . "\7f?")
+                        ("\\.\\([”’‹›«»]\\)\\." . ".\\1\7f")
+                        (",\\([”’‹›«»]\\)," . ",\\1\7f"))
+                      result)
+      (setq result (replace-regexp-in-string (car match-rep)
+                                            (cdr match-rep)
+                                            result)))))
+
+(provide 'citeproc-s)
+
+;;; citeproc-s.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-sort.el b/elpa/citeproc-20230228.1414/citeproc-sort.el
new file mode 100644 (file)
index 0000000..12bdb68
--- /dev/null
@@ -0,0 +1,191 @@
+;;; citeproc-sort.el --- cite and bibliography sorting  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions to sort cites and bibliography items.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'cl-lib)
+(require 'dash)
+(require 's)
+
+(require 'citeproc-lib)
+(require 'citeproc-s)
+(require 'citeproc-rt)
+(require 'citeproc-macro)
+(require 'citeproc-proc)
+(require 'citeproc-name)
+
+(defun citeproc--sort (_attrs _context &rest body)
+  "Placeholder function corresponding to the cs:sort element of CSL."
+  body)
+
+(defun citeproc-sort--name-var-key (var context)
+  "Return the sort-key for name-var VAR using CONTEXT.
+VAR is a CSL name-var name as a symbol. The returned value is a
+string containing a semicolon-separated list of all full names in
+sort order."
+  (citeproc-rt-to-plain
+   (citeproc-rt-render-affixes
+    (citeproc-name--render-var var '((form . "long") (name-as-sort-order . "all")
+                                    (et-al-min . nil) (et-al-use-first . "0")
+                                    (delimiter . "; "))
+                              nil nil nil nil nil context))))
+
+(defun citeproc-sort--date-as-key (d _context)
+  "Render D citeproc-date struct as a sort key."
+  (if d (let ((year (citeproc-date-year d))
+             (month (or (citeproc-date-month d) 0))
+             (day (or (citeproc-date-day d) 0)))
+         ;; We add 5000 as an offset to deal with sorting BC years properly
+         (concat (number-to-string (+ 5000 year))
+                 (citeproc-s-fill-left-to-len (number-to-string month) 2 ?0)
+                 (citeproc-s-fill-left-to-len (number-to-string day) 2 ?0)))
+    ""))
+
+(defun citeproc-sort--date-var-key (var context)
+  "Return the sort-key for name-var VAR using CONTEXT.
+VAR is a symbol."
+  (-let* (((d1 d2) (citeproc-var-value var context))
+         (rendered-first (citeproc-sort--date-as-key d1 context)))
+    (if d2
+       (concat rendered-first "–" (citeproc-sort--date-as-key d2 context))
+      rendered-first)))
+
+(defun citeproc--key (attrs context &rest _body)
+  "Return a sort key corresponding to ATTRS and CONTEXT."
+  (-let (((&alist 'macro macro
+                 'variable var)
+         attrs)
+        (global-attrs (--filter (memq (car it)
+                                      '(names-min names-use-first names-use-last))
+                                attrs)))
+    (if var (let ((var-sym (intern var)))
+             (cond
+              ((memq var-sym citeproc--number-vars)
+               ;; OPTIMIZE: This is way too complicated to simply get a filled
+               ;; numeric value..
+               (citeproc-s-fill-left-to-len
+                (citeproc-number-var-value
+                 (citeproc-var-value var-sym context) var-sym 'numeric context)
+                5))
+              ((memq var-sym citeproc--date-vars)
+               (citeproc-sort--date-var-key var-sym context))
+              ((memq var-sym citeproc--name-vars)
+               (citeproc-sort--name-var-key var-sym context))
+              (t (citeproc-rt-to-plain (citeproc-var-value var-sym context)))))
+      (let ((new-context (citeproc-context--create
+                         :vars (citeproc-context-vars context)
+                         :macros (citeproc-context-macros context)
+                         :terms (citeproc-context-terms context)
+                         :date-text (citeproc-context-date-text context)
+                         :date-numeric (citeproc-context-date-numeric context)
+                         :opts (nconc global-attrs (citeproc-context-opts context))
+                         :mode (citeproc-context-mode context)
+                         :render-mode 'sort
+                         :render-year-suffix nil)))
+       (citeproc-macro-output-as-text macro new-context)))))
+
+(defun citeproc-sort--compare-keys (k1 k2 &optional desc)
+  "Return 1, 0 or -1 depending on the sort-order of keys K1 and K2.
+If optional DESC is non-nil then reverse the comparison for
+descending sort."
+  (cond ((string-collate-equalp k1 k2) 0)
+       ((s-blank? k1) -1)
+       ((s-blank? k2) 1)
+       (t (* (if (string-collate-lessp k1 k2) 1 -1)
+             (if desc -1 1)))))
+
+(defun citeproc-sort--compare-keylists (k1 k2 sort-orders)
+  "Whether keylist K1 precedes keylist K2 in the sort order.
+SORT-ORDERS is a list of sort orders to use (see the bib- and
+cite-sort-orders slots of `citeproc-style' for details)."
+  (citeproc-lib-lex-compare k1 k2 #'citeproc-sort--compare-keys sort-orders))
+
+(defun citeproc-sort--render-keys (style var-alist mode)
+  "Render the sort keys of an item with STYLE and VAR-ALIST.
+MODE is either `cite' or `bib'."
+  (let ((context (citeproc-context-create var-alist style mode 'sort))
+       (sort (cl-ecase mode
+               (cite (citeproc-style-cite-sort style))
+               (bib (citeproc-style-bib-sort style)))))
+    (if sort (funcall sort context) nil)))
+
+(defun citeproc-itd-update-sortkey (itd style)
+  "Update the sort key of itemdata ITD for STYLE."
+  (setf (citeproc-itemdata-sort-key itd)
+       (citeproc-sort--render-keys style (citeproc-itemdata-varvals itd) 'bib)))
+
+(defun citeproc-proc-update-sortkeys (proc)
+  "Update all sort keys of the itemdata in PROC."
+  (let ((style (citeproc-proc-style proc))
+       (itds (citeproc-proc-itemdata proc)))
+    (maphash (lambda (_id itd)
+              (citeproc-itd-update-sortkey itd style))
+            itds)))
+
+(defun citeproc-sort-itds-on-citnum (itds)
+  "Sort itemdata struct list ITDS according to citation number."
+  (sort itds
+       (lambda (x y)
+         (< (string-to-number (citeproc-itd-getvar x 'citation-number))
+            (string-to-number (citeproc-itd-getvar y 'citation-number))))))
+
+(defun citeproc-sort-itds-on-subbib (itd1 itd2)
+  "Sort itemdata structs ITD1 ITD2 according to subbib order."
+  (let ((idx1 (car (citeproc-itemdata-subbib-nos itd1)))
+       (idx2 (car (citeproc-itemdata-subbib-nos itd2))))
+    (and idx1
+        (or (null idx2) (< idx1 idx2)))))
+
+(defun citeproc-sort-itds (itds sort-orders)
+  "Sort the itemdata struct list ITDS according to SORT-ORDERS."
+  (sort itds
+       (lambda (x y)
+         (citeproc-sort--compare-keylists (citeproc-itemdata-sort-key x)
+                                          (citeproc-itemdata-sort-key y)
+                                          sort-orders))))
+
+(defun citeproc-proc-sort-itds (proc)
+  "Sort the itemdata in PROC."
+  (let ((is-sorted-bib (citeproc-style-bib-sort (citeproc-proc-style proc)))
+       (is-filtered (citeproc-proc-filtered-bib-p proc)))
+    (when (or is-sorted-bib is-filtered)
+      (let* ((itds (hash-table-values (citeproc-proc-itemdata proc)))
+            (sorted (if is-sorted-bib
+                        (let ((sort-orders (citeproc-style-bib-sort-orders
+                                            (citeproc-proc-style proc))))
+                          (citeproc-sort-itds itds sort-orders))
+                      (citeproc-sort-itds-on-citnum itds))))
+       ;; Additionally sort according to subbibliographies if there are filters.
+       (when is-filtered
+         (setq sorted (sort sorted #'citeproc-sort-itds-on-subbib)))
+       ;; Set the CSL citation-number field according to the sort order.
+       (--each-indexed sorted
+         (citeproc-itd-setvar it 'citation-number
+                              (number-to-string (1+ it-index))))))))
+
+(provide 'citeproc-sort)
+
+;;; citeproc-sort.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-style.el b/elpa/citeproc-20230228.1414/citeproc-style.el
new file mode 100644 (file)
index 0000000..e7dd4c7
--- /dev/null
@@ -0,0 +1,344 @@
+;; citeproc-style.el --- CSL style structure and related functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Structure type and functions for constructing and accessing CSL style
+;; objects.
+
+;;; Code:
+
+(require 'subr-x)
+(require 'let-alist)
+(require 'dash)
+(require 'cl-lib)
+(require 's)
+
+(require 'citeproc-lib)
+(require 'citeproc-locale)
+
+(cl-defstruct (citeproc-style (:constructor citeproc-style--create))
+  "A struct representing a parsed and localized CSL style.
+INFO is the style's general info (currently simply the
+  corresponding fragment of the parsed xml),
+OPTS, BIB-OPTS, CITE-OPTS and LOCALE-OPTS are alists of general
+  and bibliography-, cite- and locale-specific CSL options,
+BIB-SORT, BIB-LAYOUT, CITE-SORT and CITE-LAYOUT are anonymous
+  functions for calculating sort-keys and rendering,
+BIB-SORT-ORDERS and CITE-SORT-ORDERS are the lists of sort orders
+  for bibliography and cite sort (the value is a list containg t
+  or nil as its n-th element depending on whether the sort for on
+  the n-th key should be in ascending or desending order,
+CITE-LAYOUT-ATTRS contains the attributes of the citation layout
+  as an alist,
+CITE-NOTE is non-nil iff the style's citation-format is \"note\",
+DATE-TEXT and DATE-NUMERIC are the style's date formats,
+LOCALE contains the locale to be used or nil if not set,
+MACROS is an alist with macro names as keys and corresponding
+  anonymous rendering functions,
+TERMS is the style's parsed term-list,
+USES-YS-VAR is non-nil iff the style uses the YEAR-SUFFIX
+  CSL-variable."
+  info opts bib-opts bib-sort bib-sort-orders
+  bib-layout cite-opts cite-note cite-sort cite-sort-orders
+  cite-layout cite-layout-attrs locale-opts macros terms
+  uses-ys-var date-text date-numeric locale)
+
+(defun citeproc-style-parse (style)
+  "Return the parsed representation of csl STYLE.
+STYLE is either a path to a style file or a style as a string.
+Returns a (YEAR-SUFF-P . PARSED-STYLE) cons cell. YEAR-SUFF-P is
+non-nil if the style uses the `year-suffix' csl var; PARSED-STYLE
+is the parsed form of the xml STYLE-FILE."
+  (let ((xml-input (s-matches-p " ?<" style)))
+    (with-temp-buffer
+      (let ((case-fold-search t))
+       (if xml-input (insert style)
+         (insert-file-contents style))
+       (goto-char 1)
+       (cons (re-search-forward "variable=\"year-suffix\"" nil t)
+             (citeproc-lib-remove-xml-comments
+              (libxml-parse-xml-region (point-min) (point-max))))))))
+
+;; TODO: Parse and store info in a more structured and sensible form. Also,
+;; currently the first in-style locale is loaded that is compatible with the
+;; locale to be used. In theory, there may be more than one compatible in-style
+;; locales that should be merged in an order reflecting their closeness to the
+;; requested locale.
+(defun citeproc-create-style-from-locale (parsed-style year-suffix locale)
+  "Create a citation style from parsed xml style PARSED-STYLE.
+YEAR-SUFFIX specifies whether the style explicitly uses the
+`year-suffix' csl variable. LOCALE is the locale for which
+in-style locale information will be loaded (if available)."
+  (let* ((style (citeproc-style--create))
+        (style-opts (cadr parsed-style))
+        locale-loaded)
+    (setf (citeproc-style-opts style) style-opts
+         (citeproc-style-uses-ys-var style) year-suffix
+         (citeproc-style-locale style)
+         (or locale (alist-get 'default-locale style-opts)))
+    (--each (cddr parsed-style)
+      (pcase (car it)
+       ('info
+        (let ((info-lst (cddr it)))
+          (setf (citeproc-style-info style) info-lst
+                (citeproc-style-cite-note style)
+                (not (not (member '(category
+                                    ((citation-format . "note")))
+                                  info-lst))))))
+       ('locale
+        (let ((lang (alist-get 'lang (cadr it))))
+          (when (and (citeproc-locale--compatible-p lang locale)
+                     (not locale-loaded))
+            (citeproc-style--update-locale style it)
+            (setq locale-loaded t))))
+       ('citation
+        (citeproc-style--update-cite-info style it))
+       ('bibliography
+        (citeproc-style--update-bib-info style it))
+       ('macro
+        (citeproc-style--update-macros style it))))
+    style))
+
+(defun citeproc-style--parse-layout-and-sort-frag (frag)
+  "Parse a citation or bibliography style xml FRAG.
+Return an alist with keys `layout', `opts', `layout-attrs', `sort'
+and `sort-orders'."
+  (let* ((opts (cadr frag))
+        (sort-p (eq (cl-caaddr frag) 'sort))
+        (layout (citeproc-style--transform-xmltree
+                 (elt frag (if sort-p 3 2))))
+        (layout-attrs (cl-cadadr (cl-caddr layout)))
+        sort sort-orders)
+    (when sort-p
+      (let* ((sort-frag (cl-caddr frag)))
+       (setq sort (citeproc-style--transform-xmltree sort-frag)
+             sort-orders (--map (not (string= "descending" (alist-get 'sort (cadr it))))
+                                (cddr sort-frag)))))
+    `((opts . ,opts) (layout . ,layout) (layout-attrs . ,layout-attrs)
+      (sort . ,sort) (sort-orders . ,sort-orders))))
+
+(defun citeproc-style--update-cite-info (style frag)
+  "Update the cite info of STYLE on the basis of its parsed FRAG."
+  (let-alist (citeproc-style--parse-layout-and-sort-frag frag)
+    (setf (citeproc-style-cite-opts style) .opts
+         (citeproc-style-cite-layout style) .layout
+         (citeproc-style-cite-layout-attrs style) .layout-attrs
+         (citeproc-style-cite-sort style) .sort
+         (citeproc-style-cite-sort-orders style) .sort-orders)))
+
+(defun citeproc-style--update-bib-info (style frag)
+  "Update the bib info of STYLE on the basis of its parsed FRAG."
+  (let-alist (citeproc-style--parse-layout-and-sort-frag frag)
+    (setf (citeproc-style-bib-opts style) .opts
+         (citeproc-style-bib-layout style) .layout
+         (citeproc-style-bib-sort style) .sort
+         (citeproc-style-bib-sort-orders style) .sort-orders)))
+
+(defun citeproc-style--update-macros (style frag)
+  "Update the macro info of STYLE on the basis of its parsed FRAG."
+  (let ((name (cl-cdaadr frag)))
+    (setf (car frag) 'macro)
+    (setf (cadr frag) nil)
+    (push (cons name (citeproc-style--transform-xmltree frag))
+         (citeproc-style-macros style))))
+
+(defun citeproc-style--update-locale (style frag)
+  "Update locale info in STYLE using xml fragment FRAG.
+FRAG should be a parsed locale element from a style or a locale."
+  (--each (cddr frag)
+    (pcase (car it)
+      ('style-options (setf (citeproc-style-locale-opts style)
+                           (-concat (citeproc-style-locale-opts style)
+                                    (cadr it))))
+      ('date
+       (citeproc-style--update-locale-date style it))
+      ('terms
+       (let ((parsed-terms (citeproc-locale-termlist-from-xml-frag (cddr it))))
+        (setf (citeproc-style-terms style)
+              (if (citeproc-style-terms style)
+                  (citeproc-term-list-update parsed-terms (citeproc-style-terms style))
+                parsed-terms)))))))
+
+(defun citeproc-style--update-locale-date (style frag)
+  "Update date info in STYLE using xml fragment FRAG.
+FRAG should be a parsed locale element from a style or a locale."
+  (let* ((date-attrs (cadr frag))
+        (form (alist-get 'form date-attrs))
+        (date-format (cons date-attrs
+                           (citeproc-lib-named-parts-to-alist frag))))
+    (if (string= form "text")
+       (unless (citeproc-style-date-text style)
+         (setf (citeproc-style-date-text style) date-format))
+      (unless (citeproc-style-date-numeric style)
+       (setf (citeproc-style-date-numeric style) date-format)))))
+
+(defconst citeproc-style--opt-defaults
+  '((cite-opts near-note-distance "5")
+    (locale-opts punctuation-in-quote "false")
+    (locale-opts limit-day-ordinals-to-day-1 "false")
+    (bib-opts hanging-indent "false")
+    (bib-opts line-spacing "1")
+    (bib-opts entry-spacing "1")
+    (opts initialize-with-hyphen "true")
+    (opts demote-non-dropping-particle "display-and-sort"))
+  "Global style options.
+Specified as a list of (STYLE-SLOT OPTION-NAME OPTION-DEFAULT)
+lists.
+
+Note: Collapse-related options are not specified here since their
+default settings are interdependent.")
+
+(defun citeproc-style--set-opt (style opt-slot opt value)
+  "Set OPT in STYLE's OPT-SLOT to VALUE."
+  (setf (cl-struct-slot-value 'citeproc-style opt-slot style)
+       (cons (cons opt value)
+             (cl-struct-slot-value 'citeproc-style opt-slot style))))
+
+(defun citeproc-style--set-opt-defaults (style)
+  "Set missing options of STYLE to their default values."
+  (cl-loop
+   for (slot option value) in citeproc-style--opt-defaults do
+   (let ((slot-value (cl-struct-slot-value 'citeproc-style slot style)))
+     (unless (alist-get option slot-value)
+       (setf (cl-struct-slot-value 'citeproc-style slot style)
+            (cons (cons option value) slot-value)))))
+  (let* ((cite-opts (citeproc-style-cite-opts style))
+        (collapse (alist-get 'collapse cite-opts)))
+    (when (and collapse (not (string= collapse "citation-number")))
+      (let ((cite-layout-dl
+            (alist-get 'delimiter (citeproc-style-cite-layout-attrs style)))
+           (cite-group-dl
+            (alist-get 'cite-group-delimiter cite-opts)))
+       (unless cite-group-dl
+         (citeproc-style--set-opt style 'cite-opts 'cite-group-delimiter ", "))
+       (unless (alist-get 'after-collapse-delimiter cite-opts)
+         (citeproc-style--set-opt
+          style 'cite-opts 'after-collapse-delimiter cite-layout-dl))
+       (when (and (member collapse '("year-suffix" "year-suffix-ranged"))
+                  (null (alist-get 'year-suffix-delimiter cite-opts)))
+         (citeproc-style--set-opt
+          style 'cite-opts 'year-suffix-delimiter cite-layout-dl))))))
+
+(defun citeproc-style--transform-xmltree (tree)
+  "Transform parsed csl xml fragment TREE into a lambda."
+  `(lambda (context) ,(citeproc-style--transform-xmltree-1 tree)))
+
+(defun citeproc-style--transform-xmltree-1 (tree)
+  "Transform parsed xml fragment TREE into an eval-able form.
+Symbols in car position are prefixed with `citeproc--' and the
+symbol `context' is inserted everywhere after the second (attrs)
+position and before the (possibly empty) body."
+  (pcase tree
+    ((pred atom) tree)
+    (`(names . ,_) (citeproc-style--transform-names tree))
+    (_
+     `(,(intern (concat "citeproc--" (symbol-name (car tree))))
+       ,(list 'quote (cadr tree))
+       context
+       ,@(mapcar #'citeproc-style--transform-xmltree-1 (cddr tree))))))
+
+(defun citeproc-style--transform-names (frag)
+  "Transform the content of a cs:names CSL element xml FRAG."
+  (let* ((names-attrs (cadr frag))
+        (body (-remove #'stringp (cddr frag)))
+        (vars (alist-get 'variable names-attrs))
+        substs name-attrs name-parts et-al-attrs
+        is-label label-attrs label-before-names)
+    (--each body
+      (pcase (car it)
+       ('name
+        (setq name-attrs (cadr it)
+              name-parts (citeproc-lib-named-parts-to-alist it)
+              label-before-names t))
+       ('et-al
+        (setq et-al-attrs (cadr it)))
+       ('label
+        (setq is-label t
+              label-attrs (cadr it)
+              label-before-names nil))
+       ('substitute
+        (setq substs
+              (mapcar
+               (lambda (x)
+                 (if (eq (car x) 'names)
+                     `(citeproc-name-render-vars
+                       ,(alist-get 'variable (cadr x))
+                       names-attrs name-attrs name-parts et-al-attrs
+                       is-label label-before-names label-attrs context)
+                   (citeproc-style--transform-xmltree-1 x)))
+               (cddr it))))))
+    `(if (citeproc-var-value 'suppress-author context) (cons nil 'empty-vars)
+       (let* ((names-attrs ',names-attrs)
+             (name-attrs ',name-attrs)
+             (count (string= (alist-get 'form name-attrs) "count"))
+             (et-al-attrs ',et-al-attrs)
+             (name-parts ',name-parts)
+             (label-attrs ',label-attrs)
+             (is-label ,is-label)
+             (label-before-names ,label-before-names)
+             (val (citeproc-name-render-vars
+                   ,vars names-attrs name-attrs name-parts et-al-attrs
+                   is-label label-before-names label-attrs context))
+             (result (if (car val)
+                         val
+                       (-if-let ((cont . type) (--first (car it)
+                                                        (list ,@substs)))
+                           (cons (cons (list '(subst . t)) (list cont)) type)
+                         (cons nil 'empty-vars))))
+             (final (if count
+                        (let* ((number (citeproc-rt-count-names (car result)))
+                               (str (if (= 0 number) "" (number-to-string number))))
+                          (cons str (cdr result)))
+                      result)))
+        ;; Handle `author' citation mode by stopping if needed
+        (citeproc-lib-maybe-stop-rendering 'names context final)))))
+
+(defun citeproc-style-global-opts (style layout)
+  "Return the global opts in STYLE for LAYOUT.
+LAYOUT is either `bib' or `cite'."
+  (-concat (cl-ecase layout
+            (bib (citeproc-style-bib-opts style))
+            (cite (citeproc-style-cite-opts style)))
+          (citeproc-style-opts style)))
+
+(defun citeproc-style-bib-opts-to-formatting-params (bib-opts)
+  "Convert BIB-OPTS to a formatting parameters alist."
+  (let ((result
+        (cl-loop
+         for (opt . val) in bib-opts
+         if (memq opt
+                  '(hanging-indent line-spacing entry-spacing second-field-align))
+         collect (cons opt
+                       (pcase val
+                         ("true" t)
+                         ("false" nil)
+                         ("flush" 'flush)
+                         ("margin" 'margin)
+                         (_ (string-to-number val)))))))
+    (if (alist-get 'second-field-align result)
+       result
+      (cons (cons 'second-field-align nil)
+           result))))
+
+(provide 'citeproc-style)
+
+;;; citeproc-style.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-subbibs.el b/elpa/citeproc-20230228.1414/citeproc-subbibs.el
new file mode 100644 (file)
index 0000000..4379e67
--- /dev/null
@@ -0,0 +1,86 @@
+;;; citeproc-subbibs.el --- support for subbibliographies -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Support for generating subbibliographies based on filtering items.
+
+;;; Code:
+
+(require 'dash)
+
+(require 'citeproc-proc)
+(require 'citeproc-itemdata)
+
+(defun citeproc-sb--match-p (vv filter)
+  "Return whether var-vals alist VV matches all conditions in FILTER.
+FILTER should be an alist containing symbol keys and string
+values, each pair describing an atomic condition to be
+satisified. For a list and description of the supported keys
+see the documentation of `citeproc-add-subbib-filters'."
+  (let* ((csl-type (alist-get 'type vv))
+        (type (or (alist-get 'blt-type vv) csl-type))
+        (keyword (alist-get 'keyword vv))
+        (keywords (and keyword (split-string keyword "[ ,;]" t))))
+    (--every-p
+     (pcase it
+       (`(type . ,key) (string= type key))
+       (`(nottype . ,key) (not (string= type key)))
+       (`(keyword . ,key) (member key keywords))
+       (`(notkeyword . ,key) (not (member key keywords)))
+       (`(filter . ,key) (funcall (intern key) vv))
+       (`(csltype . ,key) (string= csl-type key))
+       (`(notcsltype . ,key) (not (string= csl-type key)))
+       (`(,key . ,_) (error "Unsupported Citeproc filter keyword `%s'" key)))
+     filter)))
+
+(defun citeproc-sb-add-subbib-info (proc)
+  "Add subbibliography information to the items in PROC."
+  (when (citeproc-proc-filtered-bib-p proc)
+    (let ((filters (citeproc-proc-bib-filters proc)))
+      (maphash
+       (lambda (_ itemdata)
+        (let* ((varvals (citeproc-itemdata-varvals itemdata))
+               (subbib-nos
+                (-non-nil
+                 (--map-indexed
+                  (when (citeproc-sb--match-p varvals it) it-index)
+                  filters))))
+          (setf (citeproc-itemdata-subbib-nos itemdata) subbib-nos)))
+       (citeproc-proc-itemdata proc)))))
+
+(defun citeproc-sb-prune-unrendered (proc)
+  "Remove all itemdata about unrendered items from PROC.
+An item is unrendered if
+- there are subbibfilters but none of them matches it, and
+- it is not cited."
+  (when (citeproc-proc-filtered-bib-p proc)
+    (let ((itemdata (citeproc-proc-itemdata proc)))
+      (maphash
+       (lambda (id data)
+        (when (and (citeproc-itemdata-uncited data)
+                   (null (citeproc-itemdata-subbib-nos data)))
+          (remhash id itemdata)))
+       itemdata))))
+
+(provide 'citeproc-subbibs)
+
+;;; citeproc-subbibs.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-term.el b/elpa/citeproc-20230228.1414/citeproc-term.el
new file mode 100644 (file)
index 0000000..ce9bbaf
--- /dev/null
@@ -0,0 +1,113 @@
+;;; citeproc-term.el --- functions for term localization -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions for localizing the terms of a CSL style according to a locale.
+
+;;; Code:
+
+(require 'dash)
+(require 'cl-lib)
+(require 'let-alist)
+
+(require 'citeproc-lib)
+(require 'citeproc-s)
+
+(cl-defstruct (citeproc-term (:constructor citeproc-term--create))
+  "A struct representing a localized term."
+  (name nil) (form nil) (number nil) (gender nil) (gender-form nil)
+  (match nil) (text nil))
+
+(defun citeproc-term--compare (t1 t2)
+  "Compare terms T1 and T2.
+The comparison is based on the term fields except the last one,
+and relies on the alphabetical ordering of fields' string
+content (see the function `citeproc-lib-s-content'). Return 1, -1
+or 0 iff T1 precedes, succeeds or is equal according to the
+ordering."
+  (cond ((not t2) 1)
+       ((not t1) -1)
+       (t (let ((idx 1)
+                (result 0))
+            (while (and (= result 0) (< idx 7))
+              (let ((s1 (citeproc-s-content (aref t1 idx)))
+                    (s2 (citeproc-s-content (aref t2 idx))))
+                (cond ((string< s1 s2) (setq result 1))
+                      ((string> s1 s2) (setq result -1))))
+              (cl-incf idx)) result))))
+
+(defun citeproc-term-list--sort (tl)
+  "Sort termlist TL in place using `citeproc-term--compare'."
+  (cl-sort tl (lambda (x y) (> (citeproc-term--compare x y) -1))))
+
+(defun citeproc-term-list-update (tl1 tl2 &optional sorted-input)
+  "Return a term list which is TL1 updated with term list TL2.
+TL1 and TL2 are list of citeproc-term structs. The order of terms
+in the returned term list is undetermined. If the optional
+SORTED-INPUT is non-nil then the term lists are supposed to be
+already sorted according to `citeproc-term--compare', otherwise
+they are sorted in-place."
+  (let (result)
+    (unless sorted-input
+      (setq tl1 (citeproc-term-list--sort tl1)
+           tl2 (citeproc-term-list--sort tl2)))
+    (while (or tl1 tl2)
+      (let* ((t1 (car tl1))
+            (t2 (car tl2))
+            (cmp (citeproc-term--compare t1 t2)))
+       (cond ((= cmp 1) (push t1 result) (pop tl1))
+             ((= cmp -1) (push t2 result) (pop tl2))
+             (t (push t2 result) (pop tl1) (pop tl2)))))
+    result))
+
+(defun citeproc-term--from-xml-frag (frag)
+  "Transform xml FRAG representing a term into a citeproc-term struct."
+  (let-alist (car frag)
+    (-let* ((.form (or .form "long"))
+           (term (citeproc-term--create
+                  :name .name
+                  :form (citeproc-lib-intern .form)
+                  :gender (citeproc-lib-intern .gender)
+                  :match (citeproc-lib-intern .match)
+                  :gender-form (citeproc-lib-intern .gender-form))))
+      (if (= (length frag) 2)
+         (progn
+           (setf (citeproc-term-text term) (cadr frag))
+           (list term))
+       (setf (citeproc-term-text term) (cl-caddr (cadr frag)))
+       (setf (citeproc-term-number term) 'single)
+       (let ((multi-term (copy-citeproc-term term)))
+         (setf (citeproc-term-text multi-term) (cl-caddr (cl-caddr frag)))
+         (setf (citeproc-term-number multi-term) 'multiple)
+         (list term multi-term))))))
+
+(defun citeproc-term-text-from-terms (term terms)
+  "Return the first text associated with TERM in TERMS.
+Return nil if TERM is not in TERMS."
+  (-if-let (match (--first (string= term (citeproc-term-name it))
+                          terms))
+      (citeproc-term-text match)
+    nil))
+
+(provide 'citeproc-term)
+
+;;; citeproc-term.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc-test-human.el b/elpa/citeproc-20230228.1414/citeproc-test-human.el
new file mode 100644 (file)
index 0000000..202e5e1
--- /dev/null
@@ -0,0 +1,207 @@
+;; citeproc-test-human.el --- support tests in CSL suite format -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2021 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Functions to create ERT tests from tests in CSL test suite format. The
+;; official tests can be found at
+;; <https://github.com/citation-style-language/test-suite>.
+
+;;; Code:
+
+(require 'f)
+(require 's)
+(require 'json)
+(require 'ert)
+(require 'string-inflection)
+
+(require 'citeproc)
+
+(defvar citeproc-test-human--locale-dir "./test/locales")
+
+(defun citeproc-test-human--parse-testfile (file)
+  "Return a parsed form of CSL test FILE."
+  (let (result
+       (json-array-type 'list)
+       (json-key-type 'symbol))
+    (with-temp-buffer
+      (insert-file-contents file)
+      (goto-char 1)
+      (setq result (list (cons 'YEAR-SUFF
+                              (re-search-forward "variable=\"year-suffix\"" nil t))))
+      (goto-char 1)
+      (while (re-search-forward ">>=+ \\{1,2\\}\\([[:graph:]]+\\) =+>>" nil t)
+       (let ((section (intern (buffer-substring (nth 2 (match-data))
+                                                (nth 3 (match-data)))))
+             (start (1+ (point)))
+             end)
+         (re-search-forward "<<=" nil t)
+         (setq end (- (car (match-data)) 1))
+         (push (cons section (pcase section
+                               ('OUTPUT-FORMAT
+                                (intern (buffer-substring-no-properties start end)))
+                               ('CSL (buffer-substring-no-properties start end))
+                               ((or 'INPUT 'CITATIONS 'CITATION-ITEMS)
+                                (goto-char (- start 1)) (json-read))
+                               (_ (buffer-substring start end))))
+               result))))
+    result))
+
+(defun citeproc-test-human--create-getter (items)
+  "Return a getter function for ITEMS.
+ITEMS is the parsed representation of the `INPUT' section of a
+CSL test."
+  (lambda (itemids)
+    (let (result)
+     (dolist (item items result)
+       (let ((id (citeproc-s-from-num-or-s (alist-get 'id item))))
+        (when (member id itemids)
+          (push (cons id item) result)))))))
+
+(defun citeproc-test-human--proc-from-style (style parsed-input)
+  "Create a processor from STYLE and PARSED-INPUT."
+  (citeproc-create style
+                  (citeproc-test-human--create-getter parsed-input)
+                  (citeproc-locale-getter-from-dir citeproc-test-human--locale-dir)))
+
+(defun citeproc-test-human--proc-from-testfile (file)
+  "Create an (itemless) processor from a test FILE."
+  (let ((style-string (alist-get 'CSL (citeproc-test-human--parse-testfile file)))
+       (locale-getter (citeproc-locale-getter-from-dir citeproc-test-human--locale-dir)))
+    (citeproc-create style-string nil locale-getter)))
+
+(defun citeproc-test-human--parse-citation (ct-desc &optional cites-only)
+  "Parse test citations description CT-DESC.
+Return a list of citation structures. If CITES-ONLY is non-nil
+then the input is list of cites."
+  (if cites-only
+      (citeproc-citation-create
+       :cites (-map #'citeproc-test-human--normalize-cite ct-desc))
+    (let ((citation-info (car ct-desc)))
+      (let-alist (alist-get 'properties citation-info)
+       (citeproc-citation-create
+        :cites (-map #'citeproc-test-human--normalize-cite
+                     (alist-get 'citationItems citation-info))
+        :note-index .noteIndex
+        :mode (citeproc-lib-intern .mode)
+        :capitalize-first .capitalize-first
+        :suppress-affixes .suppress-affixes
+        :ignore-et-al .ignore-et-al)))))
+
+(defun citeproc-test-human--normalize-cite (cite)
+  "Normalize a test CITE."
+  (--map (let ((val (cdr it)))
+          (if (numberp val) (cons (car it) (number-to-string val)) it))
+        cite))
+
+(defun citeproc-test-human--run-parsed (parsed)
+  "Run the parsed CSL test PARSED.
+Return the resulting output."
+  (-let* (((&alist 'CSL style
+                  'INPUT input
+                  'MODE mode
+                  'CITATION-ITEMS citation-items
+                  'CITATIONS citations
+                  'OUTPUT-FORMAT output-format)
+          parsed)
+         (output-format (or output-format 'csl-test))
+         (proc (citeproc-test-human--proc-from-style style input)))
+    (--each input
+      (citeproc-proc-put-item-by-id proc
+                                   (citeproc-s-from-num-or-s (alist-get 'id it))))
+    (when (string= mode "citation")
+      (cond
+       (citation-items
+       (citeproc-append-citations (--map (citeproc-test-human--parse-citation it t)
+                                         citation-items)
+                                  proc))
+       (citations
+       (citeproc-append-citations (mapcar #'citeproc-test-human--parse-citation citations)
+                                  proc))
+       (t (citeproc-append-citations (list (citeproc-test-human--parse-citation input t))
+                                    proc))))
+    (let ((output (if (string= mode "citation")
+                     (citeproc-render-citations proc output-format
+                                                (when (eq 'csl-test output-format)
+                                                  'no-links))
+                   (car (citeproc-render-bib proc output-format 'no-links)))))
+      (if (string= mode "citation") (s-join "\n" output) output))))
+
+(defun citeproc-test-human--expected-from-parsed (parsed)
+  "Return the expected output of parsed CSL test PARSED."
+  (let ((expected (alist-get 'RESULT parsed)))
+    (if (or (string= (s-left 5 expected) "..[0]")
+           (string= (s-left 5 expected) ">>[0]"))
+       (s-join "\n" (--map (substring it 6)
+                           (split-string expected "\n")))
+      expected)))
+
+(defun citeproc-test-human-create-from-file (file expected-fails &optional name-prefix)
+  "Create an ERT test from a CSL test FILE.
+If optional NAME-PREFIX is non-nil then it is added the name of
+the created test after the obligatory `citeproc'."
+  (let* ((parsed (citeproc-test-human--parse-testfile file))
+        (expected (citeproc-test-human--expected-from-parsed parsed))
+        (file-name (f-filename file))
+        (test-name (intern
+                    (concat "citeproc-"
+                            (if name-prefix  (concat name-prefix "-") "")
+                            (string-inflection-kebab-case-function
+                             (substring file-name 0 -4)))))
+        (expected-fail (memq test-name expected-fails)))
+    (eval `(ert-deftest ,test-name ()
+            :expected-result ,(if expected-fail :failed :passed)
+            (let ((citeproc-disambiguation-cite-pos 'subsequent))
+              (should (string=
+                       ,expected
+                       (citeproc-test-human--run-parsed ',parsed))))))))
+
+(defun citeproc-test-human---read-expected-fails (expected-fails-file)
+  "Read the list of tests expected to fail from EXPECTED-FAILS-FILE."
+  (let* ((list-as-str (with-temp-buffer
+                       (insert-file-contents expected-fails-file)
+                       (buffer-string)))
+        (split (split-string list-as-str "\n")))
+    (--map (intern it) (butlast split))))
+
+(defun citeproc-test-human-create-from-dir (dir &optional
+                                               expected-fails-file name-prefix)
+  "Create all CSL tests from DIR.
+Each file in DIR having the `txt' extension is read as a
+human-readable CSL test, and a corresponding ERT test is created.
+The created test's name will be constructed by prefixing the
+test's filename (without the extension) with `citeproc-'. If the
+optional EXPECTED-FAILS-FILE is non-nil then read that file as a
+list of tests whose failure is expected. If optional NAME-PREFIX
+is non-nil then it is added the names of the created tests after
+the obligatory `citeproc'. The file should contain one test-name
+per line (together with the `citeproc-' prefix)."
+  (let ((expected-fails
+        (if expected-fails-file
+            (citeproc-test-human---read-expected-fails expected-fails-file)
+          nil)))
+    (dolist (test-file (f-glob (concat dir "/*.txt")))
+      (citeproc-test-human-create-from-file test-file expected-fails
+                                           name-prefix))))
+
+(provide 'citeproc-test-human)
+
+;;; citeproc-test-human.el ends here
diff --git a/elpa/citeproc-20230228.1414/citeproc.el b/elpa/citeproc-20230228.1414/citeproc.el
new file mode 100644 (file)
index 0000000..0a930ba
--- /dev/null
@@ -0,0 +1,317 @@
+;;; citeproc.el --- A CSL 1.0.2 Citation Processor -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2023 András Simonyi
+
+;; Author: András Simonyi <andras.simonyiNOSPAMgmail.com>
+;; Maintainer: András Simonyi <andras.simonyiNOSPAMgmail.com>
+;; URL: https://github.com/andras-simonyi/citeproc-el
+;; Keywords: bib
+;; Package-Requires: ((emacs "26") (dash "2.13.0") (s "1.12.0") (f "0.18.0") (queue "0.2") (string-inflection "1.0") (org "9") (parsebib "2.4"))
+;; Version: 0.9.3
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; citeproc-el is a library for rendering citations and bibliographies in styles
+;; described in the Citation Style Language (CSL).
+
+;;; Code:
+
+(require 'dash)
+(require 'queue)
+
+(require 'citeproc-rt)
+(require 'citeproc-locale)
+(require 'citeproc-style)
+(require 'citeproc-choose)
+(require 'citeproc-generic-elements)
+(require 'citeproc-context)
+(require 'citeproc-itemdata)
+(require 'citeproc-proc)
+(require 'citeproc-cite)
+(require 'citeproc-sort)
+(require 'citeproc-formatters)
+(require 'citeproc-itemgetters)
+(require 'citeproc-subbibs)
+
+;;; Public API
+
+(defun citeproc-create (style it-getter loc-getter &optional loc force-loc)
+  "Return a CSL processor for a given STYLE, IT-GETTER and LOC-GETTER.
+STYLE is either a path to a CSL style file or a CSL style as a
+  string.
+IT-GETTER is an item-getter function that takes a list of itemid
+  strings as its sole argument and returns an alist in which the
+  given itemids are the keys and the values are the parsed csl
+  json descriptions of the corresponding bibliography items (keys
+  are symbols, arrays and hashes should be represented as lists
+  and alists, respecively).
+LOC-GETTER is a function that takes a locale string (e.g.
+  \"en-GB\") as an argument and returns a corresponding parsed
+  CSL locale (as parsed by Emacs's `libxml-parse-xml-region').
+Optional LOC is the locale to use if the style doesn't specify a
+  default one. Defaults to \"en-US\".
+If optional FORCE-LOC is non-nil then use locale LOC even if
+  STYLE specifies a different one as default. Defaults to nil."
+  (let ((style (citeproc-create-style style loc-getter loc force-loc))
+       (names (make-hash-table :test 'equal))
+       (itemdata (make-hash-table :test 'equal))
+       (citations (make-queue)))
+    (citeproc-proc--create :style style :getter it-getter :names names 
+                          :itemdata itemdata :citations citations :finalized t)))
+
+(defun citeproc-append-citations (citations proc)
+  "Append CITATIONS to the list of citations in PROC.
+CITATIONS is a list of `citeproc-citation' structures."
+  (let ((itemdata (citeproc-proc-itemdata proc))
+       ids)
+    ;; Collect new itemids
+    (dolist (citation citations)
+      (dolist (cite (citeproc-citation-cites citation))
+       (push (alist-get 'id cite) ids)))
+    (let* ((uniq-ids (delete-dups (nreverse ids))) ; reverse pushed ids
+          (new-ids (--remove (gethash it itemdata) uniq-ids)))
+      ;; Add all new items in one pass
+      (citeproc-proc-put-items-by-id proc new-ids)
+      ;; Add itemdata to the cite structs and add them to the cite queue.
+      (dolist (citation citations)
+       (setf (citeproc-citation-cites citation)
+             (--map (cons (cons 'itd (gethash (alist-get 'id it) itemdata)) it)
+                    (citeproc-citation-cites citation)))
+       (queue-append (citeproc-proc-citations proc) citation))
+      (setf (citeproc-proc-finalized proc) nil))))
+
+(defun citeproc-add-uncited (itemids proc)
+  "Add uncited bib items with ITEMIDS to PROC.
+As an extension, an itemid can be the string \"*\" which has the
+effect of adding all items available in the itemgetter."
+  ;; We simply store the added ids here, real processing is performed when the
+  ;; processor is finalized.
+  (push itemids (citeproc-proc-uncited proc))
+  (setf (citeproc-proc-finalized proc) nil))
+
+(defun citeproc-add-subbib-filters (filters proc)
+  "Add sub-bibliography FILTERS to PROC.
+FILTERS should be a list of alists containing symbol keys and
+string values, each pair describing an atomic condition to be
+satisified by the printed entries. The following keys are
+supported:
+- `type': print only entries of the given type. Type is the
+  bib(la)tex entry type if available, otherwise the CSL type is
+  used as fallback;
+- `nottype': print only entries not of the given type. Type is
+  the bib(la)tex entry type if available, otherwise the CSL type
+  is used as fallback;
+- `csltype', `notcsltype': same as `type' and `nottype' but uses
+  the entries' CSL type even if the bib(la)tex type is also
+  available;
+- `keyword': print only entries with the given keyword;
+- `notkeyword': print only entries without the given keyword;
+- `filter': print only entries for which the function named by
+  the key returns a non-nil value."
+  (setf (citeproc-proc-bib-filters proc) filters
+       (citeproc-proc-finalized proc) nil))
+
+(defun citeproc-render-citations (proc format &optional internal-links)
+  "Render all citations in PROC in the given FORMAT.
+Return a list of formatted citations.
+  If the optional INTERNAL-LINKS is `bib-links' then link cites
+to the bibliography regardless of the style type, if `no-links'
+then don't add internal links, if nil or `auto' then add internal
+links based on the style type (cite-cite links for note styles
+and cite-bib links else). For legacy reasons, any other value is
+treated as `no-links'."
+  (citeproc-proc-finalize proc)
+  (--map (citeproc-citation--render-formatted-citation it proc format internal-links)
+        (queue-head (citeproc-proc-citations proc))))
+
+(defun citeproc-render-bib (proc format &optional internal-links
+                                no-external-links bib-formatter-fun)
+  "Render a bibliography of items in PROC in FORMAT.
+For the optional INTERNAL-LINKS argument see
+`citeproc-render-citations'. If the optional NO-EXTERNAL-LINKS is
+non-nil then don't generate external links. If the optional
+BIB-FORMATTER-FUN is given then it will be used to join the
+bibliography items instead of the content of the chosen
+formatter's `bib' slot (see `citeproc-formatter' for details).
+
+Returns an error message string if the style of PROC doesn't
+contain a bibliography section. Otherwise it returns
+a (FORMATTED-BIBLIOGRAPHY . FORMATTING-PARAMETERS) cons cell,
+where FORMATTED-BIBLIOGRAPHY is either a single bibliography or a
+list of sub-bibliograhies if filters were added to the processor,
+and FORMATTING-PARAMETERS is an alist containing the following
+formatting parameters keyed to the parameter names as symbols:
+- `max-offset' (integer): The width of the widest first field in
+  the bibliography, measured in characters.
+- `line-spacing' (integer): Vertical line distance specified as a
+  multiple of standard line height.
+- `entry-spacing' (integer): Vertical distance between
+  bibliographic entries, specified as a multiple of standard line
+  height.
+- `second-field-align' (`flush'or `margin'): The position of
+  second-field alignment.
+- `hanging-indent' (boolean): Whether the bibliography items should
+  be rendered with hanging-indents."
+  (if (null (citeproc-style-bib-layout (citeproc-proc-style proc)))
+      "[NO BIBLIOGRAPHY LAYOUT IN CSL STYLE]"
+    (citeproc-proc-finalize proc)
+    (let* ((formatter (citeproc-formatter-for-format format))
+          (rt-formatter (citeproc-formatter-rt formatter))
+          (bib-formatter (or bib-formatter-fun
+                             (citeproc-formatter-bib formatter)))
+          (bibitem-formatter (citeproc-formatter-bib-item formatter))
+          (formatter-no-external-links (citeproc-formatter-no-external-links
+                                        formatter))
+          (style (citeproc-proc-style proc))
+          (bib-opts (citeproc-style-bib-opts style))
+          (punct-in-quote (string= (alist-get 'punctuation-in-quote
+                                              (citeproc-style-locale-opts style))
+                                   "true"))
+          (itemdata (citeproc-proc-itemdata proc))
+          (filters (citeproc-proc-bib-filters proc)))
+      ;; Render raw bibitems for each itemdata struct and store them in the
+      ;; `rawbibitem' slot.
+      (maphash (lambda (_ itd)
+                (setf (citeproc-itemdata-rawbibitem itd)
+                      (citeproc-rt-finalize
+                       (citeproc-render-varlist-in-rt
+                        (citeproc-itemdata-varvals itd)
+                        style 'bib 'display internal-links
+                        (or formatter-no-external-links no-external-links))
+                       punct-in-quote)))
+              itemdata)
+      (let* ((raw-bib
+             (if (citeproc-proc-filtered-bib-p proc)
+                 ;; There are filters, we need to select and sort the subbibs.
+                 (let* ((nr-of-filters (length filters))
+                        (result (make-list nr-of-filters nil))
+                        ;; We store boolean to-be-sorted flags for each sub-bib
+                        (to-be-sorted (make-bool-vector nr-of-filters nil))
+                        (bib-sort (citeproc-style-bib-sort (citeproc-proc-style proc))))
+                   ;; Put the itds into subbib lists.
+                   (maphash
+                    (lambda (_ itd)
+                      (let ((subbib-nos (citeproc-itemdata-subbib-nos itd)))
+                        ;; Set to-be-sorted for later subbibs if itemdata
+                        ;; occcurs in more than one.
+                        (when-let ((later-subbib-nos (cdr subbib-nos)))
+                          (dolist (subbib-no later-subbib-nos)
+                            (setf (elt to-be-sorted subbib-no) t)))
+                        ;; Push the item in all corresponding subbibs.
+                        (dolist (subbib-no subbib-nos)
+                          (push itd (elt result subbib-no)))))
+                    itemdata)
+                   ;; Sort the itds in each individual list
+                   (setq result
+                         (--map-indexed
+                          (if (and bib-sort (elt to-be-sorted it-index))
+                              ;; Subbib contains earlier item, needs to sorted.
+                              (citeproc-sort-itds it (citeproc-style-bib-sort-orders
+                                                      (citeproc-proc-style proc)))
+                            ;; No earlier item, sorting on citation-number.
+                            (citeproc-sort-itds-on-citnum it))
+                          result))
+                   ;; Generate the raw bibs.
+                   (--map (mapcar #'citeproc-itemdata-rawbibitem it) result))
+               ;; No filters, so raw-bib is a list containing a single raw bibliograhy.
+               (list (mapcar #'citeproc-itemdata-rawbibitem
+                             (citeproc-sort-itds-on-citnum (hash-table-values itemdata))))))
+            ;; Perform author-substitution.
+            (substituted
+             (-if-let (subs-auth-subst
+                       (alist-get 'subsequent-author-substitute bib-opts))
+                 (--map (citeproc-rt-subsequent-author-substitute it subs-auth-subst)
+                        raw-bib)
+               raw-bib))
+            ;; Calculate formatting params.
+            (max-offset (if (alist-get 'second-field-align bib-opts)
+                            (citeproc-rt-max-offset itemdata)
+                          0))
+            (format-params (cons (cons 'max-offset max-offset)
+                                 (citeproc-style-bib-opts-to-formatting-params bib-opts)))
+            (formatted-bib
+             (--map (funcall bib-formatter
+                             (mapcar
+                              (lambda (x)
+                                (funcall
+                                 bibitem-formatter
+                                 (funcall
+                                  rt-formatter (citeproc-rt-cull-spaces-puncts x))
+                                 format-params))
+                              it)
+                             format-params)
+                    substituted)))
+       ;; Generate final return value.
+       (cons (if filters formatted-bib (car formatted-bib))
+             format-params)))))
+
+(defun citeproc-clear (proc)
+  "Remove all bibliographic and citation data from PROC."
+  (clrhash (citeproc-proc-itemdata proc))
+  (clrhash (citeproc-proc-names proc))
+  (queue-clear (citeproc-proc-citations proc))
+  (setf (citeproc-proc-finalized proc) t))
+
+;; For one-off renderings
+
+(defun citeproc-create-style (style locale-getter &optional locale force-locale)
+  "Compile style in STYLE into a citeproc-style struct.
+STYLE is either a path to a CSL style file, or a style as a
+string. LOCALE-GETTER is a getter function for locales, the
+optional LOCALE is a locale to prefer. If FORCE-LOCALE is non-nil
+then use LOCALE even if the style's default locale is different."
+  (-let* (((year-suffix . parsed-style) (citeproc-style-parse style))
+         (default-locale (alist-get 'default-locale (cadr parsed-style)))
+         (preferred-locale (if force-locale locale (or default-locale
+                                                       locale
+                                                       "en-US")))
+         (act-parsed-locale (funcall locale-getter preferred-locale))
+         (act-locale (alist-get 'lang (cadr act-parsed-locale)))
+         (style (citeproc-create-style-from-locale
+                 parsed-style
+                 (not (not year-suffix)) act-locale)))
+    (citeproc-style--update-locale style act-parsed-locale)
+    (citeproc-style--set-opt-defaults style)
+    (setf (citeproc-style-locale style) (or locale act-locale))
+    style))
+
+;; REVIEW: this should be rethought -- should we apply the specific wrappers as
+;; well?
+(defun citeproc-render-item (item-data style mode format
+                                      &optional no-external-links)
+  "Render a bibliography item described by ITEM-DATA with STYLE.
+ITEM-DATA is the parsed form of a bibliography item description
+  in CSL-JSON format,
+STYLE is a `citeproc-style' structure,
+MODE is one of the symbols `bib' or `cite',
+FORMAT is a symbol representing a supported output format.
+If the optional NO-EXTERNAL-LINKS is non-nil then don't generate
+external links in the item."
+  (let ((internal-varlist (--map-when (memq (car it) citeproc--date-vars)
+                                     (cons (car it)
+                                           (citeproc-date-parse (cdr it)))
+                                     item-data)))
+    (funcall (citeproc-formatter-rt (citeproc-formatter-for-format format))
+            (citeproc-rt-cull-spaces-puncts
+             (citeproc-rt-finalize
+              (citeproc-render-varlist-in-rt
+               internal-varlist style mode 'display 'no-links no-external-links))))))
+
+(provide 'citeproc)
+
+;;; citeproc.el ends here
diff --git a/elpa/org-ref-20230507.1420/citeproc/csl-locales/locales-en-US.xml b/elpa/org-ref-20230507.1420/citeproc/csl-locales/locales-en-US.xml
new file mode 100644 (file)
index 0000000..be78c5e
--- /dev/null
@@ -0,0 +1,357 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale xmlns="http://purl.org/net/xbiblio/csl" version="1.0" xml:lang="en-US">
+  <info>
+    <translator>
+      <name>Andrew Dunning</name>
+    </translator>
+    <translator>
+      <name>Sebastian Karcher</name>
+    </translator>
+    <translator>
+      <name>Rintze M. Zelle</name>
+    </translator>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+    <updated>2015-10-10T23:31:02+00:00</updated>
+  </info>
+  <style-options punctuation-in-quote="true"/>
+  <date form="text">
+    <date-part name="month" suffix=" "/>
+    <date-part name="day" suffix=", "/>
+    <date-part name="year"/>
+  </date>
+  <date form="numeric">
+    <date-part name="month" form="numeric-leading-zeros" suffix="/"/>
+    <date-part name="day" form="numeric-leading-zeros" suffix="/"/>
+    <date-part name="year"/>
+  </date>
+  <terms>
+    <term name="accessed">accessed</term>
+    <term name="and">and</term>
+    <term name="and others">and others</term>
+    <term name="anonymous">anonymous</term>
+    <term name="anonymous" form="short">anon.</term>
+    <term name="at">at</term>
+    <term name="available at">available at</term>
+    <term name="by">by</term>
+    <term name="circa">circa</term>
+    <term name="circa" form="short">c.</term>
+    <term name="cited">cited</term>
+    <term name="edition">
+      <single>edition</single>
+      <multiple>editions</multiple>
+    </term>
+    <term name="edition" form="short">ed.</term>
+    <term name="et-al">et al.</term>
+    <term name="forthcoming">forthcoming</term>
+    <term name="from">from</term>
+    <term name="ibid">ibid.</term>
+    <term name="in">in</term>
+    <term name="in press">in press</term>
+    <term name="internet">internet</term>
+    <term name="interview">interview</term>
+    <term name="letter">letter</term>
+    <term name="no date">no date</term>
+    <term name="no date" form="short">n.d.</term>
+    <term name="online">online</term>
+    <term name="presented at">presented at the</term>
+    <term name="reference">
+      <single>reference</single>
+      <multiple>references</multiple>
+    </term>
+    <term name="reference" form="short">
+      <single>ref.</single>
+      <multiple>refs.</multiple>
+    </term>
+    <term name="retrieved">retrieved</term>
+    <term name="scale">scale</term>
+    <term name="version">version</term>
+
+    <!-- ANNO DOMINI; BEFORE CHRIST -->
+    <term name="ad">AD</term>
+    <term name="bc">BC</term>
+
+    <!-- PUNCTUATION -->
+    <term name="open-quote">“</term>
+    <term name="close-quote">”</term>
+    <term name="open-inner-quote">‘</term>
+    <term name="close-inner-quote">’</term>
+    <term name="page-range-delimiter">–</term>
+
+    <!-- ORDINALS -->
+    <term name="ordinal">th</term>
+    <term name="ordinal-01">st</term>
+    <term name="ordinal-02">nd</term>
+    <term name="ordinal-03">rd</term>
+    <term name="ordinal-11">th</term>
+    <term name="ordinal-12">th</term>
+    <term name="ordinal-13">th</term>
+
+    <!-- LONG ORDINALS -->
+    <term name="long-ordinal-01">first</term>
+    <term name="long-ordinal-02">second</term>
+    <term name="long-ordinal-03">third</term>
+    <term name="long-ordinal-04">fourth</term>
+    <term name="long-ordinal-05">fifth</term>
+    <term name="long-ordinal-06">sixth</term>
+    <term name="long-ordinal-07">seventh</term>
+    <term name="long-ordinal-08">eighth</term>
+    <term name="long-ordinal-09">ninth</term>
+    <term name="long-ordinal-10">tenth</term>
+
+    <!-- LONG LOCATOR FORMS -->
+    <term name="book">
+      <single>book</single>
+      <multiple>books</multiple>
+    </term>
+    <term name="chapter">
+      <single>chapter</single>
+      <multiple>chapters</multiple>
+    </term>
+    <term name="column">
+      <single>column</single>
+      <multiple>columns</multiple>
+    </term>
+    <term name="figure">
+      <single>figure</single>
+      <multiple>figures</multiple>
+    </term>
+    <term name="folio">
+      <single>folio</single>
+      <multiple>folios</multiple>
+    </term>
+    <term name="issue">
+      <single>number</single>
+      <multiple>numbers</multiple>
+    </term>
+    <term name="line">
+      <single>line</single>
+      <multiple>lines</multiple>
+    </term>
+    <term name="note">
+      <single>note</single>
+      <multiple>notes</multiple>
+    </term>
+    <term name="opus">
+      <single>opus</single>
+      <multiple>opera</multiple>
+    </term>
+    <term name="page">
+      <single>page</single>
+      <multiple>pages</multiple>
+    </term>
+    <term name="number-of-pages">
+      <single>page</single>
+      <multiple>pages</multiple>
+    </term>
+    <term name="paragraph">
+      <single>paragraph</single>
+      <multiple>paragraphs</multiple>
+    </term>
+    <term name="part">
+      <single>part</single>
+      <multiple>parts</multiple>
+    </term>
+    <term name="section">
+      <single>section</single>
+      <multiple>sections</multiple>
+    </term>
+    <term name="sub verbo">
+      <single>sub verbo</single>
+      <multiple>sub verbis</multiple>
+    </term>
+    <term name="verse">
+      <single>verse</single>
+      <multiple>verses</multiple>
+    </term>
+    <term name="volume">
+      <single>volume</single>
+      <multiple>volumes</multiple>
+    </term>
+
+    <!-- SHORT LOCATOR FORMS -->
+    <term name="book" form="short">
+      <single>bk.</single>
+      <multiple>bks.</multiple>
+    </term>
+    <term name="chapter" form="short">
+      <single>chap.</single>
+      <multiple>chaps.</multiple>
+    </term>
+    <term name="column" form="short">
+      <single>col.</single>
+      <multiple>cols.</multiple>
+    </term>
+    <term name="figure" form="short">
+      <single>fig.</single>
+      <multiple>figs.</multiple>
+    </term>
+    <term name="folio" form="short">
+      <single>fol.</single>
+      <multiple>fols.</multiple>
+    </term>
+    <term name="issue" form="short">
+      <single>no.</single>
+      <multiple>nos.</multiple>
+    </term>
+    <term name="line" form="short">
+      <single>l.</single>
+      <multiple>ll.</multiple>
+    </term>
+    <term name="note" form="short">
+      <single>n.</single>
+      <multiple>nn.</multiple>
+    </term>
+    <term name="opus" form="short">
+      <single>op.</single>
+      <multiple>opp.</multiple>
+    </term>
+    <term name="page" form="short">
+      <single>p.</single>
+      <multiple>pp.</multiple>
+    </term>
+    <term name="number-of-pages" form="short">
+      <single>p.</single>
+      <multiple>pp.</multiple>
+    </term>
+    <term name="paragraph" form="short">
+      <single>para.</single>
+      <multiple>paras.</multiple>
+    </term>
+    <term name="part" form="short">
+      <single>pt.</single>
+      <multiple>pts.</multiple>
+    </term>
+    <term name="section" form="short">
+      <single>sec.</single>
+      <multiple>secs.</multiple>
+    </term>
+    <term name="sub verbo" form="short">
+      <single>s.v.</single>
+      <multiple>s.vv.</multiple>
+    </term>
+    <term name="verse" form="short">
+      <single>v.</single>
+      <multiple>vv.</multiple>
+    </term>
+    <term name="volume" form="short">
+      <single>vol.</single>
+      <multiple>vols.</multiple>
+    </term>
+
+    <!-- SYMBOL LOCATOR FORMS -->
+    <term name="paragraph" form="symbol">
+      <single>¶</single>
+      <multiple>¶¶</multiple>
+    </term>
+    <term name="section" form="symbol">
+      <single>§</single>
+      <multiple>§§</multiple>
+    </term>
+
+    <!-- LONG ROLE FORMS -->
+    <term name="director">
+      <single>director</single>
+      <multiple>directors</multiple>
+    </term>
+    <term name="editor">
+      <single>editor</single>
+      <multiple>editors</multiple>
+    </term>
+    <term name="editorial-director">
+      <single>editor</single>
+      <multiple>editors</multiple>
+    </term>
+    <term name="illustrator">
+      <single>illustrator</single>
+      <multiple>illustrators</multiple>
+    </term>
+    <term name="translator">
+      <single>translator</single>
+      <multiple>translators</multiple>
+    </term>
+    <term name="editortranslator">
+      <single>editor &amp; translator</single>
+      <multiple>editors &amp; translators</multiple>
+    </term>
+
+    <!-- SHORT ROLE FORMS -->
+    <term name="director" form="short">
+      <single>dir.</single>
+      <multiple>dirs.</multiple>
+    </term>
+    <term name="editor" form="short">
+      <single>ed.</single>
+      <multiple>eds.</multiple>
+    </term>
+    <term name="editorial-director" form="short">
+      <single>ed.</single>
+      <multiple>eds.</multiple>
+    </term>
+    <term name="illustrator" form="short">
+      <single>ill.</single>
+      <multiple>ills.</multiple>
+    </term>
+    <term name="translator" form="short">
+      <single>tran.</single>
+      <multiple>trans.</multiple>
+    </term>
+    <term name="editortranslator" form="short">
+      <single>ed. &amp; tran.</single>
+      <multiple>eds. &amp; trans.</multiple>
+    </term>
+
+    <!-- VERB ROLE FORMS -->
+    <term name="container-author" form="verb">by</term>
+    <term name="director" form="verb">directed by</term>
+    <term name="editor" form="verb">edited by</term>
+    <term name="editorial-director" form="verb">edited by</term>
+    <term name="illustrator" form="verb">illustrated by</term>
+    <term name="interviewer" form="verb">interview by</term>
+    <term name="recipient" form="verb">to</term>
+    <term name="reviewed-author" form="verb">by</term>
+    <term name="translator" form="verb">translated by</term>
+    <term name="editortranslator" form="verb">edited &amp; translated by</term>
+
+    <!-- SHORT VERB ROLE FORMS -->
+    <term name="director" form="verb-short">dir. by</term>
+    <term name="editor" form="verb-short">ed. by</term>
+    <term name="editorial-director" form="verb-short">ed. by</term>
+    <term name="illustrator" form="verb-short">illus. by</term>
+    <term name="translator" form="verb-short">trans. by</term>
+    <term name="editortranslator" form="verb-short">ed. &amp; trans. by</term>
+
+    <!-- LONG MONTH FORMS -->
+    <term name="month-01">January</term>
+    <term name="month-02">February</term>
+    <term name="month-03">March</term>
+    <term name="month-04">April</term>
+    <term name="month-05">May</term>
+    <term name="month-06">June</term>
+    <term name="month-07">July</term>
+    <term name="month-08">August</term>
+    <term name="month-09">September</term>
+    <term name="month-10">October</term>
+    <term name="month-11">November</term>
+    <term name="month-12">December</term>
+
+    <!-- SHORT MONTH FORMS -->
+    <term name="month-01" form="short">Jan.</term>
+    <term name="month-02" form="short">Feb.</term>
+    <term name="month-03" form="short">Mar.</term>
+    <term name="month-04" form="short">Apr.</term>
+    <term name="month-05" form="short">May</term>
+    <term name="month-06" form="short">Jun.</term>
+    <term name="month-07" form="short">Jul.</term>
+    <term name="month-08" form="short">Aug.</term>
+    <term name="month-09" form="short">Sep.</term>
+    <term name="month-10" form="short">Oct.</term>
+    <term name="month-11" form="short">Nov.</term>
+    <term name="month-12" form="short">Dec.</term>
+
+    <!-- SEASONS -->
+    <term name="season-01">Spring</term>
+    <term name="season-02">Summer</term>
+    <term name="season-03">Autumn</term>
+    <term name="season-04">Winter</term>
+  </terms>
+</locale>
diff --git a/elpa/org-ref-20230507.1420/citeproc/csl-styles/apa-5th-edition.csl b/elpa/org-ref-20230507.1420/citeproc/csl-styles/apa-5th-edition.csl
new file mode 100644 (file)
index 0000000..186557d
--- /dev/null
@@ -0,0 +1,341 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only">
+  <info>
+    <title>American Psychological Association 5th edition</title>
+    <title-short>APA (5th ed.)</title-short>
+    <id>http://www.zotero.org/styles/apa-5th-edition</id>
+    <link href="http://www.zotero.org/styles/apa-5th-edition" rel="self"/>
+    <link href="http://rdc.libguides.com/content.php?pid=63487" rel="documentation"/>
+    <author>
+      <name>Simon Kornblith</name>
+      <email>simonNOSPAMsimonster.com</email>
+    </author>
+    <contributor>
+      <name>Bruce D'Arcus</name>
+    </contributor>
+    <contributor>
+      <name>Curtis M. Humphrey</name>
+    </contributor>
+    <contributor>
+      <name>Richard Karnesky</name>
+      <email>karnesky+zoteroNOSPAMgmail.com</email>
+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
+    </contributor>
+    <contributor>
+      <name>Sebastian Karcher</name>
+    </contributor>
+    <category citation-format="author-date"/>
+    <category field="psychology"/>
+    <category field="generic-base"/>
+    <updated>2020-03-23T14:28:18+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <locale xml:lang="fr">
+    <terms>
+      <term name="editor" form="short">
+        <single>éd.</single>
+        <multiple>éds.</multiple>
+      </term>
+    </terms>
+  </locale>
+  <macro name="container-contributors">
+    <choose>
+      <if type="chapter paper-conference" match="any">
+        <text term="in" text-case="capitalize-first" suffix=" "/>
+        <names variable="editor" delimiter=", " suffix=", ">
+          <name and="symbol" initialize-with=". " delimiter=", "/>
+          <label form="short" prefix=" (" text-case="capitalize-first" suffix=")"/>
+          <substitute>
+            <names variable="translator"/>
+          </substitute>
+        </names>
+      </if>
+    </choose>
+  </macro>
+  <macro name="secondary-contributors">
+    <choose>
+      <if type="chapter paper-conference" match="none">
+        <names variable="translator" delimiter=", " prefix=" (" suffix=")">
+          <name and="symbol" initialize-with=". " delimiter=", "/>
+          <label form="short" prefix=", " text-case="capitalize-first"/>
+          <substitute>
+            <names variable="editor"/>
+          </substitute>
+        </names>
+      </if>
+    </choose>
+  </macro>
+  <macro name="author">
+    <names variable="author">
+      <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=" (" suffix=")" text-case="capitalize-first"/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <text macro="title"/>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="author-short">
+    <names variable="author">
+      <name form="short" and="symbol" delimiter=", " initialize-with=". "/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <choose>
+          <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+            <text variable="title" form="short" font-style="italic"/>
+          </if>
+          <else>
+            <text variable="title" form="short" quotes="true"/>
+          </else>
+        </choose>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="access">
+    <choose>
+      <if type="thesis">
+        <choose>
+          <if variable="archive" match="any">
+            <group>
+              <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+              <text term="from" suffix=" "/>
+              <text variable="archive" suffix="."/>
+              <text variable="archive_location" prefix=" (" suffix=")"/>
+            </group>
+          </if>
+          <else>
+            <group>
+              <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+              <date variable="accessed" suffix=", ">
+                <date-part name="month" suffix=" "/>
+                <date-part name="day" suffix=", "/>
+                <date-part name="year"/>
+              </date>
+              <text term="from" suffix=" "/>
+              <text variable="URL"/>
+            </group>
+          </else>
+        </choose>
+      </if>
+      <else>
+        <choose>
+          <if variable="URL">
+            <choose>
+              <if variable="archive">
+                <group>
+                  <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+                  <text term="from" suffix=" "/>
+                  <text variable="archive" suffix="."/>
+                </group>
+              </if>
+              <else>
+                <group>
+                  <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+                  <date variable="accessed" suffix=", ">
+                    <date-part name="month" suffix=" "/>
+                    <date-part name="day" suffix=", "/>
+                    <date-part name="year"/>
+                  </date>
+                  <group>
+                    <text term="from" suffix=" "/>
+                    <text variable="URL"/>
+                  </group>
+                </group>
+              </else>
+            </choose>
+          </if>
+        </choose>
+      </else>
+    </choose>
+  </macro>
+  <macro name="title">
+    <choose>
+      <if type="report thesis" match="any">
+        <text variable="title" font-style="italic"/>
+        <group prefix=" (" suffix=")">
+          <text variable="genre"/>
+          <text variable="number" prefix=" No. "/>
+        </group>
+      </if>
+      <else-if type="bill book graphic legal_case legislation manuscript motion_picture report song speech" match="any">
+        <text variable="title" font-style="italic"/>
+      </else-if>
+      <else>
+        <text variable="title"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <choose>
+      <if type="report" match="any">
+        <group delimiter=": ">
+          <text variable="publisher-place"/>
+          <text variable="publisher"/>
+        </group>
+      </if>
+      <else-if type="thesis" match="any">
+        <group delimiter=", ">
+          <text variable="publisher"/>
+          <text variable="publisher-place"/>
+        </group>
+      </else-if>
+      <else>
+        <choose>
+          <if variable="event" match="none">
+            <text variable="genre" suffix=", "/>
+          </if>
+        </choose>
+        <group delimiter=": ">
+          <text variable="publisher-place"/>
+          <text variable="publisher"/>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <macro name="event">
+    <choose>
+      <if variable="event">
+        <choose>
+          <if variable="genre" match="none">
+            <text term="presented at" text-case="capitalize-first" suffix=" "/>
+            <text variable="event"/>
+          </if>
+          <else>
+            <group delimiter=" ">
+              <text variable="genre" text-case="capitalize-first"/>
+              <text term="presented at"/>
+              <text variable="event"/>
+            </group>
+          </else>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="issued">
+    <choose>
+      <if variable="issued">
+        <group prefix=" (" suffix=").">
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+          <choose>
+            <if type="article-journal bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="none">
+              <date variable="issued">
+                <date-part prefix=", " name="month"/>
+                <date-part prefix=" " name="day"/>
+              </date>
+            </if>
+          </choose>
+        </group>
+      </if>
+      <else>
+        <text prefix=" (" term="no date" suffix=")." form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="issued-year">
+    <choose>
+      <if variable="issued">
+        <date variable="issued">
+          <date-part name="year"/>
+        </date>
+      </if>
+      <else>
+        <text term="no date" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="edition">
+    <choose>
+      <if is-numeric="edition">
+        <group delimiter=" ">
+          <number variable="edition" form="ordinal"/>
+          <text term="edition" form="short"/>
+        </group>
+      </if>
+      <else>
+        <text variable="edition" suffix="."/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="locators">
+    <choose>
+      <if type="article-journal article-magazine article-newspaper" match="any">
+        <group prefix=", " delimiter=", ">
+          <group>
+            <text variable="volume" font-style="italic"/>
+            <text variable="issue" prefix="(" suffix=")"/>
+          </group>
+          <text variable="page"/>
+        </group>
+      </if>
+      <else-if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
+        <group prefix=" (" suffix=")" delimiter=", ">
+          <text macro="edition"/>
+          <group>
+            <text term="volume" form="short" plural="true" text-case="capitalize-first" suffix=" "/>
+            <number variable="number-of-volumes" form="numeric" prefix="1-"/>
+          </group>
+          <group>
+            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>
+            <number variable="volume" form="numeric"/>
+          </group>
+          <group>
+            <label variable="page" form="short" suffix=" "/>
+            <text variable="page"/>
+          </group>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="citation-locator">
+    <group>
+      <label variable="locator" form="short"/>
+      <text variable="locator" prefix=" "/>
+    </group>
+  </macro>
+  <citation et-al-min="6" et-al-use-first="1" et-al-subsequent-min="3" et-al-subsequent-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" collapse="year">
+    <sort>
+      <key macro="author"/>
+      <key macro="issued-year"/>
+    </sort>
+    <layout prefix="(" suffix=")" delimiter="; ">
+      <group delimiter=", ">
+        <text macro="author-short"/>
+        <text macro="issued-year"/>
+        <text macro="citation-locator"/>
+      </group>
+    </layout>
+  </citation>
+  <bibliography hanging-indent="true" et-al-min="8" et-al-use-first="7" entry-spacing="0" line-spacing="2">
+    <sort>
+      <key macro="author"/>
+      <key macro="issued-year" sort="ascending"/>
+    </sort>
+    <layout>
+      <group suffix=".">
+        <text macro="author" suffix="."/>
+        <text macro="issued" suffix=" "/>
+        <group delimiter=". ">
+          <text macro="title"/>
+          <group>
+            <text macro="container-contributors"/>
+            <text macro="secondary-contributors"/>
+            <group delimiter=", ">
+              <text variable="container-title" font-style="italic"/>
+              <text variable="collection-title"/>
+            </group>
+          </group>
+        </group>
+        <text macro="locators"/>
+        <group delimiter=", " prefix=". ">
+          <text macro="event"/>
+          <text macro="publisher"/>
+        </group>
+      </group>
+      <text macro="access" prefix=". "/>
+    </layout>
+  </bibliography>
+</style>
diff --git a/elpa/org-ref-20230507.1420/citeproc/csl-styles/apa-numeric-superscript-brackets.csl b/elpa/org-ref-20230507.1420/citeproc/csl-styles/apa-numeric-superscript-brackets.csl
new file mode 100644 (file)
index 0000000..e1a2a18
--- /dev/null
@@ -0,0 +1,1711 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="never" page-range-format="expanded">
+  <info>
+    <title>American Psychological Association 7th edition (numeric, brackets)</title>
+    <title-short>APA (numeric, superscript, brackets)</title-short>
+    <id>http://www.zotero.org/styles/apa-numeric-superscript-brackets</id>
+    <link href="http://www.zotero.org/styles/apa-numeric-superscript-brackets" rel="self"/>
+    <link href="http://www.zotero.org/styles/apa" rel="template"/>
+    <link href="https://apastyle.apa.org/style-grammar-guidelines/references/examples" rel="documentation"/>
+    <author>
+      <name>Brenton M. Wiernik</name>
+      <email>zoteroNOSPAMwiernik.org</email>
+    </author>
+    <category citation-format="numeric"/>
+    <category field="psychology"/>
+    <category field="generic-base"/>
+    <summary>APA style, with numeric in-text citations in brackets</summary>
+    <updated>2021-03-11T05:11:56+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <locale xml:lang="en">
+    <terms>
+      <term name="editortranslator" form="short">
+        <single>ed. &amp; trans.</single>
+        <multiple>eds. &amp; trans.</multiple>
+      </term>
+      <term name="translator" form="short">trans.</term>
+      <term name="interviewer" form="short">
+        <single>interviewer</single>
+        <multiple>interviewers</multiple>
+      </term>
+      <term name="collection-editor" form="short">
+        <single>ed.</single>
+        <multiple>eds.</multiple>
+      </term>
+      <term name="circa" form="short">ca.</term>
+      <term name="bc"> B.C.E.</term>
+      <term name="ad"> C.E.</term>
+      <term name="letter">personal communication</term>
+      <term name="letter" form="short">letter</term>
+      <term name="issue" form="long">
+        <single>issue</single>
+        <multiple>issues</multiple>
+      </term>
+    </terms>
+  </locale>
+  <locale xml:lang="af">
+    <terms>
+      <term name="letter">persoonlike kommunikasie</term>
+      <term name="letter" form="short">brief</term>
+    </terms>
+  </locale>
+  <locale xml:lang="ar">
+    <terms>
+      <term name="letter">اتصال شخصي</term>
+      <term name="letter" form="short">خطاب</term>
+    </terms>
+  </locale>
+  <locale xml:lang="da">
+    <terms>
+      <term name="et-al">et al.</term>
+      <term name="letter">personlig kommunikation</term>
+      <term name="letter" form="short">brev</term>
+    </terms>
+  </locale>
+  <locale xml:lang="de">
+    <terms>
+      <term name="et-al">et al.</term>
+      <term name="letter">persönliche Kommunikation</term>
+      <term name="letter" form="short">Brief</term>
+    </terms>
+  </locale>
+  <locale xml:lang="es">
+    <terms>
+      <term name="from">de</term>
+      <term name="letter">comunicación personal</term>
+      <term name="letter" form="short">carta</term>
+    </terms>
+  </locale>
+  <locale xml:lang="fr">
+    <terms>
+      <term name="letter">communication personnelle</term>
+      <term name="letter" form="short">lettre</term>
+      <term name="editor" form="short">
+        <single>éd.</single>
+        <multiple>éds.</multiple>
+      </term>
+    </terms>
+  </locale>
+  <locale xml:lang="nb">
+    <terms>
+      <term name="et-al">et al.</term>
+      <term name="letter">personlig kommunikasjon</term>
+      <term name="letter" form="short">brev</term>
+    </terms>
+  </locale>
+  <locale xml:lang="nl">
+    <terms>
+      <term name="et-al">et al.</term>
+      <term name="letter">persoonlijke communicatie</term>
+      <term name="letter" form="short">brief</term>
+    </terms>
+  </locale>
+  <locale xml:lang="nn">
+    <terms>
+      <term name="et-al">et al.</term>
+      <term name="letter">personlig kommunikasjon</term>
+      <term name="letter" form="short">brev</term>
+    </terms>
+  </locale>
+  <locale xml:lang="ru">
+    <terms>
+      <term name="letter">личная переписка</term>
+      <term name="letter" form="short">письмо</term>
+    </terms>
+  </locale>
+  <locale xml:lang="tr">
+    <terms>
+      <term name="letter">kişisel iletişim</term>
+      <term name="letter" form="short">mektup</term>
+    </terms>
+  </locale>
+  <!-- General categories of item types:
+       Periodical: article-journal article-magazine article-newspaper post-weblog review review-book
+       Periodical or Booklike: paper-conference
+       Booklike: article book broadcast chapter dataset entry entry-dictionary entry-encyclopedia figure 
+                 graphic interview manuscript map motion_picture musical_score pamphlet patent 
+                 personal_communication report song speech thesis post webpage
+       Legal: bill legal_case legislation treaty
+  -->
+  <!-- APA references contain four parts: author, date, title, source -->
+  <macro name="author-bib">
+    <names variable="composer" delimiter=", ">
+      <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+      <substitute>
+        <names variable="author"/>
+        <names variable="illustrator"/>
+        <names variable="director">
+          <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+          <label form="long" prefix=" (" suffix=")" text-case="title"/>
+        </names>
+        <choose>
+          <if variable="container-title">
+            <choose>
+              <if type="book entry entry-dictionary entry-encyclopedia" match="any">
+                <choose>
+                  <if variable="title">
+                    <group delimiter=" ">
+                      <text macro="title"/>
+                      <text macro="parenthetical"/>
+                    </group>
+                  </if>
+                  <else>
+                    <text macro="title-and-descriptions"/>
+                  </else>
+                </choose>
+              </if>
+            </choose>
+          </if>
+        </choose>
+        <!-- Test for editortranslator and put that first as that becomes available -->
+        <names variable="editor" delimiter=", ">
+          <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+          <label form="short" prefix=" (" suffix=")" text-case="title"/>
+        </names>
+        <names variable="editorial-director">
+          <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+          <label form="short" prefix=" (" suffix=")" text-case="title"/>
+        </names>
+        <names variable="collection-editor">
+          <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+          <label form="short" prefix=" (" suffix=")" text-case="title"/>
+        </names>
+        <choose>
+          <if variable="title">
+            <group delimiter=" ">
+              <text macro="title"/>
+              <text macro="parenthetical"/>
+            </group>
+          </if>
+          <else>
+            <text macro="title-and-descriptions"/>
+          </else>
+        </choose>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="author-intext">
+    <choose>
+      <if type="bill legal_case legislation treaty" match="any">
+        <text macro="title-intext"/>
+      </if>
+      <else-if type="interview personal_communication" match="any">
+        <choose>
+          <!-- These variables indicate that the letter is retrievable by the reader. 
+                If not, then use the APA in-text-only personal communication format -->
+          <if variable="archive container-title DOI publisher URL" match="none">
+            <group delimiter=", ">
+              <names variable="author">
+                <name and="symbol" delimiter=", " initialize-with=". "/>
+                <substitute>
+                  <text macro="title-intext"/>
+                </substitute>
+              </names>
+              <!-- Replace with term="personal-communication" if that becomes available -->
+              <text term="letter"/>
+            </group>
+          </if>
+          <else>
+            <names variable="author" delimiter=", ">
+              <name form="short" and="symbol" delimiter=", " initialize-with=". "/>
+              <substitute>
+                <text macro="title-intext"/>
+              </substitute>
+            </names>
+          </else>
+        </choose>
+      </else-if>
+      <else>
+        <names variable="composer" delimiter=", ">
+          <name form="short" and="symbol" delimiter=", " initialize-with=". "/>
+          <substitute>
+            <names variable="author"/>
+            <names variable="illustrator"/>
+            <names variable="director"/>
+            <choose>
+              <if variable="container-title">
+                <choose>
+                  <if type="book entry entry-dictionary entry-encyclopedia" match="any">
+                    <text macro="title-intext"/>
+                  </if>
+                </choose>
+              </if>
+            </choose>
+            <names variable="editor"/>
+            <names variable="editorial-director"/>
+            <text macro="title-intext"/>
+          </substitute>
+        </names>
+      </else>
+    </choose>
+  </macro>
+  <macro name="date-bib">
+    <group delimiter=" " prefix="(" suffix=")">
+      <choose>
+        <if is-uncertain-date="issued">
+          <text term="circa" form="short"/>
+        </if>
+      </choose>
+      <group>
+        <choose>
+          <if variable="issued">
+            <date variable="issued">
+              <date-part name="year"/>
+            </date>
+            <text variable="year-suffix"/>
+            <choose>
+              <if type="article-magazine article-newspaper broadcast interview motion_picture pamphlet personal_communication post post-weblog song speech webpage" match="any">
+                <!-- Many video and audio examples in manual give full dates. Err on the side of too much information. -->
+                <date variable="issued">
+                  <date-part prefix=", " name="month"/>
+                  <date-part prefix=" " name="day"/>
+                </date>
+              </if>
+              <else-if type="paper-conference">
+                <!-- Capture 'speech' stored as 'paper-conference' -->
+                <choose>
+                  <if variable="collection-editor editor editorial-director issue page volume" match="none">
+                    <date variable="issued">
+                      <date-part prefix=", " name="month"/>
+                      <date-part prefix=" " name="day"/>
+                    </date>
+                  </if>
+                </choose>
+              </else-if>
+              <!-- Only year: article article-journal book chapter entry entry-dictionary entry-encyclopedia dataset figure graphic 
+                   manuscript map musical_score paper-conference[published] patent report review review-book thesis -->
+            </choose>
+          </if>
+          <else-if variable="status">
+            <group>
+              <text variable="status" text-case="lowercase"/>
+              <text variable="year-suffix" prefix="-"/>
+            </group>
+          </else-if>
+          <else>
+            <group>
+              <text term="no date" form="short"/>
+              <text variable="year-suffix" prefix="-"/>
+            </group>
+          </else>
+        </choose>
+      </group>
+    </group>
+  </macro>
+  <macro name="date-sort-group">
+    <choose>
+      <if variable="issued">
+        <text value="1"/>
+      </if>
+      <else-if variable="status">
+        <text value="2"/>
+      </else-if>
+      <else>
+        <text value="0"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="date-sort-date">
+    <choose>
+      <if type="article-magazine article-newspaper broadcast interview pamphlet personal_communication post post-weblog speech treaty webpage" match="any">
+        <date variable="issued" form="numeric"/>
+      </if>
+      <else-if type="paper-conference">
+        <!-- Capture 'speech' stored as 'paper-conference' -->
+        <choose>
+          <if variable="collection-editor editor editorial-director issue page volume" match="none">
+            <date variable="issued" form="numeric"/>
+          </if>
+        </choose>
+      </else-if>
+      <else>
+        <date variable="issued" form="numeric"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="date-intext">
+    <choose>
+      <if variable="issued">
+        <group delimiter="/">
+          <group delimiter=" ">
+            <choose>
+              <if is-uncertain-date="original-date">
+                <text term="circa" form="short"/>
+              </if>
+            </choose>
+            <date variable="original-date">
+              <date-part name="year"/>
+            </date>
+          </group>
+          <group delimiter=" ">
+            <choose>
+              <if is-uncertain-date="issued">
+                <text term="circa" form="short"/>
+              </if>
+            </choose>
+            <group>
+              <choose>
+                <if type="interview personal_communication" match="any">
+                  <choose>
+                    <if variable="archive container-title DOI publisher URL" match="none">
+                      <!-- These variables indicate that the communication is retrievable by the reader. 
+                           If not, then use the in-text-only personal communication format -->
+                      <date variable="issued" form="text"/>
+                    </if>
+                    <else>
+                      <date variable="issued">
+                        <date-part name="year"/>
+                      </date>
+                    </else>
+                  </choose>
+                </if>
+                <else>
+                  <date variable="issued">
+                    <date-part name="year"/>
+                  </date>
+                </else>
+              </choose>
+              <text variable="year-suffix"/>
+            </group>
+          </group>
+        </group>
+      </if>
+      <else-if variable="status">
+        <text variable="status" text-case="lowercase"/>
+        <text variable="year-suffix" prefix="-"/>
+      </else-if>
+      <else>
+        <text term="no date" form="short"/>
+        <text variable="year-suffix" prefix="-"/>
+      </else>
+    </choose>
+  </macro>
+  <!-- APA has two description elements following the title:
+       title (parenthetical) [bracketed]  -->
+  <macro name="title-and-descriptions">
+    <choose>
+      <if variable="title">
+        <group delimiter=" ">
+          <text macro="title"/>
+          <text macro="parenthetical"/>
+          <text macro="bracketed"/>
+        </group>
+      </if>
+      <else>
+        <group delimiter=" ">
+          <text macro="bracketed"/>
+          <text macro="parenthetical"/>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <macro name="title">
+    <choose>
+      <if type="post webpage" match="any">
+        <!-- Webpages are always italicized -->
+        <text variable="title" font-style="italic"/>
+      </if>
+      <else-if variable="container-title" match="any">
+        <!-- Other types are italicized based on presence of container-title.
+             Assume that review and review-book are published in periodicals/blogs,
+             not just on a web page (ex. 69) -->
+        <text variable="title"/>
+      </else-if>
+      <else>
+        <choose>
+          <if type="article-journal article-magazine article-newspaper post-weblog review review-book" match="any">
+            <text variable="title" font-style="italic"/>
+          </if>
+          <else-if type="paper-conference">
+            <choose>
+              <if variable="collection-editor editor editorial-director" match="any">
+                <group delimiter=": " font-style="italic">
+                  <text variable="title"/>
+                  <!-- Replace with volume-title as that becomes available -->
+                  <choose>
+                    <if is-numeric="volume" match="none">
+                      <group delimiter=" ">
+                        <label variable="volume" form="short" text-case="capitalize-first"/>
+                        <text variable="volume"/>
+                      </group>
+                    </if>
+                  </choose>
+                </group>
+              </if>
+              <else>
+                <text variable="title" font-style="italic"/>
+              </else>
+            </choose>
+          </else-if>
+          <else>
+            <group delimiter=": " font-style="italic">
+              <text variable="title"/>
+              <!-- Replace with volume-title as that becomes available -->
+              <choose>
+                <if is-numeric="volume" match="none">
+                  <group delimiter=" ">
+                    <label variable="volume" form="short" text-case="capitalize-first"/>
+                    <text variable="volume"/>
+                  </group>
+                </if>
+              </choose>
+            </group>
+          </else>
+        </choose>
+      </else>
+    </choose>
+  </macro>
+  <macro name="title-intext">
+    <choose>
+      <if variable="title" match="none">
+        <text macro="bracketed-intext" prefix="[" suffix="]"/>
+      </if>
+      <else-if type="bill">
+        <!-- If a bill has no number or container-title, assume it is a hearing; italic and title case -->
+        <choose>
+          <if variable="number container-title" match="none">
+            <text variable="title" form="short" font-style="italic" text-case="title"/>
+          </if>
+          <else-if variable="title">
+            <text variable="title" form="short"/>
+          </else-if>
+          <else>
+            <group delimiter=" ">
+              <text variable="genre"/>
+              <group delimiter=" ">
+                <choose>
+                  <if variable="chapter-number container-title" match="none">
+                    <!-- Replace with label variable="number" as that becomes available -->
+                    <text term="issue" form="short"/>
+                  </if>
+                </choose>
+                <text variable="number"/>
+              </group>
+            </group>
+          </else>
+        </choose>
+      </else-if>
+      <else-if type="legal_case" match="any">
+        <!-- Cases are italicized -->
+        <text variable="title" font-style="italic"/>
+      </else-if>
+      <else-if type="legislation treaty" match="any">
+        <!-- Legislation and treaties not italicized or quoted -->
+        <text variable="title" form="short"/>
+      </else-if>
+      <else-if type="post webpage" match="any">
+        <!-- Webpages are always italicized -->
+        <text variable="title" form="short" font-style="italic"/>
+      </else-if>
+      <else-if variable="container-title" match="any">
+        <!-- Other types are italicized or quoted based on presence of container-title. As in title macro. -->
+        <text variable="title" form="short" quotes="true"/>
+      </else-if>
+      <else>
+        <text variable="title" form="short" font-style="italic"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="parenthetical">
+    <!-- (Secondary contributors; Database location; Genre no. 123; Report Series 123, Version, Edition, Volume, Page) -->
+    <group prefix="(" suffix=")">
+      <choose>
+        <if type="patent">
+          <!-- authority: U.S. ; genre: patent ; number: 123,445 -->
+          <group delimiter=" ">
+            <text variable="authority" form="short"/>
+            <choose>
+              <if variable="genre">
+                <text variable="genre" text-case="capitalize-first"/>
+              </if>
+              <else>
+                <!-- This should be localized -->
+                <text value="patent" text-case="capitalize-first"/>
+              </else>
+            </choose>
+            <group delimiter=" ">
+              <!-- Replace with label variable="number" if that becomes available -->
+              <text term="issue" form="short" text-case="capitalize-first"/>
+              <text variable="number"/>
+            </group>
+          </group>
+        </if>
+        <else-if type="post webpage" match="any">
+          <!-- For post webpage, container-title is treated as publisher -->
+          <group delimiter="; ">
+            <text macro="secondary-contributors"/>
+            <text macro="database-location"/>
+            <text macro="number"/>
+            <text macro="locators-booklike"/>
+          </group>
+        </else-if>
+        <else-if variable="container-title">
+          <group delimiter="; ">
+            <text macro="secondary-contributors"/>
+            <choose>
+              <if type="broadcast graphic map motion_picture song" match="any">
+                <!-- For audiovisual media, number information comes after title, not container-title -->
+                <text macro="number"/>
+              </if>
+            </choose>
+          </group>
+        </else-if>
+        <else>
+          <group delimiter="; ">
+            <text macro="secondary-contributors"/>
+            <text macro="database-location"/>
+            <text macro="number"/>
+            <text macro="locators-booklike"/>
+          </group>
+        </else>
+      </choose>
+    </group>
+  </macro>
+  <macro name="parenthetical-container">
+    <choose>
+      <if variable="container-title" match="any">
+        <group prefix="(" suffix=")">
+          <group delimiter="; ">
+            <text macro="database-location"/>
+            <choose>
+              <if type="broadcast graphic map motion_picture song" match="none">
+                <!-- For audiovisual media, number information comes after title, not container-title -->
+                <text macro="number"/>
+              </if>
+            </choose>
+            <text macro="locators-booklike"/>
+          </group>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="bracketed">
+    <!-- [Descriptive information] -->
+    <!-- If there is a number, genre is already printed in macro="number" -->
+    <group prefix="[" suffix="]">
+      <choose>
+        <if variable="reviewed-author reviewed-title" type="review review-book" match="any">
+          <!-- Reviewed item -->
+          <group delimiter="; ">
+            <group delimiter=", ">
+              <group delimiter=" ">
+                <!-- Assume that genre is entered as 'Review of the book' or similar -->
+                <choose>
+                  <if variable="number" match="none">
+                    <choose>
+                      <if variable="genre">
+                        <text variable="genre" text-case="capitalize-first"/>
+                      </if>
+                      <else-if variable="medium">
+                        <text variable="medium" text-case="capitalize-first"/>
+                      </else-if>
+                      <else>
+                        <!-- Replace with term="review" as that becomes available -->
+                        <text value="Review of"/>
+                      </else>
+                    </choose>
+                  </if>
+                  <else>
+                    <choose>
+                      <if variable="medium">
+                        <text variable="medium" text-case="capitalize-first"/>
+                      </if>
+                      <else>
+                        <!-- Replace with term="review" as that becomes available -->
+                        <text value="Review of"/>
+                      </else>
+                    </choose>
+                  </else>
+                </choose>
+                <text macro="reviewed-title"/>
+              </group>
+              <names variable="reviewed-author">
+                <label form="verb-short" suffix=" "/>
+                <name and="symbol" initialize-with=". " delimiter=", "/>
+              </names>
+            </group>
+            <choose>
+              <if variable="genre" match="any">
+                <choose>
+                  <if variable="number" match="none">
+                    <text variable="medium" text-case="capitalize-first"/>
+                  </if>
+                </choose>
+              </if>
+            </choose>
+          </group>
+        </if>
+        <else-if type="thesis">
+          <!-- Thesis type and institution -->
+          <group delimiter="; ">
+            <choose>
+              <if variable="number" match="none">
+                <group delimiter=", ">
+                  <text variable="genre" text-case="capitalize-first"/>
+                  <choose>
+                    <if variable="archive DOI URL" match="any">
+                      <!-- Include the university in brackets if thesis is published -->
+                      <text variable="publisher"/>
+                    </if>
+                  </choose>
+                </group>
+              </if>
+            </choose>
+            <text variable="medium" text-case="capitalize-first"/>
+          </group>
+        </else-if>
+        <else-if variable="interviewer" type="interview" match="any">
+          <!-- Interview information -->
+          <choose>
+            <if variable="title">
+              <text macro="format"/>
+            </if>
+            <else-if variable="genre">
+              <group delimiter="; ">
+                <group delimiter=" ">
+                  <text variable="genre" text-case="capitalize-first"/>
+                  <group delimiter=" ">
+                    <text term="author" form="verb"/>
+                    <names variable="interviewer">
+                      <name and="symbol" initialize-with=". " delimiter=", "/>
+                    </names>
+                  </group>
+                </group>
+              </group>
+            </else-if>
+            <else-if variable="interviewer">
+              <group delimiter="; ">
+                <names variable="interviewer">
+                  <label form="verb" suffix=" " text-case="capitalize-first"/>
+                  <name and="symbol" initialize-with=". " delimiter=", "/>
+                </names>
+                <text variable="medium" text-case="capitalize-first"/>
+              </group>
+            </else-if>
+            <else>
+              <text macro="format"/>
+            </else>
+          </choose>
+        </else-if>
+        <else-if type="personal_communication">
+          <!-- Letter information -->
+          <choose>
+            <if variable="recipient">
+              <group delimiter="; ">
+                <group delimiter=" ">
+                  <choose>
+                    <if variable="number" match="none">
+                      <choose>
+                        <if variable="genre">
+                          <text variable="genre" text-case="capitalize-first"/>
+                        </if>
+                        <else-if variable="medium">
+                          <text variable="medium" text-case="capitalize-first"/>
+                        </else-if>
+                        <else>
+                          <text term="letter" form="short" text-case="capitalize-first"/>
+                        </else>
+                      </choose>
+                    </if>
+                    <else>
+                      <choose>
+                        <if variable="medium">
+                          <text variable="medium" text-case="capitalize-first"/>
+                        </if>
+                        <else>
+                          <text term="letter" form="short" text-case="capitalize-first"/>
+                        </else>
+                      </choose>
+                    </else>
+                  </choose>
+                  <names variable="recipient" delimiter=", ">
+                    <label form="verb" suffix=" "/>
+                    <name and="symbol" delimiter=", "/>
+                  </names>
+                </group>
+                <choose>
+                  <if variable="genre" match="any">
+                    <choose>
+                      <if variable="number" match="none">
+                        <text variable="medium" text-case="capitalize-first"/>
+                      </if>
+                    </choose>
+                  </if>
+                </choose>
+              </group>
+            </if>
+            <else>
+              <text macro="format"/>
+            </else>
+          </choose>
+        </else-if>
+        <else-if variable="composer" type="song" match="all">
+          <!-- Performer of classical music works -->
+          <group delimiter="; ">
+            <choose>
+              <if variable="number" match="none">
+                <group delimiter=" ">
+                  <choose>
+                    <if variable="genre">
+                      <text variable="genre" text-case="capitalize-first"/>
+                      <!-- Replace prefix with performer label as that becomes available -->
+                      <names variable="author" prefix="recorded by ">
+                        <name and="symbol" initialize-with=". " delimiter=", "/>
+                      </names>
+                    </if>
+                    <else-if variable="medium">
+                      <text variable="medium" text-case="capitalize-first"/>
+                      <!-- Replace prefix with performer label as that becomes available -->
+                      <names variable="author" prefix="recorded by ">
+                        <name and="symbol" initialize-with=". " delimiter=", "/>
+                      </names>
+                    </else-if>
+                    <else>
+                      <!-- Replace prefix with performer label as that becomes available -->
+                      <names variable="author" prefix="Recorded by ">
+                        <name and="symbol" initialize-with=". " delimiter=", "/>
+                      </names>
+                    </else>
+                  </choose>
+                </group>
+              </if>
+              <else>
+                <group delimiter=" ">
+                  <choose>
+                    <if variable="medium">
+                      <text variable="medium" text-case="capitalize-first"/>
+                      <!-- Replace prefix with performer label as that becomes available -->
+                      <names variable="author" prefix="recorded by ">
+                        <name and="symbol" initialize-with=". " delimiter=", "/>
+                      </names>
+                    </if>
+                    <else>
+                      <!-- Replace prefix with performer label as that becomes available -->
+                      <names variable="author" prefix="Recorded by ">
+                        <name and="symbol" initialize-with=". " delimiter=", "/>
+                      </names>
+                    </else>
+                  </choose>
+                </group>
+              </else>
+            </choose>
+            <choose>
+              <if variable="genre" match="any">
+                <choose>
+                  <if variable="number" match="none">
+                    <text variable="medium" text-case="capitalize-first"/>
+                  </if>
+                </choose>
+              </if>
+            </choose>
+          </group>
+        </else-if>
+        <else-if variable="container-title" match="none">
+          <!-- Other description -->
+          <text macro="format"/>
+        </else-if>
+        <else>
+          <!-- For conference presentations, chapters in reports, software, place bracketed after the container title -->
+          <choose>
+            <if type="paper-conference speech" match="any">
+              <choose>
+                <if variable="collection-editor editor editorial-director issue page volume" match="any">
+                  <text macro="format"/>
+                </if>
+              </choose>
+            </if>
+            <else-if type="book">
+              <choose>
+                <if variable="version" match="none">
+                  <text macro="format"/>
+                </if>
+              </choose>
+            </else-if>
+            <else-if type="report" match="none">
+              <text macro="format"/>
+            </else-if>
+          </choose>
+        </else>
+      </choose>
+    </group>
+  </macro>
+  <macro name="bracketed-intext">
+    <group prefix="[" suffix="]">
+      <choose>
+        <if variable="reviewed-author reviewed-title" type="review review-book" match="any">
+          <!-- This should be localized -->
+          <text macro="reviewed-title-intext" prefix="Review of "/>
+        </if>
+        <else-if variable="interviewer" type="interview" match="any">
+          <names variable="interviewer">
+            <label form="verb" suffix=" " text-case="capitalize-first"/>
+            <name and="symbol" initialize-with=". " delimiter=", "/>
+            <substitute>
+              <text macro="format-intext"/>
+            </substitute>
+          </names>
+        </else-if>
+        <else-if type="personal_communication">
+          <!-- Letter information -->
+          <choose>
+            <if variable="recipient">
+              <group delimiter=" ">
+                <choose>
+                  <if variable="number" match="none">
+                    <text variable="genre" text-case="capitalize-first"/>
+                  </if>
+                  <else>
+                    <text term="letter" form="short" text-case="capitalize-first"/>
+                  </else>
+                </choose>
+                <names variable="recipient" delimiter=", ">
+                  <label form="verb" suffix=" "/>
+                  <name and="symbol" delimiter=", "/>
+                </names>
+              </group>
+            </if>
+            <else>
+              <text macro="format-intext"/>
+            </else>
+          </choose>
+        </else-if>
+        <else>
+          <text macro="format-intext"/>
+        </else>
+      </choose>
+    </group>
+  </macro>
+  <macro name="bracketed-container">
+    <group prefix="[" suffix="]">
+      <choose>
+        <if type="paper-conference speech" match="any">
+          <!-- Conference presentations should describe the session [container] in bracketed unless published in a proceedings -->
+          <choose>
+            <if variable="collection-editor editor editorial-director issue page volume" match="none">
+              <text macro="format"/>
+            </if>
+          </choose>
+        </if>
+        <else-if type="book" variable="version" match="all">
+          <!-- For entries in mobile app reference works, place bracketed after the container-title -->
+          <text macro="format"/>
+        </else-if>
+        <else-if type="report">
+          <!-- For chapters in reports, place bracketed after the container title -->
+          <text macro="format"/>
+        </else-if>
+      </choose>
+    </group>
+  </macro>
+  <macro name="secondary-contributors">
+    <choose>
+      <if type="article-journal article-magazine article-newspaper post-weblog review review-book" match="any">
+        <text macro="secondary-contributors-periodical"/>
+      </if>
+      <else-if type="paper-conference">
+        <choose>
+          <if variable="collection-editor editor editorial-director" match="any">
+            <text macro="secondary-contributors-booklike"/>
+          </if>
+          <else>
+            <text macro="secondary-contributors-periodical"/>
+          </else>
+        </choose>
+      </else-if>
+      <else>
+        <text macro="secondary-contributors-booklike"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="secondary-contributors-periodical">
+    <group delimiter="; ">
+      <choose>
+        <if variable="title">
+          <names variable="interviewer" delimiter="; ">
+            <name and="symbol" initialize-with=". " delimiter=", "/>
+            <label form="short" prefix=", " text-case="title"/>
+          </names>
+        </if>
+      </choose>
+      <names variable="translator" delimiter="; ">
+        <name and="symbol" initialize-with=". " delimiter=", "/>
+        <label form="short" prefix=", " text-case="title"/>
+      </names>
+    </group>
+  </macro>
+  <macro name="secondary-contributors-booklike">
+    <group delimiter="; ">
+      <choose>
+        <if variable="title">
+          <names variable="interviewer">
+            <name and="symbol" initialize-with=". " delimiter=", "/>
+            <label form="short" prefix=", " text-case="title"/>
+          </names>
+        </if>
+      </choose>
+      <!-- When editortranslator becomes available, add a test: variable="editortranslator" match="none"; then print translator -->
+      <choose>
+        <if type="post webpage" match="none">
+          <!-- Webpages treat container-title like publisher -->
+          <choose>
+            <if variable="container-title" match="none">
+              <group delimiter="; ">
+                <names variable="container-author">
+                  <label form="verb-short" suffix=" " text-case="title"/>
+                  <name and="symbol" initialize-with=". " delimiter=", "/>
+                </names>
+                <names variable="editor translator" delimiter="; ">
+                  <name and="symbol" initialize-with=". " delimiter=", "/>
+                  <label form="short" prefix=", " text-case="title"/>
+                </names>
+              </group>
+            </if>
+          </choose>
+        </if>
+        <else>
+          <group delimiter="; ">
+            <names variable="container-author">
+              <label form="verb-short" suffix=" " text-case="title"/>
+              <name and="symbol" initialize-with=". " delimiter=", "/>
+            </names>
+            <names variable="editor translator" delimiter="; ">
+              <name and="symbol" initialize-with=". " delimiter=", "/>
+              <label form="short" prefix=", " text-case="title"/>
+            </names>
+          </group>
+        </else>
+      </choose>
+    </group>
+  </macro>
+  <macro name="database-location">
+    <choose>
+      <if variable="archive-place" match="none">
+        <!-- With `archive-place`: physical archives. Without: online archives. -->
+        <!-- Add archive_collection as that becomes available -->
+        <text variable="archive_location"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="number">
+    <choose>
+      <if variable="number">
+        <group delimiter=", ">
+          <group delimiter=" ">
+            <text variable="genre" text-case="title"/>
+            <choose>
+              <if is-numeric="number">
+                <!-- Replace with label variable="number" if that becomes available -->
+                <text term="issue" form="short" text-case="capitalize-first"/>
+                <text variable="number"/>
+              </if>
+              <else>
+                <text variable="number"/>
+              </else>
+            </choose>
+          </group>
+          <choose>
+            <if type="thesis">
+              <choose>
+                <!-- Include the university in brackets if thesis is published -->
+                <if variable="archive DOI URL" match="any">
+                  <text variable="publisher"/>
+                </if>
+              </choose>
+            </if>
+          </choose>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="locators-booklike">
+    <choose>
+      <if type="article-journal article-magazine article-newspaper broadcast interview patent post post-weblog review review-book speech webpage" match="any"/>
+      <else-if type="paper-conference">
+        <choose>
+          <if variable="collection-editor editor editorial-director" match="any">
+            <group delimiter=", ">
+              <text macro="version"/>
+              <text macro="edition"/>
+              <text macro="volume-booklike"/>
+            </group>
+          </if>
+        </choose>
+      </else-if>
+      <else>
+        <group delimiter=", ">
+          <text macro="version"/>
+          <text macro="edition"/>
+          <text macro="volume-booklike"/>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <macro name="version">
+    <choose>
+      <if is-numeric="version">
+        <group delimiter=" ">
+          <!-- replace with label variable="version" if that becomes available -->
+          <text term="version" text-case="capitalize-first"/>
+          <text variable="version"/>
+        </group>
+      </if>
+      <else>
+        <text variable="version"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="edition">
+    <choose>
+      <if is-numeric="edition">
+        <group delimiter=" ">
+          <number variable="edition" form="ordinal"/>
+          <label variable="edition" form="short"/>
+        </group>
+      </if>
+      <else>
+        <text variable="edition"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="volume-booklike">
+    <group delimiter=", ">
+      <!-- Report series [ex. 52] -->
+      <choose>
+        <if type="report">
+          <group delimiter=" ">
+            <text variable="collection-title" text-case="title"/>
+            <text variable="collection-number"/>
+          </group>
+        </if>
+      </choose>
+      <choose>
+        <if variable="volume" match="any">
+          <choose>
+            <!-- Non-numeric volumes are already printed as part of the book title -->
+            <if is-numeric="volume" match="none"/>
+            <else>
+              <group delimiter=" ">
+                <label variable="volume" form="short" text-case="capitalize-first"/>
+                <number variable="volume" form="numeric"/>
+              </group>
+            </else>
+          </choose>
+        </if>
+        <else>
+          <group>
+            <!-- Replace with label variable="number-of-volumes" if that becomes available -->
+            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>
+            <text term="page-range-delimiter" prefix="1"/>
+            <number variable="number-of-volumes" form="numeric"/>
+          </group>
+        </else>
+      </choose>
+      <group delimiter=" ">
+        <label variable="issue" text-case="capitalize-first"/>
+        <text variable="issue"/>
+      </group>
+      <group delimiter=" ">
+        <label variable="page" form="short" suffix=" "/>
+        <text variable="page"/>
+      </group>
+    </group>
+  </macro>
+  <macro name="reviewed-title">
+    <choose>
+      <if variable="reviewed-title">
+        <!-- Not possible to distinguish TV series episode from other reviewed 
+              works [Ex. 69] -->
+        <text variable="reviewed-title" font-style="italic"/>
+      </if>
+      <else>
+        <!-- Assume title is title of reviewed work -->
+        <text variable="title" font-style="italic"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="reviewed-title-intext">
+    <choose>
+      <if variable="reviewed-title">
+        <!-- Not possible to distinguish TV series episode from other reviewed works [Ex. 69] -->
+        <text variable="reviewed-title" form="short" font-style="italic"/>
+      </if>
+      <else>
+        <!-- Assume title is title of reviewed work -->
+        <text variable="title" form="short" font-style="italic"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="format">
+    <choose>
+      <if variable="genre medium" match="any">
+        <group delimiter="; ">
+          <choose>
+            <if variable="number" match="none">
+              <text variable="genre" text-case="capitalize-first"/>
+            </if>
+          </choose>
+          <text variable="medium" text-case="capitalize-first"/>
+        </group>
+      </if>
+      <!-- Generic labels for specific types -->
+      <!-- These should be localized when possible -->
+      <else-if type="dataset">
+        <text value="Data set"/>
+      </else-if>
+      <else-if type="book" variable="version" match="all">
+        <!-- Replace with type="software" and term="software" as that becomes available -->
+        <text value="Computer software"/>
+      </else-if>
+      <else-if type="interview personal_communication" match="any">
+        <choose>
+          <if variable="archive container-title DOI publisher URL" match="none">
+            <text term="letter" text-case="capitalize-first"/>
+          </if>
+          <else-if type="interview">
+            <text term="interview" text-case="capitalize-first"/>
+          </else-if>
+        </choose>
+      </else-if>
+      <else-if type="map">
+        <text value="Map"/>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="format-intext">
+    <choose>
+      <if variable="genre" match="any">
+        <text variable="genre" text-case="capitalize-first"/>
+      </if>
+      <else-if variable="medium">
+        <text variable="medium" text-case="capitalize-first"/>
+      </else-if>
+      <!-- Generic labels for specific types -->
+      <!-- These should be localized when possible -->
+      <else-if type="dataset">
+        <text value="Data set"/>
+      </else-if>
+      <else-if type="book" variable="version" match="all">
+        <!-- Replace with type="software" and term="software" as that becomes available -->
+        <text value="Computer software"/>
+      </else-if>
+      <else-if type="interview personal_communication" match="any">
+        <choose>
+          <if variable="archive container-title DOI publisher URL" match="none">
+            <text term="letter" text-case="capitalize-first"/>
+          </if>
+          <else-if type="interview">
+            <text term="interview" text-case="capitalize-first"/>
+          </else-if>
+        </choose>
+      </else-if>
+      <else-if type="map">
+        <text value="Map"/>
+      </else-if>
+    </choose>
+  </macro>
+  <!-- APA 'source' element contains four parts:
+       container, event, publisher, access -->
+  <macro name="container">
+    <choose>
+      <if type="article-journal article-magazine article-newspaper post-weblog review review-book" match="any">
+        <!-- Periodical items -->
+        <text macro="container-periodical"/>
+      </if>
+      <else-if type="paper-conference">
+        <!-- Determine if paper-conference is a periodical or booklike -->
+        <choose>
+          <if variable="editor editorial-director collection-editor container-author" match="any">
+            <text macro="container-booklike"/>
+          </if>
+          <else>
+            <text macro="container-periodical"/>
+          </else>
+        </choose>
+      </else-if>
+      <else-if type="post webpage" match="none">
+        <!-- post and webpage treat container-title like publisher -->
+        <text macro="container-booklike"/>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="container-periodical">
+    <group delimiter=". ">
+      <group delimiter=", ">
+        <text variable="container-title" font-style="italic" text-case="title"/>
+        <choose>
+          <if variable="volume">
+            <group>
+              <text variable="volume" font-style="italic"/>
+              <text variable="issue" prefix="(" suffix=")"/>
+            </group>
+          </if>
+          <else>
+            <text variable="issue" font-style="italic"/>
+          </else>
+        </choose>
+        <choose>
+          <if variable="page">
+            <text variable="page"/>
+          </if>
+          <else>
+            <!-- Ex. 6: Journal article with article number or eLocator -->
+            <!-- This should be localized -->
+            <text variable="number" prefix="Article "/>
+          </else>
+        </choose>
+      </group>
+      <choose>
+        <if variable="issued">
+          <choose>
+            <if variable="issue page volume" match="none">
+              <text variable="status" text-case="capitalize-first"/>
+            </if>
+          </choose>
+        </if>
+      </choose>
+    </group>
+  </macro>
+  <macro name="container-booklike">
+    <choose>
+      <if variable="container-title" match="any">
+        <group delimiter=" ">
+          <text term="in" text-case="capitalize-first"/>
+          <group delimiter=", ">
+            <names variable="editor translator" delimiter=", &amp; ">
+              <!-- Change to editortranslator and move editor to substitute as that becomes available -->
+              <name and="symbol" initialize-with=". " delimiter=", "/>
+              <label form="short" text-case="title" prefix=" (" suffix=")"/>
+              <substitute>
+                <names variable="editorial-director"/>
+                <names variable="collection-editor"/>
+                <names variable="container-author"/>
+              </substitute>
+            </names>
+            <group delimiter=": " font-style="italic">
+              <text variable="container-title"/>
+              <!-- Replace with volume-title as that becomes available -->
+              <choose>
+                <if is-numeric="volume" match="none">
+                  <group delimiter=" ">
+                    <label variable="volume" form="short" text-case="capitalize-first"/>
+                    <text variable="volume"/>
+                  </group>
+                </if>
+              </choose>
+            </group>
+          </group>
+          <text macro="parenthetical-container"/>
+          <text macro="bracketed-container"/>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <group delimiter="; ">
+      <choose>
+        <if type="thesis">
+          <choose>
+            <if variable="archive DOI URL" match="none">
+              <text variable="publisher"/>
+            </if>
+          </choose>
+        </if>
+        <else-if type="post webpage" match="any">
+          <!-- For websites, treat container title like publisher -->
+          <group delimiter="; ">
+            <text variable="container-title" text-case="title"/>
+            <text variable="publisher"/>
+          </group>
+        </else-if>
+        <else-if type="paper-conference">
+          <!-- For paper-conference, don't print publisher if in a journal-like proceedings -->
+          <choose>
+            <if variable="collection-editor editor editorial-director" match="any">
+              <text variable="publisher"/>
+            </if>
+          </choose>
+        </else-if>
+        <else-if type="article-journal article-magazine article-newspaper post-weblog" match="none">
+          <text variable="publisher"/>
+        </else-if>
+      </choose>
+      <group delimiter=", ">
+        <choose>
+          <if variable="archive-place">
+            <!-- With `archive-place`: physical archives. Without: online archives. -->
+            <!-- For physical archives, print the location before the archive name.
+                For electronic archives, these are printed in macro="description". -->
+            <!-- Split "archive_location" into "archive_collection" and "archive_location" as that becomes available -->
+            <!-- Must test for archive_collection:
+                With collection: archive_collection (archive_location), archive, archive-place
+                No collection: archive (archive_location), archive-place
+            -->
+            <text variable="archive_location"/>
+          </if>
+        </choose>
+        <text variable="archive"/>
+        <text variable="archive-place"/>
+      </group>
+    </group>
+  </macro>
+  <macro name="access">
+    <choose>
+      <if variable="DOI" match="any">
+        <text variable="DOI" prefix="https://doi.org/"/>
+      </if>
+      <else-if variable="URL">
+        <group delimiter=" ">
+          <choose>
+            <if variable="issued status" match="none">
+              <group delimiter=" ">
+                <text term="retrieved" text-case="capitalize-first"/>
+                <date variable="accessed" form="text" suffix=","/>
+                <text term="from"/>
+              </group>
+            </if>
+          </choose>
+          <text variable="URL"/>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="event">
+    <choose>
+      <if variable="event">
+        <!-- To prevent Zotero from printing event-place due to its double-mapping of all 'place' to
+             both publisher-place and event-place. Remove this 'choose' when that is changed. -->
+        <choose>
+          <if variable="collection-editor editor editorial-director issue page volume" match="none">
+            <!-- Don't print event info if published in a proceedings -->
+            <group delimiter=", ">
+              <text variable="event"/>
+              <text variable="event-place"/>
+            </group>
+          </if>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <!-- After 'source', APA also prints publication history (original publication, reprint info, retraction info) -->
+  <macro name="publication-history">
+    <choose>
+      <if type="patent" match="none">
+        <group prefix="(" suffix=")">
+          <choose>
+            <if variable="references">
+              <!-- This provides the option for more elaborate description 
+                   of publication history, such as full "reprinted" references
+                   (examples 11, 43, 44) or retracted references -->
+              <text variable="references"/>
+            </if>
+            <else>
+              <group delimiter=" ">
+                <text value="Original work published"/>
+                <choose>
+                  <if is-uncertain-date="original-date">
+                    <text term="circa" form="short"/>
+                  </if>
+                </choose>
+                <date variable="original-date">
+                  <date-part name="year"/>
+                </date>
+              </group>
+            </else>
+          </choose>
+        </group>
+      </if>
+      <else>
+        <text variable="references" prefix="(" suffix=")"/>
+      </else>
+    </choose>
+  </macro>
+  <!-- Legal citations have their own rules -->
+  <macro name="legal-cites">
+    <choose>
+      <if type="legal_case">
+        <group delimiter=". ">
+          <group delimiter=", ">
+            <text variable="title"/>
+            <group delimiter=" ">
+              <text macro="container-legal"/>
+              <text macro="date-legal"/>
+            </group>
+            <text variable="references"/>
+          </group>
+          <text macro="access"/>
+        </group>
+      </if>
+      <else-if type="bill">
+        <!-- Currently designed to handle bills, resolutions, hearings, rederal reports. -->
+        <group delimiter=". ">
+          <group delimiter=", ">
+            <choose>
+              <if variable="number container-title" match="none">
+                <!-- If no number or container-title, then assume it is a hearing -->
+                <text variable="title" font-style="italic"/>
+              </if>
+              <else>
+                <text variable="title"/>
+              </else>
+            </choose>
+            <group delimiter=" ">
+              <text macro="container-legal"/>
+              <text macro="date-legal"/>
+              <choose>
+                <if variable="number container-title" match="none">
+                  <!-- If no number or container-title, then assume it is a hearing -->
+                  <names variable="author" prefix="(testimony of " suffix=")">
+                    <name and="symbol" delimiter=", "/>
+                  </names>
+                </if>
+                <else>
+                  <text variable="status" prefix="(" suffix=")"/>
+                </else>
+              </choose>
+            </group>
+            <text variable="references"/>
+          </group>
+          <text macro="access"/>
+        </group>
+      </else-if>
+      <else-if type="legislation">
+        <!-- Currently designed to handle statutes, codified regulations, executive orders.
+             For uncodified regulations, assume future code section is in status. -->
+        <group delimiter=". ">
+          <group delimiter=", ">
+            <text variable="title"/>
+            <group delimiter=" ">
+              <text macro="container-legal"/>
+              <text macro="date-legal"/>
+              <text variable="status" prefix="(" suffix=")"/>
+            </group>
+            <text variable="references"/>
+          </group>
+          <text macro="access"/>
+        </group>
+      </else-if>
+      <else-if type="treaty">
+        <!-- APA generally defers to Bluebook for legal citations, but diverges without
+             explanation for treaty items. The Bluebook format that was used in APA 6th
+             ed. is used here. -->
+        <group delimiter=", ">
+          <text variable="title" text-case="title"/>
+          <names variable="author">
+            <name initialize-with="." form="short" delimiter="-"/>
+          </names>
+          <text macro="date-legal"/>
+          <text macro="container-legal"/>
+          <text macro="access"/>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="date-legal">
+    <choose>
+      <if type="legal_case">
+        <group prefix="(" suffix=")" delimiter=" ">
+          <text variable="authority"/>
+          <choose>
+            <if variable="container-title" match="any">
+              <!-- Print only year for cases published in reporters-->
+              <date variable="issued" form="numeric" date-parts="year"/>
+            </if>
+            <else>
+              <date variable="issued" form="text"/>
+            </else>
+          </choose>
+        </group>
+      </if>
+      <else-if type="bill legislation" match="any">
+        <group prefix="(" suffix=")" delimiter=" ">
+          <group delimiter=" ">
+            <date variable="original-date">
+              <date-part name="year"/>
+            </date>
+            <text term="and" form="symbol"/>
+          </group>
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+        </group>
+      </else-if>
+      <else-if type="treaty">
+        <date variable="issued" form="text"/>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="container-legal">
+    <!-- Expect legal item container-titles to be stored in short form -->
+    <choose>
+      <if type="legal_case">
+        <group delimiter=" ">
+          <choose>
+            <if variable="container-title">
+              <group delimiter=" ">
+                <text variable="volume"/>
+                <text variable="container-title"/>
+                <group delimiter=" ">
+                  <!-- Change to label variable="section" as that becomes available -->
+                  <text term="section" form="symbol"/>
+                  <text variable="section"/>
+                </group>
+                <choose>
+                  <if variable="page page-first" match="any">
+                    <text variable="page-first"/>
+                  </if>
+                  <else>
+                    <text value="___"/>
+                  </else>
+                </choose>
+              </group>
+            </if>
+            <else>
+              <group delimiter=" ">
+                <choose>
+                  <if is-numeric="number">
+                    <!-- Replace with label variable="number" if that becomes available -->
+                    <text term="issue" form="short" text-case="capitalize-first"/>
+                  </if>
+                </choose>
+                <text variable="number"/>
+              </group>
+            </else>
+          </choose>
+        </group>
+      </if>
+      <else-if type="bill">
+        <group delimiter=", ">
+          <group delimiter=" ">
+            <text variable="genre"/>
+            <group delimiter=" ">
+              <choose>
+                <if variable="chapter-number container-title" match="none">
+                  <!-- Replace with label variable="number" as that becomes available -->
+                  <text term="issue" form="short"/>
+                </if>
+              </choose>
+              <text variable="number"/>
+            </group>
+          </group>
+          <text variable="authority"/>
+          <text variable="chapter-number"/>
+          <group delimiter=" ">
+            <text variable="volume"/>
+            <text variable="container-title"/>
+            <text variable="page-first"/>
+          </group>
+        </group>
+      </else-if>
+      <else-if type="legislation">
+        <choose>
+          <if variable="number">
+            <!--There's a public law number-->
+            <group delimiter=", ">
+              <text variable="number" prefix="Pub. L. No. "/>
+              <group delimiter=" ">
+                <text variable="volume"/>
+                <text variable="container-title"/>
+                <text variable="page-first"/>
+              </group>
+            </group>
+          </if>
+          <else>
+            <group delimiter=" ">
+              <text variable="volume"/>
+              <text variable="container-title"/>
+              <choose>
+                <if variable="section">
+                  <group delimiter=" ">
+                    <!-- Change to label variable="section" as that becomes available -->
+                    <text term="section" form="symbol"/>
+                    <text variable="section"/>
+                  </group>
+                </if>
+                <else>
+                  <text variable="page-first"/>
+                </else>
+              </choose>
+            </group>
+          </else>
+        </choose>
+      </else-if>
+      <else-if type="treaty">
+        <group delimiter=" ">
+          <number variable="volume"/>
+          <text variable="container-title"/>
+          <choose>
+            <if variable="page page-first" match="any">
+              <text variable="page-first"/>
+            </if>
+            <else>
+              <group delimiter=" ">
+                <!-- Replace with label variable="number" if that becomes available -->
+                <text term="issue" form="short" text-case="capitalize-first"/>
+                <text variable="number"/>
+              </group>
+            </else>
+          </choose>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="citation-locator">
+    <group delimiter=" ">
+      <choose>
+        <if locator="chapter">
+          <label variable="locator" text-case="capitalize-first"/>
+        </if>
+        <else>
+          <label variable="locator" form="short"/>
+        </else>
+      </choose>
+      <text variable="locator"/>
+    </group>
+  </macro>
+  <citation collapse="citation-number">
+    <sort>
+      <key variable="citation-number"/>
+    </sort>
+    <layout delimiter="," prefix="[" suffix="]" vertical-align="sup">
+      <group>
+        <text variable="citation-number"/>
+        <text macro="citation-locator" prefix="(" suffix=")"/>
+      </group>
+    </layout>
+  </citation>
+  <bibliography hanging-indent="true" et-al-min="21" et-al-use-first="19" et-al-use-last="true" entry-spacing="0" line-spacing="2">
+    <layout>
+      <group delimiter=". ">
+        <text variable="citation-number"/>
+        <choose>
+          <if type="bill legal_case legislation treaty" match="any">
+            <!-- Legal items have different orders and delimiters -->
+            <choose>
+              <if variable="DOI URL" match="any">
+                <text macro="legal-cites"/>
+              </if>
+              <else>
+                <text macro="legal-cites" suffix="."/>
+              </else>
+            </choose>
+          </if>
+          <else>
+            <group delimiter=" ">
+              <group delimiter=". " suffix=".">
+                <text macro="author-bib"/>
+                <text macro="date-bib"/>
+                <text macro="title-and-descriptions"/>
+                <text macro="container"/>
+                <text macro="event"/>
+                <text macro="publisher"/>
+              </group>
+              <text macro="access"/>
+              <text macro="publication-history"/>
+            </group>
+          </else>
+        </choose>
+      </group>
+    </layout>
+  </bibliography>
+</style>
diff --git a/elpa/org-ref-20230507.1420/citeproc/csl-styles/chicago-author-date-16th-edition.csl b/elpa/org-ref-20230507.1420/citeproc/csl-styles/chicago-author-date-16th-edition.csl
new file mode 100644 (file)
index 0000000..6ff1f0b
--- /dev/null
@@ -0,0 +1,657 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="display-and-sort" page-range-format="chicago">
+  <info>
+    <title>Chicago Manual of Style 16th edition (author-date)</title>
+    <id>http://www.zotero.org/styles/chicago-author-date-16th-edition</id>
+    <link href="http://www.zotero.org/styles/chicago-author-date-16th-edition" rel="self"/>
+    <link href="http://www.chicagomanualofstyle.org/tools_citationguide.html" rel="documentation"/>
+    <author>
+      <name>Julian Onions</name>
+      <email>julian.onionsNOSPAMgmail.com</email>
+    </author>
+    <contributor>
+      <name>Sebastian Karcher</name>
+    </contributor>
+    <contributor>
+      <name>Richard Karnesky</name>
+      <email>karnesky+zoteroNOSPAMgmail.com</email>
+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
+    </contributor>
+    <contributor>
+      <name>Andrew Dunning</name>
+      <email>andrew.dunningNOSPAMutoronto.ca</email>
+    </contributor>
+    <contributor>
+      <name>Brenton M. Wiernik</name>
+    </contributor>
+    <category citation-format="author-date"/>
+    <category field="generic-base"/>
+    <summary>The author-date variant of the Chicago style</summary>
+    <updated>2020-04-26T18:22:50+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <locale xml:lang="en">
+    <terms>
+      <term name="editor" form="verb-short">ed.</term>
+      <term name="container-author" form="verb">by</term>
+      <term name="translator" form="verb-short">trans.</term>
+      <term name="editortranslator" form="verb">edited and translated by</term>
+      <term name="translator" form="short">trans.</term>
+    </terms>
+  </locale>
+  <macro name="secondary-contributors">
+    <choose>
+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="none">
+        <group delimiter=". ">
+          <names variable="editor translator" delimiter=". ">
+            <label form="verb" text-case="capitalize-first" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+          <names variable="director" delimiter=". ">
+            <label form="verb" text-case="capitalize-first" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="container-contributors">
+    <choose>
+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">
+        <group prefix=", " delimiter=", ">
+          <names variable="container-author" delimiter=", ">
+            <label form="verb" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+          <names variable="editor translator" delimiter=", ">
+            <label form="verb" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="editor">
+    <names variable="editor">
+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=", "/>
+    </names>
+  </macro>
+  <macro name="translator">
+    <names variable="translator">
+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=", "/>
+    </names>
+  </macro>
+  <macro name="recipient">
+    <choose>
+      <if type="personal_communication">
+        <choose>
+          <if variable="genre">
+            <text variable="genre" text-case="capitalize-first"/>
+          </if>
+          <else>
+            <text term="letter" text-case="capitalize-first"/>
+          </else>
+        </choose>
+      </if>
+    </choose>
+    <names variable="recipient" delimiter=", ">
+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>
+      <name and="text" delimiter=", "/>
+    </names>
+  </macro>
+  <macro name="substitute-title">
+    <choose>
+      <if type="article-magazine article-newspaper review review-book" match="any">
+        <text macro="container-title"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="contributors">
+    <group delimiter=". ">
+      <names variable="author">
+        <name and="text" name-as-sort-order="first" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>
+        <label form="short" prefix=", "/>
+        <substitute>
+          <names variable="editor"/>
+          <names variable="translator"/>
+          <names variable="director"/>
+          <text macro="substitute-title"/>
+          <text macro="title"/>
+        </substitute>
+      </names>
+      <text macro="recipient"/>
+    </group>
+  </macro>
+  <macro name="contributors-short">
+    <names variable="author">
+      <name form="short" and="text" delimiter=", " initialize-with=". "/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <names variable="director"/>
+        <text macro="substitute-title"/>
+        <text macro="title"/>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="interviewer">
+    <names variable="interviewer" delimiter=", ">
+      <label form="verb" prefix=" " text-case="capitalize-first" suffix=" "/>
+      <name and="text" delimiter=", "/>
+    </names>
+  </macro>
+  <macro name="archive">
+    <group delimiter=". ">
+      <text variable="archive_location" text-case="capitalize-first"/>
+      <text variable="archive"/>
+      <text variable="archive-place"/>
+    </group>
+  </macro>
+  <macro name="access">
+    <group delimiter=". ">
+      <choose>
+        <if type="graphic report" match="any">
+          <text macro="archive"/>
+        </if>
+        <else-if type="article-journal bill book chapter legal_case legislation motion_picture paper-conference" match="none">
+          <text macro="archive"/>
+        </else-if>
+      </choose>
+      <choose>
+        <if type="webpage post-weblog" match="any">
+          <date variable="issued" delimiter=" ">
+            <date-part name="month"/>
+            <date-part name="day"/>
+          </date>
+        </if>
+      </choose>
+      <choose>
+        <if variable="issued" match="none">
+          <group delimiter=" ">
+            <text term="accessed" text-case="capitalize-first"/>
+            <date variable="accessed" delimiter=" ">
+              <date-part name="month"/>
+              <date-part name="day"/>
+            </date>
+          </group>
+        </if>
+      </choose>
+      <choose>
+        <if type="legal_case" match="none">
+          <choose>
+            <if variable="DOI">
+              <text variable="DOI" prefix="doi:"/>
+            </if>
+            <else>
+              <text variable="URL"/>
+            </else>
+          </choose>
+        </if>
+      </choose>
+    </group>
+  </macro>
+  <macro name="title">
+    <choose>
+      <if variable="title" match="none">
+        <choose>
+          <if type="personal_communication" match="none">
+            <text variable="genre" text-case="capitalize-first"/>
+          </if>
+        </choose>
+      </if>
+      <else-if type="bill book graphic legislation motion_picture song" match="any">
+        <text variable="title" text-case="title" font-style="italic"/>
+        <group prefix=" (" suffix=")" delimiter=" ">
+          <text term="version"/>
+          <text variable="version"/>
+        </group>
+      </else-if>
+      <else-if variable="reviewed-author">
+        <choose>
+          <if variable="reviewed-title">
+            <group delimiter=". ">
+              <text variable="title" text-case="title" quotes="true"/>
+              <group delimiter=", ">
+                <text variable="reviewed-title" text-case="title" font-style="italic" prefix="Review of "/>
+                <names variable="reviewed-author">
+                  <label form="verb-short" text-case="lowercase" suffix=" "/>
+                  <name and="text" delimiter=", "/>
+                </names>
+              </group>
+            </group>
+          </if>
+          <else>
+            <group delimiter=", ">
+              <text variable="title" text-case="title" font-style="italic" prefix="Review of "/>
+              <names variable="reviewed-author">
+                <label form="verb-short" text-case="lowercase" suffix=" "/>
+                <name and="text" delimiter=", "/>
+              </names>
+            </group>
+          </else>
+        </choose>
+      </else-if>
+      <else-if type="legal_case interview patent" match="any">
+        <text variable="title"/>
+      </else-if>
+      <else>
+        <text variable="title" text-case="title" quotes="true"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="edition">
+    <choose>
+      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+        <choose>
+          <if is-numeric="edition">
+            <group delimiter=" " prefix=". ">
+              <number variable="edition" form="ordinal"/>
+              <text term="edition" form="short" strip-periods="true"/>
+            </group>
+          </if>
+          <else>
+            <text variable="edition" text-case="capitalize-first" prefix=". "/>
+          </else>
+        </choose>
+      </if>
+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">
+        <choose>
+          <if is-numeric="edition">
+            <group delimiter=" " prefix=", ">
+              <number variable="edition" form="ordinal"/>
+              <text term="edition" form="short"/>
+            </group>
+          </if>
+          <else>
+            <text variable="edition" prefix=", "/>
+          </else>
+        </choose>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="locators">
+    <choose>
+      <if type="article-journal">
+        <choose>
+          <if variable="volume">
+            <text variable="volume" prefix=" "/>
+            <group prefix=" (" suffix=")">
+              <choose>
+                <if variable="issue">
+                  <text variable="issue"/>
+                </if>
+                <else>
+                  <date variable="issued">
+                    <date-part name="month"/>
+                  </date>
+                </else>
+              </choose>
+            </group>
+          </if>
+          <else-if variable="issue">
+            <group delimiter=" " prefix=", ">
+              <text term="issue" form="short"/>
+              <text variable="issue"/>
+              <date variable="issued" prefix="(" suffix=")">
+                <date-part name="month"/>
+              </date>
+            </group>
+          </else-if>
+          <else>
+            <date variable="issued" prefix=", ">
+              <date-part name="month"/>
+            </date>
+          </else>
+        </choose>
+      </if>
+      <else-if type="legal_case">
+        <text variable="volume" prefix=", "/>
+        <text variable="container-title" prefix=" "/>
+        <text variable="page" prefix=" "/>
+      </else-if>
+      <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+        <group prefix=". " delimiter=". ">
+          <group>
+            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>
+            <number variable="volume" form="numeric"/>
+          </group>
+          <group>
+            <number variable="number-of-volumes" form="numeric"/>
+            <text term="volume" form="short" prefix=" " plural="true"/>
+          </group>
+        </group>
+      </else-if>
+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">
+        <choose>
+          <if variable="page" match="none">
+            <group prefix=". ">
+              <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>
+              <number variable="volume" form="numeric"/>
+            </group>
+          </if>
+        </choose>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="locators-chapter">
+    <choose>
+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">
+        <choose>
+          <if variable="page">
+            <group prefix=", ">
+              <text variable="volume" suffix=":"/>
+              <text variable="page"/>
+            </group>
+          </if>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="locators-article">
+    <choose>
+      <if type="article-newspaper">
+        <group prefix=", " delimiter=", ">
+          <group delimiter=" ">
+            <text variable="edition"/>
+            <text term="edition"/>
+          </group>
+          <group>
+            <text term="section" form="short" suffix=" "/>
+            <text variable="section"/>
+          </group>
+        </group>
+      </if>
+      <else-if type="article-journal">
+        <choose>
+          <if variable="volume issue" match="any">
+            <text variable="page" prefix=": "/>
+          </if>
+          <else>
+            <text variable="page" prefix=", "/>
+          </else>
+        </choose>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="point-locators">
+    <choose>
+      <if variable="locator">
+        <choose>
+          <if locator="page" match="none">
+            <choose>
+              <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+                <choose>
+                  <if variable="volume">
+                    <group>
+                      <text term="volume" form="short" suffix=" "/>
+                      <number variable="volume" form="numeric"/>
+                      <label variable="locator" form="short" prefix=", " suffix=" "/>
+                    </group>
+                  </if>
+                  <else>
+                    <label variable="locator" form="short" suffix=" "/>
+                  </else>
+                </choose>
+              </if>
+              <else>
+                <label variable="locator" form="short" suffix=" "/>
+              </else>
+            </choose>
+          </if>
+          <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+            <number variable="volume" form="numeric" suffix=":"/>
+          </else-if>
+        </choose>
+        <text variable="locator"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="container-prefix">
+    <text term="in" text-case="capitalize-first"/>
+  </macro>
+  <macro name="container-title">
+    <choose>
+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">
+        <text macro="container-prefix" suffix=" "/>
+      </if>
+    </choose>
+    <choose>
+      <if type="legal_case" match="none">
+        <text variable="container-title" text-case="title" font-style="italic"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <group delimiter=": ">
+      <text variable="publisher-place"/>
+      <text variable="publisher"/>
+    </group>
+  </macro>
+  <macro name="date">
+    <choose>
+      <if variable="issued">
+        <group delimiter=" ">
+          <date variable="original-date" form="text" date-parts="year" prefix="(" suffix=")"/>
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+        </group>
+      </if>
+      <else-if variable="accessed">
+        <date variable="accessed">
+          <date-part name="year"/>
+        </date>
+      </else-if>
+      <else-if variable="status">
+        <text variable="status" text-case="capitalize-first"/>
+      </else-if>
+      <else>
+        <text term="no date" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="date-in-text">
+    <choose>
+      <if variable="issued">
+        <group delimiter=" ">
+          <date variable="original-date" form="text" date-parts="year" prefix="[" suffix="]"/>
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+        </group>
+      </if>
+      <else-if variable="accessed">
+        <date variable="accessed">
+          <date-part name="year"/>
+        </date>
+      </else-if>
+      <else-if variable="status">
+        <text variable="status"/>
+      </else-if>
+      <else>
+        <text term="no date" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="day-month">
+    <date variable="issued">
+      <date-part name="month"/>
+      <date-part name="day" prefix=" "/>
+    </date>
+  </macro>
+  <macro name="collection-title">
+    <choose>
+      <if match="none" type="article-journal">
+        <choose>
+          <if match="none" is-numeric="collection-number">
+            <group delimiter=", ">
+              <text variable="collection-title" text-case="title"/>
+              <text variable="collection-number"/>
+            </group>
+          </if>
+          <else>
+            <group delimiter=" ">
+              <text variable="collection-title" text-case="title"/>
+              <text variable="collection-number"/>
+            </group>
+          </else>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="collection-title-journal">
+    <choose>
+      <if type="article-journal">
+        <group delimiter=" ">
+          <text variable="collection-title"/>
+          <text variable="collection-number"/>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="event">
+    <group delimiter=" ">
+      <choose>
+        <if variable="genre">
+          <text term="presented at"/>
+        </if>
+        <else>
+          <text term="presented at" text-case="capitalize-first"/>
+        </else>
+      </choose>
+      <text variable="event"/>
+    </group>
+  </macro>
+  <macro name="description">
+    <choose>
+      <if type="interview">
+        <group delimiter=". ">
+          <text macro="interviewer"/>
+          <text variable="medium" text-case="capitalize-first"/>
+        </group>
+      </if>
+      <else-if type="patent">
+        <group delimiter=" " prefix=". ">
+          <text variable="authority"/>
+          <text variable="number"/>
+        </group>
+      </else-if>
+      <else>
+        <text variable="medium" text-case="capitalize-first" prefix=". "/>
+      </else>
+    </choose>
+    <choose>
+      <if variable="title" match="none"/>
+      <else-if type="thesis personal_communication speech" match="any"/>
+      <else>
+        <group delimiter=" " prefix=". ">
+          <text variable="genre" text-case="capitalize-first"/>
+          <choose>
+            <if type="report">
+              <text variable="number"/>
+            </if>
+          </choose>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <macro name="issue">
+    <choose>
+      <if type="legal_case">
+        <text variable="authority" prefix=". "/>
+      </if>
+      <else-if type="speech">
+        <group prefix=". " delimiter=", ">
+          <group delimiter=" ">
+            <text variable="genre" text-case="capitalize-first"/>
+            <text macro="event"/>
+          </group>
+          <text variable="event-place"/>
+          <text macro="day-month"/>
+        </group>
+      </else-if>
+      <else-if type="article-newspaper article-magazine personal_communication" match="any">
+        <text macro="day-month" prefix=", "/>
+      </else-if>
+      <else-if type="patent">
+        <group delimiter=", " prefix=", ">
+          <group delimiter=" ">
+            <!--Needs Localization-->
+            <text value="filed"/>
+            <date variable="submitted" form="text"/>
+          </group>
+          <group delimiter=" ">
+            <choose>
+              <if variable="issued submitted" match="all">
+                <text term="and"/>
+              </if>
+            </choose>
+            <!--Needs Localization-->
+            <text value="issued"/>
+            <date variable="issued" form="text"/>
+          </group>
+        </group>
+      </else-if>
+      <else>
+        <group prefix=". " delimiter=", ">
+          <choose>
+            <if type="thesis">
+              <text variable="genre" text-case="capitalize-first"/>
+            </if>
+          </choose>
+          <text macro="publisher"/>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <citation et-al-min="4" et-al-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" collapse="year">
+    <layout prefix="(" suffix=")" delimiter="; ">
+      <group delimiter=", ">
+        <choose>
+          <if variable="issued accessed" match="any">
+            <group delimiter=" ">
+              <text macro="contributors-short"/>
+              <text macro="date-in-text"/>
+            </group>
+          </if>
+          <!---comma before forthcoming and n.d.-->
+          <else>
+            <group delimiter=", ">
+              <text macro="contributors-short"/>
+              <text macro="date-in-text"/>
+            </group>
+          </else>
+        </choose>
+        <text macro="point-locators"/>
+      </group>
+    </layout>
+  </citation>
+  <bibliography hanging-indent="true" et-al-min="11" et-al-use-first="7" subsequent-author-substitute="&#8212;&#8212;&#8212;" entry-spacing="0">
+    <sort>
+      <key macro="contributors"/>
+      <key variable="issued"/>
+      <key variable="title"/>
+    </sort>
+    <layout suffix=".">
+      <group delimiter=". ">
+        <text macro="contributors"/>
+        <text macro="date"/>
+        <text macro="title"/>
+      </group>
+      <text macro="description"/>
+      <text macro="secondary-contributors" prefix=". "/>
+      <text macro="container-title" prefix=". "/>
+      <text macro="container-contributors"/>
+      <text macro="edition"/>
+      <text macro="locators-chapter"/>
+      <text macro="collection-title-journal" prefix=", " suffix=", "/>
+      <text macro="locators"/>
+      <text macro="collection-title" prefix=". "/>
+      <text macro="issue"/>
+      <text macro="locators-article"/>
+      <text macro="access" prefix=". "/>
+    </layout>
+  </bibliography>
+</style>
diff --git a/elpa/org-ref-20230507.1420/citeproc/csl-styles/elsevier-harvard.csl b/elpa/org-ref-20230507.1420/citeproc/csl-styles/elsevier-harvard.csl
new file mode 100644 (file)
index 0000000..cc97857
--- /dev/null
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="never" default-locale="en-US">
+  <info>
+    <title>Elsevier - Harvard (with titles)</title>
+    <id>http://www.zotero.org/styles/elsevier-harvard</id>
+    <link href="http://www.zotero.org/styles/elsevier-harvard" rel="self"/>
+    <link href="http://www.zotero.org/styles/ecology-letters" rel="template"/>
+    <link href="http://www.elsevier.com/journals/biological-conservation/0006-3207/guide-for-authors#68000" rel="documentation"/>
+    <author>
+      <name>David Kaplan</name>
+      <email>david.kaplanNOSPAMird.fr</email>
+    </author>
+    <contributor>
+      <name>Simon Kornblith</name>
+      <email>simonNOSPAMsimonster.com</email>
+    </contributor>
+    <contributor>
+      <name>Bruce D'Arcus</name>
+    </contributor>
+    <contributor>
+      <name>Curtis M. Humphrey</name>
+    </contributor>
+    <contributor>
+      <name>Richard Karnesky</name>
+      <email>karnesky+zoteroNOSPAMgmail.com</email>
+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
+    </contributor>
+    <contributor>
+      <name>Sebastian Karcher</name>
+    </contributor>
+    <category citation-format="author-date"/>
+    <category field="biology"/>
+    <category field="generic-base"/>
+    <updated>2014-03-04T00:09:00+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <macro name="container">
+    <choose>
+      <if type="chapter paper-conference" match="any">
+        <text term="in" prefix=", " suffix=": "/>
+        <names variable="editor translator" delimiter=", " suffix=", ">
+          <name name-as-sort-order="all" sort-separator=", " initialize-with="." delimiter=", " delimiter-precedes-last="always"/>
+          <label form="short" text-case="capitalize-first" prefix=" (" suffix=")"/>
+        </names>
+        <group delimiter=", ">
+          <text variable="container-title" text-case="title"/>
+          <text variable="collection-title" text-case="title"/>
+        </group>
+      </if>
+      <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+        <group prefix=", " delimiter=", ">
+          <text variable="container-title"/>
+          <text variable="collection-title"/>
+        </group>
+      </else-if>
+      <else>
+        <group prefix=". " delimiter=", ">
+          <text variable="container-title" form="short"/>
+          <text variable="collection-title"/>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <macro name="author">
+    <names variable="author">
+      <name name-as-sort-order="all" sort-separator=", " initialize-with="." delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=" (" suffix=")" text-case="capitalize-first"/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <text macro="title"/>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="author-short">
+    <names variable="author">
+      <name form="short" and="text" delimiter=", " initialize-with=". "/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <choose>
+          <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+            <text variable="title" form="short" font-style="italic"/>
+          </if>
+          <else>
+            <text variable="title" form="short" quotes="true"/>
+          </else>
+        </choose>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="access">
+    <choose>
+      <if variable="DOI">
+        <text variable="DOI" prefix="https://doi.org/"/>
+      </if>
+      <else-if type="webpage post-weblog" match="any">
+        <group delimiter=" ">
+          <text value="URL"/>
+          <text variable="URL"/>
+          <group prefix="(" suffix=").">
+            <text term="accessed" suffix=" "/>
+            <date variable="accessed">
+              <date-part name="month" form="numeric" suffix="."/>
+              <date-part name="day" suffix="."/>
+              <date-part name="year" form="short"/>
+            </date>
+          </group>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="title">
+    <choose>
+      <if type="report thesis" match="any">
+        <text variable="title"/>
+        <group prefix=" (" suffix=")" delimiter=" ">
+          <text variable="genre"/>
+          <text variable="number" prefix="No. "/>
+        </group>
+      </if>
+      <else-if type="bill book graphic legal_case legislation motion_picture report song speech" match="any">
+        <text variable="title"/>
+        <text macro="edition" prefix=", "/>
+      </else-if>
+      <else-if type="webpage">
+        <text variable="title"/>
+        <text value="WWW Document" prefix=" [" suffix="]"/>
+      </else-if>
+      <else>
+        <text variable="title"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <group delimiter=", ">
+      <text variable="publisher"/>
+      <text variable="publisher-place"/>
+    </group>
+  </macro>
+  <macro name="event">
+    <choose>
+      <if variable="event">
+        <text term="presented at" text-case="capitalize-first" suffix=" "/>
+        <text variable="event"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="issued">
+    <choose>
+      <if variable="issued">
+        <date variable="issued">
+          <date-part name="year"/>
+        </date>
+      </if>
+      <else>
+        <text term="no date" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="edition">
+    <group delimiter=" ">
+      <choose>
+        <if is-numeric="edition">
+          <number variable="edition" form="ordinal"/>
+        </if>
+        <else>
+          <text variable="edition" suffix="."/>
+        </else>
+      </choose>
+      <text value="ed"/>
+    </group>
+  </macro>
+  <macro name="locators">
+    <choose>
+      <if type="article-journal article-magazine article-newspaper" match="any">
+        <group prefix=" " delimiter=", ">
+          <group>
+            <text variable="volume"/>
+          </group>
+          <text variable="page"/>
+        </group>
+      </if>
+      <else-if type="bill book graphic legal_case legislation motion_picture report song thesis" match="any">
+        <group delimiter=", " prefix=". ">
+          <text macro="event"/>
+          <text macro="publisher"/>
+        </group>
+      </else-if>
+      <else-if type="chapter paper-conference" match="any">
+        <group delimiter=", " prefix=". ">
+          <text macro="event"/>
+          <text macro="publisher"/>
+          <group>
+            <label variable="page" form="short" suffix=" "/>
+            <text variable="page"/>
+          </group>
+        </group>
+      </else-if>
+      <else-if type="patent">
+        <text variable="number" prefix=". "/>
+      </else-if>
+    </choose>
+  </macro>
+  <citation et-al-min="3" et-al-use-first="1" disambiguate-add-givenname="true" disambiguate-add-year-suffix="true" collapse="year" cite-group-delimiter=", ">
+    <sort>
+      <key macro="author"/>
+      <key macro="issued" sort="descending"/>
+    </sort>
+    <layout prefix="(" suffix=")" delimiter="; ">
+      <group delimiter=", ">
+        <text macro="author-short"/>
+        <text macro="issued"/>
+        <group delimiter=" ">
+          <label variable="locator" form="short"/>
+          <text variable="locator"/>
+        </group>
+      </group>
+    </layout>
+  </citation>
+  <bibliography hanging-indent="true" entry-spacing="0" line-spacing="1">
+    <sort>
+      <key macro="author"/>
+      <key macro="issued" sort="descending"/>
+    </sort>
+    <layout>
+      <group suffix=".">
+        <text macro="author" suffix=","/>
+        <text macro="issued" prefix=" "/>
+        <group prefix=". ">
+          <text macro="title"/>
+          <text macro="container"/>
+          <text macro="locators"/>
+        </group>
+      </group>
+      <text macro="access" prefix=". "/>
+    </layout>
+  </bibliography>
+</style>
\ No newline at end of file
diff --git a/elpa/org-ref-20230507.1420/citeproc/csl-styles/elsevier-with-titles.csl b/elpa/org-ref-20230507.1420/citeproc/csl-styles/elsevier-with-titles.csl
new file mode 100644 (file)
index 0000000..135329d
--- /dev/null
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-US">
+  <info>
+    <title>Elsevier (numeric, with titles)</title>
+    <id>http://www.zotero.org/styles/elsevier-with-titles</id>
+    <link href="http://www.zotero.org/styles/elsevier-with-titles" rel="self"/>
+    <link href="http://www.zotero.org/styles/elsevier-without-titles" rel="template"/>
+    <link href="http://www.elsevier.com/journals/journal-of-hazardous-materials/0304-3894/guide-for-authors#68001" rel="documentation"/>
+    <author>
+      <name>Richard Karnesky</name>
+      <email>karnesky+zoteroNOSPAMgmail.com</email>
+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
+    </author>
+    <contributor>
+      <name>Rintze Zelle</name>
+      <uri>http://twitter.com/rintzezelle</uri>
+    </contributor>
+    <category citation-format="numeric"/>
+    <category field="generic-base"/>
+    <summary>A style for many of Elsevier's journals that includes article titles in the reference list</summary>
+    <updated>2019-10-15T15:14:08+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <macro name="author">
+    <names variable="author">
+      <name initialize-with="." delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=", "/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="editor">
+    <names variable="editor">
+      <name initialize-with="." delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=" (" text-case="capitalize-first" suffix=")"/>
+    </names>
+  </macro>
+  <macro name="year-date">
+    <choose>
+      <if variable="issued">
+        <date variable="issued">
+          <date-part name="year"/>
+        </date>
+      </if>
+      <else>
+        <text term="no date" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <text variable="publisher" suffix=", "/>
+    <text variable="publisher-place" suffix=", "/>
+    <text macro="year-date"/>
+  </macro>
+  <macro name="edition">
+    <!--TODO: CSL should have low numeric be text (e.g. '3'->'third')-->
+    <choose>
+      <if is-numeric="edition">
+        <group delimiter=" ">
+          <number variable="edition" form="ordinal"/>
+          <text term="edition" form="short"/>
+        </group>
+      </if>
+      <else>
+        <text variable="edition"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="access">
+    <choose>
+      <if variable="URL">
+        <text variable="URL"/>
+        <group prefix=" (" suffix=")" delimiter=" ">
+          <text term="accessed"/>
+          <date variable="accessed" form="text"/>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <citation collapse="citation-number">
+    <sort>
+      <key variable="citation-number"/>
+    </sort>
+    <layout prefix="[" suffix="]" delimiter=",">
+      <text variable="citation-number"/>
+    </layout>
+  </citation>
+  <bibliography entry-spacing="0" second-field-align="flush">
+    <layout suffix=".">
+      <text variable="citation-number" prefix="[" suffix="]"/>
+      <text macro="author" suffix=", "/>
+      <choose>
+        <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+          <group delimiter=", ">
+            <text variable="title"/>
+            <text macro="edition"/>
+            <text macro="publisher"/>
+          </group>
+        </if>
+        <else-if type="chapter paper-conference" match="any">
+          <text variable="title" suffix=", "/>
+          <text term="in" suffix=": "/>
+          <text macro="editor" suffix=", "/>
+          <text variable="container-title" form="short" text-case="title" suffix=", "/>
+          <text macro="edition" suffix=", "/>
+          <text macro="publisher"/>
+          <group delimiter=" ">
+            <label variable="page" form="short" prefix=": "/>
+            <text variable="page"/>
+          </group>
+        </else-if>
+        <else-if type="patent">
+          <group delimiter=", ">
+            <text variable="title"/>
+            <text variable="number"/>
+            <text macro="year-date"/>
+          </group>
+        </else-if>
+        <else-if type="thesis">
+          <group delimiter=", ">
+            <text variable="title"/>
+            <text variable="genre"/>
+            <text variable="publisher"/>
+            <text macro="year-date"/>
+          </group>
+        </else-if>
+        <else>
+          <group delimiter=" ">
+            <text variable="title" suffix=","/>
+            <text variable="container-title" form="short" text-case="title" suffix="."/>
+            <text variable="volume"/>
+            <text macro="year-date" prefix="(" suffix=")"/>
+            <text variable="page" form="short"/>
+          </group>
+        </else>
+      </choose>
+      <choose>
+        <if variable="DOI">
+          <text variable="DOI" prefix=". https://doi.org/"/>
+        </if>
+        <else>
+          <text macro="access" prefix=". "/>
+        </else>
+      </choose>
+    </layout>
+  </bibliography>
+</style>
diff --git a/elpa/org-ref-20230507.1420/contrib.el b/elpa/org-ref-20230507.1420/contrib.el
new file mode 100644 (file)
index 0000000..4e811de
--- /dev/null
@@ -0,0 +1,73 @@
+;;; contrib.el --- Code contributed by users
+
+;;; Commentary:
+;; 
+
+;;; Code:
+
+;; * Add messages in minibuffer
+;; Contributed in https://github.com/jkitchin/org-ref/issues/938 by @DiogoFerrari
+
+
+(defun org-ref-get-bibtex-key-under-cursor--display ()
+  "Return key under the cursor in `org-mode'.
+If not on a key, but on a cite, prompt for key."
+  (if-let ((key (get-text-property (point) 'cite-key)))
+      ;; Point is on a key, so we get it directly
+      key
+    ;; point is not on a key, but may still be on a cite link
+    (let ((el (org-element-context))
+         data
+         keys)
+      (cond
+       ;; on a cite-link type
+       ((and
+        (eq (org-element-type el) 'link)
+        (assoc (org-element-property :type el) org-ref-cite-types))
+
+       (goto-char (org-element-property :begin el))
+       (setq data (org-ref-parse-cite-path (org-element-property :path el))
+             keys (cl-loop for ref in (plist-get data :references)
+                           collect (plist-get ref :key)))
+       (setq text nil)
+       (dolist (key keys)
+         (search-forward key)
+         (goto-char (match-beginning 0))
+         (get-text-property (point) 'cite-key)
+         ;; (message (bibtex-completion-apa-format-reference key))
+         (setq text (concat text "\n" (bibtex-completion-apa-format-reference key))))))))
+  (message (string-trim-left text)))
+
+
+(defvar org-ref-message-timer nil
+  "Stores the idle timer for cite minibuffer messages.")
+
+
+(defcustom org-ref-message-interval 0.5
+  "Time in seconds to wait for the idle timer that displays the cite message."
+  :group 'org-ref)
+
+
+(defun org-ref-link-message ()
+  "Display a message in the minibuffer when point is on a cite link."
+  (when (and (eq major-mode 'org-mode) (eq (get-text-property (point) 'help-echo) 'org-ref-cite-tooltip))
+    (save-excursion (org-ref-get-bibtex-key-under-cursor--display))))
+
+
+(defun org-ref-messages-on ()
+  "Turn cite messages to minibuffer on."
+  (interactive)
+  (setq org-ref-message-timer (run-with-idle-timer org-ref-message-interval 0 'org-ref-link-message)))
+
+
+(defun org-ref-messages-off ()
+  "Turn cite messages to minibuffer off."
+  (interactive)
+  (when org-ref-message-timer
+    (cancel-timer org-ref-message-timer)
+    (setq org-ref-message-timer nil)))
+
+
+(provide 'contrib)
+
+;;; contrib.el ends here
diff --git a/elpa/org-ref-20230507.1420/doi-utils.el b/elpa/org-ref-20230507.1420/doi-utils.el
new file mode 100644 (file)
index 0000000..74e0d65
--- /dev/null
@@ -0,0 +1,1659 @@
+;;; doi-utils.el --- DOI utilities for making bibtex entries
+
+;; Copyright (C) 2015-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+;; Version: 0.1
+;; Package-Requires: ((org-ref))
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides functionality to download PDFs and bibtex entries from
+;; a DOI, as well as to update a bibtex entry from a DOI.  It depends slightly
+;; on org-ref, to determine where to save pdf files too, and where to insert
+;; bibtex entries in the default bibliography.
+
+;; The principle commands you will use from here are:
+
+;; - doi-utils-get-bibtex-entry-pdf with the cursor in a bibtex entry.
+;; - doi-utils-insert-bibtex-entry-from-doi to insert a bibtex entry at your cursor, clean it and try to get a pdf.
+;; - doi-utils-add-bibtex-entry-from-doi to add an entry to your default bibliography (cleaned with pdf if possible).
+;; - doi-utils-update-bibtex-entry-from-doi with cursor in an entry to update its fields.
+
+;;; Code:
+
+(defvar url-http-end-of-headers)
+(declare-function org-ref-find-bibliography "org-ref-core")
+(declare-function org-ref-clean-bibtex-entry "org-ref-core")
+(declare-function bibtex-completion-edit-notes "bibtex-completion")
+(declare-function org-bibtex-yank "org-bibtex")
+(declare-function org-ref-possible-bibfiles "org-ref-core")
+
+(eval-when-compile
+  (require 'cl-lib))
+(require 'bibtex)
+(require 'dash)
+(require 'json)
+(require 'org)                          ; org-add-link-type
+
+(or (require 'ol-bibtex nil t)
+    (require 'org-bibtex)) ; org-bibtex-yank
+
+(require 'url-http)
+(require 'org-ref-utils)
+(require 'hydra)
+
+;;* Customization
+(defgroup doi-utils nil
+  "Customization group for doi-utils."
+  :tag "DOI utils"
+  :group 'doi-utils)
+
+
+(defcustom doi-utils-download-pdf
+  t
+  "Try to download PDFs when adding bibtex entries when non-nil."
+  :type 'boolean
+  :group 'doi-utils)
+
+(defcustom doi-utils-open-pdf-after-download
+  nil
+  "Open PDF after adding bibtex entries."
+  :type 'boolean
+  :group 'doi-utils)
+
+
+(defcustom doi-utils-timestamp-field
+  "DATE_ADDED"
+  "The bibtex field to store the date when an entry has been added."
+  :type 'string
+  :group 'doi-utils)
+
+(defcustom doi-utils-timestamp-format-function
+  'current-time-string
+  "The function to format the timestamp for a bibtex entry.
+Set to a function that returns nil to avoid setting timestamps in the entries.
+e.g. (lambda () nil)"
+  :type 'function
+  :group 'doi-utils)
+
+
+(defcustom doi-utils-dx-doi-org-url
+  "https://doi.org/"
+  "Base url to retrieve doi metadata from. A trailing / is required."
+  :type 'string
+  :group 'doi-utils)
+
+
+(defcustom doi-utils-metadata-function 'doi-utils-get-json-metadata
+  "Function for retrieving json metadata from `doi-utils-dx-doi-org-url'.
+The default is `doi-utils-get-json-metadata', but it sometimes
+fails with a proxy. An alternative is
+`doi-utils-get-json-metadata-curl' which requires an external
+program to use curl."
+  :type 'function
+  :group 'doi-utils)
+
+
+(defcustom doi-utils-async-download t
+  "Use `doi-utils-async-download-pdf' to get pdfs asynchrounously.
+If nil use `doi-utils-get-bibtex-entry-pdf' synchronously."
+  :type 'boolean
+  :group 'doi-utils)
+
+
+;;* Getting pdf files from a DOI
+
+;; The idea here is simple. When you visit http://dx.doi.org/doi or
+;; https://doi.org/doi, you get redirected to the journal site. Once you have
+;; the url for the article, you can usually compute the url to the pdf, or find
+;; it in the page. Then you simply download it.
+
+;; There are some subtleties in doing this that are described here. To get the
+;; redirect, we have to use url-retrieve, and a callback function. The callback
+;; does not return anything, so we communicate through global variables.
+;; url-retrieve is asynchronous, so we have to make sure to wait for it to
+;; finish.
+
+(defvar *doi-utils-waiting* t
+  "Stores waiting state for url retrieval.")
+
+(defvar *doi-utils-redirect* nil
+  "Stores redirect url from a callback function.")
+
+(defun doi-utils-redirect-callback (&optional status)
+  "Callback for `url-retrieve' to set the redirect.
+Optional argument STATUS Unknown why this is optional."
+  (when (plist-get status :error)
+    (signal (car (plist-get status :error)) (cdr(plist-get status :error))))
+  (when (plist-get status :redirect) ;  is nil if there none
+    (setq *doi-utils-redirect* (plist-get status :redirect)))
+  ;; we have done our job, so we are not waiting any more.
+  (setq *doi-utils-waiting* nil))
+
+;; To actually get the redirect we use url-retrieve like this.
+
+(defun doi-utils-get-redirect (doi)
+  "Get redirect url from `doi-utils-dx-doi-org-url'/doi."
+  ;; we are going to wait until the url-retrieve is done
+  (setq *doi-utils-waiting* t)
+  ;; start with no redirect. it will be set in the callback.
+  (setq *doi-utils-redirect* nil)
+  (url-retrieve
+   (format "%s%s" doi-utils-dx-doi-org-url doi)
+   'doi-utils-redirect-callback)
+  ;; I suspect we need to wait here for the asynchronous process to
+  ;; finish. we loop and sleep until the callback says it is done via
+  ;; `*doi-utils-waiting*'. this works as far as i can tell. Before I
+  ;; had to run this a few times to get it to work, which i suspect
+  ;; just gave the first one enough time to finish.
+  (while *doi-utils-waiting* (sleep-for 0.1)))
+
+;; Once we have a redirect for a particular doi, we need to compute the url to
+;; the pdf. We do this with a series of functions. Each function takes a single
+;; argument, the redirect url. If it knows how to compute the pdf url it does,
+;; and returns it. We store the functions in a variable:
+
+(defvar doi-utils-pdf-url-functions nil
+  "Functions that return a url to a pdf from a redirect url.
+Each function takes one argument, the redirect url.  The function
+must return a pdf-url, or nil.")
+
+
+;;** APS journals
+
+(defun aps-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s*\\)://journals.aps.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "/abstract/" "/pdf/" *doi-utils-redirect*)))
+
+
+;;** Science
+
+(defun science-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://www.sciencemag.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf")))
+
+
+;;** Nature
+
+(defun nature-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://www.nature.com" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".pdf")))
+
+
+;;** Elsevier/ScienceDirect
+;; You cannot compute these pdf links; they are embedded in the redirected pages.
+
+(defvar *doi-utils-pdf-url* nil
+  "Stores url to pdf download from a callback function.")
+
+;;** Wiley
+;; Wiley have changed the url structure from
+;; http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/abstract
+;; http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/pdf
+;; to
+;; http://onlinelibrary.wiley.com/doi/abs/10.1002/anie.201402680
+;; http://onlinelibrary.wiley.com/doi/pdf/10.1002/anie.201402680
+;; Hence fewer steps are now required.
+
+;; https://onlinelibrary.wiley.com/doi/10.1002/adts.202200926
+;; https://onlinelibrary.wiley.com/doi/epdf/10.1002/adts.202200926
+
+;; (defun wiley-pdf-url (*doi-utils-redirect*)
+;;   "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+;;   (when (string-match "^http\\(s?\\)://onlinelibrary.wiley.com" *doi-utils-redirect*)
+;;     (replace-regexp-in-string "doi/abs" "doi/pdf" *doi-utils-redirect*)))
+
+
+(defun wiley-pdf-url-2 (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*.
+[2023-04-10 Mon] updated a new rule.
+https://onlinelibrary.wiley.com/doi/pdfdirect/10.1002/anie.201310461?download=true"
+  (when (string-match "^http\\(s?\\)://onlinelibrary.wiley.com" *doi-utils-redirect*)
+    (concat
+     (replace-regexp-in-string "doi/" "doi/pdfdirect/" *doi-utils-redirect*)
+     "?download=true")))
+
+
+(defun agu-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "https://agupubs.onlinelibrary.wiley.com"
+                     *doi-utils-redirect*)
+    (replace-regexp-in-string "/full/" "/pdfdirect/" *doi-utils-redirect*)))
+
+
+;;** Springer
+
+(defun springer-chapter-pdf-url (*doi-utils-redirect*)
+  (when (string-match "^http\\(s?\\)://link.springer.com/chapter/" *doi-utils-redirect*)
+    (replace-regexp-in-string "/chapter" "/content/pdf"
+                             (concat *doi-utils-redirect* ".pdf"))))
+
+
+(defun springer-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://link.springer.com" *doi-utils-redirect*)
+    (replace-regexp-in-string "/article/" "/content/pdf/"
+                             (concat *doi-utils-redirect* ".pdf"))))
+
+
+;;** ACS
+;; here is a typical url http://pubs.acs.org/doi/abs/10.1021/nl500037x
+;; the pdf is found at http://pubs.acs.org/doi/pdf/10.1021/nl500037x
+
+;; we just change /abs/ to /pdf/.
+
+(defun acs-pdf-url-1 (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://pubs.acs.org/doi/abs/" *doi-utils-redirect*)
+    (replace-regexp-in-string "/abs/" "/pdf/" *doi-utils-redirect*)))
+
+;; 1/20/2016 I noticed this new pattern in pdf urls, where there is no abs in
+;; the url
+(defun acs-pdf-url-2 (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://pubs.acs.org/doi/" *doi-utils-redirect*)
+    (replace-regexp-in-string "/doi/" "/doi/pdf/" *doi-utils-redirect*)))
+
+;; 1/18/2019: It looks like they are using https now
+(defun acs-pdf-url-3 (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^https://pubs.acs.org/doi/" *doi-utils-redirect*)
+    (replace-regexp-in-string "/doi/" "/doi/pdf/" *doi-utils-redirect*)))
+
+
+;;** IOP
+
+(defun iop-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://iopscience.iop.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* "/pdf")))
+
+;;** JSTOR
+
+(defun jstor-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://www.jstor.org" *doi-utils-redirect*)
+    (concat (replace-regexp-in-string "/stable/" "/stable/pdfplus/" *doi-utils-redirect*) ".pdf")))
+
+
+;;** AIP
+
+(defun aip-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://scitation.aip.org" *doi-utils-redirect*)
+    ;; get stuff after content
+    (let (p1 p2 s p3)
+      (setq p2 (replace-regexp-in-string
+                "^http\\(s?\\)://scitation.aip.org/" "" *doi-utils-redirect*))
+      (setq s (split-string p2 "/"))
+      (setq p1 (mapconcat 'identity (-remove-at-indices '(0 6) s) "/"))
+      (setq p3 (concat "/" (nth 0 s) (nth 1 s) "/" (nth 2 s) "/" (nth 3 s)))
+      (format "http://scitation.aip.org/deliver/fulltext/%s.pdf?itemId=/%s&mimeType=pdf&containerItemId=%s"
+              p1 p2 p3))))
+
+(defun aip-pdf-url-2 (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  ;; [2021-08-28 Sat] Seems like they changed the link a little?
+  ;; https://aip.scitation.org/doi/10.1063/1.5019667
+  ;; to
+  ;; https://aip.scitation.org/doi/pdf/10.1063/1.5019667
+  (when (string-match "^http\\(s?\\)://aip.scitation.org" *doi-utils-redirect*)
+    (concat "https://aip.scitation.org/doi/pdf" (cl-second (split-string *doi-utils-redirect* "doi")))))
+
+;;** Taylor and Francis
+
+(defun tandfonline-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://www.tandfonline.com" *doi-utils-redirect*)
+    (replace-regexp-in-string "/abs/\\|/full/" "/pdf/" *doi-utils-redirect*)))
+
+;;** ECS
+
+(defun ecs-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://jes.ecsdl.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "\.abstract$" ".full.pdf" *doi-utils-redirect*)))
+
+;; http://ecst.ecsdl.org/content/25/2/2769
+;; http://ecst.ecsdl.org/content/25/2/2769.full.pdf
+
+
+(defun ecst-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://ecst.ecsdl.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf")))
+
+
+
+;;** RSC
+
+(defun rsc-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://pubs.rsc.org" *doi-utils-redirect*)
+    (let ((url (downcase *doi-utils-redirect*)))
+      (setq url (replace-regexp-in-string "articlelanding" "articlepdf" url))
+      url)))
+
+;;** Science Direct
+
+;; https://www.sciencedirect.com/science/article/pii/S001085452200577X?via%3Dihub
+;; https://www.sciencedirect.com/science/article/pii/S001085452200577X/pdfft?isDTMRedir=true&download=true
+
+(defun science-direct-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://www.sciencedirect.com" *doi-utils-redirect*)
+    (replace-string "?via%3Dihub" "/pdfft?isDTMRedir=true&download=true" *doi-utils-redirect*)))
+
+;; (defun doi-utils-get-science-direct-pdf-url (redirect-url)
+;;   "Science direct hides the pdf url in html.  We get it out here.
+;; REDIRECT-URL is where the pdf url will be in."
+;;   (let ((first-url
+;;          (with-current-buffer (url-retrieve-synchronously redirect-url)
+;;            (goto-char (point-min))
+;;            (when (re-search-forward "pdf_url\" content=\"\\([^\"]*\\)\"" nil t)
+;;              (match-string-no-properties 1)))))
+;;     (and first-url
+;;          (with-current-buffer (url-retrieve-synchronously first-url)
+;;            (goto-char (point-min))
+;;            (when (re-search-forward "or click <a href=\"\\([^\"]*\\)\">" nil t)
+;;              (match-string-no-properties 1))))))
+
+;; (defun science-direct-pdf-url (*doi-utils-redirect*)
+;;   "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+;;   (when (string-match "^http\\(s?\\)://www.sciencedirect.com" *doi-utils-redirect*)
+;;     (doi-utils-get-science-direct-pdf-url *doi-utils-redirect*)))
+
+;; sometimes I get
+;; http://linkinghub.elsevier.com/retrieve/pii/S0927025609004558
+;; which actually redirect to
+;; http://www.sciencedirect.com/science/article/pii/S0927025609004558
+
+;; https://www.sciencedirect.com/science/article/pii/S001085452200577X?via%3Dihub
+;; https://www.sciencedirect.com/science/article/pii/S001085452200577X/pdfft?isDTMRedir=true&download=true
+
+;; (defun linkinghub-elsevier-pdf-url (*doi-utils-redirect*)
+;;   "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+;;   (when (string-match
+;;      "^https://linkinghub.elsevier.com/retrieve" *doi-utils-redirect*)
+;;     (science-direct-pdf-url
+;;      (replace-regexp-in-string
+;;       ;; change URL to science direct and use function to get pdf URL
+;;       "https://linkinghub.elsevier.com/retrieve"
+;;       "https://www.sciencedirect.com/science/article"
+;;       *doi-utils-redirect*))))
+
+;; https://www.sciencedirect.com/science/article/pii/S1385894723014973/pdfft?isDTMRedir=true&download=true
+
+(defun linkinghub-elsevier-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match
+        "^https://linkinghub.elsevier.com/retrieve" *doi-utils-redirect*)
+    (concat
+     (replace-regexp-in-string
+      ;; change URL to science direct and use function to get pdf URL
+      "https://linkinghub.elsevier.com/retrieve"
+      "https://www.sciencedirect.com/science/article"
+      *doi-utils-redirect*)
+     "/pdfft?isDTMRedir=true")))
+
+;;** PNAS
+;; http://www.pnas.org/content/early/2014/05/08/1319030111
+;; http://www.pnas.org/content/early/2014/05/08/1319030111.full.pdf
+
+;; with supporting info
+;; http://www.pnas.org/content/early/2014/05/08/1319030111.full.pdf+html?with-ds=yes
+
+(defun pnas-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://www.pnas.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf?with-ds=yes")))
+
+
+;;** Copernicus Publications
+(defvar copernicus-journal-urls '(
+                                  "^https://www.adv-geosci.net/"
+                                  "^https://www.adv-radio-sci.net/"
+                                  "^https://www.adv-sci-res.net/"
+                                  "^https://www.adv-stat-clim-meteorol-oceanogr.net/"
+                                  "^https://www.ann-geophys.net/"
+                                  "^https://www.arch-anim-breed.net/"
+                                  "^https://www.astra-proc.net/"
+                                  "^https://www.atmos-chem-phys.net/"
+                                  "^https://www.atmos-chem-phys-discuss.net/"
+                                  "^https://www.atmos-meas-tech.net/"
+                                  "^https://www.atmos-meas-tech-discuss.net/"
+                                  "^https://www.biogeosciences.net/"
+                                  "^https://www.biogeosciences-discuss.net/"
+                                  "^https://www.clim-past.net/recent_papers.html"
+                                  "^https://www.clim-past-discuss.net/"
+                                  "^https://www.drink-water-eng-sci.net/"
+                                  "^https://www.drink-water-eng-sci-discuss.net/"
+                                  "^https://www.eg-quaternary-sci-j.net/"
+                                  "^https://www.earth-surf-dynam.net/"
+                                  "^https://www.earth-surf-dynam-discuss.net/"
+                                  "^https://www.earth-syst-dynam.net/"
+                                  "^https://www.earth-syst-dynam-discuss.net/"
+                                  "^https://www.earth-syst-sci-data.net/"
+                                  "^https://www.earth-syst-sci-data-discuss.net/"
+                                  "^https://www.foss-rec.net/"
+                                  "^https://www.geogr-helv.net/"
+                                  "^https://www.geosci-instrum-method-data-syst.net/"
+                                  "^https://www.geosci-instrum-method-data-syst-discuss.net/"
+                                  "^https://www.geosci-model-dev.net/"
+                                  "^https://www.geosci-model-dev-discuss.net/"
+                                  "^https://www.hist-geo-space-sci.net/"
+                                  "^https://www.hydrol-earth-syst-sci.net/"
+                                  "^https://www.hydrol-earth-syst-sci-discuss.net/"
+                                  "^https://www.j-sens-sens-syst.net/"
+                                  "^https://www.mech-sci.net/"
+                                  "^https://www.nat-hazards-earth-syst-sci.net/"
+                                  "^https://www.nonlin-processes-geophys-discuss.net/"
+                                  "^https://www.ocean-sci.net/"
+                                  "^https://www.ocean-sci-discuss.net/"
+                                  "^https://www.primate-biol.net/"
+                                  "^https://www.proc-iahs.net/"
+                                  "^https://www.sci-dril.net/"
+                                  "^https://www.soil-journal.net/"
+                                  "^https://www.soil-discuss.net/"
+                                  "^https://www.solid-earth.net/"
+                                  "^https://www.solid-earth-discuss.net/"
+                                  "^https://www.stephan-mueller-spec-publ-ser.net/"
+                                  "^https://www.the-cryosphere.net/"
+                                  "^https://www.the-cryosphere-discuss.net/"
+                                  "^https://www.web-ecol.net/"
+                                  "^https://www.wind-energ-sci.net/"
+                                  "^https://www.wind-energ-sci-discuss.net/"
+                                  )
+  "List of Copernicus URLs.")
+
+(defun doi-utils-get-copernicus-pdf-url (redirect-url)
+  "Copernicus hides the pdf url in html.  We get it out here.
+REDIRECT-URL is where the pdf url will be in."
+  (setq *doi-utils-waiting* t)
+  (url-retrieve
+   redirect-url
+   (lambda (status)
+     (goto-char (point-min))
+     (re-search-forward "citation_pdf_url\" content=\"\\([^\"]*\\)\"" nil t)
+
+     (setq *doi-utils-pdf-url* (match-string 1)
+          *doi-utils-waiting* nil)))
+  (while *doi-utils-waiting* (sleep-for 0.1))
+  *doi-utils-pdf-url*)
+
+(defun copernicus-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+
+  (car (cl-loop for copurl in copernicus-journal-urls
+               when (string-match copurl *doi-utils-redirect*)
+               collect
+               (progn (doi-utils-get-copernicus-pdf-url *doi-utils-redirect*)
+                      *doi-utils-pdf-url*))))
+
+
+;;** Sage
+(defun sage-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://pss.sagepub.com" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf")))
+
+
+;;** Journal of Neuroscience
+(defun jneurosci-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://www.jneurosci.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf")))
+
+;;** Generic .full.pdf
+(defun generic-full-pdf-url (*doi-utils-redirect*)
+  (let ((pdf (concat *doi-utils-redirect* ".full.pdf")))
+    (when (url-http-file-exists-p pdf)
+      pdf)))
+
+;;** IEEE
+;; 10.1109/re.2014.6912247
+;; http(s)://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6912247
+;; http(s)://ieeexplore.ieee.org/ielx7/6903646/6912234/06912247.pdf
+;; http(s)://ieeexplore.ieee.org/iel7/6903646/6912234/06912247.pdf?arnumber=6912247
+;; <meta name="citation_pdf_url" content="http(s)://ieeexplore.ieee.org/iel7/6903646/6912234/06912247.pdf?arnumber=6912247">
+;; <frame src="http(s)://ieeexplore.ieee.org/ielx7/6903646/6912234/06912247.pdf?tp=&arnumber=6912247&isnumber=6912234" frameborder=0 />
+(defun ieee-pdf-url (*doi-utils-redirect*)
+  "Get a url to the pdf from *DOI-UTILS-REDIRECT* for IEEE urls."
+  (when (string-match "^https?://ieeexplore.ieee.org" *doi-utils-redirect*)
+    (with-current-buffer (url-retrieve-synchronously *doi-utils-redirect*)
+      (goto-char (point-min))
+      (when (re-search-forward "<meta name=\"citation_pdf_url\" content=\"\\([[:ascii:]]*?\\)\">" nil t)
+       (let ((framed-url (match-string 1)))
+          (with-current-buffer (url-retrieve-synchronously framed-url)
+            (goto-char (point-min))
+            (when (re-search-forward "<frame src=\"\\(http[[:ascii:]]*?\\)\"" nil t)
+              (match-string 1))))))))
+
+;; At least some IEEE papers need the following new pdf-link parsing
+;; Example: 10.1109/35.667413
+(defun ieee2-pdf-url (*doi-utils-redirect*)
+  "Get a url to the pdf from *DOI-UTILS-REDIRECT* for IEEE urls."
+  (when (string-match "^https?://ieeexplore.ieee.org" *doi-utils-redirect*)
+    (with-current-buffer (url-retrieve-synchronously *doi-utils-redirect*)
+      (goto-char (point-min))
+      (when (re-search-forward "\"pdfUrl\":\"\\([[:ascii:]]*?\\)\"" nil t)
+       (let ((framed-url (match-string 1)))
+          (with-current-buffer (url-retrieve-synchronously (concat "http://ieeexplore.ieee.org" framed-url))
+            (goto-char (point-min))
+            (when (re-search-forward "<frame src=\"\\(http[[:ascii:]]*?\\)\"" nil t)
+              (match-string 1))))))))
+
+;; Another try to get the ieee pdf
+;; <iframe src="http(s)://ieeexplore.ieee.org/ielx5/8/4538127/04538164.pdf?tp=&arnumber=4538164&isnumber=4538127" frameborder=0>
+(defun ieee3-pdf-url (*doi-utils-redirect*)
+  "Get a url to the pdf from *DOI-UTILS-REDIRECT* for IEEE urls."
+  (when (string-match "^https?://ieeexplore.ieee.org" *doi-utils-redirect*)
+    (with-current-buffer (url-retrieve-synchronously *doi-utils-redirect*)
+      (goto-char (point-min))
+      (when (re-search-forward "\"pdfUrl\":\"\\([[:ascii:]]*?\\)\"" nil t)
+       (let ((framed-url (match-string 1)))
+          (with-current-buffer (url-retrieve-synchronously (concat "http://ieeexplore.ieee.org" framed-url))
+            (goto-char (point-min))
+            (when (re-search-forward "<iframe src=\"\\(http[[:ascii:]]*?\\)\"" nil t)
+              (match-string 1))))))))
+
+;; ACM Digital Library
+;; https://dl.acm.org/doi/10.1145/1368088.1368132
+(defun acm-pdf-url (*doi-utils-redirect*)
+  "Get a url to the pdf from *DOI-UTILS-REDIRECT* for ACM urls."
+  (when (string-match "^https?://dl.acm.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "doi" "doi/pdf" *doi-utils-redirect* )))
+
+;;** Optical Society of America (OSA)
+(defun osa-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^https://www.osapublishing.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "abstract.cfm" "viewmedia.cfm" *doi-utils-redirect* )))
+
+
+
+;;** ASME Biomechanical Journal
+
+(defun asme-biomechanical-pdf-url (*doi-utils-redirect*)
+  "Typical URL:  http://biomechanical.asmedigitalcollection.asme.org/article.aspx?articleid=1427237
+
+On this page the pdf might be here:     <meta name=\"citation_author\" content=\"Dalong Li\" /><meta27048/101013_1.pdf\" />
+
+It is in the citation_pdf_url.
+
+It would be better to parse this, but here I just use a regexp.
+"
+
+  (when (string-match "^http\\(s?\\)://biomechanical.asmedigitalcollection.asme.org" *doi-utils-redirect*)
+    (setq *doi-utils-waiting* 0)
+    (url-retrieve
+     *doi-utils-redirect*
+     (lambda (status)
+       (goto-char (point-min))
+       (re-search-forward "citation_pdf_url\" content=\"\\(.*\\)\"" nil t)
+       ;; (message-box (match-string 1))
+       (setq *doi-utils-pdf-url* (match-string 1)
+            *doi-utils-waiting* nil)))
+    (while (and *doi-utils-waiting* (< *doi-utils-waiting* 5))
+      (setq *doi-utils-waiting* (+ *doi-utils-waiting* 0.1))
+      (sleep-for 0.1))
+    *doi-utils-pdf-url*))
+
+
+;; Society for Industrial and Applied Mathematics (SIAM)
+(defun siam-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s?\\)://epubs.siam.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "/doi/" "/doi/pdf/" *doi-utils-redirect* )))
+
+;; PLOS journals
+;; https://plos.org/
+(defun plos-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http\\(s*\\)://journals.plos.org" *doi-utils-redirect*)
+    (concat (replace-regexp-in-string (regexp-quote "/article?id=") "/article/file?id=" *doi-utils-redirect*) "&type=printable")))
+
+
+;; https://www.frontiersin.org/articles/10.3389/fchem.2022.1037997/full
+;; https://www.frontiersin.org/articles/10.3389/fchem.2022.1037997/pdf
+(defun frontiers-pdf-url (*doi-utils-redirect*)
+  (when (string-match "^http\\(s*\\)://www.frontiersin.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "/full" "/pdf" *doi-utils-redirect*)))
+
+
+
+
+;; https://chemistry-europe.onlinelibrary.wiley.com/doi/10.1002/celc.201902035
+;; https://chemistry-europe.onlinelibrary.wiley.com/doi/epdf/10.1002/celc.201902035
+(defun chemistry-europe-pdf-url (*doi-utils-redirect*)
+  (when (string-match "^http\\(s*\\)://chemistry-europe.onlinelibrary.wiley.com" *doi-utils-redirect*)
+    (concat
+     (replace-regexp-in-string "/doi" "/doi/pdfdirect" *doi-utils-redirect*)
+     "?download=true")))
+
+
+
+;;** Add all functions
+
+(setq doi-utils-pdf-url-functions
+      (list
+       'aps-pdf-url
+       'science-pdf-url
+       'nature-pdf-url
+       ;; 'wiley-pdf-url
+       'wiley-pdf-url-2
+       'springer-chapter-pdf-url
+       'springer-pdf-url
+       'acs-pdf-url-1
+       'acs-pdf-url-2
+       'acs-pdf-url-3
+       'iop-pdf-url
+       'jstor-pdf-url
+       'aip-pdf-url
+       'aip-pdf-url-2
+       'science-direct-pdf-url
+       'linkinghub-elsevier-pdf-url
+       'tandfonline-pdf-url
+       'ecs-pdf-url
+       'ecst-pdf-url
+       'rsc-pdf-url
+       'pnas-pdf-url
+       'copernicus-pdf-url
+       'sage-pdf-url
+       'jneurosci-pdf-url
+       'ieee-pdf-url
+       'ieee2-pdf-url
+       'ieee3-pdf-url
+       'acm-pdf-url
+       'osa-pdf-url
+       'asme-biomechanical-pdf-url
+       'siam-pdf-url
+       'agu-pdf-url
+       'plos-pdf-url
+       'frontiers-pdf-url
+       'chemistry-europe-pdf-url 
+       'generic-full-pdf-url))
+
+;;** Get the pdf url for a doi
+
+(defun doi-utils-get-pdf-url (doi)
+  "Return a url to a pdf for the DOI if one can be calculated.
+Loops through the functions in `doi-utils-pdf-url-functions'
+until one is found."
+  (doi-utils-get-redirect doi)
+
+  (unless *doi-utils-redirect*
+    (error "No redirect found for %s" doi))
+  (catch 'pdf-url
+    (dolist (func doi-utils-pdf-url-functions)
+      (let ((this-pdf-url (funcall func *doi-utils-redirect*)))
+        (when this-pdf-url
+          (throw 'pdf-url this-pdf-url))))))
+
+;;** Finally, download the pdf
+(defvar bibtex-completion-library-path)
+(defvar bibtex-completion-bibliography)
+(declare-function async-start "async")
+
+;;;###autoload
+(defun doi-utils-async-download-pdf ()
+  "Download the PDF for bibtex entry at point asynchronously.
+It is not fully async, only the download is. Fully async is
+harder because you need to run `doi-utils-get-pdf-url' async
+too. "
+  (interactive)
+  (require 'async)
+  (save-excursion
+    (bibtex-beginning-of-entry)
+    (let (;; get doi, removing http://dx.doi.org/ if it is there.
+          (doi (replace-regexp-in-string
+                "https?://\\(dx.\\)?.doi.org/" ""
+                (bibtex-autokey-get-field "doi")))
+          (key (cdr (assoc "=key=" (bibtex-parse-entry))))
+          (pdf-url)
+          (pdf-file))
+
+      (setq pdf-file
+           (concat (cond
+                    ((stringp bibtex-completion-library-path)
+                     bibtex-completion-library-path)
+                    ((= 1 (length bibtex-completion-library-path))
+                     (car bibtex-completion-library-path))
+                    (t
+                     (completing-read "Dir: " bibtex-completion-library-path)))
+                   key ".pdf"))
+
+      (unless doi (error "No DOI found to get a pdf for"))
+
+      (when (file-exists-p pdf-file)
+       (error "%s already exists. Delete to re-download" pdf-file))
+
+      ;; (doi-utils-get-pdf-url "10.1063/1.5019667")
+      ;; If you get here, try getting the pdf file
+      (async-start
+       `(lambda ()
+         (setq package-user-dir ,package-user-dir)
+         (require 'package)
+         (package-initialize)
+         (setq load-path (list ,@load-path))
+         (require 'doi-utils)
+
+         (setq pdf-url (doi-utils-get-pdf-url ,doi))
+         (when pdf-url
+           (url-copy-file pdf-url ,pdf-file t)
+
+           (let* ((header (with-temp-buffer
+                            (set-buffer-multibyte nil)
+                            (insert-file-contents-literally ,pdf-file nil 0 5)
+                            (buffer-string)))
+                  (valid (and (stringp header)
+                              (string-equal (encode-coding-string header 'utf-8) "%PDF-"))))
+             (if valid
+                 (format "%s downloaded" ,pdf-file)
+               (delete-file ,pdf-file)
+               (require 'browse-url)
+               (browse-url pdf-url)
+               (message "Invalid pdf (file deleted). Header = %s" header)))))
+       `(lambda (result)
+         (message "doi-utils-async-download-pdf: %s"  result))))))
+
+
+;;;###autoload
+(defun doi-utils-get-bibtex-entry-pdf (&optional arg)
+  "Download pdf for entry at point if the pdf does not already exist locally.
+The entry must have a doi. The pdf will be saved, by the name
+%s.pdf where %s is the bibtex label. Files will not be
+overwritten. The pdf will be checked to make sure it is a pdf,
+and not some html failure page. You must have permission to
+access the pdf. We open the pdf at the end if
+`doi-utils-open-pdf-after-download' is non-nil.
+
+With one prefix ARG, directly get the pdf from a file (through
+`read-file-name') instead of looking up a DOI. With a double
+prefix ARG, directly get the pdf from an open buffer (through
+`read-buffer-to-switch') instead. These two alternative methods
+work even if the entry has no DOI, and the pdf file is not
+checked."
+  (interactive "P")
+  (save-excursion
+    (bibtex-beginning-of-entry)
+    (let (;; get doi, removing http://dx.doi.org/ if it is there.
+          (doi (replace-regexp-in-string
+                "https?://\\(dx.\\)?.doi.org/" ""
+                (bibtex-autokey-get-field "doi")))
+          (key (cdr (assoc "=key=" (bibtex-parse-entry))))
+          (pdf-url)
+          (pdf-file))
+
+      (setq pdf-file
+           (concat (cond
+                    ((stringp bibtex-completion-library-path)
+                     bibtex-completion-library-path)
+                    ((= 1 (length bibtex-completion-library-path))
+                     (car bibtex-completion-library-path))
+                    (t
+                     (completing-read "Dir: " bibtex-completion-library-path)))
+                   key ".pdf"))
+      ;; now get file if needed.
+      (unless (file-exists-p pdf-file)
+       (cond
+        ((and (not arg)
+              doi
+              (setq pdf-url (doi-utils-get-pdf-url doi)))
+         (url-copy-file pdf-url pdf-file)
+         ;; now check if we got a pdf
+          (if (org-ref-pdf-p pdf-file)
+              (message "%s saved" pdf-file)
+            (delete-file pdf-file)
+            (message "No pdf was downloaded.")
+            (browse-url pdf-url)))
+        ((equal arg '(4))
+         (copy-file (expand-file-name (read-file-name "Pdf file: " nil nil t))
+                    pdf-file))
+        ((equal arg '(16))
+         (with-current-buffer (read-buffer-to-switch "Pdf buffer: ")
+           (write-file pdf-file)))
+        (t
+         (message "We don't have a recipe for this journal.")))
+
+       (when (file-exists-p pdf-file)
+         (bibtex-set-field "file" pdf-file))
+
+       (when (and doi-utils-open-pdf-after-download (file-exists-p pdf-file))
+         (org-open-file pdf-file))))))
+
+;;* Getting bibtex entries from a DOI
+
+;; [[http://homepages.see.leeds.ac.uk/~eeaol/notes/2013/02/doi-metadata/][found]]
+;; you can download metadata about a DOI from http://dx.doi.org. You just have
+;; to construct the right http request to get it. Here is a function that gets
+;; the metadata as a plist in emacs.
+;;
+;;
+(defvar doi-utils-cache nil
+  "Cache variable for storing data we can reuse.
+A-list (doi . data) where doi is doi string, and data is what is
+retrieved from it. This is transient, and disappears when you
+restart Emacs. This mostly exists to prevent
+`doi-utils-update-field' from needing to download the data for
+every field.")
+
+
+(defun doi-utils-clear-cache ()
+  "Clear `doi-utils-cache'."
+  (interactive)
+  (setq doi-utils-cache '()))
+
+
+(defun doi-utils-get-json-metadata (doi)
+  "Try to get json metadata for DOI.  Open the DOI in a browser if we do not get it."
+  (if-let ((data (cdr (assoc doi doi-utils-cache))))
+      ;; We have the data already, so we return it.
+      data
+    (let ((url-request-method "GET")
+          (url-mime-accept-string "application/citeproc+json")
+          (json-object-type 'plist)
+          (json-data)
+         (url (concat doi-utils-dx-doi-org-url doi)))
+      (with-current-buffer
+          (url-retrieve-synchronously
+           ;; (concat "http://dx.doi.org/" doi)
+          url)
+       (setq json-data (buffer-substring url-http-end-of-headers (point-max)))
+
+       (when (or (string-match "<title>Error: DOI Not Found</title>" json-data)
+                 (string-match "Resource not found" json-data)
+                 (string-match "Status *406" json-data)
+                 (string-match "400 Bad Request" json-data))
+         (browse-url (concat doi-utils-dx-doi-org-url doi))
+         (error "Something went wrong.  We got this response:
+%s
+
+Opening %s" json-data url))
+
+       (setq data (json-read-from-string json-data))
+       (cl-pushnew (cons doi data) doi-utils-cache)
+       data))))
+
+
+(defun doi-utils-get-json-metadata-curl (doi)
+  "Try to get json metadata for DOI.  Open the DOI in a browser if we do not get it."
+  (let ((json-object-type 'plist)
+        (json-data)
+       (url (concat doi-utils-dx-doi-org-url doi)))
+    (with-temp-buffer
+      (call-process "curl" nil t nil
+                    "--location"
+                    "--silent"
+                    "--header"
+                    "Accept: application/citeproc+json"
+                    url)
+      (setq json-data (buffer-string))
+      (cond
+       ((or (string-match "<title>Error: DOI Not Found</title>" json-data)
+           (string-match "Resource not found" json-data)
+           (string-match "Status *406" json-data)
+           (string-match "400 Bad Request" json-data))
+       (browse-url url)
+       (error "Something went wrong.  We got this response:
+%s
+Opening %s" json-data url))
+       ;; everything seems ok with the data
+       (t
+       (json-read-from-string json-data))))))
+
+;; We can use that data to construct a bibtex entry. We do that by defining a
+;; template, and filling it in. I wrote this template expansion code which
+;; makes it easy to substitute values like %{} in emacs lisp.
+
+
+(defun doi-utils-expand-template (s)
+  "Expand a string template S containing %{} with the eval of its contents."
+  (replace-regexp-in-string "%{\\([^}]+\\)}"
+                           (lambda (arg)
+                             (let ((sexp (substring arg 2 -1)))
+                               (format "%s" (eval (read sexp)))))
+                           s))
+
+
+;; Now we define a function that fills in that template from the metadata.
+
+;; As different bibtex types share common keys, it is advantageous to separate
+;; data extraction from json, and the formatting of the bibtex entry.
+
+;; We use eval-and-compile because we use the three following forms in the
+;; `doi-utils-def-bibtex-type' macro.  Since the macro is expanded at compile
+;; time, we need to ensure these defuns and defvars are evaluated at
+;; compile-time.
+(eval-and-compile
+  (defvar doi-utils-json-metadata-extract
+    '((type       (plist-get results :type))
+      (author     (mapconcat (lambda (x)
+                              (message "%s" x)
+                              (if (plist-get x :name)
+                                  (plist-get x :name)
+                                (concat (plist-get x :given) " " (plist-get x :family))))
+                             (plist-get results :author) " and "))
+      (title      (plist-get results :title))
+      (subtitle   (plist-get results :subtitle))
+      (journal    (plist-get results :container-title))
+      (series     (plist-get results :container-title))
+      (publisher  (plist-get results :publisher))
+      (volume     (plist-get results :volume))
+      (issue      (plist-get results :issue))
+      (number     (plist-get results :issue))
+      (year       (or (elt (elt (plist-get (plist-get results :issued) :date-parts) 0) 0)
+                      (elt (elt (plist-get (plist-get results :approved) :date-parts) 0) 0)
+                      ))
+      ;; Some dates don't have a month in them.
+      (month      (let ((date (elt
+                              (plist-get (plist-get results :issued) :date-parts) 0)))
+                   (if (>= (length date) 2)
+                       (elt date 1)
+                     "-")))
+      (pages      (or (plist-get results :page)
+                     (plist-get results :article-number)))
+      (doi        (plist-get results :DOI))
+      (url        (plist-get results :URL))
+      (booktitle  (plist-get results :container-title))
+      (school     (or (plist-get results :school)
+                      (plist-get (plist-get results :institution) :name)))))
+
+  ;; Next, we need to define the different bibtex types. Each type has a bibtex
+  ;; type (for output) and the type as provided in the doi record. Finally, we
+  ;; have to declare the fields we want to output.
+
+  (defvar doi-utils-bibtex-type-generators nil)
+
+  (defun doi-utils-concat-prepare (lst &optional acc)
+    "Minimize the number of args passed to `concat' from LST.
+Given a list LST of strings and other expressions, which are
+intended to be passed to `concat', concat any subsequent strings,
+minimising the number of arguments being passed to `concat'
+without changing the results.  ACC is the list of additional
+expressions."
+    (cond ((null lst) (nreverse acc))
+          ((and (stringp (car lst))
+                (stringp (car acc)))
+           (doi-utils-concat-prepare (cdr lst) (cons (concat (car acc) (car lst))
+                                                     (cdr acc))))
+          (t (doi-utils-concat-prepare (cdr lst) (cons (car lst) acc))))))
+
+(defmacro doi-utils-def-bibtex-type (name matching-types &rest fields)
+  "Define a BibTeX type identified by (symbol) NAME.
+MATCHING-TYPES is a list of strings.  FIELDS are symbols that
+match to retrieval expressions in
+`doi-utils-json-metadata-extract'.  This type will only be used
+when the `:type' parameter in the JSON metadata is contained in
+MATCHING-TYPES."
+  `(push (lambda (type results)
+           (when
+               (or ,@(mapcar
+                      (lambda (match-type)
+                        `(string= type ,match-type)) matching-types))
+             (let ,(mapcar (lambda (field)
+                             (let ((field-expr
+                                    (assoc field doi-utils-json-metadata-extract)))
+                               (if field-expr
+                                   ;; need to convert to string first
+                                   `(,(car field-expr) (format "%s" ,(cadr field-expr)))
+                                 (error "Unknown bibtex field type %s" field))))
+                           fields)
+               (concat
+                ,@(doi-utils-concat-prepare
+                   (-flatten
+                    (list (concat "@" (symbol-name name) "{,\n")
+                          ;; there seems to be some bug with mapcan,
+                          ;; so we fall back to flatten
+                          (mapcar (lambda (field)
+                                    `("  " ,(symbol-name field) " = {" ,field "},\n"))
+                                  fields)
+                          "}\n")))))))
+         doi-utils-bibtex-type-generators))
+
+(doi-utils-def-bibtex-type article ("journal-article" "article-journal" "article")
+                           author title journal year volume number pages doi url)
+
+(doi-utils-def-bibtex-type inproceedings ("proceedings-article" "paper-conference")
+                           author title booktitle year month pages doi url)
+
+(doi-utils-def-bibtex-type book ("book")
+                           author title series publisher year pages doi url)
+
+(doi-utils-def-bibtex-type inbook ("chapter" "book-chapter" "reference-entry")
+                           author title booktitle series publisher year pages doi url)
+(doi-utils-def-bibtex-type phdthesis ("phdthesis" "thesis" "dissertation")
+                  author title school publisher year)
+
+;; this is what preprints in chemrxiv look like for now
+(doi-utils-def-bibtex-type misc ("posted-content")
+                          author title year doi url)
+
+
+
+;; With the code generating the bibtex entry in place, we can glue it to the json retrieval code.
+
+(defun doi-utils-doi-to-bibtex-string (doi)
+  "Return a bibtex entry as a string for the DOI.  Not all types are supported yet."
+  (let* ((results (funcall doi-utils-metadata-function doi))
+         (type (plist-get results :type)))
+    ;; (format "%s" results) ; json-data
+    (or (-some (lambda (g) (funcall g type results)) doi-utils-bibtex-type-generators)
+        (message "%s not supported yet\n%S." type results))))
+
+;; That is just the string for the entry. To be useful, we need a function that
+;; inserts the string into a buffer. This function will insert the string at the
+;; cursor, clean the entry, try to get the pdf.
+
+(defun doi-utils-insert-bibtex-entry-from-doi (doi)
+  "Insert and clean bibtex entry from a DOI."
+  (insert (doi-utils-doi-to-bibtex-string doi))
+  (backward-char)
+  ;; set date added for the record
+  (let ((ts (funcall doi-utils-timestamp-format-function)))
+    (when ts
+      (bibtex-set-field doi-utils-timestamp-field
+                       ts)))
+  (org-ref-clean-bibtex-entry)
+  (save-buffer))
+
+
+;;;###autoload
+(defun doi-utils-add-bibtex-entry-from-doi (doi &optional bibfile)
+  "Add DOI entry to end of a file in the current directory.
+Pick the file ending with .bib or in .  If you have an active region that
+starts like a DOI, that will be the initial prompt.  If no region
+is selected and the first entry of the ‘kill-ring’ starts like a
+DOI, then that is the initial prompt.  Otherwise, you have to type
+or paste in a DOI.
+Argument BIBFILE the bibliography to use."
+  (interactive
+   (list (read-string
+          "DOI: "
+          ;; now set initial input
+          (doi-utils-maybe-doi-from-region-or-current-kill))))
+
+  (unless bibfile
+    (setq bibfile (completing-read "Bibfile: " (org-ref-possible-bibfiles))))
+  ;; Wrap in save-window-excursion to restore your window arrangement after this
+  ;; is done.
+  (save-window-excursion
+    (with-current-buffer
+        (find-file-noselect bibfile)
+      ;; Check if the doi already exists
+      (goto-char (point-min))
+      (if (re-search-forward (concat doi "\\_>") nil t)
+          (message "%s is already in this file" doi)
+        (goto-char (point-max))
+
+       (when (not (looking-back "\n\n" (min 3 (point))))
+         (insert "\n\n"))
+
+        (doi-utils-insert-bibtex-entry-from-doi doi)
+        (save-buffer)))))
+
+(defalias 'doi-add-bibtex-entry 'doi-utils-add-bibtex-entry-from-doi
+  "Alias function for convenience.")
+
+(defun doi-utils-maybe-doi-from-region-or-current-kill ()
+  "Try to get a DOI from the active region or current kill."
+  (let* ((the-active-region (if (region-active-p) ;; nil if no active region
+                                (buffer-substring (region-beginning) (region-end))
+                              nil))
+         (the-current-kill (ignore-errors (current-kill 0 t)))  ;; nil if empty kill ring
+         ;; DOI urls
+         ;; Ex: https://doi.org/10.1109/MALWARE.2014.6999410
+         ;; Ex: https://dx.doi.org/10.1007/978-3-319-60876-1_10
+         (doi-url-prefix-regexp "^https?://\\(dx\\.\\)?doi\\.org/")
+         ;; https://www.crossref.org/blog/dois-and-matching-regular-expressions/
+         (doi-regexp "10\\.[0-9]\\{4,9\\}/[-._;()/:A-Z0-9]+$"))
+    (cond
+     ;; Check if a DOI can be found in the active region
+     ;; DOI raw
+     ;; Ex: 10.1109/MALWARE.2014.6999410
+     ((and (stringp the-active-region)
+           (s-match (concat "^" doi-regexp) the-active-region))
+      the-active-region)
+     ;; DOI url
+     ;; Ex: https://doi.org/10.1109/MALWARE.2014.6999410
+     ((and (stringp the-active-region)
+           (s-match (concat doi-url-prefix-regexp doi-regexp) the-active-region))
+      (replace-regexp-in-string doi-url-prefix-regexp "" the-active-region))
+     ;; DOI url as customized
+     ((and (stringp the-active-region)
+           (s-match (regexp-quote doi-utils-dx-doi-org-url) the-active-region))
+      (replace-regexp-in-string (regexp-quote doi-utils-dx-doi-org-url) "" the-active-region))
+     ;; Check if DOI can be found in the current kill
+     ;; DOI raw
+     ;; Ex: 10.1109/MALWARE.2014.6999410
+     ((and (stringp the-current-kill)
+           (s-match (concat "^" doi-regexp) the-current-kill))
+      the-current-kill)
+     ;; DOI url
+     ;; Ex: https://doi.org/10.1109/MALWARE.2014.6999410
+     ((and (stringp the-current-kill)
+           (s-match (concat doi-url-prefix-regexp doi-regexp) the-current-kill))
+      (replace-regexp-in-string doi-url-prefix-regexp "" the-current-kill))
+     ;; DOI url as customized
+     ((and (stringp the-current-kill)
+           (s-match (regexp-quote doi-utils-dx-doi-org-url) the-current-kill))
+      (replace-regexp-in-string (regexp-quote doi-utils-dx-doi-org-url) "" the-current-kill))
+     ;; otherwise, return nil
+     (t
+      nil))))
+
+;;;###autoload
+(defun doi-utils-doi-to-org-bibtex (doi)
+  "Convert a DOI to an ‘org-bibtex’ form and insert it at point."
+  (interactive "sDOI: ")
+  (with-temp-buffer
+    (insert (doi-utils-doi-to-bibtex-string doi))
+    (bibtex-clean-entry)
+    (kill-region (point-min) (point-max)))
+  (org-bibtex-yank)
+  (org-metaright)
+  (org-metaright))
+
+;;* Updating bibtex entries
+
+;; I wrote this code because it is pretty common for me to copy bibtex entries
+;; from ASAP articles that are incomplete, e.g. no page numbers because it is
+;; not in print yet. I wanted a convenient way to update an entry from its DOI.
+;; Basically, we get the metadata, and update the fields in the entry.
+
+;; There is not bibtex set field function, so I wrote this one.
+
+
+;;;###autoload
+(defun bibtex-set-field (field value &optional nodelim)
+  "Set FIELD to VALUE in bibtex file.  create field if it does not exist.
+Optional argument NODELIM see `bibtex-make-field'."
+  (interactive "sfield: \nsvalue: ")
+  (bibtex-beginning-of-entry)
+  (let ((found))
+    (if (setq found (bibtex-search-forward-field field t))
+        ;; we found a field
+        (progn
+          (goto-char (car (cdr found)))
+          (when value
+            (bibtex-kill-field)
+            (bibtex-make-field field nil nil nodelim)
+            (backward-char)
+            (insert value)))
+      ;; make a new field
+      (bibtex-beginning-of-entry)
+      (forward-line) (beginning-of-line)
+      (bibtex-next-field nil)
+      (forward-char)
+      (bibtex-make-field field nil nil nodelim)
+      (backward-char)
+      (insert value))))
+
+
+(defun plist-get-keys (plist)
+  "Return keys in a PLIST."
+  (-slice plist 0 nil 2))
+
+
+;;;###autoload
+(defun doi-utils-update-bibtex-entry-from-doi (doi)
+  "Update fields in a bibtex entry from the DOI.
+Every field will be updated, so previous change will be lost."
+  (interactive (list
+                (or (replace-regexp-in-string
+                     "https?://\\(dx.\\)?doi.org/" ""
+                     (bibtex-autokey-get-field "doi"))
+                    (read-string "DOI: "))))
+  (let* ((results (funcall doi-utils-metadata-function doi))
+         (type (plist-get results :type))
+         (author (mapconcat
+                  (lambda (x)
+                   ;; There are two possible ways an author is named. The most
+                   ;; common is with :given and :family, but sometimes there is
+                   ;; :name instead.
+                   (if (plist-get x :name)
+                       (plist-get x :name)
+                     (concat (plist-get x :given)
+                             " " (plist-get x :family))))
+                  (plist-get results :author) " and "))
+         (title (plist-get results :title))
+         (journal (plist-get results :container-title))
+         (year (format "%s"
+                       (elt
+                        (elt
+                         (plist-get
+                          (plist-get results :issued) :date-parts) 0) 0)))
+         (volume (plist-get results :volume))
+         (number (or (plist-get results :issue) ""))
+         (pages (or (plist-get results :page) ""))
+         (url (or (plist-get results :URL) ""))
+         (doi (plist-get results :DOI))
+         mapping)
+
+    ;; map the json fields to bibtex fields. The code each field is mapped to is
+    ;; evaluated.
+    (setq mapping '((:author . (bibtex-set-field "author" author))
+                    (:title . (bibtex-set-field "title" title))
+                    (:container-title . (bibtex-set-field "journal" journal))
+                    (:issued . (bibtex-set-field "year" year))
+                    (:volume . (bibtex-set-field "volume" volume))
+                    (:issue . (bibtex-set-field "number" number))
+                    (:page . (bibtex-set-field "pages" pages))
+                    (:DOI . (bibtex-set-field "doi" doi))
+                    (:URL . (bibtex-set-field "url" url))))
+
+    ;; now we have code to run for each entry. we map over them and evaluate the code
+    (mapc
+     (lambda (key)
+       (eval (cdr (assoc key mapping))))
+     (plist-get-keys results)))
+
+  (org-ref-clean-bibtex-entry))
+
+
+;; A downside to updating an entry is it overwrites what you have already fixed.
+;; So, we next develop a function to update the field at point.
+
+
+;;;###autoload
+(defun doi-utils-update-field ()
+  "Update the field at point in the bibtex entry.
+Data is retrieved from the doi in the entry."
+  (interactive)
+  (let* ((doi (bibtex-autokey-get-field "doi"))
+         (results (funcall doi-utils-metadata-function doi))
+         (field (car (bibtex-find-text-internal nil nil ","))))
+    (cond
+     ((string= field "volume")
+      (bibtex-set-field field (plist-get results :volume)))
+     ((string= field "number")
+      (bibtex-set-field field (plist-get results :issue)))
+     ((string= field "pages")
+      (bibtex-set-field field (or (plist-get results :page)
+                                  (plist-get results :article-number))))
+     ((string= field "year")
+      (bibtex-set-field field (plist-get results :year)))
+     (t
+      (message "%s not supported yet." field)))))
+
+
+
+;;* DOI functions for WOS
+
+;; I came across this API http://wokinfo.com/media/pdf/OpenURL-guide.pdf to make
+;; links to the things I am interested in here. Based on that document, here are
+;; three links based on a doi:10.1021/jp047349j that take you to different Web
+;; Of Science (WOS) pages.
+
+
+;; 1. go to article in WOS: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/10.1021/jp047349j
+;; 2. citing articles: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F10.1021/jp047349j&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.citing=yes
+;; 3. related articles: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F10.1021/jp047349j&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.related=yes
+
+;; These are pretty easy to construct, so we can write functions that will
+;; create them and open the url in our browser. There are some other options
+;; that could be considered, but since we usually have a doi, it seems like the
+;; best way to go for creating the links. Here are the functions.
+
+;;;###autoload
+(defun doi-utils-wos (doi)
+  "Open Web of Science entry for DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/%s" doi)))
+
+;;;###autoload
+(defun doi-utils-wos-citing (doi)
+  "Open Web of Science citing articles entry for DOI.
+May be empty if none are found."
+  (interactive "sDOI: ")
+  (browse-url
+   (concat
+    "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F"
+    doi
+    "&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.citing=yes")))
+
+;;;###autoload
+(defun doi-utils-wos-related (doi)
+  "Open Web of Science related articles page for DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (concat "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F"
+           doi
+           "&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.related=yes")))
+
+
+;;* DOI functions for ADS
+
+;;;###autoload
+(defun doi-utils-ads (doi)
+  "Open ADS entry for DOI"
+  (interactive "sDOI: ")
+  (browse-url
+   (concat
+    "https://ui.adsabs.harvard.edu/abs/" "%22" doi "%22")))
+
+
+;;* A new doi link for org-mode
+;; The idea is to add a menu to the doi link, so rather than just clicking to open the article, you can do other things.
+;; 1. open doi
+;; 2. open in wos
+;; 3. open citing articles
+;; 4. open related articles
+;; 5. open bibtex entry
+;; 6. get bibtex entry
+
+
+;;;###autoload
+(defun doi-utils-open (doi)
+  "Open DOI in browser."
+  (interactive "sDOI: ")
+  (browse-url (concat doi-utils-dx-doi-org-url doi)))
+
+
+;;;###autoload
+(defun doi-utils-open-bibtex (doi)
+  "Search through variable `bibtex-completion-bibliography' for DOI."
+  (interactive "sDOI: ")
+  (cl-loop for f in (if (listp bibtex-completion-bibliography)
+                       bibtex-completion-bibliography
+                     (list bibtex-completion-bibliography))
+          when (progn (find-file f)
+                      (when (search-forward doi (point-max) t)
+                        (bibtex-beginning-of-entry)))
+          return f))
+
+
+;;;###autoload
+(defun doi-utils-crossref (doi)
+  "Search DOI in CrossRef."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://search.crossref.org/?q=%s" doi)))
+
+
+;;;###autoload
+(defun doi-utils-google-scholar (doi)
+  "Google scholar the DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://scholar.google.com/scholar?q=%s" doi)))
+
+
+;;;###autoload
+(defun doi-utils-pubmed (doi)
+  "Search Pubmed for the DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s"
+    (url-hexify-string doi))))
+
+(declare-function org-element-property "org-element")
+
+(defhydra doi-link-follow (:color blue :hint nil)
+  "DOI actions:
+"
+  ("o" (doi-utils-open (org-element-property :path (org-element-context))) "open")
+  ("w" (doi-utils-wos (org-element-property :path (org-element-context))) "wos")
+  ("c" (doi-utils-wos-citing (org-element-property :path (org-element-context))) "wos citing articles")
+  ("r" (doi-utils-wos-related (org-element-property :path (org-element-context))) "wos related articles" )
+  ("a" (doi-utils-ads (org-element-property :path (org-element-context))) "ads")
+  ("s" (doi-utils-google-scholar (org-element-property :path (org-element-context))) "Google Scholar")
+  ("f" (doi-utils-crossref (org-element-property :path (org-element-context))) "CrossRef")
+  ("p" (doi-utils-pubmed (org-element-property :path (org-element-context))) "Pubmed")
+  ("b" (doi-utils-open-bibtex (org-element-property :path (org-element-context))) "open in bibtex")
+  ("g" (doi-utils-add-bibtex-entry-from-doi (org-element-property :path (org-element-context))) "get bibtex entry"))
+
+
+(org-link-set-parameters "doi"
+                        :follow (lambda (_) (doi-link-follow/body))
+                        :export (lambda (doi desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"%s%s\">%s</a>"
+                                            doi-utils-dx-doi-org-url
+                                            doi
+                                            (or desc (concat "doi:" doi))))
+                                   ((eq format 'latex)
+                                    (format "\\href{%s%s}{%s}"
+                                            doi-utils-dx-doi-org-url
+                                            doi
+                                            (or desc (concat "doi:" doi)))))))
+
+;;* Getting a doi for a bibtex entry missing one
+
+;; Some bibtex entries do not have a DOI, maybe because they were entered by
+;; hand, or copied from a source that did not have it available. Here we develop
+;; some functions to help you find the DOI using Crossref.
+
+;; Here is our example bibtex entry.
+;; #+BEGIN_SRC bibtex
+;; @article{deml-2014-oxide,
+;;   author =   {Ann M. Deml and Vladan Stevanovi{\'c} and
+;;                   Christopher L. Muhich and Charles B. Musgrave and
+;;                   Ryan O'Hayre},
+;;   title =    {Oxide Enthalpy of Formation and Band Gap Energy As
+;;                   Accurate Descriptors of Oxygen Vacancy Formation
+;;                   Energetics},
+;;   journal =  {Energy Environ. Sci.},
+;;   volume =   7,
+;;   number =   6,
+;;   pages =    1996,
+;;   year =     2014,
+;;   doi =              {10.1039/c3ee43874k,
+;;   url =              {http://dx.doi.org/10.1039/c3ee43874k}},
+
+;; }
+
+
+;; The idea is to query Crossref in a way that is likely to give us a hit
+;; relevant to the entry.
+
+;; According to http://search.crossref.org/help/api we can send a query with a
+;; free form citation that may give us something back. We do this to get a list
+;; of candidates, which could be used to get the doi.
+
+(declare-function org-ref-bib-citation "org-ref-bibtex")
+;;;###autoload
+(defun doi-utils-crossref-citation-query ()
+  "Query Crossref with the title of the bibtex entry at point.
+Get a list of possible matches. Choose one with completion."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (let* ((entry (bibtex-parse-entry))
+        (raw-json-string)
+         (json-string)
+         (json-data)
+         (doi (bibtex-autokey-get-field "doi")))
+    (unless (string= "" doi)
+      (error "Entry already has a doi field"))
+
+    (with-current-buffer
+        (url-retrieve-synchronously
+         (concat
+          "http://search.crossref.org/dois?q="
+          (url-hexify-string (org-ref-bib-citation))))
+      (save-excursion
+       (goto-char (point-min))
+       (while (re-search-forward "<i>\\|</i>" nil t)
+         (replace-match ""))
+       (goto-char (point-min))
+       (while (re-search-forward "&amp;" nil t)
+         (replace-match "&"))
+       (goto-char (point-min))
+       (while (re-search-forward "&quot;" nil t)
+         (replace-match "\\\"" nil t)))
+      (setq raw-json-string (buffer-substring url-http-end-of-headers (point-max)))
+      ;; decode json string
+      (setq json-string (decode-coding-string (encode-coding-string raw-json-string 'utf-8) 'utf-8))
+      (setq json-data (json-read-from-string json-string)))
+
+    (let* ((name (format "Crossref hits for %s" (org-ref-bib-citation)))
+           (candidates (mapcar (lambda (x)
+                                 (cons
+                                  (concat
+                                   (cdr (assoc 'fullCitation x)))
+                                  (cdr (assoc 'doi x))))
+                               json-data))
+
+          (doi (cdr (assoc (completing-read "DOI: " candidates) candidates))))
+      (bibtex-make-field "doi" t)
+      (backward-char)
+      ;; crossref returns doi url, but I prefer only a doi for the doi field
+      (insert (replace-regexp-in-string "^https?://\\(dx.\\)?doi.org/" "" doi))
+      (when (string= "" (bibtex-autokey-get-field "url"))
+        (bibtex-make-field "url" t)
+        (backward-char)
+        (insert doi)))))
+
+
+
+;;* Debugging a DOI
+
+;; I wrote this function to help debug a DOI. This function generates an
+;; org-buffer with the doi, gets the json metadata, shows the bibtex entry, and
+;; the pdf link for it.
+(defun doi-utils-get-json (doi)
+  "Return json data as a string for DOI."
+  (let ((url-request-method "GET")
+        (url-mime-accept-string "application/citeproc+json")
+        (json-data))
+    (with-current-buffer
+        (url-retrieve-synchronously
+         (concat doi-utils-dx-doi-org-url doi))
+      (setq json-data (buffer-substring url-http-end-of-headers (point-max)))
+      (if (string-match "Resource not found" json-data)
+          (progn
+            (browse-url (concat doi-utils-dx-doi-org-url doi))
+            (error "Resource not found.  Opening website"))
+       json-data))))
+
+
+;;;###autoload
+(defun doi-utils-debug (doi)
+  "Generate an org-buffer showing data about DOI."
+  (interactive "sDOI: ")
+  (switch-to-buffer "*debug-doi*")
+  (erase-buffer)
+  (org-mode)
+  (insert (concat "doi:" doi) "\n\n")
+  (insert "* JSON
+"
+         (let ((url-request-method "GET")
+               (url-mime-accept-string "application/citeproc+json"))
+           (pp
+            (json-read-from-string (with-current-buffer
+                                       (url-retrieve-synchronously
+                                        (concat doi-utils-dx-doi-org-url doi))
+                                     (buffer-substring url-http-end-of-headers (point-max))))))
+         "\n\n")
+  (goto-char (point-min)))
+
+;;* Adding a bibtex entry from a crossref query
+
+;; The idea here is to perform a query on Crossref, get a completion buffer of
+;; candidates, and select the entry(ies) you want to add to your bibtex file.
+;; You can select a region, e.g. a free form citation, or set of words, or you
+;; can type the query in by hand.
+
+;;;###autoload
+(defun doi-utils-add-entry-from-crossref-query (query bibtex-file)
+  "Search Crossref with QUERY and use completion to select an entry to add to BIBTEX-FILE."
+  (interactive (list
+                (read-string
+                 "Query: "
+                 ;; now set initial input
+                 (cond
+                  ;; If region is active assume we want it
+                  ((region-active-p)
+                   (replace-regexp-in-string
+                    "\n" " "
+                    (buffer-substring (region-beginning) (region-end))))
+                  ;; type or paste it in
+                  (t
+                   nil)))
+                (completing-read
+                 "Bibfile: "
+                 (append (f-entries "." (lambda (f) (f-ext? f "bib")))
+                         bibtex-completion-bibliography))))
+  (let* ((raw-json-string)
+        (json-string)
+        (json-data)
+        (doi))
+
+    (with-current-buffer
+       (url-retrieve-synchronously
+        (concat
+         "http://search.crossref.org/dois?q="
+         (url-hexify-string query)))
+      ;; replace html entities
+      (save-excursion
+       (goto-char (point-min))
+       (while (re-search-forward "<i>\\|</i>" nil t)
+         (replace-match ""))
+       (goto-char (point-min))
+       (while (re-search-forward "&amp;" nil t)
+         (replace-match "&"))
+       (goto-char (point-min))
+       (while (re-search-forward "&quot;" nil t)
+         (replace-match "\\\"" nil t)))
+      (setq raw-json-string (buffer-substring url-http-end-of-headers (point-max)))
+      ;; decode json string
+      (setq json-string (decode-coding-string (encode-coding-string raw-json-string 'utf-8) 'utf-8))
+      (setq json-data (json-read-from-string json-string)))
+
+    (let* ((name (format "Crossref hits for %s"
+                        ;; remove carriage returns. They can make completion confusing.
+                        (replace-regexp-in-string "\n" " " query)))
+          (candidates (mapcar (lambda (x)
+                                (cons
+                                 (concat
+                                  (cdr (assoc 'fullCitation x)))
+                                 (cdr (assoc 'doi x))))
+                              json-data))
+          (doi (cdr (assoc (completing-read "Choice: " candidates) candidates))))
+      (with-current-buffer (find-file-noselect bibtex-file)
+       (doi-utils-add-bibtex-entry-from-doi
+        (replace-regexp-in-string
+         "^https?://\\(dx.\\)?doi.org/" "" doi)
+        bibtex-file)
+       (save-buffer)))))
+
+(defalias 'crossref-add-bibtex-entry 'doi-utils-add-entry-from-crossref-query
+  "Alias function for convenience.")
+
+;; * Convenience
+
+(defun doi-utils-toggle-pdf-download ()
+  "Toggle the setting of `doi-utils-download-pdf'.
+I find this useful when downloading the pdfs slows down adding a
+lot of references; then you just toggle it off."
+  (interactive)
+  (message "Setting doi-utils-download-pdf to %s"
+          (setq doi-utils-download-pdf (not doi-utils-download-pdf))))
+
+;;* The end
+(provide 'doi-utils)
+;;; doi-utils.el ends here
diff --git a/elpa/org-ref-20230507.1420/nist-webbook.el b/elpa/org-ref-20230507.1420/nist-webbook.el
new file mode 100644 (file)
index 0000000..57764dd
--- /dev/null
@@ -0,0 +1,42 @@
+;;; nist-webbook.el --- Integration of Emacs with NIST Webbook
+;; Integration of Emacs with NIST webbook
+
+;;; Commentary:
+;; nist-webbook-name :: search for a chemical name
+;; nist-webbook-formula :: search by chemical formula
+
+;;; Code:
+
+(require 'org)
+(require 'org-ref-utils)
+
+;;;###autoload
+(defun nist-webbook-formula (formula)
+  "Search NIST webbook for FORMULA."
+  (interactive "sFormula: ")
+  (browse-url
+   (concat
+    "http://webbook.nist.gov/cgi/cbook.cgi?Formula="
+    formula
+    "&NoIon=on&Units=SI")))
+
+;;;###autoload
+(defun nist-webbook-name (name)
+  "Search NIST webbook for NAME."
+  (interactive "sChemical Name: ")
+  (browse-url
+   (concat "http://webbook.nist.gov/cgi/cbook.cgi?Name="
+           (url-hexify-string name)
+           "&Units=SI")))
+
+(org-link-set-parameters "nist-wb-name"
+                        :follow (lambda (name)
+                                  (nist-webbook-name name)))
+
+(org-link-set-parameters "nist-wb-formula"
+                        :follow (lambda (formula)
+                                  (nist-webbook-formula formula)))
+
+(provide 'nist-webbook)
+
+;;; nist-webbook.el ends here
diff --git a/elpa/org-ref-20230507.1420/openalex.el b/elpa/org-ref-20230507.1420/openalex.el
new file mode 100644 (file)
index 0000000..256e58c
--- /dev/null
@@ -0,0 +1,459 @@
+;;; openalex.el --- Org-ref interface to OpenAlex
+
+;;; Commentary:
+;; This is an elisp interface to OpenAlex (https://docs.openalex.org/) for org-ref.
+;;
+;; This provides functionality for the Work and Author API
+;;
+;; See
+;; https://docs.openalex.org/how-to-use-the-api/rate-limits-and-authentication#the-polite-pool
+;; for why we add email to the request.
+
+(require 'dash)
+(require 'request)
+
+;;; Code:
+
+(defun oa--response-parser ()
+  "Parse the response from json to elisp."
+  (let ((json-array-type 'list)
+       (json-object-type 'plist)
+       (json-key-type 'keyword)
+       (json-false nil)
+       (json-encoding-pretty-print nil))
+    (json-read)))
+
+
+;; * Work object
+
+(defun oa--work (entity-id &optional filter)
+  "Retrieve json data for a Work object for ENTITY-ID.
+ENTITY-ID is an OpenAlex ID, DOI, Pubmed id,etc.
+
+ENTITY-ID may also be a list of ids with a filter.
+
+If FILTER is non-nil it should be a string like \"filter=openalex:\"
+
+https://docs.openalex.org/api-entities/works"
+
+  (let* ((url (concat  "https://api.openalex.org/works"
+                      (if filter
+                          (concat "?" filter entity-id)
+                        (concat "/" entity-id))
+                      (if user-mail-address
+                          (concat "?mailto=" user-mail-address)
+                        "")))
+        (req (request url :sync t :parser 'oa--response-parser))
+        (data (request-response-data req)))
+    ;; this is for convenience to inspect data in a browser.
+    (plist-put data :oa-url url)
+    data))
+
+
+;; * Viewing works
+;;
+;; This section provides a replacer and helper function to format org-entries
+;; from the results returned in OpenAlex.
+
+(defun oa--replacer (query object)
+  "Replacer function for `s-format'.
+QUERY is a string that is either a sexp for a function to
+evaluate or a dot notation path to data in OBJECT. If QUERY is a
+sexp, it is read and evaluated. Otherwise, the path is split, and
+looked up sequentially in object.
+
+OBJECT is a plist, usually from a Work request."
+  (if (s-starts-with? "(" query)
+      ;; this is a function
+      (eval (read query))
+    ;; just get data
+    (let ((fields (s-split "\\." query))
+         result)
+      (while fields
+       (setq object (plist-get object (intern-soft (concat ":" (pop fields))))))
+      (or (string-replace "\\n" "" (format "%s" object)) "Not found"))))
+
+
+;; ** help functions for complex data
+;;
+;; Some things like authors need to be constructed, and cannot just be looked
+;; up. In other cases, I want logic, e.g. if data is there provide something,
+;; and if not return an empty string. These functions do that work.
+(defun oa--authors (wrk)
+  "Return an author string for WRK.
+The string is a comma-separated list of links to author pages in OpenAlex."
+  (s-join ", " (cl-loop for author in (plist-get wrk :authorships)
+                       collect
+                       (format "[[elisp:(oa-author \"%s\")][%s]]"
+                               (plist-get
+                                (plist-get author :author)
+                                :id)
+                               (plist-get
+                                (plist-get author :author)
+                                :display_name)))))
+
+
+;; I want some links if they can be made so the buffer is interactive. It might
+;; be nice to integrate M-, navigation.
+(defun oa--elisp-get-bibtex (wrk)
+  "Return a elisp link to get a bibtex entry for WRK if there is a doi."
+  (if-let ((doi (plist-get wrk :doi)))
+      (format "[[elisp:(doi-add-bibtex-entry \"%s\")][Get bibtex entry]]" doi)
+    ""))
+
+
+(defun oa--elisp-get-oa-related (wrk)
+  "Return a elisp link to get related works for WRK."
+  (format "[[elisp:(progn (xref--push-markers) (oa--related-works \"%s\"))][Get related work (%s)]]"
+         (plist-get wrk :id)
+         (length (plist-get wrk :related_works))))
+
+
+(defun oa--elisp-get-oa-refs (wrk)
+  "Return a elisp link to get references for WRK."
+  (format "[[elisp:(progn (xref--push-markers) (oa--referenced-works \"%s\"))][Get references (%s)]]"
+         (plist-get wrk :id)
+         (length  (plist-get wrk :referenced_works))))
+
+
+(defun oa--elisp-get-oa-cited-by (wrk)
+  "Return a elisp link to get works that cite WRK."
+  (format "[[elisp:(progn (xref--push-markers) (oa--cited-by-works \"%s\"))][Get cited by (%s)]]"
+         (plist-get wrk :id)
+         (plist-get wrk :cited_by_count)))
+
+
+(defun oa--works-entries (works)
+  "Return a list of org-formatted entries in WORKS.
+WORKS is a list of results from OpenAlex."
+  (cl-loop for wrk in (plist-get works :results)
+          collect
+          (s-format "** ${title}
+:PROPERTIES:
+:HOST: ${host_venue.display_name}
+:YEAR: ${publication_year}
+:CITED_BY_COUNT: ${cited_by_count}
+:AUTHOR: ${(oa--authors wrk)}
+:DOI: ${doi}
+:OPENALEX: ${id}
+:END:
+
+
+${(oa--elisp-get-bibtex wrk)}
+
+- ${(oa--elisp-get-oa-refs wrk)}
+- ${(oa--elisp-get-oa-related wrk)}
+- ${(oa--elisp-get-oa-cited-by wrk)}
+
+"
+                    'oa--replacer wrk)))
+
+
+(defun oa--works-buffer (bufname header entries)
+  "Create an org-buffer with BUFNAME representing the results in WORKS.
+HEADER is the first thing in the buffer
+WORKS is usually a list of results from OpenAlex.
+Argument ENTRIES A list of strings for each org entry."
+  (let ((buf (get-buffer-create bufname)))
+    
+    (with-current-buffer buf
+      (erase-buffer)
+      (insert header)
+      (insert "#+COLUMNS: %25ITEM %YEAR %CITED_BY_COUNT
+elisp:org-columns    elisp:org-columns-quit
+
+
+#+caption: Sort
+| year     | [[elisp:(oa-buffer-sort-year t)][old first]] | [[elisp:(oa-buffer-sort-year)][new first]] |
+| cited by | [[elisp:(oa-buffer-sort-cited-by-count t)][low first]] | [[elisp:(oa-buffer-sort-cited-by-count)][high first]] |
+
+")
+      (insert (s-join "\n" entries))
+      (org-mode)
+      (goto-char (point-min))
+      (org-next-visible-heading 1))
+    ;; (display-buffer-in-side-window buf '((side . right)))
+    (pop-to-buffer buf)))
+
+
+;; There is something funny about pages here, maybe 25 results per page?
+;; https://docs.openalex.org/how-to-use-the-api/get-lists-of-entities/paging I
+;; am not sure how to do pages in this approach, so I am just getting these 25
+;; at a time.
+(defun oa--related-works (entity-id)
+  "Show the Related works buffer for ENTITY-ID."
+  (let* ((wrk (oa--work entity-id))
+        (related-work (plist-get wrk :related_works))
+        split
+        entries)
+    (while related-work
+      (setq split (-split-at 25 related-work)
+           related-work (nth 1 split))
+      
+      ;; split is what we process now
+      (setq entries (append entries
+                           (oa--works-entries
+                            (oa--work (s-join "|" (nth 0 split))
+                                      "filter=openalex:")))))
+    
+    (oa--works-buffer
+     "*OpenAlex - Related works*"
+     (format "* OpenAlex - Related works for %s ([[%s][json]])
+%s\n\n"
+            entity-id
+            (plist-get wrk :oa-url)
+            (s-format ":PROPERTIES:
+:TITLE: ${title}
+:HOST: ${host_venue.display_name}
+:AUTHOR: ${(oa--authors wrk)}
+:DOI: ${doi}
+:YEAR: ${publication_year}
+:OPENALEX: ${id}
+:END:" 'oa--replacer wrk))
+     entries)))
+
+
+(defun oa--referenced-works (entity-id)
+  "Show the Referenced work for ENTITY-ID."
+  (let* ((wrk (oa--work entity-id))
+        (referenced-work (plist-get wrk :referenced_works))
+        split
+        (entries '()))
+    (while referenced-work
+      (setq split (-split-at 25 referenced-work)
+           referenced-work (nth 1 split))
+      ;; split is what we process now
+      (setq entries (append entries
+                           (oa--works-entries
+                            (oa--work (s-join "|" (nth 0 split))
+                                      "filter=openalex:")))))
+    (oa--works-buffer
+     "*OpenAlex - References*"
+     (format "* OpenAlex - References from %s ([[%s][json]])
+%s\n\n"
+            entity-id
+            (plist-get wrk :oa-url)
+            (s-format ":PROPERTIES:
+:TITLE: ${title}
+:HOST: ${host_venue.display_name}
+:AUTHOR: ${(oa--authors wrk)}
+:DOI: ${doi}
+:YEAR: ${publication_year}
+:OPENALEX: ${id}
+:END:" 'oa--replacer wrk))
+     entries)))
+
+
+;; This function is different than the previous two. First we follow a URL
+;; provided by the data, and second, here we do follow pages.
+(defun oa--cited-by-works (entity-id)
+  "Show the Cited by buffer for ENTITY-ID."
+  (let* ((wrk (oa--work entity-id))
+        (url (plist-get wrk :cited_by_api_url))
+        (cited-by-works (request-response-data
+                         (request url
+                           :sync t
+                           :parser 'oa--response-parser)))
+        (count (plist-get (plist-get cited-by-works :meta) :count))
+        (per-page (plist-get (plist-get cited-by-works :meta) :per_page))
+        (entries '())
+        (page 2))
+    ;; get first page
+    (setq entries (oa--works-entries cited-by-works))
+    (while (> count (* per-page (- page 1)))
+      (setq cited-by-works (request-response-data
+                           (request (format "%s&page=%s" url page)
+                             :sync t
+                             :parser 'oa--response-parser)))
+      (setq entries (append entries (oa--works-entries cited-by-works)))
+      (cl-incf page))
+    
+    (oa--works-buffer
+     "*OpenAlex - Cited by*"
+     (format "* OpenAlex - %s Cited by ([[%s][json]])
+%s"
+            entity-id
+            url
+            (s-format ":PROPERTIES:
+:TITLE: ${title}
+:HOST: ${host_venue.display_name}
+:AUTHOR: ${(oa--authors wrk)}
+:DOI: ${doi}
+:YEAR: ${publication_year}
+:OPENALEX: ${id}
+:END:\n\n" 'oa--replacer wrk))
+     entries)))
+
+
+;; ** buffer utilities for sorting entries
+
+(defun oa-buffer-sort-year (&optional ascending)
+  "Sort org headings by year in descending order (new to old).
+With prefix arg ASCENDING, sort in ascending order (old to new)"
+  (interactive "P")
+  (if ascending
+      (org-sort-entries nil ?f
+                       (lambda () (string-to-number (or (org-entry-get (point) "YEAR") "0")))
+                       (lambda (y1 y2)
+                         (< y1 y2)))
+    (org-sort-entries nil ?f
+                     (lambda () (string-to-number (or (org-entry-get (point) "YEAR") "0")))
+                     (lambda (y1 y2)
+                       (> y1 y2)))))
+
+
+(defun oa-buffer-sort-cited-by-count (&optional ascending)
+  "Sort orgheadings by cited by count in descending order high to low.
+With prefix arg ASCENDING sort from low to high."
+  (interactive "P")
+  (if ascending
+      (org-sort-entries nil ?f
+                       (lambda ()
+                         (string-to-number
+                          (or (org-entry-get (point) "CITED_BY_COUNT")
+                              "0")))
+                       #'<)
+    (org-sort-entries nil ?f
+                     (lambda ()
+                       (string-to-number
+                        (or
+                         (org-entry-get (point) "CITED_BY_COUNT")
+                         "0")))
+                     #'>)))
+
+
+;; * Interactive versions for org-ref citations
+
+(defun oa-related-works ()
+  "Open the side window for Related works on cite at point."
+  (interactive)
+  (oa--related-works (concat "doi:" (org-ref-get-doi-at-point))))
+
+
+(defun oa-referenced-works ()
+  "Open the side window for References from the cite at point."
+  (interactive)
+  (oa--referenced-works (concat "doi:" (org-ref-get-doi-at-point))))
+
+
+(defun oa-cited-by-works ()
+  "Open the side window for Citing works for the cite at point."
+  (interactive)
+  (oa--cited-by-works (concat "doi:" (org-ref-get-doi-at-point))))
+
+
+(defhydra+ org-ref-citation-hydra () ("ar" oa-related-works "Related documents" :column "OpenAlex"))
+(defhydra+ org-ref-citation-hydra () ("ac" oa-cited-by-works "Cited by documents" :column "OpenAlex"))
+(defhydra+ org-ref-citation-hydra () ("af" oa-referenced-works "References from" :column "OpenAlex"))
+
+
+;; * utilities
+
+(defun oa-kill-buffers ()
+  "Kill OpenAlex buffers."
+  (interactive)
+  (cl-loop for buf in (buffer-list)
+          do
+          (when (s-starts-with? "*OpenAlex" (buffer-name buf))
+            (kill-buffer buf))))
+
+;; * Author object
+
+(defun oa--author (entity-id &optional filter)
+  "Get an Author object for entity-id"
+  (let* ((url (concat  "https://api.openalex.org/authors"
+                      (if filter
+                          (concat "?" filter entity-id)
+                        (concat "/" entity-id))
+                      (if user-mail-address
+                          (concat "?mailto=" user-mail-address)
+                        "")))
+        (req (request url :sync t :parser 'oa--response-parser))
+        (data (request-response-data req))) 
+    ;; this is for convenience to inspect data in a browser.
+    (plist-put data :oa-url url)
+    data))
+
+
+(defun oa-author-entries (works-data url)
+  "Get entries from WORKS-DATA."
+  (let* ((meta (plist-get works-data :meta)) 
+        (per-page (plist-get meta :per_page))
+        (count (plist-get meta :count))
+        (pages (/ count per-page))
+        (entries '())
+        purl)
+    ;; if there is a remainder we need to get the rest
+    (when (> (mod count per-page) 0) (cl-incf pages))
+    
+    ;; Now we have to loop through the pages
+    (cl-loop for i from 1 to pages
+            do
+            (setq purl (concat url (format "&page=%s" i))
+                  works-data (request-response-data
+                              (request purl
+                                :sync t
+                                :parser 'oa--response-parser))
+                  entries (append entries
+                                  (cl-loop for result in (plist-get works-data :results)
+                                           collect
+                                           (s-format "** ${title}
+:PROPERTIES:
+:ID: ${id}
+:DOI: ${ids.doi}
+:YEAR: ${publication_year}
+:HOST_VENUE: ${host_venue.display_name}
+:AUTHORS: ${(oa--authors result)}
+:CITED_BY_COUNT: ${cited_by_count}
+:END:
+
+${(oa--elisp-get-bibtex result)}
+
+- ${(oa--elisp-get-oa-refs result)}
+- ${(oa--elisp-get-oa-related result)}
+- ${(oa--elisp-get-oa-cited-by result)}
+
+    " 'oa--replacer result)))))
+    entries))
+
+
+(defun oa-author (entity-id)
+  "View Author for ENTITY-ID in an org-buffer."
+  (let* ((buf (get-buffer-create "*OpenAlex - Author*"))
+        (data (oa--author entity-id))
+        (works-count (plist-get data :works_count))
+        (works-url (plist-get data :works_api_url))
+        (works-data (request-response-data
+                     (request works-url
+                       :sync t
+                       :parser 'oa--response-parser))))
+    (with-current-buffer buf
+      (erase-buffer)
+      (insert (s-format "* ${display_name} ([[${oa-url}][json]])
+:PROPERTIES:
+:ORCID: ${orcid}
+:SCOPUS: ${ids.scopus}
+:WORKS_COUNT: ${works_count}
+:CITED_BY_COUNT: ${cited_by_count}
+:INSTITUTION: ${last_known_institution.display_name}, ${last_known_institution.country_code}
+:END:
+
+#+COLUMNS: %25ITEM %YEAR %CITED_BY_COUNT
+elisp:org-columns    elisp:org-columns-quit
+
+#+caption: Sort
+| year     | [[elisp:(oa-buffer-sort-year t)][old first]] | [[elisp:(oa-buffer-sort-year)][new first]] |
+| cited by | [[elisp:(oa-buffer-sort-cited-by-count t)][low first]] | [[elisp:(oa-buffer-sort-cited-by-count)][high first]] |
+
+"
+                       'oa--replacer data))
+      (insert (s-join "\n" (oa-author-entries works-data works-url)))
+      (org-mode)
+      (goto-char (point-min))
+      (org-next-visible-heading 1))
+    (pop-to-buffer buf)))
+
+
+(provide 'openalex)
+
+;;; openalex.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-arxiv.el b/elpa/org-ref-20230507.1420/org-ref-arxiv.el
new file mode 100644 (file)
index 0000000..31572c5
--- /dev/null
@@ -0,0 +1,303 @@
+;;; org-ref-arxiv.el --- arxiv utilities for org-mode        -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; this library creates a new org-link for Arxiv (http://arxiv.org/) entries,
+;; and provides functions to retrieve bibtex entries from an Arxiv number.
+;;
+;; An Arxiv number might look like: cond-mat/0410285 or 1503.01742
+
+;;; Code:
+(require 'bibtex)
+(require 'dash)
+(require 'f)
+(require 'org)
+(require 's)
+(require 'org-ref-utils)
+(require 'parsebib)
+
+(require 'xml)
+
+;; This is a local variable defined in `url-http'.  We need it to avoid
+;; byte-compiler errors.
+(defvar url-http-end-of-headers)
+
+
+(declare-function parsebib-find-bibtex-dialect "parsebib")
+(declare-function org-ref-clean-bibtex-entry "org-ref-core")
+;; this is a C function
+(declare-function libxml-parse-xml-region "xml")
+
+;;* The org-mode link
+;; this just makes a clickable link that opens the entry.
+;; example: arxiv:cond-mat/0410285
+(org-link-set-parameters "arxiv"
+                        :follow (lambda (link-string)
+                                  (browse-url (format "http://arxiv.org/abs/%s" link-string)))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format  "<a href=\"http://arxiv.org/abs/%s\">arxiv:%s</a>"
+                                             keyword  (or desc keyword)))
+                                   ((eq format 'latex)
+                                    ;; write out the latex command
+                                    (format "\\url{http://arxiv.org/abs/%s}{%s}" keyword (or desc keyword))))))
+
+;;* Getting a bibtex entry for an arXiv article using remote service:
+;; For an arxiv article, there is a link to a NASA ADS page like this:
+;; http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:1503.01742
+;; On that page, there is a link to a bibtex entry:
+;; http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=2015arXiv150301742H&data_type=BIBTEX&db_key=PRE&nocookieset=1
+;;
+;; It looks like you need to get a Bibliographic code from the arxiv number to
+;; then get the bibtex entry.
+
+(defun arxiv-get-bibliographic-code (arxiv-number)
+  "Get Bibliographic code for ARXIV-NUMBER."
+  (with-current-buffer
+      (url-retrieve-synchronously
+       (concat
+        "http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:"
+        arxiv-number))
+    (search-forward-regexp "<link rel=\"canonical\" href=\"http://ui.adsabs.harvard.edu/abs/\\(.*\\)/abstract\"/>")
+    (match-string 1)))
+
+
+(defun arxiv-get-bibtex-entry (arxiv-bibliographic-code)
+  "Get bibtex entry for ARXIV-BIBLIOGRAPHIC-CODE."
+  (with-current-buffer
+      (url-retrieve-synchronously (format "https://ui.adsabs.harvard.edu/abs/%s/exportcitation" arxiv-bibliographic-code))
+    (when (re-search-forward
+          "<textarea.*>\\(.*\\(?:\n.*\\)*?\\(?:\n\\s-*\n\\|\\'\\)\\)</textarea>"
+          nil t)
+      (xml-substitute-special (match-string 1)))))
+
+;;* Getting a bibtex entry for an arXiv article using arXiv API:
+;; Retrieves the meta data of an article view arXiv's http API,
+;; extracts the necessary information, and formats a new BibTeX entry.
+
+(defvar arxiv-entry-format-string "@article{%s,
+  journal = {CoRR},
+  title = {%s},
+  author = {%s},
+  archivePrefix = {arXiv},
+  year = {%s},
+  eprint = {%s},
+  primaryClass = {%s},
+  abstract = {%s},
+  url = {%s},
+}"
+  "Template for BibTeX entries of arXiv articles.")
+
+
+(declare-function doi-utils-doi-to-bibtex-string "doi-utils")
+(declare-function org-ref-replace-nonascii "org-ref-bibtex")
+
+(defun arxiv-get-bibtex-entry-via-arxiv-api (arxiv-number)
+  "Retrieve meta data for ARXIV-NUMBER.
+Returns a formatted BibTeX entry."
+  (with-current-buffer
+      (url-retrieve-synchronously (format "http://export.arxiv.org/api/query?id_list=%s" arxiv-number) t)
+    (let* ((parse-tree (libxml-parse-xml-region
+                        (progn (goto-char 0)
+                               (search-forward "<?xml ")
+                               (match-beginning 0))
+                        (point-max)))
+           (entry (assq 'entry parse-tree))
+           (authors (--map (nth 2 (nth 2 it))
+                           (--filter (and (listp it) (eq (car it) 'author)) entry)))
+           (year (format-time-string "%Y" (date-to-time (nth 2 (assq 'published entry)))))
+           (title (nth 2 (assq 'title entry)))
+           (names (arxiv-bibtexify-authors authors))
+           (category (cdar (nth 1 (assq 'primary_category entry))))
+           (abstract (s-trim (nth 2 (assq 'summary entry))))
+           (url (nth 2 (assq 'id entry)))
+           (temp-bibtex (format arxiv-entry-format-string "" title names year arxiv-number category abstract url))
+           (key (with-temp-buffer
+                  (insert temp-bibtex)
+                 (bibtex-mode)
+                 (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+                 (org-ref-replace-nonascii)
+                  (bibtex-generate-autokey)))
+          (doi (assq 'doi entry)))
+      (if doi
+         (doi-utils-doi-to-bibtex-string (nth 2 doi))
+       ;; no doi, so we fall back to the simple template
+       (format arxiv-entry-format-string key title names year arxiv-number category abstract url)))))
+
+
+(defun arxiv-bibtexify-authors (authors)
+  "Return names in 'SURNAME, FIRST NAME' format from AUTHORS list."
+  (s-join " and "
+          (--map (concat (-last-item it) ", " (s-join " " (-remove-last 'stringp it)))
+                 (--map (s-split " +" it) authors))))
+
+
+(defun arxiv-maybe-arxiv-id-from-current-kill ()
+  "Try to get an arxiv ID from the current kill."
+  (let* ((the-current-kill (ignore-errors (current-kill 0 t)))  ;; nil if empty kill ring
+         (arxiv-url-prefix-regexp "^https?://arxiv\\.org/\\(pdf\\|abs\\|format\\)/")
+         (arxiv-cite-prefix-regexp "^\\(arXiv\\|arxiv\\):")
+         (arxiv-id-old-regexp "[a-z-]+\\(\\.[A-Z]\\{2\\}\\)?/[0-9]\\{5,7\\}") ; Ex: math.GT/0309136
+         (arxiv-id-new-regexp "[0-9]\\{4\\}[.][0-9]\\{4,5\\}\\(v[0-9]+\\)?") ; Ex: 1304.4404v2
+         (arxiv-id-regexp (concat "\\(" arxiv-id-old-regexp "\\|" arxiv-id-new-regexp "\\)")))
+    (cond
+     (;; make sure current-kill has something in it
+      ;; if current-kill is not a string, return nil
+      (not (stringp the-current-kill))
+      nil)
+     (;; check if current-kill looks like an arxiv ID
+      ;; if so, return it
+      ;; Ex: 1304.4404v2
+      (s-match (concat "^" arxiv-id-regexp) the-current-kill)
+      the-current-kill)
+     (;; check if current-kill looks like an arxiv cite
+      ;; if so, remove the prefix and return
+      ;; Ex: arXiv:1304.4404v2 --> 1304.4404v2
+      (s-match (concat arxiv-cite-prefix-regexp arxiv-id-regexp "$") the-current-kill)
+      (replace-regexp-in-string arxiv-cite-prefix-regexp "" the-current-kill))
+     (;; check if current-kill looks like an arxiv url
+      ;; if so, remove the url prefix and return
+      ;; Ex: https://arxiv.org/abs/1304.4404 --> 1304.4404
+      (s-match (concat arxiv-url-prefix-regexp arxiv-id-regexp "$") the-current-kill)
+      (replace-regexp-in-string arxiv-url-prefix-regexp "" the-current-kill))
+     (;; check if current-kill looks like an arxiv PDF url
+      ;; if so, remove the url prefix, the .pdf suffix, and return
+      ;; Ex: https://arxiv.org/pdf/1304.4404.pdf --> 1304.4404
+      (s-match (concat arxiv-url-prefix-regexp arxiv-id-regexp "\\.pdf$") the-current-kill)
+      (replace-regexp-in-string arxiv-url-prefix-regexp "" (substring the-current-kill 0 (- (length the-current-kill) 4))))
+     ;; otherwise, return nil
+     (t
+      nil))))
+
+(defvar bibtex-completion-bibliography)
+
+;;;###autoload
+(defun arxiv-add-bibtex-entry (arxiv-number bibfile)
+  "Add bibtex entry for ARXIV-NUMBER to BIBFILE."
+  (interactive
+   (list (read-string
+          "arxiv: "
+          (arxiv-maybe-arxiv-id-from-current-kill))
+         ;;  now get the bibfile to add it to
+         (completing-read
+          "Bibfile: "
+          (append (f-entries "." (lambda (f) (f-ext? f "bib")))
+                 (if (stringp bibtex-completion-bibliography)
+                     (list bibtex-completion-bibliography)
+                   bibtex-completion-bibliography)))))
+  (save-window-excursion
+    (find-file bibfile)
+    (goto-char (point-max))
+    (when (not (looking-at "^")) (insert "\n"))
+    (insert (arxiv-get-bibtex-entry-via-arxiv-api arxiv-number))
+    (org-ref-clean-bibtex-entry)
+    (goto-char (point-max))
+    (when (not (looking-at "^")) (insert "\n"))
+    (save-buffer)))
+
+
+;;;###autoload
+(defun arxiv-get-pdf (arxiv-number pdf)
+  "Retrieve a pdf for ARXIV-NUMBER and save it to PDF."
+  (interactive
+   (list (read-string
+          "arxiv: "
+          (arxiv-maybe-arxiv-id-from-current-kill))
+         (read-string
+          "PDF: ")))
+  (let ((pdf-url (with-current-buffer
+                     (url-retrieve-synchronously
+                      (concat
+                       "http://arxiv.org/abs/" arxiv-number))
+                   ;; <meta name="citation_pdf_url" content="http://arxiv.org/pdf/0801.1144" />
+                   (goto-char (point-min))
+                   (search-forward-regexp
+                    "name=\\\"citation_pdf_url\\\" content=\\\"\\(.*\\)\\\"")
+                   (match-string 1))))
+    (url-copy-file pdf-url pdf)
+    ;; now check if we got a pdf
+    (unless (org-ref-pdf-p pdf)
+      (delete-file pdf)
+      (message "Error downloading arxiv pdf %s" pdf-url))))
+
+(defvar bibtex-completion-library-path)
+
+;;;###autoload
+(defun arxiv-get-pdf-add-bibtex-entry (arxiv-number bibfile pdfdir)
+  "Add bibtex entry for ARXIV-NUMBER to BIBFILE.
+Remove troublesome chars from the bibtex key, retrieve a pdf
+for ARXIV-NUMBER and save it to PDFDIR with the same name of the
+key."
+  (interactive
+   (list (read-string
+          "arxiv: "
+          (arxiv-maybe-arxiv-id-from-current-kill))
+         ;;  now get the bibfile to add it to
+         (completing-read
+          "Bibfile: "
+          (append (f-entries "." (lambda (f) (f-ext? f "bib")))
+                  bibtex-completion-bibliography))
+        (cond
+         ((stringp bibtex-completion-library-path)
+          bibtex-completion-library-path)
+         ((= 1 (length bibtex-completion-library-path))
+          (car bibtex-completion-library-path))
+         (t
+          (completing-read "PDF dir: " bibtex-completion-library-path)))))
+
+  (arxiv-add-bibtex-entry arxiv-number bibfile)
+
+  (save-window-excursion
+    (let ((key ""))
+      (find-file bibfile)
+      (goto-char (point-max))
+      (bibtex-beginning-of-entry)
+      (re-search-forward bibtex-entry-maybe-empty-head)
+      (if (match-beginning bibtex-key-in-head)
+          (progn
+            (setq key (delete-and-extract-region
+                       (match-beginning bibtex-key-in-head)
+                       (match-end bibtex-key-in-head)))
+            ;; remove potentially troublesome characters from key
+            ;; as it will be used as  a filename
+            (setq key (replace-regexp-in-string   "\"\\|\\*\\|/\\|:\\|<\\|>\\|\\?\\|\\\\\\||\\|\\+\\|,\\|\\.\\|;\\|=\\|\\[\\|]\\|!\\|@"
+                                                  "" key))
+            ;; check if the key is in the buffer
+            (when (save-excursion
+                    (bibtex-search-entry key))
+              (save-excursion
+                (bibtex-search-entry key)
+                (bibtex-copy-entry-as-kill)
+                (switch-to-buffer-other-window "*duplicate entry*")
+                (bibtex-yank))
+              (setq key (bibtex-read-key "Duplicate Key found, edit: " key))))
+        (setq key (bibtex-read-key "Key not found, insert: ")))
+      (insert key)
+      (arxiv-get-pdf arxiv-number (concat pdfdir key ".pdf"))
+      ;; Check that it worked, and insert a field for it.
+      (when (file-exists-p (concat pdfdir key ".pdf"))
+       (bibtex-end-of-entry)
+       (backward-char)
+       (insert (format "  file = {%s}\n  " (concat pdfdir key ".pdf")))))))
+
+
+(provide 'org-ref-arxiv)
+;;; org-ref-arxiv.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-autoloads.el b/elpa/org-ref-20230507.1420/org-ref-autoloads.el
new file mode 100644 (file)
index 0000000..ccdf40a
--- /dev/null
@@ -0,0 +1,855 @@
+;;; org-ref-autoloads.el --- automatically extracted autoloads  -*- lexical-binding: t -*-
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+                         (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "contrib" "contrib.el" (0 0 0 0))
+;;; Generated autoloads from contrib.el
+
+(register-definition-prefixes "contrib" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "doi-utils" "doi-utils.el" (0 0 0 0))
+;;; Generated autoloads from doi-utils.el
+
+(autoload 'doi-utils-async-download-pdf "doi-utils" "\
+Download the PDF for bibtex entry at point asynchronously.
+It is not fully async, only the download is. Fully async is
+harder because you need to run `doi-utils-get-pdf-url' async
+too. " t nil)
+
+(autoload 'doi-utils-get-bibtex-entry-pdf "doi-utils" "\
+Download pdf for entry at point if the pdf does not already exist locally.
+The entry must have a doi. The pdf will be saved, by the name
+%s.pdf where %s is the bibtex label. Files will not be
+overwritten. The pdf will be checked to make sure it is a pdf,
+and not some html failure page. You must have permission to
+access the pdf. We open the pdf at the end if
+`doi-utils-open-pdf-after-download' is non-nil.
+
+With one prefix ARG, directly get the pdf from a file (through
+`read-file-name') instead of looking up a DOI. With a double
+prefix ARG, directly get the pdf from an open buffer (through
+`read-buffer-to-switch') instead. These two alternative methods
+work even if the entry has no DOI, and the pdf file is not
+checked.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'doi-utils-add-bibtex-entry-from-doi "doi-utils" "\
+Add DOI entry to end of a file in the current directory.
+Pick the file ending with .bib or in .  If you have an active region that
+starts like a DOI, that will be the initial prompt.  If no region
+is selected and the first entry of the ‘kill-ring’ starts like a
+DOI, then that is the initial prompt.  Otherwise, you have to type
+or paste in a DOI.
+Argument BIBFILE the bibliography to use.
+
+\(fn DOI &optional BIBFILE)" t nil)
+
+(autoload 'doi-utils-doi-to-org-bibtex "doi-utils" "\
+Convert a DOI to an ‘org-bibtex’ form and insert it at point.
+
+\(fn DOI)" t nil)
+
+(autoload 'bibtex-set-field "doi-utils" "\
+Set FIELD to VALUE in bibtex file.  create field if it does not exist.
+Optional argument NODELIM see `bibtex-make-field'.
+
+\(fn FIELD VALUE &optional NODELIM)" t nil)
+
+(autoload 'doi-utils-update-bibtex-entry-from-doi "doi-utils" "\
+Update fields in a bibtex entry from the DOI.
+Every field will be updated, so previous change will be lost.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-update-field "doi-utils" "\
+Update the field at point in the bibtex entry.
+Data is retrieved from the doi in the entry." t nil)
+
+(autoload 'doi-utils-wos "doi-utils" "\
+Open Web of Science entry for DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-wos-citing "doi-utils" "\
+Open Web of Science citing articles entry for DOI.
+May be empty if none are found.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-wos-related "doi-utils" "\
+Open Web of Science related articles page for DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-ads "doi-utils" "\
+Open ADS entry for DOI
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-open "doi-utils" "\
+Open DOI in browser.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-open-bibtex "doi-utils" "\
+Search through variable `bibtex-completion-bibliography' for DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-crossref "doi-utils" "\
+Search DOI in CrossRef.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-google-scholar "doi-utils" "\
+Google scholar the DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-pubmed "doi-utils" "\
+Search Pubmed for the DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-crossref-citation-query "doi-utils" "\
+Query Crossref with the title of the bibtex entry at point.
+Get a list of possible matches. Choose one with completion." t nil)
+
+(autoload 'doi-utils-debug "doi-utils" "\
+Generate an org-buffer showing data about DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'doi-utils-add-entry-from-crossref-query "doi-utils" "\
+Search Crossref with QUERY and use completion to select an entry to add to BIBTEX-FILE.
+
+\(fn QUERY BIBTEX-FILE)" t nil)
+
+(register-definition-prefixes "doi-utils" '("*doi-utils-" "agu-pdf-url" "aip-pdf-url" "aps-pdf-url" "asme-biomechanical-pdf-url" "chemistry-europe-pdf-url" "copernicus-" "crossref-add-bibtex-entry" "doi-" "ecs" "frontiers-pdf-url" "generic-full-pdf-url" "ieee" "iop-pdf-url" "jneurosci-pdf-url" "jstor-pdf-url" "linkinghub-elsevier-pdf-url" "nature-pdf-url" "osa-pdf-url" "pnas-pdf-url" "rsc-pdf-url" "sage-pdf-url" "science-" "siam-pdf-url" "springer-" "tandfonline-pdf-url" "wiley-pdf-url-2"))
+
+;;;***
+\f
+;;;### (autoloads nil "nist-webbook" "nist-webbook.el" (0 0 0 0))
+;;; Generated autoloads from nist-webbook.el
+
+(autoload 'nist-webbook-formula "nist-webbook" "\
+Search NIST webbook for FORMULA.
+
+\(fn FORMULA)" t nil)
+
+(autoload 'nist-webbook-name "nist-webbook" "\
+Search NIST webbook for NAME.
+
+\(fn NAME)" t nil)
+
+;;;***
+\f
+;;;### (autoloads nil "openalex" "openalex.el" (0 0 0 0))
+;;; Generated autoloads from openalex.el
+
+(register-definition-prefixes "openalex" '("oa-" "org-ref-citation-hydra"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-arxiv" "org-ref-arxiv.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-arxiv.el
+
+(autoload 'arxiv-add-bibtex-entry "org-ref-arxiv" "\
+Add bibtex entry for ARXIV-NUMBER to BIBFILE.
+
+\(fn ARXIV-NUMBER BIBFILE)" t nil)
+
+(autoload 'arxiv-get-pdf "org-ref-arxiv" "\
+Retrieve a pdf for ARXIV-NUMBER and save it to PDF.
+
+\(fn ARXIV-NUMBER PDF)" t nil)
+
+(autoload 'arxiv-get-pdf-add-bibtex-entry "org-ref-arxiv" "\
+Add bibtex entry for ARXIV-NUMBER to BIBFILE.
+Remove troublesome chars from the bibtex key, retrieve a pdf
+for ARXIV-NUMBER and save it to PDFDIR with the same name of the
+key.
+
+\(fn ARXIV-NUMBER BIBFILE PDFDIR)" t nil)
+
+(register-definition-prefixes "org-ref-arxiv" '("arxiv-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-bibliography-links" "org-ref-bibliography-links.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-bibliography-links.el
+
+(register-definition-prefixes "org-ref-bibliography-links" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-bibtex" "org-ref-bibtex.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from org-ref-bibtex.el
+
+(autoload 'org-ref-bibtex-generate-longtitles "org-ref-bibtex" "\
+Generate longtitles.bib which are @string definitions.
+The full journal names are in `org-ref-bibtex-journal-abbreviations'." t nil)
+
+(autoload 'org-ref-bibtex-generate-shorttitles "org-ref-bibtex" "\
+Generate shorttitles.bib which are @string definitions.
+The abbreviated journal names in `org-ref-bibtex-journal-abbreviations'." t nil)
+
+(autoload 'org-ref-stringify-journal-name "org-ref-bibtex" "\
+Replace journal name in a bibtex entry with a string.
+The strings are defined in
+`org-ref-bibtex-journal-abbreviations'.  The optional arguments KEY,
+START and END allow you to use this with `bibtex-map-entries'
+
+\(fn &optional KEY START END)" t nil)
+
+(autoload 'org-ref-set-journal-string "org-ref-bibtex" "\
+Set a bibtex journal name to the string that represents FULL-JOURNAL-NAME.
+This is defined in `org-ref-bibtex-journal-abbreviations'.
+
+\(fn FULL-JOURNAL-NAME)" t nil)
+
+(autoload 'org-ref-replace-nonascii "org-ref-bibtex" "\
+Replace non-ascii characters with LaTeX representations in a
+bibtex entry." t nil)
+
+(autoload 'org-ref-title-case "org-ref-bibtex" "\
+Convert a bibtex entry title and booktitle to title-case.
+Convert only if the entry type is a member of the list
+`org-ref-title-case-types'. The arguments KEY, START and END are
+optional, and are only there so you can use this function with
+`bibtex-map-entries' to change all the title entries in articles and
+books.
+
+\(fn &optional KEY START END)" t nil)
+
+(autoload 'org-ref-title-case-article "org-ref-bibtex" "\
+Convert a bibtex entry article or book title to title-case.
+The arguments KEY, START and END are optional, and are only there
+so you can use this function with `bibtex-map-entries' to change
+all the title entries in articles and books.
+
+\(fn &optional KEY START END)" t nil)
+
+(autoload 'org-ref-sentence-case-article "org-ref-bibtex" "\
+Convert a bibtex entry article title to sentence-case.
+The arguments KEY, START and END are optional, and are only there
+so you can use this function with `bibtex-map-entries' to change
+all the title entries in articles.
+
+\(fn &optional KEY START END)" t nil)
+
+(autoload 'org-ref-bibtex-next-entry "org-ref-bibtex" "\
+Jump to the beginning of the next bibtex entry.
+N is a prefix argument.  If it is numeric, jump that many entries
+forward.  Negative numbers do nothing.
+
+\(fn &optional N)" t nil)
+
+(autoload 'org-ref-bibtex-previous-entry "org-ref-bibtex" "\
+Jump to beginning of the previous bibtex entry.
+N is a prefix argument.  If it is numeric, jump that many entries back.
+
+\(fn &optional N)" t nil)
+
+(autoload 'org-ref-bibtex-visible-entry "org-ref-bibtex" "\
+Jump to visible entry." t nil)
+
+(autoload 'org-ref-bibtex-visible-field "org-ref-bibtex" "\
+Jump to visible field." t nil)
+
+(autoload 'org-ref-bibtex-format-url-if-doi "org-ref-bibtex" "\
+Hook function to format url to follow the current DOI conventions." t nil)
+
+(autoload 'org-ref-bibtex-wos "org-ref-bibtex" "\
+Open bibtex entry in Web Of Science if there is a DOI." t nil)
+
+(autoload 'org-ref-bibtex-wos-citing "org-ref-bibtex" "\
+Open citing articles for bibtex entry in Web Of Science if
+there is a DOI." t nil)
+
+(autoload 'org-ref-bibtex-wos-related "org-ref-bibtex" "\
+Open related articles for bibtex entry in Web Of Science if
+there is a DOI." t nil)
+
+(autoload 'org-ref-bibtex-crossref "org-ref-bibtex" "\
+Open the bibtex entry in Crossref by its doi." t nil)
+
+(autoload 'org-ref-bibtex-google-scholar "org-ref-bibtex" "\
+Open the bibtex entry at point in google-scholar by its doi." t nil)
+
+(autoload 'org-ref-bibtex-pubmed "org-ref-bibtex" "\
+Open the bibtex entry at point in Pubmed by its doi." t nil)
+
+(autoload 'org-ref-bibtex-pdf "org-ref-bibtex" "\
+Open the pdf for the bibtex entry at point.
+Thin wrapper to get `org-ref-bibtex' to open pdf, because it
+calls functions with a DOI argument.
+
+\(fn &optional _)" t nil)
+
+(autoload 'org-ref-bibtex-assoc-pdf-with-entry "org-ref-bibtex" "\
+Prompt for pdf associated with entry at point and rename it.
+Check whether a pdf already exists in `bibtex-completion-library' with the
+name '[bibtexkey].pdf'. If the file does not exist, rename it to
+'[bibtexkey].pdf' using
+`org-ref-bibtex-assoc-pdf-with-entry-move-function' and place it in
+a directory. Optional PREFIX argument toggles between
+`rename-file' and `copy-file'.
+
+\(fn &optional PREFIX)" t nil)
+
+(autoload 'org-ref-email-bibtex-entry "org-ref-bibtex" "\
+Email current bibtex entry at point and pdf if it exists." t nil)
+
+(autoload 'org-ref-set-bibtex-keywords "org-ref-bibtex" "\
+Add KEYWORDS to a bibtex entry.
+If KEYWORDS is a list, it is converted to a comma-separated
+string.  The KEYWORDS are added to the beginning of the
+field.  Otherwise KEYWORDS should be a string of comma-separate
+keywords.  Optional argument ARG prefix arg to replace keywords.
+
+\(fn KEYWORDS &optional ARG)" t nil)
+
+(autoload 'org-ref-extract-bibtex-blocks "org-ref-bibtex" "\
+Extract all bibtex blocks in buffer to BIBFILE.
+If BIBFILE exists, append, unless you use a prefix arg (C-u), which
+will clobber the file.
+
+\(fn BIBFILE)" t nil)
+
+(autoload 'org-ref-open-bibtex-pdf "org-ref-bibtex" "\
+Open pdf for a bibtex entry, if it exists." t nil)
+
+(autoload 'org-ref-open-bibtex-notes "org-ref-bibtex" "\
+From a bibtex entry, open the notes if they exist." t nil)
+
+(autoload 'org-ref-open-in-browser "org-ref-bibtex" "\
+Open the bibtex entry at point in a browser using the url field or doi field." t nil)
+
+(autoload 'org-ref-build-full-bibliography "org-ref-bibtex" "\
+Build pdf of all bibtex entries, and open it." t nil)
+
+(autoload 'org-ref-sort-bibtex-entry "org-ref-bibtex" "\
+Sort fields of entry in standard order." t nil)
+
+(autoload 'org-ref-downcase-bibtex-entry "org-ref-bibtex" "\
+Downcase the entry type and fields." t nil)
+
+(autoload 'org-ref-clean-bibtex-entry "org-ref-bibtex" "\
+Clean and replace the key in a bibtex entry.
+See functions in `org-ref-clean-bibtex-entry-hook'." t nil)
+
+(register-definition-prefixes "org-ref-bibtex" '("orcb-" "org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-citation-links" "org-ref-citation-links.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-citation-links.el
+
+(autoload 'org-ref-delete-citation-at-point "org-ref-citation-links" "\
+Delete the citation or reference at point." t nil)
+
+(autoload 'org-ref-replace-citation-at-point "org-ref-citation-links" "\
+Replace the citation at point." t nil)
+
+(autoload 'org-ref-edit-pre-post-notes "org-ref-citation-links" "\
+Edit the pre/post notes at point.
+
+if you are not on a key, or with optional prefix
+arg COMMON, edit the common prefixes instead.
+
+\(fn &optional COMMON)" t nil)
+
+(autoload 'org-ref-change-cite-type "org-ref-citation-links" "\
+Change the cite type of citation link at point." t nil)
+
+(autoload 'org-ref-sort-citation-link "org-ref-citation-links" "\
+Replace link at point with sorted link by year." t nil)
+
+(autoload 'org-ref-next-key "org-ref-citation-links" "\
+Move cursor to the next cite key when on a cite link.
+Otherwise run `right-word'. If the cursor moves off the link,
+move to the beginning of the next cite link after this one." t nil)
+
+(autoload 'org-ref-previous-key "org-ref-citation-links" "\
+Move cursor to the previous cite key when on a cite link.
+Otherwise run `left-word'. If the cursor moves off the link,
+move to the beginning of the previous cite link after this one." t nil)
+
+(autoload 'org-ref-jump-to-visible-key "org-ref-citation-links" "\
+Jump to a visible key with avy." t nil)
+
+(autoload 'org-ref-insert-cite-link "org-ref-citation-links" "\
+Insert a cite link with completion.
+Optional prefix arg SET-TYPE to choose the cite type.
+
+\(fn &optional SET-TYPE)" t nil)
+
+(register-definition-prefixes "org-ref-citation-links" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-compat" "org-ref-compat.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from org-ref-compat.el
+
+(register-definition-prefixes "org-ref-compat" '("org-ref-to-org-cite"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-core" "org-ref-core.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-core.el
+
+(autoload 'org-ref-insert-link "org-ref-core" "\
+Insert an org-ref link.
+If no prefix ARG insert a cite.
+If one prefix ARG insert a ref.
+If two prefix ARGs insert a label.
+
+This is a generic function. Specific backends might
+provide their own version.
+
+\(fn ARG)" t nil)
+
+(autoload 'org-ref-help "org-ref-core" "\
+Open the `org-ref' manual." t nil)
+
+(register-definition-prefixes "org-ref-core" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-export" "org-ref-export.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from org-ref-export.el
+
+(register-definition-prefixes "org-ref-export" '("org-ref"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-glossary" "org-ref-glossary.el" (0
+;;;;;;  0 0 0))
+;;; Generated autoloads from org-ref-glossary.el
+
+(autoload 'org-ref-add-glossary-entry "org-ref-glossary" "\
+Insert a new glossary entry.
+LABEL is how you refer to it with links.
+NAME is the name of the entry to be defined.
+DESCRIPTION is the definition of the entry.
+Entry gets added after the last #+latex_header line.
+
+This is not a preferred way to add entries. It is preferred to
+manually add them to the glossary table.
+
+\(fn LABEL NAME DESCRIPTION)" t nil)
+
+(autoload 'org-ref-add-acronym-entry "org-ref-glossary" "\
+Add an acronym entry with LABEL.
+  ABBRV is the abbreviated form.
+  FULL is the expanded acronym.
+
+This is not the preferred way to add acronyms, you should add
+them manually to the acronyms table.
+
+\(fn LABEL ABBRV FULL)" t nil)
+
+(register-definition-prefixes "org-ref-glossary" '("or-" "org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-helm" "org-ref-helm.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-helm.el
+
+(autoload 'org-ref-cite-insert-helm "org-ref-helm" "\
+Search BibTeX entries.
+
+With a prefix ARG, the cache is invalidated and the bibliography
+reread.
+
+If LOCAL-BIB is non-nil, display that the BibTeX entries are read
+from the local bibliography.  This is set internally by
+`helm-bibtex-with-local-bibliography'.
+
+If INPUT is non-nil and a string, that value is going to be used
+as a predefined search term.  Can be used to define functions for
+frequent searches (e.g. your own publications).
+
+\(fn &optional ARG LOCAL-BIB INPUT)" t nil)
+
+(register-definition-prefixes "org-ref-helm" '("org-ref-helm-source-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-isbn" "org-ref-isbn.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-isbn.el
+
+(autoload 'org-ref-isbn-clean-bibtex-entry "org-ref-isbn" "\
+Clean a bibtex entry inserted via `isbn-to-bibtex'.
+See functions in `org-ref-isbn-clean-bibtex-entry-hook'." t nil)
+
+(autoload 'isbn-to-bibtex-lead "org-ref-isbn" "\
+Search lead.to for ISBN bibtex entry.
+You have to copy the entry if it is on the page to your bibtex
+file.
+
+\(fn ISBN)" t nil)
+
+(autoload 'isbn-to-bibtex "org-ref-isbn" "\
+Get bibtex entry for ISBN and insert it into BIBFILE.
+Nothing happens if an entry with the generated key already exists
+in the file. Data comes from www.ebook.de.
+
+\(fn ISBN BIBFILE)" t nil)
+
+(register-definition-prefixes "org-ref-isbn" '("isbn-to-bibtex-open-library" "org-ref-isbn-" "oricb-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-ivy" "org-ref-ivy.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-ivy.el
+
+(register-definition-prefixes "org-ref-ivy" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-label-link" "org-ref-label-link.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-label-link.el
+
+(autoload 'org-ref-insert-label-link "org-ref-label-link" "\
+Insert a new label with completion.
+The completion helps ensure you use a unique label." t nil)
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-latex" "org-ref-latex.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-latex.el
+
+(register-definition-prefixes "org-ref-latex" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-misc-links" "org-ref-misc-links.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-misc-links.el
+
+(autoload 'org-ref-list-of-figures "org-ref-misc-links" "\
+Generate buffer with list of figures in them.
+ARG does nothing.
+Ignore figures in COMMENTED sections.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'org-ref-list-of-tables "org-ref-misc-links" "\
+Generate a buffer with a list of tables.
+ARG does nothing.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'org-ref-index "org-ref-misc-links" "\
+Open an *index* buffer with links to index entries.
+PATH is required for the org-link, but it does nothing here.
+
+\(fn &optional PATH)" t nil)
+
+(register-definition-prefixes "org-ref-misc-links" '("org-ref-idxproc"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-natbib-bbl-citeproc" "org-ref-natbib-bbl-citeproc.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-natbib-bbl-citeproc.el
+
+(register-definition-prefixes "org-ref-natbib-bbl-citeproc" '("org-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-pdf" "org-ref-pdf.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-pdf.el
+
+(autoload 'org-ref-pdf-to-bibtex "org-ref-pdf" "\
+Add pdf of current buffer to bib file and save pdf. The pdf
+should be open in Emacs using the `pdf-tools' package." t nil)
+
+(autoload 'org-ref-pdf-debug-pdf "org-ref-pdf" "\
+Try to debug getting a doi from a pdf.
+Opens a buffer with the pdf converted to text, and `occur' on the
+variable `org-ref-pdf-doi-regex'.
+
+\(fn PDF-FILE)" t nil)
+
+(autoload 'org-ref-pdf-crossref-lookup "org-ref-pdf" "\
+Lookup highlighted text in PDFView in CrossRef." t nil)
+
+(register-definition-prefixes "org-ref-pdf" '("org-ref-" "pdftotext-executable"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-pubmed" "org-ref-pubmed.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from org-ref-pubmed.el
+
+(autoload 'pubmed-insert-bibtex-from-pmid "org-ref-pubmed" "\
+Insert a bibtex entry at point derived from PMID.
+You must clean the entry after insertion.
+
+\(fn PMID)" t nil)
+
+(autoload 'pubmed "org-ref-pubmed" "\
+Open http://www.ncbi.nlm.nih.gov/pubmed in a browser." t nil)
+
+(autoload 'pubmed-advanced "org-ref-pubmed" "\
+Open http://www.ncbi.nlm.nih.gov/pubmed/advanced in a browser." t nil)
+
+(autoload 'pubmed-simple-search "org-ref-pubmed" "\
+Open QUERY in Pubmed in a browser.
+
+\(fn QUERY)" t nil)
+
+(autoload 'pubmed-clinical "org-ref-pubmed" "\
+Open http://www.ncbi.nlm.nih.gov/pubmed/clinical in a browser." t nil)
+
+(autoload 'pubmed-clinical-search "org-ref-pubmed" "\
+Open QUERY in pubmed-clinical.
+
+\(fn QUERY)" t nil)
+
+(register-definition-prefixes "org-ref-pubmed" '("pubmed-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-ref-links" "org-ref-ref-links.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-ref-links.el
+
+(register-definition-prefixes "org-ref-ref-links" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-refproc" "org-ref-refproc.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from org-ref-refproc.el
+
+(register-definition-prefixes "org-ref-refproc" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-scifinder" "org-ref-scifinder.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-scifinder.el
+
+(autoload 'scifinder "org-ref-scifinder" "\
+Open https://scifinder.cas.org/scifinder/view/scifinder/scifinderExplore.jsf in a browser." t nil)
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-scopus" "org-ref-scopus.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from org-ref-scopus.el
+
+(autoload 'scopus-related-by-keyword-url "org-ref-scopus" "\
+Return a Scopus url to articles related by keyword for DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'scopus-related-by-author-url "org-ref-scopus" "\
+Return a Scopus url to articles related by author for DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'scopus-related-by-references-url "org-ref-scopus" "\
+Return a Scopus url to articles related by references for DOI.
+
+\(fn DOI)" t nil)
+
+(autoload 'scopus-open-eid "org-ref-scopus" "\
+Open article with EID in browser.
+
+\(fn EID)" t nil)
+
+(autoload 'scopus-basic-search "org-ref-scopus" "\
+Open QUERY as a basic title-abstract-keyword search at scopus.com.
+
+\(fn QUERY)" t nil)
+
+(autoload 'scopus-advanced-search "org-ref-scopus" "\
+Open QUERY as an advanced search at scopus.com.
+
+\(fn QUERY)" t nil)
+
+(register-definition-prefixes "org-ref-scopus" '("*hydra-eid*" "*scopus-api-key*" "scopus"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-url-utils" "org-ref-url-utils.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org-ref-url-utils.el
+
+(autoload 'org-ref-url-debug-url "org-ref-url-utils" "\
+Open a buffer to URL with all doi patterns highlighted.
+
+\(fn URL)" t nil)
+
+(autoload 'org-ref-url-html-to-bibtex "org-ref-url-utils" "\
+Convert URL to a bibtex or biblatex entry in BIBFILE.
+If URL is the first in the kill ring, use it. Otherwise, prompt for
+one in the minibuffer.
+
+\(fn BIBFILE &optional URL)" t nil)
+
+(register-definition-prefixes "org-ref-url-utils" '("org-ref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-utils" "org-ref-utils.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-utils.el
+
+(autoload 'org-ref-version "org-ref-utils" "\
+Provide a version string for org-ref.
+Copies the string to the clipboard." t nil)
+
+(autoload 'org-ref-debug "org-ref-utils" "\
+Print some debug information to a buffer." t nil)
+
+(autoload 'org-ref-open-pdf-at-point "org-ref-utils" "\
+Open the pdf for bibtex key under point if it exists." t nil)
+
+(autoload 'org-ref-add-pdf-at-point "org-ref-utils" "\
+Add the pdf for bibtex key under point if it exists.
+
+Similar to org-ref-bibtex-assoc-pdf-with-entry prompt for pdf
+associated with bibtex key at point and rename it.  Check whether a
+pdf already exists in `bibtex-completion-library' with the name
+'[bibtexkey].pdf'. If the file does not exist, rename it to
+'[bibtexkey].pdf' using
+`org-ref-bibtex-assoc-pdf-with-entry-move-function' and place it
+in a directory. Optional PREFIX argument toggles between
+`rename-file' and `copy-file'.
+
+\(fn &optional PREFIX)" t nil)
+
+(autoload 'org-ref-open-url-at-point "org-ref-utils" "\
+Open the url for bibtex key under point." t nil)
+
+(autoload 'org-ref-open-notes-at-point "org-ref-utils" "\
+Open the notes for bibtex key under point in a cite link in a buffer.
+Can also be called with THEKEY in a program.
+
+\(fn &optional THEKEY)" t nil)
+
+(autoload 'org-ref-open-citation-at-point "org-ref-utils" "\
+Open bibtex file to key at point." t nil)
+
+(autoload 'org-ref-copy-entry-as-summary "org-ref-utils" "\
+Copy the bibtex entry for the citation at point as a summary." t nil)
+
+(autoload 'org-ref-ads-at-point "org-ref-utils" "\
+Open the doi in ADS for bibtex key under point." t nil)
+
+(autoload 'org-ref-wos-at-point "org-ref-utils" "\
+Open the doi in wos for bibtex key under point." t nil)
+
+(autoload 'org-ref-wos-citing-at-point "org-ref-utils" "\
+Open the doi in wos citing articles for bibtex key under point." t nil)
+
+(autoload 'org-ref-wos-related-at-point "org-ref-utils" "\
+Open the doi in wos related articles for bibtex key under point." t nil)
+
+(autoload 'org-ref-google-scholar-at-point "org-ref-utils" "\
+Search google scholar for bibtex key under point using the title." t nil)
+
+(autoload 'org-ref-biblio-at-point "org-ref-utils" "\
+Do a biblio search for bibtex key under point using the title." t nil)
+
+(autoload 'org-ref-pubmed-at-point "org-ref-utils" "\
+Open the doi in pubmed for bibtex key under point." t nil)
+
+(autoload 'org-ref-crossref-at-point "org-ref-utils" "\
+Open the doi in crossref for bibtex key under point." t nil)
+
+(autoload 'org-ref-email-at-point "org-ref-utils" "\
+Email the citation(s) at point." t nil)
+
+(autoload 'org-ref-find-non-ascii-characters "org-ref-utils" "\
+Find non-ascii characters in the buffer.  Useful for cleaning up bibtex files." t nil)
+
+(autoload 'org-ref-extract-bibtex-to-file "org-ref-utils" "\
+Extract all bibtex entries for citations buffer to BIBFILE.
+If BIBFILE exists, append, unless you use a prefix arg (C-u),
+which will CLOBBER the file.
+
+\(fn BIBFILE &optional CLOBBER)" t nil)
+
+(autoload 'org-ref-extract-bibtex-entries "org-ref-utils" "\
+Extract the bibtex entries in the current buffer into a bibtex src block." t nil)
+
+(register-definition-prefixes "org-ref-utils" '("ords" "org-ref"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-worldcat" "org-ref-worldcat.el" (0
+;;;;;;  0 0 0))
+;;; Generated autoloads from org-ref-worldcat.el
+
+(register-definition-prefixes "org-ref-worldcat" '("worldcat-query-all"))
+
+;;;***
+\f
+;;;### (autoloads nil "org-ref-wos" "org-ref-wos.el" (0 0 0 0))
+;;; Generated autoloads from org-ref-wos.el
+
+(autoload 'wos-search "org-ref-wos" "\
+Open the word at point or selection in Web of Science as a topic query." t nil)
+
+(autoload 'wos "org-ref-wos" "\
+Open Web of Science search page in a browser." t nil)
+
+(register-definition-prefixes "org-ref-wos" '("*wos-" "wos-"))
+
+;;;***
+\f
+;;;### (autoloads nil "x2bib" "x2bib.el" (0 0 0 0))
+;;; Generated autoloads from x2bib.el
+
+(autoload 'ris2bib "x2bib" "\
+Convert RISFILE to bibtex and insert at point.
+Without a prefix arg, stderr is diverted.
+If VERBOSE is non-nil show command output.
+If the region is active, assume it is a ris entry
+and convert it to bib format in place.
+
+\(fn RISFILE &optional VERBOSE)" t nil)
+
+(autoload 'medxml2bib "x2bib" "\
+Convert MEDFILE (in Pubmed xml) to bibtex and insert at point.
+Without a prefix arg, stderr is diverted.
+Display output if VERBOSE is non-nil.
+
+\(fn MEDFILE &optional VERBOSE)" t nil)
+
+(autoload 'clean-entries "x2bib" "\
+Map over bibtex entries and clean them." t nil)
+
+;;;***
+\f
+;;;### (autoloads nil nil ("org-ref-pgk.el" "org-ref-pkg.el" "org-ref-sci-id.el"
+;;;;;;  "org-ref.el") (0 0 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; org-ref-autoloads.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-bibliography-links.el b/elpa/org-ref-20230507.1420/org-ref-bibliography-links.el
new file mode 100644 (file)
index 0000000..ba432b7
--- /dev/null
@@ -0,0 +1,312 @@
+;;; org-ref-bibliography-links.el --- Bibliography and bibliographystyle links
+;;
+;; Copyright (C) 2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+
+;;; Code:
+
+(defcustom org-ref-latex-bib-resolve-func #'file-relative-name
+  "Function to expand paths to the bibliography file on latex export.
+Use this to convert a path to what you want, e.g. relative to
+some directory, absolute, etc."
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-validate-bibliography nil
+  "If non-nil, validate bibliography files in fontification.
+This can be slow, so we don't do it by default."
+  :type 'boolean
+  :group 'org-ref)
+
+
+;;* bibliography* links
+
+(defun org-ref-get-bibfile-path (bibfile)
+  "Get a path to BIBFILE as local file, or using kpsewhich.
+This should allow you to use a bib file that is setup with TeX
+variables like BIBINPUTS."
+  (or (when (file-exists-p bibfile) bibfile)
+      (let ((f (replace-regexp-in-string
+               "\n$" ""
+               (shell-command-to-string (format "kpsewhich %s" bibfile)))))
+       (unless (string= "" f)
+         f))))
+
+
+(defun org-ref-bibliography*-export (cmd bibfiles _desc backend)
+  "Exporting function for bibliography links.
+To be used as a partial function e.g.
+ (apply-partially \"bibliography\" 'org-ref-bibliography*-export)
+Argument CMD is the command it should export to.
+Argument BIBFILES is a comma-separated list of strings.
+Argument BACKEND is the export backend."
+  (cond
+   ((eq backend 'latex)
+    (format "%s{%s}"
+           cmd
+           (if (not (string= "" bibfiles)) 
+               (replace-regexp-in-string
+                "\\.bib" ""
+                (mapconcat
+                 'identity
+                 (mapcar
+                  (lambda (f)
+                    (funcall org-ref-latex-bib-resolve-func (org-ref-get-bibfile-path f)))
+                  (split-string bibfiles ","))
+                 ","))
+             "")))))
+
+
+(defun org-ref-bibliography-activate (start end path _bracketp)
+  "Activate a bibliography link.
+Adds a warning face to non-existent or invalid bib-files.
+START and END are the bounds of the link.
+PATH is a comma-separated list of bibfiles."
+  (goto-char start)
+  (cl-loop for p in (split-string path ",") do
+          (setq p (string-trim p))
+          (search-forward p)
+          (setq p (org-ref-get-bibfile-path p))
+          (put-text-property (match-beginning 0) (match-end 0) 'org-ref-bibfile p)
+          (put-text-property (match-beginning 0) (match-end 0) 'help-echo (format "File exists at %s" p))
+
+          ;; activate files that don't exist
+          (when (or (null p) (not (file-exists-p p)))
+            (put-text-property (match-beginning 0) (match-end 0)
+                               'face 'font-lock-warning-face)
+            (put-text-property (match-beginning 0) (match-end 0)
+                               'help-echo "This file was not found."))
+
+          (when (and p (file-exists-p p))
+            (when org-ref-validate-bibliography
+              ;; Let's do a validation, but only if it has changed since the last time we checked.
+              (let* ((mod-time-last-check (or (get-text-property (match-beginning 0)
+                                                                 'mod-time-last-check)
+                                              '(0 0 0 0)))
+                     (last-modified (file-attribute-modification-time (file-attributes p)))
+                     (bibtex-valid))
+                (if (time-equal-p mod-time-last-check last-modified)
+                    (setq bibtex-valid (get-text-property (match-beginning 0) 'bibtex-valid))
+
+                  ;; the times were not equal, so we check and store the state.
+                  (setq bibtex-valid (save-match-data
+                                       (with-current-buffer (find-file-noselect p)
+                                         (bibtex-validate))))
+                  (put-text-property (match-beginning 0)
+                                     (match-end 0)
+                                     'mod-time-last-check
+                                     last-modified)
+                  (put-text-property (match-beginning 0)
+                                     (match-end 0)
+                                     'bibtex-valid
+                                     bibtex-valid))
+
+                (unless bibtex-valid
+                  (put-text-property (match-beginning 0) (match-end 0)
+                                     'face 'font-lock-warning-face)
+                  (put-text-property (match-beginning 0) (match-end 0)
+                                     'help-echo "This file did not pass `bibtex-validate'.")))))))
+
+
+(defun org-ref-bibliography*-follow (_path)
+  "Function to follow bibliography links."
+  (interactive)
+  (save-excursion
+    (unless (get-text-property (point) 'org-ref-bibfile)
+      (re-search-forward ":"))
+    (find-file (org-ref-get-bibfile-path (get-text-property (point) 'org-ref-bibfile)))))
+
+
+(defun org-ref-printbibliography-export (options _desc backend)
+  "Export function for printbibliography links.
+Argument OPTIONS are the options used for the command.
+Optional argument BACKEND is the export backend."
+  (cond
+   ((eq backend 'latex)
+    ;; write out the biblatex bibliography command
+    (format "\\printbibliography%s"
+           (if (not (string= "" options))
+               (format "[%s]" options)
+             "")))))
+
+(defvar org-ref-cite-types)
+(declare-function org-element-map "org-element")
+(declare-function org-element-property "org-element")
+(declare-function org-element-parse-buffer "org-element")
+(declare-function bibtex-completion-show-entry "bibtex-completion")
+(declare-function org-ref-possible-bibfiles "org-ref-core")
+(declare-function org-ref-parse-cite-path "org-ref-citation-links")
+
+(defun org-ref-insert-bibliography-link ()
+  "Insert a bibliography link for the files used in this buffer."
+  (interactive)
+  (let* ((cite-links (org-element-map (org-element-parse-buffer) 'link
+                      (lambda (lnk)
+                        (when (assoc (org-element-property :type lnk) org-ref-cite-types)
+                          lnk))))
+        (keys (delete-dups (cl-loop for cl in cite-links append
+                                    (cl-loop for ref in (plist-get (org-ref-parse-cite-path
+                                                                    (org-element-property :path cl))
+                                                                   :references)
+                                             collect (plist-get ref :key)))))
+        (files (delete-dups (cl-loop for key in keys collect
+                                     (save-window-excursion
+                                       (bibtex-completion-show-entry (list key))
+                                       (buffer-file-name))))))
+    (insert (format "[[bibliography:%s]]" (string-join files ",")))))
+
+
+(defun org-ref-bibliography-complete (&optional arg)
+  "Completion function for bibliography links."
+  (concat "bibliography:"
+         (completing-read "Bibliography file: " (org-ref-possible-bibfiles))))
+
+(defun org-ref-nobibliography-complete (&optional arg)
+  "Completion function for bibliography links."
+  (concat "nobibliography:"
+         (completing-read "Bibliography file: " (org-ref-possible-bibfiles))))
+
+
+(defvar org-ref-default-citation-link)
+
+(defun org-ref-bibtex-store-link ()
+  "Store a link from a bibtex file. Only supports the cite link.
+This essentially the same as the store link in org-bibtex, but it
+creates a cite link."
+  (when (eq major-mode 'bibtex-mode)
+    (let ((link (concat org-ref-default-citation-link
+                       ":&"
+                       (save-excursion
+                          (bibtex-beginning-of-entry)
+                         (cdr (assoc "=key=" (bibtex-parse-entry)))))))
+      (push (list link) org-stored-links)
+      (car org-stored-links))))
+
+
+;; ** bibliography* links
+
+(org-link-set-parameters "bibliography"
+                        :follow #'org-ref-bibliography*-follow
+                        :store #'org-ref-bibtex-store-link
+                        :complete #'org-ref-bibliography-complete
+                        :help-echo "Bibliography link"
+                        :export (apply-partially 'org-ref-bibliography*-export "\\bibliography")
+                        :activate-func #'org-ref-bibliography-activate
+                        :face 'org-link)
+
+
+(org-link-set-parameters "nobibliography"
+                        :complete #'org-ref-nobibliography-complete
+                        :store #'org-ref-bibtex-store-link
+                        :help-echo "No bibliography link"
+                        :activate-func #'org-ref-bibliography-activate
+                        :follow #'org-ref-bibliography*-follow
+                        :export (apply-partially 'org-ref-bibliography*-export "\\nobibliography")
+                        :face 'org-link)
+
+
+(org-link-set-parameters "nobibliography*"
+                        :complete #'org-ref-nobibliography-complete
+                        :store #'org-ref-bibtex-store-link
+                        :help-echo "No bibliography link"
+                        :activate-func #'org-ref-bibliography-activate
+                        :follow #'org-ref-bibliography*-follow
+                        :export (apply-partially 'org-ref-bibliography*-export "\\nobibliography*")
+                        :face 'org-link)
+
+
+(org-link-set-parameters "printbibliography"
+                        :export #'org-ref-printbibliography-export)
+
+;; Note I removed the addbibresource link, it goes in the header, not the document.
+
+;; *** bibliographystyle
+(defvar-local org-ref-bst-styles nil
+  "A list of known bibliography styles. Used to cache results.")
+
+
+(defun org-ref-clear-bst-cache ()
+  "Clear `org-ref-bst-styles' to reload it."
+  (interactive)
+  (setq org-ref-bst-styles nil))
+
+
+(defun org-ref-bibliography-styles ()
+  "Return a list of known bibliography styles.
+Returns `org-ref-bst-styles' or sets it and returns it."
+  (or org-ref-bst-styles
+      (setq org-ref-bst-styles
+           (mapcar 'file-name-nondirectory
+                   (mapcar 'file-name-sans-extension
+                           (-flatten
+                            (mapcar (lambda (path)
+                                      (setq path (replace-regexp-in-string "!" "" path))
+                                      (when (file-directory-p path)
+                                        (f-entries path (lambda (f) (f-ext? f "bst")) t)))
+                                    (split-string
+                                     ;; https://tex.stackexchange.com/questions/431948/get-a-list-of-installed-bibliography-styles-with-kpsewhich?noredirect=1#comment1082436_431948
+                                     (shell-command-to-string "kpsewhich -expand-path '$BSTINPUTS'")
+                                     ":"))))))))
+
+
+(defun org-ref-bibliographystyle-complete-link (&optional arg)
+  "Completion function for bibliography style links.
+ARG is a not used."
+  (when (executable-find "kpsewhich")
+    (concat "bibliographystyle:"
+           (completing-read "Style: " (org-ref-bibliography-styles)))))
+
+
+(defun org-ref-bibliographystyle-activate (start _end path _bracketp)
+  "Activation function for bibliography styles.
+START is the beginning position of the link.
+Optional argument PATH contains the selected style."
+  (unless (member path (org-ref-bibliography-styles))
+    (goto-char start)
+    (search-forward path)
+    (put-text-property (match-beginning 0) (match-end 0) 'face 'font-lock-warning-face)
+    (put-text-property (match-beginning 0) (match-end 0) 'help-echo "Unrecognized style")))
+
+
+(defun org-ref-bibliographystyle-export (style _desc backend)
+  "Export function for bibliographystyle links.
+Argument STYLE is the desired style.
+Optional argument BACKEND is the export backend."
+  (cond
+   ((or (eq backend 'latex)
+       (eq backend 'beamer))
+    ;; write out the latex bibliography command
+    (format "\\bibliographystyle{%s}" style))
+   ;; No other backend needs this I think
+   (t
+    "")))
+
+
+(org-link-set-parameters "bibliographystyle"
+                        :complete #'org-ref-bibliographystyle-complete-link
+                        :activate-func #'org-ref-bibliographystyle-activate
+                        :export #'org-ref-bibliographystyle-export)
+
+
+(provide 'org-ref-bibliography-links)
+
+;;; org-ref-bibliography-links.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-bibtex.el b/elpa/org-ref-20230507.1420/org-ref-bibtex.el
new file mode 100644 (file)
index 0000000..4efa4b0
--- /dev/null
@@ -0,0 +1,1462 @@
+;;; org-ref-bibtex.el -- org-ref-bibtex utilities
+
+;; Copyright(C) 2014-2021 John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; URL: https://github.com/jkitchin/org-ref
+;; Version: 0.1
+;; Keywords: org-mode, bibtex
+
+;; This file is not currently part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program ; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+
+;; Functions to act on a bibtex entry or file
+;;
+;; ** Modifying bibtex entries
+;; - `org-ref-sort-bibtex-entry' :: sort the fields in an entry
+;; - `org-ref-downcase-bibtex-entry' :: downcase the fields in an entry
+;; - `org-ref-clean-bibtex-entry' :: run hooks in `org-ref-clean-bibtex-entry-hook' on an entry
+;; - `org-ref-title-case-article' :: title case the title in an article or book
+;; - `org-ref-sentence-case-article' :: sentence case the title in an article.
+;; org-ref-bibtex-generate-longtitles
+;; org-ref-bibtex-generate-shorttitles
+;; org-ref-stringify-journal-name :: replace a journal name with a string in
+;; `org-ref-bibtex-journal-abbreviations'
+;; org-ref-set-journal-string :: in a bibtex entry run this to replace the
+;; journal with a string
+;;
+
+;; * Navigating bibtex entries
+;; `org-ref-bibtex-next-entry' :: bound to M-n
+;; `org-ref-bibtex-previous-entry' :: bound to M-p
+
+;;
+;; ** Operate on whole bibtex file
+;; - `org-ref-build-full-bibliography'
+;; org-ref-replace-nonascii :: replace nonascii characters in a bibtex
+;; entry.  Replacements are in `org-ref-nonascii-latex-replacements'.
+;;
+;; ** hydra menu for bibtex files
+;; `org-ref-bibtex-hydra/body' gives a hydra menu to a lot of useful functions.
+;; `org-ref-bibtex-new-entry/body' gives a hydra menu to add new bibtex entries.
+;; `org-ref-bibtex-file/body' gives a hydra menu of actions for the bibtex file
+;;
+;;; Code
+
+(require 'bibtex)
+(require 'dash)
+(require 'hydra)
+(require 'message)
+(require 's)
+(require 'doi-utils)
+(require 'avy)
+
+(defvar bibtex-completion-bibliography)
+(declare-function bibtex-completion-show-entry "bibtex-completion")
+(declare-function org-ref-find-bibliography "org-ref-core")
+(declare-function org-element-property "org-element")
+
+;;* Custom variables
+(defgroup org-ref-bibtex nil
+  "Customization group for org-ref-bibtex."
+  :group 'org-ref-bibtex)
+
+
+(defcustom org-ref-shorten-authors nil
+  "If non-nil show only last names in the completion selection buffer."
+  :type 'boolean
+  :group 'org-ref-bibtex)
+
+
+(defcustom org-ref-bibtex-sort-order
+  '(("article"  . ("author" "title" "journal" "volume" "number" "pages" "year" "doi" "url"))
+    ("inproceedings" . ("author" "title" "booktitle" "year" "volume" "number" "pages" "doi" "url"))
+    ("book" . ("author" "title" "year" "publisher" "url")))
+  "A-list of bibtex entry fields and the order to sort an entry with.
+\(entry-type . (list of fields). This is used in
+`org-ref-sort-bibtex-entry'. Entry types not listed here will
+have fields sorted alphabetically."
+  :type '(alist :key-type (string) :value-type (repeat string))
+  :group 'org-ref)
+
+
+(defcustom orcb-%-replacement-string " \\\\%"
+  "Replacement for a naked % sign in cleaning a BibTeX entry.
+The replacement string should be escaped for use with
+`replace-match'. Compare to the default value. Common choices
+would be to omit the space or to replace the space with a ~ for a
+non-breaking space."
+  :type 'regexp
+  :group 'org-ref)
+
+
+(defcustom org-ref-clean-bibtex-key-function
+  (lambda (key)
+    (replace-regexp-in-string ":" "" key))
+  "Function to modify a bibtex key.
+The default behavior is to remove : from the key."
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-clean-bibtex-entry-hook
+  '(org-ref-bibtex-format-url-if-doi
+    orcb-key-comma
+    org-ref-replace-nonascii
+    orcb-&
+    orcb-%
+    org-ref-title-case-article
+    orcb-clean-year
+    orcb-key
+    orcb-clean-doi
+    orcb-clean-pages
+    orcb-check-journal
+    org-ref-sort-bibtex-entry
+    orcb-fix-spacing
+    orcb-download-pdf)
+  "Hook that is run in `org-ref-clean-bibtex-entry'.
+The functions should have no arguments, and
+operate on the bibtex entry at point. You can assume point starts
+at the beginning of the entry. These functions are wrapped in
+`save-restriction' and `save-excursion' so you do not need to
+save the point position.
+
+Org ref contains some functions that are not included by default
+such as `orcb-clean-nil' or `orcb-clean-nil-opinionated' that
+users may be interested in adding themselves."
+  :group 'org-ref
+  :type 'hook)
+
+;; see https://github.com/fxcoudert/tools/blob/master/doi2bib for more replacements
+(defcustom org-ref-nonascii-latex-replacements
+  '(("í" . "{\\\\'i}")
+    ("æ" . "{\\\\ae}")
+    ("ć" . "{\\\\'c}")
+    ("é" . "{\\\\'e}")
+    ("ä" . "{\\\\\"a}")
+    ("è" . "{\\\\`e}")
+    ("à" . "{\\\\`a}")
+    ("á" . "{\\\\'a}")
+    ("ø" . "{\\\\o}")
+    ("ë" . "{\\\\\"e}")
+    ("ü" . "{\\\\\"u}")
+    ("ñ" . "{\\\\~n}")
+    ("ņ" . "{\\\\c{n}}")
+    ("ñ" . "{\\\\~n}")
+    ("å" . "{\\\\aa}")
+    ("ö" . "{\\\\\"o}")
+    ("Á" . "{\\\\'A}")
+    ("í" . "{\\\\'i}")
+    ("ó" . "{\\\\'o}")
+    ("ó" . "{\\\\'o}")
+    ("ú" . "{\\\\'u}")
+    ("ú" . "{\\\\'u}")
+    ("ý" . "{\\\\'y}")
+    ("š" . "{\\\\v{s}}")
+    ("č" . "{\\\\v{c}}")
+    ("ř" . "{\\\\v{r}}")
+    ("š" . "{\\\\v{s}}")
+    ("İ" . "{\\\\.I}")
+    ("ğ" . "{\\\\u{g}}")
+    ("δ" . "$\\\\delta$")
+    ("ç" . "{\\\\c{c}}")
+    ("ß" . "{\\\\ss}")
+    ("≤" . "$\\\\le$")
+    ("≥" . "$\\\\ge$")
+    ("θ" . "$\\\\theta$")
+    ("μ" . "$\\\\mu$")
+    ("→" . "$\\\\rightarrow$")
+    ("⇌" . "$\\\\leftrightharpoons$")
+    ("×" . "$\\\\times$")
+    ("°" . "$\\\\deg$")
+    ("ş" . "{\\\\c{s}}")
+    ("γ" . "$\\\\gamma$")
+    ("ɣ" . "$\\\\gamma$")
+    ("º" . "degC")
+    ("η" . "$\\\\eta$")
+    ("µ" . "$\\\\mu$")
+    ("α" . "$\\\\alpha$")
+    ("β" . "$\\\\beta$")
+    ("ɛ" . "$\\\\epsilon$")
+    ("Ⅵ" . "\\textrm{VI}")
+    ("Ⅲ" . "\\textrm{III}")
+    ("Ⅴ" . "\\textrm{V}")
+    ("λ" . "$\\\\lambda$")
+    ("π" . "$\\\\pi$")
+    ("∞" . "$\\\\infty$")
+    ("χ" . "$\\\\chi$")
+    ("∼" . "\\\\textasciitilde{}")
+    ("‑" . "\\\\textemdash{}")
+    (" " . " ")
+    ("…" . "...")
+    ("•" . "\\\\textbullet ")
+    ;; I think these are non-ascii spaces. there seems to be more than one.
+    (" " . " ")
+    (" " . " ")
+    (" " . " ")
+    ("–" . "-")
+    ("−" . "-")
+    ("–" . "-")
+    ("—" . "-")
+    ("‒" . "\\\\textemdash{}")
+    ("‘" . "'")
+    ("’" . "'")
+    ("’" . "'")
+    ("“" . "\"")
+    ("’" . "'")
+    ("”" . "\""))
+  "Cons list of non-ascii characters and their LaTeX representations.
+This may be deprecated. When `org-ref' started, non-ascii
+characters were often problematic with bibtex, but in 2021, it is
+not obvious that is still try."
+  :type '(alist :key-type (string) :value-type (string))
+  :group 'org-ref-bibtex)
+
+(defcustom org-ref-bibtex-assoc-pdf-with-entry-move-function 'rename-file
+  "Function to use when associating pdf files with bibtex entries.
+The value should be either `rename-file' or `copy-file'. The former
+will move and rename the original file. The latter will leave the
+original file in place while creating a renamed copy in some directory."
+  :type 'function
+  :group 'org-ref-bibtex)
+
+;;* Journal abbreviations
+(defcustom org-ref-bibtex-journal-abbreviations
+  '(("ACR" "Accounts of Chemical Research" "Acc. Chem. Res.")
+    ("ACAT" "ACS Catalysis" "ACS Catal.")
+    ("AM" "Acta Materialia" "Acta Mater.")
+    ("AMM" "Acta Metallurgica et Materialia" "Acta Metall. Mater.")
+    ("AEM" "Advanced Energy Materials" "Adv. Energy Mater.")
+    ("AAMI" "ACS Applied Materials \\& Interfaces"
+     "ACS Appl. Mater. Interfaces")
+    ("AMiner" "American Mineralogist" "Am. Mineral.")
+    ("AngC" "Angewandte Chemie-International Edition"
+     "Angew. Chem. Int. Edit.")
+    ("APLM" "APL Materials" "APL Mat.")
+    ("ACBE" "Applied Catalysis B: Environmental" "Appl. Catal. B-Environ.")
+    ("APL" "Applied Physics Letters" "Appl. Phys. Lett.")
+    ("ASS" "Applied Surface Science" "Appl. Surf. Sci.")
+    ("CL" "Catalysis Letters" "Catal. Lett.")
+    ("CC" "Catalysis Communications" "Catal. Commun.")
+    ("CST" "Catalysis Science & Technology" "Catal. Sci. Technol.")
+    ("CT" "Catalysis Today" "Catal. Today")
+    ("ChC" "Chemical Communications" "Chem. Commun.")
+    ("CPL" "Chemical Physics Letters" "Chem. Phys. Lett")
+    ("CR" "Chemical Reviews" "Chem. Rev.")
+    ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
+    ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
+    ("CM" "Chemistry of Materials" "Chem. Mater.")
+    ("CSA" "Colloids and Surfaces, A: Physicochemical and Engineering Aspects"
+     "Colloids Surf., A")
+    ("CF" "Combustion and Flame" "Combust. Flame")
+    ("CPMS" "Computational Materials Science" "Comp. Mater. Sci.")
+    ("CPC" "Computer Physics Communications" "Comput. Phys. Commun.")
+    ("CSE" "Computing in Science \\& Engineering" "Comput. Sci. Eng.")
+    ("CGD" "Crystal Growth \\& Design" "Cryst. Growth Des.")
+    ("CEC" "CrystEngComm" "CrystEngComm")
+    ("EA" "Electrochimica Acta" "Electrochim. Acta")
+    ("ECST" "ECS Transactions" "ECS Trans.")
+    ("EES" "Energy \\& Environmental Science" "Energy Environ. Sci.")
+    ("HPR" "High Pressure Research" "High Pressure Res.")
+    ("IC" "Inorganic Chemistry" "Inorg. Chem.")
+    ("IECR" "Industrial \\& Engineering Chemistry Research"
+     "Ind. Eng. Chem. Res.")
+    ("JJAP" "Japanese Journal of Applied Physics" "Jpn. J. Appl. Phys.")
+    ("JMatR" "Journal of  Materials Research" "J. Mater. Res.")
+    ("JALC" "Journal of Alloys and Compounds" "J. Alloy Compd.")
+    ("JAC" "Journal of Applied Crystallography" "J. Appl. Crystallogr.")
+    ("JAE" "Journal of Applied Electrochemistry" "J. Appl. Electrochem.")
+    ("JAP" "Journal of Applied Physics" "J. Appl. Phys.")
+    ("JC" "Journal of Catalysis" "J. Catal.")
+    ("JCP" "Journal of Chemical Physics" "J. Chem. Phys.")
+    ("JCC" "Journal of Computational Chemistry" "J. Comput. Chem.")
+    ("JCG" "Journal of Crystal Growth" "J. Crys. Growth")
+    ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
+    ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
+    ("JMSL" "Journal of Materials Science Letters" "J. Mater. Sci. Lett.")
+    ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
+    ("JPE" "Journal of Phase Equilibria" "J. Phase Equilib.")
+    ("JPCS" "Journal of Physics and Chemistry of Solids"
+     "J. Phys. Chem. Solids")
+    ("JPCM" "Journal of Physics: Condensed Matter"
+     "J. Phys.: Condens. Matter")
+    ("JPS" "Journal of Power Sources" "J. Power Sources")
+    ("JSSC" "Journal of Solid State Chemistry" "J. Solid State Chem.")
+    ("JACerS" "Journal of the American Ceramic Society" "J. Am. Ceram. Soc.")
+    ("JACS" "Journal of the American Chemical Society" "J. Am. Chem. Soc.")
+    ("JASIST" "Journal of the American Society for Information Science and Technology"
+     "J. Am. Soc. Inf. Sci. Technol.")
+    ("JES" "Journal of The Electrochemical Society" "J. Electrochem. Soc.")
+    ("JEaC" "Journal of Electroanalytical Chemistry" "J. Electroanal. Chem.")
+    ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
+    ("JRS" "Journal of Raman Spectroscopy" "J. Raman Spectrosc.")
+    ("JVST" "Journal of Vacuum Science \\& Technology A"
+     "J. Vac. Sci. Technol. A")
+    ("ML" "Materials Letters" "Mater. Lett.")
+    ("MSE-BS" "Materials Science and Engineering B" "Mat. Sci. Eng. B-Solid")
+    ("MOLSIM" "Molecular Simulation" "Mol. Sim.")
+    ("Nature" "Nature" "Nature")
+    ("NM" "Nature Materials" "Nat. Mater.")
+    ("NC" "Nature Chemistry" "Nat. Chem.")
+    ("PML" "Philosophical Magazine Letters" "Phil. Mag. Lett.")
+    ("PMA" "Philosophical Magazine A" "Phil. Mag. A")
+    ("PA" "Physica A: Statistical Mechanics and its Applications" "Physica A")
+    ("PB" "Physica B-Condensed Matter" "Physica B")
+    ("PCCP" "Physical Chemistry Chemical Physics" "Phys. Chem. Chem. Phys.")
+    ("PSSB" "physica status solidi (b)" "Phys. Status Solidi B")
+    ("PRA" "Physical Review A" "Phys. Rev. A")
+    ("PRB" "Physical Review B" "Phys. Rev. B")
+    ("PRL" "Physical Review Letters" "Phys. Rev. Lett.")
+    ("PCM" "Physics and Chemistry of Minerals" "Phys. Chem. Miner.")
+    ("PNAS" "Proceedings of the National Academy of Sciences of the United States of America"
+     "Proc. Natl. Acad. Sci. U. S. A.")
+    ("PSurfSci" "Progress in Surface Science" "Prog. Surf. Sci.")
+    ("Science" "Science" "Science")
+    ("SM" "Scripta Materialia" "Scr. Mater.")
+    ("SABC" "Sensors and Actuators B: Chemical" "Sensor. Actuat. B-Chem.")
+    ("SS" "Surface Science" "Surf. Sci.")
+    ("EPJB" "The European Physical Journal B" "Eur. Phys. J. B")
+    ("JPC" "The Journal of Physical Chemistry" "J. Phys. Chem.")
+    ("JPCB" "The Journal of Physical Chemistry B" "J. Phys. Chem. B")
+    ("JPCC" "The Journal of Physical Chemistry C" "J. Phys. Chem. C")
+    ("JPCL" "The Journal of Physical Chemistry Letters"
+     "J. Phys. Chem. Lett.")
+    ("JCP" "The Journal of Chemical Physics" "J. Chem. Phys.")
+    ("MSMSE" "Modelling and Simulation in Materials Science and Engineering"
+     "Modell. Simul. Mater. Sci. Eng.")
+    ("TSF" "Thin Solid Films" "Thin Solid Films")
+    ("TC" "Topics in Catalysis" "Top. Catal.")
+    ("WR" "Water Research" "Water Res."))
+  "List of (string journal-full-name journal-abbreviation). Find
+  new abbreviations at http://cassi.cas.org/search.jsp."
+  :type '(list (repeat (list string string)))
+  :group 'org-ref-bibtex)
+
+
+(defcustom org-ref-title-case-types '(("article" . ("title"))
+                                     ("book" . ("booktitle")))
+
+  "An a-list of bibtex entry types and fields that will be converted to
+title-case by org-ref-title-case."
+  :type '(repeat string)
+  :group 'org-ref-bibtex)
+
+
+(defcustom org-ref-bibtex-pdf-download-dir
+  (cond
+   ((stringp bibtex-completion-library-path)
+    bibtex-completion-library-path)
+   (t
+    (car bibtex-completion-library-path)))
+  "Default directory to look for downloaded pdfs.
+Used in `org-ref-bibtex-assoc-pdf-with-entry' when looking for a
+PDF to associate with an entry. Defaults to the first entry in
+`bibtex-completion-library-path'."
+  :group 'org-ref-bibtex
+  :type 'directory)
+
+
+;; * Modifying journal titles
+;;;###autoload
+(defun org-ref-bibtex-generate-longtitles ()
+  "Generate longtitles.bib which are @string definitions.
+The full journal names are in `org-ref-bibtex-journal-abbreviations'."
+  (interactive)
+  (with-temp-file "longtitles.bib"
+    (dolist (row org-ref-bibtex-journal-abbreviations)
+      (insert (format "@string{%s=\"%s\"}\n"
+                      (nth 0 row)
+                      (nth 1 row))))))
+
+
+;;;###autoload
+(defun org-ref-bibtex-generate-shorttitles ()
+  "Generate shorttitles.bib which are @string definitions.
+The abbreviated journal names in `org-ref-bibtex-journal-abbreviations'."
+  (interactive)
+  (with-temp-file "shorttitles.bib"
+    (dolist (row org-ref-bibtex-journal-abbreviations)
+      (insert (format "@string{%s=\"%s\"}\n"
+                      (nth 0 row)
+                      (nth 2 row))))))
+
+
+;;;###autoload
+(defun org-ref-stringify-journal-name (&optional key start end)
+  "Replace journal name in a bibtex entry with a string.
+The strings are defined in
+`org-ref-bibtex-journal-abbreviations'.  The optional arguments KEY,
+START and END allow you to use this with `bibtex-map-entries'"
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (when
+      (string= "article"
+               (downcase
+                (cdr (assoc "=type=" (bibtex-parse-entry)))))
+    (let* ((full-names (mapcar
+                        (lambda (row)
+                          (cons  (nth 1 row) (nth 0 row)))
+                        org-ref-bibtex-journal-abbreviations))
+           (abbrev-names (mapcar
+                          (lambda (row)
+                            (cons  (nth 2 row) (nth 0 row)))
+                          org-ref-bibtex-journal-abbreviations))
+           (journal (s-trim (bibtex-autokey-get-field "journal")))
+           (bstring (or
+                     (cdr (assoc journal full-names))
+                     (cdr (assoc journal abbrev-names)))))
+      (when bstring
+        (bibtex-set-field "journal" bstring t)
+        (bibtex-fill-entry)))))
+
+
+;;;###autoload
+(defun org-ref-set-journal-string (full-journal-name)
+  "Set a bibtex journal name to the string that represents FULL-JOURNAL-NAME.
+This is defined in `org-ref-bibtex-journal-abbreviations'."
+  (interactive (list
+                (completing-read
+                 "Journal: "
+                 (mapcar
+                  (lambda (x)
+                    (nth 1 x))
+                  org-ref-bibtex-journal-abbreviations))))
+  ;; construct data alist for the string lookup.
+  (let ((alist (mapcar
+                (lambda (x)
+                  (cons (nth 1 x) (nth 0 x)))
+                org-ref-bibtex-journal-abbreviations)))
+    (bibtex-set-field "journal" (cdr (assoc full-journal-name alist)) t)
+    (bibtex-fill-entry)
+    (bibtex-clean-entry)))
+
+;;* Non-ascii character replacement
+
+;;;###autoload
+(defun org-ref-replace-nonascii ()
+  "Replace non-ascii characters with LaTeX representations in a
+bibtex entry."
+  (interactive)
+  (save-restriction
+    (bibtex-narrow-to-entry)
+    (goto-char (point-min))
+    (dolist (char (mapcar (lambda (x)
+                           (car x))
+                         org-ref-nonascii-latex-replacements))
+      (while (re-search-forward char nil t)
+        (replace-match (cdr (assoc char org-ref-nonascii-latex-replacements))))
+      (goto-char (point-min)))))
+
+
+;;* Title case transformations
+(defvar org-ref-lower-case-words
+  '("a" "an" "on" "and" "for"
+    "the" "of" "in")
+  "List of words to keep lowercase when changing case in a title.")
+
+
+;;;###autoload
+(defun org-ref-title-case (&optional key start end)
+  "Convert a bibtex entry title and booktitle to title-case.
+Convert only if the entry type is a member of the list
+`org-ref-title-case-types'. The arguments KEY, START and END are
+optional, and are only there so you can use this function with
+`bibtex-map-entries' to change all the title entries in articles and
+books."
+  (interactive)
+  (save-restriction
+    (bibtex-narrow-to-entry)
+    (bibtex-beginning-of-entry)
+    (let* ((entry-type (downcase (cdr (assoc "=type=" (bibtex-parse-entry)))))
+          (fields (cdr (assoc entry-type org-ref-title-case-types)))
+          ;; temporary variables
+          title words)
+      (when fields
+       (cl-loop for field in fields
+                when (bibtex-autokey-get-field field)
+                do
+                (setq title (bibtex-autokey-get-field field)
+                      words (split-string title)
+                      start 0)
+                (setq words (mapcar
+                             (lambda (word)
+                               (cond
+                                ;; words containing more than one . are probably
+                                ;; abbreviations. We do not change those.
+                                ((with-temp-buffer
+                                   (insert word)
+                                   (goto-char (point-min))
+                                   (> (count-matches "\\.") 1))
+                                 word)
+                                ;; match words containing {} or \ which are probably
+                                ;; LaTeX or protected words, ignore
+                                ((string-match "\\$\\|{\\|}\\|(\\|)\\|\\\\" word)
+                                 word)
+                                ;; these words should not be capitalized, unless they
+                                ;; are the first word
+                                ((-contains? org-ref-lower-case-words
+                                             (s-downcase word))
+                                 (s-downcase word))
+                                ;; Words that are quoted
+                                ((s-starts-with? "\"" word)
+                                 (concat "\"" (s-capitalize (substring word 1))))
+                                (t
+                                 (s-capitalize word))))
+                             words))
+
+                ;; Check if first word should be capitalized
+                (when (-contains? org-ref-lower-case-words (car words))
+                  (setf (car words) (s-capitalize (car words))))
+
+                (setq title (mapconcat 'identity words " "))
+
+                ;; Capitalize letters after a dash
+                (while
+                    (string-match "[a-zA-Z]-\\([a-z]\\)" title start)
+                  (let ((char (substring title (match-beginning 1) (match-end 1))))
+                    (setf (substring title (match-beginning 1) (match-end 1))
+                          (format "%s" (upcase char)))
+                    (setq start (match-end 1))))
+
+                ;; this is defined in doi-utils
+                (bibtex-set-field
+                 field
+                 title)
+                (bibtex-fill-entry))))))
+
+
+;;;###autoload
+(defun org-ref-title-case-article (&optional key start end)
+  "Convert a bibtex entry article or book title to title-case.
+The arguments KEY, START and END are optional, and are only there
+so you can use this function with `bibtex-map-entries' to change
+all the title entries in articles and books."
+  (interactive)
+  (let ((org-ref-title-case-types '(("article" . ("title")))))
+    (org-ref-title-case)))
+
+
+;;;###autoload
+(defun org-ref-sentence-case-article (&optional key start end)
+  "Convert a bibtex entry article title to sentence-case.
+The arguments KEY, START and END are optional, and are only there
+so you can use this function with `bibtex-map-entries' to change
+all the title entries in articles."
+  (interactive)
+  (bibtex-beginning-of-entry)
+
+  (let* ((title (bibtex-autokey-get-field "title"))
+         (words (split-string title))
+         (start 0))
+    (when
+        (string= "article"
+                (downcase
+                 (cdr (assoc "=type="
+                             (bibtex-parse-entry)))))
+      (setq words (mapcar
+                   (lambda (word)
+                     (if
+                         ;; match words containing {} or \ which are probably
+                         ;; LaTeX or protected words
+                         (string-match "\\$\\|{\\|}\\|\\\\" word)
+                         word
+                       (s-downcase word)))
+                   words))
+
+      ;; capitalize first word
+      (setf (car words) (s-capitalize (car words)))
+
+      ;; join the words
+      (setq title (mapconcat 'identity words " "))
+
+      ;; capitalize a word after a :, eg. a subtitle, and protect it
+      (while
+          (string-match "[a-z]:\\s-+\\([A-Z]\\)" title start)
+        (let ((char (substring title (match-beginning 1) (match-end 1))))
+          (setf (substring title (match-beginning 1) (match-end 1))
+                (format "%s" (upcase char)))
+          (setq start (match-end 1))))
+
+      ;; this is defined in doi-utils
+      (bibtex-set-field "title" title)
+
+      ;; clean and refill entry so it looks nice
+      (bibtex-clean-entry)
+      (bibtex-fill-entry))))
+
+
+;;* Navigation in bibtex file
+;;;###autoload
+(defun org-ref-bibtex-next-entry (&optional n)
+  "Jump to the beginning of the next bibtex entry.
+N is a prefix argument.  If it is numeric, jump that many entries
+forward.  Negative numbers do nothing."
+  (interactive "P")
+  ;; Note if we start at the beginning of an entry, nothing
+  ;; happens. We need to move forward a char, and call again.
+  (when (= (point) (save-excursion
+                     (bibtex-beginning-of-entry)))
+    (forward-char)
+    (org-ref-bibtex-next-entry))
+
+  ;; search forward for an entry
+  (when
+      (re-search-forward bibtex-entry-head nil t (and (numberp n) n))
+    ;; go to beginning of the entry
+    (bibtex-beginning-of-entry)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-previous-entry (&optional n)
+  "Jump to beginning of the previous bibtex entry.
+N is a prefix argument.  If it is numeric, jump that many entries back."
+  (interactive "P")
+  (bibtex-beginning-of-entry)
+  (when
+      (re-search-backward bibtex-entry-head nil t (and (numberp n) n))
+    (bibtex-beginning-of-entry)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-visible-entry ()
+  "Jump to visible entry."
+  (interactive)
+  (avy-with avy-ve
+    (avy-process
+     (save-excursion
+       (goto-char (window-start))
+       (let ((positions ()))
+        (while (re-search-forward "^@.*{" (window-end) t)
+          (push (match-beginning 0) positions))
+        (reverse positions))))
+    (avy--style-fn avy-style)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-visible-field ()
+  "Jump to visible field."
+  (interactive)
+  (avy-with avy-vf
+    (avy-process
+     (save-excursion
+       (goto-char (window-start))
+       (let ((positions ()))
+        (while (re-search-forward ".*=\\s-*." (window-end) t)
+          (push (match-end 0) positions))
+        (reverse positions))))
+    (avy--style-fn avy-style)))
+
+
+(defun org-ref-bibtex-mode-keys ()
+  "Modify keymaps used by `bibtex-mode'."
+  (local-set-key (kbd "M-n") 'org-ref-bibtex-next-entry)
+  (local-set-key (kbd "M-p") 'org-ref-bibtex-previous-entry))
+
+;; add to bibtex-mode-hook
+(add-hook 'bibtex-mode-hook 'org-ref-bibtex-mode-keys)
+
+;;* Functions to act on an entry with a doi
+
+(defun org-ref-bibtex-entry-doi ()
+  "Get doi from entry at point."
+  (save-excursion
+    (bibtex-beginning-of-entry)
+    (when (not (looking-at bibtex-any-valid-entry-type))
+      (error "This entry does not appear to be a valid type."))
+    (let ((entry (bibtex-parse-entry t)))
+      (when (null entry)
+       (error "Unable to parse this bibtex entry."))
+      (cdr (assoc "doi" entry)))))
+
+;; function that ensures that the url field of a bibtex entry is the
+;; properly-formatted hyperlink of the DOI. See
+;; http://blog.crossref.org/2016/09/new-crossref-doi-display-guidelines.html
+;; for more information.
+;;;###autoload
+(defun org-ref-bibtex-format-url-if-doi ()
+  "Hook function to format url to follow the current DOI conventions."
+  (interactive)
+  ;; Don't overwrite an existing url field though.
+  (unless (bibtex-autokey-get-field "url")
+    (if (eq (org-ref-bibtex-entry-doi) "") nil
+      (let ((front-url "https://doi.org/")
+            (doi (org-ref-bibtex-entry-doi)))
+       (bibtex-set-field "url"
+                          (concat front-url doi))))))
+
+
+;;;###autoload
+(defun org-ref-bibtex-wos ()
+  "Open bibtex entry in Web Of Science if there is a DOI."
+  (interactive)
+  (doi-utils-wos (org-ref-bibtex-entry-doi)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-wos-citing ()
+  "Open citing articles for bibtex entry in Web Of Science if
+there is a DOI."
+  (interactive)
+  (doi-utils-wos-citing (org-ref-bibtex-entry-doi)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-wos-related ()
+  "Open related articles for bibtex entry in Web Of Science if
+there is a DOI."
+  (interactive)
+  (doi-utils-wos-related (org-ref-bibtex-entry-doi)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-crossref ()
+  "Open the bibtex entry in Crossref by its doi."
+  (interactive)
+  (doi-utils-crossref (org-ref-bibtex-entry-doi)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-google-scholar ()
+  "Open the bibtex entry at point in google-scholar by its doi."
+  (interactive)
+  (let ((doi (org-ref-bibtex-entry-doi)))
+    (doi-utils-google-scholar
+     (if (string= "" doi)
+        (save-excursion
+          (bibtex-beginning-of-entry)
+          (cdr (assoc "title" (bibtex-parse-entry t))))
+       doi))))
+
+
+;;;###autoload
+(defun org-ref-bibtex-pubmed ()
+  "Open the bibtex entry at point in Pubmed by its doi."
+  (interactive)
+  (doi-utils-pubmed (org-ref-bibtex-entry-doi)))
+
+
+;;;###autoload
+(defun org-ref-bibtex-pdf (&optional _)
+  "Open the pdf for the bibtex entry at point.
+Thin wrapper to get `org-ref-bibtex' to open pdf, because it
+calls functions with a DOI argument."
+  (interactive)
+  (org-ref-open-bibtex-pdf))
+
+
+(defun org-ref-bibtex-get-file-move-func (prefix)
+  "Determine whether to use `rename-file' or `copy-file' for `org-ref-bibtex-assoc-pdf-with-entry'.
+When called with a PREFIX argument,
+`org-ref-bibtex-assoc-pdf-with-entry-move-function' switches to the
+opposite function from that which is defined in
+`org-ref-assoc-pdf-with-entry-move-function'."
+  (message (format "%s" prefix))
+  (if (eq prefix nil)
+      org-ref-bibtex-assoc-pdf-with-entry-move-function
+    (if (eq org-ref-bibtex-assoc-pdf-with-entry-move-function 'rename-file)
+       'copy-file
+      'rename-file)))
+
+
+(defvar bibtex-completion-library-path)
+(declare-function bibtex-completion-find-pdf-in-library "bibtex-completion")
+
+
+;;;###autoload
+(defun org-ref-bibtex-assoc-pdf-with-entry (&optional prefix)
+  "Prompt for pdf associated with entry at point and rename it.
+Check whether a pdf already exists in `bibtex-completion-library' with the
+name '[bibtexkey].pdf'. If the file does not exist, rename it to
+'[bibtexkey].pdf' using
+`org-ref-bibtex-assoc-pdf-with-entry-move-function' and place it in
+a directory. Optional PREFIX argument toggles between
+`rename-file' and `copy-file'."
+  (interactive "P")
+  (save-excursion
+    (bibtex-beginning-of-entry)
+    (let* ((file (read-file-name
+                 "Select file associated with entry: "
+                 org-ref-bibtex-pdf-download-dir))
+          (bibtex-expand-strings t)
+           (entry (bibtex-parse-entry t))
+           (key (cdr (assoc "=key=" entry)))
+          (file-move-func (org-ref-bibtex-get-file-move-func prefix))
+          pdf)
+      (if (bibtex-completion-find-pdf-in-library key)
+         (message (format "A file named %s already exists" (bibtex-completion-find-pdf-in-library key)))
+       (setq pdf (expand-file-name (concat key ".pdf") (cond
+                                                        ((stringp bibtex-completion-library-path)
+                                                         bibtex-completion-library-path)
+                                                        ((and (listp bibtex-completion-library-path)
+                                                              (= 1 (length bibtex-completion-library-path)))
+                                                         (car bibtex-completion-library-path))
+                                                        (t
+                                                         (completing-read "Dir: " bibtex-completion-library-path)))))
+       (funcall file-move-func file pdf)
+       (message (format "Created file %s" pdf))))))
+
+
+;;* Hydra menus
+;;** Hydra menu for bibtex entries
+;; hydra menu for actions on bibtex entries
+(defhydra org-ref-bibtex-hydra (:color blue :hint nil)
+  "Bibtex actions:
+"
+  ;; Open-like actions
+  ("p" org-ref-open-bibtex-pdf "PDF" :column "Open")
+  ("n" org-ref-open-bibtex-notes "Notes" :column "Open")
+  ("b" org-ref-open-in-browser "URL" :column "Open")
+
+  ;; edit/modify
+  ("K" (lambda ()
+         (interactive)
+         (org-ref-set-bibtex-keywords
+          (read-string "Keywords: "
+                       (bibtex-autokey-get-field "keywords"))
+          t))
+   "Keywords" :column "Edit")
+  ("a" org-ref-replace-nonascii "Replace nonascii" :column "Edit")
+  ("s" org-ref-sort-bibtex-entry "Sort fields" :column "Edit")
+  ("T" org-ref-title-case-article "Title case" :column "Edit")
+  ("S" org-ref-sentence-case-article "Sentence case" :column "Edit")
+  ("U" (doi-utils-update-bibtex-entry-from-doi (org-ref-bibtex-entry-doi)) "Update entry" :column "Edit")
+  ("u" doi-utils-update-field "Update field" :column "Edit" :color red)
+  ("<backspace>" (cl--set-buffer-substring (line-beginning-position) (+ 1 (line-end-position)) "")
+   "Delete line" :column "Edit" :color red)
+  ("d" bibtex-kill-entry "Kill entry" :column "Edit")
+  ("L" org-ref-clean-bibtex-entry "Clean entry" :column "Edit")
+  ("A" org-ref-bibtex-assoc-pdf-with-entry "Add pdf" :column "Edit")
+  ("r" (lambda ()
+        (interactive)
+         (bibtex-beginning-of-entry)
+         (bibtex-kill-entry)
+         (find-file (completing-read
+                     "Bibtex file: "
+                    (append bibtex-completion-bibliography
+                            (f-entries "." (lambda (f) (f-ext? f "bib"))))))
+         (goto-char (point-max))
+         (bibtex-yank)
+         (save-buffer)
+         (kill-buffer))
+   "Refile entry" :column "Edit")
+
+  ;; www
+  ("P" org-ref-bibtex-pubmed "Pubmed" :column "WWW")
+  ("w" org-ref-bibtex-wos "WOS" :column "WWW")
+  ("c" org-ref-bibtex-wos-citing "WOS citing" :column "WWW")
+  ("a" org-ref-bibtex-wos-related "WOS related" :column "WWW")
+  ("R" org-ref-bibtex-crossref "Crossref" :column "WWW")
+  ("g" org-ref-bibtex-google-scholar "Google Scholar" :column "WWW")
+  ("e" org-ref-email-bibtex-entry "Email" :column "WWW")
+
+
+  ;; Copy
+  ("o" (lambda ()
+        (interactive)
+        (bibtex-copy-entry-as-kill)
+        (message "Use %s to paste the entry"
+                 (substitute-command-keys (format "\\[bibtex-yank]"))))
+   "Copy entry" :column "Copy")
+
+  ("y" (save-excursion
+        (bibtex-beginning-of-entry)
+        (when (looking-at bibtex-entry-maybe-empty-head)
+          (kill-new (bibtex-key-in-head))))
+   "Copy key" :column "Copy")
+
+  ("f" (save-excursion
+        (bibtex-beginning-of-entry)
+        (kill-new (bibtex-completion-apa-format-reference
+                   (cdr (assoc "=key=" (bibtex-parse-entry t))))))
+   "Formatted entry" :column "Copy")
+
+  ;; Navigation
+  ("[" org-ref-bibtex-next-entry "Next entry" :column "Navigation" :color red)
+  ("]" org-ref-bibtex-previous-entry "Previous entry" :column "Navigation" :color red)
+  ("<down>" next-line "Next line" :column "Navigation" :color red)
+  ("<up>" previous-line "Previous line" :column "Navigation" :color red)
+  ("<next>" scroll-up-command "Scroll up" :column "Navigation" :color red)
+  ("<prior>" scroll-down-command "Scroll down" :column "Navigation" :color red)
+  ("v" org-ref-bibtex-visible-entry "Visible entry" :column "Navigation" :color red)
+  ("V" org-ref-bibtex-visible-field "Visible field" :column "Navigation" :color red)
+
+
+  ;; Miscellaneous
+  ("F" org-ref-bibtex-file/body "File hydra" :column "Misc")
+  ("N" org-ref-bibtex-new-entry/body "New entry" :column "Misc")
+  ("q" nil))
+
+
+(declare-function biblio-lookup "biblio")
+(declare-function arxiv-add-bibtex-entry "org-ref-arxiv")
+(declare-function doi-insert-bibtex "doi-utils")
+
+;;** Hydra menu for new bibtex entries
+;; A hydra for adding new bibtex entries.
+(defhydra org-ref-bibtex-new-entry (:color blue)
+  "New Bibtex entry:"
+  ("d" doi-insert-bibtex "from DOI" :column "Automatic")
+  ("c" crossref-add-bibtex-entry "from Crossref" :column "Automatic")
+  ("a" arxiv-add-bibtex-entry "From Arxiv" :column "Automatic")
+  ("b" biblio-lookup "From biblio" :column "Automatic")
+  ;; Bibtex types
+  ("ma" bibtex-Article "Article" :column "Manual")
+  ("mb" bibtex-Book "Book" :column "Manual")
+  ("mi" bibtex-InBook "In book" :column "Manual")
+  ("ml" bibtex-Booklet "Booklet" :column "Manual")
+  ("mP" bibtex-Proceedings "Proceedings" :column "Manual")
+  ("mp" bibtex-InProceedings "In proceedings" :column "Manual")
+  ("mm" bibtex-Misc "Misc." :column "Manual")
+  ("mM" bibtex-Manual "Manual" :column "Manual")
+  ("mT" bibtex-PhdThesis "PhD Thesis" :column "Manual")
+  ("mt" bibtex-MastersThesis "MS Thesis" :column "Manual")
+  ("mR" bibtex-TechReport "Report" :column "Manual")
+  ("mu" bibtex-Unpublished "unpublished" :column "Manual")
+  ("mc" bibtex-InCollection "Article in collection" :column "Manual")
+  ("q" nil "quit"))
+
+
+;;** Hydra menu of functions to act on a bibtex file.
+(defhydra org-ref-bibtex-file (:color blue)
+  "Bibtex file functions: "
+  ("v" bibtex-validate "Validate entries")
+  ("s" bibtex-sort-buffer "Sort entries")
+  ("r" bibtex-reformat "Reformat entries")
+  ("c" bibtex-count-entries "Count entries")
+  ("p" org-ref-build-full-bibliography "PDF bibliography"))
+
+
+;;* Email a bibtex entry
+(declare-function bibtex-completion-find-pdf "bibtex-completion")
+
+;;;###autoload
+(defun org-ref-email-bibtex-entry ()
+  "Email current bibtex entry at point and pdf if it exists."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (let* ((key (cdr (assoc "=key=" (bibtex-parse-entry t))))
+        (pdfs (bibtex-completion-find-pdf key)))
+
+    (bibtex-copy-entry-as-kill)
+    (compose-mail)
+    (message-goto-body)
+    (insert (pop bibtex-entry-kill-ring))
+    (message-goto-subject)
+    (insert key)
+    (cl-loop for pdf in pdfs do (mml-attach-file pdf))
+    (message-goto-to)
+    ;; I am not sure why I have to put an empty string here, but it prevents a
+    ;; bell error.
+    ""))
+
+;;* org-ref bibtex keywords
+;; adapted from bibtex-utils.el
+;; these are candidates for selecting keywords/tags
+(defun org-ref-bibtex-keywords ()
+  "Get keywords defined in current bibtex file.
+These are in the keywords field, and are comma or semicolon separated."
+  (save-excursion
+    (goto-char (point-min))
+    (let (keywords kstring)
+      (while (re-search-forward "^\\s-*keywords.*{\\([^}]+\\)}" nil t)
+        ;; TWS - remove newlines/multiple spaces:
+        (setq kstring (replace-regexp-in-string
+                      "[ \t\n]+" " "
+                      (match-string 1)))
+        (mapc
+         (lambda (v)
+           (add-to-list 'keywords v t))
+         (split-string kstring "\\(,\\|;\\)[ \n]*\\|{\\|}" t)))
+      keywords)))
+
+
+;;;###autoload
+(defun org-ref-set-bibtex-keywords (keywords &optional arg)
+  "Add KEYWORDS to a bibtex entry.
+If KEYWORDS is a list, it is converted to a comma-separated
+string.  The KEYWORDS are added to the beginning of the
+field.  Otherwise KEYWORDS should be a string of comma-separate
+keywords.  Optional argument ARG prefix arg to replace keywords."
+  (interactive
+   (list
+    (completing-read "Keyword: " (org-ref-bibtex-keywords))
+    current-prefix-arg))
+  (bibtex-set-field
+   "keywords"
+   (if arg
+       ;; replace with arg
+       (if (listp keywords)
+           (mapconcat 'identity keywords ", ")
+         keywords)
+     ;; else concatenate
+     (concat
+      (if (listp keywords)
+          (mapconcat 'identity keywords ", ")
+        keywords)
+      (when (not (string= "" (bibtex-autokey-get-field "keywords")))
+        (concat ", "  (bibtex-autokey-get-field "keywords"))))))
+  (when (buffer-file-name)
+    (save-buffer)))
+
+
+(defun org-ref-save-all-bibtex-buffers ()
+  "Save all bibtex-buffers."
+  (cl-loop for buffer in (buffer-list)
+          do
+          (with-current-buffer buffer
+            (when (and (buffer-file-name) (f-ext? (buffer-file-name) "bib"))
+              (save-buffer)))))
+
+
+;; * Extract bibtex blocks from an org-file
+
+;;;###autoload
+(defun org-ref-extract-bibtex-blocks (bibfile)
+  "Extract all bibtex blocks in buffer to BIBFILE.
+If BIBFILE exists, append, unless you use a prefix arg (C-u), which
+will clobber the file."
+  (interactive
+   (list (read-file-name "Bibfile: " nil nil nil
+                        (file-name-nondirectory
+                         (concat (file-name-sans-extension
+                                  (buffer-file-name))
+                                 ".bib")))))
+
+  (let ((contents ""))
+    (when (and (file-exists-p bibfile)
+              (not current-prefix-arg))
+      (setq contents (with-temp-buffer
+                      (insert-file-contents bibfile)
+                      (buffer-string))))
+
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward "#\\+BEGIN_SRC bibtex" nil t)
+       (setq contents
+             (concat
+              contents
+              (org-element-property :value (org-element-at-point))))))
+
+    (with-temp-file bibfile
+      (insert contents))))
+
+
+;;** create text citations from a bibtex entry
+(declare-function bibtex-completion-apa-format-reference "bibtex-completion")
+(declare-function bibtex-completion-get-key-bibtex "bibtex-completion")
+
+(defun org-ref-bib-citation ()
+  "From a bibtex entry, create and return a lightly formatted citation string."
+  (bibtex-completion-apa-format-reference (list (bibtex-completion-get-key-bibtex))))
+
+
+;;** Open pdf in bibtex entry
+(declare-function bibtex-completion-open-pdf "bibtex-completion")
+;;;###autoload
+(defun org-ref-open-bibtex-pdf ()
+  "Open pdf for a bibtex entry, if it exists."
+  (interactive)
+  (bibtex-completion-open-pdf (list (bibtex-completion-get-key-bibtex))))
+
+
+;;** Open notes from bibtex entry
+(declare-function bibtex-completion-edit-notes "bibtex-completion")
+
+;;;###autoload
+(defun org-ref-open-bibtex-notes ()
+  "From a bibtex entry, open the notes if they exist."
+  (interactive)
+  (bibtex-completion-edit-notes (list (bibtex-completion-get-key-bibtex))))
+
+
+;;** Open bibtex entry in browser
+(declare-function bibtex-completion-open-url-or-doi "bibtex-completion")
+
+;;;###autoload
+(defun org-ref-open-in-browser ()
+  "Open the bibtex entry at point in a browser using the url field or doi field."
+  (interactive)
+  (bibtex-completion-open-url-or-doi (list (bibtex-completion-get-key-bibtex))))
+
+
+;;** Build a pdf of the bibtex file
+;;;###autoload
+(defun org-ref-build-full-bibliography ()
+  "Build pdf of all bibtex entries, and open it."
+  (interactive)
+  (let* ((bibfile (file-name-nondirectory (buffer-file-name)))
+         (bib-base (file-name-sans-extension bibfile))
+         (texfile (concat bib-base ".tex"))
+         (pdffile (concat bib-base ".pdf")))
+    (find-file texfile)
+    (erase-buffer)
+    (insert (format "\\documentclass[12pt]{article}
+\\usepackage[version=3]{mhchem}
+\\usepackage{url}
+\\usepackage[numbers]{natbib}
+\\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue, pdfstartview=FitH]{hyperref}
+\\usepackage{doi}
+\\begin{document}
+\\nocite{*}
+\\bibliographystyle{unsrtnat}
+\\bibliography{%s}
+\\end{document}" bib-base))
+    (save-buffer)
+    (shell-command (concat "pdflatex " bib-base))
+    (shell-command (concat "bibtex " bib-base))
+    (shell-command (concat "pdflatex " bib-base))
+    (shell-command (concat "pdflatex " bib-base))
+    (kill-buffer texfile)
+    (org-open-file pdffile)))
+
+
+;;** Sort fields in a bibtex entry
+;;;###autoload
+(defun org-ref-sort-bibtex-entry ()
+  "Sort fields of entry in standard order."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (let* ((entry (bibtex-parse-entry))
+         (entry-fields)
+         (other-fields)
+         (type (cdr (assoc "=type=" entry)))
+         (key (cdr (assoc "=key=" entry)))
+        (field-order (cdr (assoc (if type (downcase type))
+                                 org-ref-bibtex-sort-order))))
+
+    ;; these are the fields we want to order that are in this entry
+    (setq entry-fields (mapcar (lambda (x) (car x)) entry))
+    ;; we do not want to reenter these fields
+    (setq entry-fields (remove "=key=" entry-fields))
+    (setq entry-fields (remove "=type=" entry-fields))
+
+    ;;these are the other fields in the entry, and we sort them alphabetically.
+    (setq other-fields
+         (sort (-remove (lambda(x) (member x field-order)) entry-fields)
+               'string<))
+
+    (save-restriction
+      (bibtex-kill-entry)
+      (insert
+       (concat "@" type "{" key ",\n"
+              (mapconcat
+               (lambda (field)
+                 (when (member field entry-fields)
+                   (format "%s = %s,"
+                           field
+                           (cdr (assoc field entry)))))
+               field-order "\n")
+              ;; now add the other fields
+              (mapconcat
+               (lambda (field)
+                 (cl-loop for (f . v) in entry concat
+                          (when (string= f field)
+                            (format "%s = %s,\n" f v))))
+               (-uniq other-fields) "\n")
+              "\n}"))
+      (bibtex-find-entry key)
+      (bibtex-fill-entry)
+      (bibtex-clean-entry))))
+
+;; downcase entries
+;;;###autoload
+(defun org-ref-downcase-bibtex-entry ()
+  "Downcase the entry type and fields."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (let* ((entry (bibtex-parse-entry))
+         (entry-fields)
+         (type (downcase (cdr (assoc "=type=" entry))))
+         (key (cdr (assoc "=key=" entry))))
+
+    (setq entry-fields (mapcar (lambda (x) (car x)) entry))
+    ;; we do not want to reenter these fields
+    (setq entry-fields (remove "=key=" entry-fields))
+    (setq entry-fields (remove "=type=" entry-fields))
+
+    (bibtex-kill-entry)
+    (insert
+     (concat "@" (downcase type) "{" key ",\n"
+            (mapconcat
+             (lambda (field)
+               (format "%s = %s,"
+                       (downcase field)
+                       (cdr (assoc field entry))))
+             entry-fields "\n")
+            "\n}\n\n"))
+    (bibtex-find-entry key)
+    (bibtex-fill-entry)
+    (bibtex-clean-entry)))
+
+
+;;** Clean a bibtex entry
+;; These functions operate on a bibtex entry and "clean" it in some way.
+
+(defun orcb-clean-nil (arg)
+  "Remove nil from some article fields.
+The removal is conditional. Sometimes it is useful to have nil
+around, e.g. for ASAP articles where the fields are not defined
+yet but will be in the future.
+
+With \\[universal-argument], run `bibtex-clean-entry' after."
+  (interactive "P")
+  (bibtex-beginning-of-entry)
+  (let* ((entry (bibtex-parse-entry))
+         (type (downcase (cdr (assoc "=type=" entry)))))
+    (when (string= type "article")
+      (cond
+       ;; we have volume and pages but number is nil.
+       ;; remove the number field.
+       ((and (string= type "article")
+            (not (string= (cdr (assoc "volume" entry)) "{nil}"))
+            (not (string= (cdr (assoc "pages" entry)) "{nil}"))
+            (string= (cdr (assoc "number" entry)) "{nil}"))
+       (bibtex-set-field "number" "")
+       (if arg
+            (bibtex-clean-entry)))))))
+
+
+(defun orcb-clean-nil-opinionated ()
+  "Remove nil from all article fields.
+
+Note that by default, this will leave the entry empty, which may
+then get deleted by `bibtex-clean-entry.' To disable this
+behavior, remove opts-or-alts from `bibtex-entry-format'. This
+will leave the empty entries so that you may fill them in later."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (let* ((entry (bibtex-parse-entry))
+         (type (downcase (cdr (assoc "=type=" entry)))))
+    (when (string= type "article")
+      (cl-loop for (field . text) in entry do
+               (if (string= text "{nil}")
+                   (bibtex-set-field field ""))))))
+
+
+(defun orcb-clean-doi ()
+  "Remove http://dx.doi.org/ or https://doi.org in the doi field."
+  (let ((doi (bibtex-autokey-get-field "doi")))
+    (when (or (string-match "^http://dx.doi.org/" doi)
+             (string-match "^https://doi.org/" doi))
+      (setq doi (replace-match "" nil nil doi))
+      (bibtex-beginning-of-entry)
+      (goto-char (car (cdr (bibtex-search-forward-field "doi" t))))
+      (bibtex-kill-field)
+      (bibtex-make-field "doi")
+      (backward-char)
+      (insert doi))))
+
+
+(defun orcb-clean-year (&optional new-year)
+  "Fix years set to 0.
+If optional NEW-YEAR set it to that, otherwise prompt for it."
+  ;; asap articles often set year to 0, which messes up key
+  ;; generation. fix that.
+  (let ((year (bibtex-autokey-get-field "year")))
+    (when (string= "0" year)
+      (bibtex-beginning-of-entry)
+      (goto-char (car (cdr (bibtex-search-forward-field "year" t))))
+      (bibtex-kill-field)
+      (bibtex-make-field "year")
+      (backward-char)
+      (insert (or new-year (read-string "Enter year: "))))))
+
+
+(defun orcb-clean-pages ()
+  "Check for empty pages, and put eid in its place if it exists."
+  (let ((pages (bibtex-autokey-get-field "pages"))
+       (eid (bibtex-autokey-get-field "eid")))
+    (when (and (not (string= "" eid))
+              (or (string= "" pages)))
+      (bibtex-set-field "pages" eid))))
+
+
+(defun orcb-& ()
+  "Replace naked & with \& in a bibtex entry."
+  (save-restriction
+    (bibtex-narrow-to-entry)
+    (bibtex-beginning-of-entry)
+    (while (re-search-forward " & " nil t)
+      (replace-match " \\\\& "))))
+
+
+(defun orcb-% ()
+  "Replace naked % with % in a bibtex entry.
+Except when it is already escaped or in a URL. The replacement
+for the % is defined by `orcb-%-replacement-string'."
+  (save-restriction
+    (bibtex-narrow-to-entry)
+    (bibtex-beginning-of-entry)
+    (while (re-search-forward "\\([^\\]\\)%\\([^[:xdigit:]]\\)" nil t)
+      (replace-match (concat "\\1"
+                             orcb-%-replacement-string
+                             "\\2")))))
+
+
+(defun orcb-key-comma ()
+  "Make sure there is a comma at the end of the first line."
+  (bibtex-beginning-of-entry)
+  (end-of-line)
+  ;; some entries do not have a key or comma in first line. We check and add it,
+  ;; if needed.
+  (unless (string-match ", *$" (thing-at-point 'line))
+    (end-of-line)
+    (insert ",")))
+
+
+(defun orcb-key (&optional allow-duplicate-keys)
+  "Replace the key in the entry.
+Prompts for replacement if the new key duplicates one already in
+the file, unless ALLOW-DUPLICATE-KEYS is non-nil."
+  (let ((key (funcall org-ref-clean-bibtex-key-function
+                     (bibtex-generate-autokey))))
+    ;; remove any \\ in the key
+    (setq key (replace-regexp-in-string "\\\\" "" key))
+    ;; first we delete the existing key
+    (bibtex-beginning-of-entry)
+    (re-search-forward bibtex-entry-maybe-empty-head)
+    (if (match-beginning bibtex-key-in-head)
+       (delete-region (match-beginning bibtex-key-in-head)
+                      (match-end bibtex-key-in-head)))
+    ;; check if the key is in the buffer
+    (when (and (not allow-duplicate-keys)
+               (save-excursion
+                 (bibtex-search-entry key)))
+      (save-excursion
+       (bibtex-search-entry key)
+       (bibtex-copy-entry-as-kill)
+       (switch-to-buffer-other-window "*duplicate entry*")
+       (bibtex-yank))
+      (setq key (bibtex-read-key "Duplicate Key found, edit: " key)))
+
+    (insert key)
+    (kill-new key)))
+
+
+(defun orcb-check-journal ()
+  "Check entry at point to see if journal exists in `org-ref-bibtex-journal-abbreviations'.
+If not, issue a warning."
+  (interactive)
+  (when
+      (string= "article"
+               (downcase
+                (cdr (assoc "=type=" (bibtex-parse-entry)))))
+    (save-excursion
+      (bibtex-beginning-of-entry)
+      (let* ((entry (bibtex-parse-entry t))
+             (journal (cdr (assoc "journal" entry))))
+        (when (null journal)
+          (warn "Unable to get journal for this entry."))
+        (unless (member journal (-flatten org-ref-bibtex-journal-abbreviations))
+          (message "Journal \"%s\" not found in org-ref-bibtex-journal-abbreviations." journal))))))
+
+
+(defun orcb-fix-spacing ()
+  "Delete whitespace and fix spacing between entries."
+  (let (beg end)
+    (save-excursion
+      (save-restriction
+       (widen)
+       (bibtex-beginning-of-entry)
+       (setq beg (point))
+       (bibtex-end-of-entry)
+       (setq end (if (re-search-forward bibtex-any-entry-maybe-empty-head nil t)
+                     (progn (beginning-of-line)
+                            (point))
+                   (point-max)))
+       ;; 1. delete whitespace
+       (narrow-to-region beg end)
+       (delete-trailing-whitespace)
+       ;; 2. delete consecutive empty lines
+       (goto-char end)
+       (while (re-search-backward "\n\n\n+" nil 'move)
+         (replace-match "\n\n"))
+       ;; 3. add one line between entries
+       (goto-char end)
+       (forward-line -1)
+       (when (looking-at "[}][ \t]*\\|@Comment.+\\|%.+")
+         (end-of-line)
+         (newline))))))
+
+
+(defun orcb-download-pdf ()
+  "Try to get the pdf in an entry."
+  ;; try to get pdf
+  (when doi-utils-download-pdf
+    (if doi-utils-async-download
+       (doi-utils-async-download-pdf)
+      (doi-utils-get-bibtex-entry-pdf))))
+
+
+(defun orcb-clean-<>-tags ()
+  "Try removing <tags> from the entry."
+  (sgml-mode)
+  (ignore-errors
+    (while (sgml-skip-tag-forward 1)
+      (sgml-skip-tag-backward 1)
+      (sgml-delete-tag 1)))
+  (bibtex-mode))
+
+
+;;;###autoload
+(defun org-ref-clean-bibtex-entry ()
+  "Clean and replace the key in a bibtex entry.
+See functions in `org-ref-clean-bibtex-entry-hook'."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (bibtex-narrow-to-entry)
+      (bibtex-beginning-of-entry)
+      ;; run hooks. each of these operates on the entry with no arguments.
+      ;; this did not work like  i thought, it gives a symbolp error.
+      ;; (run-hooks org-ref-clean-bibtex-entry-hook)
+      (mapc (lambda (x)
+             (save-restriction
+               (save-excursion
+                 (funcall x))))
+           org-ref-clean-bibtex-entry-hook))))
+
+
+;; * Missing functions in bibtex-completion
+;; I couldn't find these, and they seem useful.
+
+(defun org-ref-bibtex-get-entry (key)
+  "Return a parsed bibtex entry."
+  (save-window-excursion
+    (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
+      (bibtex-completion-show-entry (list key))
+      (bibtex-beginning-of-entry)
+      (bibtex-parse-entry))))
+
+
+(defun org-ref-bibtex-get-entry-value (key field)
+  "For the entry associated with KEY get the FIELD value."
+  (cdr (assoc field (org-ref-bibtex-get-entry key))))
+
+
+(defun org-ref-get-citation-year (key)
+  "Get the year of an entry with KEY.  Return year as a string."
+  (org-ref-bibtex-get-entry-value key "year"))
+
+
+;;* The end
+(provide 'org-ref-bibtex)
+
+;;; org-ref-bibtex.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-citation-links.el b/elpa/org-ref-20230507.1420/org-ref-citation-links.el
new file mode 100644 (file)
index 0000000..8c6e0c8
--- /dev/null
@@ -0,0 +1,1392 @@
+;;; org-ref-citation-links.el --- citation links for org-ref -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; This library provides hyper-functional citation links. These links can
+;; contain common pre/post notes, and multiple citation keys that each have
+;; their own pre/postnotes.
+;;
+;; These links are fontified to indicate if the citation keys are valid, and to
+;; indicate the pre/post-note structure. They also have tooltips that show
+;; information from the bibtex entry.
+;;
+;; Each link is functional, and clicking on one will open a hydra menu
+;; `org-ref-citation-hydra/body' of actions that range from opening the bibtex
+;; entry, notes, pdf or associated URL, to searching the internet for related
+;; articles.
+;;
+;; Each citation link also has a local keymap on it, which provides keyboard
+;; shortcuts for some actions like sorting, rearranging and navigating citation
+;; links. See `org-ref-cite-keymap' for the key bindings.
+;;
+;; Each link exports to a corresponding LaTeX citation command, or can be
+;; rendered with CSL for other kinds of exports like HTML, markdown, or ODT.
+;;
+;; This library also provides a minimal set of insertion functions that use
+;; completion. You can also use the org link completion mechanism to insert a
+;; citation.
+;;
+;; natmove like preprocessing is provided with `org-ref-cite-natmove'.
+;;
+;;; Code:
+
+(require 'hydra)
+(require 'xref)
+(eval-when-compile (require 'subr-x))
+
+(defgroup org-ref-faces nil
+  "A group for faces in `org-ref'."
+  :group 'org-ref-faces)
+
+
+(defface org-ref-cite-face
+  `((t (:inherit org-link
+                 :foreground "forest green")))
+  "Color for cite-like links in org-ref."
+  :group 'org-ref-faces)
+
+
+(defface org-ref-bad-cite-key-face
+  `((t (:inherit org-ref-cite-face
+                :foreground "red")))
+  "Color for bad cite keys in org-ref."
+  :group 'org-ref-faces)
+
+
+(defface org-ref-cite-global-prefix/suffix-face
+  `((t (:inherit org-ref-cite-face :weight bold)))
+  "Face for global prefix/suffix in a cite link."
+  :group 'org-ref-faces)
+
+
+(defface org-ref-cite-&-face
+  `((t (:inherit org-ref-cite-face :weight bold)))
+  "Face for the starting & in a cite key."
+  :group 'org-ref-faces)
+
+
+(defface org-ref-cite-local-prefix/suffix-face
+  `((t (:inherit org-ref-cite-face :slant italic)))
+  "Face for local prefix/suffix in a cite link."
+  :group 'org-ref-faces)
+
+
+(defface org-ref-cite-invalid-local-prefix/suffix-face
+  `((t (:inherit org-ref-cite-face :foreground "red")))
+  "Face for invalid local prefix/suffix in a cite link.
+This is mostly for multicites and natbib."
+  :group 'org-ref-faces)
+
+
+(defcustom org-ref-activate-cite-links t
+  "If non-nil use font-lock to activate citations.
+In large documents with many citations activation can be slow.
+Set this to nil to turn that off, which increase performance."
+  :type 'boolean
+  :group 'org-ref)
+
+
+(defcustom org-ref-default-citation-link
+  "cite"
+  "The default type of citation link to use."
+  :type 'string
+  :group 'org-ref)
+
+
+(defcustom org-ref-natbib-types
+  '(("cite" "basic citation")
+    ("nocite" "add key to bibliography, but do not cite it in the text")
+    ("citet" "textual, Jones et al. (1990)")
+    ("citet*" "textual, full author list Jones, Baker, and Williams (1990)")
+    ("citep" "parenthetical citation (Jones et al. (1990))")
+    ("citep*" "parenthetical, full author list, (Jones, Baker, and Williams, 1990)")
+    ("citealt" "same as citet, but without parentheses")
+    ("citealt*" "same as citet, with full author list but without parentheses")
+    ("citealp" "same as citep, but without parentheses")
+    ("citealp*" "same as citep, with full author list, but without parentheses")
+    ("citenum" "The number of the citation in the bibliography, e.g. 11")
+    ("citetext" "text inserted in citation in the document")
+    ("citeauthor" "Only the author, Jones et al.")
+    ("citeauthor*" "The full author list, Jones, Baker, and Williams")
+    ("citeyear" "The year of the citation, 2021")
+    ("citeyearpar" "The year in parentheses (2021)")
+    ("Citet" "like citet, but with forced capitalization for starting sentences")
+    ("Citep" "like citep, but with forced capitalization for starting sentences")
+    ("Citealt" "like citet, but with forced capitalization and no parentheses")
+    ("Citealp" "like citep, but with forced capitalization and no parentheses")
+    ("Citeauthor" "like citeauthor with forced capitalization")
+    ("Citet*" "like citet, with full author list and forced capitalization")
+    ("Citep*" "like citep, with full author list and forced capitalization")
+    ("Citealt*" "like citet, with full author list, forced capitalization and no parentheses")
+    ("Citealp*" "like citep, with full author list, forced capitalization and no parentheses")
+    ("Citeauthor*" "like citeauthor with forced capitalization"))
+  "Natbib commands can have many references, and global prefix/suffix text.
+  For natbib cite commands see
+  http://tug.ctan.org/macros/latex/contrib/natbib/natnotes.pdf"
+  :type '(repeat :tag "List of citation types" (list string string))
+  :group 'org-ref)
+
+
+(defcustom org-ref-biblatex-types
+  '(("Cite" "basic citation with capitalization")
+    ("parencite" "similar to cite with parentheses")
+    ("Parencite" "similar to cite with parentheses and capitalization")
+    ("footcite" "Put the citation in a footnote")
+    ("footcitetext" "Put the citation in a footnote using \footnotetext")
+
+    ("textcite" "print the authors or editors as a subject of the sentence")
+    ("Textcite" "print the authors or editors as a subject of the sentence with capitalization")
+    ("smartcite" "like parencite in a footnote, and footcite in the body")
+    ("Smartcite" "like parencite in a footnote, and footcite in the body with capitalization")
+    ("cite*" "similar to cite, but prints the year or title")
+    ("parencite*" "similar to parencite, but prints the year or title")
+    ("supercite" "superscripted numeric citation (only in numeric styles)")
+
+    ("autocite" "handles some punctuation nuances")
+    ("Autocite" "handles some punctuation nuances with punctuation")
+    ("autocite*" "same as autocite but * is passed to the backend")
+    ("Autocite*" "same as Autocite but * is passed to the backend")
+
+    ("citetitle" "the shorttitle or title field")
+    ("citetitle*" "the full title")
+
+    ("citeyear" "the year field")
+    ("citeyear*" "the year field and extradate information if available")
+
+    ("citedate" "the full date or year")
+    ("citedate*" "the full date or year, including extradate information if available")
+
+    ("citeurl" "the url field")
+
+    ("fullcite" "create a full citation similar to what is in the bibliography")
+    ("footfullcite" "create a full citation as a footnote")
+    ;; "volcite" "Volcite" cannot support the syntax
+    ("notecite" "print prenote and postnote, but no citation")
+    ("Notecite" "print prenote and postnote, but no citation with capitalization")
+
+    ("pnotecite" "similar to notecite with parentheses")
+    ("Pnotecite" "similar to Notecite with parentheses")
+    ("fnotecite" "similar to notecite in a footnote"))
+  "biblatex commands.
+  Biblatex commands
+  https://mirrors.ibiblio.org/CTAN/macros/latex/contrib/biblatex/doc/biblatex.pdf"
+  :type '(repeat :tag "List of citation types" string)
+  :group 'org-ref)
+
+
+(defcustom org-ref-biblatex-multitypes
+  '(("cites" "multicite version of cite")
+    ("Cites" "multicite version of Cite")
+    ("parencites" "multicite version of parencite")
+    ("Parencites" "multicite version of Parencite")
+    ("footcites" "multicite version of footcite")
+    ("footcitetexts" "multicite version of footcitetext")
+    ("smartcites" "multicite version of smartcite")
+    ("Smartcites" "multicite version of Smartcite")
+    ("textcites" "multicite version of textcite")
+    ("Textcites" "multicite version of Textcite")
+    ("supercites" "multicite version of supercite")
+    ("autocites" "multicite version of autocite")
+    ("Autocites" "multicite version of Autocite"))
+  "Multicite link types"
+  :type '(repeat :tag "List of citation types" string)
+  :group 'org-ref)
+
+
+(defcustom org-ref-cite-types
+  (append
+   org-ref-natbib-types
+   org-ref-biblatex-types
+   org-ref-biblatex-multitypes
+   ;; for the bibentry package
+   '(("bibentry" "Insert the bibtex entry")))
+  "List of citation types known in `org-ref'."
+  :type '(repeat :tag "List of citation types (type description)" (list string string))
+  :group 'org-ref)
+
+
+(defvar org-ref-insert-cite-function)
+
+(defcustom org-ref-cite-keymap
+  (let ((map (copy-keymap org-mouse-map)))
+    ;; Navigation keys
+    (define-key map (kbd "C-<left>") 'org-ref-previous-key)
+    (define-key map (kbd "C-<right>") 'org-ref-next-key)
+
+    ;; rearrangement keys
+    (define-key map (kbd "S-<left>") (lambda () (interactive) (org-ref-swap-citation-link -1)))
+    (define-key map (kbd "S-<right>") (lambda () (interactive) (org-ref-swap-citation-link 1)))
+    (define-key map (kbd "S-<up>") 'org-ref-sort-citation-link)
+    (define-key map (kbd "<tab>") (lambda ()
+                                   (interactive)
+                                   (funcall org-ref-insert-cite-function)))
+
+    ;; xref navigation
+    (define-key map (kbd "M-.") (lambda ()
+                                 (interactive)
+                                 (xref-push-marker-stack)
+                                 (org-ref-open-citation-at-point)))
+    map)
+  "Keymap for cite links."
+  :type 'symbol
+  :group 'org-ref)
+
+
+(defcustom org-ref-cite-insert-version 3
+  "Default version to insert citations with.
+  The default is 3. In legacy documents you might prefer 2 though,
+  so this variable can be buffer- or directory local if you want.
+
+  version 2 means the links are not bracketed, and comma-separated keys.
+
+  version 3 means the links are bracketed, with semicolon-separated
+  &keys."
+  :type 'number
+  :group 'org-ref)
+
+
+(defvar org-ref-citation-key-re
+  (rx-to-string
+   '(seq "&" (group-n 1 (one-or-more (any word "-.:?!`'/*@+|(){}<>&_^$#%~")))))
+  "Numbered regular expression for a version 3 cite key.
+  Key is in group 1.
+  Adapted from the expression in org-cite.")
+
+
+(defun org-ref-cite-version (path)
+  "Return the version for PATH.
+  PATH is from a cite link.
+  Version 2 is separated by commas and uses plain keys.
+  Version 3 is separated by semicolons and uses &keys.
+  I think that if there is a & in path, it must be version 3."
+  (if (string-match "&" path)
+      3
+    2))
+
+
+;; * Parsing/interpreting a citation path
+
+(defun org-ref-parse-cite-path (path)
+  "Return a data structure representing the PATH.
+  the data structure is a plist with (:version :prefix :suffix :references).
+  Each reference is a plist with (:key :prefix :suffix)."
+  (pcase (org-ref-cite-version path)
+    (2
+     ;; This will not have any prefix or suffix, since that was previously done in the desc.
+     (list :version 2 :references (cl-loop for key in (split-string path ",") collect
+                                          (list :key (string-trim key)))))
+    (3 (let ((citation-references (split-string path ";"))
+            (these-results '(:version 3)))
+        ;; if the first ref doesn't match a key, it must be a global prefix
+        ;; this pops the reference off.
+        (when (null (string-match org-ref-citation-key-re (cl-first citation-references)))
+          (setq these-results (append these-results (list :prefix (cl-first citation-references)))
+                citation-references (cdr citation-references)))
+
+        ;; if the last ref doesn't match a key, then it is a global suffix
+        ;; we remove the last one if this is true after getting the suffix.
+        (when (null (string-match org-ref-citation-key-re (car (last citation-references))))
+          (setq these-results (append these-results (list :suffix (car (last citation-references))))
+                citation-references (butlast citation-references)))
+
+        (setq these-results
+              (append these-results
+                      (list
+                       :references
+                       (cl-loop for s in citation-references collect
+                                (if (null (string-match org-ref-citation-key-re s))
+                                    (error "No matching key found in %s" s)
+                                  (let* ((key (match-string-no-properties 1 s))
+                                         (key-start (match-beginning 0))
+                                         (key-end (match-end 0))
+                                         (prefix (let ((p (substring s 0 key-start)))
+                                                   (if (string= "" (string-trim p))
+                                                       nil
+                                                     p)))
+                                         (suffix (let ((s (substring s key-end)))
+                                                   (if (string= "" (string-trim s))
+                                                       nil
+                                                     s))))
+                                    (list :key key :prefix prefix :suffix suffix)))))))))))
+
+
+(defun org-ref-interpret-cite-data (data)
+  "Interpret the DATA structure from `org-ref-parse-cite-path' back
+to a path string."
+  (pcase (plist-get data :version)
+    (2
+     (string-join (cl-loop for ref in (plist-get data :references) collect (plist-get ref :key)) ","))
+    (3
+     (concat
+      (when-let (prefix (plist-get data :prefix)) (concat prefix ";"))
+      (string-join (cl-loop for ref in (plist-get data :references) collect
+                           (concat
+                            (plist-get ref :prefix)
+                            "&" (plist-get ref :key)
+                            (plist-get ref :suffix)))
+                  ";")
+      (when-let (suffix (plist-get data :suffix)) (concat ";" suffix))))))
+
+
+;; * Activating citation links
+;;
+;; We use the activate-func for fontification of pieces of each link.
+
+
+(declare-function bibtex-completion-candidates "bibtex-completion")
+(declare-function bibtex-completion-init "bibtex-completion")
+(defvar bibtex-completion-bibliography)
+(defvar bibtex-completion-display-formats-internal)
+
+;; (defun org-ref-valid-keys ()
+;;   "Return a list of valid bibtex keys for this buffer.
+;; This is used a lot in `org-ref-cite-activate' so it needs to be
+;; fast, but also up to date."
+;;   ;; this seems to be needed, but we don't want to do this every time
+;;   (unless bibtex-completion-display-formats-internal
+;;     (bibtex-completion-init))
+
+;;   (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
+;;     (cl-loop for entry in (bibtex-completion-candidates)
+;;          collect
+;;          (cdr (assoc "=key=" (cdr entry))))))
+
+
+(defun org-ref-valid-keys ()
+  "Return a list of valid bibtex keys for this buffer.
+This is used a lot in `org-ref-cite-activate' so it needs to be
+fast, but also up to date."
+
+  ;; this seems to be needed, but we don't want to do this every time
+  (unless bibtex-completion-display-formats-internal
+    (bibtex-completion-init))
+
+  (let* ((files (org-ref-find-bibliography)))
+    (if (seq-every-p 'identity
+                    (cl-loop for file in files
+                             collect (assoc file bibtex-completion-cache)))
+       ;; We have a cache for each file
+       ;; bibtex-completion-cache contains (filename md5hash entries)
+       (cl-loop for entry in
+                (cl-loop
+                 for file in files
+                 append (cddr (assoc file bibtex-completion-cache)))
+                collect (cdr (assoc "=key=" (cdr entry))))
+      ;; you need to get a cache because one or more of the files was not in the cache.
+      (let ((bibtex-completion-bibliography files))
+       (cl-loop for entry in (bibtex-completion-candidates)
+                collect
+                (cdr (assoc "=key=" (cdr entry))))))))
+
+
+(defvar-local org-ref-valid-keys-hashes nil)
+(defvar-local org-ref-valid-keys-cache  nil)
+
+(defun org-ref-valid-keys-cached ()
+  "Update `org-ref-valid-keys-cache` only when files changed."
+
+  (let ((local-hashes (cons bibtex-completion-bibliography
+                            (mapcar 'cadr bibtex-completion-cache))))
+    (when (not (equal local-hashes org-ref-valid-keys-hashes))
+      (setq-local org-ref-valid-keys-hashes local-hashes)
+      (setq-local org-ref-valid-keys-cache (make-hash-table :test 'equal))
+      (cl-loop for entry in (org-ref-valid-keys)
+               do
+               (puthash entry t org-ref-valid-keys-cache))))
+  org-ref-valid-keys-cache)
+
+
+(defun org-ref-cite-activate (start end path _bracketp)
+  "Activation function for a cite link.
+START and END are the bounds of the link.
+PATH has the citations in it."
+  (when (and org-ref-activate-cite-links
+            ;; Try avoid fontifying org-cite elements. this is based on the
+            ;; path containing @ which makes it likely to be an org-cite. Maybe
+            ;; a text property is better, in case this is an issue in the
+            ;; future.
+            (not (s-contains-p "@" path)))
+    (let* ((valid-keys (org-ref-valid-keys))
+          valid-key
+          substrings)
+      (goto-char start)
+      (pcase (org-ref-cite-version path)
+       (2
+        ;; This makes the brackets visible, but we only need it when there is a
+        ;; description.
+        (when (looking-at "\\[\\[\\(.*\\)\\]\\[\\(.*\\)\\]\\]")
+          (remove-text-properties start end '(invisible nil)))
+        (setq substrings (split-string path ","))
+        (cl-loop for key in substrings
+                 do
+                 ;; get to the substring
+                 (search-forward key end)
+                 (put-text-property (match-beginning 0)
+                                    (match-end 0)
+                                    'keymap
+                                    org-ref-cite-keymap)
+                 (put-text-property (match-beginning 0)
+                                    (match-end 0)
+                                    'cite-key
+                                    key)
+                 (unless (member (string-trim key) valid-keys)
+                   (put-text-property (match-beginning 0)
+                                      (match-end 0)
+                                      'face 'org-ref-bad-cite-key-face)
+                   (put-text-property (match-beginning 0)
+                                      (match-end 0)
+                                      'help-echo "Key not found"))))
+       (3
+        (setq substrings (split-string path ";"))
+        (cl-loop for i from 0 for s in substrings
+                 do
+                 ;; get to the substring
+                 (search-forward s end)
+                 (put-text-property (match-beginning 0)
+                                    (match-end 0)
+                                    'keymap
+                                    org-ref-cite-keymap)
+                 (let* (key-begin
+                        key-end
+                        key)
+
+                   ;; Look for a key. common pre/post notes do not have keys in them.
+                   (save-match-data
+                     (when (string-match org-ref-citation-key-re s)
+                       (setq key (match-string-no-properties 1 s)
+                             valid-key (member key valid-keys))))
+
+                   ;; these are global prefix/suffixes
+                   (when (and (or (= i 0)
+                                  (= i (- (length substrings) 1)))
+                              (null key))
+                     (put-text-property (match-beginning 0) (match-end 0)
+                                        'face 'org-ref-cite-global-prefix/suffix-face)
+                     (put-text-property (match-beginning 0) (match-end 0)
+                                        'help-echo "Global prefix/suffix"))
+
+                   ;; we have a key. we have to re-search to get its position
+                   (when key
+                     (save-excursion
+                       (save-match-data
+                         (search-backward (concat "&" key))
+                         (setq key-begin (match-beginning 0)
+                               key-end (match-end 0))))
+                     ;; mark the &
+                     (put-text-property key-begin (+ 1 key-begin)
+                                        'face 'org-ref-cite-&-face)
+                     ;; store key on the whole thing
+                     (put-text-property (match-beginning 0)
+                                        (match-end 0)
+                                        'cite-key
+                                        key)
+
+                     ;; fontify any prefix /suffix text
+                     (put-text-property (match-beginning 0) key-begin
+                                        'face 'org-ref-cite-local-prefix/suffix-face)
+
+                     (put-text-property key-end (match-end 0)
+                                        'face 'org-ref-cite-local-prefix/suffix-face)
+
+                     ;; bad key activation
+                     (unless valid-key
+                       (put-text-property key-begin key-end
+                                          'face 'font-lock-warning-face)
+                       (put-text-property key-begin key-end
+                                          'help-echo "Key not found"))))))))))
+
+
+;; * Following citation links
+
+(declare-function org-ref-get-bibtex-key-and-file "org-ref-core")
+
+(defhydra org-ref-citation-hydra (:color blue :hint nil)
+  "Citation actions
+"
+  ("o" org-ref-open-citation-at-point  "Bibtex" :column "Open")
+  ("p" org-ref-open-pdf-at-point "PDF" :column "Open")
+  ("n" org-ref-open-notes-at-point "Notes" :column "Open")
+  ("u" org-ref-open-url-at-point "URL" :column "Open")
+
+  ;; WWW actions
+  ("ww" org-ref-wos-at-point "WOS" :column "WWW")
+  ("wr" org-ref-wos-related-at-point "WOS related" :column "WWW")
+  ("wc" org-ref-wos-citing-at-point "WOS citing" :column "WWW")
+  ("wg" org-ref-google-scholar-at-point "Google Scholar" :column "WWW")
+  ("wp" org-ref-pubmed-at-point "Pubmed" :column "WWW")
+  ("wf" org-ref-crossref-at-point "Crossref" :column "WWW")
+  ("wb" org-ref-biblio-at-point "Biblio" :column "WWW")
+  ("e" org-ref-email-at-point "Email" :column "WWW")
+
+  ;; Copyish actions
+  ("K" (save-window-excursion
+        (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
+          (bibtex-completion-show-entry (list (org-ref-get-bibtex-key-under-cursor)))
+          (bibtex-copy-entry-as-kill)
+          (kill-new (pop bibtex-entry-kill-ring))))
+   "Copy bibtex" :column "Copy")
+  ("a" org-ref-add-pdf-at-point "add pdf to library" :column "Copy")
+  ("k" (kill-new (car (org-ref-get-bibtex-key-and-file))) "Copy key" :column "Copy")
+  ("f" (kill-new (bibtex-completion-apa-format-reference
+                 (org-ref-get-bibtex-key-under-cursor)))
+   "Copy formatted" :column "Copy")
+  ("h" (kill-new
+       (format "* %s\n\n cite:&%s"
+               (bibtex-completion-apa-format-reference
+                (org-ref-get-bibtex-key-under-cursor))
+               (car (org-ref-get-bibtex-key-and-file))))
+   "Copy org heading"
+   :column "Copy")
+
+  ;; Editing actions
+  ("<left>" org-ref-cite-shift-left "Shift left" :color red :column "Edit")
+  ("<right>" org-ref-cite-shift-right "Shift right" :color red :column "Edit")
+  ("<up>" org-ref-sort-citation-link "Sort by year" :column "Edit")
+  ("i" (funcall org-ref-insert-cite-function) "Insert cite" :column "Edit")
+  ("t" org-ref-change-cite-type "Change cite type" :column "Edit")
+  ("d" org-ref-delete-citation-at-point "Delete at point" :column "Edit")
+  ("r" org-ref-replace-citation-at-point "Replace cite" :column "Edit")
+  ("P" org-ref-edit-pre-post-notes "Edit pre/suffix" :column "Edit")
+
+  ;; Navigation
+  ("[" org-ref-previous-key "Previous key" :column "Navigation" :color red)
+  ("]"  org-ref-next-key "Next key" :column "Navigation" :color red)
+  ("v" org-ref-jump-to-visible-key "Visible key" :column "Navigation" :color red)
+  ("q" nil "Quit"))
+
+
+(defun org-ref-cite-follow (_path)
+  "Follow a cite link."
+  (org-ref-citation-hydra/body))
+
+
+;; * Citation links tooltips
+(defvar bibtex-completion-bibliography)
+(defvar bibtex-completion-pdf-symbol)
+(defvar bibtex-completion-notes-symbol)
+(defvar bibtex-completion-find-note-functions)
+
+(declare-function org-ref-find-bibliography "org-ref-core")
+(declare-function bibtex-completion-find-pdf "bibtex-completion")
+(declare-function bibtex-completion-apa-format-reference "bibtex-completion")
+
+(defun org-ref-cite-tooltip (_win _obj position)
+  "Get a tooltip for the cite at POSITION."
+  (let ((key (get-text-property position 'cite-key)))
+    (when key
+      (let ((bibtex-completion-bibliography (org-ref-find-bibliography))
+           (has-pdf (when (bibtex-completion-find-pdf key) bibtex-completion-pdf-symbol))
+           (has-notes (when (cl-some #'identity
+                                     (mapcar (lambda (fn)
+                                               (funcall fn key))
+                                             bibtex-completion-find-note-functions))
+                        bibtex-completion-notes-symbol)))
+       (format "%s%s %s" (or has-pdf "") (or has-notes "")
+               (bibtex-completion-apa-format-reference key))))))
+
+
+;; * Exporting citation links
+
+(defun org-ref-cite-export (cmd path desc backend)
+  "Export a cite link.
+This supports the syntax:  \\cmd[optional prefix][optional suffix]{keys}
+The prefix and suffix must be the global version. Local prefix/suffixes are ignored.
+PATH contains the link path.
+BACKEND is the export backend.
+Use with apply-partially."
+  (pcase backend
+    ('latex
+     (let* ((cite (org-ref-parse-cite-path path))
+           (references (plist-get cite :references))
+           (keys (cl-loop for ref in references collect
+                          (plist-get ref :key))))
+       (pcase (org-ref-cite-version path)
+        (2
+         (let* ((prefix-suffix (split-string (or desc "") "::"))
+                (prefix (cond
+                         ((and (cl-first prefix-suffix) (not (string= "" (cl-first prefix-suffix))))
+                          (format "[%s]" (cl-first prefix-suffix)))
+                         ((cl-second prefix-suffix)
+                          "[]")
+                         (t
+                          "")))
+                (suffix (cond
+                         ((cl-second prefix-suffix)
+                          (format "[%s]" (cl-second prefix-suffix)))
+                         (t
+                          ""))))
+           (s-format "\\${cmd}${prefix}${suffix}{${keys}}" 'aget
+                     `(("cmd" . ,cmd)
+                       ("prefix" . ,(string-trim prefix))
+                       ("suffix" . ,(string-trim suffix))
+                       ("keys" . ,(string-join keys ","))))))
+        (3
+         (s-format "\\${cmd}${prefix}${suffix}{${keys}}" 'aget
+                   `(("cmd" . ,cmd)
+                     ;; if there is more than one key, we only do global
+                     ;; prefix/suffix But for one key, we should allow local
+                     ;; prefix and suffix or the global one.
+                     ("prefix" . ,(if (= 1 (length references))
+                                      ;; single reference
+                                      (cond
+                                       ;; global and common prefixes exist, combine them
+                                       ((and (plist-get cite :prefix)
+                                             (plist-get (car references) :prefix))
+
+                                        (concat "["
+                                                (plist-get cite :prefix)
+                                                ";" ;; add this back as a separator
+                                                (plist-get (car references) :prefix)
+                                                "]"))
+                                       ;; local prefix is not empty, we use it.
+                                       ((plist-get (car references) :prefix)
+                                        (concat "["
+                                                (string-trim (plist-get (car references) :prefix))
+                                                "]"))
+                                       ;; local prefix is empty, but global one
+                                       ;; is not, so we use it
+                                       ((plist-get cite :prefix)
+                                        (concat "["
+                                                (string-trim (plist-get cite :prefix))
+                                                "]"))
+                                       ;; if you have a suffix, you need an empty prefix
+                                       ((plist-get cite :suffix)
+                                        "[]")
+                                       (t
+                                        ""))
+                                    ;; Multiple references
+                                    (cond
+                                     ;; Check the common prefix
+                                     ((plist-get cite :prefix)
+                                      (concat "["
+                                              (string-trim (plist-get cite :prefix))
+                                              "]"))
+                                     ;; Check the prefix in the first cite
+                                     ((plist-get (car references) :prefix)
+                                      (concat "["
+                                              (string-trim (plist-get (car references) :prefix))
+                                              "]"))
+                                     ;; if you get here, the prefix is empty.
+                                     ;; if you have a suffix, you need an empty prefix placeholder
+                                     ((plist-get cite :suffix)
+                                      "[]")
+                                     (t
+                                      ""))))
+                     ("suffix" . ,(if (= 1 (length references))
+                                      ;; Single reference
+                                      (cond
+                                       ;; local suffix is not empty, so use it
+                                       ((plist-get (car references) :suffix)
+                                        (format "[%s]"
+                                                (string-trim (plist-get (car references) :suffix))))
+                                       ;; global suffix is not empty
+                                       ((plist-get cite :suffix)
+                                        (format "[%s]" (string-trim (plist-get cite :suffix))))
+                                       (t
+                                        ;; If there is a prefix, then this should
+                                        ;; be an empty bracket, and if not it
+                                        ;; should am empty string. You need an
+                                        ;; empty bracket, at least for biblatex
+                                        ;; commands. With just one set of
+                                        ;; brackets it is interpreted as a
+                                        ;; suffix.
+                                        (if (or (plist-get cite :prefix)
+                                                (plist-get (car references) :prefix))
+                                            "[]"
+                                          "")))
+                                    ;; Multiple references
+                                    (cond
+                                     ;; this is a common suffix
+                                     ((plist-get cite :suffix)
+                                      (format "[%s]" (string-trim (plist-get cite :suffix))))
+                                     ;; last reference has a suffix
+                                     ((plist-get (car (last references)) :suffix)
+                                      (format "[%s]" (string-trim (plist-get (car (last references)) :suffix))))
+                                     (t
+                                      ;; If there is a prefix, then this should
+                                      ;; be an empty bracket, and if not it
+                                      ;; should am empty string. You need an
+                                      ;; empty bracket, at least for biblatex
+                                      ;; commands. With just one set of
+                                      ;; brackets it is interpreted as a
+                                      ;; suffix.
+                                      (if (or (plist-get cite :prefix)
+                                              (plist-get (car references) :prefix))
+                                          "[]"
+                                        "")))))
+                     ("keys" . ,(string-join keys ","))))))))))
+
+
+(defun org-ref-multicite-export (cmd path _desc backend)
+  "Export a multicite link.
+This supports the syntax:  \\cmd(multiprenote)(multipostnote)[prenote][postnote]{key1}...[prenote][postnote]{key}
+PATH contains the link path.
+BACKEND is the export backend.
+Use with apply-partially."
+  (pcase backend
+    ('latex
+     (let ((cite (org-ref-parse-cite-path path)))
+       (s-format "\\${cmd}${global-prefix}${global-suffix}${keys}" 'aget
+                `(("cmd" . ,cmd)
+                  ("global-prefix" . ,(cond
+                                       ((plist-get cite :prefix)
+                                        (concat "(" (plist-get cite :prefix) ")"))
+                                       ;; if you have a suffix, you need an empty prefix
+                                       ((plist-get cite :suffix)
+                                        "()")
+                                       (t
+                                        "")))
+                  ("global-suffix" . ,(if (not (string= "" (or (plist-get cite :suffix) "")))
+                                          (format "(%s)" (plist-get cite :suffix))
+                                        ""))
+                  ("keys" . ,(string-join
+                              (cl-loop for ref in (plist-get cite :references)
+                                       collect
+                                       (format "%s%s{%s}"
+                                               (cond
+                                                ;; we have a prefix, stick it in
+                                                ((not (string= ""
+                                                               (or (plist-get ref :prefix) "")))
+                                                 (concat "[" (plist-get ref :prefix) "]"))
+                                                ;; no prefix, but a suffix, so
+                                                ;; empty prefix for placeholder
+                                                ((not (string= ""
+                                                               (or (plist-get ref :suffix) "")))
+                                                 "[]")
+                                                (t
+                                                 ""))
+                                               (cond
+                                                ((not (string= ""
+                                                               (or (plist-get ref :suffix) "")))
+                                                 (concat "[" (plist-get ref :suffix) "]"))
+                                                (t
+                                                 ""))
+                                               (plist-get ref :key)))))))))))
+
+;; * Completion for citation links
+;;
+;; This allows you to type C-c l, choose a cite link type, and then insert a key.
+
+(defun org-ref-cite-link-complete (cmd &optional _arg)
+  "Cite link completion for CMD."
+  (concat
+   cmd ":"
+   "&" (org-ref-read-key)))
+
+;; * Generate all the links
+;;
+;; We loop on the three categories because there are some differences between
+;; them, mostly in the multitypes.
+
+(cl-loop for (cmd _desc) in (append org-ref-natbib-types
+                                   org-ref-biblatex-types)
+        do
+        (org-link-set-parameters
+         cmd
+         :complete (apply-partially #'org-ref-cite-link-complete cmd)
+         :follow #'org-ref-cite-follow
+         :face 'org-ref-cite-face
+         :help-echo #'org-ref-cite-tooltip
+         :export (apply-partially 'org-ref-cite-export  cmd)
+         :activate-func #'org-ref-cite-activate))
+
+
+(cl-loop for (cmd _desc) in org-ref-biblatex-multitypes do
+        (org-link-set-parameters
+         cmd
+         :complete (apply-partially #'org-ref-cite-link-complete cmd)
+         :follow #'org-ref-cite-follow
+         :face 'org-ref-cite-face
+         :help-echo #'org-ref-cite-tooltip
+         :export (apply-partially 'org-ref-multicite-export cmd)
+         :activate-func #'org-ref-cite-activate))
+
+
+(org-link-set-parameters
+ "bibentry"
+ :complete (apply-partially #'org-ref-cite-link-complete "bibentry")
+ :follow #'org-ref-cite-follow
+ :face 'org-ref-cite-face
+ :help-echo #'org-ref-cite-tooltip
+ :export (apply-partially 'org-ref-cite-export  "bibentry")
+ :activate-func #'org-ref-cite-activate)
+
+
+;; * Cite link utilities
+
+;;;###autoload
+(defun org-ref-delete-citation-at-point ()
+  "Delete the citation or reference at point."
+  (interactive)
+  (let* ((object (org-element-context))
+         (type (org-element-property :type object))
+         (begin (org-element-property :begin object))
+         (end (org-element-property :end object))
+         (link-string (org-element-property :path object))
+        (data (org-ref-parse-cite-path link-string))
+        (references (plist-get data :references))
+        (cp (point))
+         key i)
+    ;;   We only want this to work on citation links
+    (when (assoc type org-ref-cite-types)
+      (setq key (org-ref-get-bibtex-key-under-cursor))
+      (if (null key)
+         ;; delete the whole cite
+         (cl--set-buffer-substring begin end "")
+       (setq i (seq-position references key (lambda (el key)
+                                              (string= key (plist-get el :key)))))
+       ;; delete i'th reference
+       (setq references (-remove-at i references))
+       (setq data (plist-put data :references references))
+       (save-excursion
+         (goto-char begin)
+         (re-search-forward link-string)
+         (replace-match (org-ref-interpret-cite-data data)))
+       (goto-char cp)))))
+
+
+;;;###autoload
+(defun org-ref-replace-citation-at-point ()
+  "Replace the citation at point."
+  (interactive)
+  (let* ((object (org-element-context))
+         (type (org-element-property :type object))
+         (begin (org-element-property :begin object))
+         (end (org-element-property :end object))
+         (link-string (org-element-property :path object))
+        (data (org-ref-parse-cite-path link-string))
+        (references (plist-get data :references))
+        (cp (point))
+         key i)
+    ;;   We only want this to work on citation links
+    (when (assoc type org-ref-cite-types)
+      (setq key (org-ref-get-bibtex-key-under-cursor))
+
+      (if (null key)
+         ;; delete the whole cite
+         (cl--set-buffer-substring begin end "")
+       (setq i (seq-position references key (lambda (el key) (string= key (plist-get el :key))))) ;; defined in org-ref
+       (setf (plist-get (nth i references) :key)  (org-ref-read-key))
+
+       (setq data (plist-put data :references references))
+       (save-excursion
+         (goto-char begin)
+         (re-search-forward link-string)
+         (replace-match (org-ref-interpret-cite-data data)))
+       (goto-char cp)))))
+
+
+;;;###autoload
+(defun org-ref-edit-pre-post-notes (&optional common)
+  "Edit the pre/post notes at point.
+
+if you are not on a key, or with optional prefix
+arg COMMON, edit the common prefixes instead."
+  (interactive "P")
+  ;; find out what the point is on.
+  (let* ((key (get-text-property (point) 'cite-key))
+        (cp (point))
+        (cite (org-element-context))
+        (type (org-element-property :type cite))
+        (data (org-ref-parse-cite-path (org-element-property :path cite)))
+        prefix suffix
+        (delta 0))
+
+    (if (or (null key) common)
+       (progn
+         (setq prefix (read-string "prenote: " (plist-get data :prefix))
+               suffix (read-string "postnote: " (plist-get data :suffix))
+               delta (- (length (plist-get data :prefix)) (length prefix)))
+
+         (plist-put data :prefix (if (string= "" prefix)
+                                     nil prefix))
+
+         (plist-put data :suffix (if (string= "" suffix)
+                                     nil suffix)))
+
+      ;; On a key
+      (let ((index (seq-position (plist-get data :references)
+                                key
+                                (lambda (el1 key-at-point)
+                                  (string= key-at-point (plist-get el1 :key))))))
+       ;; Pad with spaces after prefix and before suffix
+       (setq prefix (concat
+                     (read-string "prenote: "
+                                  (string-trim
+                                   (or
+                                    (plist-get
+                                     (nth index (plist-get data :references))
+                                     :prefix)
+                                    "")))
+                     " ")
+             suffix (concat " "
+                            (read-string "postnote: "
+                                         (string-trim
+                                          (or
+                                           (plist-get
+                                            (nth index (plist-get data :references))
+                                            :suffix)
+                                           ""))))
+             delta (- (length (plist-get
+                               (nth index (plist-get data :references))
+                               :prefix))
+                      (length prefix)))
+       (plist-put
+        (nth index (plist-get data :references))
+        :prefix (if (string= "" prefix)
+                    nil prefix))
+
+       (plist-put
+        (nth index (plist-get data :references))
+        :suffix (if (string= "" suffix)
+                    nil suffix))))
+
+
+    (cl--set-buffer-substring (org-element-property :begin cite) (org-element-property :end cite)
+                             (format "[[%s:%s]]" type (org-ref-interpret-cite-data data)))
+
+    ;; This doesn't exactly save the point. I need a fancier calculation for
+    ;; that I think that accounts for the change due to the prefix change. e.g.
+    ;; you might add or subtract from the prefix.
+    (goto-char (- cp delta))))
+
+
+(declare-function org-element-create "org-element")
+
+;;;###autoload
+(defun org-ref-change-cite-type ()
+  "Change the cite type of citation link at point."
+  (interactive)
+  (let* ((type-annotation (lambda (s)
+                           (let ((item (assoc s minibuffer-completion-table)))
+                             (when item (concat
+                                         (make-string (- 12 (length s)) ? )
+                                         "-- "
+                                         (cl-second item))))))
+        (completion-extra-properties `(:annotation-function ,type-annotation))
+        (new-type (completing-read "Type: " org-ref-cite-types))
+        (cite-link (org-element-context))
+        (cp (point)))
+    (cl--set-buffer-substring
+     (org-element-property :begin cite-link)
+     (org-element-property :end cite-link)
+     (org-element-interpret-data
+      (org-element-create 'link
+                         `(:type ,new-type
+                                 :path ,(org-element-property :path cite-link)
+                                 :contents-begin ,(org-element-property :contents-begin cite-link)
+                                 :contents-end ,(org-element-property :contents-end  cite-link)))))
+    (goto-char cp)))
+
+
+(defun org-ref-get-bibtex-key-under-cursor ()
+  "Return key under the cursor in org-mode.
+If not on a key, but on a cite, prompt for key."
+  (if-let ((key (get-text-property (point) 'cite-key)))
+      ;; Point is on a key, so we get it directly
+      key
+    ;; point is not on a key, but may still be on a cite link
+    (let ((el (org-element-context))
+         (cp (point))
+         data
+         keys)
+      (cond
+       ;; on a cite-link type
+       ((and
+        (eq (org-element-type el) 'link)
+        (assoc (org-element-property :type el) org-ref-cite-types))
+
+       (goto-char (org-element-property :begin el))
+       (setq data (org-ref-parse-cite-path (org-element-property :path el))
+             keys (cl-loop for ref in (plist-get data :references)
+                           collect (plist-get ref :key)))
+       (cond
+        ((= 1 (length keys))
+         (search-forward (car keys))
+         (goto-char (match-beginning 0)))
+        ;; multiple keys
+        (t
+         (setq key (completing-read "Key: " keys))
+         (search-forward key)
+         (goto-char (match-beginning 0))))
+       (prog1
+           (get-text-property (point) 'cite-key)
+         (goto-char cp)))
+
+       ;; somewhere else, but looking at a cite-type see issue #908. links in
+       ;; places like keywords are not parsed as links, but they seem to get
+       ;; activated, so we can just get onto the key, and then open it.
+       ((assoc (thing-at-point 'word) org-ref-cite-types)
+       (save-excursion
+         (when (re-search-forward ":" (line-end-position) t)
+           (prog1
+               (get-text-property (point) 'cite-key)
+             (goto-char cp)))))))))
+
+
+;; ** Shift-arrow sorting of keys in a cite link
+
+(defun org-ref-swap-list-elements (i j lst)
+  "Swap index I and J in the list LST."
+  (let ((tempi (nth i lst)))
+    (setf (nth i lst) (nth j lst))
+    (setf (nth j lst) tempi))
+  lst)
+
+
+(defun org-ref-swap-citation-link (direction)
+  "Move citation at point in DIRECTION +1 is to the right, -1 to the left."
+  (let* ((object (org-element-context))
+         (type (org-element-property :type object))
+         (begin (org-element-property :begin object))
+         ;; (end (org-element-property :end object))
+         (link-string (org-element-property :path object))
+        (data (org-ref-parse-cite-path link-string))
+        (references (plist-get data :references))
+         key i)
+    ;;   We only want this to work on citation links
+    (when (assoc type org-ref-cite-types)
+      (setq key (org-ref-get-bibtex-key-under-cursor))
+      (setq i (seq-position references key (lambda (el key) (string= key (plist-get el :key))))) ;; defined in org-ref
+      (if (> direction 0) ;; shift right
+          (org-ref-swap-list-elements i (min (+ i 1) (- (length references) 1)) references)
+        (org-ref-swap-list-elements i (max (- i 1) 0) references))
+      (setq data (plist-put data :references references))
+
+      ;; and replace the link with the sorted keys
+      (save-excursion
+       (goto-char begin)
+       (re-search-forward link-string)
+       (replace-match (org-ref-interpret-cite-data data)))
+      ;; now go forward to key so we can move with the key
+      (goto-char begin)
+      (re-search-forward key)
+      (goto-char (match-beginning 0)))))
+
+
+(defun org-ref-cite-shift-left ()
+  "Shift reference at point to the left."
+  (interactive)
+  (org-ref-swap-citation-link -1))
+
+
+(defun org-ref-cite-shift-right ()
+  "Shift citation at point to the right."
+  (interactive)
+  (org-ref-swap-citation-link +1))
+
+
+;;** Sort cite in cite link
+
+;;;###autoload
+(defun org-ref-sort-citation-link ()
+  "Replace link at point with sorted link by year."
+  (interactive)
+  (let* ((object (org-element-context))
+         ;; (type (org-element-property :type object))
+         (begin (org-element-property :begin object))
+         ;; (end (org-element-property :end object))
+         (link-string (org-element-property :path object))
+        (data (org-ref-parse-cite-path link-string))
+        (references (plist-get data :references))
+        (bibtex-completion-bibliography (org-ref-find-bibliography))
+        current-point)
+
+    (setq references (cl-sort (cl-loop for ref in references collect
+                                      (append ref (list :year (bibtex-completion-get-value
+                                                               "year"
+                                                               (bibtex-completion-get-entry
+                                                                (plist-get ref :key))))))
+                             (lambda (x y)
+                               (< (string-to-number (plist-get x :year))
+                                  (string-to-number (plist-get y :year))))))
+    (setq data (plist-put data :references references)
+         current-point (point))
+    (goto-char begin)
+    (re-search-forward link-string)
+    (replace-match (org-ref-interpret-cite-data data))
+    (goto-char current-point)))
+
+
+;;** C-arrow navigation of cite keys
+;;
+;; These are a little tricky to understand to me. There are two calls because
+;; when you are on a cite, and move, the first change is the boundary of the
+;; current cite, and the second is the boundary of next cite.
+
+;;;###autoload
+(defun org-ref-next-key ()
+  "Move cursor to the next cite key when on a cite link.
+Otherwise run `right-word'. If the cursor moves off the link,
+move to the beginning of the next cite link after this one."
+  (interactive)
+  (when-let (next (next-single-property-change (point) 'cite-key))
+    (goto-char next))
+  (unless (get-text-property (point) 'cite-key)
+    (when-let (next (next-single-property-change (point) 'cite-key))
+      (goto-char next))))
+
+
+;;;###autoload
+(defun org-ref-previous-key ()
+  "Move cursor to the previous cite key when on a cite link.
+Otherwise run `left-word'. If the cursor moves off the link,
+move to the beginning of the previous cite link after this one."
+  (interactive)
+  (when-let (prev (previous-single-property-change (point) 'cite-key))
+    (goto-char prev))
+  (unless (get-text-property (point) 'cite-key)
+    (when-let (prev (previous-single-property-change (point) 'cite-key))
+      (goto-char prev))))
+
+(defvar avy-goto-key)
+(defvar avy-style)
+(declare-function avy--style-fn "avy")
+(declare-function avy-process "avy")
+(declare-function avy-with "avy")
+(declare-function org-element-parse-buffer "org-element")
+(declare-function org-element-property "org-element")
+(declare-function org-element-type "org-element")
+(declare-function org-element-map "org-element")
+(declare-function bibtex-completion-get-value "bibtex-completion")
+(declare-function bibtex-completion-get-entry "bibtex-completion")
+
+;;;###autoload
+(defun org-ref-jump-to-visible-key ()
+  "Jump to a visible key with avy."
+  (interactive)
+  (avy-with avy-goto-key
+    (avy-process
+     (apply #'append
+           (save-excursion
+             (org-element-map (org-element-parse-buffer) 'link
+               (lambda (c)
+                 (when (assoc (org-element-property :type c) org-ref-cite-types)
+                   (goto-char (org-element-property :begin c))
+                   (let* ((path (org-element-property :path c))
+                          (data (org-ref-parse-cite-path path))
+                          (references (plist-get data :references)))
+                     (append (list (org-element-property :begin c))
+                             (cl-loop for ref in references collect
+                                      (progn
+                                        (search-forward (plist-get ref :key))
+                                        (match-beginning 0)))))))))))
+    (avy--style-fn avy-style)))
+
+
+;; * Insert links
+(declare-function bibtex-completion-format-entry "bibtex-completion")
+
+;; The formatting is adapted from ivy-bibtex-transformer. I feel like it is
+;; slower than ivy-bibtex though. It is completion agnostic though...
+(defun org-ref-read-key ()
+  "Read a key with completion."
+  (unless bibtex-completion-display-formats-internal
+    (bibtex-completion-init))
+  (let* ((bibtex-completion-bibliography (org-ref-find-bibliography))
+        (candidates (mapcar (lambda (entry)
+                              (cons (bibtex-completion-format-entry entry (1- (frame-width)))
+                                    (cdr entry)))
+                            (bibtex-completion-candidates)))
+        (choice (completing-read "org-ref BibTeX entries: " candidates)))
+    (cdr (assoc "=key=" (assoc choice candidates)))))
+
+
+(defun org-ref-insert-cite-key (key &optional set-type)
+  "Insert KEY at point as a cite link.
+With optional prefix SET-TYPE choose the link type (only on initial insert).
+Rules:
+1. at beginning of key, insert before it.
+2. at middle or end of key, insert after it."
+  (let* ((object (org-element-context))
+        (type (org-element-property :type object))
+        ;; (cp (point))
+        link-string version data references key-at-point index
+        (type-annotation (lambda (s)
+                           (let ((item (assoc s minibuffer-completion-table)))
+                             (when item (concat
+                                         (make-string (- 12 (length s)) ? )
+                                         "-- "
+                                         (cl-second item))))))
+        (completion-extra-properties `(:annotation-function ,type-annotation)))
+
+    (cond
+     ((derived-mode-p 'latex-mode)
+      (insert (bibtex-completion-format-citation-cite (list key))))
+     (t
+    (cond
+     ;; Not on a link, so we just insert a cite
+     ((null (assoc type org-ref-cite-types))
+      (insert (format "[[%s:%s%s]]"
+                     (if set-type
+                         (completing-read "cite type: " org-ref-cite-types)
+                       org-ref-default-citation-link)
+                     (pcase org-ref-cite-insert-version
+                       (2 "")
+                       (3 "&"))
+                     key)))
+     ;; On a link with no path
+     ;; See https://github.com/jkitchin/org-ref/issues/951#issuecomment-985998821
+     ;; This is an unusual corner case most often triggered by a snippet, although
+     ;; perhaps there is some scenario like [[cite:]]
+     ((string= "" (org-element-property :path object))
+      (unless (looking-back ":" 1)
+       (goto-char (org-element-property :end object))
+       (skip-chars-backward "]"))
+      (insert (concat
+              (pcase org-ref-cite-insert-version
+                (2 "")
+                (3 "&"))
+              key)))
+
+     ;; On a link somewhere, and we need to figure out what to do.
+     (t
+      (setq link-string (org-element-property :path object)
+           version (org-ref-cite-version link-string)
+           data (org-ref-parse-cite-path link-string)
+           references (plist-get data :references)
+           key-at-point (get-text-property (point) 'cite-key))
+
+      ;; There are two scenarios where key-at-point is null
+      ;; 1. on the link-type before the :
+      ;; 2. at the end of the link
+      ;; Either way we just go to the end.
+      (when (null key-at-point)
+       ;; that failed, so move to the last one This seems weird, but when you
+       ;; insert several marked candidates the point does weird things.
+       (goto-char (org-element-property :end object))
+       (skip-chars-backward " ")
+       (setq key-at-point (plist-get (car (last references)) :key)))
+
+
+      ;; this is index of selected key
+      (setq index (seq-position references key-at-point
+                               (lambda (el1 key-at-point)
+                                 (string= key-at-point (plist-get el1 :key)))))
+
+      (setq data (plist-put data :references
+                           (-insert-at
+                            (+ index (if (and (= 3 version) (looking-at "&"))
+                                         0
+                                       1))
+                            (list :key key) references)))
+
+      (pcase org-ref-cite-insert-version
+       (2
+        (cl--set-buffer-substring
+         (org-element-property :begin object)
+         (org-element-property :end object)
+         (concat type ":" (string-join (cl-loop for ref in (plist-get data :references)
+                                                collect (plist-get ref :key))
+                                       ","))))
+       (3 (cl--set-buffer-substring
+           (org-element-property :begin object)
+           (org-element-property :end object)
+           (concat "[["
+                   type ":"
+                   (org-ref-interpret-cite-data data)
+                   "]]"
+                   (make-string (org-element-property :post-blank object) ? )))))))
+
+    ;; Now get to the end of the key you just put in.
+    (setq object (org-element-context))
+    (goto-char (org-element-property :end object))
+    (skip-chars-backward " ")))))
+
+
+(defun org-ref-insert-cite-keys (keys &optional set-type)
+  "Insert KEYS as citation links.
+Optional SET-TYPE to choose the cite type."
+  (cl-loop for key in keys
+          do
+          (org-ref-insert-cite-key key set-type)))
+
+
+;;;###autoload
+(defun org-ref-insert-cite-link (&optional set-type)
+  "Insert a cite link with completion.
+Optional prefix arg SET-TYPE to choose the cite type."
+  (interactive "P")
+  (org-ref-insert-cite-key (org-ref-read-key) set-type))
+
+
+;; * natmove like pre-processing
+;;
+;; I think that citations belong in the sentence where they are used, which
+;; means on the left side of punctuation. However, for some citation styles,
+;; especially superscripts, it is nicer if they appear on the right hand side of
+;; punctuation. achemso in LaTeX provides natmove
+;; (https://ctan.org/pkg/natmove?lang=en) for this. It doesn't seem to work for
+;; all LaTeX styles though, and in particular only works on the cite command
+;; itself. So, Here is a preprocessor function you can use to move all the
+;; cites.
+
+(declare-function org-ref-get-cite-links "org-ref-export")
+
+(defun org-ref-cite-natmove (_backend)
+  "Move citations to the right side of punctuation.
+Intended for use in `org-export-before-parsing-hook'.
+
+Here is an example use:
+
+  (let ((org-export-before-parsing-hook '(org-ref-cite-natmove)))
+    (org-open-file (org-latex-export-to-pdf)))"
+  (let ((cites (org-ref-get-cite-links))
+       punct)
+    (cl-loop for cite in (reverse cites) do
+            (goto-char (org-element-property :end cite))
+            (skip-chars-backward " ")
+            (when (string-match-p "[[:punct:]]" (buffer-substring (point) (+ (point) 1)))
+              (setq punct (buffer-substring (point) (+ (point) 1)))
+              ;; delete the punctuation
+              (cl--set-buffer-substring (point) (+ (point) 1) "")
+              ;; and insert it at the beginning of the link.
+              (goto-char (org-element-property :begin cite))
+              ;; delete spaces backward
+              (skip-chars-backward " ")
+              (cl--set-buffer-substring (point) (org-element-property :begin cite) "")
+              (insert punct)))))
+
+;; * Convert version 2 to version 3
+
+(defun org-ref-v2-cites-to-v3 ()
+  "Replace version 2 citation syntax with version 3 citation syntax"
+  (interactive)
+  (cl-loop for cite in (reverse (org-ref-get-cite-links))
+          collect
+          (let ((data (org-ref-parse-cite-path (org-element-property :path cite)))
+                prefix-suffix)
+            (when (org-element-property :contents-begin cite)
+              (setq prefix-suffix (split-string (buffer-substring (org-element-property :contents-begin cite)
+                                                                  (org-element-property :contents-end cite))
+                                                "::"))
+              (plist-put data :prefix (cl-first prefix-suffix))
+              (plist-put data :suffix (cl-second prefix-suffix)))
+            (plist-put data :version  3)
+            (cl--set-buffer-substring (org-element-property :begin cite)
+                                      (org-element-property :end cite)
+                                      (format "[[%s:%s]]" (org-element-property :type cite)
+                                              (org-ref-interpret-cite-data data))))))
+
+
+(provide 'org-ref-citation-links)
+
+;;; org-ref-citation-links.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-compat.el b/elpa/org-ref-20230507.1420/org-ref-compat.el
new file mode 100644 (file)
index 0000000..1e9beaf
--- /dev/null
@@ -0,0 +1,94 @@
+;;; org-ref-compat.el --- Compatibility functions for org-cite
+
+;;; Commentary:
+;;
+;; The main function of this library is to provide compatibility functions for
+;; converting between org-ref and org-cite.
+
+(require 'org-ref-export)
+
+
+(defcustom org-ref-to-org-cite-mapping
+  '(("cite" . "")
+    ("citep" . "")
+    ("Citep" . "//caps-full")
+    ("citealp" . "//bare")
+    ("Citealp" . "//bare-caps")
+    ("Citealp*" . "//bare-caps-full")
+    ("citep*" . "//full")
+
+    ("citet" . "/text")
+
+    ("citeyear" . "/noauthor/bare")
+    ("citeyearpar" . "/noauthor")
+    
+    ("nocite" . "/nocite")
+
+    ("citeauthor" . "/author")
+    ("citeauthor*" . "/author/full")
+    ("Citeauthor" . "/author/caps"))
+  
+  "A-list of (org-ref-type . org-cite-style).
+This builds from
+https://blog.tecosaur.com/tmio/2021-07-31-citations.html#cite-syntax.
+There is no way to get them all though, there are conflicting
+translations with some biblatex and some natbib commands. This
+list maps the natbib commands. I have also opted to use the full
+names rather than the short names."
+  :group 'org-ref)
+
+
+(defun org-ref-to-org-cite ()
+  (interactive)
+  (let ((ref-cites (reverse (org-ref-get-cite-links)))
+       ref-type
+       path
+       beg end)
+    ;; This takes care of the cite links
+    (cl-loop for rc in ref-cites do
+            (setq
+             type (org-element-property :type rc)
+             path (org-element-property :path rc)
+             beg (org-element-property :begin rc)
+             end (org-element-property :end rc))
+            (cl--set-buffer-substring
+             beg end
+             (format "[cite%s:%s]"
+                     (or (cdr (assoc type org-ref-to-org-cite-mapping)) "")
+                     ;; This is not 100% correct, if someone has put an extra &
+                     ;; anywhere in a note, this will be a little wrong. It
+                     ;; would be a little more correct if I also look for a
+                     ;; word next to it. The most correct would probably be to
+                     ;; build the data and then use org-element interpret I
+                     ;; think
+                     (replace-regexp-in-string "&" "@" path))))
+
+    ;; Next replace bibliography links. I assume the paths are ok, and we just
+    ;; need to convert them to keywords.
+    (cl-loop for bib-link in
+            (reverse (org-element-map (org-element-parse-buffer) 'link
+                       (lambda (bl)
+                         (when (member (org-element-property :type bl)
+                                       '("bibliography" "nobibliography"))
+                           bl))))
+            do
+            (cl--set-buffer-substring
+             (org-element-property :begin bib-link)
+             (org-element-property :end bib-link)
+             (format "#+bibliography: %s%s"
+                     (org-element-property :path bib-link)
+                     (if (string= "bibliography"
+                                  (org-element-property :type bib-link))
+                         "\n#+print_bibliography:"
+                       ""))))
+    ;; Note it is a bit ambiguous what do do about where the bibliography is to
+    ;; be printed. This should be done via #+print_bibliography:. In org-ref the
+    ;; bibliography normally goes where the bibliography link was, and I sue
+    ;; that convention.
+    
+    ))
+
+
+(provide 'org-ref-compat)
+
+;;; org-ref-compat.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-core.el b/elpa/org-ref-20230507.1420/org-ref-core.el
new file mode 100644 (file)
index 0000000..1c2d6d8
--- /dev/null
@@ -0,0 +1,339 @@
+;;; org-ref-core.el --- citations, cross-references and bibliographies in org-mode -*- lexical-binding: t; -*-
+
+;; Copyright(C) 2014-2021 John Kitchin
+
+;; This file is not currently part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program ; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; This is the core library.
+;;
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl-lib))
+
+(require 'org)
+;; the eval and compile seems especially necessary for native compilation on the newest Emacs.
+(eval-and-compile (require 'org-macs))
+
+(require 'org-element)
+
+(require 'dash)
+(require 'f)
+(require 's)
+
+(require 'parsebib)
+(require 'bibtex-completion)
+(require 'hydra)
+
+(require 'org-ref-bibliography-links)
+(require 'org-ref-citation-links)
+(require 'org-ref-ref-links)
+(require 'org-ref-label-link)
+(require 'org-ref-misc-links)
+(require 'org-ref-export)
+
+(require 'org-ref-utils)
+(require 'org-ref-bibtex)
+(require 'org-ref-glossary)
+
+
+;;* Custom variables
+
+(defgroup org-ref nil
+  "Customization group for org-ref."
+  :tag "Org Ref"
+  :group 'org)
+
+
+(defcustom org-ref-insert-link-function
+  nil
+  "Generic function for inserting org-ref links.
+The function should take a prefix arg.
+No arg means insert a cite link
+1 arg means insert a ref link
+2 args means insert a label."
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-insert-cite-function
+  nil
+  "Function to call to insert citation links.
+This function should prompt for keys with completion, and insert
+the citation link into the buffer."
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-cite-completion-function
+  nil
+  "Function to prompt for keys with completion."
+  :type '(choice (const nil)
+                 (function))
+  :group 'org-ref)
+
+
+(defcustom org-ref-insert-label-function
+  nil
+  "Function to call to insert label links.
+This function should prompt for a label, and insert the label
+link."
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-insert-ref-function
+  nil
+  "Function to call to insert ref links.
+This function should prompt for a label with completion, and
+insert the ref link."
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-cite-onclick-function
+  nil
+  "Function that runs when you click on a cite link.
+The function must take one argument which is the path of the link
+that was clicked on."
+  :type 'function
+  :group 'org-ref)
+
+
+(defvar org-ref-prefix-arg nil
+  "Variable to store a prefix arg during completion.")
+
+
+(defun org-ref-minibuffer-prefix ()
+  "Hook function for `minibuffer-setup-hook'.
+The idea is to locally bind C-u to a function that captures
+prefix args in `org-ref-prefix-arg' so you can use them later."
+  (setq org-ref-prefix-arg nil)
+  (local-set-key (kbd "C-u") (lambda ()
+                              (interactive)
+                              (setq org-ref-prefix-arg
+                                    (if (null org-ref-prefix-arg)
+                                        '(4)
+                                      (list (* 4 (car org-ref-prefix-arg))))))))
+
+
+;; * Bibliography related functions
+
+(defun org-ref-find-bibliography ()
+  "Find the bibliography in the buffer.
+This function sets and returns a list of files either from internal bibliographies, from files in the
+BIBINPUTS env var, and finally falling back to what the user has
+set in `bibtex-completion-bibliography'"
+  (let ((org-ref-bibliography-files ()))
+    (catch 'result
+      (save-excursion
+       (when (eq major-mode 'org-mode)
+         (org-with-wide-buffer
+           (goto-char (point-min))
+          ;; This just searches for these strings, and then checks if it
+          ;; is on a link. This is faster than parsing the org-file when
+          ;; it gets large.
+           ;; look for org-ref bibliography
+           (while (re-search-forward "\\(no\\)?bibliography:" nil t)
+            (let ((link (org-element-context)))
+              (when (and (eq (car link) 'link)
+                         (member (org-element-property :type link) '("bibliography" "nobibliography")))
+                (setq org-ref-bibliography-files
+                      (mapcar 'org-ref-get-bibfile-path
+                              (mapcar 'string-trim (split-string
+                                                    (org-element-property :path link)
+                                                    ","))))
+                (throw 'result (nreverse (delete-dups org-ref-bibliography-files))))))
+
+           (goto-char (point-min))
+           (while (re-search-forward "\\\\addbibresource{\\(.*\\)}" nil t)
+             (push (match-string 1) org-ref-bibliography-files))
+
+           (when org-ref-bibliography-files
+             (throw 'result (nreverse (delete-dups (mapcar 'org-ref-get-bibfile-path org-ref-bibliography-files)))))))
+       ;; we did not find anything. use defaults. Make sure we have a list in
+        ;; case it is a single string. 
+       (throw 'result (if (listp bibtex-completion-bibliography)
+                          bibtex-completion-bibliography
+                        (list bibtex-completion-bibliography)))))))
+
+
+(defun org-ref-key-in-file-p (key filename)
+  "Determine if the KEY is in the FILENAME."
+  (with-temp-buffer
+    (insert-file-contents filename)
+    (hack-local-variables)
+    (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+    (bibtex-search-entry key)))
+
+
+(defun org-ref-possible-bibfiles ()
+  "Make a unique list of possible bibliography files for completing-read"
+  (-uniq
+   (append
+    ;; see if we should add it to a bib-file defined in the file
+    (org-ref-find-bibliography)
+    ;; or any bib-files that exist in the current directory
+    (f-entries "." (lambda (f)
+                    (and (not (string-match "#" f))
+                         (f-ext? f "bib"))))
+    ;; and last in the default bibliography
+    (if (stringp bibtex-completion-bibliography)
+       (list bibtex-completion-bibliography)
+      bibtex-completion-bibliography))))
+
+
+(defun org-ref-get-bibtex-key-and-file (&optional key)
+  "Return a  a cons cell of (KEY . file) that KEY is in.
+If no key is provided, get one under point."
+  (unless key
+    (setq key (org-ref-get-bibtex-key-under-cursor)))
+
+  (cons key (save-window-excursion
+             (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
+               (bibtex-completion-show-entry (list key))
+               (buffer-file-name)))))
+
+
+;; * Insert link functions
+
+;;;###autoload
+(defun org-ref-insert-link (arg)
+  "Insert an org-ref link.
+If no prefix ARG insert a cite.
+If one prefix ARG insert a ref.
+If two prefix ARGs insert a label.
+
+This is a generic function. Specific backends might
+provide their own version."
+  (interactive "P")
+  (cond
+   ((eq arg nil)
+    (funcall org-ref-insert-cite-function))
+   ((equal arg '(4))
+    (funcall org-ref-insert-ref-function))
+   ((equal arg '(16))
+    (funcall org-ref-insert-label-function))))
+
+
+;; This is an alternative that doesn't rely on prefix args.
+(defhydra org-ref-insert-link-hydra (:color red :hint nil)
+  "Insert an org-ref link
+"
+  ("[" (funcall org-ref-insert-cite-function) "Citation" :column "org-ref")
+  ("]" (funcall org-ref-insert-ref-function) "Cross-reference" :column "org-ref")
+  ("\\" (funcall org-ref-insert-label-function) "Label"  :column "org-ref")
+  
+  ("bs" (insert (org-ref-bibliographystyle-complete-link)) "Bibliographystyle" :column "Bibliography" :color blue)
+  ("bf" (insert (org-ref-bibliography-complete)) "Bibliography" :column "Bibliography" :color blue)
+  ("nb" (insert (org-ref-nobibliography-complete)) "Bibliography" :column "Bibliography" :color blue)
+  
+  ("g" org-ref-insert-glossary-link "Glossary link" :column "Glossary" :color blue)
+  ("a" org-ref-insert-acronym-link "Acronym link" :column "Glossary" :color blue)
+  ("ng" (progn
+         (org-mark-ring-push)
+         (goto-char (point-min))
+         (if (re-search-forward "#\\+name: glossary" nil t)
+             (progn
+               (goto-char (org-element-property :contents-end (org-element-context)))
+               (backward-char)
+               (org-table-insert-row '(4)))
+           ;; no table found
+           (goto-char (point-max))
+           (insert "\n\n#+name: glossary
+| label | term    | definition                    |
+|-------+---------+-------------------------------|
+|       |         |                               |")
+           (beginning-of-line)
+           (forward-char)))
+   "New glossary term" :column "Glossary")
+  
+  ("na" (progn
+         (org-mark-ring-push)
+         (goto-char (point-min))
+         (if (re-search-forward "#\\+name: acronym" nil t)
+             (progn
+               (goto-char (org-element-property :contents-end (org-element-context)))
+               (backward-char)
+               (org-table-insert-row '(4)))
+           ;; no table found
+           (goto-char (point-max))
+           (insert "\n\n#+name: acronyms
+| label | abbreviation | full form                  |
+|-------+--------------+----------------------------|
+|       |              |                            |")
+           (beginning-of-line)
+           (forward-char)))
+   "New acronym term" :column "Glossary")
+
+  ("bd" doi-add-bibtex-entry "Add bibtex entry from a DOI" :column "Bibtex")
+  ("bc" crossref-add-bibtex-entry "Add bibtex entry from Crossref" :column "Bibtex")
+  ("bo" (find-file (completing-read "Bibliography: " (org-ref-find-bibliography)))
+   "Open bibtex file" :column "Bibtex")
+  
+  ("t" (insert "[[list-of-tables:]]\n") "List of tables" :column "Misc")
+  ("f" (insert "[[list-of-figures:]]\n") "List of figures" :column "Misc")
+  ("i" (insert (format "[[index:%s]]" (string-trim (read-string "Index entry: ")))) "Index entry" :column "Misc")
+  ("pi" (insert "[[printindex:]]") "Print index" :column "Misc")
+  ("pg" (insert "[[printglossaries:]]") "Print glossary" :column "Misc"))
+
+
+;;* org-ref-help
+;;;###autoload
+(defun org-ref-help ()
+  "Open the `org-ref' manual."
+  (interactive)
+  (find-file (expand-file-name
+              "org-ref.org"
+              (file-name-directory
+               (find-library-name "org-ref")))))
+
+
+;;* org-ref menu
+
+(defun org-ref-org-menu ()
+  "Add `org-ref' menu to the Org menu."
+
+  (easy-menu-change
+   '("Org") "org-ref"
+   `(["Insert citation" ,org-ref-insert-cite-function]
+     ["Insert ref" ,org-ref-insert-ref-function]
+     ["Insert label" ,org-ref-insert-label-function]
+     "--"
+     ["List of figures" org-ref-list-of-figures]
+     ["List of tables" org-ref-list-of-tables]
+     ["Extract bibtex entries" org-ref-extract-bibtex-entries]
+     ["Check org-file" org-ref]
+     "--"
+     ["Help" org-ref-help]
+     ["Customize org-ref" (customize-group 'org-ref)])
+   "Show/Hide")
+
+  (easy-menu-change '("Org") "--" nil "Show/Hide"))
+
+(add-hook 'org-mode-hook 'org-ref-org-menu)
+
+
+
+;;* The end
+(provide 'org-ref-core)
+
+;;; org-ref-core.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-export.el b/elpa/org-ref-20230507.1420/org-ref-export.el
new file mode 100644 (file)
index 0000000..9902f48
--- /dev/null
@@ -0,0 +1,672 @@
+;;; org-ref-export.el --- org-ref-export library -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;; This is an export library that uses CSL to process the citations and bibliography.
+;;
+;; It is intended for non-LaTeX exports, but you can also use it with LaTeX if
+;; you want to avoid using bibtex/biblatex for some reason.
+;;
+;; The default style is set by a CSL-STYLE keyword or
+;; `org-ref-csl-default-style'. If this is an absolute or relative path that
+;; exists, it is used. Otherwise, it looks in `org-cite-csl-styles-dir' from
+;; `org-cite' if it is defined, and in the citeproc/csl-styles directory in
+;; `org-ref' otherwise.
+;;
+;; The default locale is set by a CSL-LOCALE keyword or
+;; `org-ref-csl-default-locale'. This is looked for in
+;; `org-cite-csl-locales-dir' if it is defined, and otherwise in the csl-locales
+;; directory of `org-ref'.
+;;
+;; Note that citeproc does not do anything for cross-references, so if non-LaTeX
+;; export is your goal, you may want to use org-ref-refproc.el to handle
+;; cross-references.
+;;
+
+;;; Code:
+(eval-when-compile
+  (require 'hydra))
+
+(defvar hfy-user-sheet-assoc)                  ; to quiet compiler
+
+(require 'ox-org)
+(if (executable-find "pandoc")
+    (require 'ox-pandoc))
+
+(require 'citeproc)
+
+(defcustom org-ref-backend-csl-formats
+  '((html . html)
+    (latex . latex)
+    (md . plain)
+    (org . org)
+    (ascii . plain)
+    (odt . org-odt)
+    (docx . org))
+  "Mapping of export backend to csl-backends."
+  :type '(alist :key-type (symbol) :value-type (symbol))
+  :group 'org-ref)
+
+
+(defcustom org-ref-cite-internal-links 'auto
+  "Should be one of
+- 'bib-links :: link cites to bibliography entries
+- 'no-links :: do not link cites to bibliography entries
+- nil or 'auto :: add links based on the style."
+  :type '(choice bib-links no-links auto nil)
+  :group 'org-ref)
+
+
+(defcustom org-ref-csl-default-style "chicago-author-date-16th-edition.csl"
+  "Default csl style to use.
+Should be a csl filename, or an absolute path to a csl filename."
+  :type 'string
+  :group 'org-ref)
+
+
+(defcustom org-ref-csl-default-locale "en-US"
+  "Default csl locale to use."
+  :type 'string
+  :group 'org-ref)
+
+
+(defcustom org-ref-csl-label-aliases
+  '((("app" "apps") . "appendix")
+    (("art" "arts") . "article-locator")
+    (("bk" "bks") . "book")
+    (("can") . "canon")
+    (("ch" "chap" "chaps" "chapt") . "chapter")
+    (("col" "cols") . "column")
+    (("el") . "elocation")
+    (("eq" "eqs") . "equation")
+    (("fig" "figs") . "figure")
+    (("fol" "fols") . "folio")
+    (("iss") . "issue")
+    (("l" "ll") . "line")
+    (("n" "nn") . "note")
+    ;; number is not listed in the url in the docstring
+    (("no" "nos" "#") . "number")
+    (("op" "opp") . "opus")
+    (("p" "pp" "pg" "pgs") . "page")
+    (("para" "paras" "¶" "¶¶" "§" "§§") . "paragraph")
+    (("pt" "pts") . "part")
+    (("sec" "secs") . "section")
+    (("s.v" "s.vv") . "sub verbo")
+    (("sup" "supp") . "supplement")
+    (("tab" "tabs") . "table")
+    (("ts") . "timestamp")
+    (("ti" "tit") . "title")
+    (("v" "vv") . "verse")
+    (("vol" "vols") . "volume"))
+  "A-list of aliases for a csl label.
+The car is a list of possible aliases (including if they end in a .
+This list was adapted from `org-cite-csl--label-alist'.
+See https://github.com/citation-style-language/documentation/blob/master/specification.rst#locators"
+  :type '(alist :key-type (list (repeat string)) :value-type string)
+  :group 'org-ref)
+
+
+(defcustom org-ref-export-suppress-affix-types 
+  '("citet"
+    "citet*"
+    "citetitle"
+    "citeyear"
+    "citeauthor"
+    "citenum"
+    "textcite")
+  "List of cite types to suppress affixes (usually parentheses) on."
+  :type '(list (repeat string))
+  :group 'org-ref)
+
+
+(defun org-ref-dealias-label (alias)
+  "Return the full, de-aliased label for ALIAS.
+Looked up from `org-ref-csl-label-aliases'.
+
+I added this because I think it is reasonable to expect if you
+write pg. 2 that it will show that way when rendered. At the
+moment that is not the case, and only page is accepted. This is
+actually done in oc-csl too, although it uses a flat a-list."
+  (or (cdr (assoc "page" org-ref-csl-label-aliases
+                 (lambda (x1 _x2)
+                   (or (member alias x1)
+                       (member (concat (downcase alias) ".") x1)))))
+      alias))
+
+
+(defun org-ref-get-cite-links ()
+  "Return list of cite links in the order they appear in the buffer."
+  (org-element-map (org-element-parse-buffer) 'link
+    (lambda (lnk)
+      (when (assoc (org-element-property :type lnk) org-ref-cite-types)
+       lnk))))
+
+
+(defun org-ref-ref-csl-data (ref type)
+  "Return the CSL alist for a REF of TYPE.
+REF is a plist data structure returned from `org-ref-parse-cite-path'."
+  ;; I believe the suffix contains "label locator suffix"
+  ;; where locator is a number, or maybe a range of numbers like 5-6.
+  ;; label is something like page or chapter
+  ;; and the rest is the suffix text.
+  ;; For example: ch. 5, for example
+  ;; would be label = ch., locator=5, ",for example" as suffix.
+  (let* ((full-suffix (string-trim (or (plist-get ref :suffix) ""))) 
+        locator
+        label locator suffix)
+
+    ;; org-cite is more sophisticated than this and would allow things like 5, 6
+    ;; and 12. I am not sure about what all should be supported yet. I guess the
+    ;; idea there is you use everything from the first to last number as the
+    ;; locator, but that seems tricky, what about something like: 5, 6 and 12,
+    ;; because he had 3 books. One solution might be some kind of delimiter,
+    ;; e.g. {5, 6 and 12}, because he had 3 books.
+
+    (if (and (string-match
+             (rx-to-string
+              `(seq
+                ;; optional label
+                (group-n 1 (optional
+                            (regexp ,(regexp-opt (cl-loop for (abbrvs . full)
+                                                          in org-ref-csl-label-aliases
+                                                          append (append abbrvs (list full)))))))
+                (optional (one-or-more space))
+                ;; number or numeric ranges
+                (group-n 2 (one-or-more digit) (optional "-" (one-or-more digit)))
+                ;; everything else
+                (group-n 3 (* "."))))        
+             full-suffix)
+            (match-string 2 full-suffix)
+            (not (string= "" (match-string 2 full-suffix)))) 
+       ;; We found a locator
+       (setq label (match-string 1 full-suffix)
+             locator (match-string 2 full-suffix)
+             suffix (match-string 3 full-suffix))
+      (setq label nil
+           locator nil
+           suffix full-suffix))
+    
+    ;; Let's assume if you have a locator but not a label that you mean page.
+    (when (and locator (string= "" (string-trim label)))
+      (setq label "page"))
+    
+    `((id . ,(plist-get ref :key))
+      (prefix . ,(plist-get ref :prefix))
+      (suffix . ,suffix)
+      (locator . ,locator)
+      (label . ,(when label (org-ref-dealias-label (string-trim label))))
+      ;; TODO: proof of concept and not complete. I did not go through all the
+      ;; types to see what else should be in here.
+      (suppress-author . ,(not (null (member type
+                                            '("citenum"
+                                              "citeyear"
+                                              "citeyear*"
+                                              "citedate"
+                                              "citedate*"
+                                              "citetitle"
+                                              "citetitle*"
+                                              "citeurl"))))))))
+
+(declare-function org-ref-find-bibliography "org-ref-core")
+
+(defun org-ref-process-buffer (backend &optional subtreep)
+  "Process the citations and bibliography in the org-buffer.
+Usually run on a copy of the buffer during export.
+BACKEND is the org export backend."
+  (save-restriction
+    (when subtreep
+      (org-narrow-to-subtree))
+    (let* ((csl-backend (or (cdr (assoc backend org-ref-backend-csl-formats)) 'plain))
+
+          (style (or (cadr (assoc "CSL-STYLE"
+                                  (org-collect-keywords
+                                   '("CSL-STYLE"))))
+                     org-ref-csl-default-style))
+          (locale (or (cadr (assoc "CSL-LOCALE"
+                                   (org-collect-keywords
+                                    '("CSL-LOCALE"))))
+                      org-ref-csl-default-locale))
+
+          (proc (citeproc-create
+                 ;; The style
+                 (cond
+                  ((file-exists-p style)
+                   style)
+                  ;; In a user-dir
+                  ((and (bound-and-true-p org-cite-csl-styles-dir)
+                        (file-exists-p (f-join org-cite-csl-styles-dir style)))
+                   (f-join org-cite-csl-styles-dir style))
+                  ;; provided by org-ref
+                  ((file-exists-p (expand-file-name style
+                                                    (f-join (file-name-directory
+                                                             (locate-library "org-ref"))
+                                                            "citeproc/csl-styles")))
+                   (expand-file-name style (f-join
+                                            (file-name-directory
+                                             (locate-library "org-ref"))
+                                            "citeproc/csl-styles")))
+                  (t
+                   (error "%s not found" style)))
+                 ;; item-getter
+                 ;; (citeproc-itemgetter-from-bibtex (org-ref-find-bibliography))
+                 (citeproc-hash-itemgetter-from-any (org-ref-find-bibliography) t)
+                 ;; locale getter
+                 (citeproc-locale-getter-from-dir (if (bound-and-true-p org-cite-csl-locales-dir)
+                                                      org-cite-csl-locales-dir
+                                                    (f-join (file-name-directory
+                                                             (locate-library "org-ref"))
+                                                            "citeproc/csl-locales")))
+                 ;; the actual locale
+                 locale))
+
+          ;; list of links in the buffer
+          (cite-links (org-element-map (org-element-parse-buffer) 'link
+                        (lambda (lnk)
+                          (when (assoc (org-element-property :type lnk) org-ref-cite-types)
+                            lnk))))
+
+          (cites (cl-loop for cl in cite-links collect
+                          (let* ((cite-data (org-ref-parse-cite-path (org-element-property :path cl)))
+                                 (common-prefix (or (plist-get cite-data :prefix) ""))
+                                 (common-suffix (or (plist-get cite-data :suffix) ""))
+                                 (refs (plist-get cite-data :references))
+                                 (type (org-element-property :type cl))
+
+                                 (cites (cl-loop for ref in refs collect
+                                                 (org-ref-ref-csl-data ref type))))
+                            ;; TODO: update eventually
+                            ;; https://github.com/andras-simonyi/citeproc-el/issues/46
+                            ;; To handle common prefixes, suffixes, I just concat
+                            ;; them with the first/last entries. That is all that
+                            ;; is supported for now. Combine common/local prefix
+                            (setf (cdr (assoc 'prefix (cl-first cites)))
+                                  (concat common-prefix
+                                          (cdr (assoc 'prefix (cl-first cites)))))
+                            ;; Combine local/common suffix
+                            (setf (cdr (assoc 'suffix (car (last cites))))
+                                  (concat (cdr (assoc 'suffix (car (last cites))))
+                                          common-suffix))
+
+                            ;; https://github.com/andras-simonyi/citeproc-el#creating-citation-structures
+                            (citeproc-citation-create
+                             :cites cites
+                             :suppress-affixes (let ((type (org-element-property :type cl)))
+                                                 (when (member type
+                                                               org-ref-export-suppress-affix-types)
+                                                   t))
+
+                             ;; TODO: this is proof of concept, and not complete.
+                             ;; mode is one of suppress-author, textual,
+                             ;; author-only, year-only, or nil for default. These
+                             ;; are not all clear to me.
+                             :mode (let ((type (org-element-property :type cl)))
+                                     (cond
+                                      ((member type '("citet" "citet*"))
+                                       'textual)
+                                      ((member type '("citeauthor" "citeauthor*"))
+                                       'author-only)
+                                      ((member type '("citeyear" "citeyear*"))
+                                       'year-only)
+                                      ((member type '("citedate" "citedate*"))
+                                       'suppress-author)
+                                      (t
+                                       nil)))
+
+                             ;; I think the capitalized styles are what this is for
+                             :capitalize-first (string-match
+                                                "[A-Z]"
+                                                (substring
+                                                 (org-element-property :type cl) 0 1))
+                             ;; I don't know where this information would come from.
+                             :note-index nil
+                             :ignore-et-al nil
+                             :grouped nil))))
+
+          (rendered-citations (progn (citeproc-append-citations cites proc)
+                                     (citeproc-render-citations proc csl-backend org-ref-cite-internal-links)))
+          ;; I only use the returned bibliography string. citeproc returns a
+          ;; bunch of other things related to offsets and linespacing, but I
+          ;; don't know what you do with these, so just ignore them here.
+          (bibdata (citeproc-render-bib proc csl-backend))
+          (rendered-bib (car bibdata))
+          (bib-parameters (cdr bibdata))
+          ;; The idea is we will wrap each citation and the bibliography in
+          ;; org-code so it exports appropriately.
+          (cite-formatters '((html . "@@html:%s@@")
+                             (latex . "@@latex:%s@@")
+                             (odt . "@@odt:%s@@")))
+          (bib-formatters '((html .  "\n#+BEGIN_EXPORT html\n%s\n#+END_EXPORT\n")
+                            (latex .  "\n#+BEGIN_EXPORT latex\n%s\n#+END_EXPORT\n")
+                            (odt . "\n#+BEGIN_EXPORT ODT\n%s\n#+END_EXPORT\n"))))
+
+      ;; replace the cite links
+      (cl-loop for cl in (reverse cite-links) for rc in (reverse rendered-citations) do
+              (cl--set-buffer-substring (org-element-property :begin cl)
+                                        (org-element-property :end cl)
+                                        (format (or
+                                                 (cdr (assoc backend cite-formatters))
+                                                 "%s")
+                                                (concat
+                                                 rc
+                                                 ;; Add on extra spaces that were
+                                                 ;; following it.
+                                                 (make-string
+                                                  (or
+                                                   (org-element-property :post-blank cl) 0)
+                                                  ? )))))
+
+      ;; Decorate the bibliography for different outputs adapted from
+      ;;  `org-cite-csl-render-bibliography' in oc-csl I don't know what all
+      ;;  these do or how to use them in the CSS for html, or LaTeX. This is to
+      ;;  fix an annoying HTML feature that has an extra line in the numbering.
+      ;;  This seems to do the right thing. I don't support hanging-indent like
+      ;;  oc-csl does, and I don't currently support LaTeX here. It already does
+      ;;  a good job there.
+      ;;
+      ;; (find-library "oc-csl")
+      ;;
+      ;; Here are some examples of what is in the bib-parameters.
+      ;;  (max-offset . 2) (hanging-indent) (second-field-align . flush)
+      ;; (entry-spacing . 0)
+      ;; (line-spacing . 2)
+      ;;
+      ;; Here we add style css for html output.
+      (cond
+       ((or (eq 'html backend) (eq 'html csl-backend))
+       (let ((s1 "")
+             (s2 ""))
+         (when (cdr (assq 'second-field-align bib-parameters))
+           (setq s1 (format
+                     "<style>.csl-left-margin{float: left; padding-right: 0em;}
+ .csl-right-inline{margin: 0 0 0 %dem;}</style>"
+                     ;; I hard coded this factor of 0.6 from the oc-csl code.  
+                     (* 0.6  (or (cdr (assq 'max-offset bib-parameters)) 0)))))
+
+         ;; hard-coded the hanging indent. oc-csl uses a variable for this. I
+         ;; guess we could too, but this seems simpler.
+         (when (cdr (assq 'hanging-indent bib-parameters))
+           (setq s2 "<style>.csl-entry{text-indent: -1.5em; margin-left: 1.5em;}</style>"))
+         
+         (setq rendered-bib (concat
+                             s1 s2
+                             rendered-bib)))))
+
+      ;; replace the bibliography
+      (org-element-map (org-element-parse-buffer) 'link
+       (lambda (lnk)
+         (cond
+          ((string= (org-element-property :type lnk) "bibliography")
+           (cl--set-buffer-substring (org-element-property :begin lnk)
+                                     (org-element-property :end lnk)
+                                     (format (or
+                                              (cdr (assoc backend bib-formatters))
+                                              "%s")
+                                             rendered-bib)))
+          ;; We just get rid of nobibliography links.
+          ((string= (org-element-property :type lnk) "nobibliography")
+           (cl--set-buffer-substring (org-element-property :begin lnk)
+                                     (org-element-property :end lnk)
+                                     "")))))
+      ;; For LaTeX we need to define the citeprocitem commands
+      ;; see https://www.mail-archive.com/emacs-orgmodeNOSPAMgnu.org/msg138546.html
+      (when (eq backend 'latex)
+       (goto-char (point-min))
+       (insert "#+latex_header: \\makeatletter
+#+latex_header: \\newcommand{\\citeprocitem}[2]{\\hyper@linkstart{cite}{citeproc_bib_item_#1}#2\\hyper@linkend}
+#+latex_header: \\makeatother\n")))))
+
+
+(defun org-ref-export-to (backend &optional async subtreep visible-only
+                                 body-only info)
+  "Export buffer to BACKEND.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (let* ((fname (buffer-file-name))
+        (extensions '((html . ".html")
+                      (latex . ".tex")
+                      (ascii . ".txt")
+                      (md . ".md")
+                      (odt . ".odf")))
+        (cp (point))
+        (mm)                           ;marker to save place
+        (export-name (concat (file-name-sans-extension fname)
+                             (or (cdr (assoc backend extensions)) ""))))
+
+    (org-export-with-buffer-copy
+     ;; Note I use a marker here to make sure we stay in the same place we were.
+     ;; This is more robust than save-excursion I think, since processing moves
+     ;; points around. In theory the marker should move too.
+     (setq mm (make-marker))
+     (move-marker mm cp)
+     ;; make sure we expand includes
+     (org-export-expand-include-keyword)
+     (goto-char (marker-position mm))
+     (org-ref-process-buffer backend subtreep)
+     (set-marker mm nil)
+     
+     (pcase backend
+       ;; odt is a little bit special, and is missing one argument
+       ('odt (org-open-file (org-odt-export-to-odt async subtreep visible-only
+                                                  info)
+                           'system))
+       ;; for pandoc, we mean make a docx via pandoc
+       ('docx (org-open-file (plist-get (org-pandoc-export-to-docx async subtreep visible-only
+                                                                  body-only info)
+                                       'output-file)
+                            'system))
+       (_
+       (org-open-file (org-export-to-file backend export-name
+                        async subtreep visible-only
+                        body-only info)
+                      'system))))))
+
+
+;; I guess I tried to use apply-partially here, and it did not work, so these
+;; are each defined manually
+
+(defun org-ref-export-to-html (&optional async subtreep visible-only
+                                        body-only info)
+  "Export the buffer to HTML and open.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (org-ref-export-to 'html async subtreep visible-only
+                    body-only info))
+
+
+(defun org-ref-export-to-ascii (&optional async subtreep visible-only
+                                         body-only info)
+  "Export the buffer to ascii and open.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (org-ref-export-to 'ascii async subtreep visible-only
+                    body-only info))
+
+
+(defun org-ref-export-to-md (&optional async subtreep visible-only
+                                      body-only info)
+  "Export the buffer to md and open.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (org-ref-export-to 'md async subtreep visible-only
+                    body-only info))
+
+
+(defun org-ref-export-to-pdf (&optional async subtreep visible-only
+                                       body-only info)
+  "Export the buffer to PDF via LaTeX and open.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (let ((org-export-before-parsing-hook (append
+                                        org-export-before-parsing-hook
+                                        '(org-ref-csl-preprocess-buffer))))
+    (org-open-file (org-latex-export-to-pdf async subtreep visible-only
+                                           body-only info))))
+
+
+(defun org-ref-export-to-latex (&optional async subtreep visible-only
+                                         body-only info)
+  "Export the buffer to LaTeX and open.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (org-ref-export-to 'latex async subtreep visible-only
+                    body-only info))
+
+
+(defun org-ref-export-to-odt (&optional async subtreep visible-only
+                                       body-only info)
+  "Export the buffer to ODT and open.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (require 'htmlfontify)
+  (unless (boundp 'hfy-user-sheet-assoc) (setq  hfy-user-sheet-assoc nil))
+  (org-ref-export-to 'odt async subtreep visible-only
+                    body-only info))
+
+
+(defun org-ref-export-to-docx (&optional async subtreep visible-only
+                                        body-only info)
+  "Export the buffer to docx via pandoc and open.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (org-ref-export-to 'docx async subtreep visible-only
+                    body-only info))
+
+
+(defun org-ref-export-as-org (&optional _async subtreep visible-only
+                                       body-only info)
+  "Export the buffer to an ORG buffer and open.
+We only make a buffer here to avoid overwriting the original file.
+See `org-export-as' for the meaning of ASYNC SUBTREEP
+VISIBLE-ONLY BODY-ONLY and INFO."
+  (let* ((export-buf "*org-ref ORG Export*")
+        export)
+
+    (org-export-with-buffer-copy
+     (org-ref-process-buffer 'org subtreep)
+     (setq export (org-export-as 'org subtreep visible-only body-only info))
+     (with-current-buffer (get-buffer-create export-buf)
+       (erase-buffer)
+       (org-mode)
+       (insert export)))
+    (pop-to-buffer export-buf)))
+
+
+(defun org-ref-export-to-message (&optional _async subtreep visible-only
+                                           body-only info)
+  "Export to ascii and insert in an email message."
+  (let* ((backend 'ascii)
+        (content (org-export-with-buffer-copy
+                  (org-ref-process-buffer backend subtreep)
+                  (org-export-as backend subtreep visible-only
+                                 body-only info))))
+    (compose-mail)
+    (message-goto-body)
+    (insert content)
+    (message-goto-to)))
+
+
+(org-export-define-derived-backend 'org-ref 'org
+  :menu-entry
+  '(?r "Org-ref export"
+       ((?a "to Ascii" org-ref-export-to-ascii)
+       (?m "to markdown" org-ref-export-to-md)
+       (?h "to html" org-ref-export-to-html)
+       (?l "to LaTeX" org-ref-export-to-latex)
+       (?p "to PDF" org-ref-export-to-pdf)
+       (?o "to ODT" org-ref-export-to-odt)
+       (?O "to Org buffer" org-ref-export-as-org)
+       (?e "to email" org-ref-export-to-message)
+       (?w "to docx" org-ref-export-to-docx))))
+
+;; An alternative to this exporter is to use an  `org-export-before-parsing-hook'
+;; (add-hook 'org-export-before-parsing-hook 'org-ref-csl-preprocess-buffer)
+
+(defun org-ref-csl-preprocess-buffer (backend)
+  "Preprocess the buffer in BACKEND export.
+Note this may not work as expected, what about subtreep? The hook
+function just takes one argument. For now we rely on
+`buffer-narrowed-p' and an org-heading at the beginning.
+I am not positive on this though."
+  (org-ref-process-buffer backend (and (buffer-narrowed-p)
+                                      (save-excursion
+                                        (goto-char (point-min))
+                                        (org-at-heading-p)))))
+
+
+;; A hydra exporter with preprocessors
+(defhydradio org-ref ()
+  (natmove "natmove")
+  (citeproc "CSL citations")
+  (refproc "cross-references")
+  (acrossproc "Acronyms, glossary")
+  (idxproc "Index")
+  (bblproc "BBL citations"))
+
+
+(defun org-ref-export-from-hydra (&optional arg)
+  "Run the export dispatcher with the desired hooks selected in `org-ref-export/body'."
+  (interactive "P")
+
+  (when (and org-ref/citeproc org-ref/bblproc)
+    (error "You cannot use CSL and BBL at the same time."))
+  
+  (let ((org-export-before-parsing-hook org-export-before-parsing-hook))
+    (when org-ref/citeproc
+      (cl-pushnew 'org-ref-csl-preprocess-buffer org-export-before-parsing-hook))
+
+    (when org-ref/refproc
+      (cl-pushnew 'org-ref-refproc org-export-before-parsing-hook))
+
+    (when org-ref/acrossproc
+      (cl-pushnew 'org-ref-acrossproc org-export-before-parsing-hook))
+
+    (when org-ref/idxproc
+      (cl-pushnew 'org-ref-idxproc org-export-before-parsing-hook))
+
+    (when org-ref/bblproc
+      (unless (featurep 'org-ref-natbib-bbl-citeproc)
+       (require 'org-ref-natbib-bbl-citeproc))
+      (cl-pushnew 'org-ref-bbl-preprocess org-export-before-parsing-hook))
+    
+    ;; this goes last since it moves cites before they might get replaced.
+    (when org-ref/natmove
+      (cl-pushnew 'org-ref-cite-natmove org-export-before-parsing-hook))
+
+    (org-export-dispatch arg)))
+
+
+(defhydra org-ref-export (:color red)
+  "
+_C-n_: natmove % -15`org-ref/natmove       _C-c_: citeproc % -15`org-ref/citeproc^^^  _C-r_: refproc % -15`org-ref/refproc^^^
+_C-a_: acrossproc % -15`org-ref/acrossproc    _C-i_: idxproc % -15`org-ref/idxproc^^^   _C-b_: bblproc % -15`org-ref/bblproc^^^
+"
+  ("C-n" (org-ref/natmove) nil)
+  ("C-c" (org-ref/citeproc) nil)
+  ("C-r" (org-ref/refproc) nil)
+  ("C-a" (org-ref/acrossproc) nil)
+  ("C-i" (org-ref/idxproc) nil)
+  ("C-b" (org-ref/bblproc) nil)
+
+  ("e" org-ref-export-from-hydra "Export" :color blue)
+  ("q" nil "quit"))
+
+(provide 'org-ref-export)
+
+;;; org-ref-export.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-glossary.el b/elpa/org-ref-20230507.1420/org-ref-glossary.el
new file mode 100644 (file)
index 0000000..fc6ec4a
--- /dev/null
@@ -0,0 +1,980 @@
+;;; org-ref-glossary.el --- glossary support in org-ref  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides Some acronym and glossary support for org-mode. Only export to LaTeX
+;; is currently supported. The functionality is based on the LaTeX glossaries
+;; package. See https://en.wikibooks.org/wiki/LaTeX/Glossary and
+;; http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/glossaries/glossaries-user.pdf
+
+;; Put something like this in your org-file.
+;; #+latex_header: \usepackage{glossaries}
+;; #+latex_header: \makeglossaries
+
+;; Put this where you want the glossaries to appear in your org-file.
+;; [[printglossaries:]]
+
+;; This is the preferred way to add glossary entries to an org-file. The table
+;; must be named glossary.
+;; 
+;; #+name: glossary
+;; | label | name  | description   |
+;; |-------+-------+---------------|
+;; | tree  | Tree  | A woody plant |
+;; | shrub | Shrub | A woody bush  |
+;;
+;; This is the preferred way to add acronyms
+;; #+name: acronyms
+;; | key  | abbreviation | full form                      |
+;; |------+--------------+--------------------------------|
+;; | mimo |              | multiple-input multiple output |
+;; | qos  | QoS          | quality-of-service             |
+;; | bb   | BB           | branch and bound               |
+;;
+;; Then add `org-ref-glossary-before-parsing' and
+;; `org-ref-acronyms-before-parsing' to the `org-export-before-parsing-hook'.
+
+;; See `org-ref-acronym-types' and `org-ref-glossary-gls-commands' for the types defined.
+
+;; Use `org-ref-insert-glossary-link' and `org-ref-insert-acronym-link' to
+;; insert a link with completion.
+
+;; * Known limitations
+;; 
+;; This only works well in a single file (i.e. you cannot include the tables
+;; from another file). I tried implementing that once, and it was too slow.
+
+
+
+;; * DEPRECATED way of adding entries
+;; This is still supported but using the tables is preferred.
+;; Add new glossary entries to your org-file like this. Enclose strings
+;; containing a comma in {}. Multiline entries are supported.
+
+;; #+latex_header_extra: \newglossaryentry{computer}{name=computer,description={A machine, that computes}}
+;; #+latex_header_extra: \newglossaryentry{tree}{name=tree,description=a big plant}
+
+;; #+latex_header_extra: \newglossaryentry{naiive}
+;; #+latex_header_extra: {
+;; #+latex_header_extra:   name=na\"{\i}ve,
+;; #+latex_header_extra:   description={is a French loanword (adjective, form of naïf)
+;; #+latex_header_extra:                indicating having or showing a lack of experience,
+;; #+latex_header_extra:                understanding or sophistication}
+;; #+latex_header_extra: }
+
+;; Here is an example acronym definition
+;; #+latex_header_extra: \newacronym{lvm}{LVM}{Logical Volume Manager}
+
+(require 'org-element)
+(require 'org-ref-utils)
+(require 'ox)
+
+;;; Code:
+(defgroup org-ref-glossary nil
+  "Customization group for org-ref-glossary."
+  :tag "Org Ref glossary"
+  :group 'org)
+
+
+(defcustom org-ref-activate-glossary-links t
+  "If non-nil activate acronym and glossary links.
+Checks in `org-ref-glossary-face-fn' and `org-ref-acronym-face-fn'.
+This is not always fast, so we provide a way to disable it."
+  :type 'boolean
+  :group 'org-ref-glossary)
+
+
+(defvar org-ref-glsentries '()
+  "Variable to hold locations of glsentries load files.")
+
+
+(defvar-local org-ref-glossary-cache nil
+  "Buffer-local variable for glossary entry cache.")
+
+
+(defvar-local org-ref-acronym-cache nil
+  "Buffer-local variable for acronym entry cache.")
+
+
+(defun or-find-closing-curly-bracket (&optional limit)
+  "Find closing bracket for the bracket at point and move point to it.
+Go up to LIMIT or `point-max'. This is a parsing function. I
+wrote this because using `forward-list' does not always work if
+there is an escaped \" for example. This seems pretty robust."
+  (unless (looking-at "{") (error "Not at a curley bracket"))
+
+  (let ((level 1))
+    (while (and (not (= 0 level))
+               (not (eobp))
+               (< (point) (or limit (point-max))))
+      (forward-char)
+      (when (and (looking-at "{")
+                (not (looking-back "\\\\" (- (point) 2))))
+       (cl-incf level))
+      (when (and (looking-at "}")
+                (not (looking-back "\\\\" (- (point) 2))))
+       (cl-decf level)))
+    (point)))
+
+
+;;* Glossary
+(defun or-parse-glossary-entry (entry)
+  "Parse a LaTeX glossary ENTRY definition to a p-list of key=value.
+ENTRY is the label we are looking for.
+Typically returns  (:name name :description description)
+but there could be other :key value pairs.
+
+This is a source of performance loss, because this is search
+based and it is done on each fontification. It is easy to cache
+the results, but not easy to invalidate them, e.g. to reflect
+changes."
+  (if (and org-ref-glossary-cache (gethash entry org-ref-glossary-cache))
+      ;; We have the cache, and an entry and use it
+      (gethash entry org-ref-glossary-cache)
+    ;; We don't have a cache, or an entry in it, so we find it.
+    ;; No cache? we make one
+    (unless org-ref-glossary-cache
+      (setq-local org-ref-glossary-cache (make-hash-table)))
+
+    ;; Now we search to get the data
+    (save-excursion
+      (goto-char (point-min))
+      (let* (end-of-entry
+            data
+            (external (when (re-search-forward
+                             "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
+                        (match-string 1)))
+            (glsentries (and external
+                             (or (cdr (assoc external org-ref-glsentries))
+                                 (progn
+                                   (cl-pushnew (cons external (s-trim
+                                                               (shell-command-to-string
+                                                                (format "kpsewhich tex %s"
+                                                                        external))))
+                                               org-ref-glsentries)
+                                   (cdr (assoc external org-ref-glsentries))))))
+            key value p1 p2)
+       (setq data
+             (catch 'data
+               ;; look inside first for latex-headers
+               (goto-char (point-min))
+               (when (re-search-forward
+                      (format "\\newglossaryentry{%s}" entry) nil t)
+                 (re-search-forward "{")
+                 (save-excursion
+                   (backward-char)
+                   (or-find-closing-curly-bracket)
+                   (setq end-of-entry (point)))
+
+                 (while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
+                   (setq key (match-string 1))
+                   ;; get value
+                   (goto-char (+ 1 (match-end 1)))
+                   (setq p1 (point))
+                   (if (looking-at "{")
+                       ;; value is wrapped in {}
+                       (progn
+                         (or-find-closing-curly-bracket)
+                         (setq p2 (point)
+                               value (buffer-substring (+ 1 p1) p2)))
+                     ;; value is up to the next comma
+                     (re-search-forward "," end-of-entry 'mv)
+                     (setq value (buffer-substring p1 (- (point) 1))))
+                   ;; remove #+latex_header_extra:
+                   (setq value (replace-regexp-in-string
+                                "#\\+latex_header_extra: " "" value))
+                   (setq value (replace-regexp-in-string
+                                "\n +" " " value))
+                   (setq data (append data
+                                      (list :label entry)
+                                      (list (intern (format ":%s" key)))
+                                      (list value))))
+                 (throw 'data data))
+
+               ;; check for a glossary table
+               (let* ((entries (save-excursion
+                                 (catch 'found
+                                   (org-element-map
+                                       (org-element-parse-buffer)
+                                       'table
+                                     (lambda (el)
+                                       (when (string= "glossary" (org-element-property :name el))
+                                         (goto-char (org-element-property :contents-begin el))
+                                         (throw 'found
+                                                (nthcdr 2 (org-babel-read-table)))))))))
+                      (result (assoc entry entries)))
+                 (when result
+                   (throw 'data (list :label entry :name (cl-second result) :description (cl-third result)))))
+
+               ;; then external
+               (when (and glsentries
+                          (file-exists-p glsentries))
+
+                 (with-current-buffer (find-file-noselect glsentries)
+                   (goto-char (point-min))
+                   (when (re-search-forward
+                          (format "\\newglossaryentry{%s}" entry) nil t)
+                     (re-search-forward "{")
+                     (save-excursion
+                       (backward-char)
+                       (or-find-closing-curly-bracket)
+                       (setq end-of-entry (point)))
+
+                     (while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
+                       (setq key (match-string 1))
+                       ;; get value
+                       (goto-char (+ 1 (match-end 1)))
+                       (setq p1 (point))
+                       (if (looking-at "{")
+                           ;; value is wrapped in {}
+                           (progn
+                             (or-find-closing-curly-bracket)
+                             (setq p2 (point)
+                                   value (buffer-substring (+ 1 p1) p2)))
+                         ;; value is up to the next comma
+                         (re-search-forward "," end-of-entry 'mv)
+                         (setq value (buffer-substring p1 (- (point) 1))))
+                       (setq data (append data
+                                          (list :label entry)
+                                          (list (intern (format ":%s" key)))
+                                          (list value))))
+                     (throw 'data data))))))
+       (puthash entry data org-ref-glossary-cache)
+       data))))
+
+
+;;;###autoload
+(defun org-ref-add-glossary-entry (label name description)
+  "Insert a new glossary entry.
+LABEL is how you refer to it with links.
+NAME is the name of the entry to be defined.
+DESCRIPTION is the definition of the entry.
+Entry gets added after the last #+latex_header line.
+
+This is not a preferred way to add entries. It is preferred to
+manually add them to the glossary table."
+  (interactive "sLabel: \nsName: \nsDescription: ") 
+  (save-excursion
+    (goto-char (point-max))
+    ;; get to the last latex_header line
+    (re-search-backward "#\\+latex_header" nil t)
+    (forward-line)
+    (when (not (looking-at "^$"))
+      (beginning-of-line)
+      (insert "\n")
+      (forward-line -1))
+    (insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name={%s},description={%s}}\n"
+                   label name description))))
+
+
+(defun org-ref-glossary-face-fn (label)
+  "Return a face for a glossary link."
+  (if org-ref-activate-glossary-links
+      (save-match-data
+       (cond
+        ((or-parse-glossary-entry label)
+         'org-ref-glossary-face)
+        (t
+         'font-lock-warning-face)))
+    'org-ref-glossary-face))
+
+
+;;** Glossary links
+(defun or-follow-glossary (entry)
+  "Goto beginning of the glossary ENTRY."
+  (org-mark-ring-push)
+  
+  (cond 
+   ;; Try finding in the table
+   ((progn (goto-char (point-min))
+          (and (re-search-forward "#\\+name: glossary" nil t)
+               (re-search-forward entry nil t)))
+    nil)
+
+   ((progn (goto-char (point-min)) (re-search-forward (format "\\newglossaryentry{%s}" entry) nil t))
+    (goto-char (match-beginning 0)))   
+
+   (t
+    (message "no entry found for %s" entry))))
+
+
+(defvar org-ref-glossary-gls-commands
+  '(("gls" "The term associated with the label")
+    ("glspl" "The plural term")
+    ("Gls" "The capitalized term")
+    ("Glspl" "The plural capitalized term")
+    ("glssymbol" "The symbol defined (only with latex definition)")
+    ("Glssymbol" "The capitalized symbol defined (only with latex definition)")
+    ("glsdesc" "The description associated with the label")
+    ("Glsdesc" "The capitalized description associated with the label"))
+  "An alist of (cmd description).")
+
+(dolist (command org-ref-glossary-gls-commands)
+  (org-link-set-parameters (cl-first command)
+                          :follow #'or-follow-glossary
+                          :face 'org-ref-glossary-face-fn
+                          :help-echo 'or-glossary-tooltip
+                          :export (lambda (path _ format)
+                                    (cond
+                                     ((memq format '(latex beamer))
+                                      (format "\\%s{%s}" (cl-first command) path))
+                                     (t
+                                      (format "%s" path))))))
+
+
+(org-link-set-parameters "glslink"
+                        :follow #'or-follow-glossary
+                        :face 'org-ref-glossary-face-fn
+                        :help-echo 'or-glossary-tooltip
+                        :export (lambda (path desc format)
+                                  (cond
+                                   ((memq format '(latex beamer))
+                                    (format "\\glslink{%s}{%s}" path desc))
+                                   (t
+                                    (format "%s" path)))))
+
+;;** Tooltips on glossary entries
+(defface org-ref-glossary-face
+  `((t (:inherit org-link :foreground "Mediumpurple3")))
+  "Face for glossary links.")
+
+
+(defun or-glossary-tooltip (_window _object position)
+  "Return tooltip for the glossary entry.
+The entry is in WINDOW and OBJECT at POSITION.
+Used in fontification."
+  (save-excursion
+    (goto-char position)
+    (let* ((label (org-element-property :path (org-element-context)))
+          (data (or (or-parse-glossary-entry label)
+                    (or-parse-acronym-entry label)))
+          (name (or (plist-get data :name)
+                    (plist-get data :abbrv)))
+          (description (or (plist-get data :description)
+                           (plist-get data :full))))
+      (format
+       "%s: %s"
+       name
+       (with-temp-buffer
+        (insert (concat  description "."))
+        (fill-paragraph)
+        (buffer-string))))))
+
+
+;; **  printglossaries links
+;; There is a printglossary command in LaTeX, but I am not supporting it for now.
+(org-link-set-parameters "printglossaries"
+                        :export (lambda (path _desc format)
+                                  (cond
+                                   ((memq format '(latex beamer))
+                                    "\\printglossaries")
+                                   (t
+                                    (format "%s" path)))))
+
+
+
+;; ** exporting with a glossary table
+(defun org-ref-glossary-before-parsing (_backend)
+  "Function to preprocess a glossary table on export.
+This assumes a table like
+
+#+name: glossary
+| label | name  | description   |
+|-------+-------+---------------|
+| tree  | Tree  | A woody plant |
+| shrub | Shrub | A woody bush  |
+
+is in the org-buffer, and will add the relevant latex_header
+items if there is. The table is deleted in a copy of the buffer
+before the export, so you can put it where you want. The column
+names are arbitrary, but three columns are expected, and the
+hline is expected.
+
+This is intended to be run in `org-export-before-parsing-hook'."
+  (save-restriction
+    (widen)
+    (let* (begin
+          end
+          (entries (save-excursion
+                     (catch 'found
+                       (org-element-map
+                           (org-element-parse-buffer)
+                           'table
+                         (lambda (el)
+                           (when (and (org-element-property :name el)
+                                      (stringp (org-element-property :name el))
+                                      (string= "glossary" (org-element-property :name el)))
+                             (setq begin (org-element-property :begin el)
+                                   end (org-element-property :end el))
+                             (goto-char (org-element-property :contents-begin el))
+                             (throw 'found
+                                    (nthcdr 2 (org-babel-read-table))))))))))
+      ;; Delete the table
+      (when entries
+       (cl--set-buffer-substring begin end ""))
+
+      (goto-char (point-min))
+      (cl-loop for (label name description) in entries
+              do
+              (insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name=%s,description={{%s}}}\n"
+                              label name description))))))
+
+
+;;* Acronyms
+
+;;;###autoload
+(defun org-ref-add-acronym-entry (label abbrv full)
+  "Add an acronym entry with LABEL.
+  ABBRV is the abbreviated form.
+  FULL is the expanded acronym.
+
+This is not the preferred way to add acronyms, you should add
+them manually to the acronyms table."
+  (interactive "sLabel: \nsAcronym: \nsFull name: ")
+  (save-excursion
+    (re-search-backward "#\\+latex_header" nil t)
+    (forward-line)
+    (when (not (looking-at "^$"))
+      (beginning-of-line)
+      (insert "\n")
+      (forward-line -1))
+    (insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n"
+                   label abbrv full))))
+
+
+(defun or-parse-acronym-entry (label)
+  "Parse an acronym entry LABEL to a plist.
+Returns (:abbrv abbrv :full full :label label)
+The plist maps to \newacronym{<label>}{<abbrv>}{<full>}"
+  (if (and org-ref-acronym-cache (gethash label org-ref-acronym-cache))
+      ;; We have the cache, and an entry and use it
+      (gethash label org-ref-acronym-cache)
+    ;; We don't have a cache, or an label in it, so we find it.
+    ;; No cache? we make one
+    (unless org-ref-acronym-cache
+      (setq-local org-ref-acronym-cache (make-hash-table)))
+
+    ;; Now search for the data
+    (save-excursion
+      (goto-char (point-min))
+      (let* (abbrv
+            full p1
+            (external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
+                        (match-string 1)))
+            (glsentries (and external
+                             (or (cdr (assoc external org-ref-glsentries))
+                                 (progn
+                                   (cl-pushnew (cons external
+                                                     (s-trim (shell-command-to-string
+                                                              (format "kpsewhich tex %s" external))))
+                                               org-ref-glsentries)
+                                   (cdr (assoc external org-ref-glsentries))))))
+            data)
+       (setq data
+             (catch 'data
+               (goto-char (point-min))
+               ;; check in the definitions of newacronym
+               (when (re-search-forward (format "\\newacronym{%s}" label) nil t)
+                 (setq p1 (+ 1 (point)))
+                 (forward-list)
+                 (setq abbrv (buffer-substring p1 (- (point) 1)))
+                 (setq p1 (+ 1 (point)))
+                 (forward-list)
+                 (setq full (buffer-substring p1 (- (point) 1)))
+                 (throw 'data
+                        (list :label label :abbrv abbrv :full full)))
+
+               ;; look for acronyms table
+               (let* ((entries (save-excursion
+                                 (catch 'found
+                                   (org-element-map
+                                       (org-element-parse-buffer)
+                                       'table
+                                     (lambda (el)
+                                       (when (string= "acronyms" (org-element-property :name el))
+                                         (goto-char (org-element-property :contents-begin el))
+                                         (throw 'found
+                                                (nthcdr 2 (org-babel-read-table)))))))))
+                      (result (assoc label entries)))
+                 (when result
+                   (throw 'data (list :label label
+                                      :abbrv (cl-second result) :full (cl-third result)))))
+
+               ;; look external
+               (when (and glsentries
+                          (file-exists-p glsentries))
+                 (with-current-buffer (find-file-noselect glsentries)
+                   (goto-char (point-min))
+                   (when (re-search-forward (format "\\newacronym{%s}" label) nil t)
+                     (setq p1 (+ 1 (point)))
+                     (forward-list)
+                     (setq abbrv (buffer-substring p1 (- (point) 1)))
+                     (setq p1 (+ 1 (point)))
+                     (forward-list)
+                     (setq full (buffer-substring p1 (- (point) 1)))
+                     (throw 'data
+                            (list :label label :abbrv abbrv :full full )))))))
+       (puthash label data org-ref-acronym-cache)
+       data))))
+
+
+(defun org-ref-glossary-invalidate-caches ()
+  "Function to invalidate the caches."
+  (interactive)
+  (setq-local org-ref-acronym-cache (make-hash-table))
+  (setq-local org-ref-glossary-cache (make-hash-table)))
+
+;;** Acronym links
+(defun or-follow-acronym (label)
+  "Go to the definition of the acronym LABEL."
+  (org-mark-ring-push)
+  (cond
+   ;; table first
+   ((progn (goto-char (point-min))
+          (and (re-search-forward "#\\+name: acronyms" nil t)
+               (re-search-forward label nil t)))
+    nil)
+   
+   ((progn (goto-char (point-min)) (re-search-forward (format "\\newacronym{%s}" label) nil t))
+    (goto-char (match-beginning 0)))
+
+   (t
+    (message "no entry found for %s" label))))
+
+
+(defvar org-ref-acronym-types
+  '(("acrshort" "The acronym for label")
+    ("acrshortpl" "The acronym for label in plural")
+    ("Acrshort" "Capitalized acronym")
+    ("Acrshortpl" "Plural capitalized acronym")
+    ("ACRshort" "ALL-CAPS acronym")
+    ("ACRshortpl" "ALL-CAPS plural acronym")
+    
+    ("acrlong" "The label definition")
+    ("acrlongpl" "The plural definition")
+    ("Acrlong" "Capitalized definition")
+    ("Acrlongpl" "Plural capitalized definition")
+    ("ACRlong" "ALL-CAPS definition")
+    ("ACRlongpl" "plural ALL-CAPS definition")
+    
+    ("acrfull" "Both the acronym and its definition")
+    ("acrfullpl" "Both the acronym and its definition in plural")
+    ("Acrfull" "Capitalized both the acronym and its definition")
+    ("Acrfullpl" "Capitalized both the acronym and its definition in plural")
+    ("ACRfull" "Both the acronym and its definition in ALL-CAPS")
+    ("ACRfullpl" "Both the acronym and its definition in plural ALL-CAPS"))
+  "list of acronym types (type description)")
+
+
+(cl-dolist (mapping org-ref-acronym-types)
+  (org-link-set-parameters (cl-first mapping)
+                          :follow #'or-follow-acronym
+                          :face 'org-ref-acronym-face-fn
+                          :help-echo 'or-acronym-tooltip
+                          :export (lambda (path _ format)
+                                    (cond
+                                     ((memq format '(latex beamer))
+                                      (format "\\%s{%s}" (cl-first mapping) path))
+                                     (t
+                                      (format "%s" (upcase path)))))))
+
+
+;;** Tooltips on acronyms
+(defface org-ref-acronym-face
+  `((t (:inherit org-link :foreground "Darkorange2")))
+  "Face for acronym links.")
+
+
+(defun org-ref-acronym-face-fn (label)
+  "Return a face for an acronym link."
+  (if org-ref-activate-glossary-links
+      (save-match-data
+       (cond
+        ((or-parse-acronym-entry label)
+         'org-ref-acronym-face)
+        (t
+         'font-lock-warning-face)))
+    'org-ref-acronym-face))
+
+
+(defun or-acronym-tooltip (_window _object position)
+  "Return tooltip for the acronym entry.
+The entry is in WINDOW and OBJECT at POSITION.
+Used in fontification.
+WINDOW and OBJECT are ignored."
+  (save-excursion
+    (goto-char position)
+    (let* ((label (org-element-property :path (org-element-context)))
+          (acronym-data (or-parse-acronym-entry label))
+          (abbrv (plist-get acronym-data :abbrv))
+          (full (plist-get acronym-data :full)))
+      (if acronym-data
+         (format
+          "%s: %s"
+          abbrv full)
+       (format "%s is not defined in this file." label)))))
+
+
+;; ** Exporting with an acronym table
+(defun org-ref-acronyms-before-parsing (_backend)
+  "Function to preprocess a glossary table on export.
+This assumes a table like
+
+#+name: acronyms
+| Key  | Short | Long                           |
+|------+-------+--------------------------------|
+| mimo |       | multiple-input multiple output |
+| qos  | QoS   | quality-of-service             |
+| bb   | BB    | branch and bound               |
+
+is in the org-buffer, and will add the relevant latex_header items if there is. The table is deleted in a copy of the buffer before the export.
+
+This will run in `org-export-before-parsing-hook'."
+  (save-restriction
+    (widen)
+    (let* (begin
+          end
+          (entries (save-excursion
+                     (catch 'found
+                       (org-element-map
+                           (org-element-parse-buffer)
+                           'table
+                         (lambda (el)
+                           (when (and (org-element-property :name el)
+                                      (stringp (org-element-property :name el))
+                                      (string= "acronyms" (org-element-property :name el)))
+                             (setq begin (org-element-property :begin el)
+                                   end (org-element-property :end el))
+                             (goto-char (org-element-property :contents-begin el))
+                             (throw 'found
+                                    (nthcdr 2 (org-babel-read-table))))))))))
+      (when entries
+       ;; Delete the table
+       (cl--set-buffer-substring begin end ""))
+
+      (goto-char (point-min))
+      (cl-loop for (label name description) in entries
+              do
+              (insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n"
+                              label name description))))))
+
+
+;; * Interactive command to insert acroynm/glossary links
+
+(defun org-ref-insert-glossary-link ()
+  "Insert glossary entry as links."
+  (interactive)
+  ;; gather entries
+  (let* ((glossary-candidates '()) 
+        key entry type
+        type-annotation
+        completion-extra-properties
+        choice)
+
+    ;; glossary terms
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward
+             "\\\\newglossaryentry{\\([[:ascii:]]+?\\)}" nil t)
+
+       (setq key (match-string 1)
+             entry (or-parse-glossary-entry key))
+
+       (cl-pushnew (cons
+                    (propertize (format "%s: %s - glossary."
+                                        (plist-get entry :name)
+                                        (plist-get entry :description))
+                                'face 'org-ref-glossary-face)
+                    entry)
+                   glossary-candidates)))
+
+    ;; get entries from the table
+    (let ((entries (save-excursion
+                    (catch 'found
+                      (org-element-map
+                          (org-element-parse-buffer)
+                          'table
+                        (lambda (el)
+                          (when (and (org-element-property :name el)
+                                     (stringp (org-element-property :name el))
+                                     (string= "glossary"
+                                              (org-element-property :name el)))
+                            (goto-char (org-element-property :contents-begin el))
+                            (throw 'found
+                                   ;; skip header and hline
+                                   (nthcdr 2 (org-babel-read-table))))))))))
+      (cl-loop for (label name description) in entries do
+              (cl-pushnew (cons
+                           (propertize (format "%s: %s - glossary."
+                                               label
+                                               description)
+                                       'face 'org-ref-glossary-face)
+                           (list :label label :name name :description description))
+                          glossary-candidates)))
+
+
+    (setq choice (completing-read "Choose: " glossary-candidates)
+         entry (cdr (assoc choice glossary-candidates))
+         type-annotation (lambda (s)
+                           (let ((item (assoc s minibuffer-completion-table)))
+                             (when item (concat
+                                         (make-string (- 12 (length s)) ? )
+                                         "-- "
+                                         (cl-second item)))))
+         completion-extra-properties `(:annotation-function ,type-annotation)
+         type (completing-read "Type: "
+                               org-ref-glossary-gls-commands
+                               nil t))
+
+    (insert (format
+            "[[%s:%s][%s]]"
+            type
+            (plist-get entry :label)
+            (pcase type
+              ("gls" (plist-get entry :name))
+              ("glspl" (concat (plist-get entry :name) "s"))
+              ("Gls" (concat (capitalize (substring (plist-get entry :name) 0 1))
+                             (substring (plist-get entry :name) 1)))
+              ("Glspl" (concat (capitalize (substring (plist-get entry :name) 0 1))
+                               (substring (plist-get entry :name) 1)
+                               "s"))
+              ("glssymbol" (plist-get entry :name))
+              ("Glssymbol" (concat (capitalize (substring (plist-get entry :name) 0 1))
+                                   (substring (plist-get entry :name) 1)))
+              ("glsdesc" (plist-get entry :description))
+              ("Glsdesc" (concat (capitalize (substring (plist-get entry :description) 0 1))
+                                 (substring (plist-get entry :description) 1)))
+              ;; fall-through for everything else
+              (_ (plist-get entry :name)))))))
+
+
+(defun org-ref-insert-acronym-link ()
+  "Insert acronym entry as links."
+  (interactive)
+  ;; gather entries
+  (let* ((acronym-candidates '())
+        key entry
+        type
+        type-annotation
+        completion-extra-properties
+        choice
+        (cap1 (lambda (s)
+                "capitalize first letter only"
+                (concat
+                 (capitalize (substring s 0 1))
+                 (substring s 1)))))
+
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward
+             "\\\\newacronym{\\([[:ascii:]]+?\\)}" nil t)
+       (setq key (match-string 1)
+             entry (or-parse-acronym-entry key))
+       (cl-pushnew (cons (propertize
+                          (format "%s (%s) - acronym."
+                                  (plist-get entry :full)
+                                  (plist-get entry :abbrv))
+                          'face 'org-ref-acronym-face)
+                         entry)
+                   acronym-candidates)))
+
+    (let ((entries (save-excursion
+                    (catch 'found
+                      (org-element-map
+                          (org-element-parse-buffer)
+                          'table
+                        (lambda (el)
+                          (when (and (org-element-property :name el)
+                                     (stringp (org-element-property :name el))
+                                     (string= "acronyms"
+                                              (org-element-property :name el)))
+                            (goto-char (org-element-property :contents-begin el))
+                            (throw 'found
+                                   ;; skip header and hline
+                                   (nthcdr 2 (org-babel-read-table))))))))))
+      (cl-loop for (key abbrv full) in entries do
+              (cl-pushnew (cons (propertize
+                                 (format "%s (%s) - acronym."
+                                         full
+                                         abbrv)
+                                 'face 'org-ref-acronym-face)
+                                (list :label key :abbrv abbrv :full full))
+                          acronym-candidates)))
+
+    (setq choice (completing-read "Choose: " acronym-candidates)
+         entry (cdr (assoc choice acronym-candidates))
+         type-annotation (lambda (s)
+                           (let ((item (assoc s minibuffer-completion-table)))
+                             (when item (concat
+                                         (make-string (- 12 (length s)) ? )
+                                         "-- "
+                                         (cl-second item)))))
+         
+         completion-extra-properties `(:annotation-function ,type-annotation)
+         type (completing-read "Type: "
+                               org-ref-acronym-types
+                               nil t))
+
+    (insert (format
+            "[[%s:%s][%s]]"
+            type
+            (plist-get entry :label)
+            (pcase type
+              ("acrshort" (plist-get entry :abbrv))
+              ;; this is a cheap way to pluralize. I don't know what the rules
+              ;; are in LaTeX. this is only for display, so it isn't critical.
+              ("acrshortpl" (concat (plist-get entry :abbrv) "s"))
+              
+              ("Acrshort" (funcall cap1 (plist-get entry :abbrv)))
+              ("Acrshortpl" (concat (capitalize (plist-get entry :abbrv)) "s"))
+
+              ("ACRshort" (upcase (plist-get entry :abbrv)))
+              ("ACRshortpl" (concat (upcase (plist-get entry :abbrv)) "s"))
+
+              ("acrlong" (plist-get entry :full))
+              ("acrlongpl" (concat (plist-get entry :full) "s"))
+              
+              ("Acrlong" (funcall cap1 (plist-get entry :full)))
+              ("Acrlongpl" (concat (funcall cap1 (plist-get entry :full)) "s"))
+              
+              ("acrfull" (format "%s (%s)"
+                                 (plist-get entry :full)
+                                 (plist-get entry :abbrv)))
+              ("acrfullpl" (format "%ss (%ss)"
+                                   (plist-get entry :full)
+                                   (plist-get entry :abbrv)))
+              
+              ("Acrfull" (funcall cap1 (format "%s (%s)"
+                                               (plist-get entry :full)
+                                               (plist-get entry :abbrv))))
+              ("Acrfullpl" (funcall cap1 (format "%ss (%ss)"
+                                                 (plist-get entry :full)
+                                                 (plist-get entry :abbrv))))
+              ("ACRfull" (upcase (format "%s (%s)"
+                                         (plist-get entry :full)
+                                         (plist-get entry :abbrv))))
+              ("ACRfullpl" (upcase (format "%ss (%ss)"
+                                           (plist-get entry :full)
+                                           (plist-get entry :abbrv))))
+              ;; fall-through in case anything is added later.
+              (_ (plist-get entry :abbrv)))))))
+
+
+;; * acrossproc - acronym and glossary preprocessor
+;;
+;; Replace printglossary with the acronym and glossary entries
+;;
+;; Replace the links with links
+;;
+;; TODO: support only one or the other? via printglossary:acronyms for example?
+
+(defun org-ref-acrossproc (_backend)
+  "Preprocessing function for acronyms and glossary entries.
+Meant for non-LaTeX exports."
+  (save-excursion
+    (let* ((glossary)
+          (acronyms)
+          (printglossary-link)
+          (links))
+
+      (setq glossary (org-element-map
+                        (org-element-parse-buffer)
+                        'table 
+                      (lambda (el)
+                        (when (and (org-element-property :name el)
+                                   (stringp (org-element-property :name el))
+                                   (string= "glossary" (org-element-property :name el))) 
+                          (goto-char (org-element-property :contents-begin el))
+                          (prog1
+                              ;; skip header and hline
+                              (nthcdr 2 (org-babel-read-table))
+                            ;; delete the table
+                            (cl--set-buffer-substring (org-element-property :begin el)
+                                                      (org-element-property :end el)
+                                                      ""))))
+                      nil t))
+      (setq acronyms (org-element-map
+                        (org-element-parse-buffer)
+                        'table 
+                      (lambda (el)
+                        (when (and (org-element-property :name el)
+                                   (stringp (org-element-property :name el))
+                                   (string= "acronyms" (org-element-property :name el))) 
+                          (goto-char (org-element-property :contents-begin el))
+                          (prog1
+                              (nthcdr 2 (org-babel-read-table))
+                            ;; delete the table
+                            (cl--set-buffer-substring (org-element-property :begin el)
+                                                      (org-element-property :end el)
+                                                      ""))))
+                      nil t))
+      
+      ;; Replace printglossary link
+      ;; For each entry, use - name :: description <<label>>
+      (setq printglossary-link (org-element-map
+                                  ;; reparse in case the replacement above changed places
+                                  (org-element-parse-buffer)
+                                  'link
+                                (lambda (lnk)
+                                  (when (string= "printglossaries"
+                                                 (org-element-property :type lnk))
+                                    lnk))
+                                nil t))
+      (when printglossary-link
+       (cl--set-buffer-substring (org-element-property :begin printglossary-link)
+                                 (org-element-property :end printglossary-link)
+                                 
+                                 (concat "*Glossary*\n"
+                                         (string-join
+                                          (cl-loop for (label name description) in glossary collect
+                                                   (format "<<%s>>\n- %s :: %s" label name description))
+                                          "\n")
+
+                                         "\n*Acronyms*\n"
+                                         (string-join
+                                          (cl-loop for (label name description) in acronyms collect
+                                                   (format "<<%s>>\n- %s :: %s " label name description))
+                                          "\n"))))
+
+
+      ;; Replace links
+      (setq links (org-element-map
+                     ;; reparse in case the replacement above changed places
+                     (org-element-parse-buffer)
+                     'link
+                   (lambda (lnk)
+                     (when (assoc (org-element-property :type lnk)
+                                  (append org-ref-glossary-gls-commands
+                                          org-ref-acronym-types))
+                       lnk))))
+      ;; For each link, replace with [[label][link description]]
+      (cl-loop for lnk in (reverse links) do
+              (cl--set-buffer-substring (org-element-property :begin lnk)
+                                        (org-element-property :end lnk)
+                                        (format "[[%s][%s]]%s"
+                                                (org-element-property :path lnk)
+                                                (buffer-substring (org-element-property :contents-begin lnk)
+                                                                  (org-element-property :contents-end lnk))
+                                                (make-string (org-element-property :post-blank lnk) ? )))))))
+
+
+(provide 'org-ref-glossary)
+;;; org-ref-glossary.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-helm.el b/elpa/org-ref-20230507.1420/org-ref-helm.el
new file mode 100644 (file)
index 0000000..f4f02b8
--- /dev/null
@@ -0,0 +1,114 @@
+;;; org-ref-helm.el --- org-ref interface to helm-bibtex -*- lexical-binding: t; -*-
+
+;; Copyright(C) 2014-2022 John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; URL: https://github.com/jkitchin/org-ref
+;; Version: 1.0
+;; Keywords: org-mode, cite, ref, label
+;; Package-Requires: ((helm-bibtex "0") (org-ref "0"))
+
+;; This file is not currently part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program ; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; Adapted from helm-bibtex, mostly so you get the default action to insert a citation
+
+(require 'org-ref-core)
+(require 'helm-bibtex)
+
+(defvar helm-bibtex-local-bib)  ; to quiet compiler. 
+
+;;; Code:
+
+(helm-bibtex-helmify-action org-ref-insert-cite-keys org-ref-helm-bibtex-insert-citation)
+
+(defvar org-ref-helm-source-bibtex
+  (helm-build-sync-source "BibTeX entries"
+    :header-name (lambda (name)
+                   (format "%s%s: " name (if helm-bibtex-local-bib " (local)" "")))
+    :candidates 'helm-bibtex-candidates
+    :filtered-candidate-transformer 'helm-bibtex-candidates-formatter
+    :action (helm-make-actions
+            "Insert citation"            'org-ref-helm-bibtex-insert-citation
+            "Insert reference"           'helm-bibtex-insert-reference
+             "Open PDF, URL or DOI"       'helm-bibtex-open-any
+             "Open URL or DOI in browser" 'helm-bibtex-open-url-or-doi
+             "Insert BibTeX key"          'helm-bibtex-insert-key
+             "Insert BibTeX entry"        'helm-bibtex-insert-bibtex
+             "Attach PDF to email"        'helm-bibtex-add-PDF-attachment
+             "Edit notes"                 'helm-bibtex-edit-notes
+             "Show entry"                 'helm-bibtex-show-entry
+             "Add PDF to library"         'helm-bibtex-add-pdf-to-library))
+  "Source for searching in BibTeX files.")
+
+(defvar org-ref-helm-source-fallback-options
+  '((name            . "Fallback options")
+    (match             (lambda (_candidate) t))
+    (candidates      . bibtex-completion-fallback-candidates)
+    (no-matchplugin)
+    (nohighlight)
+    (action          . (lambda (candidate) (bibtex-completion-fallback-action candidate helm-pattern))))
+  "Source for online look-up.")
+
+;; Helm-bibtex command:
+
+;;;###autoload
+(defun org-ref-cite-insert-helm (&optional arg local-bib input)
+  "Search BibTeX entries.
+
+With a prefix ARG, the cache is invalidated and the bibliography
+reread.
+
+If LOCAL-BIB is non-nil, display that the BibTeX entries are read
+from the local bibliography.  This is set internally by
+`helm-bibtex-with-local-bibliography'.
+
+If INPUT is non-nil and a string, that value is going to be used
+as a predefined search term.  Can be used to define functions for
+frequent searches (e.g. your own publications)."
+  (interactive "P")
+  (when arg
+    (bibtex-completion-clear-cache))
+  (bibtex-completion-init)
+  (let* ((candidates (bibtex-completion-candidates))
+         (key (bibtex-completion-key-at-point))
+         (preselect (and key
+                         (cl-position-if (lambda (cand)
+                                          (member (cons "=key=" key)
+                                                  (cdr cand)))
+                                         candidates))))
+    (helm :sources (list org-ref-helm-source-bibtex org-ref-helm-source-fallback-options)
+          :full-frame helm-bibtex-full-frame
+          :buffer "*helm bibtex*"
+          :input input
+          :preselect (lambda ()
+                      (and preselect
+                           (> preselect 0)
+                           (helm-next-line preselect)))
+          :candidate-number-limit (max 500 (1+ (or preselect 0)))
+          :bibtex-candidates candidates
+          :bibtex-local-bib local-bib)))
+
+
+(setq org-ref-insert-cite-function 'org-ref-cite-insert-helm)
+
+
+(provide 'org-ref-helm)
+
+;;; org-ref-helm.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-isbn.el b/elpa/org-ref-20230507.1420/org-ref-isbn.el
new file mode 100644 (file)
index 0000000..d0f08c6
--- /dev/null
@@ -0,0 +1,259 @@
+;;; org-ref-isbn.el --- utilities for generating bibtex entries from an ISBN  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides functions to download bibtex entries from isbn numbers.
+
+;;; Code:
+(require 'f)
+(require 'org)
+(require 'org-ref-core)
+
+(defvar url-http-end-of-headers)
+
+;;* ISBN utility
+
+(defcustom org-ref-isbn-clean-bibtex-entry-hook
+  '(oricb-remove-enclosing-brackets
+    oricb-clean-author-field
+    oricb-remove-period
+    oricb-kill-fields
+    oricb-replace-field-names)
+  "Hook that is run in `org-ref-isbn-clean-bibtex-entry'.
+The functions should have no arguments, and operate on the bibtex
+entry at point. You can assume point starts at the beginning of the
+entry. These functions are wrapped in `save-restriction' and
+`save-excursion' so you do not need to save the point position."
+  :group 'org-ref-isbn
+  :type 'hook)
+
+
+(defcustom org-ref-isbn-exclude-fields nil
+  "List of bibtex fields to kill when new entry is inserted."
+  :group 'org-ref-isbn
+  :type '(repeat :tag "List of bibtex fields to kill" string))
+
+
+(defcustom org-ref-isbn-field-name-replacements nil
+  "List of bitex field name/replacement pairs.
+The entries in this list are cons cells where the car is the field name
+and cdr is the replacement name."
+  :group 'org-ref-isbn
+  :type '(repeat (cons (string :tag "Field name")
+                      (string :tag "Field name replacement"))))
+
+
+(defun oricb-replace-field-names ()
+  "Replace bibtex field names defined in
+`org-ref-isbn-field-name-replacements'."
+  (when org-ref-isbn-field-name-replacements
+    (mapcar (lambda (field)
+             (bibtex-beginning-of-entry)
+             (let ((f (bibtex-autokey-get-field (car field))))
+               (unless (string= "" f)
+                 (goto-char (cadr (bibtex-search-forward-field (car field) t)))
+                 (bibtex-kill-field)
+                 (bibtex-make-field (cdr field))
+                 (backward-char)
+                 (insert f))))
+           org-ref-isbn-field-name-replacements)))
+
+
+(defun oricb-kill-fields ()
+  "Kill all bibtex fields defined in `org-ref-isbn-exclude-fields'."
+  (when org-ref-isbn-exclude-fields
+    (mapcar (lambda (field)
+             (bibtex-beginning-of-entry)
+             (let ((f (bibtex-autokey-get-field field)))
+               (unless (string= "" f)
+                 (goto-char (cadr (bibtex-search-forward-field field t)))
+                 (bibtex-kill-field))))
+           org-ref-isbn-exclude-fields)))
+
+
+(defun oricb-remove-enclosing-brackets ()
+  "Remove enclosing brackets from fields."
+  (save-restriction
+    (bibtex-narrow-to-entry)
+    (while (re-search-forward "\\({\\)\\(\\[\\)\\(.+\\)\\(]\\)\\(}\\)" nil t)
+      (replace-match "\\1\\3\\5"))))
+
+
+(defun oricb-clean-author-field ()
+  "Remove extra information from author's field."
+  (goto-char (cadr (bibtex-search-forward-field "author" t)))
+  (let ((case-fold-search nil))
+    (when (re-search-forward "\\({\\)\\(by \\|ed. by \\|edited by \\)" nil t)
+      (replace-match "\\1"))))
+
+
+(defun oricb-remove-period ()
+  "Remove period from author's field."
+  (goto-char (cadr (bibtex-search-forward-field "author" t)))
+  (when (re-search-forward "\\(\\.\\)\\(}\\)" nil t)
+    (replace-match "\\2")))
+
+
+;;;###autoload
+(defun org-ref-isbn-clean-bibtex-entry ()
+  "Clean a bibtex entry inserted via `isbn-to-bibtex'.
+See functions in `org-ref-isbn-clean-bibtex-entry-hook'."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (mapc (lambda (x)
+         (save-restriction
+           (save-excursion
+             (funcall x))))
+       org-ref-isbn-clean-bibtex-entry-hook))
+
+
+;; I found this on the web. It can be handy, but the bibtex entry has a lot of stuff in it.
+
+;;;###autoload
+(defun isbn-to-bibtex-lead (isbn)
+  "Search lead.to for ISBN bibtex entry.
+You have to copy the entry if it is on the page to your bibtex
+file."
+  (interactive "sISBN: ")
+  (browse-url
+   (format
+    "http://lead.to/amazon/en/?key=%s+&si=all&op=bt&bn=&so=sa&ht=us"
+    isbn)))
+
+
+;; Here we get isbn metadata and build a bibtex entry.
+
+;;;###autoload
+(defun isbn-to-bibtex (isbn bibfile)
+  "Get bibtex entry for ISBN and insert it into BIBFILE.
+Nothing happens if an entry with the generated key already exists
+in the file. Data comes from www.ebook.de."
+  (interactive
+   (list
+    (read-string
+     "ISBN: "
+     ;; now set initial input
+     (cond
+      ;; If region is active and it starts with a number, we use it
+      ((and  (region-active-p)
+             (s-match "^[0-9]" (buffer-substring (region-beginning) (region-end))))
+       (buffer-substring (region-beginning) (region-end)))
+      ;; if first entry in kill ring starts with a number assume it is an isbn
+      ;; and use it as the guess
+      ((stringp (car kill-ring))
+       (when (s-match "^[0-9]" (car kill-ring))
+        (car kill-ring)))
+      ;; type or paste it in
+      (t
+       nil)))
+    (completing-read "Bibfile: " (org-ref-possible-bibfiles))))
+
+  (let* ((url (format "https://www.ebook.de/de/tools/isbn2bibtex?isbn=%s" isbn))
+        (entry))
+    (with-current-buffer (url-retrieve-synchronously url t t)
+      (goto-char (point-min))
+      (when (re-search-forward "@[a-zA-Z]+{.+\\(\n\s+[^\n]+\\)+}$" nil t)
+       (setq entry (match-string 0))))
+
+    (if (not entry)
+       (message "Nothing found.")
+      (find-file bibfile)
+      (goto-char (point-max))
+      (insert (with-temp-buffer
+               (insert (concat entry "\n}"))
+               (goto-char (point-min))
+               ;; [2020-06-06 Sat] I got a report that ottobib returns entries
+               ;; with ,, in the first line. here if we find one, I eliminate
+               ;; one of them.
+               (when (re-search-forward ",," nil t)
+                 (delete-char -1))
+               (org-ref-isbn-clean-bibtex-entry)
+               (org-ref-clean-bibtex-entry)
+               (bibtex-fill-entry)
+               (s-trim (buffer-string))))
+      (save-buffer))))
+
+
+(defun isbn-to-bibtex-open-library (isbn bibfile)
+  "Retrieve bibtex entry for a book with ISBN using openlibrary.org.
+
+API: https://openlibrary.org/developers/api
+"
+  (interactive
+   (list
+    (read-string
+     "ISBN: "
+     ;; now set initial input
+     (cond
+      ;; If region is active and it starts with a number, we use it
+      ((and  (region-active-p)
+             (s-match "^[0-9]" (buffer-substring (region-beginning) (region-end))))
+       (buffer-substring (region-beginning) (region-end)))
+      ;; if first entry in kill ring starts with a number assume it is an isbn
+      ;; and use it as the guess
+      ((stringp (car kill-ring))
+       (when (s-match "^[0-9]" (car kill-ring))
+        (car kill-ring)))
+      ;; type or paste it in
+      (t
+       nil)))
+    (completing-read "Bibfile: " (org-ref-possible-bibfiles))))
+
+  (let* ((url (format "https://openlibrary.org/isbn/%s.json" isbn))
+        (json (with-current-buffer (url-retrieve-synchronously url)
+                (json-read-from-string (string-trim (buffer-substring url-http-end-of-headers (point-max))))))
+        (title (cdr (assoc 'title json)))
+        (publisher (s-join ", " (cdr (assoc 'publishers json))))
+        (year (cdr (assoc 'publish_date  json)))
+        ;; this is a list of urls
+        (author-urls (cdr (assoc 'authors json)))
+        (authors (s-join " and "
+                         (cl-loop for aurl across author-urls
+                                  collect
+                                  (with-current-buffer (url-retrieve-synchronously
+                                                        (format "https://openlibrary.org%s.json"
+                                                                (cdr (assoc 'key  aurl)))) 
+                                    (cdr (assoc 'personal_name
+                                                (json-read-from-string
+                                                 (string-trim (buffer-substring url-http-end-of-headers (point-max)))))))))) 
+        (burl (format "https://openlibrary.org%s" (cdr (assoc 'key json))))
+        (bibtex (format "@Book{,
+  author =      {%s},
+  title =       {%s},
+  publisher =   {%s},
+  year =        {%s},
+  url = {%s}
+}"
+                        authors
+                        title
+                        publisher
+                        year
+                        burl)))
+
+    (with-current-buffer (find-file-noselect bibfile)
+      (goto-char (point-max))
+      (insert "\n\n")
+      (insert bibtex)
+      (org-ref-clean-bibtex-entry)
+      (save-buffer))))
+
+(provide 'org-ref-isbn)
+;;; org-ref-isbn.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-ivy.el b/elpa/org-ref-20230507.1420/org-ref-ivy.el
new file mode 100644 (file)
index 0000000..9be16c0
--- /dev/null
@@ -0,0 +1,163 @@
+;;; org-ref-ivy.el --- org-ref with ivy completion -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; URL: https://github.com/jkitchin/org-ref
+;; Version: 1.0
+;; Keywords: org-mode, cite, ref, label
+;; Package-Requires: ((org-ref "0") (ivy-bibtex "0"))
+
+;; This file is not currently part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This customizes org-ref specifically around using ivy and ivy-bibtex. The
+;; citation selection looks like `ivy-bibtex' but it is a customized ivy
+;; function with customized actions.
+
+(require 'org-ref-core)
+(require 'ivy-bibtex)
+
+
+;; all these functions are defined in ivy-bibtex, but not in a variable. Here
+;; you can set them as you see fit.
+(defcustom org-ref-citation-alternate-insert-actions
+  '(("p" ivy-bibtex-open-pdf "Open PDF file (if present)")
+    ("u" ivy-bibtex-open-url-or-doi "Open URL or DOI in browser")
+    ;; this insert-citation only inserts an org-ref cite.
+    ;; ("c" ivy-bibtex-insert-citation "Insert citation")
+    ("R" ivy-bibtex-insert-reference "Insert formatted reference")
+    ("k" ivy-bibtex-insert-key "Insert BibTeX key")
+    ("b" ivy-bibtex-insert-bibtex "Insert BibTeX entry")
+    ("a" ivy-bibtex-add-PDF-attachment "Attach PDF to email")
+    ("e" ivy-bibtex-edit-notes "Edit notes")
+    ("s" ivy-bibtex-show-entry "Show entry")
+    ("l" ivy-bibtex-add-pdf-to-library "Add PDF to library")
+    ("h" (lambda (candidate)
+          (org-insert-heading)
+          (insert (bibtex-completion-apa-format-reference
+                   (cdr (assoc "=key=" candidate)))
+                  " "
+                  (format "cite:&%s" (cdr (assoc "=key=" candidate)))))
+     "Insert org-heading")
+    ("m" (lambda (candidate)
+          (insert (bibtex-completion-apa-format-reference
+                   (cdr (assoc "=key=" candidate)))))
+     "Insert formatted citation")
+    ("f" (lambda (_candidate) (ivy-bibtex-fallback ivy-text)) "Fallback options")
+    ("d" (lambda (_)
+          "Add a bibtex entry from doi and insert cite to it at point."
+          (funcall-interactively 'doi-utils-add-bibtex-entry-from-doi
+                                 (read-string
+                                  "DOI: "
+                                  ;; now set initial input
+                                  (doi-utils-maybe-doi-from-region-or-current-kill)))
+          (org-ref-insert-cite-key
+           (current-kill 0 t)))
+     "Insert from a DOI"))
+  "Alternate actions to do instead of inserting."
+  :type '(list (repeat (string function string)))
+  :group 'org-ref)
+
+
+;; This is modified from ivy-bibtex which had " " instead of "" which breaks marking.
+(defun org-ref-ivy-bibtex-display-transformer (candidate)
+  "Prepare bib entry CANDIDATE for display."
+  (let* ((width (- (frame-width) 2))
+        (idx (get-text-property 1 'idx candidate))
+        (entry (cdr (nth idx (ivy-state-collection ivy-last)))))
+    (s-concat (if (s-starts-with-p ivy-mark-prefix candidate) ivy-mark-prefix "")
+             (bibtex-completion-format-entry entry width))))
+
+
+(ivy-configure 'org-ref-cite-insert-ivy :display-transformer-fn 'org-ref-ivy-bibtex-display-transformer)
+
+
+(defun org-ref-cite-multi-insert-ivy (candidates)
+  "A multi-action function to insert CANDIDATES."
+  (with-ivy-window
+    (org-ref-insert-cite-keys
+     (mapcar (lambda (entry)
+              (cdr (assoc "=key=" (cdr entry))))
+            candidates)
+     ivy-current-prefix-arg)))
+
+
+(defun org-ref-cite-insert-ivy ()
+  "Function for inserting a citation."
+  (interactive)
+  ;; Set this in the function so it is updated if you change the functions while
+  ;; writing
+  (ivy-set-actions
+   'org-ref-cite-insert-ivy
+   org-ref-citation-alternate-insert-actions)
+
+  ;; This initializes bibtex if the variable is not defined.
+  (unless bibtex-completion-display-formats-internal
+    (bibtex-completion-init))
+
+  (let* ((bibtex-completion-bibliography (org-ref-find-bibliography))
+        (candidates (bibtex-completion-candidates)))
+    (ivy-read "org-ref-ivy BibTeX entries: " candidates
+             :preselect (ivy-thing-at-point)
+             :multi-action #'org-ref-cite-multi-insert-ivy
+             :action '(1
+                       ("o" (lambda (candidate)
+                              (org-ref-insert-cite-key
+                               (cdr (assoc "=key=" (cdr candidate)))
+                               ivy-current-prefix-arg))
+                        "insert")
+                       ("r" (lambda (candidate)
+                              (let* ((object (org-element-context))
+                                     (type (org-element-property :type object))
+                                     (begin (org-element-property :begin object))
+                                     (end (org-element-property :end object))
+                                     (link-string (org-element-property :path object))
+                                     (data (org-ref-parse-cite-path link-string))
+                                     (references (plist-get data :references))
+                                     (cp (point))
+                                     (key)
+                                     keys i)
+                                ;;   We only want this to work on citation links
+                                (when (assoc type org-ref-cite-types)
+                                  (setq key (org-ref-get-bibtex-key-under-cursor))
+                                  (if (null key)
+                                      ;; delete the whole cite
+                                      (cl--set-buffer-substring begin end "")
+                                    (setq i (seq-position
+                                             references key
+                                             (lambda (el key)
+                                               (string= key
+                                                        (plist-get el :key)))))
+                                    (setf (plist-get (nth i references) :key)
+                                          (cdr (assoc "=key=" (cdr candidate))))
+                                    (setq data (plist-put data :references references))
+                                    (save-excursion
+                                      (goto-char begin)
+                                      (re-search-forward link-string)
+                                      (replace-match (org-ref-interpret-cite-data data)))
+                                    (goto-char cp)))))
+                        "Replace key at point"))
+             :caller 'org-ref-cite-insert-ivy)))
+
+
+(setq org-ref-insert-cite-function 'org-ref-cite-insert-ivy)
+
+
+(provide 'org-ref-ivy)
+
+;;; org-ref-ivy.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-label-link.el b/elpa/org-ref-20230507.1420/org-ref-label-link.el
new file mode 100644 (file)
index 0000000..432332b
--- /dev/null
@@ -0,0 +1,60 @@
+;;; org-ref-label-link.el --- -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+
+;;; Code:
+
+
+(defface org-ref-label-face
+  `((t (:inherit org-link :foreground "dark magenta")))
+  "Color for ref links in `org-ref'."
+  :group 'org-ref-faces)
+
+
+;;** label link (maybe deprecated)
+
+
+(org-link-set-parameters
+ "label"
+ :export (lambda (path _desc format)
+          (cond
+           ((eq format 'latex)
+            (format "\\label{%s}" path))))
+ :face 'org-ref-label-face
+ :help-echo "A label")
+
+
+;;;###autoload
+(defun org-ref-insert-label-link ()
+  "Insert a new label with completion.
+The completion helps ensure you use a unique label."
+  (interactive)
+  (let* ((known-labels (mapcar 'car (org-ref-get-labels)))
+        (new-label (completing-read "Label: " known-labels nil)))
+    (when (member new-label known-labels)
+      (warn "Inserting duplicate label"))
+    (insert (format "label:%s" new-label))))
+
+
+(provide 'org-ref-label-link)
+
+;;; org-ref-label-link.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-latex.el b/elpa/org-ref-20230507.1420/org-ref-latex.el
new file mode 100644 (file)
index 0000000..637e5b9
--- /dev/null
@@ -0,0 +1,104 @@
+;;; org-ref-latex.el --- org-ref functionality for LaTeX files  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: languages
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary: Make cites in LaTeX documents clickable, and with tooltips.
+;; We use font-lock to add some functionality to the keys.
+
+;;; Code:
+
+(require 'org-ref-citation-links)
+(require 'bibtex-completion)
+
+(defvar latex-mode-map)
+(defvar org-ref-cite-types)
+
+
+(defvar org-ref-latex-cite-re
+  (concat "\\\\\\(?1:" (mapconcat
+                       (lambda (x)
+                         (replace-regexp-in-string "\\*" "\\\\*" x))
+                       (mapcar 'car org-ref-cite-types)
+                       "\\|")
+         "\\)"
+         "\\(?2:\\[[^]]*\\]\\)?"               ; optional []
+         "\\(?3:\\[[^]]*\\]\\)?"               ; optional []
+         "{\\(?4:[^}]*\\)}")           ; group 4 contains the keys
+  "Regexp for LaTeX citations. \\citetype[opti{o}nal][optiona{l}]{some,keys}.
+The clickable part are the keys.")
+
+
+(defun org-ref-latex-get-bibliography ()
+  "Find bibliographies in the tex file"
+  (save-excursion
+    (let ((bibliography '()))
+      (goto-char (point-min))
+      (while (re-search-forward "\\\\bibliography{\\(?1:.*\\)}" nil t)
+       (setq bibliography (append bibliography
+                                  (mapcar (lambda (f)
+                                            (concat f ".bib"))
+                                          (split-string (match-string-no-properties 1) ",")))))
+      (goto-char (point-min))
+      (while (re-search-forward "\\\\addbibresource{\\(?1:.*\\)}" nil t)
+       (setq bibliography (append bibliography (list (match-string-no-properties 1)))))
+
+      bibliography)))
+
+
+(defun org-ref-next-latex-cite (&optional limit)
+  "Font-lock function to make cites in LaTeX documents clickable."
+  (while (re-search-forward org-ref-latex-cite-re limit t)
+    (setq font-lock-extra-managed-props (delq 'help-echo font-lock-extra-managed-props))
+    (goto-char (match-beginning 0))
+    (let ((end (match-end 0)))
+      (cl-loop for key in (mapcar #'s-trim (split-string (match-string-no-properties 4) ","))
+              unless (string-empty-p key)
+              do
+              (save-match-data
+                (search-forward key)
+                (add-text-properties
+                 (match-beginning 0)
+                 (match-end 0)
+                 `(mouse-face highlight
+                              local-map ,(let ((map (copy-keymap latex-mode-map)))
+                                           (define-key map [mouse-1]
+                                             `(lambda ()
+                                                (interactive)
+                                                (let ((bibtex-completion-bibliography (org-ref-latex-get-bibliography)))
+                                                  (bibtex-completion-show-entry (list ,key))
+                                                  (bibtex-beginning-of-entry))))
+                                           map)
+                              help-echo ,(let* ((bibtex-completion-bibliography (org-ref-latex-get-bibliography)))
+                                           (condition-case nil
+                                               (bibtex-completion-apa-format-reference key)
+                                             (error (display-warning :warning (format "Key %s missing." key)))))))))
+      (goto-char end))))
+
+
+(defun org-ref-latex-cite-on ()
+  "Add the font-lock on for citations."
+  (font-lock-add-keywords
+   'latex-mode
+   '((org-ref-next-latex-cite 0 font-lock-constant-face))))
+
+(add-hook 'LaTeX-mode-hook 'org-ref-latex-cite-on)
+
+
+(provide 'org-ref-latex)
+;;; org-ref-latex.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-misc-links.el b/elpa/org-ref-20230507.1420/org-ref-misc-links.el
new file mode 100644 (file)
index 0000000..45b2204
--- /dev/null
@@ -0,0 +1,305 @@
+;;; org-ref-misc-links.el --- Miscellaneous links -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;; * Miscellaneous links
+
+
+;;; Commentary:
+;;
+
+;;; Code:
+
+;;** List of figures
+
+;;;###autoload
+(defun org-ref-list-of-figures (&optional _arg)
+  "Generate buffer with list of figures in them.
+ARG does nothing.
+Ignore figures in COMMENTED sections."
+  (interactive)
+  (save-excursion
+    (widen)
+    (let* ((c-b (buffer-name))
+          (counter 0)
+          (list-of-figures
+           (org-element-map (org-ref-parse-buffer) 'link
+             (lambda (link)
+               "create a link for to the figure"
+               (when
+                   (and (string= (org-element-property :type link) "file")
+                        (string-match-p
+                         "[^.]*\\.\\(png\\|jpg\\|eps\\|pdf\\|svg\\)$"
+                         (org-element-property :path link))
+                        ;; ignore commented sections
+                        (save-excursion
+                          (goto-char (org-element-property :begin link))
+                          (not (or (org-in-commented-heading-p)
+                                   (org-at-comment-p)
+                                   (-intersection (org-get-tags) org-export-exclude-tags)))))
+                 (cl-incf counter)
+
+                 (let* ((start (org-element-property :begin link))
+                        (linenum (progn (goto-char start) (line-number-at-pos)))
+                        (fname (org-element-property :path link))
+                        (parent (car (cdr
+                                      (org-element-property :parent link))))
+                        (caption (cl-caaar (plist-get parent :caption)))
+                        (name (plist-get parent :name)))
+
+                   (if caption
+                       (format "[[file:%s::%s][Figure %s:]] %s\n" c-b linenum counter caption)
+                     ;; if it has no caption, try the name
+                     ;; if it has no name, use the file name
+                     (cond (name
+                            (format "[[file:%s::%s][Figure %s:]] %s\n" c-b linenum counter name))
+                           (fname
+                            (format "[[file:%s::%s][Figure %s:]] %s\n"
+                                    c-b linenum counter fname))))))))))
+      (switch-to-buffer "*List of Figures*")
+      (setq buffer-read-only nil)
+      (org-mode)
+      (erase-buffer)
+      (insert (mapconcat 'identity list-of-figures ""))
+      (goto-char (point-min))
+      ;; open links in the same window
+      (setq-local org-link-frame-setup
+                 '((file . find-file)))
+      (setq buffer-read-only t)
+      (use-local-map (copy-keymap org-mode-map))
+      (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
+
+
+(org-link-set-parameters "list-of-figures"
+                        :follow #'org-ref-list-of-figures
+                        :export (lambda (_path _desc format)
+                                  (cond
+                                   ((eq format 'latex)
+                                    (format "\\listoffigures")))))
+
+;;** List of tables
+;;;###autoload
+(defun org-ref-list-of-tables (&optional _arg)
+  "Generate a buffer with a list of tables.
+ARG does nothing."
+  (interactive)
+  (save-excursion
+    (widen)
+    (let* ((c-b (buffer-name))
+           (counter 0)
+           (list-of-tables
+            (org-element-map (org-ref-parse-buffer 'element) 'table
+              (lambda (table)
+                "create a link for to the table"
+               (save-excursion
+                 (goto-char (org-element-property :begin table))
+                 (when
+                     ;; ignore commented sections
+                     (not (or (org-in-commented-heading-p)
+                              (-intersection (org-get-tags) org-export-exclude-tags)
+                              (looking-at "#\\+RESULTS:") ))
+                   (cl-incf counter)
+                   (let* ((start (org-element-property :begin table))
+                          (linenum (progn (goto-char start) (line-number-at-pos)))
+                          (caption (cl-caaar (org-element-property :caption table)))
+                          (name (org-element-property :name table)))
+                     (if caption
+                         (format "[[file:%s::%s][Table %s:]] %s\n" c-b linenum counter caption)
+                       ;; if it has no caption, try the name
+                       ;; if it has no name, use generic name
+                       (cond (name
+                              (format "[[file:%s::%s][Table %s:]] %s\n"
+                                      c-b linenum counter name))
+                             (t
+                              (format "[[file:%s::%s][Table %s:]] No caption\n"
+                                      c-b linenum counter)))))))))))
+      (switch-to-buffer "*List of Tables*")
+      (setq buffer-read-only nil)
+      (org-mode)
+      (erase-buffer)
+      (insert (mapconcat 'identity list-of-tables ""))
+      (goto-char (point-min))
+      ;; open links in the same window
+      (setq-local org-link-frame-setup
+                 '((file . find-file)))
+      (setq buffer-read-only t)
+      (use-local-map (copy-keymap org-mode-map))
+      (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
+
+
+(org-link-set-parameters "list-of-tables"
+                        :follow #'org-ref-list-of-tables
+                        :export (lambda (_path _desc format)
+                                  (cond
+                                   ((eq format 'latex)
+                                    (format "\\listoftables")))))
+
+
+;;* Index link
+;;
+;; You need these lines in the header
+;; 
+;; #+latex_header: \usepackage{makeidx}
+;; #+latex_header: \makeindex
+(org-link-set-parameters "index"
+                        :follow (lambda (path)
+                                  (occur path))
+                        :export (lambda (path _desc format)
+                                  (cond
+                                   ((eq format 'latex)
+                                    (format "\\index{%s}" path)))))
+
+
+;; this will generate a temporary index of entries in the file when clicked on.
+;;;###autoload
+(defun org-ref-index (&optional _path)
+  "Open an *index* buffer with links to index entries.
+PATH is required for the org-link, but it does nothing here."
+  (interactive)
+  (let ((*index-links* '())
+       (*initial-letters* '()))
+
+    ;; get links
+    (org-element-map (org-ref-parse-buffer) 'link
+      (lambda (link)
+       (let ((plist (nth 1 link)))
+
+         (when (equal (plist-get plist ':type) "index")
+           (add-to-list
+            '*index-links*
+            (cons (plist-get plist :path)
+                  (format
+                   "[[elisp:(progn (switch-to-buffer \"%s\") (goto-char %s) (org-cycle '(64)))][%s]] "
+                   (current-buffer)
+                   (plist-get plist :begin) ;; position of link
+                   ;; grab a description
+                   (save-excursion
+                     (goto-char (plist-get plist :begin))
+                     (if (thing-at-point 'sentence)
+                         ;; get a sentence
+                         (let ((s (thing-at-point 'sentence)))
+                           (cl-loop for char in '("[" "]" "\n")
+                                    do
+                                    (setq s (replace-regexp-in-string
+                                             (regexp-quote char) " " s)))
+                           (concat s " "))
+                       ;; or call it a link
+                       "link")))))))))
+
+    ;; sort the links
+    (setq *index-links* (cl-sort *index-links* 'string-lessp :key 'car))
+
+    ;; now separate out into chunks first letters
+    (dolist (link *index-links*)
+      (push (substring (car link) 0 1) *initial-letters*))
+
+    (setq *initial-letters* (reverse *initial-letters*))
+
+    ;; now create the index
+    (switch-to-buffer (get-buffer-create "*index*"))
+    (org-mode)
+    (erase-buffer)
+    (insert "#+TITLE: Index\n\n")
+    (dolist (letter *initial-letters*)
+      (insert (format "* %s\n" (upcase letter)))
+      ;; now process the links
+      (while (and
+             *index-links*
+             (string= letter (substring (car (car *index-links*)) 0 1)))
+       (let ((link (pop *index-links*)))
+         (insert (format "%s %s\n\n" (car link) (cdr link))))))
+    (switch-to-buffer "*index*")))
+
+
+(org-link-set-parameters "printindex"
+                        :follow #'org-ref-index
+                        :export (lambda (_path _desc format)
+                                  (cond
+                                   ((eq format 'latex)
+                                    (format "\\printindex")))))
+
+
+(defun org-ref-idxproc (_backend)
+  "Preprocess index entries.
+Each entry is replaced by a radio target. The printindex is
+replaced by links to them."
+  (let* ((index-links (reverse (org-element-map (org-element-parse-buffer) 'link
+                                (lambda (lnk)
+                                  (when (string= "index" (org-element-property :type lnk))
+                                    lnk)))))
+        (sorted-groups (seq-sort-by
+                        (lambda (x)
+                          "Alphabetically sort groups"
+                          (car x))
+                        #'string-lessp
+                        (seq-group-by
+                         (lambda (lnk)
+                           (org-element-property :path lnk))
+                         index-links)))
+        (link-replacements '()))
+
+    ;; Sort within each group
+    (cl-loop for (key . links) in sorted-groups do
+            (setf (cdr (assoc key sorted-groups))
+                  (sort links (lambda (a b)
+                                (< (org-element-property :begin a)
+                                   (org-element-property :begin b))))))
+    
+    ;; Compute replacements for each index link.
+    (cl-loop for (key . links) in sorted-groups do
+            (cl-loop for i from 0 for lnk in links do
+                     (cl-pushnew (cons
+                                  (org-element-property :begin lnk)
+                                  (format "<<%s-%s>>" key i))
+                                 link-replacements)))
+
+    (cl-loop for il in index-links collect
+            (cl--set-buffer-substring
+             (org-element-property :begin il)
+             (org-element-property :end il)
+             (cdr (assoc (org-element-property :begin il) link-replacements))))
+
+    ;; Now we replace the printindex link
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (lnk)
+       (when (string= "printindex" (org-element-property :type lnk))
+         (cl--set-buffer-substring (org-element-property :begin lnk)
+                                   (org-element-property :end lnk)
+                                   ;; If sorted-groups is empty, we should do nothing I think.
+                                   (if sorted-groups
+                                       (format "*Index*\n\n%s"
+                                               (string-join
+                                                (cl-loop for (key . links) in sorted-groups collect
+                                                         (format "%s: %s"
+                                                                 key
+                                                                 (string-join 
+                                                                  (cl-loop for i from 0 for lnk in links collect
+                                                                           (format "[[%s-%s][%s-%s]] "
+                                                                                   (org-element-property :path lnk)
+                                                                                   i
+                                                                                   (org-element-property :path lnk)
+                                                                                   i))
+                                                                  ", ")))
+                                                "\n\n"))
+                                     "")))))))
+
+
+(provide 'org-ref-misc-links)
+
+;;; org-ref-misc-links.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-natbib-bbl-citeproc.el b/elpa/org-ref-20230507.1420/org-ref-natbib-bbl-citeproc.el
new file mode 100644 (file)
index 0000000..9d30d9b
--- /dev/null
@@ -0,0 +1,518 @@
+;;; org-ref-natbib-bbl-citeproc.el --- A bibtex + natbib BBL-based citeproc -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+;; This is a citation processor that uses the bbl from bibtex and natbib.
+;;
+;; It is kind of hacky. I parse the bbl file into entries, and then replace the
+;; in-text citations and the bibliography with data from the parsed bbl.
+;;
+;; The CSL exporter is probably better all around than this, but this does have
+;; the advantage of using LaTeX/bibtex for formatting.
+;;
+;; TODO: pre/post notes are not handled in the bbl file. They have to be handled
+;; separately
+;;
+;; This seems to work ok for
+;; See https://gking.harvard.edu/files/natnotes2.pdf
+;;
+;; Basically supports stylying options in natbib including [numbers, super, authoryear] for style,
+;; and [round, square, curly, angle] for in-text citations
+;; and [comma, semicolon; colon] for citation separators
+;; and [sort, compress, sort&compress] if you want to sort and/or compress citation numbers.
+;;
+;; longnamesfirst is not currently supported.
+;;
+;; To use this for HTML export you do something like this:
+;; (let ((org-export-before-parsing-hook '(org-ref-bbl-preprocess)))
+;;   (org-open-file (org-html-export-to-html)))
+;;
+;;
+;;; Code:
+
+(defvar org-ref-natmove)                       ;silence compiler
+
+(defun org-bbl-clean-string (s)
+  "Clean S of markups.
+This replaces some LaTeX markup and bibtex markups including:
+\\emph{}, \\doi{}, \\url{},\\citename, and {\\em ...} {\\bf ...},
+removes things like \\protect and \\penalty0, and replaces ~ with
+a space. This function is surely not complete, and it does not
+cover any math (yet)."
+  (with-temp-buffer
+    (insert s)
+    ;; I convert these to org syntax.
+    ;; \emph... -> org italics
+    ;; TODO This list is surely not complete.
+    ;; convert \cmd{stuff} to the format string
+    (let (p1 p2 p3 p4 ss cmd-p)
+      (cl-loop for (cmd . repl-format) in '(("emph" . "/%s/")
+                                           ("doi" . "%s")
+                                           ("url" . "%s")
+                                           ("citename" . "%s")
+                                           ;; natexlab seems to be for differentiating similar authors.
+                                           ("natexlab" . "(%s)")
+                                           ;; I use \ce{} a lot, and just strip it here.
+                                           ("ce" . "%s"))
+              do
+              (goto-char (point-min))
+              (while (search-forward (format "\\%s{" cmd) nil t)
+                (setq p1 (match-beginning 0)
+                      p2 (point))
+                (backward-char)
+                (forward-list)
+                (setq p4 (point)
+                      p3 (- (point) 1))
+                (setq s (buffer-substring p2 p3))
+                (cl--set-buffer-substring p1 p4 (format repl-format s))))
+
+      ;; some times we have these markups TODO I bet there are more Note I use
+      ;; non-breaking spaces here to make the org syntax ok. It doesn't seem to
+      ;; do quite the right thing in the bib-items though.
+      (cl-loop for (markup . fmt) in '(("\\em" . " /%s/ ")
+                                      ("\\it" . " /%s/ ")
+                                      ("\\bf" . " *%s* ")
+                                      ("\\tt" . " =%s= "))
+              do
+              (goto-char (point-min))
+              (while (search-forward (concat "{" markup) nil t)
+                (setq p1 (match-beginning 0)
+                      p2 (point))
+                (goto-char (match-beginning 0))
+                (forward-list)
+                (setq p4 (point)
+                      p3 (- (point) 1))
+                (setq ss (string-trim (buffer-substring p2 p3)))
+                (setf (buffer-substring p1 p4) (format fmt ss))))
+
+      ;; {text} for protecting case. This is tricky to do reliably. I try to check
+      ;; if this is not part of a command, and skip it if so. This leaves
+      ;; un-cleaned commands in, which is desirable to me so you can see if there
+      ;; are ones we might handle in the future.
+      (goto-char (point-min))
+      (while (search-forward "{" nil t)
+       ;; I think if we go back a word, and are then looking back at \\, we are in a command.
+       ;; this would fail on a latex command like \word-word{} but I can't think of any right now.
+       (save-excursion
+         (backward-word)
+         (setq cmd-p (looking-back "\\\\" 1)))
+       ;; This looks back for a \cmd, basically things not a closing }
+       (unless cmd-p
+         (setq p1 (match-beginning 0)
+               p2 (point))
+         (backward-char)
+         (forward-list)
+         (setq p4 (point)
+               p3 (- (point) 1))
+         (setq s (buffer-substring p2 p3))
+         (cl--set-buffer-substring p1 p4 s))))
+
+
+    (let ((result (buffer-string)))
+      (cl-loop for (s . repl) in '(("~" . " ")
+                                  ("\\\\&" . "&")
+                                  ("\\\\protect" . "")
+                                  ("\\\\penalty0" . "")
+                                  ("\\\\ " . " "))
+              do
+              (setq result (replace-regexp-in-string s repl result)))
+      result)))
+
+
+(defun org-ref-bbl-get-natbib-options ()
+  "Return natbib-options (including the brackets).
+Defaults to [numbers,super,sort]"
+  (goto-char (point-min))
+  (if (re-search-forward "\\usepackage\\(?1:\\[.*\\]\\)?{natbib}")
+      (match-string 1)
+    "[numbers,super,sort]"))
+
+
+
+(defun org-ref-bbl-entry (entry)
+  "ENTRY is a string containing the contents of a bibitem from a bbl file.
+Return the bibliography string associated with the entry. This is
+done in a temp-buffer so we don't actually modify the bbl file."
+  (with-temp-buffer
+    (insert (org-bbl-clean-string entry))
+    (goto-char (point-min))
+    (let (p1
+         p2 
+         authors
+         blocks
+         entry)
+      (setq p1 (point))
+      (search-forward "\\newblock")
+      (setq p2 (match-beginning 0))
+      (setq authors (string-join
+                    (mapcar 'string-trim
+                            (split-string (buffer-substring p1 p2) "\n"))
+                    " "))
+      (goto-char (- p2 1))
+      (while (search-forward "\\newblock" nil t)
+       (setq p1 (point))
+       (setq p2 (save-excursion
+                  (if (search-forward "\\newblock" nil t)
+                      (match-beginning 0)
+                    (point-max))))
+
+       (cl-pushnew (string-join
+                    (mapcar 'string-trim
+                            (split-string (buffer-substring p1 p2) "\n"))
+                    " ")
+                   blocks))
+
+      (setq entry (string-join (append (list authors) blocks) " "))
+      entry)))
+
+
+(defun org-ref-bbl-bibliography-data ()
+  "Get an p-list for each entry in the buffer.
+Assumes you are in a bbl file.
+Returns a plist (list bibitem-key :entry (org-ref-bbl-entry bibitem-entry)
+                         :index counter :bracket-data bibitem-bracket)"
+  (let ((data '())
+       N ss
+       p1 p2 bbl-max
+       bibitem-bracket
+       bibitem-key
+       bibitem-entry
+       (counter 0))
+
+    (goto-char (point-min))
+    (search-forward "\\end{thebibliography}")
+    ;; this is the character that the last line starts on.
+    (setq bbl-max (match-beginning 0))
+
+    (goto-char (point-min))
+    (when (looking-at "\\\\begin{thebibliography}{\\(?1:[0-9]*\\)}")
+      (setq N (string-to-number (match-string 1))))
+
+    ;; This might only work for numeric types
+    (if (> 0 N)
+       (cl-loop for i from 1 to N do
+                (search-forward "\\bibitem[")
+                ;; get text in [...]
+                (setq p1 (point))
+                (forward-list)
+                (setq p2 (point))
+                ;; the bracket usually contains [stuff (year) more stuff]
+                (setq ss (org-bbl-clean-string
+                          (buffer-substring-no-properties p1 p2)))
+
+                (let* ((s (string-match "(" ss))
+                       (e (string-match ")" ss s)))
+                  ;; in numerical mode I think this is ignored, but we get it
+                  ;; just in case for some later day.
+                  (setq bibitem-bracket (format "%s%s"
+                                                (substring ss 0 s)
+                                                (if (string= "()" (substring ss s (+ e 1)))
+                                                    ""
+                                                  (concat " " (substring ss s (+ e 1)))))))
+
+                ;; Now get the key. From the last
+                (search-forward "{")
+                (goto-char (match-beginning 0))
+                (setq p1 (+ 1 (point)))
+                (forward-list)
+                (setq p2 (- (point) 1)
+                      bibitem-key (buffer-substring p1 p2))
+
+                ;; Now get up to the next bibitem
+                (setq p1 (point))
+                (save-excursion
+                  (setq p2 (or (when (search-forward "\\bibitem[" nil t)
+                                 (match-beginning 0))
+                               bbl-max)))
+                (setq bibitem-entry (string-trim (buffer-substring p1 p2)))
+
+                (cl-pushnew (list bibitem-key :entry (org-ref-bbl-entry bibitem-entry)
+                                  :index i :bracket-data bibitem-bracket)
+                            data))
+      ;; no number found probably author year
+      (while (search-forward "\\bibitem[" nil t)
+       (cl-incf counter)
+       ;; get text in [...]
+       (setq p1 (point))
+       (search-forward "]")
+       (backward-char)
+       (setq p2 (point))
+
+       (setq ss (org-bbl-clean-string
+                 (buffer-substring-no-properties p1 p2)))
+
+       (let* ((s (string-match "(" ss))
+              (e (string-match ")" ss s)))
+
+         (setq bibitem-bracket (format "%s%s"
+                                       (substring ss 0 s)
+                                       (if (string= "()" (substring ss s (+ e 1)))
+                                           ""
+                                         (concat " " (substring ss s (+ e 1)))))))
+
+
+       ;; Now get the key. From the last
+       (search-forward "{")
+       (goto-char (match-beginning 0))
+       (setq p1 (+ 1 (point)))
+       (forward-list)
+       (setq p2 (- (point) 1)
+             bibitem-key (buffer-substring p1 p2))
+
+       ;; Now get up to the next bibitem
+       (setq p1 (point))
+       (save-excursion
+         (setq p2 (or (when (search-forward "\\bibitem[" nil t)
+                        (match-beginning 0))
+                      bbl-max)))
+       (setq bibitem-entry (string-trim (buffer-substring p1 p2)))
+
+       (cl-pushnew (list bibitem-key :entry (org-ref-bbl-entry bibitem-entry)
+                         :index counter :bracket-data bibitem-bracket)
+                   data)))
+    (reverse data)))
+
+
+(defun org-ref-bbl-compress-numbers (lst)
+  "Take a list like (1 2 3 6) and return \"1-3,6\"."
+  (let* ((a (pop lst))
+        b
+        (sequence (list a))
+        (sequentials '()))
+    (while lst
+      (setq b (pop lst))
+      (if (= (- b a) 1)
+         ;; we have a sequence, add it, set a=b and continue
+         (setq sequence (append sequence (list b))
+               a b)
+       ;; lost sequence, store the sequence
+       (setq sequentials (append sequentials (list sequence))
+             sequence (list b)
+             a b)))
+    ;; store last one
+    (setq sequentials (append sequentials (list sequence)))
+
+    ;; Now construct strings for each group
+    (cl-loop for group in sequentials collect
+            (pcase (length group)
+              (1 (format "[[%s]]" (car group)))
+              (2 (format "[[%s]],[[%s]]" (cl-first group) (cl-second group)))
+              (_ (format "[[%s]]-[[%s]]" (cl-first group) (car (last group))))))))
+
+
+(defun org-ref-replace-cite-link (link bibdata NATBIB-OPTIONS backend)
+  "NATBIB-OPTIONS is the string to options.
+Argument LINK is an org link for a citation.
+Argument BIBDATA the data parsed from a bbl file.
+Argument BACKEND is the export format."
+  (let* ((refs (plist-get (org-ref-parse-cite-path (org-element-property :path link)) :references))
+        (keys (cl-loop for ref in refs collect (plist-get ref :key)))
+        items replacements replacement joiner p1 p2)
+
+    ;; Numeric types
+    (cond
+     ((or (string-match-p "numbers" NATBIB-OPTIONS)
+         (string-match-p "super" NATBIB-OPTIONS))
+      (setq items (cl-loop for key in keys
+                          collect (plist-get (cdr (assoc key bibdata)) :index)))
+
+      (when (string-match-p "sort" NATBIB-OPTIONS)
+       (setq items (sort items #'<)))
+
+      (setq replacements (if (string-match-p "compress" NATBIB-OPTIONS)
+                            (org-ref-bbl-compress-numbers items)
+                          ;; these are fuzzy org links to the target in item.
+                          (cl-loop for item in items collect (format "[[%s]]" item)))))
+
+     ;; authoryear types
+     ;; This html provides an anchor that is named. Targets are usually replaced with numbers, not the text.
+     ((string-match-p "authoryear" NATBIB-OPTIONS)
+      (setq replacements (cl-loop for key in keys
+                                 collect
+                                 (cond
+                                  ((eq backend 'html)
+                                   (format "@@html:<a href=\"#%s\">%s</a>@@"
+                                           (plist-get (cdr (assoc key bibdata)) :bracket-data) 
+                                           (plist-get (cdr (assoc key bibdata)) :bracket-data)))
+                                  (t
+                                   (format "[[%s]]" (plist-get (cdr (assoc key bibdata)) :bracket-data)))))))
+     (t
+      (error "%s not supported yet" NATBIB-OPTIONS)))
+
+    ;; Now join all the replacements for each reference
+    (setq joiner (cond
+                 ((string-match-p "comma" NATBIB-OPTIONS)
+                  ",")
+                 ((or (string-match-p "semicolon" NATBIB-OPTIONS)
+                      (string-match-p "colon" NATBIB-OPTIONS))
+                  ";")
+                 (t
+                  ";")))
+
+    ;; Finally create the overall replacement
+    (setq replacement (cond
+                      ((string-match-p "super" NATBIB-OPTIONS)
+                       (format "^{%s}" (string-join replacements joiner)))
+
+                      ((string-match-p "square" NATBIB-OPTIONS)
+                       (format "[%s]" (string-join replacements joiner)))
+
+                      ((string-match-p "round" NATBIB-OPTIONS)
+                       (format "(%s)" (string-join replacements joiner)))
+
+                      ((string-match-p "curly" NATBIB-OPTIONS)
+                       (format "{%s}" (string-join replacements joiner)))
+
+                      ((string-match-p "angle" NATBIB-OPTIONS)
+                       (format "<%s>" (string-join replacements joiner)))
+
+                      ((string-match-p "authoryear" NATBIB-OPTIONS)
+                       (string-join replacements joiner))
+
+                      (t
+                       (error "Cannot compute replacement for %s" NATBIB-OPTIONS))))
+
+    ;; When super is the style, we need to replace any blanks back to the last
+    ;; non-space. We just look back and move point if needed here.
+    (if (not (string-match-p "super" NATBIB-OPTIONS))
+       (setq p1 (org-element-property :begin link))
+      (goto-char (org-element-property :begin link))
+      (while (looking-back " " 1)
+       (backward-char))
+      (setq p1 (point)))
+
+    (setq p2 (org-element-property :end link))
+
+    ;; org-ref-natmove is dynamically bound here
+    (when org-ref-natmove
+      (save-excursion
+       (goto-char (org-element-property :end link))
+       (skip-chars-backward " ")
+
+       (when (string-match-p "[[:punct:]]" (buffer-substring (point) (+ (point) 1)))
+         ;; Get the character
+         (setq replacement (concat (buffer-substring (org-element-property :end link)
+                                                     (+ 1 (org-element-property :end link)))
+                                   replacement)
+               p2 (+ 1 (org-element-property :end link))))))
+
+    (setf (buffer-substring p1 p2)
+         (concat replacement (make-string (org-element-property :post-blank link) ? )))))
+
+
+(defun org-ref-bbl-replace-bibliography (bib-link bibdata NATBIB-OPTIONS backend)
+  "Get a replacement bibliography string for BIBDATA and NATBIB-OPTIONS.
+BIBDATA comes from `org-ref-bbl-bibliography-data'.
+Argument BIB-LINK an org link for a bibliography.
+Argument BACKEND is the export format."
+  (cl--set-buffer-substring (org-element-property :begin bib-link)
+                           (org-element-property :end bib-link)
+                           (cond
+                            ((or (string-match-p "numbers" NATBIB-OPTIONS)
+                                 (string-match-p "super" NATBIB-OPTIONS))
+                             (concat "\n* Bibliography\n\n"
+                                     (string-join
+                                      (cl-loop for entry in bibdata collect
+                                               (format "%s. <<%s>> %s"
+                                                       (plist-get (cdr entry) :index)
+                                                       (plist-get (cdr entry) :index)
+                                                       (plist-get (cdr entry) :entry)))
+                                      "\n\n")))
+
+
+                            ((string-match-p "authoryear" NATBIB-OPTIONS)
+                             (concat "\n* Bibliography\n\n"
+                                     (string-join
+                                      (cl-loop for entry in bibdata collect
+                                               (cond
+                                                ((eq backend 'html)
+                                                 (format "- @@html:<a id=\"%s\"></a>@@(%s) %s\n"
+                                                         (plist-get (cdr entry) :bracket-data)
+                                                         (plist-get (cdr entry) :bracket-data)
+                                                         (plist-get (cdr entry) :entry)))
+                                                (t
+                                                 (format "- <<%s>> %s"
+                                                         (plist-get (cdr entry) :bracket-data)
+                                                         (plist-get (cdr entry) :entry)))))
+                                      
+                                      
+                                      "\n")))
+                            (t
+                             (error "%s not supported yet" NATBIB-OPTIONS)))))
+
+
+
+(defun org-ref-bbl-preprocess (&optional backend)
+  "Should work on a copy of the buffer.
+Meant to be used in `org-export-before-parsing-hook'.
+Optional argument BACKEND The export backend.
+
+You need a LaTeX file and a bbl file for it. This hook generates
+those, then gets the data, replaces the citations and the
+bibliography.
+"
+  (let* ((org-export-before-parsing-hook nil)
+        (tex-file (org-latex-export-to-latex))
+        (bbl-file (concat (file-name-sans-extension tex-file) ".bbl"))
+        natbib-options bibdata org-ref-natmove
+        buf)
+
+    (when-let (buf (find-buffer-visiting tex-file))
+      (kill-buffer buf))
+
+    (when-let (buf (find-buffer-visiting bbl-file))
+      (kill-buffer buf))
+
+    ;; refresh these
+    (call-process-shell-command (format "latex -shell-escape %s" tex-file))
+    (call-process-shell-command (format "bibtex %s" (file-name-sans-extension tex-file)))
+
+    (setq buf (find-file-noselect tex-file))
+    (with-current-buffer buf
+      (goto-char (point-min))
+      (setq natbib-options (org-ref-bbl-get-natbib-options))
+      (goto-char (point-min))
+      (setq org-ref-natmove (search-forward "\\usepackage{natmove}" nil t)))
+    (kill-buffer buf)
+
+    (setq buf (find-file-noselect bbl-file))
+    (with-current-buffer buf
+      (goto-char (point-min))
+      (setq bibdata (org-ref-bbl-bibliography-data)))
+    (kill-buffer buf)
+
+    ;; Replace all the cite links
+    (cl-loop for cl in (reverse (org-ref-get-cite-links)) do
+            (org-ref-replace-cite-link cl bibdata natbib-options backend))
+
+    (org-ref-bbl-replace-bibliography
+     (org-element-map (org-element-parse-buffer) 'link
+       (lambda (lnk)
+        (when (string= (org-element-property :type lnk) "bibliography")
+          lnk))
+       nil
+       t)
+     bibdata natbib-options backend)))
+
+
+(provide 'org-ref-natbib-bbl-citeproc)
+
+;;; org-ref-natbib-bbl-citeproc.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-pdf.el b/elpa/org-ref-20230507.1420/org-ref-pdf.el
new file mode 100644 (file)
index 0000000..248b1ee
--- /dev/null
@@ -0,0 +1,176 @@
+;;; org-ref-pdf.el --- Drag-n-drop PDF onto bibtex files  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library provides functions to enable drag-n-drop of pdfs onto a bibtex
+;; buffer to add bibtex entries to it.
+;;
+;; [2021-08-29 Sun] I have not found drag-and-drop to be especially reliable,
+;; and don't recommend you use it. This code relies 'pdf-tools, which is slow to
+;; load for me. pdf-tools is no longer automatically installed, so if you use
+;; this, you should install it yourself.
+
+;; TODO: If no DOI is found, figure out a way to do a crossref/google query to
+;; get a doi. This needs a reliable title/citation.
+
+;;; Code:
+(require 'pdf-tools)
+
+(require 'f)
+
+
+(eval-when-compile
+  (require 'cl-lib))
+
+
+(defgroup org-ref-pdf nil
+  "Customization group for org-ref-pdf"
+  :tag "Org Ref PDF"
+  :group 'org-ref-pdf)
+
+
+(defcustom pdftotext-executable
+  "pdftotext"
+  "Executable for pdftotext. Set if the executable is not on your
+path, or you want to use another version."
+  :type 'file
+  :group 'org-ref-pdf)
+
+
+(defcustom org-ref-pdf-doi-regex
+  "10\\.[0-9]\\{4,9\\}/[-+._;()/:A-Z0-9]+"
+  "Regular expression to match DOIs in a pdf converted to text."
+  :type 'regexp
+  :group 'org-ref-pdf)
+
+
+(defcustom org-ref-pdf-to-bibtex-function
+  'copy-file
+  "Function for getting  a pdf to a directory.
+Defaults to `copy-file', but could also be `rename-file'."
+  :type 'File :group 'org-ref-pdf)
+
+
+(defun org-ref-extract-doi-from-pdf (pdf)
+  "Try to extract a doi from a PDF file.
+There may be more than one doi in the file. This function returns
+all the ones it finds based on two patterns: doi: up to a quote,
+bracket, space or end of line. dx.doi.org/up to a quote, bracket,
+space or end of line.
+
+If there is a trailing . we chomp it off. Returns a list of doi
+strings, or nil."
+  (with-temp-buffer
+    (insert (shell-command-to-string (format "%s %s -"
+                                            pdftotext-executable
+                                            (shell-quote-argument pdf))))
+    (goto-char (point-min))
+    (let ((matches '()))
+      (while (re-search-forward org-ref-pdf-doi-regex nil t)
+       ;; I don't know how to avoid a trailing . on some dois with the
+       ;; expression above, so if it is there, I chomp it off here.
+       (let ((doi (match-string 0)))
+         (when (or (s-ends-with? "." doi) (s-ends-with? ";" doi))
+           (setq doi (substring doi 0 (- (length doi) 1))))
+         (cl-pushnew doi matches :test #'equal)))
+      matches)))
+
+
+(defun org-ref-pdf-doi-candidates (dois)
+  "Generate candidate list for a completion source.
+Used when multiple dois are found in a pdf file."
+  (cl-loop for doi in dois
+          collect
+          (condition-case nil
+              (cons
+               (plist-get (doi-utils-get-json-metadata doi) :title)
+               doi)
+            (error (cons (format "%s read error" doi) doi)))))
+
+
+(defun org-ref-bibtex-key-from-doi (doi)
+  "Return a bibtex entry's key from a DOI.
+BIB is an optional filename to get the entry from."
+  (catch 'key
+    (cl-loop for bibfile in (if (stringp bibtex-completion-bibliography)
+                               (list bibtex-completion-bibliography)
+                             bibtex-completion-bibliography)
+            do
+            (with-temp-buffer
+              (insert-file-contents (expand-file-name bibfile))
+              (when (search-forward doi)
+                (bibtex-beginning-of-entry)
+                (throw 'key (cdr (assoc "=key=" (bibtex-parse-entry)))))))))
+
+
+;;;###autoload
+(defun org-ref-pdf-to-bibtex ()
+  "Add pdf of current buffer to bib file and save pdf. The pdf
+should be open in Emacs using the `pdf-tools' package."
+  (interactive)
+  (when (not (f-ext? (downcase (buffer-file-name)) "pdf"))
+    (error "Buffer is not a pdf file"))
+  ;; Get doi from pdf of current buffer
+  (let* ((dois (org-ref-extract-doi-from-pdf (buffer-file-name)))
+         (doi-utils-download-pdf nil)
+         (doi (if (= 1 (length dois))
+                  (car dois)
+                (completing-read "Select DOI: " dois))))
+    ;; Add bib entry from doi:
+    (doi-utils-add-bibtex-entry-from-doi doi)
+    ;; Copy pdf to a directory
+    (let ((key (org-ref-bibtex-key-from-doi doi)))
+      (funcall org-ref-pdf-to-bibtex-function
+              (buffer-file-name)
+               (expand-file-name (format "%s.pdf" key) (org-ref-library-path))))))
+
+
+;;;###autoload
+(defun org-ref-pdf-debug-pdf (pdf-file)
+  "Try to debug getting a doi from a pdf.
+Opens a buffer with the pdf converted to text, and `occur' on the
+variable `org-ref-pdf-doi-regex'."
+  (interactive "fPDF: ")
+  (switch-to-buffer (get-buffer-create "*org-ref-pdf debug*"))
+  (erase-buffer)
+  (insert (shell-command-to-string (format "%s %s -"
+                                          pdftotext-executable
+                                          (shell-quote-argument pdf-file))))
+  (goto-char (point-min))
+  (highlight-regexp org-ref-pdf-doi-regex)
+  (occur org-ref-pdf-doi-regex)
+  (switch-to-buffer-other-window "*Occur*"))
+
+
+;;;###autoload
+(defun org-ref-pdf-crossref-lookup ()
+  "Lookup highlighted text in PDFView in CrossRef."
+  (interactive)
+  (require 'pdf-view)
+  (unless (pdf-view-active-region-p)
+    (error "The region is not active"))
+  (let* ((txt (pdf-view-active-region-text)))
+    (pdf-view-deactivate-region)
+    (crossref-lookup (mapconcat 'identity txt "         \n"))))
+
+
+(provide 'org-ref-pdf)
+;;; org-ref-pdf.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-pgk.el b/elpa/org-ref-20230507.1420/org-ref-pgk.el
new file mode 100644 (file)
index 0000000..9e7c134
--- /dev/null
@@ -0,0 +1,14 @@
+(define-package "org-ref" "3.0.0" "citations, cross-references and bibliographies in org-mode"
+  '((dash "0")
+    (s "0")
+    (f "0")
+    (hydra "0")
+    (htmlize "0")
+    (parsebib "0")
+    (bibtex-completion "0")
+    (emacs "26")))
+
+
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/elpa/org-ref-20230507.1420/org-ref-pkg.el b/elpa/org-ref-20230507.1420/org-ref-pkg.el
new file mode 100644 (file)
index 0000000..96065ef
--- /dev/null
@@ -0,0 +1,24 @@
+(define-package "org-ref" "20230507.1420" "citations, cross-references and bibliographies in org-mode"
+  '((org "9.4")
+    (dash "0")
+    (s "0")
+    (f "0")
+    (htmlize "0")
+    (hydra "0")
+    (avy "0")
+    (parsebib "0")
+    (bibtex-completion "0")
+    (citeproc "0")
+    (ox-pandoc "0"))
+  :commit "83396bfa793850e8bc43755912bbdede0df87815" :authors
+  '(("John Kitchin" . "jkitchinNOSPAMandrew.cmu.edu"))
+  :maintainers
+  '(("John Kitchin" . "jkitchinNOSPAMandrew.cmu.edu"))
+  :maintainer
+  '("John Kitchin" . "jkitchinNOSPAMandrew.cmu.edu")
+  :keywords
+  '("org-mode" "cite" "ref" "label")
+  :url "https://github.com/jkitchin/org-ref")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/elpa/org-ref-20230507.1420/org-ref-pubmed.el b/elpa/org-ref-20230507.1420/org-ref-pubmed.el
new file mode 100644 (file)
index 0000000..b4aa044
--- /dev/null
@@ -0,0 +1,266 @@
+;;; org-ref-pubmed.el --- Links and functions for Pubmed and NIH databases  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;* Introduction
+
+;; This document is an experiment at creating a literate program to provide
+;; functions for interacting with pubmed databases.
+
+;; This library provides links that go to pubmed resources, e.g.
+
+;; pmcid:PMC3498956
+;;
+;; pmid:23162369
+;;
+;; and nihmsid:NIHMS395714
+;;
+;; See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details
+;; of these identifiers.
+;;
+;; For PMID there is one interactive function that inserts a bibtex entry:
+;; pubmed-insert-bibtex-from-pmid.
+
+;; This library is complementary to [[./doi-utils.org]].
+
+;;; Code:
+
+;;* PMID (from PubMed) link and functions
+
+;; A PMID is a number that identifies an entry in the Pubmed database.  The PMID
+;; is a unique reference number for PubMed citations. The PMID is a distinctly
+;; different number from the PMCID and is used only for PubMed records.
+
+(require 'dash)
+(require 'org)
+(require 'org-ref-utils)
+
+(org-link-set-parameters "pmid"
+                        :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pubmed/%s" link-string)))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s\">pmid:%s</a>" keyword (or desc keyword))) ; no output for html
+                                   ((eq format 'latex)
+                                    ;; write out the latex command
+                                    (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
+
+;;** Get MEDLINE metadata
+
+;; We can get bibliographic metadata from a pmid. Here we get the MEDLINE
+;; text. The website wraps the data in <pre></pre> tags.
+
+(defun pubmed-get-medline (pmid)
+  "Get MEDLINE text for PMID as a string."
+  (with-current-buffer
+      (url-retrieve-synchronously
+       (format "https://pubmed.ncbi.nlm.nih.gov/%s/?format=pubmed" pmid))
+    (goto-char (point-min))
+    (let ((p1 (search-forward "<pre class=\"article-details\" id=\"article-details\">"))
+          (p2 (search-forward "</pre>")))
+      (replace-regexp-in-string "\r" "" (buffer-substring (+ 1 p1) (- p2 6))))))
+
+;;** Parse the PMID MEDLINE data
+
+;; We can parse this into a data structure.
+(defun pubmed-parse-medline (pmid)
+  "Parse the medline text for PMID and return a list of cons cells."
+  (let ((data '())
+        (p1)
+        (p2)
+        (tag)
+        (value))
+    (with-temp-buffer (insert (pubmed-get-medline pmid))
+                      (goto-char (point-min))
+                      (while (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- "
+                                               nil t)
+                        (setq tag (match-string 1))
+                        ;; point is at end of the search
+                        (setq p1 (point))
+                        ;; now go to next tag
+                        (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
+                        (setq p2 (- (match-beginning 1) 1))
+                        (setq value (buffer-substring p1 p2))
+                        (setq data (append data (list (cons tag value))))
+                        ;; now go back to last tag to get the next one
+                        (goto-char p1)))
+    data))
+
+;;** PMID to bibtex entry
+
+;; The point of parsing the MEDLINE text is so we can make bibtex entries. We
+;; only support Journal articles for now.
+
+(defun pubmed-pmid-to-bibtex (pmid)
+  "Convert a PMID to a bibtex entry."
+  (let* ((data (pubmed-parse-medline pmid))
+         (type (downcase (cdr (assoc "PT" data))))
+         (title (cdr (assoc "TI" data)))
+         (authors (mapconcat 'cdr
+                             (-filter (lambda (x)
+                                        (string= (car x) "FAU"))
+                                      data)
+                             " and "))
+         (abstract (cdr (assoc "AB" data)))
+         (volume (cdr (assoc "VI" data)))
+         (issue (cdr (assoc "IP" data)))
+         (journal (cdr (assoc "JT" data)))
+         (year (cdr (assoc "DP" data)))
+         (pages (cdr (assoc "PG" data)))
+         (aid (cdr (assoc "AID" data))))
+
+    (cond
+     ((string= type "journal article")
+      (concat "@article{,
+ author = {" authors "},
+ title = {" title "},
+ abstract = {" abstract "},
+ journal = {" journal "},
+ volume = {" volume "},
+ number = {" issue "},
+ year = {" (car (split-string year)) "},
+ pages = {" pages "},
+ doi = {" (replace-regexp-in-string " \\[doi\\]" "" (or aid "")) "},
+}"))
+     (t
+      (message "No conversion for type: %s" type)))))
+
+;; And we probably want to be able to insert a bibtex entry
+
+;;;###autoload
+(defun pubmed-insert-bibtex-from-pmid (pmid)
+  "Insert a bibtex entry at point derived from PMID.
+You must clean the entry after insertion."
+  (interactive "sPMID: ")
+  (insert (pubmed-pmid-to-bibtex pmid)))
+
+
+;;* Pubmed Central (PMC) link
+
+;; A PMCID starts with PMC and is followed by numbers. The PMCID is a unique
+;; reference number or identifier that is assigned to every article that is
+;; accepted into PMC. The PMCID is also used by recipients of NIH funding to
+;; demonstrate compliance with the NIH Public Access policy. The PMCID can be
+;; found in both PMC and PubMed.
+
+;; Here we define a new link. Clicking on it simply opens a webpage to the
+;; article.
+
+(org-link-set-parameters "pmcid"
+                        :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/%s" link-string)))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/%s\">pmcid:%s</a>" keyword (or desc keyword)))
+                                   ((eq format 'latex)
+                                    (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/%s}{%s}" keyword (or desc keyword))))))
+
+;;* NIHMSID
+
+;; The NIHMSID is a preliminary article identifier that applies only to
+;; manuscripts deposited through the NIHMS system. The NIHMSID is only valid for
+;; compliance reporting for 90 days after the publication date of an
+;; article. Once the Web version of the NIHMS submission is approved for
+;; inclusion in PMC and the corresponding citation is in PubMed, the article
+;; will also be assigned a PMCID.
+
+(org-link-set-parameters "nihmsid"
+                        :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s" link-string)))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid//%s\">nihmsid:%s</a>" keyword (or desc keyword)))
+                                   ((eq format 'latex)
+                                    ;; write out the latex command
+                                    (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
+
+
+;;* Searching pubmed
+
+;;;###autoload
+(defun pubmed ()
+  "Open http://www.ncbi.nlm.nih.gov/pubmed in a browser."
+  (interactive)
+  (browse-url "http://www.ncbi.nlm.nih.gov/pubmed"))
+
+
+;;;###autoload
+(defun pubmed-advanced ()
+  "Open http://www.ncbi.nlm.nih.gov/pubmed/advanced in a browser."
+  (interactive)
+  (browse-url "http://www.ncbi.nlm.nih.gov/pubmed/advanced"))
+
+
+;;;###autoload
+(defun pubmed-simple-search (query)
+  "Open QUERY in Pubmed in a browser."
+  (interactive "sQuery: ")
+  (browse-url
+   (format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
+
+
+(org-link-set-parameters "pubmed-search"
+                        :follow (lambda (query)
+                                  "Open QUERY in a `pubmed-simple-search'."
+                                  (pubmed-simple-search query))
+                        :export (lambda (query desc format)
+                                  (let ((url (format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
+                                    (cond
+                                     ((eq format 'html)
+                                      (format "<a href=\"%s\">%s</a>" url (or desc (concat "pubmed-search:" query))))
+                                     ((eq format 'latex)
+                                      (format "\\href{%s}{%s}" url (or desc (concat "pubmed-search:" query))))))))
+
+;; ** Pubmed clinical
+;; These functions were suggested by Colin Melville <casm40NOSPAMgmail.com>.
+;;;###autoload
+(defun pubmed-clinical ()
+  "Open http://www.ncbi.nlm.nih.gov/pubmed/clinical in a browser."
+  (interactive)
+  (browse-url "http://www.ncbi.nlm.nih.gov/pubmed/clinical"))
+
+
+;;;###autoload
+(defun pubmed-clinical-search (query)
+  "Open QUERY in pubmed-clinical."
+  (interactive "sQuery: ")
+  (browse-url
+   (format "https://www.ncbi.nlm.nih.gov/pubmed/clinical?term=%s" (url-hexify-string query))))
+
+
+(org-link-set-parameters "pubmed-clinical"
+                        :follow (lambda (query)
+                                  "Open QUERY in a `pubmed-clinical-search'."
+                                  (pubmed-clinical-search query))
+                        :export (lambda (query desc format)
+                                  (let ((url (format "http://www.ncbi.nlm.nih.gov/pubmed/clinical?term=%s"
+                                                     (url-hexify-string query))))
+                                    (cond
+                                     ((eq format 'html)
+                                      (format "<a href=\"%s\">%s</a>" url
+                                              (or desc (concat "pubmed-clinical-search:" query))))
+                                     ((eq format 'latex)
+                                      (format "\\href{%s}{%s}" url
+                                              (or desc (concat "pubmed-clinical-search:" query))))))))
+
+
+(provide 'org-ref-pubmed)
+;;; org-ref-pubmed.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-ref-links.el b/elpa/org-ref-20230507.1420/org-ref-ref-links.el
new file mode 100644 (file)
index 0000000..5f6a9e4
--- /dev/null
@@ -0,0 +1,632 @@
+;;; org-ref-ref-links.el --- cross-reference links for org-ref -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;;
+
+;;; Code:
+(eval-and-compile (require 'org-macs))
+(require 'hydra)
+
+(defcustom org-ref-default-ref-type "ref"
+  "Default ref link type to use when inserting ref links."
+  :type 'string
+  :group 'org-ref)
+
+
+(defcustom org-ref-activate-ref-links t
+  "If non-nil use font lock to activate ref links.
+Activation can be slow in large documents with a lot of ref
+links. Set this to nil to turn off activation."
+  :type 'boolean
+  :group 'org-ref)
+
+
+(defface org-ref-ref-face
+  `((t (:inherit org-link :foreground "dark red")))
+  "Face for ref links in org-ref."
+  :group 'org-ref-faces)
+
+
+(defvar org-ref-label-re
+  (rx-to-string
+   '(group-n 1 (one-or-more (any word "-.:?!`'/*@+|(){}<>&_^$#%~"))))
+  "Regexp for labels.")
+
+
+(defvar org-ref-label-link-re
+  (rx-to-string
+   `(seq "label:" (group-n 1 (one-or-more (any word "-.:?!`'/*@+|(){}<>&_^$#%~")))))
+  "Regexp for label links.")
+
+
+(defvar org-ref-ref-label-regexps
+  (list
+   (concat ":ID:\\s-+" org-ref-label-re "\\_>")
+   ;; CUSTOM_ID in a heading
+   (concat ":CUSTOM_ID:\\s-+" org-ref-label-re "\\_>")
+   ;; #+name
+   (concat "^\\s-*#\\+name:\\s-+" org-ref-label-re "\\_>")
+   ;; labels in latex
+   (concat "\\\\label{" org-ref-label-re "}")
+   ;; A target, code copied from org-target-regexp and group 1 numbered.
+   (let ((border "[^<>\n\r \t]"))
+     (format "<<\\(?1:%s\\|%s[^<>\n\r]*%s\\)>>"
+            border border border))
+   ;; A label link
+   (concat "label:" org-ref-label-re "\\_>")
+   "\\\\lstset{.*label=\\(?1:.*?\\),.*}")
+  "List of regular expressions to labels.
+The label should always be in group 1.")
+
+
+(defvar org-ref-ref-types
+  '(("ref" "A regular cross-reference to a label")
+    ("eqref" "A cross-reference to an equation")
+    ("pageref" "to the page number a label is on")
+    ("nameref" "to the name associated with a label (e.g. a caption)")
+    ("autoref" "from hyperref, adds automatic prefixes")
+    ("Autoref" "from hyperref, capitalized version of autoref")
+    ("cref" "from cleveref, adds automatic prefixes, and condenses multiple refs")
+    ("Cref" "from cleveref, capitalized version of cref")
+    ("crefrange" "from cleveref, makes a range of refs from two refs with a prefix")
+    ("Crefrange" "from cleveref, capitalized prefix version of crefrange"))
+  "List of ref link types (type description).")
+
+
+(defun org-ref-select-ref-type ()
+  "Select a ref type with annotated completion."
+  (let* ((type-annotation (lambda (s)
+                           (let ((item (assoc s minibuffer-completion-table)))
+                             (when item (concat
+                                         (make-string (- 12 (length s)) ? )
+                                         "-- "
+                                         (cl-second item))))))
+        (completion-extra-properties `(:annotation-function ,type-annotation)))
+    (completing-read "Type: " org-ref-ref-types)))
+
+
+(defun org-ref-change-ref-type (new-type)
+  "Change the ref type to NEW-TYPE."
+  (interactive (list (org-ref-select-ref-type)))
+  (let* ((cite-link (org-element-context))
+        (old-type (org-element-property :type cite-link))
+        (begin (org-element-property :begin cite-link))
+        (end (org-element-property :end cite-link))
+        (bracketp (eq 'bracket (org-element-property :format cite-link)))
+        (path (org-element-property :path cite-link))
+        (deltap (- (point) begin)))
+    ;; note this does not respect brackets
+    (cl--set-buffer-substring begin end
+                             (concat
+                              (if bracketp "[[" "")
+                              new-type ":" path
+                              (if bracketp "]]" "")))
+    ;; try to preserve the character the point is on.
+    (goto-char (+ begin deltap (- (length new-type) (length old-type))))))
+
+
+(defvar-local org-ref-label-cache nil
+  "Buffer-local cache variable for labels.")
+
+
+(defvar-local org-ref-buffer-chars-modified-tick nil
+  "Buffer-local variable to hold `buffer-chars-modified-tick'.")
+
+
+(defun org-ref-get-labels ()
+  "Return a list of referenceable labels in the document.
+You can reference:
+A NAME keyword
+A CUSTOM_ID property on a heading
+A LaTeX label
+A target.
+A label link
+A setting in lstset
+
+See `org-ref-ref-label-regexps' for the patterns that find these.
+
+Returns a list of cons cells (label . context).
+
+It is important for this function to be fast, since we use it in
+font-lock."
+  (if (or
+       ;; if we have not checked we have to check
+       (null org-ref-buffer-chars-modified-tick)
+       ;; Now check if buffer has changed since last time we looked. We check
+       ;; this with the buffer-chars-modified-tick which keeps track of changes.
+       ;; If this hasn't changed, no chars have been modified.
+       (not (= (buffer-chars-modified-tick)
+              org-ref-buffer-chars-modified-tick)))
+      ;; We need to search for all the labels either because we don't have them,
+      ;; or the buffer has changed since we looked last time.
+      (let ((case-fold-search t)
+           (rx (string-join org-ref-ref-label-regexps "\\|"))
+           (labels '())
+           oe ;; org-element
+           context
+           data)
+       (save-excursion
+         (org-with-wide-buffer
+          (goto-char (point-min))
+          (while (re-search-forward rx nil t)
+            (save-match-data
+              ;; Here we try to get some relevant context for different things you
+              ;; might reference.
+              (setq oe (org-element-context)
+                    context (string-trim
+                             (pcase (car oe)
+                               ('latex-environment (buffer-substring
+                                                    (org-element-property :begin oe)
+                                                    (org-element-property :end oe)))
+                               ;; figure
+                               ('paragraph (buffer-substring
+                                            (org-element-property :begin oe)
+                                            (org-element-property :end oe)))
+                               ('table (buffer-substring
+                                        (org-element-property :begin oe)
+                                        (org-element-property :end oe)))
+                               ;; Headings fall here.
+                               (_ (buffer-substring (line-beginning-position)
+                                                    (line-end-position)))))))
+            (cl-pushnew (cons (match-string-no-properties 1) context)
+                        labels))))
+       
+       ;; reverse so they are in the order we find them.
+       (setq
+        org-ref-buffer-chars-modified-tick (buffer-chars-modified-tick)
+        org-ref-label-cache (delete-dups (reverse labels))))
+
+    ;; retrieve the cached data
+    org-ref-label-cache))
+
+
+(defun org-ref-ref-jump-to (&optional path)
+  "Jump to the target for the ref link at point."
+  (interactive)
+  (let ((case-fold-search t)
+       (label (get-text-property (point) 'org-ref-ref-label))
+       (labels (split-string path ","))
+       (rx (string-join org-ref-ref-label-regexps "\\|")))
+    (when (null label)
+      (pcase (length labels)
+       (1
+        (setq label (cl-first labels)))
+       (_
+        (setq label (completing-read "Label: " labels)))))
+    (when label
+      (org-mark-ring-push)
+      (widen)
+      (goto-char (point-min))
+      (catch 'found
+       (while (re-search-forward rx)
+         (when (string= label (match-string-no-properties 1))
+           (save-match-data (org-mark-ring-push))
+           (goto-char (match-beginning 1))
+           (org-show-entry)
+           (substitute-command-keys
+            "Go back with (org-mark-ring-goto) \`\\[org-mark-ring-goto]'.")
+           (throw 'found t)))))))
+
+
+(defun org-ref-ref-help-echo (_win _obj position)
+  "Tooltip for context on a ref label.
+POSITION is the point under the mouse I think."
+  (cdr (assoc (get-text-property position 'org-ref-ref-label) (org-ref-get-labels))))
+
+
+(defun org-ref-ref-activate (start _end path _bracketp)
+  "Activate a ref link.
+The PATH should be a comma-separated list of labels.
+Argument START is the start of the link.
+Argument END is the end of the link."
+  (when org-ref-activate-ref-links
+    (let ((labels (mapcar 'car (org-ref-get-labels))))
+      (goto-char start)
+      (cl-loop for label in (split-string path ",") do
+              (search-forward label)
+              ;; store property so we can follow it later.
+              (put-text-property (match-beginning 0)
+                                 (match-end 0)
+                                 'org-ref-ref-label
+                                 label)
+
+              (unless (member label labels)
+                
+                (put-text-property (match-beginning 0)
+                                   (match-end 0)
+                                   'face
+                                   'font-lock-warning-face)
+                (put-text-property (match-beginning 0)
+                                   (match-end 0)
+                                   'help-echo
+                                   "Label not found"))))))
+
+
+(defun org-ref-ref-export (cmd keyword _desc backend)
+  "An export function for ref links.
+Argument CMD is the LaTeX command to export to.
+Argument KEYWORD is the path of the ref link.
+Argument BACKEND is the export backend.
+This is meant to be used with `apply-partially' in the link definitions."
+  (cond
+   ((eq backend 'latex)
+    (format "\\%s{%s}" cmd keyword))))
+
+
+(defun org-ref-complete-link (refstyle &optional _arg)
+  "Complete a ref link to an existing label."
+  (concat refstyle ":" (completing-read "Label: " (org-ref-get-labels))))
+
+
+(defun org-ref-store-ref-link (&optional reftype)
+  "Store a ref link to a label.  The output will be a ref to that label."
+  ;; First we have to make sure we are on a label link.
+  (unless reftype (setq reftype "ref"))
+  (let* ((object (and (eq major-mode 'org-mode) (org-element-context)))
+        (label (cond
+                ;; here literally on a label link.
+                ((and
+                  (equal (org-element-type object) 'link)
+                  (equal (org-element-property :type object) "label"))
+                 (org-element-property :path object))
+
+                ;; here on a file link. if it has a caption with a label in it, we store
+                ;; it.
+                ((and
+                  (equal (org-element-type object) 'link)
+                  (equal (org-element-property :type object) "file")
+                  (org-file-image-p (org-element-property :path object)))
+
+                 (if (org-element-property :name object)
+                     (org-element-property :name object)
+                   ;; maybe we have a caption to get it from.
+                   (let* ((parent (org-element-property :parent object)))
+                     (when (and parent
+                                (equal (org-element-type parent) 'paragraph))
+                       (if (org-element-property :name parent)
+                           ;; caption paragraph may have a name which we use if it is there
+                           (org-element-property :name parent)
+                         ;; else search caption
+                         (let ((caption (s-join
+                                         ""
+                                         (mapcar 'org-no-properties
+                                                 (org-export-get-caption parent))))) 
+                           (when (string-match org-ref-label-re caption)
+                             (match-string 1 caption))))))))
+
+                ;; here on a paragraph (eg in a caption of an image). it is a paragraph with a caption
+                ;; in a caption, with no name, but maybe a label
+                ((equal (org-element-type object) 'paragraph)
+                 (if (org-element-property :name object)
+                     (org-element-property :name object)
+
+                   ;; See if it is in the caption name
+                   (let ((caption (s-join "" (mapcar 'org-no-properties
+                                                     (org-export-get-caption object)))))
+                     (when (string-match org-ref-label-re caption)
+                       (match-string 1 caption)))))
+
+                ;; If you are in a table, we need to be at the beginning to
+                ;; make sure we get the name. Note when in a caption it appears
+                ;; you are in a table but org-at-table-p is nil there.
+                ((or (equal (org-element-type object) 'table) (org-at-table-p))
+                 (save-excursion
+                   (goto-char (org-table-begin))
+                   (let* ((table (org-element-context))
+                          (label (org-element-property :name table))
+                          (caption (s-join "" (mapcar 'org-no-properties
+                                                      (org-export-get-caption table)))))
+                     (when (null label)
+                       ;; maybe there is a label in the caption?
+                       (when (string-match org-ref-label-link-re caption)
+                         (match-string 1 caption))))))
+
+                ;; and to #+namel: lines
+                ((and (equal (org-element-type object) 'paragraph)
+                      (org-element-property :name object))
+                 (org-element-property :name object))
+
+                ;; in a latex environment
+                ((equal (org-element-type object) 'latex-environment)
+                 (let ((value (org-element-property :value object))
+                       label)
+                   (when (string-match "\\\\label{\\(?1:[+a-zA-Z0-9:\\._-]*\\)}" value)
+                     (match-string-no-properties 1 value))))
+
+                ;; Match targets, like <<label>>
+                ((equal (org-element-type object) 'target)
+                 (org-element-property :value object))
+
+                (t
+                 nil))))
+    
+    (when label
+      (org-link-store-props
+       :type reftype
+       :link (concat reftype ":" label)) 
+      t)))
+
+
+;; ** ref link
+
+(org-link-set-parameters "ref"
+                        :store (defun org-ref-store-ref () (org-ref-store-ref-link "ref"))
+                        :complete (apply-partially #'org-ref-complete-link "ref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "ref")
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+
+;;** pageref link
+
+(org-link-set-parameters "pageref"
+                        :store (defun org-ref-store-pageref () (org-ref-store-ref-link "pageref"))
+                        :complete (apply-partially #'org-ref-complete-link "pageref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "pageref")
+                        :face 'org-ref-ref-face
+                        :complete (lambda (&optional arg) (org-ref-complete-link arg "pageref"))
+                        :help-echo #'org-ref-ref-help-echo)
+
+
+;;** nameref link
+
+(org-link-set-parameters "nameref"
+                        :store (defun org-ref-store-nameref () (org-ref-store-ref-link "nameref"))
+                        :complete (apply-partially #'org-ref-complete-link "nameref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "nameref")
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+;;** eqref link
+
+(org-link-set-parameters "eqref"
+                        :store (defun org-ref-store-eqref () (org-ref-store-ref-link "eqref"))
+                        :complete (apply-partially #'org-ref-complete-link "eqref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "eqref")
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+;;** autoref link
+
+(org-link-set-parameters "autoref"
+                        :store (defun org-ref-store-autoref () (org-ref-store-ref-link "autoref"))
+                        :complete (apply-partially #'org-ref-complete-link "autoref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "autoref")
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+
+(org-link-set-parameters "Autoref"
+                        :store (defun org-ref-store-Autoref () (org-ref-store-ref-link "Autoref"))
+                        :complete (apply-partially #'org-ref-complete-link "Autoref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "Autoref")
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+;;** cref link
+;; for LaTeX cleveref package:
+;; https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref
+
+
+(org-link-set-parameters "cref"
+                        :store (defun org-ref-store-cref () (org-ref-store-ref-link "cref"))
+                        :complete (apply-partially #'org-ref-complete-link "cref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "cref")
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+
+(org-link-set-parameters "Cref"
+                        :store (defun org-ref-store-Cref () (org-ref-store-ref-link "Cref"))
+                        :complete (apply-partially #'org-ref-complete-link "Cref")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export (apply-partially #'org-ref-ref-export "Cref")
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+
+(defun org-ref-crefrange-export (path _desc backend)
+  (pcase backend
+    ('latex
+     (let ((labels (split-string path ",")))
+       (format "\\crefrange{%s}{%s}" (cl-first labels) (cl-second labels))))))
+
+
+(defun org-ref-Crefrange-export (path _desc backend)
+  (pcase backend
+    ('latex
+     (let ((labels (split-string path ",")))
+       (format "\\Crefrange{%s}{%s}" (cl-first labels) (cl-second labels))))))
+
+
+(defun org-ref-crefrange-complete (cmd &optional _arg)
+  "Completing function for the c/Crefrange links."
+  (concat cmd ":"
+         (completing-read "Label 1: " (org-ref-get-labels))
+         ","
+         (completing-read "Label 2: " (org-ref-get-labels))))
+
+
+(org-link-set-parameters "crefrange"
+                        :complete (apply-partially #'org-ref-crefrange-complete "crefrange")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export #'org-ref-crefrange-export
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+
+(org-link-set-parameters "Crefrange"
+                        :complete (apply-partially #'org-ref-crefrange-complete "Crefrange")
+                        :activate-func #'org-ref-ref-activate
+                        :follow #'org-ref-ref-jump-to
+                        :export #'org-ref-Crefrange-export
+                        :face 'org-ref-ref-face
+                        :help-echo #'org-ref-ref-help-echo)
+
+
+;; ** remove store functions
+(defun org-ref-ref-remove-store ()
+  "Remove the store functions from ref links.
+These tend to clobber the org store links. You can use C-u C-u
+C-c C-l to not use them, but if you prefer not to use them, this
+function removes the store functions from the links."
+  (interactive)
+  (cl-loop for reflink in '("ref" "pageref" "nameref" "eqref" "autoref" "Autoref"
+                           "cref" "Cref" "crefrange" "Crefrange")
+          do
+          (setf (cdr (assoc reflink org-link-parameters))
+                (org-plist-delete (cdr (assoc reflink org-link-parameters)) :store))))
+
+;; * Insert link
+(defvar org-ref-equation-environments
+  '("equation"
+    "equation*"
+    "align"
+    "align*"
+    "multline"
+    "multline*")
+  "LaTeX environments that should be treated as equations when referencing.")
+
+
+(defvar org-ref-ref-type-inference-alist
+  '((org-ref-equation-label-p . "eqref"))
+  "Alist of predicate functions taking a label name and the
+  desired reference type if the predicate returns true.")
+
+
+(defun org-ref-enclosing-environment (label)
+  "Returns the name of the innermost LaTeX environment containing
+the first instance of the label, or nil of there is none."
+  (or
+   (save-excursion
+     (save-restriction
+       (widen)
+       (goto-char (point-min))
+       (let ((label-point (search-forward (format "\\label{%s}" label) nil t)))
+        (when label-point
+           (catch 'return
+             (let (last-begin-point last-env)
+               (while (setq
+                       last-begin-point (re-search-backward "\\\\begin{\\([^}]+\\)}" nil t)
+                       last-env (match-string-no-properties 1))
+                (let ((env-end-point
+                       (search-forward (format "\\end{%s}" last-env) nil t)))
+                   (if (and env-end-point
+                            (> env-end-point label-point))
+                       (throw 'return last-env)
+                     (goto-char last-begin-point))))))))))
+   ;; Check latex-environments for names, and matching environment
+   (org-element-map (org-element-parse-buffer) 'latex-environment
+     (lambda (le)
+       (when (and (string= label (org-element-property :name le))
+                 (string-match
+                  (concat "begin{\\("
+                          (regexp-opt org-ref-equation-environments)
+                          "\\)}")
+                  (org-element-property :value le)))
+        (match-string 1 (org-element-property :value le))))
+     nil t)))
+
+
+(defun org-ref-equation-label-p (label)
+  "Return non-nil if LABEL is an equation label."
+  (let ((maybe-env (org-ref-enclosing-environment label)))
+    (when maybe-env
+      (member maybe-env org-ref-equation-environments))))
+
+
+(defun org-ref-infer-ref-type (label)
+  "Return inferred type for LABEL."
+  (or (cl-dolist (pred-pair org-ref-ref-type-inference-alist)
+       (when (funcall (car pred-pair) label)
+         (cl-return (eval (cdr pred-pair)))))
+      org-ref-default-ref-type))
+
+
+(defun org-ref-ref-link-p ()
+  "Return the link at point if point is on a ref link."
+  (let ((el (org-element-context)))
+    (and (eq (org-element-type el) 'link)
+        (assoc (org-element-property :type el) org-ref-ref-types)
+        el)))
+
+
+(defun org-ref-select-label ()
+  "Select a label in the buffer with annotated completion."
+  (let*  ((type-annotation (lambda (s)
+                            (let ((item (assoc s minibuffer-completion-table))) 
+                              (when item
+                                (with-temp-buffer
+                                  (insert "\n" (cdr item))
+                                  (indent-rigidly (point-min) (point-max) 20)
+                                  (buffer-string))))))
+         (completion-extra-properties `(:annotation-function ,type-annotation)))
+    (completing-read "Label: " (org-ref-get-labels))))
+
+
+(defun org-ref-insert-ref-link (&optional set-type)
+  "Insert a ref link.
+If on a link, append a label to the end.
+With a prefix arg SET-TYPE choose the ref type."
+  (interactive "P")
+  (let* ((minibuffer-setup-hook '(org-ref-minibuffer-prefix))
+        (label (org-ref-select-label)) 
+        (type (if (or set-type org-ref-prefix-arg)
+                  (org-ref-select-ref-type)
+                ;; in general, we prefer to infer the type, so that equations
+                ;; get a better default. However, if you customize
+                ;; `org-ref-default-ref-type', we use that instead. The most
+                ;; common use case for this is setting that variable to cref,
+                ;; which does its own automatic inference of the type.
+                (if (string= "ref" org-ref-default-ref-type)
+                    (org-ref-infer-ref-type label)
+                  org-ref-default-ref-type))))
+    (if-let* ((lnk (org-ref-ref-link-p))
+             (path (org-element-property :path lnk))
+             (beg (org-element-property :begin lnk))
+             (end (org-element-property :end lnk)))
+       (progn
+         (setf (plist-get (cadr lnk) :path) (concat path "," label))
+         (cl--set-buffer-substring beg end (org-element-interpret-data lnk)))
+
+      (insert (format  "%s:%s" type label)))
+    (goto-char (org-element-property :end (org-element-context)))))
+
+
+(provide 'org-ref-ref-links)
+
+;;; org-ref-ref-links.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-refproc.el b/elpa/org-ref-20230507.1420/org-ref-refproc.el
new file mode 100644 (file)
index 0000000..85e35f7
--- /dev/null
@@ -0,0 +1,467 @@
+;;; org-ref-refproc.el --- refproc - for exporting ref links in non-LaTeX backends -*- lexical-binding: t; -*-
+
+;; For autoref and cref* links, a clever prefix is added at export.
+;; Prefixes are found in `org-ref-refproc-clever-prefixes'
+;; Use a keyword like this to set the style of clever prefixes. You can use a full or abbreviated prefix
+;;
+;; #+refproc: :abbreviate t :capitalize t
+
+
+;;; Commentary:
+;;
+
+;;; Code:
+(require 'org-ref-ref-links)
+
+
+(defcustom org-ref-refproc-clever-prefixes
+  '((section :full "section" :abbrv "sec." :org-element headline)
+    (figure :full "figure" :abbrv "fig." :org-element link)
+    (table :full "table" :abbrv "tab." :org-element table)
+    (equation :full "equation" :abbrv "eq." :org-element latex-environment)
+    (proof :full "proof" :abbrv "pf." :org-element latex-environment)
+    (listing :full "listing" :abbrv "lst." :org-element src-block)
+    (lemma :full "lemma" :abbrv "lem." :org-element special-block)
+    (theorem :full "theorem" :abbrv "thm." :org-element special-block)
+    (corollary :full "corollary" :abbrv "cor." :org-element special-block))
+  "Prefixes for cleveref links.
+plist with :full and :abbrv forms for each type.
+:org-element is the element these are defined in."
+  :type 'sexp
+  :group 'org-ref)
+
+
+
+;; * refproc
+;;
+
+(defun org-ref-refproc-get-options ()
+  "Return a plist of options from a #+refproc keyword.
+Supported options are:
+:abbreviate (nil or non-nil)
+:capitalize (nil or non-nil)
+
+These options only affect the cref* links."
+  (read (format "(%s)" (cadr (assoc "REFPROC"
+                                   (org-collect-keywords
+                                    '("REFPROC")))))))
+
+
+(defun org-ref-get-ref-links ()
+  "Return a list of ref links in the buffer."
+  (org-element-map (org-element-parse-buffer) 'link
+    (lambda (lnk)
+      (when (assoc (org-element-property :type lnk) org-ref-ref-types)
+       lnk))))
+
+
+(defun org-ref-refproc-referenceables ()
+  "Return a list of referenceable items, grouped by type.
+This will be a list of (type label1 label2 ...).
+
+Not all styles of target are currently supported. This supports
+named tables, figures and src-blocks, headlines with a custom_id,
+and latex_environments with a latex label or name (these are all
+considered equations, which might be wrong for other
+environments)."
+  (let* ((parse-data (org-element-parse-buffer))
+        type el
+        ;; for each type, we specify what org-element to get the labels from.
+        (referencables (cl-loop for entry in org-ref-refproc-clever-prefixes
+                                do
+                                (setq type (car entry)
+                                      el (plist-get (cdr entry) :org-element))
+                                collect
+                                (cons type
+                                      (org-element-map parse-data el
+                                        (lambda (e)
+                                          (pcase el
+                                            ;; Headlines
+                                            ('headline
+                                             (cond
+                                              ;; There is a custom_id, we use it.
+                                              ((org-element-property :CUSTOM_ID e)
+                                               (org-element-property :CUSTOM_ID e))
+                                              ;; See if there is a target in the heading
+                                              ((string-match org-target-regexp
+                                                             (org-element-property :raw-value e))
+                                               (match-string 1 (org-element-property :raw-value e)))
+                                              ;; Check for a label link
+                                              ((string-match (concat "label:" org-ref-label-re)
+                                                             (org-element-property :raw-value e))
+                                               (match-string 1 (org-element-property :raw-value e)))))
+
+                                            ;;  Figures
+                                            ('link
+                                             (cond
+                                              ;; file link with a name property
+                                              ((and (org-file-image-p (org-element-property :path e))
+                                                    (org-element-property
+                                                     :name (org-element-property :parent e)))
+                                               (org-element-property
+                                                :name (org-element-property :parent e)))
+                                              ;; a label link in the caption
+                                              ((and  (org-file-image-p (org-element-property :path e))
+                                                     (org-element-property
+                                                      :caption (org-element-property :parent e))
+
+                                                     (string-match (concat "label:" org-ref-label-re)
+                                                                   (org-element-interpret-data
+                                                                    (org-element-property
+                                                                     :caption
+                                                                     (org-element-property :parent e)))))
+                                               (match-string 1 (org-element-interpret-data
+                                                                (org-element-property
+                                                                 :caption
+                                                                 (org-element-property :parent e)))))))
+
+                                            ;; Tables
+                                            ('table
+                                             (cond
+                                              ;; A name keyword is preferred
+                                              ((org-element-property :name e)
+                                               (org-element-property :name e))
+                                              ;; a label link in a caption also works
+                                              ((string-match (concat "label:" org-ref-label-re)
+                                                             (or (org-element-interpret-data
+                                                                  (org-element-property :caption e))
+                                                                 ""))
+                                               (match-string 1 (org-element-interpret-data
+                                                                (org-element-property :caption e))))))
+
+                                            ;; equations, proofs, and other latex environments
+                                            ('latex-environment
+                                             (when (or (and (eq type 'equation)
+                                                            (string-match "\\\\begin{equation}"
+                                                                          (org-element-property :value e)))
+                                                       (and (eq type 'proof) (string-match "\\\\begin{proof}"
+                                                                                           (org-element-property :value e))))
+
+                                               (cond
+                                                ;; Name keyword
+                                                ((org-element-property :name e)
+                                                 (org-element-property :name e))
+
+                                                ;; latex label in the value
+                                                ((string-match "\\\\label{\\(.*\\)}" (org-element-property :value e))
+                                                 (match-string 1 (org-element-property :value e))))))
+
+                                            ;; special blocks
+                                            ('special-block
+                                             (cond
+                                              ((and (eq type 'lemma)
+                                                    (org-element-property :name e)
+                                                    (string= "lemma" (org-element-property :type e)))
+                                               (org-element-property :name e))
+                                              
+                                              ((and (eq type 'corollary)
+                                                    (org-element-property :name e)
+                                                    (string= "corollary" (org-element-property :type e)))
+                                               (org-element-property :name e))
+
+                                              ((and (eq type 'theorem)
+                                                    (org-element-property :name e)
+                                                    (string= "theorem" (org-element-property :type e)))
+                                               (org-element-property :name e))))
+
+
+                                            ;; Listings of code blocks
+                                            ('src-block
+                                             (when-let (name (org-element-property :name e))
+                                               name)))))))))
+    referencables))
+
+
+(defun org-ref-refproc-get-type (label referenceables)
+  "Get the type of reference LABEL refers to.
+REFERENCEABLES comes from `org-ref-refproc-referenceables'.
+Returns a plist (:type type :label label :index index)"
+  (cl-loop for type in referenceables
+          if (member label type)
+          return (list :type (car  type) :label label :index (seq-position (cdr type) label 'equal))))
+
+
+(defun org-ref-refproc-group-sort-labels (lbls referenceables)
+  "Group and sort the labels in LBLS.
+REFERENCEABLES comes from `org-ref-refproc-referenceables'.
+Returns a list of (list (type l1 i1) (type l2, i2)...) where l1
+is label1, i1 is index1, etc.
+
+This data structure has all the references from a single link
+grouped by type. For some links there will only be one type, and
+one label, because that is all that is allowed, e.g. for ref,
+eqref, pageref, nameref and autoref.
+
+For the cref* links though you can have many labels, even to
+different kinds of things, and these are why we do the fancy
+grouping and sorting here."
+
+  (cl-loop for entry in
+          (seq-group-by (lambda (el)
+                          (plist-get el :type))
+                        (cl-loop for label in lbls collect
+                                 (org-ref-refproc-get-type label referenceables)))
+          collect
+          (sort (cdr entry) (lambda (a b)
+                              (< (plist-get a :index) (plist-get b :index))))))
+
+
+;; * Refproc - a reference processor for org-mode
+;;
+;; The strategy is to compute string replacements that are just org-syntax, then
+;; replace each link with the replacement.
+(defun org-ref-refproc-replacement (ref-link referenceables backend)
+  "Compute a replacement for REF-LINK (an org-element).
+REFERENCEABLES comes from `org-ref-refproc-referenceables'.
+BACKEND is the export backend."
+  (let* ((ref-type (org-element-property :type ref-link))
+        (labels (split-string (org-element-property :path ref-link) ","))
+        (post-blanks (org-element-property :post-blank ref-link))
+        (data (cl-loop for label in labels collect (org-ref-refproc-get-type label referenceables))))
+
+    (pcase ref-type
+      ;; These types only allow one label in the reference
+      ("ref"
+       (when (>  (length data) 1)
+        (error "A ref link can only have one label in it"))
+       (setq data (cl-first data))
+       (format "[[%s%s]]%s"
+              (if (eq 'section (plist-get data :type))
+                  "#"
+                "")
+              (plist-get data :label)
+              ;; add back post blank spaces.
+              (make-string post-blanks ? )))
+
+      ("eqref"
+       (when (>  (length data) 1)
+        (error "An eqref link can only have one label in it"))
+       (setq data (cl-first data))
+       (format (if (eq backend 'html)
+                  "[[%s]]%s"
+                "([[%s]])%s")
+              (plist-get data :label)
+              ;; add back post blank spaces.
+              (make-string post-blanks ? )))
+
+      ;; This one doesn't make much sense in unpaginated exports, and I don't
+      ;; have a way to get a page number anyway, so we make this a regular ref.
+      ("pageref"
+       (when (>  (length data) 1)
+        (error "A pageref link can only have one label in it"))
+       (setq data (cl-first data))
+       (format "[[%s%s]]%s"
+              (if (eq 'section (plist-get data :type))
+                  "#"
+                "")
+              (plist-get data :label)
+              ;; add back post blank spaces.
+              (make-string post-blanks ? )))
+
+      ;; this will use the heading name, or caption of the ref
+      ("nameref"
+       (when (>  (length data) 1)
+        (error "A nameref link can only have one label in it"))
+       (setq data (cl-first data))
+
+       ;; Basically I follow the link, and depending on the ref type get a
+       ;; "name" for it. Right now there is no error if there is not a heading
+       ;; or caption, you would just get an empty string.
+       (save-excursion
+        (goto-char (org-element-property :begin ref-link))
+        (search-forward ":")
+        (org-ref-ref-jump-to (org-element-property :path ref-link))
+        (pcase (plist-get data :type)
+          ('section
+           (org-previous-visible-heading 1)
+           (format "[[#%s][%s]]%s"
+                   (plist-get data :label)
+                   (cl-fifth (org-heading-components))
+                   (make-string post-blanks ? )))
+
+          ('table
+           (format "[[%s][%s]]%s"
+                   (plist-get data :label)
+                   (org-element-interpret-data (org-element-property :caption (org-element-context)))
+                   (make-string post-blanks ? )))
+
+          ('figure
+           (format "[[%s][%s]]%s"
+                   (plist-get data :label)
+                   (org-element-interpret-data (org-element-property :caption (org-element-context)))
+                   (make-string post-blanks ? )))
+
+          ('listing
+           (format "[[%s][%s]]%s"
+                   (plist-get data :label)
+                   (org-element-interpret-data (org-element-property :caption (org-element-context)))
+                   (make-string post-blanks ? )))
+          ;; does equation even make sense? is there ever a caption?
+          (_
+           (error "The nameref link is not implemented for %S" data)))))
+
+      ;; autoref is the first place we have to be clever.
+      ("autoref"
+       (when (>  (length data) 1)
+        (error "A pageref link can only have one label in it"))
+       (setq data (cl-first data))
+
+       (let* ((prefix-data (cdr (assoc (plist-get data :type) org-ref-refproc-clever-prefixes)))
+             (options (org-ref-refproc-get-options))
+             (prefix (plist-get prefix-data  (if (plist-get options :abbreviate)
+                                                 :abbrv
+                                               :full))))
+        (when (plist-get options :capitalize) (setq prefix (capitalize prefix)))
+        (format "%s [[%s%s]]%s"
+                prefix
+                (if (eq 'section (plist-get data :type))
+                    "#"
+                  "")
+                (plist-get data :label)
+                (make-string post-blanks ? ))))
+
+      ;; Now we get to the cref* links. These are complicated, so I will pass
+      ;; this out to dedicated functions. At this point, I have the ref-link,
+      ("cref"
+       (org-ref-refproc-cref-replacement ref-link referenceables nil))
+
+      ("Cref"
+       (org-ref-refproc-cref-replacement ref-link referenceables t))
+
+      (_
+       (error "%s links are not supported yet" ref-type)))))
+
+
+(defun org-ref-refproc-cref-replacement (ref-link referenceables capitalize)
+  "Calculate a replacement for a REF-LINK.
+
+REFERENCEABLES comes from `org-ref-refproc-referenceables'.
+
+If CAPITALIZE is non-nil, capitalize the first entry (this is for
+Cref) and is different than the capitalize option in #+refproc:
+which capitalizes each prefix."
+  (let* ((options (org-ref-refproc-get-options))
+        ;; I guess I know this will be cref or Cref here.
+        ;; (ref-type (org-element-property :type ref-link))
+        (labels (split-string (org-element-property :path ref-link) ","))
+        (post-blanks (org-element-property :post-blank ref-link))
+        (data (cl-loop for label in labels collect (org-ref-refproc-get-type label referenceables)))
+        (groups (seq-group-by (lambda (entry)
+                                (plist-get entry :type))
+                              data))
+        ;; this will be a list of sorted entries.
+        (sorted-groups (cl-loop for group in groups collect
+                                (sort (cdr group) (lambda (a b)
+                                                    (< (plist-get a :index) (plist-get b :index))))))
+        ;; temp vars
+        prefix
+        prefix-data
+        ;; Now we have to be clever on each sorted group. One day I should add compression to the groups, e.g. 1,2,3 - > 1 to 3
+        ;; For each group we need a prefix, and it may have to be a plural prefix.
+        ;; If there are two members of a group, they are joined by and
+        ;; if there are more than two members of a group, they are separated by commas with and at the end.
+        (replacements (cl-loop for collection in sorted-groups collect
+                               (pcase (length collection)
+                                 ;; One thing in the list
+                                 (1
+                                  (setq collection (cl-first collection)
+                                        prefix-data (cdr (assoc (plist-get collection :type) org-ref-refproc-clever-prefixes))
+                                        prefix (plist-get  prefix-data (if (plist-get options :abbreviate)
+                                                                           :abbrv
+                                                                         :full)))
+                                  (when (plist-get options :capitalize)
+                                    (setq prefix (capitalize prefix)))
+                                  (format "%s [[%s]]"
+                                          ;; prefix
+                                          prefix
+                                          (concat
+                                           (if (eq 'section (plist-get collection :type)) "#" "")
+                                           (plist-get collection :label))))
+                                 (2
+                                  ;; the prefix can be found from the first label, but we have to make it plural.
+                                  (setq prefix-data (cdr (assoc (plist-get (cl-first collection) :type)
+                                                                org-ref-refproc-clever-prefixes))
+                                        prefix (plist-get  prefix-data (if (plist-get options :abbreviate)
+                                                                           :abbrv
+                                                                         :full)))
+                                  (when (plist-get options :capitalize)
+                                    (setq prefix (capitalize prefix)))
+
+                                  ;; Make it plural (substring "fig." -1)
+                                  (setq prefix (if (string= "." (substring prefix -1))
+                                                   (concat (substring prefix 0 -1) "s.")
+                                                 (concat prefix "s")))
+
+                                  (format "%s [[%s]] and [[%s]]"
+                                          prefix
+                                          (concat
+                                           (if (eq 'section (plist-get (cl-first collection) :type)) "#" "")
+                                           (plist-get (cl-first collection) :label))
+                                          (concat
+                                           (if (eq 'section (plist-get (cl-second collection) :type)) "#" "")
+                                           (plist-get (cl-second collection) :label))))
+
+                                 (_
+                                  ;; the prefix can be found from the first label, but we have to make it plural.
+                                  (setq prefix-data (cdr (assoc (plist-get (cl-first collection) :type)
+                                                                org-ref-refproc-clever-prefixes))
+                                        prefix (plist-get  prefix-data (if (plist-get options :abbreviate)
+                                                                           :abbrv
+                                                                         :full)))
+                                  (when (plist-get options :capitalize)
+                                    (setq prefix (capitalize prefix)))
+
+                                  ;; Make it plural. If the prefix ends in .
+                                  ;; (i.e. it is abbreviated) we remove it and
+                                  ;; add s.
+                                  (setq prefix (if (string= "." (substring prefix -1))
+                                                   (concat (substring prefix 0 -1) "s.")
+                                                 (concat prefix "s")))
+
+                                  ;; now get
+                                  (format "%s %s and [[%s]]"
+                                          prefix
+                                          (string-join
+                                           (cl-loop for entry in (butlast collection) collect
+                                                    (format "[[%s]]"
+                                                            (concat
+                                                             (if (eq 'section (plist-get entry :type)) "#" "")
+                                                             (plist-get entry :label))))
+                                           ", ")
+                                          ;; the last one
+                                          (concat
+                                           (if (eq 'section (plist-get (car (last collection)) :type)) "#" "")
+                                           (plist-get (car (last collection)) :label))))))))
+
+
+    (when capitalize (setf (car replacements) (concat (capitalize (substring (car replacements) 0 1)) (substring (car replacements) 1))))
+
+    ;; Finally, join them together with commas, and add post-blank spaces.
+    (concat
+     (pcase (length replacements)
+       (1
+       (cl-first replacements))
+       (2
+       (concat (cl-first replacements) " and " (cl-second replacements)))
+       (_
+       (concat (string-join (butlast replacements) ", ") " and " (car (last replacements)))))
+
+     (make-string post-blanks ? ))))
+
+
+(defun org-ref-refproc (&optional backend)
+  "Process the buffer replacing all ref links with org syntax.
+BACKEND is the
+Meant to be used in an `org-export-before-parsing-hook' on a copy
+of the buffer."
+  (let ((ref-links (org-ref-get-ref-links))
+       (referenceables (org-ref-refproc-referenceables)))
+
+    (cl-loop for ref in (reverse ref-links) do
+            (cl--set-buffer-substring (org-element-property :begin ref)
+                                      (org-element-property :end ref)
+                                      (org-ref-refproc-replacement ref referenceables backend)))))
+
+(provide 'org-ref-refproc)
+
+;;; org-ref-refproc.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-sci-id.el b/elpa/org-ref-20230507.1420/org-ref-sci-id.el
new file mode 100644 (file)
index 0000000..7e304e9
--- /dev/null
@@ -0,0 +1,54 @@
+;;; org-ref-sci-id.el --- org-mode links for scientific IDs  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; New org-mode links for scientific IDs like orcid (http://orcid.org) and researcherid (http://www.researcherid.com)
+;; orcid:0000-0003-2625-9232
+;; researcherid:A-2363-2010
+
+;;; Code:
+
+(require 'org)
+(require 'org-ref-utils)
+
+(org-link-set-parameters "orcid"
+                        :follow (lambda
+                                  (link-string)
+                                  (browse-url
+                                   (format "http://orcid.org/%s" link-string)))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"http://orcid.org/%s\">orcid:%s</a>" keyword (or desc keyword))))))
+
+(org-link-set-parameters "researcherid"
+                        :follow (lambda
+                                  (link-string)
+                                  (browse-url
+                                   (format "http://www.researcherid.com/rid/%s" link-string)))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"http://www.researcherid.com/rid/%s\">ResearcherID:%s</a>"
+                                            keyword (or desc keyword))))))
+
+(provide 'org-ref-sci-id)
+;;; org-ref-sci-id.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-scifinder.el b/elpa/org-ref-20230507.1420/org-ref-scifinder.el
new file mode 100644 (file)
index 0000000..b0b2449
--- /dev/null
@@ -0,0 +1,35 @@
+;;; org-ref-scifinder.el --- Emacs interface to SciFinder
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; Hopefully this eventually integrates the Scifinder API into Emacs. For now,
+;; there is just one function that opens Scifinder for you.
+
+;;; Code:
+
+;;;###autoload
+(defun scifinder ()
+  "Open https://scifinder.cas.org/scifinder/view/scifinder/scifinderExplore.jsf in a browser."
+  (interactive)
+  (browse-url "https://scifinder.cas.org/scifinder/view/scifinder/scifinderExplore.jsf"))
+
+(provide 'org-ref-scifinder)
+
+;;; org-ref-scifinder.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-scopus.el b/elpa/org-ref-20230507.1420/org-ref-scopus.el
new file mode 100644 (file)
index 0000000..a0286d8
--- /dev/null
@@ -0,0 +1,222 @@
+;;; org-ref-scopus.el --- Emacs-lisp interface to the Scopus API  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;  See http://dev.elsevier.com/index.html for more information about the Scopus API
+;;
+;; New org-links:
+;; eid:2-s2.0-72649092395 with a hydra menu
+;; [[scopus-search:alloy Au segregation]]
+;; [[scopus-advanced-search:au-id(24176978500)]]
+
+;;; Code:
+
+(require 'org)
+(require 'hydra)
+(require 'xml)
+(require 'org-ref-utils)
+
+(defvar url-request-method)
+(defvar url-mime-accept-string)
+(defvar url-http-end-of-headers)
+(defvar url-request-extra-headers)
+
+(defvar *scopus-api-key* nil
+  "Your Scopus API key.
+You need to set this in your init files.  Get a key here:
+http://dev.elsevier.com/myapikey.html.")
+
+
+;; (defun scopus-doi-to-xml (doi)
+;;   "Return a parsed xml from the Scopus article retrieval api for DOI.
+;; This does not always seem to work for the most recent DOIs."
+;;   (let* ((url-request-method "GET")
+;;      (url-request-extra-headers  (list (cons "X-ELS-APIKey" *scopus-api-key*)))
+;;      (url (format  "http://api.elsevier.com/content/article/doi/%s" doi))
+;;      (xml))
+;;     (setq xml
+;;       (with-current-buffer  (url-retrieve-synchronously url)
+;;         (xml-parse-region url-http-end-of-headers (point-max))))
+;;     (if (eq 'service-error (caar xml))
+;;     (progn (message-box "%s\n%s\n%s" doi url xml)
+;;            nil)
+;;       xml)))
+
+(defun scopus-doi-to-eid (doi)
+  "Get a Scopus eid from a DOI.
+Requires `*scopus-api-key*' to be defined."
+  (unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
+  (let* ((url-request-method "GET")
+         (url-mime-accept-string "application/xml")
+         (url-request-extra-headers  (list (cons "X-ELS-APIKey" *scopus-api-key*)
+                                           '("field" . "eid")))
+         (url (format  "http://api.elsevier.com/content/search/scopus?query=doi(%s)" doi))
+         (xml (with-current-buffer  (url-retrieve-synchronously url)
+                (xml-parse-region url-http-end-of-headers (point-max))))
+         (results (car xml))
+         (entry (car (xml-get-children results 'entry))))
+    (car (xml-node-children (car (xml-get-children entry 'eid))))))
+
+
+;;;###autoload
+(defun scopus-related-by-keyword-url (doi)
+  "Return a Scopus url to articles related by keyword for DOI."
+  (interactive)
+  (unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
+  (let ((eid (scopus-doi-to-eid doi)))
+    (when eid (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=key&zone=relatedDocuments" eid))))
+
+
+;;;###autoload
+(defun scopus-related-by-author-url (doi)
+  "Return a Scopus url to articles related by author for DOI."
+  (interactive)
+  (unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
+  (let ((eid (scopus-doi-to-eid doi)))
+    (when eid (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=aut&zone=relatedDocuments" eid))))
+
+
+;;;###autoload
+(defun scopus-related-by-references-url (doi)
+  "Return a Scopus url to articles related by references for DOI."
+  (interactive)
+  (unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
+  (let ((eid (scopus-doi-to-eid doi)))
+    (when eid (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=ref&zone=relatedDocuments" eid))))
+
+
+(defun scopus-citing-url (doi)
+  "Return a Scopus url to articles citing DOI."
+  (format "http://www.scopus.com/results/citedbyresults.url?sort=plf-f&cite=%s&src=s&imp=t&sot=cite&sdt=a&sl=0&origin=recordpage" (scopus-doi-to-eid doi)))
+
+
+;;;###autoload
+(defun scopus-open-eid (eid)
+  "Open article with EID in browser."
+  (interactive "sEID: ")
+  (browse-url (format "http://www.scopus.com/record/display.url?eid=%s&origin=resultslist" eid)))
+
+
+(defun scopus ()
+  "Open http://scopus.com is a browser."
+  (browse-url "http://www.scopus.com"))
+
+
+;;;###autoload
+(defun scopus-basic-search (query)
+  "Open QUERY as a basic title-abstract-keyword search at scopus.com."
+  (interactive "sQuery: ")
+  (browse-url
+   (format
+    "http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=b&sdt=b&sl=%s&s=TITLE-ABS-KEY%%28%s%%29&origin=searchbasic"
+    (length (url-unhex-string (concat "TITLE-ABS-KEY%28" (url-hexify-string query) "%29")))
+    (url-hexify-string query))))
+
+
+;;;###autoload
+(defun scopus-advanced-search (query)
+  "Open QUERY as an advanced search at scopus.com."
+  (interactive "sQuery: ")
+  (browse-url
+   (format
+    "http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=a&sdt=a&sl=%s&s=%s&origin=searchadvanced"
+    (length query)
+    (url-hexify-string query))))
+
+
+;;; Org-mode EID link and an action menu
+;; These functions use a global var *hydra-eid*
+(defvar *hydra-eid* nil
+  "Global variable to pass an EID from an ‘org-mode’ link to a hydra function.")
+
+
+(defhydra scopus-hydra (:color blue)
+  ("o" (scopus-open-eid *hydra-eid*) "Open in Scopus")
+  ("a" (browse-url (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=aut&zone=relatedDocuments" *hydra-eid*))
+   "Related by author")
+  ("k" (browse-url (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=key&zone=relatedDocuments" *hydra-eid*))
+   "Related by keyword")
+  ("r" (browse-url (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=ref&zone=relatedDocuments" *hydra-eid*))
+   "Related by references")
+  ("c" (browse-url (format "http://www.scopus.com/results/citedbyresults.url?sort=plf-f&cite=%s&src=s&imp=t&sot=cite&sdt=a&sl=0&origin=recordpage" *hydra-eid*))
+   "Citing articles"))
+
+
+(org-link-set-parameters "eid"
+                        :follow (lambda (eid)
+                                  "Opens the hydra menu."
+                                  (setq *hydra-eid* eid)
+                                  (scopus-hydra/body))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\" http://www.scopus.com/record/display.url?eid=%s&origin=resultslist\">%s</a>" keyword (or desc keyword)))
+                                   ((eq format 'latex)
+                                    (format "\\href{http://www.scopus.com/record/display.url?eid=%s&origin=resultslist}{%s}"
+                                            keyword (or desc keyword))))))
+
+
+(org-link-set-parameters "scopus-search"
+                        :follow (lambda (query)
+                                  (scopus-basic-search query))
+                        :export (lambda (query desc format)
+                                  (let ((url (format
+                                              "http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=b&sdt=b&sl=%s&s=TITLE-ABS-KEY%%28%s%%29&origin=searchbasic"
+                                              (length (url-unhex-string (concat "TITLE-ABS-KEY%28" (url-hexify-string query) "%29")))
+                                              (url-hexify-string query))))
+                                    (cond
+                                     ((eq format 'html)
+                                      (format "<a href=\"%s\">%s</a>" url (or desc query)))
+                                     ((eq format 'latex)
+                                      (format "\\href{%s}{%s}" url (or desc query)))))))
+
+(org-link-set-parameters "scopus-advanced-search"
+                        :follow (lambda (query)
+                                  (scopus-advanced-search query))
+                        :export (lambda (query desc format)
+                                  (let ((url (format
+                                              "http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=a&sdt=a&sl=%s&s=%s&origin=searchadvanced"
+                                              (length (url-hexify-string query))
+                                              (url-hexify-string query))))
+                                    (cond
+                                     ((eq format 'html)
+                                      (format "<a href=\"%s\">%s</a>" url (or desc query)))
+                                     ((eq format 'latex)
+                                      (format "\\href{%s}{%s}" url (or desc query)))))))
+
+(org-link-set-parameters "scopusid"
+                        :follow (lambda
+                                  (link-string)
+                                  (browse-url
+                                   (format
+                                    "http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s"
+                                    link-string)))
+                        :export (lambda (keyword desc format)
+                                  (cond
+                                   ((eq format 'latex)
+                                    (format "\\href{http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s}{%s}"
+                                            keyword (or desc (concat "scopusid:" keyword))))
+                                   ((eq format 'html)
+                                    (format "<a href=\"http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s\">%s</a>"
+                                            keyword (or desc (concat "scopusid:" keyword)))))))
+
+
+(provide 'org-ref-scopus)
+;;; org-ref-scopus.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-url-utils.el b/elpa/org-ref-20230507.1420/org-ref-url-utils.el
new file mode 100644 (file)
index 0000000..fe3c87e
--- /dev/null
@@ -0,0 +1,310 @@
+;;; org-ref-url-utils.el --- Utility functions to scrape DOIs from urls  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Drag a webpage onto a bibtex file to insert a bibtex entry.
+;;
+;; [2021-08-29 Sun] I have not found drag-and-drop reliable or convenient. I
+;; don't recommend using this, but I am also not deleting it (yet).
+
+;; This works by scraping DOIs from the content at the URL using patterns in
+;; `org-ref-doi-regexps'. If one DOI is found, it is added as an entry. If
+;; multiple DOIs are found, you will get a selection buffer to choose what
+;; you want to add. You can add new patterns to `org-ref-doi-regexps'.
+
+;; You can press Control to "debug" a URL, which will open a buffer of the
+;; content with the current DOI patterns highlighted. If you want to get all the
+;; DOIs at a URL, you can press Meta during the drag-n-drop.
+
+;; You can also insert formatted bibtex entries using the
+;; `org-ref-url-html-to-bibtex' command, which converts a web page to
+;; bibtex or biblatex entry using URL. The org-cliplink package can
+;; help cleanup HTML code. Installing it is recommended.
+
+;;; Code:
+(defvar org-ref-bibliography-entry-format)
+(defvar org-ref-cite-types)
+(defvar org-cliplink-escape-alist)
+
+(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
+(declare-function 'org-ref-find-bibliography "org-ref-core.el")
+
+(declare-function dnd-handle-one-url "dnd")
+(declare-function dnd--unescape-uri "dnd")
+
+(require 'doi-utils)
+(require 'f)
+(require 's)
+(eval-when-compile
+  (require 'cl-lib))
+
+
+(defgroup org-ref-url nil
+  "Customization group for org-ref-url-utils"
+  :tag "Org Ref URL"
+  :group 'org-ref-url-utils)
+
+
+(defcustom org-ref-doi-regexps
+  '("scheme=\"doi\" content=\"\\([^\"]*\\)\""
+    "citation_doi\" content=\"\\([^\"]*\\)\""
+    "data-doi=\"\\([^\"]*\\)\""
+    "content=\"\\([^\"]*\\)\" name=\"citation_doi"
+    "objectDOI\" : \"\\([^\"]*\\)\""
+    "doi = '\\([^']*\\)'"
+    "\"http://dx.doi.org/\\([^\"]*\\)\""
+    "/doi/\\([^\"]*\\)\">"
+    "doi/full/\\(.*\\)&"
+    "doi=\\([^&]*\\)&amp")
+  "List of regexps to match a DOI.
+The doi should be in group 1 so that (match-string 1) contains
+the DOI."
+  :type '(repeat regexp)
+  :group 'org-ref-url-utils)
+
+
+(defvar org-ref-url-title-re
+  "<title.?+?>\\([[:ascii:][:nonascii:]]*?\\|.+\\)</title>"
+  "Regular expression for matching title.")
+
+
+(defvar org-ref-url-author-re
+  "<meta name=\"author\" content=\"\\(.+\\)\"\s?/?>"
+  "Regular expression for matching author.")
+
+
+(defvar org-ref-url-date-re
+  "<[a-z].+ class=\\(.?+date.[^>]*\\)>\\([[:ascii:][:nonascii:]]*?\\)</[a-z].+>"
+  "Regular expression for matching date.")
+
+
+(defvar org-ref-url-bibtex-template
+  "@misc{key,
+  title        = {${:title}},
+  author       = {${:author}},
+  howpublished = {${:url}},
+  year         = {${:year}},
+  note         = {Online; accessed ${:urldate}}
+}"
+  "BibTeX entry template for online sources.")
+
+(defvar org-ref-url-biblatex-template
+  "@online{key,
+title   = {${:title}},
+author  = {${:author}},
+url     = {${:url}}
+year    = {${:year}},
+urldate = {Online; accessed ${:urldate}}
+}"
+  "Biblatex entry template for online sources.")
+
+
+;;* Scrape DOIs from a URL
+
+(defun org-ref-url-scrape-dois (url)
+  "Scrape all dois from a URL matching a pattern in `org-ref-doi-regexps'.
+Returns a list of collected DOIs in the order found."
+  (let ((dois '()))
+    (with-current-buffer (url-retrieve-synchronously url)
+      (cl-loop for doi-pattern in org-ref-doi-regexps
+              do
+              (goto-char (point-min))
+              (while (re-search-forward doi-pattern nil t)
+                (cl-pushnew (match-string 1) dois :test #'equal)))
+      (reverse dois))))
+
+
+(defun org-ref-url-dnd-protocol (url action)
+  "Protocol function for use in `dnd-protocol-alist'.
+We scrape DOIs from the url first. If there is one, we add it. If
+there is more than one, we offer a completion buffer of selections. If
+no DOI is found, we create a misc entry, with a prompt for a key."
+  ;; make sure we are on a bib-file
+  (if (and (buffer-file-name)
+          (f-ext? (buffer-file-name) "bib"))
+      (let ((dois (org-ref-url-scrape-dois url)))
+       (cond
+        ;; One doi found. Assume it is what we want.
+        ((= 1 (length dois))
+         (doi-utils-add-bibtex-entry-from-doi
+          (car dois)
+          (buffer-file-name))
+         action)
+        ;; Multiple DOIs found
+        ((> (length dois) 1)
+         (let ((doi (completing-read "Select a DOI: " dois)))
+           (doi-utils-add-bibtex-entry-from-doi doi (buffer-file-name))))
+        ;; No DOIs found, add a misc entry.
+        (t
+          (org-ref-url-html-to-bibtex (buffer-file-name) url)
+         action)))
+    ;; pass back to dnd. Copied from `org-download-dnd'. Apparently
+    ;; returning nil does not do this.
+    (let ((dnd-protocol-alist
+          (rassq-delete-all
+           'org-ref-url-dnd-protocol
+           (copy-alist dnd-protocol-alist))))
+      (dnd-handle-one-url nil action url))))
+
+
+(add-to-list 'dnd-protocol-alist '("^https?" . org-ref-url-dnd-protocol))
+
+;;* Enable a DOI to be dragged onto a bibtex buffer
+(defun org-ref-doi-dnd-protocol (doi action)
+  "Protocol for when a doi is dragged onto a bibtex file.
+A doi will be either doi:10.xxx  or 10.xxx."
+  (if (and (buffer-file-name)
+          (f-ext? (buffer-file-name) "bib"))
+      (let ((doi (dnd--unescape-uri doi)))
+       ;; Get the actual doi now
+       (string-match "\\(?:DOI\\|doi\\)?:? *\\(10.*\\)" doi)
+       (setq doi (match-string 1 doi))
+       (when doi
+         (doi-add-bibtex-entry doi (buffer-file-name))
+         (save-buffer)
+         action))
+    ;; not on a bib file
+    (let ((dnd-protocol-alist
+          (rassq-delete-all
+           'org-ref-url-dnd-protocol
+           (copy-alist dnd-protocol-alist))))
+      (dnd-handle-one-url nil action doi))))
+
+(add-to-list 'dnd-protocol-alist '("^doi" . org-ref-doi-dnd-protocol))
+(add-to-list 'dnd-protocol-alist '("^10" . org-ref-doi-dnd-protocol))
+
+
+;;* Debugging DOIs from a URL
+
+;; You can use this to see if there are any DOIs in a URL, and to use re-builder
+;; to add new patterns to `org-ref-doi-regexps'.
+;;;###autoload
+(defun org-ref-url-debug-url (url)
+  "Open a buffer to URL with all doi patterns highlighted."
+  (interactive "sURL: ")
+  (switch-to-buffer
+   (url-retrieve-synchronously url))
+  (highlight-regexp
+   (mapconcat 'identity org-ref-doi-regexps "\\|")))
+
+
+;;* HTML to BibTeX functions
+
+(defun org-ref-url-html-replace (string)
+  "Replace HTML entities in STRING with their unicode equivalent."
+  (let (result
+       (case-fold-search nil))
+    (with-temp-buffer
+      (insert string)
+      (mapc (lambda (char)
+             (goto-char (point-min))
+             (while (re-search-forward (car char) nil t)
+               (replace-match (cdr char))))
+           org-cliplink-escape-alist)
+      (setq result (buffer-substring (point-min) (point-max))))
+    result))
+
+
+(defun org-ref-url-add-nil (list)
+  "Add nil to all missing keys in LIST."
+  (let (newlist)
+    (mapc (lambda (key)
+           (unless (alist-get key list)
+             (push (cons key "nil") newlist)))
+         (list :title :author :url :urldate :year))
+    (append list newlist)))
+
+
+(defun org-ref-url-html-read (url)
+  "Read URL content and return fields.
+Fields include author, title, url, urldate, and year."
+  ;; Start with fields we already know
+  (let ((fields `((:url . ,url)
+                 (:urldate . ,(format-time-string "%d %B %Y")))))
+    (with-current-buffer
+       (url-retrieve-synchronously url t t)
+
+      ;; find pubdate
+      (goto-char (point-min))
+      (when (re-search-forward org-ref-url-date-re nil t)
+       (let ((string (match-string 2)))
+         (when (string-match "\\([0-9]\\{4\\}\\)" string)
+           (push (cons :year (match-string 1 string)) fields))))
+
+      ;; find author
+      (goto-char (point-min))
+      (let ((author (if (re-search-forward org-ref-url-author-re nil t)
+                        (match-string 1)
+                      "Unknown")))
+        (push (cons :author author) fields))
+
+      ;; find title
+      (goto-char (point-min))
+      (when (re-search-forward org-ref-url-title-re nil t)
+       (push (cons :title
+                   (s-trim (decode-coding-string (match-string 1) 'utf-8)))
+             fields)))
+
+    ;; Finally add nil value to missing fields
+    (org-ref-url-add-nil fields)))
+
+
+;;;###autoload
+(defun org-ref-url-html-to-bibtex (bibfile &optional url)
+  "Convert URL to a bibtex or biblatex entry in BIBFILE.
+If URL is the first in the kill ring, use it. Otherwise, prompt for
+one in the minibuffer."
+  (interactive (if (-contains? (org-ref-find-bibliography) (buffer-file-name))
+                  (list (buffer-file-name))
+                (list (completing-read "Bibtex file: " (org-ref-find-bibliography)))))
+  (let ((url (if url url
+              (if (s-match "^http" (current-kill 0 'do-not-move))
+                  (format "%s" (current-kill 0 'do-not-move))
+                (read-from-minibuffer "URL: ")))))
+    (with-current-buffer
+       (find-file-noselect bibfile)
+      ;; Maybe check dialect if set as local variable
+      (let* ((dialect bibtex-dialect)
+            (alist (org-ref-url-html-read url))
+            (entry (s-format
+                    ;; Check dialect and format entry accordingly
+                    (if (eq dialect 'biblatex)
+                        org-ref-url-biblatex-template
+                      org-ref-url-bibtex-template)
+                    'aget alist)))
+       (goto-char (point-max))
+       ;; Place new entry one line after the last entry. Sometimes we are in a
+       ;; new file though, in which case we don't want to do this.
+       (unless (bobp)
+         (while (not (looking-back "^}\n" 2))
+           (delete-char -1)))
+       (insert "\n")
+       (insert (if (require 'org-cliplink nil 'noerror)
+                   ;; Sanitize values by replacing html entities
+                   (org-ref-url-html-replace entry)
+                 entry))
+       (insert "\n")
+       (bibtex-beginning-of-entry)
+       (org-ref-clean-bibtex-entry)
+       (save-buffer)))))
+
+(provide 'org-ref-url-utils)
+;;; org-ref-url-utils.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-utils.el b/elpa/org-ref-20230507.1420/org-ref-utils.el
new file mode 100644 (file)
index 0000000..0ac4ee3
--- /dev/null
@@ -0,0 +1,1262 @@
+;;; org-ref-utils.el --- Utility functions for org-ref  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016-2021  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+(eval-when-compile (require 'cl-lib))
+
+(require 'org)
+(eval-and-compile (require 'org-macs))
+
+
+(defvar org-ref-cite-types)
+(defvar pdftotext-executable)
+
+(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
+(declare-function 'org-ref-find-bibliography "org-ref-core.el")
+(declare-function 'org-ref-bib-citation "org-ref-core.el")
+(declare-function 'org-ref-get-bibtex-key-under-cursor "org-ref-core.el")
+
+;;; Code:
+;;;###autoload
+(defun org-ref-version ()
+  "Provide a version string for org-ref.
+Copies the string to the clipboard."
+  (interactive)
+  ;; version in the el file.
+  (let* ((org-ref-el (concat
+                     (file-name-sans-extension
+                      (locate-library "org-ref"))
+                     ".el"))
+        (org-ref-dir (file-name-directory org-ref-el))
+        org-version
+        git-commit
+        version-string)
+
+    (setq org-version (with-temp-buffer
+                       (insert-file-contents org-ref-el)
+                       (goto-char (point-min))
+                       (re-search-forward ";; Version:")
+                       (s-trim (buffer-substring (point)
+                                                 (line-end-position)))))
+
+    (setq git-commit
+         ;; If in git, get current commit
+         (let ((default-directory org-ref-dir))
+           (when (and
+                  ;; this is tricky, as a submodule, .git is a file
+                  (or (file-directory-p ".git") (file-exists-p ".git"))
+                  (= 0 (shell-command "git rev-parse --git-dir")))
+             (format "%s in %s"
+                     (s-trim (shell-command-to-string "git rev-parse HEAD"))
+                     (s-trim (shell-command-to-string "git rev-parse --show-toplevel"))))))
+
+    (setq version-string (format "org-ref: Version %s%s"
+                                org-version
+                                (if git-commit
+                                    (format " (git-commit %s)" git-commit)
+                                  "")))
+    (kill-new version-string)
+    (message version-string)))
+
+
+(defun org-ref-report-issue ()
+  "Report an issue in org-ref.
+Opens https://github.com/jkitchin/org-ref/issues/new."
+  (save-window-excursion
+    (org-ref-debug)
+    (kill-new (buffer-string)))
+  (message "org-ref-debug has been run. You can paste the results in the issue website if you like.")
+  (browse-url "https://github.com/jkitchin/org-ref/issues/new"))
+
+
+;;* Debug
+;; this is just for me to have a nicer debug statement.
+(defmacro ords (&rest body)
+  "Evaluate BODY and return a string."
+  `(format "%s" (progn ,@body)))
+
+
+;;;###autoload
+(defun org-ref-debug ()
+  "Print some debug information to a buffer."
+  (interactive)
+  (switch-to-buffer "*org-ref-debug*")
+  (erase-buffer)
+  (org-mode)
+  (insert
+   (s-format "#+TITLE: org-ref debug
+
+${org-ref-version}
+
+* System
+
+- system-type :: ${system}
+- system-configuration :: ${system-configuration}
+- window system :: ${window-system}
+- Emacs :: ${emacs-version}
+- org-version :: ${org-version}
+
+* about org-ref
+
+org-ref installed in [[${org-ref-location}]].
+
+* org-ref setup
+
+-  org-ref-insert-link-function :: ${org-ref-insert-link-function}
+-  org-ref-insert-cite-function :: ${org-ref-insert-cite-function}
+-  org-ref-insert-label-function :: ${org-ref-insert-label-function}
+-  org-ref-insert-ref-function :: ${org-ref-insert-ref-function}
+-  org-ref-cite-onclick-function :: ${org-ref-cite-onclick-function}
+
+* org-ref libraries
+
+** org-ref-helm (loaded: ${org-ref-helm-p})
+** org-ref-ivy  (loaded: ${org-ref-ivy-p})
+** org-ref-pdf (loaded: ${org-ref-pdf-p})
+
+- system pdftotext :: ${pdftotext}
+
+You set =pdftotext-executable= to ${pdftotext-executable} (exists: ${pdftotext-executable-p})
+
+** org-ref-url-utils (loaded: ${org-ref-url-p})
+
+* export variables
+
+- org-latex-pdf-process :: ${org-latex-pdf-process}
+"
+            'aget
+            `(("org-ref-version" . ,(org-ref-version))
+              ("org-latex-pdf-process" . ,(format "%S" org-latex-pdf-process))
+              ("org-ref-location" . ,(format "%s" (locate-library "org-ref")))
+
+              ("system" . ,(format "System: %s" system-type))
+              ("system-configuration" . ,(ords system-configuration))
+              ("window-system" . ,(format "Window system: %s" window-system))
+              ("emacs-version" . ,(ords (emacs-version)))
+              ("org-version" . ,(org-version))
+
+              ("org-ref-pdf-p" . ,(ords (featurep 'org-ref-pdf)))
+              ("org-ref-helm-p" . ,(ords (featurep 'org-ref-helm)))
+              ("org-ref-ivy-p" . ,(ords (featurep 'org-ref-ivy)))
+
+              ("pdftotext" . ,(ords (if (featurep 'org-ref-pdf)
+                                        (executable-find "pdftotext")
+                                      "org-ref-pdf not loaded")))
+              ("pdftotext-executable" . ,(ords (if (featurep 'org-ref-pdf)
+                                                   pdftotext-executable
+                                                 "org-ref-pdf not loaded")))
+              ("pdftotext-executable-p" . ,(ords (if (boundp 'pdftotext-executable)
+                                                     (or
+                                                      (executable-find pdftotext-executable)
+                                                      (file-exists-p pdftotext-executable))
+                                                   "pdftotext-executable is not bound")))
+              ("org-ref-url-p" . ,(ords (featurep 'org-ref-url)))
+              ("org-ref-insert-link-function" . ,org-ref-insert-link-function)
+              ("org-ref-insert-cite-function" . ,org-ref-insert-cite-function)
+              ("org-ref-insert-label-function" . ,org-ref-insert-label-function)
+              ("org-ref-insert-ref-function" . ,org-ref-insert-ref-function)
+              ("org-ref-cite-onclick-function" . ,org-ref-cite-onclick-function)))))
+
+
+(defun org-ref-get-bibtex-entry-citation (key)
+  "Return a string for the bibliography entry corresponding to KEY."
+  (bibtex-completion-apa-format-reference key))
+
+
+(defun org-ref-get-bibtex-entry (key)
+  "Return the bibtex entry as a string."
+  (save-window-excursion
+    (bibtex-completion-show-entry (list key))
+    (bibtex-copy-entry-as-kill)
+    (pop bibtex-entry-kill-ring)))
+
+(defun org-ref-library-path ()
+  "return the library path"
+  (cond
+   ((stringp bibtex-completion-library-path)
+    bibtex-completion-library-path)
+   ((and (listp bibtex-completion-library-path)
+        (= 1 (length bibtex-completion-library-path)))
+    (car bibtex-completion-library-path))
+   (t
+    (completing-read "Dir: " bibtex-completion-library-path))))
+
+;;*** key at point functions
+(defun org-ref-get-pdf-filename (key)
+  "Return the pdf filename associated with a bibtex KEY.
+This searches for the pattern KEY*.pdf. If one result is found it
+is returned, but if multiple results are found, e.g. there are
+related files to the KEY you are prompted for which one you want."
+  (let ((results (bibtex-completion-find-pdf-in-library key)))
+    (cond
+     ((null results)
+      nil)
+     ((= 1 (length results))
+      (car results))
+     (t
+      (completing-read "PDF: " results)))))
+
+;; TODO: do we even need this?
+(defun org-ref-get-mendeley-filename (key)
+  "Return the pdf filename indicated by mendeley file field.
+Falls back to `org-ref-get-pdf-filename' if file field does not exist.
+Contributed by https://github.com/autosquid.
+Argument KEY is the bibtex key."
+  (let* ((results (org-ref-get-bibtex-key-and-file key))
+         (bibfile (cdr results)))
+    (with-temp-buffer
+      (insert-file-contents bibfile)
+      (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+      (bibtex-search-entry key nil 0)
+      (let ((e (bibtex-autokey-get-field "file")))
+       (if (> (length e) 4)
+            (let ((clean-field (replace-regexp-in-string "{\\|}\\|\\\\" "" e)))
+              (let ((first-file (car (split-string clean-field ";" t))))
+               (format "/%s" (substring first-file 1
+                                        (- (length first-file) 4)))))
+          (expand-file-name (format "%s.pdf" key) (cond
+                                                  ((stringp bibtex-completion-library-path)
+                                                   bibtex-completion-library-path)
+                                                  ((= 1 (length bibtex-completion-library-path))
+                                                   (car bibtex-completion-library-path))
+                                                  (t
+                                                   (completing-read "PDF dir: " bibtex-completion-library-path)))))))))
+
+
+(defun org-ref-get-pdf-filename-bibtex-completion (key)
+  "Use bibtex-completion to retrieve a PDF filename for KEY.
+bibtex-completion looks in both the configured directory
+`bibtex-completion-library-path' and in the fields of the bibtex
+item for a filename. It understands file fields exported by
+Jabref, Mendeley and Zotero. See `bibtex-completion-find-pdf'."
+  (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
+    (or (car (bibtex-completion-find-pdf key)) "")))
+
+
+;;;###autoload
+(defun org-ref-open-pdf-at-point ()
+  "Open the pdf for bibtex key under point if it exists."
+  (interactive)
+  (let* ((bibtex-completion-bibliography (org-ref-find-bibliography))
+        (results (org-ref-get-bibtex-key-and-file))
+         (key (car results))
+         (pdf-file (bibtex-completion-find-pdf key t)))
+    (pcase (length pdf-file)
+      (0
+       (message "no pdf found for %s" key))
+      (1
+       (funcall bibtex-completion-pdf-open-function (car pdf-file)))
+      (_
+       (funcall bibtex-completion-pdf-open-function
+               (completing-read "pdf: " pdf-file))))))
+
+
+;;;###autoload
+(defun org-ref-add-pdf-at-point (&optional prefix)
+  "Add the pdf for bibtex key under point if it exists.
+
+Similar to org-ref-bibtex-assoc-pdf-with-entry prompt for pdf
+associated with bibtex key at point and rename it.  Check whether a
+pdf already exists in `bibtex-completion-library' with the name
+'[bibtexkey].pdf'. If the file does not exist, rename it to
+'[bibtexkey].pdf' using
+`org-ref-bibtex-assoc-pdf-with-entry-move-function' and place it
+in a directory. Optional PREFIX argument toggles between
+`rename-file' and `copy-file'."
+
+  (interactive)
+  (let* ((bibtex-completion-bibliography (org-ref-find-bibliography))
+        (results (org-ref-get-bibtex-key-and-file))
+         (key (car results))
+         (pdf-file (bibtex-completion-find-pdf-in-library key)))
+    (if pdf-file
+        (message "PDF for key [%s] already exists %s" key pdf-file)
+      (let* (
+             (source-file-name (read-file-name (format "Select pdf file associated with key [%s]: " key)
+                                  org-ref-bibtex-pdf-download-dir))
+             (dest-file-name (expand-file-name (format "%s.pdf" key) (org-ref-library-path)))
+             (file-move-func (org-ref-bibtex-get-file-move-func prefix))
+             )
+        (progn
+          (funcall file-move-func source-file-name dest-file-name)
+          (message "added file %s to key %s" dest-file-name))))))
+
+;;;###autoload
+(defun org-ref-open-url-at-point ()
+  "Open the url for bibtex key under point."
+  (interactive)
+  (let* ((bibtex-completion-bibliography (org-ref-find-bibliography))
+        (results (org-ref-get-bibtex-key-and-file))
+         (key (car results))
+         (bibfile (cdr results)))
+    (save-excursion
+      (with-temp-buffer
+        (insert-file-contents bibfile)
+        (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+        (bibtex-search-entry key)
+        ;; I like this better than bibtex-url which does not always find
+        ;; the urls
+        (catch 'done
+          (let ((url (s-trim (bibtex-autokey-get-field "url"))))
+            (unless (s-blank? url)
+              (browse-url url)
+              (throw 'done nil)))
+
+          (let ((doi (s-trim (bibtex-autokey-get-field "doi"))))
+            (unless (s-blank? doi)
+              (if (string-match "^http" doi)
+                  (browse-url doi)
+                (browse-url (format "http://dx.doi.org/%s" doi)))
+              (throw 'done nil))))))))
+
+
+;;;###autoload
+(defun org-ref-open-notes-at-point (&optional thekey)
+  "Open the notes for bibtex key under point in a cite link in a buffer.
+Can also be called with THEKEY in a program."
+  (interactive)
+  (org-mark-ring-push)
+  (when (null thekey)
+    (setq thekey (org-ref-get-bibtex-key-under-cursor)))
+  (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
+    (bibtex-completion-edit-notes (list thekey))))
+
+
+;;;###autoload
+(defun org-ref-open-citation-at-point ()
+  "Open bibtex file to key at point."
+  (interactive)
+  (org-mark-ring-push)
+  (let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
+    (bibtex-completion-show-entry (list (org-ref-get-bibtex-key-under-cursor)))))
+
+
+;;*** cite menu
+
+;;;###autoload
+(defun org-ref-copy-entry-as-summary ()
+  "Copy the bibtex entry for the citation at point as a summary."
+  (interactive)
+  (kill-new (org-ref-bib-citation)))
+
+
+(defun org-ref-get-doi-at-point ()
+  "Get doi for key at point."
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+         (key (car results))
+         (bibfile (cdr results))
+         doi)
+    (save-excursion
+      (with-temp-buffer
+        (insert-file-contents bibfile)
+        (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+        (bibtex-search-entry key)
+        (setq doi (bibtex-autokey-get-field "doi"))
+        ;; in case doi is a url, remove the url part.
+        (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))))
+
+
+;;**** functions that operate on key at point for click menu
+
+;;;###autoload
+(defun org-ref-ads-at-point ()
+  "Open the doi in ADS for bibtex key under point."
+  (interactive)
+  (doi-utils-ads (org-ref-get-doi-at-point)))
+
+
+;;;###autoload
+(defun org-ref-wos-at-point ()
+  "Open the doi in wos for bibtex key under point."
+  (interactive)
+  (doi-utils-wos (org-ref-get-doi-at-point)))
+
+
+;;;###autoload
+(defun org-ref-wos-citing-at-point ()
+  "Open the doi in wos citing articles for bibtex key under point."
+  (interactive)
+  (doi-utils-wos-citing (org-ref-get-doi-at-point)))
+
+
+;;;###autoload
+(defun org-ref-wos-related-at-point ()
+  "Open the doi in wos related articles for bibtex key under point."
+  (interactive)
+  (doi-utils-wos-related (org-ref-get-doi-at-point)))
+
+
+;;;###autoload
+(defun org-ref-google-scholar-at-point ()
+  "Search google scholar for bibtex key under point using the title."
+  (interactive)
+  (browse-url
+   (url-encode-url
+    (format
+     "http://scholar.google.com/scholar?q=%s"
+     (bibtex-completion-get-value
+      "title"
+      (bibtex-completion-get-entry (org-ref-get-bibtex-key-under-cursor)))))))
+
+
+;;;###autoload
+(defun org-ref-biblio-at-point ()
+  "Do a biblio search for bibtex key under point using the title."
+  (interactive)
+  (biblio-lookup
+   nil
+   (bibtex-completion-get-value
+    "title"
+    (bibtex-completion-get-entry (org-ref-get-bibtex-key-under-cursor)))))
+
+
+;;;###autoload
+(defun org-ref-pubmed-at-point ()
+  "Open the doi in pubmed for bibtex key under point."
+  (interactive)
+  (doi-utils-pubmed (org-ref-get-doi-at-point)))
+
+
+;;;###autoload
+(defun org-ref-crossref-at-point ()
+  "Open the doi in crossref for bibtex key under point."
+  (interactive)
+  (doi-utils-crossref (org-ref-get-doi-at-point)))
+
+
+;;;###autoload
+(defun org-ref-email-at-point ()
+  "Email the citation(s) at point."
+  (interactive)
+  (let* ((cite (org-element-context))
+        (keys ()))
+    (compose-mail)
+    (message-goto-body)
+    (cl-loop for ref in (plist-get
+                        (org-ref-parse-cite-path (org-element-property :path cite))
+                        :references)
+            do
+            (let* ((key (plist-get ref :key))
+                   (entry (save-window-excursion
+                            (bibtex-completion-show-entry (list key))
+                            (bibtex-copy-entry-as-kill)
+                            (pop bibtex-entry-kill-ring)))
+                   (pdfs (bibtex-completion-find-pdf key)))
+              (setq keys (append keys (list key)))
+              (insert entry)
+              (cl-loop for pdf in pdfs do (mml-attach-file pdf))))
+
+    (message-goto-subject)
+    (insert "References: " (string-join keys ","))))
+
+
+;;* General org-ref utilities
+
+
+(defun org-ref-get-bibtex-keys (&optional sort)
+  "Return a list of unique keys in the buffer.
+Use SORT to specify alphabetical order by key."
+  (let ((keys '()))
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (link)
+        (let ((plist (nth 1 link)))
+          (when (assoc (plist-get plist ':type) org-ref-cite-types)
+           (setq keys (append keys (cl-loop for ref in
+                                            (plist-get (org-ref-parse-cite-path
+                                                        (org-element-property :path link))
+                                                       :references)
+                                            collect (plist-get ref :key)))))))
+      ;; set with-affiliated to get keys in captions
+      nil nil nil t)
+    (when sort
+      ;; Sort keys alphabetically
+      (setq keys (cl-sort keys 'string-lessp :key 'downcase)))
+    (delete-dups keys)))
+
+
+(defun org-ref-pdf-p (filename)
+  "Check if FILENAME is PDF file.
+
+From the PDF specification 1.7:
+
+    The first line of a PDF file shall be a header consisting of
+    the 5 characters %PDF- followed by a version number of the
+    form 1.N, where N is a digit between 0 and 7."
+  (let* ((header (with-temp-buffer
+                  (set-buffer-multibyte nil)
+                  (insert-file-contents-literally filename nil 0 5)
+                  (buffer-string)))
+        (valid (string-equal (encode-coding-string header 'utf-8) "%PDF-")))
+    (if valid
+       valid
+      (message "Invalid pdf. Header = %s" header)
+      nil)))
+
+
+
+
+;; This section creates some code that should speed up org-ref for large files.
+;; I use org-element-parse-buffer a lot for getting information about labels
+;; etc. However, it gets called a lot, and this is slow in large documents. Here
+;; we try to use a cache that helps speed this up at least on loading. Some
+;; notes for the future: on loading, it seems like fontification triggers buffer
+;; changes, so here we only consider char changes. I am not sure this is the
+;; best strategy overall. It is faster to use regexps for finding this
+;; information, but those are substantially more difficult to debug in my
+;; experience. There is an unfortunate number of ways to reference things in
+;; org-mode, and so far this has been most reliable. An alternative might be to
+;; leveralge what happens in font-lock somehow to update local variables
+;; containing org-ref labels, refs, cites, etc. That would miss some #+names
+;; though, and maybe some other things like custom-ids.
+
+(defvar-local org-ref-char-change-tick nil
+  "Local variable to track character changes.")
+
+
+(defvar-local org-ref-parse-buffer-cache nil
+  "Local variable to store parse buffer data.")
+
+
+(defun org-ref-parse-buffer (&optional force)
+  "This is a thin wrapper around `org-element-parse-buffer'.
+The idea is to cache the data, and return it unless we can tell
+the buffer has been modified since the last time we ran it.
+if FORCE is non-nil reparse the buffer no matter what."
+  (if force
+      (progn
+       (message "Forcing update.")
+       (setq-local org-ref-char-change-tick (buffer-chars-modified-tick))
+       (setq-local org-ref-parse-buffer-cache (org-element-parse-buffer)))
+
+    (cond
+     ((null org-ref-parse-buffer-cache)
+      ;; (message "First parse.")
+      (setq-local org-ref-char-change-tick (buffer-chars-modified-tick))
+      (setq-local org-ref-parse-buffer-cache (org-element-parse-buffer)))
+
+     ((not (eq org-ref-char-change-tick (buffer-chars-modified-tick)))
+      ;; (message "Updating from a char change in the buffer.")
+      (setq-local org-ref-char-change-tick (buffer-chars-modified-tick))
+      (setq-local org-ref-parse-buffer-cache (org-element-parse-buffer)))
+
+     (t
+      ;; (message "Using cache.")
+      org-ref-parse-buffer-cache))))
+
+
+
+;;** bad citations, labels, refs and files in orgfile
+;;  These are used i
+(defvar bibtex-files)
+(defvar bibtex-file-path)
+(defun org-ref-bad-cite-candidates ()
+  "Return a list of conses (key . marker) where key does not exist in the known bibliography files, and marker points to the key."
+  (let* ((cp (point))                  ; save to return to later
+         (bibtex-files (cl-loop for f in (org-ref-find-bibliography)
+                               if (file-exists-p f)
+                               collect (file-truename f)))
+         (bibtex-file-path (mapconcat
+                            (lambda (x)
+                              (file-name-directory (file-truename x)))
+                            bibtex-files ":"))
+         (bibtex-keys (mapcar (lambda (x) (car x))
+                              (bibtex-global-key-alist)))
+         (bad-citations '()))
+
+    (org-element-map (org-ref-parse-buffer) 'link
+      (lambda (link)
+        (let ((plist (nth 1 link)))
+          (when (assoc (plist-get plist :type) org-ref-cite-types)
+           (when (not (string= "*" (plist-get plist :path)))
+             (cl-loop for ref in (plist-get (org-ref-parse-cite-path (plist-get plist :path)) :references)
+                      do
+                      (when (not (member (plist-get ref :key) bibtex-keys))
+                        (goto-char (plist-get plist :begin))
+                        (re-search-forward (plist-get ref :key))
+                        (push (cons (plist-get ref :key) (point-marker)) bad-citations)))))))
+      ;; add with-affiliates to get cites in caption
+      nil nil nil t)
+    (goto-char cp)
+    bad-citations))
+
+
+(defun org-ref-bad-ref-candidates ()
+  "Return a list of conses (ref . marker) where ref is a ref link that does not point to anything (i.e. a label)."
+  ;; first get a list of legitimate labels
+  (let ((cp (point))
+        (labels (mapcar 'car (org-ref-get-labels)))
+        (bad-refs '()))
+    ;; now loop over ref links
+    (goto-char (point-min))
+    (org-element-map (org-ref-parse-buffer) 'link
+      (lambda (link)
+        (let ((plist (nth 1 link)))
+         (when (assoc (plist-get plist ':type)  org-ref-ref-types)
+           (cl-loop for label in (split-string (plist-get plist :path) ",")
+                    do
+                    (unless (-contains? labels label)
+                      (goto-char (plist-get plist :begin))
+                      (add-to-list
+                       'bad-refs
+                       (cons label (point-marker)))))))))
+    (goto-char cp)
+    bad-refs))
+
+
+(defun org-ref-count-labels (label)
+  "Return the number of times LABEL appears in the buffer."
+  (let ((rx (string-join org-ref-ref-label-regexps "\\|"))
+       (labels '()))
+    (save-excursion
+      (org-with-wide-buffer
+       (goto-char (point-min))
+       (while (re-search-forward rx nil t)
+        (cl-pushnew (match-string-no-properties 1) labels))))
+    (-count (lambda (x) (and (stringp x) (string= x label))) labels)))
+
+
+(defun org-ref-bad-label-candidates ()
+  "Return a list of labels where label is multiply defined."
+  (let ((labels (mapcar 'car (org-ref-get-labels)))
+        (multiple-labels '()))
+    ;; labels should be a unique list.
+    (dolist (label labels)
+      (when (> (org-ref-count-labels label) 1)
+       (let ((cp (point)))
+          (goto-char (point-min))
+         ;; regular org label:tag links
+          (while (re-search-forward
+                  (format  "[^#+]label:%s\\s-" label) nil t)
+            (cl-pushnew (cons label (point-marker)) multiple-labels
+                       :test (lambda (a b)
+                               (and (string= (car a) (car b))
+                                    (= (marker-position (cdr a))
+                                       (marker-position (cdr b)))))))
+
+          (goto-char (point-min))
+         ;; latex style
+          (while (re-search-forward
+                  (format  "\\label{%s}\\s-?" label) nil t)
+            (cl-pushnew (cons label (point-marker)) multiple-labels
+                       :test (lambda (a b)
+                               (and (string= (car a) (car b))
+                                    (= (marker-position (cdr a))
+                                       (marker-position (cdr b)))))))
+
+         ;; keyword style
+          (goto-char (point-min))
+          (while (re-search-forward
+                  (format  "^\\( \\)*#\\+label:\\s-*%s" label) nil t)
+            (cl-pushnew (cons label (point-marker)) multiple-labels
+                       :test (lambda (a b)
+                               (and (string= (car a) (car b))
+                                    (= (marker-position (cdr a))
+                                       (marker-position (cdr b)))))))
+
+          (goto-char (point-min))
+          (while (re-search-forward
+                  (format "^\\( \\)*#\\+tblname:\\s-*%s" label) nil t)
+            (cl-pushnew (cons label (point-marker)) multiple-labels
+                       :test (lambda (a b)
+                               (and (string= (car a) (car b))
+                                    (= (marker-position (cdr a))
+                                       (marker-position (cdr b)))))))
+          (goto-char cp))))
+    multiple-labels))
+
+
+(defun org-ref-bad-file-link-candidates ()
+  "Return list of conses (link . marker) where the file in the link does not exist."
+  (let* ((bad-files '()))
+    (org-element-map (org-ref-parse-buffer) 'link
+      (lambda (link)
+        (let ((type (org-element-property :type link)))
+          (when (or  (string= "file" type)
+                     (string= "attachfile" type))
+            (unless (file-exists-p (org-element-property :path link))
+              (add-to-list 'bad-files
+                           (cons (org-element-property :path link)
+                                 (save-excursion
+                                   (goto-char
+                                    (org-element-property :begin link))
+                                   (point-marker)))))))))
+    ;; Let us also check \attachfile{fname}
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward "\\\\attachfile{\\([^}]*\\)}" nil t)
+        (unless (file-exists-p (match-string 1))
+          (push  (cons (match-string 1) (point-marker)) bad-files))))
+    bad-files))
+
+
+;; * org-ref command
+(defun org-ref ()
+  "Check the current org-buffer for potential issues."
+  (interactive)
+  (let* ((buf (get-buffer-create "*org-ref*"))
+        (cb (current-buffer))
+        (fname (buffer-file-name))
+        ;; Check if elc is ok before anything else because if it is not, it
+        ;; causes problems in org-ref.
+        (elc-ok (let* ((org-ref-el (concat
+                                    (file-name-sans-extension
+                                     (locate-library "org-ref"))
+                                    ".el"))
+                       (orel-mod)
+                       (org-ref-elc (concat
+                                     (file-name-sans-extension
+                                      (locate-library "org-ref"))
+                                     ".elc"))
+                       (orelc-mod)
+                       (elc-version))
+                  (when (file-exists-p org-ref-el)
+                    (setq orel-mod (file-attribute-modification-time (file-attributes org-ref-el))))
+                  (when (file-exists-p org-ref-elc)
+                    (setq orelc-mod (file-attribute-modification-time (file-attributes org-ref-elc))))
+
+                  (with-current-buffer buf
+                    (read-only-mode -1)
+                    (erase-buffer)
+                    (org-mode)
+                    (insert (format "#+title: org-ref report on [[%s][%s]]\n\n" (buffer-file-name cb) (buffer-name cb)))
+                    (insert (format "org-ref called from %s\n\n" (buffer-file-name cb)))
+
+                    (unless (time-less-p orel-mod orelc-mod)
+                      (insert (format "org-ref.elc (%s) is older than org-ref.el (%s). That is probably not right. Please delete %s.\n"
+                                      (format-time-string "%Y-%m-%d %H:%M:%S" orelc-mod)
+                                      (format-time-string "%Y-%m-%d %H:%M:%S" orel-mod)
+                                      org-ref-elc))
+                      (insert (format "- load-prefer-newer = %s\n" load-prefer-newer))
+                      (insert (format  "  consider
+- deleting %s
+- [[elisp:(delete-file \"%s\")]]
+- add (setq load-prefer-newer t) to your init files
+- using https://github.com/emacscollective/auto-compile.\n" org-ref-elc org-ref-elc))
+
+                      ;; Check for byte-compiling compatibility with current emacs
+                      (when (and org-ref-elc
+                                 (file-exists-p org-ref-elc))
+                        (setq elc-version (with-temp-buffer
+                                            (insert-file-contents org-ref-elc)
+                                            (goto-char (point-min))
+                                            (when (re-search-forward ";;; in Emacs version \\([0-9]\\{2\\}\\.[0-9]+\\)"
+                                                                     nil t)
+                                              (match-string 1))))
+                        (unless (string= elc-version
+                                         (format "%s.%s" emacs-major-version emacs-minor-version))
+                          (insert (format "%s compiled with Emacs %s but you are running %s. That could be a problem.\n"
+                                          elc-version emacs-major-version emacs-minor-version))))))))
+        (bad-citations (org-ref-bad-cite-candidates))
+        (bad-refs (org-ref-bad-ref-candidates))
+        (bad-labels (org-ref-bad-label-candidates))
+        (bad-files (org-ref-bad-file-link-candidates))
+        (bib-candidates '())
+        (unreferenced-labels '())
+        natbib-required
+        natbib-used
+        cleveref-required
+        cleveref-used
+        biblatex-required
+        biblatex-used
+        mbuffer
+        mchar
+        (org-latex-prefer-user-labels (and (boundp 'org-latex-prefer-user-labels)
+                                           org-latex-prefer-user-labels)))
+
+    (when elc-ok nil)                  ; this is to silence a compiler error
+                                       ; about elc-ok not being used. I use it
+                                       ; as a side-effect above
+
+    ;; See if natbib, biblatex or cleveref are required
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (link)
+       (when (member (org-element-property :type link) org-ref-natbib-types)
+         (setq natbib-required t))
+       (when (member (org-element-property :type link) org-ref-biblatex-types)
+         (setq biblatex-required t))
+       (when (member (org-element-property :type link) '("cref" "Cref"))
+         (setq cleveref-required t)))
+      nil t)
+
+    ;; See if natbib is probably used. This will miss a case where natbib is included somehow.
+    (setq natbib-used
+         (or
+          (member "natbib" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
+          (member "natbib" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
+          ;; see of something like \usepackage{natbib} exists.
+          (save-excursion
+            (goto-char (point-min))
+            (re-search-forward "{natbib}" nil t))))
+
+    (setq biblatex-used
+         (or
+          (member "biblatex" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
+          (member "biblatex" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
+          ;; see of something like \usepackage{biblatex} exists.
+          (save-excursion
+            (goto-char (point-min))
+            (re-search-forward "{biblatex}" nil t))))
+
+    (setq cleveref-used
+         (or
+          (member "cleveref" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
+          (member "cleveref" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
+          ;; see of something like \usepackage{cleveref} exists.
+          (save-excursion
+            (goto-char (point-min))
+            (re-search-forward  "{cleveref}" nil t))))
+
+    ;; setup bib-candidates. This checks a variety of things in the
+    ;; bibliography, bibtex files. check for which bibliographies are used
+
+    (cl-loop for bibfile in (org-ref-find-bibliography)
+            do
+            (let ((bibdialect))
+              (with-current-buffer (find-file-noselect bibfile)
+                (setq bibdialect bibtex-dialect))
+              (cl-pushnew
+               (format "[[%s]] (dialect = %s)\n" bibfile bibdialect)
+               bib-candidates)))
+
+
+    ;; Check bibliography style exists
+    (save-excursion
+      (goto-char 0)
+      (unless (re-search-forward "bibliographystyle:\\|\\\\bibliographystyle{" nil t)
+       (cl-pushnew
+        "No bibliography style found. This may be ok, if your latex class style sets that up, but if not this is an error. Try adding something like:
+    bibliographystyle:unsrt
+    at the end of your file.\n"
+        bib-candidates)))
+
+    ;; Check if latex knows of the bibliographystyle. We only check links here.
+    ;;  I also assume this style exists as a bst file that kpsewhich can find.
+    (save-excursion
+      (goto-char 0)
+      (when (re-search-forward "bibliographystyle:" nil t)
+       ;; on a link. get style
+       (let ((path (org-element-property :path (org-element-context))))
+          (unless (= 0 (shell-command (format "kpsewhich %s.bst" path)))
+            (cl-pushnew
+            (format "bibliographystyle \"%s\" may be unknown" path)
+            bib-candidates)))))
+
+    ;; check for multiple bibliography links
+    (let* ((bib-links (-filter
+                       (lambda (el)
+                        (string= (org-element-property :type el) "bibliography"))
+                       (org-element-map (org-element-parse-buffer) 'link 'identity)))
+           (n-bib-links (length bib-links)))
+
+      (when (> n-bib-links 1)
+       (mapc (lambda (link)
+               (setq
+                bib-candidates
+                (append
+                  bib-candidates
+                  (list (format  "Multiple bibliography link: %s"
+                                (org-element-property :raw-link link))))))
+              bib-links)))
+
+    ;; Check for bibliography files existence.
+    (mapc (lambda (bibfile)
+            (unless (file-exists-p bibfile)
+              (cl-pushnew
+              (format "%s does not exist." bibfile)
+              bib-candidates)))
+          (org-ref-find-bibliography))
+
+    ;; check for spaces in bibliography
+    (let ((bibfiles (mapcar 'expand-file-name
+                            (org-ref-find-bibliography))))
+      (mapc (lambda (bibfile)
+              (when (string-match " " bibfile)
+               (cl-pushnew
+                (format "One or more spaces found in path to %s. No spaces are allowed in bibtex file paths. We recommend replacing them with -. Underscores usually cause other problems." bibfile)
+                bib-candidates)))
+            bibfiles))
+
+    ;; validate bibtex files
+    (let ((bibfiles (mapcar 'expand-file-name
+                            (org-ref-find-bibliography))))
+      (mapc
+       (lambda (bibfile)
+        (unless (with-current-buffer
+                     (find-file-noselect bibfile)
+                   (bibtex-validate))
+           (cl-pushnew
+           (format  "Invalid bibtex file found. [[file:%s]]\n" bibfile)
+           bib-candidates)))
+       bibfiles)
+      ;; check types
+      (mapc
+       (lambda (bibfile)
+        (with-current-buffer
+             (find-file-noselect bibfile)
+          (goto-char (point-min))
+          (while (re-search-forward "^@\\(.*?\\)[({]" nil t)
+            (when (and (not (string= "string" (downcase (match-string-no-properties 1))))
+                       (not (member (s-trim (downcase (match-string-no-properties 1)))
+                                    (cdr (assoc bibtex-dialect
+                                                (list
+                                                 (cons 'BibTeX (mapcar (lambda (e) (downcase (car e)))
+                                                                       bibtex-BibTeX-entry-alist))
+                                                 (cons 'biblatex (mapcar (lambda (e) (downcase (car e)))
+                                                                         bibtex-biblatex-entry-alist))))))))
+              (cl-pushnew
+               (format  "Invalid bibtex entry type (%s) found in [[file:%s::%s]]\n" (match-string-no-properties 1)
+                        bibfile (line-number-at-pos))
+               bib-candidates)))))
+       bibfiles))
+
+    ;; unreferenced labels
+    (save-excursion
+      (save-restriction
+       (widen)
+       (goto-char (point-min))
+       (let ((matches '()))
+         ;; these are the org-ref label:stuff  kinds
+         (while (re-search-forward
+                 "[^#+]label:\\([a-zA-Z0-9:-]*\\)" nil t)
+           (cl-pushnew (cons
+                        (match-string-no-properties 1)
+                        (point))
+                       matches))
+         ;; now add all the other kinds of labels.
+         ;; #+label:
+         (save-excursion
+           (goto-char (point-min))
+           (while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" nil t)
+             ;; do not do this for tables. We get those in `org-ref-get-tblnames'.
+             ;; who would have thought you have save match data here? Trust me. When
+             ;; I wrote this, you did.
+             (unless (save-match-data  (equal (car (org-element-at-point)) 'table))
+               (cl-pushnew (cons (match-string-no-properties 1) (point)) matches))))
+
+         ;; \label{}
+         (save-excursion
+           (goto-char (point-min))
+           (while (re-search-forward "\\\\label{\\([a-zA-Z0-9:-]*\\)}"
+                                     nil t)
+             (cl-pushnew (cons (match-string-no-properties 1) (point)) matches)))
+
+         ;; #+tblname: and actually #+label
+         (cl-loop for cell in (org-element-map (org-element-parse-buffer 'element) 'table
+                                (lambda (table)
+                                  (cons (org-element-property :name table)
+                                        (org-element-property :begin table))))
+                  do
+                  (cl-pushnew cell matches))
+
+         ;; CUSTOM_IDs
+         (org-map-entries
+          (lambda ()
+            (let ((custom_id (org-entry-get (point) "CUSTOM_ID")))
+              (when (not (null custom_id))
+                (cl-pushnew (cons custom_id (point)) matches)))))
+
+         (goto-char (point-min))
+         (while (re-search-forward "^#\\+name:\\s-+\\(.*\\)" nil t)
+           (cl-pushnew (cons (match-string 1) (point)) matches))
+
+
+         ;; unreference labels
+         (let ((refs (org-element-map (org-element-parse-buffer) 'link
+                       (lambda (el)
+                         (when (or (string= "ref" (org-element-property :type el))
+                                   (string= "eqref" (org-element-property :type el))
+                                   (string= "pageref" (org-element-property :type el))
+                                   (string= "nameref" (org-element-property :type el))
+                                   (string= "autoref" (org-element-property :type el))
+                                   (string= "cref" (org-element-property :type el))
+                                   (string= "Cref" (org-element-property :type el)))
+                           (org-element-property :path el))))))
+           (cl-loop for (label . p) in matches
+                    do
+                    (when (and label (not (-contains? refs label)))
+                      (cl-pushnew
+                       (cons label (set-marker (make-marker) p))
+                       unreferenced-labels)))))))
+
+
+    (with-current-buffer buf
+      (when bad-citations
+       (insert "\n* Bad citations\n")
+       (cl-loop for (key . marker) in bad-citations
+                do
+                (setq mbuffer (buffer-name (marker-buffer marker))
+                      mchar (marker-position marker))
+                (insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
+                                mbuffer mchar key))))
+      (when bad-refs
+       (insert "\n* Bad ref links\n")
+       (cl-loop for (key . marker) in bad-refs
+                do
+                (setq mbuffer (buffer-name (marker-buffer marker))
+                      mchar (marker-position marker))
+                (insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
+                                mbuffer mchar key))))
+
+      (when bad-labels
+       (insert "\n* Multiply defined label links\n")
+       (cl-loop for (key . marker) in bad-labels
+                do
+                (setq mbuffer (buffer-name (marker-buffer marker))
+                      mchar (marker-position marker))
+                (insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
+                                mbuffer mchar key))))
+
+      (when bad-files
+       (insert "\n* Bad files\n")
+       (cl-loop for (fname pos) in bad-files do
+                (insert (format "- [[elisp:(goto-char %s)][%s]]\n" pos fname))))
+
+      (when unreferenced-labels
+       (insert "\n* Unreferenced label links\n")
+       (cl-loop for (key . marker) in unreferenced-labels
+                when (not (string= key ""))
+                do
+                (setq mbuffer (buffer-name (marker-buffer marker))
+                      mchar (marker-position marker))
+                (insert (format "- [[elisp:(progn (switch-to-buffer %S) (goto-char %S)(org-show-entry))][%s]]\n"
+                                mbuffer mchar key))))
+
+      (when bib-candidates
+       (insert "\n* Bibliography\n\n")
+       (cl-loop for candidate in bib-candidates
+                do
+                (insert (format "- %s" candidate))))
+
+      (insert "\n* Miscellaneous\n\n")
+      (cl-loop for s in `(,(format "org-latex-prefer-user-labels = %s"
+                                  org-latex-prefer-user-labels)
+                         ,(format "bibtex-dialect = %s" bibtex-dialect)
+                         ,(format "biblatex is%srequired." (if biblatex-required " " " not "))
+                         ,(format "biblatex is%sused." (if biblatex-used " " " not "))
+                         ,(format "emacs-version = %s" (emacs-version))
+                         ,(format "org-version = %s" (org-version))
+                         ,(org-ref-version)
+                         ,(format "org-ref.el installed at %s" (concat
+                                                                (file-name-sans-extension
+                                                                 (locate-library "org-ref"))
+                                                                ".el"))
+                         ,(format "org-ref-insert-cite-function = %s" org-ref-insert-cite-function)
+                         ,(format "org-ref-insert-label-function = %s" org-ref-insert-label-function)
+                         ,(format "org-ref-insert-ref-function = %s" org-ref-insert-ref-function)
+                         ,(format "org-ref-cite-onclick-function = %s" org-ref-cite-onclick-function)
+                         ,(format "org-latex-pdf-process is defined as %s" org-latex-pdf-process)
+                         ,(format "natbib is%srequired." (if natbib-required " " " not "))
+                         ,(format "natbib is%sin %s or %s."
+                                  (if natbib-used " " " not ")
+                                  (propertize "org-latex-default-packages-alist"
+                                              'help-echo (format "%S" (mapconcat
+                                                                       (lambda (s)
+                                                                         (format "%s" s))
+                                                                       org-latex-default-packages-alist
+                                                                       "\n"))
+                                              'font-lock-face '(:foreground "red3"))
+                                  (propertize "org-latex-packages-alist"
+                                              'help-echo (format "%S" (mapconcat
+                                                                       (lambda (s)
+                                                                         (format "%s" s))
+                                                                       org-latex-packages-alist
+                                                                       "\n"))
+                                              'font-lock-face '(:foreground "red3")))
+                         ,(format "cleveref is%srequired." (if cleveref-required " " " not "))
+                         ,(format "cleveref is%sin %s or %s."
+                                  (if cleveref-used " " " not ")
+                                  (propertize "org-latex-default-packages-alist"
+                                              'help-echo (format "%S" (mapconcat
+                                                                       (lambda (s)
+                                                                         (format "%s" s))
+                                                                       org-latex-default-packages-alist
+                                                                       "\n"))
+                                              'font-lock-face '(:foreground "red3"))
+                                  (propertize "org-latex-packages-alist"
+                                              'help-echo (format "%S" (mapconcat
+                                                                       (lambda (s)
+                                                                         (format "%s" s))
+                                                                       org-latex-packages-alist
+                                                                       "\n"))
+                                              'font-lock-face '(:foreground "red3")))
+                         ,(format "bibtex-completion installed = %s" (featurep 'bibtex-completion))
+                         ,(format "bibtex-completion loaded = %s" (fboundp 'bibtex-completion-candidates)))
+              do
+              (insert "- " s "\n"))
+      (insert (format "- org-latex-default-packages-alist\n"))
+      (cl-loop for el in org-latex-default-packages-alist
+              do
+              (insert (format "  %S\n" el)))
+
+      (if (null org-latex-packages-alist)
+         (insert "-  org-latex-packages-alist is nil\n")
+       (insert "-  org-latex-packages-alist\n")
+       (cl-loop for el in org-latex-packages-alist
+                do
+                (insert (format "  %S\n" el))))
+
+
+      (insert (format "- ox-bibtex loaded = %s\n" (featurep 'ox-bibtex)))
+      (insert (format "- ox-bibtex loaded after org-ref = %s\n"
+                     (let ((org-ref-i (seq-position load-history (assoc (locate-library "org-ref") load-history)) )
+                           (ox-bibtex-i (seq-position load-history (assoc (locate-library "ox-bibtex") load-history))))
+                       (and org-ref-i ox-bibtex-i
+                            (> org-ref-i ox-bibtex-i)))))
+
+      (insert (format "- ebib loaded = %s\n" (featurep 'ebib)))
+      (insert (format "- ebib loaded after org-ref = %s\n"
+                     (let ((org-ref-i (seq-position load-history (assoc (locate-library "org-ref") load-history)) )
+                           (ebib-i (seq-position load-history (assoc (locate-library "ebib") load-history))))
+                       (and org-ref-i ebib-i
+                            (> org-ref-i ebib-i)))))
+
+
+
+      (insert "- cite link definition:\n" (with-temp-buffer
+                                           (insert (format "%S" (assoc "cite" org-link-parameters)))
+                                           (pp-buffer)
+                                           (buffer-string)))
+
+      (insert "\n* LaTeX setup\n\n")
+      (cl-loop for executable in '("latex" "pdflatex" "bibtex" "biblatex"
+                                  "makeindex" "makeglossaries")
+              do
+              (insert (format "%s is installed at %s\n" executable (executable-find executable))))
+
+      (insert "\n* Warnings\n")
+      (if (get-buffer "*Warnings*")
+         (cl-loop for line in (s-split "\n" (with-current-buffer "*Warnings*"
+                                              (buffer-string)))
+                  if (s-starts-with?  "Warning (org-ref):" line)
+                  do
+                  (insert " - " line "\n"))
+       (insert "- No (org-ref) Warnings found."))
+
+
+      (insert (format  "\n* Utilities
+
+- [[elisp:(progn (find-file %S) (ispell))][Spell check document]]
+- [[elisp:(progn (find-file %S) (org-ref))][recheck document with org-ref]]
+" fname fname))
+      (goto-char (point-min))
+
+      ;; (setq header-line-format "Press q to quit.")
+      ;; (local-set-key "q"
+      ;;                    #'(lambda ()
+      ;;                        (interactive)
+      ;;                        (delete-window)))
+      (read-only-mode))
+
+    (display-buffer-in-side-window buf '((side . right)))))
+
+
+
+;;** Find non-ascii characters
+;;;###autoload
+(defun org-ref-find-non-ascii-characters ()
+  "Find non-ascii characters in the buffer.  Useful for cleaning up bibtex files."
+  (interactive)
+  (occur "[^[:ascii:]]"))
+
+;;;###autoload
+(defun org-ref-extract-bibtex-to-file (bibfile &optional clobber)
+  "Extract all bibtex entries for citations buffer to BIBFILE.
+If BIBFILE exists, append, unless you use a prefix arg (C-u),
+which will CLOBBER the file."
+  (interactive
+   (list (read-file-name "Bibfile: " nil nil nil
+                        (file-name-nondirectory
+                         (concat (file-name-sans-extension
+                                  (buffer-file-name))
+                                 ".bib")))
+        current-prefix-arg))
+
+  (let* ((bibtex-files (org-ref-find-bibliography))
+        (keys (reverse (org-ref-get-bibtex-keys)))
+        (bibtex-entry-kill-ring-max (length keys))
+        (bibtex-entry-kill-ring '())
+        (kill-cb (not (find-buffer-visiting bibfile)))
+        (cb (find-file-noselect bibfile))
+        (current-bib-entries (with-current-buffer cb
+                               (prog1
+                                   (buffer-string)
+                                 (when kill-cb (kill-buffer cb))))))
+
+    (save-window-excursion
+      (cl-loop for key in keys
+              do
+              (bibtex-search-entry key t)
+              (bibtex-kill-entry t)))
+
+    (with-temp-file bibfile
+      (unless clobber (insert current-bib-entries))
+      (insert (mapconcat
+              'identity
+              bibtex-entry-kill-ring
+              "\n\n")))))
+
+
+;;* Utilities
+
+;;** Extract bibtex entries in org-file
+
+;;;###autoload
+(defun org-ref-extract-bibtex-entries ()
+  "Extract the bibtex entries in the current buffer into a bibtex src block."
+  (interactive)
+  (let* ((bibtex-files (org-ref-find-bibliography))
+        (keys (reverse (org-ref-get-bibtex-keys)))
+        (bibtex-entry-kill-ring-max (length keys))
+        (bibtex-entry-kill-ring '()))
+
+    (save-window-excursion
+      (cl-loop for key in keys
+              do
+              (bibtex-search-entry key t)
+              (bibtex-kill-entry t)))
+
+    (goto-char (point-max))
+    (insert "\n\n")
+    (org-insert-heading)
+    (insert (format " Bibtex entries
+
+#+BEGIN_SRC bibtex :tangle %s
+%s
+#+END_SRC"
+                   (let ((bibfile (concat (file-name-base
+                                           (or (buffer-file-name) "references"))
+                                          ".bib")))
+                     (if (file-exists-p bibfile)
+                         (file-name-nondirectory
+                          (read-file-name "Bibfile: " nil nil nil bibfile))
+                       bibfile))
+                   (mapconcat
+                    'identity
+                    bibtex-entry-kill-ring
+                    "\n\n")))))
+
+
+
+
+(provide 'org-ref-utils)
+;;; org-ref-utils.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-worldcat.el b/elpa/org-ref-20230507.1420/org-ref-worldcat.el
new file mode 100644 (file)
index 0000000..7223f2c
--- /dev/null
@@ -0,0 +1,20 @@
+;;; org-ref-worldcat.el --- Worldcat library
+
+;;; Commentary:
+;; Provides a function to query world cat
+;; See:
+;; https://www.worldcat.org/wcpa/content/affiliate/default.jsp
+;; https://www.worldcat.org/affiliate/tools?atype=text
+
+;;; Code:
+
+(defun worldcat-query-all (query)
+  "Open browser to Worldcat QUERY."
+  (browse-url
+   (format
+    "http://www.worldcat.org/search?qt=worldcat_org_all&q=%s"
+    query)))
+
+(provide 'org-ref-worldcat)
+
+;;; org-ref-worldcat.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref-wos.el b/elpa/org-ref-20230507.1420/org-ref-wos.el
new file mode 100644 (file)
index 0000000..18ae583
--- /dev/null
@@ -0,0 +1,107 @@
+;;; org-ref-wos.el --- Web of Science functions              -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Adds a new org-mode link for a search in Web of Science.
+;;; and an org-mode link for a link to an Accession number.
+
+(require 'org)
+(require 's)
+(require 'org-ref-utils)
+
+;;; Code:
+(org-link-set-parameters "wos"
+                        :follow (lambda (accession-number)
+                                  (browse-url
+                                   (concat
+                                    "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:ut/"
+                                    accession-number)))
+                        :export (lambda (accession-number desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:ut/%s\">%s</a>"
+                                            accession-number
+                                            (or desc (concat "wos:" accession-number)))))))
+
+(org-link-set-parameters "wos-search"
+                        :follow (lambda (path)
+                                  (browse-url
+                                   (format  "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
+                                            (s-join "+" (split-string path)))))
+                        :export (lambda (link desc format)
+                                  (cond
+                                   ((eq format 'html)
+                                    (format "<a href=\"%s\">%s</a>"
+                                            (format  "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
+                                                     (s-join "+" (split-string link)))
+                                            (or desc link))))))
+
+;;;###autoload
+(defun wos-search ()
+  "Open the word at point or selection in Web of Science as a topic query."
+  ;; the url was derived from this page: http://wokinfo.com/webtools/searchbox/
+  (interactive)
+  (browse-url
+   (format "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
+           (if (region-active-p)
+               (mapconcat 'identity (split-string
+                                     (buffer-substring (region-beginning)
+                                                       (region-end))) "+")
+             (thing-at-point 'word)))))
+
+
+;;;###autoload
+(defun wos ()
+  "Open Web of Science search page in a browser."
+  (interactive)
+  (browse-url "http://apps.webofknowledge.com"))
+
+;;* Accession numbers
+;; see http://kitchingroup.cheme.cmu.edu/blog/2015/06/08/Getting-a-WOS-Accession-number-from-a-DOI/
+(defvar *wos-redirect* nil
+  "Holds the redirect from a `url-retrieve' callback function.")
+
+(defvar *wos-waiting* nil
+  "Non-nil when waiting for a `url-retrieve' redirect.")
+
+
+(defun wos-get-wos-redirect (url)
+  "Return final redirect URL for open-url."
+  (setq *wos-waiting* t)
+  (url-retrieve
+   url
+   (lambda (status)
+     (setq *wos-redirect* (car (last status)))
+     (setq *wos-waiting* nil)))
+  (while *wos-waiting* (sleep-for 0.1))
+  (url-unhex-string *wos-redirect*))
+
+
+(defun wos-doi-to-accession-number (doi)
+  "Return a WOS Accession number for a DOI."
+  (let* ((open-url (concat "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/" doi))
+         (redirect (wos-get-wos-redirect open-url)))
+    (message redirect)
+    (string-match "&KeyUT=WOS:\\([^&]*\\)&" redirect)
+    (match-string 1 redirect)))
+
+(provide 'org-ref-wos)
+;;; org-ref-wos.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref.bib b/elpa/org-ref-20230507.1420/org-ref.bib
new file mode 100644 (file)
index 0000000..0526093
--- /dev/null
@@ -0,0 +1,333 @@
+@book{Dominik201408,
+  keywords = {org-mode},
+  url = {http://amazon.com/o/ASIN/9881327709/},
+  isbn = 9789881327703,
+  year = 2014,
+  publisher = {Samurai Media Limited},
+  author = {Carsten Dominik},
+  title = {The Org Mode 8 Reference Manual - Organize your life with GNU
+                  Emacs},
+}
+@article{xu-2015-relat-between,
+  title =       {Relationships Between the Surface Electronic and Chemical
+                  Properties of Doped 4d and 5d Late Transition Metal Dioxides},
+  eid =                 104703,
+  url =
+                  "http://scitation.aip.org/content/aip/journal/jcp/142/10/10.1063/1.4914093",
+  doi =                 {10.1063/1.4914093},
+  year =        2015,
+  pages =       104703,
+  number =      10,
+  volume =      142,
+  journal =     "The Journal of Chemical Physics",
+  keywords =    {DESC0004031, early-career, orgmode},
+  author =      "Xu, Zhongnan and Kitchin, John R.",
+}
+
+@article{xu-2015-linear-respon,
+  title =       {A Linear Response {DFT}+{U} Study of Trends in the Oxygen
+                  Evolution Activity of Transition Metal Rutile Dioxides},
+  eprint =      { http://dx.doi.org/10.1021/jp511426q },
+  url =                 { http://dx.doi.org/10.1021/jp511426q },
+  doi =                 {10.1021/jp511426q},
+  year =        2015,
+  pages =       {4827-4833},
+  number =      9,
+  volume =      119,
+  journal =     {The Journal of Physical Chemistry C},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Xu, Zhongnan and Rossmeisl, Jan and Kitchin, John R.},
+}
+
+@article{boes-2015-suppor-infor,
+  title =       {Supporting Information: Estimating Bulk-Composition-Dependent
+                  \ce{H2} Adsorption Energies on \ce{Cu_{x}Pd_{1-x}} Alloy (111)
+                  Surfaces},
+  url =
+                  {http://pubs.acs.org/doi/suppl/10.1021/cs501585k/suppl_file/cs501585k_si_001.pdf},
+  doi =                 {10.1021/cs501585k},
+  year =        2015,
+  pages =       {1020-1026},
+  volume =      5,
+  journal =     {ACS Catalysis},
+  keywords =    {orgmode},
+  author =      {Jacob R. Boes and Gamze Gumuslu and James B. Miller and Andrew
+                  J. Gellman and John R. Kitchin},
+}
+
+@article{boes-2015-estim-bulk,
+  title =       {Estimating Bulk-Composition-Dependent \ce{H2} Adsorption
+                  Energies on \ce{Cu_{x}Pd_{1-x}} Alloy (111) Surfaces},
+  url =                 {http://dx.doi.org/10.1021/cs501585k},
+  doi =                 {10.1021/cs501585k},
+  year =        2015,
+  pages =       {1020-1026},
+  volume =      5,
+  keywords =    {orgmode},
+  journal =     {ACS Catalysis},
+  author =      {Jacob R. Boes and Gamze Gumuslu and James B. Miller and Andrew
+                  J. Gellman and John R. Kitchin},
+}
+
+@article{curnan-2014-effec-concen,
+  title =       {Effects of Concentration, Crystal Structure, Magnetism, and
+                  Electronic Structure Method on First-Principles Oxygen Vacancy
+                  Formation Energy Trends in Perovskites},
+  eprint =      { http://dx.doi.org/10.1021/jp507957n },
+  url =                 {http://dx.doi.org/10.1021/jp507957n},
+  doi =                 {10.1021/jp507957n},
+  year =        2014,
+  pages =       {28776-28790},
+  number =      49,
+  volume =      118,
+  journal =     {The Journal of Physical Chemistry C},
+  keywords =    {orgmode, },
+  author =      {Curnan, Matthew T. and Kitchin, John R.},
+}
+
+@article{miller-2014-simul-temper,
+  title =       {Simulating Temperature Programmed Desorption of Oxygen on
+                  {P}t(111) Using {DFT} Derived Coverage Dependent Desorption
+                  Barriers},
+  url =                 {http://dx.doi.org/10.1007/s11244-013-0166-3},
+  doi =                 {10.1007/s11244-013-0166-3},
+  year =        2014,
+  pages =       {106-117},
+  number =      {1-4},
+  volume =      57,
+  journal =     {Topics in Catalysis},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Spencer D. Miller and Vladimir V. Pushkarev and Andrew
+                  J. Gellman and John R. Kitchin},
+}
+
+@article{xu-2014-probin-cover,
+  title =       {Probing the Coverage Dependence of Site and Adsorbate
+                  Configurational Correlations on (111) Surfaces of Late
+                  Transition Metals},
+  url =                 {http://dx.doi.org/10.1021/jp508805h},
+  doi =                 {10.1021/jp508805h},
+  year =        2014,
+  pages =       {25597-25602},
+  number =      44,
+  volume =      118,
+  journal =     {J. Phys. Chem. C},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Zhongnan Xu and John R. Kitchin},
+}
+
+@article{xu-2014-relat-elect,
+  title =       {Relating the Electronic Structure and Reactivity of the 3d
+                  Transition Metal Monoxide Surfaces},
+  abstract =    "Abstract We performed a series of density functional theory
+                  calculations of dissociative oxygen adsorption on fcc metals
+                  and their corresponding rocksalt monoxides to elucidate the
+                  relationship between the oxide electronic structure and its
+                  corresponding reactivity. We decomposed the dissociative
+                  adsorption energy of oxygen on an oxide surface into a sum of
+                  the adsorption energy on the metal and a change in adsorption
+                  energy caused by both expanding and oxidizing the lattice. We
+                  were able to identify the key features of the electronic
+                  structure that explains the trends in adsorption energies on
+                  3d transition metal monoxide surfaces. ",
+  issn =        "1566-7367",
+  url =                 {http://dx.doi.org/10.1016/j.catcom.2013.10.028},
+  doi =                 {10.1016/j.catcom.2013.10.028},
+  year =        2014,
+  pages =       {60-64},
+  volume =      52,
+  journal =     {Catalysis Communications},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Zhongnan Xu and John R. Kitchin},
+}
+
+@article{mehta-2014-ident-poten,
+  title =       {Identifying Potential \ce{BO2} Oxide Polymorphs for Epitaxial
+                  Growth Candidates},
+  eprint =      {http://pubs.acs.org/doi/pdf/10.1021/am4059149},
+  url =                 {http://dx.doi.org/10.1021/am4059149},
+  doi =                 {10.1021/am4059149},
+  year =        2014,
+  pages =       {3630-3639},
+  number =      5,
+  volume =      6,
+  journal =     {ACS Appl. Mater. Interfaces},
+  keywords =    {orgmode, },
+  author =      {Prateek Mehta and Paul A. Salvador and John R. Kitchin},
+}
+
+@article{hallenbeck-2013-effec,
+  title =       {Effects of \ce{O_2} and \ce{SO_2} on the Capture Capacity of a
+                  Primary-Amine Based Polymeric \ce{CO_2} Sorbent},
+  eprint =      "http://pubs.acs.org/doi/pdf/10.1021/ie400582a",
+  url =                 "http://pubs.acs.org/doi/abs/10.1021/ie400582a",
+  doi =                 "10.1021/ie400582a",
+  year =        2013,
+  pages =       "10788-10794",
+  journal =     "Industrial \& Engineering Chemistry Research",
+  keywords =    {RUA, orgmode},
+  author =      "Hallenbeck, Alexander P. and Kitchin, John R.",
+}
+
+
+@article{kitchin-2016-autom-data,
+  abstract =    "In the current scientific publishing landscape, there is a
+                  need for an authoring workflow that easily integrates data and
+                  code into manuscripts and that enables the data and code to be
+                  published in reusable form. Automated embedding of data and
+                  code into published output will enable superior communication
+                  and data archiving. In this work, we demonstrate a proof of
+                  concept for a workflow, org-mode, which successfully provides
+                  this authoring capability and workflow integration. We
+                  illustrate this concept in a series of examples for potential
+                  uses of this workflow. First, we use data on citation counts
+                  to compute the h-index of an author, and show two code
+                  examples for calculating the h-index. The source for each
+                  example is automatically embedded in the PDF during the export
+                  of the document. We demonstrate how data can be embedded in
+                  image files, which themselves are embedded in the document.
+                  Finally, metadata about the embedded files can be
+                  automatically included in the exported PDF, and accessed by
+                  computer programs. In our customized export, we embedded
+                  metadata about the attached files in the PDF in an Info field.
+                  A computer program could parse this output to get a list of
+                  embedded files and carry out analyses on them. Authoring tools
+                  such as Emacs + org-mode can greatly facilitate the
+                  integration of data and code into technical writing. These
+                  tools can also automate the embedding of data into document
+                  formats intended for consumption.",
+  author =      "Kitchin, John R. and Van Gulick, Ana E. and Zilinski, Lisa D.",
+  keywords =    {orgmode},
+  doi =                 "10.1007/s00799-016-0173-7",
+  issn =        "1432-1300",
+  journal =     "International Journal on Digital Libraries",
+  pages =       "1--6",
+  title =       {Automating Data Sharing Through Authoring Tools},
+  url =                 "http://dx.doi.org/10.1007/s00799-016-0173-7",
+  year =        2016,
+}
+
+@article{kitchin-2015-data-surfac-scien,
+  author =      "John R. Kitchin",
+  title =       {Data Sharing in Surface Science},
+  journal =     "Surface Science ",
+  volume =      {647},
+  pages =       {103-107},
+  year =        2015,
+  doi =                 {10.1016/j.susc.2015.05.007},
+  url =
+                  "http://www.sciencedirect.com/science/article/pii/S0039602815001326",
+  issn =        "0039-6028",
+  keywords =    {DESC0004031, early-career, orgmode, Data sharing },
+}
+
+@article{kitchin-2015-examp,
+  author =      {Kitchin, John R.},
+  title =       {Examples of Effective Data Sharing in Scientific Publishing},
+  journal =     {ACS Catalysis},
+  volume =      {5},
+  number =      {6},
+  pages =       {3894-3899},
+  year =        2015,
+  doi =                 {10.1021/acscatal.5b00538},
+  url =                 { http://dx.doi.org/10.1021/acscatal.5b00538 },
+  keywords =    {DESC0004031, early-career, orgmode, Data sharing },
+  eprint =      { http://dx.doi.org/10.1021/acscatal.5b00538 },
+}
+
+@misc{jkitchin76:online,
+  author =      {John Kitchin},
+  title =       {jkitchin/org-ref: org-mode modules for citations,
+                  cross-references, bibliographies in org-mode and useful bibtex
+                  tools to go with it.},
+  url =                 {https://github.com/jkitchin/org-ref},
+  urldate =     {12/04/2016}
+}
+
+@book{chen-2006-handb-data-visual,
+  author =      {Hrsg. Chun-houh Chen ; Hrsg. Wolfgang H{\"a}rdle ; Hrsg.
+                  Antony Unwin},
+  title =       {Handbook of Data Visualization},
+  year =        2006,
+  publisher =   {Springer Berlin},
+  url =                 {http://www.worldcat.org/oclc/150289486?referer=xid},
+  city =        {Berlin},
+  ed =          {1. Ed.},
+  form =        {BA},
+  isbn =        9783540330363,
+  lang =        {eng},
+  lccn =        2007931825,
+  oclcnum =     {150289486 214357554 232302403 314615038 474712418 494787249
+                  645208009 743424036 751135412 76799021 804152581 849253364
+                  873514520 612218650},
+}
+
+@article{geng-2017-first-princ,
+  author =      {Feiyang Geng and Jacob R. Boes and John R. Kitchin},
+  title =       {First-Principles Study of the {Cu-Pd} Phase Diagram},
+  journal =     {Calphad},
+  volume =      56,
+  pages =       {224-229},
+  year =        2017,
+  doi =                 {10.1016/j.calphad.2017.01.009},
+  url =                 {https://doi.org/10.1016/j.calphad.2017.01.009},
+  DATE_ADDED =  {Wed Feb 22 09:13:55 2017},
+}
+
+@article{boes-2017-model-segreg,
+  author =       {Boes, Jacob Russell and Kitchin, John R.},
+  title =        {Modeling Segregation on {AuPd}(111) Surfaces With Density
+                  Functional Theory and Monte Carlo Simulations},
+  journal =      {The Journal of Physical Chemistry C},
+  volume =      {121},
+  number =      {6},
+  pages =       {3479-3487},
+  year =         2017,
+  doi =          {10.1021/acs.jpcc.6b12752},
+  url =          {https://doi.org/10.1021/acs.jpcc.6b12752},
+  eprint =       { http://dx.doi.org/10.1021/acs.jpcc.6b12752 },
+}
+
+@article{xu-2017-first-princ,
+  author =      {Xu, Zhongnan and Salvador, Paul A. and Kitchin, John R.},
+  title =       {First-Principles Investigation of the Epitaxial Stabilization
+                  of Oxide Polymorphs: \ce{TiO2} on \ce{(Sr{,}Ba)TiO3}},
+  journal =     {ACS Applied Materials \& Interfaces},
+  volume =      {9},
+  number =      {4},
+  pages =       {4106-4118},
+  year =        2017,
+  doi =                 {10.1021/acsami.6b11791},
+  url =                 {https://doi.org/10.1021/acsami.6b11791},
+  eprint =      { http://dx.doi.org/10.1021/acsami.6b11791 },
+  note =        {PMID: 28004912},
+}
+
+@article{boes-2017-neural-networ,
+  author =      {Jacob R. Boes and John R. Kitchin},
+  title =       {Neural Network Predictions of Oxygen Interactions on a Dynamic
+                  {Pd} Surface},
+  journal =     {Molecular Simulation},
+  pages =       {1-9},
+  year =        2017,
+  doi =                 {10.1080/08927022.2016.1274984},
+  url =                 {https://doi.org/10.1080/08927022.2016.1274984},
+  keywords =    {CBET-1506770, orgmode},
+}
+
+
+@article{boes-2016-neural-networ,
+  author =      {Jacob R. Boes and Mitchell C. Groenenboom and John A. Keith
+                  and John R. Kitchin},
+  title =       {Neural Network and {Reaxff} Comparison for {Au} Properties},
+  journal =     {Int. J. Quantum Chem.},
+  volume =      116,
+  number =      13,
+  pages =       {979-987},
+  year =        2016,
+  doi =                 {10.1002/qua.25115},
+  url =                 {http://dx.doi.org/10.1002/qua.25115},
+  issn =        {1097-461X},
+  keywords =    {Kohn-Sham density functional theory, neural networks, reactive
+                  force fields, potential energy surfaces, machine learning},
+}
\ No newline at end of file
diff --git a/elpa/org-ref-20230507.1420/org-ref.el b/elpa/org-ref-20230507.1420/org-ref.el
new file mode 100644 (file)
index 0000000..048b693
--- /dev/null
@@ -0,0 +1,53 @@
+;;; org-ref.el --- citations, cross-references and bibliographies in org-mode -*- lexical-binding: t; -*-
+
+;; Copyright(C) 2014-2021 John Kitchin
+
+;; Author: John Kitchin <jkitchinNOSPAMandrew.cmu.edu>
+;; URL: https://github.com/jkitchin/org-ref
+;; Version: 3.0
+;; Keywords: org-mode, cite, ref, label
+;; Package-Requires: ((org "9.4") (dash "0") (s "0") (f "0") (htmlize "0") (hydra "0") (avy "0") (parsebib "0") (bibtex-completion "0") (citeproc "0") (ox-pandoc "0"))
+;; This file is not currently part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program ; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; Lisp code to setup bibliography, cite, ref and label org-mode links. The
+;; links are clickable and do things that are useful.
+;;
+;; This uses vanilla completing-read in Emacs. You can customize by requiring
+;; `org-ref-helm' or `org-ref-ivy' after this.
+
+;; You should really read org-ref.org in this package for details.
+;;
+
+;;; Code:
+
+(require 'org-ref-core)
+
+
+(setq org-ref-insert-link-function 'org-ref-insert-link
+      org-ref-insert-cite-function 'org-ref-insert-cite-link
+      org-ref-insert-label-function 'org-ref-insert-label-link
+      org-ref-insert-ref-function 'org-ref-insert-ref-link
+      org-ref-cite-onclick-function (lambda (_) (org-ref-citation-hydra/body)))
+
+
+;;* The end
+(provide 'org-ref)
+
+;;; org-ref.el ends here
diff --git a/elpa/org-ref-20230507.1420/org-ref.org b/elpa/org-ref-20230507.1420/org-ref.org
new file mode 100644 (file)
index 0000000..fe26e22
--- /dev/null
@@ -0,0 +1,1109 @@
+#+TITLE: The org-ref manual (version 3)
+#+AUTHOR: John Kitchin
+#+DATE: [2021-08-25 Wed]
+#+OPTIONS: toc:nil ^:{}
+#+LATEX_HEADER: \usepackage{natbib}
+#+LATEX_HEADER: \usepackage[version=3]{mhchem}
+#+latex_header: \usepackage{makeidx}
+#+latex_header: \usepackage{cleveref}
+#+latex_header: \makeindex
+# This ridiculousness is to make the index start in the middle of a page.
+# https://tex.stackexchange.com/questions/23870/index-shouldnt-start-new-page
+#+latex_header: \makeatletter
+#+latex_header: \renewenvironment{theindex}
+#+latex_header:                {\section*{\indexname}%
+#+latex_header:                 \@mkboth{\MakeUppercase\indexname}%
+#+latex_header:                         {\MakeUppercase\indexname}%
+#+latex_header:                 \thispagestyle{plain}\parindent\z@
+#+latex_header:                 \parskip\z@ \@plus .3\p@\relax
+#+latex_header:                 \columnseprule \z@
+#+latex_header:                 \columnsep 35\p@
+#+latex_header:                 \let\item\@idxitem}
+#+latex_header:                {}
+#+latex_header: \makeatother
+
+#+latex_header: \usepackage{glossaries}
+#+latex_header: \makeglossaries
+#+latex_header_extra: \newglossaryentry{acronym}{name={acronym},description={An acronym is an abbreviation used as a word which is formed from the initial components in a phrase or a word. Usually these components are individual letters (as in NATO or laser) or parts of words or names (as in Benelux)}}
+#+latex_header_extra: \newacronym{tla}{TLA}{Three Letter Acronym}
+
+@@latex:\maketitle@@
+@@latex:\tableofcontents@@
+
+* Introduction to org-ref
+
+Org-ref is a library for org-mode [[cite:&Dominik201408]] that provides rich support for citations, labels and cross-references in org-mode. org-ref is especially suitable for org-mode documents destined for LaTeX export and scientific publication. org-ref is also extremely useful for research documents and notes. org-ref bundles several other libraries that provide functions to create and modify bibtex entries from a variety of sources, but most notably from a DOI.
+
+The basic idea of org-ref is that it defines a convenient interface to insert citations from a reference database (e.g. from a bibtex file(s)), cross-references to targets in the document, and a set of functional org-mode links for citations, cross-references and labels that export properly to LaTeX, and that provide clickable functionality to the user. org-ref uses [[https://github.com/tmalsburg/helm-bibtex][bibtex-completion]] for the candidates you can use for citations.
+
+org-ref provides a fairly large number of utilities for finding bad citations, extracting bibtex entries from citations in an org-file, and functions for interacting with bibtex entries. We find these utilities indispensable in scientific writing.
+
+org-ref has been in development since sometime in 2013. It was written to aid in the preparation of scientific manuscripts. These are the first dozen scientific articles we wrote with it:
+
+- cite:hallenbeck-2013-effec
+- cite:mehta-2014-ident-poten
+- cite:xu-2014-relat-elect
+- cite:xu-2014-probin-cover
+- cite:miller-2014-simul-temper
+- cite:curnan-2014-effec-concen
+- cite:boes-2015-estim-bulk
+- cite:xu-2015-linear-respon
+- cite:xu-2015-relat-between
+- cite:boes-2016-neural-networ
+- cite:boes-2017-neural-networ
+- cite:xu-2017-first-princ
+
+
+Be sure to check out the supporting information files for each of these. The org source for the supporting information is usually embedded in the supporting information. You may also find these two perspective articles cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien interesting, as well as this article on data sharing cite:kitchin-2016-autom-data we wrote.
+
+
+Biblatex users should read section ref:sec-biblatex-users.
+
+If you want to export this document to another format like PDF or HTML, see section ref:sec-other-forms.
+
+** 2021 version 2 vs version 3
+
+A new citation syntax was recently (2021) integrated into org-mode. Initially I thought this would make at least the citation part of org-ref obsolete. I no longer think that is the case though. One of the goals of org-ref is to provide complete coverage of natbib/biblatex citation commands, with syntax that is close to what you would write in LaTeX, and that is close to what you would read in the LaTeX documentation. The new org-mode citation syntax does not do that. It uses a very different notion of citation and bibliography style syntax. I still think there is significant value to new writers, as well as more experienced writers who are very familiar with LaTeX to use the org-ref approach.
+
+An early criticism of org-ref was its limited capability to support prenote/postnote syntax, especially for multiple citations. It turns out to be reasonably straightforward to support this, and version 3 does fully support the same syntax as the org-mode citation syntax, and it supports common prefix/suffix text, as well as local prefix/suffix text on each citation reference. I have intentionally chosen to use =&= as the prefix for bibtex keys in org-ref, so that it is explicitly different than the one org-cite uses (=@=) to reduce confusion about which syntax you are using.
+
+ [[citep:See; in &kitchin-2015-examp page 12; in &kitchin-2015-data-surfac-scien figure 6; for examples]]
+
+You can use both version 2 and version 3 syntax in the same document (although you should not mix them in the same citation). Here are the same citations from above in version 3 syntax.
+
+- cite:&hallenbeck-2013-effec
+- cite:&mehta-2014-ident-poten
+- cite:&xu-2014-relat-elect
+- cite:&xu-2014-probin-cover
+- cite:&miller-2014-simul-temper
+- cite:&curnan-2014-effec-concen
+- cite:&boes-2015-estim-bulk
+- cite:&xu-2015-linear-respon
+- cite:&xu-2015-relat-between
+- cite:&boes-2016-neural-networ
+- cite:&boes-2017-neural-networ
+- cite:&xu-2017-first-princ
+
+You should not mix org-ref links and org-cite citations. They are treated separately and you are not likely to get what you want.
+
+Another criticism was that non-LaTeX exports were usually not that good because org-ref either implemented a minimal formatting engine, and because my early effort at developing a citeproc in org-ref fizzled out. Now, there is citeproc-el, and org-ref supports that for export.
+
+The new citation syntax does not cover labels and cross-references, which are essential in our scientific writing. org-ref continues to support this. We anticipate a long life for org-ref.
+
+Should you use org-ref? If your main export target is LaTeX, and you want cross-references, then probably so.
+
+If you have no need for cross-references (either you don't use them, or vanilla org syntax is adequate), or if you don't like using ivy, and don't want to roll your own citation inserter, then you may not need org-ref.
+
+At this time, I have not integrated the org-cite capability I wrote in https://github.com/jkitchin/org-ref-cite into org-ref. I have not decided if that is a good or bad idea to do.
+
+
+** known issues with org-ref and org-citations
+
+You should not try to define a cite/*: (i.e. do not define a link type that starts with cite/) link. org-cite will probably think it is an org-citation.
+
+** Basic configuration <<basic-configuration>>
+
+You have to setup bibtex-completion variables if you want default bibliographies, notes, pdfs, and other features. You should also set the bibtex-autokey-* variables for generating bibtex keys if you use doi-utils.
+
+Here is the setup I use.
+
+#+BEGIN_SRC emacs-lisp
+(use-package ivy-bibtex
+  :init
+  (setq bibtex-completion-bibliography '("~/Dropbox/emacs/bibliography/references.bib"
+                                        "~/Dropbox/emacs/bibliography/dei.bib"
+                                        "~/Dropbox/emacs/bibliography/master.bib"
+                                        "~/Dropbox/emacs/bibliography/archive.bib")
+       bibtex-completion-library-path '("~/Dropbox/emacs/bibliography/bibtex-pdfs/")
+       bibtex-completion-notes-path "~/Dropbox/emacs/bibliography/notes/"
+       bibtex-completion-notes-template-multiple-files "* ${author-or-editor}, ${title}, ${journal}, (${year}) :${=type=}: \n\nSee [[cite:&${=key=}]]\n"
+
+       bibtex-completion-additional-search-fields '(keywords)
+       bibtex-completion-display-formats
+       '((article       . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${journal:40}")
+         (inbook        . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} Chapter ${chapter:32}")
+         (incollection  . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
+         (inproceedings . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
+         (t             . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*}"))
+       bibtex-completion-pdf-open-function
+       (lambda (fpath)
+         (call-process "open" nil 0 nil fpath))))
+
+(use-package org-ref
+  :ensure nil
+  :load-path (lambda () (expand-file-name "org-ref" scimax-dir))
+  :init
+  (add-to-list 'load-path
+              (expand-file-name "org-ref" scimax-dir))
+  (require 'bibtex)
+  (setq bibtex-autokey-year-length 4
+       bibtex-autokey-name-year-separator "-"
+       bibtex-autokey-year-title-separator "-"
+       bibtex-autokey-titleword-separator "-"
+       bibtex-autokey-titlewords 2
+       bibtex-autokey-titlewords-stretch 1
+       bibtex-autokey-titleword-length 5)
+  (define-key bibtex-mode-map (kbd "H-b") 'org-ref-bibtex-hydra/body)
+  (define-key org-mode-map (kbd "C-c ]") 'org-ref-insert-link)
+  (define-key org-mode-map (kbd "s-[") 'org-ref-insert-link-hydra/body)
+  (require 'org-ref-ivy)
+  (require 'org-ref-arxiv)
+  (require 'org-ref-scopus)
+  (require 'org-ref-wos))
+
+
+(use-package org-ref-ivy
+  :ensure nil
+  :load-path (lambda () (expand-file-name "org-ref" scimax-dir))
+  :init (setq org-ref-insert-link-function 'org-ref-insert-link-hydra/body
+             org-ref-insert-cite-function 'org-ref-cite-insert-ivy
+             org-ref-insert-label-function 'org-ref-insert-label-link
+             org-ref-insert-ref-function 'org-ref-insert-ref-link
+             org-ref-cite-onclick-function (lambda (_) (org-ref-citation-hydra/body))))
+#+END_SRC
+
+
+** Basic usage of org-ref
+
+*** Bibliography links
+index:bibliography index:bibliographystyle
+
+org-ref provides a bibliography link to specify which bibtex files to use in the document.
+
+1. A comma separated list of relative or absolute paths
+2. A comma separated list of files found in your BIBINPUTS environment variable
+
+This link is clickable; clicking on a filename will open the file. On export, the bibliography will appear at the position where the link is defined. Usually this link goes near the end of your document, e.g. like [[bibliography link][here]].
+
+There is also a nobibliography link, which is useful for specifying a bibliography file, but not listing a bibliography in the exported document.
+
+There is also a bibliographystyle link that specifies the style. This link does nothing but export to a LaTeX command. For LaTeX export a bibliography and bibliographystyle link is /required/ if you use bibtex. If you use biblatex see ref:sec-biblatex-users.
+
+These links support completion, so you can type C-c C-l, choose one of them, and it will help you complete the link.
+
+*** Citations <<citations>>
+
+index:cite
+
+org-ref uses the [[bibliography link]] to determine which bibtex files to get citations from, and falls back to the bibtex files defined in the variable ~bibtex-completion-bibliography~  if no bibliography link is found. Note that you *must* include a [[bibliography link]] in your document if you are exporting your document to pdf; ~bibtex-completion-bibliography~ is not used by the [[BibTeX users][LaTeX exporter]].
+
+For simple citation needs, org-ref is simple to use. At the point you want to insert a citation, yfield, you need to add it to the variable ~bibtex-completion-additional-search-fields~.
+
+If the cursor is on a citation key, you should see a tooltip that summarizes which citation it refers to. If you click on a key, you should get a hydra menu with some actions to choose, including opening the bibtex entry, opening/getting a pdf for the entry, searching the entry in Web of Science, etc...
+
+The default citation type is customizable (=org-ref-default-citation-link=), and set to "cite".
+
+See http://tug.ctan.org/macros/latex/contrib/natbib/natnotes.pdf for the cite commands supported in bibtex index:natbib, and http://ctan.mirrorcatalogs.com/macros/latex/contrib/biblatex/doc/biblatex.pdf for the commands supported in biblatex. index:biblatex.
+
+If the cursor is on a citation, or at the end of the citation, and you add another citation, it will be appended to the current citation.
+
+[[index:cite!shift]]
+Finally, if you do not like the order of the keys in a citation, you can put your cursor on a key and use shift-arrows (left or right) to move the key around. Alternatively, you can use shift-up or you can run the command ~org-ref-sort-citation-link~ which will sort the keys by year, oldest to newest.
+
+Alternatively, there is a keymap defined on cite links. By default this map is defined in the variable ~org-ref-cite-keymap~.
+
+There are navigation bindings that work on a cite link.
+
+| C-left  | Jump to previous key  |
+| C-right | Jump to next key      |
+| S-left  | move key to the left  |
+| S-right | move key to the right |
+
+You can also sort a cite link with multiple keys by year.
+
+| S-up | sort keys by ascending year |
+
+*** Pre/post text support
+
+org-ref has two versions of syntax. In version 2 there is very limited support for pre/post text in citations. You can get pre/post text by using a description in a cite link, with pre/post text separated by ::. For example, [[citep:Dominik201408][See page 20::, for example]]. I do not recommend you use this anymore.
+
+version 3 is much more capable, similar to the new org-cite syntax. The general syntax is:
+
+=Common prefix; prenote 1 &key1 postnote1; prenote n &keyn postnote n; Common suffix=
+
+The tradeoff is you have to prefix the keys with &, separate them by semicolons, and the links have to be bracketed if you put&p;are still a few caveats. Natbib only supports a single set of pre/post notes; some citation styles with biblatex support the full syntax. Not all cite types in LaTeX support pre/post text (e.g. cite, citenum do not support them), so be careful when you use them.
+
+
+*** labels
+    :PROPERTIES:
+    :CUSTOM_ID: sec-label-link
+    :END:
+index:label
+
+LaTeX uses labels to define places you can refer to. These can be labels in the captions of figures and tables, or labels in sections. We illustrate some uses here. You can use label links, but it is preferred to use name keywords or other native org label mechanisms.
+
+Here is a way to use a label link:
+
+#+caption: Another simple table. label:tab-ydata
+| y |
+| 4 |
+| 5 |
+
+This is the preferred way to label a table.
+
+#+name: tab-ydata-name
+#+caption: Another simple table. 
+| y |
+| 4 |
+| 5 |
+
+org-ref can help you insert unique labels with the command =org-ref-insert-label-link=. This will show you the existing labels, and insert your new label as a link. There is no default key-binding for this.
+
+*** ref links <<ref-links>>
+index:ref
+
+A ref link refers to a label of some sort. You can use the label in a name keyword, a LaTeX label, a CUSTOM_ID property, a label link (ref:sec-label-link), or a radio target.
+
+
+For example, you can refer to a table name, e.g. Table ref:table-1. You have to provide the context before the ref link, e.g. Table, Figure, Equation, Section, and so on.
+
+#+name: table-1
+#+caption: A simple table.
+| x |
+| 1 |
+| 2 |
+
+Or you can refer to an org-mode label as in Table ref:table-3.
+
+
+Note: You may need to set org-latex-prefer-user-labels to t if you refer to things by their "name" for the export to use the name you create.
+
+#+BEGIN_SRC emacs-lisp :results silent
+(setq org-latex-prefer-user-labels t)
+#+END_SRC
+
+
+#+caption: Another simple table. label:table-3
+| y |
+|---|
+| 3 |
+| 2 |
+
+You can also refer to an org-ref label link as in Table ref:tab-ydata.
+
+To help you insert ref links, use the "Org -> org-ref -> Insert ref" menu, or run the command = org-ref-insert-ref-link=.
+
+ref links are functional. If you put the cursor on a ref link, you will see a tooltip with some context of the corresponding label. If you click on the ref link, you will get a hydra to jump to it or change the ref type.
+
+You can make a ref link to a section with a CUSTOM_ID. For this to work, you should set ~org-latex-prefer-user-labels~ to t.
+
+Also note that "#+tblname:" and "#+label:" are deprecated in org-mode now, and "#+name:" is preferred.
+
+**** Miscellaneous ref links  label:sec-misc
+index:ref!pageref index:ref!nameref index:ref!eqref
+
+org-ref also provides these links:
+
+- pageref :: The page a label is on
+- nameref :: The name of a section a label is in
+- eqref :: Puts the equation number in parentheses
+- autoref :: A command from hyperref that automatically prefixes the reference number. (requires hyperref)
+- cref & Cref :: [[https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref?lang=en][cleveref – Intelligent cross-referencing]]
+- crefrange & Crefrange ::  [[https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref?lang=en][cleveref – Intelligent cross-referencing]]
+
+Note for eqref, you must use a LaTeX label like this:
+
+\begin{equation} \label{eq:1}
+e^x = 4
+\end{equation}
+
+or a named equation like this:
+
+#+name: eq-in-name
+\begin{equation}
+e^x = 4
+\end{equation}
+
+Then you can refer to Eq. eqref:eq:1 or ref:eq-in-name in your documents.
+
+Autoref works like this: autoref:table-3, autoref:sec-misc.
+
+The crefranges require two labels to define the range: Crefrange:table-1,table-3  and crefrange:table-1,table-3
+
+These links do not have much meaning outside of LaTeX.
+
+*** Some other links
+[[index:list of tables]] [[index:list of figures]]
+
+org-ref provides clickable links for a =[[list-of-tables:]]= and =[[list-of-figures:]]=. These links don't need a path, so you have to put them in brackets. These export as listoftables and listoffigures LaTeX commands, and they are clickable links that open a mini table of contents with links to the tables and figures in the buffer. There are also interactive commands for this: elisp:org-ref-list-of-tables and elisp:org-ref-list-of-figures.
+
+
+** Some basic org-ref utilities
+[[index:bibtex!clean entry]]
+
+The command ~org-ref~ does a lot for you automatically. It will check the buffer for errors, e.g. multiply-defined labels, bad citations or ref links, and provide easy access to a few commands through a side-window buffer.
+
+~org-ref-clean-bibtex-entry~ will sort the fields of a bibtex entry, clean it, and give it a bibtex key. By default, this function does a lot of cleaning:
+
+1. adds a comma if needed in the first line of the entry
+2. makes sure the DOI field is an actual DOI, and not a URL
+3. fixes bad year entries
+4. fixes empty pages
+5. escapes ampersand and percentage signs
+6. generate a key according to your setup
+7. runs your hook functions
+8. sorts the fields in the entry
+9. checks the entry for non-ascii characters
+10. converts article title to title case (note: see below to convert titles in other entry types)
+
+
+
+This function has a hook ~org-ref-clean-bibtex-entry-hook~, which you can add functions to of your own. Each function must work on a bibtex entry at point. (Note: the default behavior can be changed by removing the relevant functions from the initial value of ~org-ref-clean-bibtex-entry-hook~.)
+
+Here are the functions run on cleaning:
+
+#+BEGIN_SRC emacs-lisp :exports both
+org-ref-clean-bibtex-entry-hook
+#+END_SRC
+
+#+RESULTS:
+| org-ref-bibtex-format-url-if-doi | orcb-key-comma | org-ref-replace-nonascii | orcb-& | orcb-% | org-ref-title-case-article | orcb-clean-year | orcb-key | orcb-clean-doi | orcb-clean-pages | orcb-check-journal | org-ref-sort-bibtex-entry | orcb-fix-spacing |
+
+You can add your own function to the hook like this.
+
+#+BEGIN_SRC emacs-lisp
+(add-hook 'org-ref-clean-bibtex-entry-hook 'org-ref-replace-nonascii)
+#+END_SRC
+
+~org-ref-extract-bibtex-entries~ will create a bibtex file from the citations in the current buffer.
+
+** LaTeX export
+index:export!LaTeX
+
+All org-ref links are designed to export to the corresponding LaTeX commands for citations, labels, refs and the bibliography/bibliography style. Once you have the LaTeX file, you have to build it, using the appropriate latex and bibtex commands. You can have org-mode do this for you with a setup like:
+
+#+BEGIN_SRC emacs-lisp
+(setq org-latex-pdf-process
+      '("pdflatex -interaction nonstopmode -output-directory %o %f"
+       "bibtex %b"
+       "pdflatex -interaction nonstopmode -output-directory %o %f"
+       "pdflatex -interaction nonstopmode -output-directory %o %f"))
+#+END_SRC
+
+I have also had success with this setup:
+
+#+BEGIN_SRC emacs-lisp
+(setq org-latex-pdf-process (list "latexmk -shell-escape -bibtex -f -pdf %f"))
+#+END_SRC
+
+*** BibTeX users
+
+To have your citations compiled by BibTex, you *must* include a [[bibliography link]].  You will also need to include a [[bibliographystyle link]], unless you are using a LaTeX style that includes that for you.
+
+Note that some citation types may require additional LaTeX packages to be included in your export settings.
+
+Here are the natbib types (these will export in LaTeX with the unsrtnat style). These will export differently in author-year styles.
+
+Here are some examples of the pre/post note syntax for each natbib type. Not all of these make sense. For example the plain cite command does not take pre/post notes, even with natbib. If you use these a lot, you should use citet/citep. Not all of the commands take pre/post notes, e.g. citenum.
+
+
+- =[[citet:See &kitchin-2015-examp page 2]]= :: [[citet:See &kitchin-2015-examp page 2]]
+- =[[citet*:See &kitchin-2015-examp page 2]]= :: [[citet*:See &kitchin-2015-examp page 2]]
+- =[[citep:See &kitchin-2015-examp page 2]]= :: [[citep:See &kitchin-2015-examp page 2]]
+- =[[citep*:See &kitchin-2015-examp page 2]]= :: [[citep*:See &kitchin-2015-examp page 2]]
+- =[[citealt:See &kitchin-2015-examp page 2]]= :: [[citealt:See &kitchin-2015-examp page 2]]
+- =[[citealt*:See &kitchin-2015-examp page 2]]= :: [[citealt*:See &kitchin-2015-examp page 2]]
+- =[[citealp:See &kitchin-2015-examp page 2]]= :: [[citealp:See &kitchin-2015-examp page 2]]
+- =[[citealp*:See &kitchin-2015-examp page 2]]= :: [[citealp*:See &kitchin-2015-examp page 2]]
+- =[[citenum:&kitchin-2015-examp]]= :: [[citenum:&kitchin-2015-examp]]
+- =[[citetext:See &kitchin-2015-examp page 2]]= :: [[citetext:See &kitchin-2015-examp page 2]]
+- =[[citeauthor:See &kitchin-2015-examp page 2]]= :: [[citeauthor:See &kitchin-2015-examp page 2]]
+- =[[citeauthor*:See &kitchin-2015-examp page 2]]= :: [[citeauthor*:See &kitchin-2015-examp page 2]]
+- =[[citeyear:See &kitchin-2015-examp page 2]]= :: [[citeyear:See &kitchin-2015-examp page 2]]
+- =[[citeyearpar:See &kitchin-2015-examp page 2]]= :: [[citeyearpar:See &kitchin-2015-examp page 2]]
+- =[[Citet:See &kitchin-2015-examp page 2]]= :: [[Citet:See &kitchin-2015-examp page 2]]
+- =[[Citet*:See &kitchin-2015-examp page 2]]= :: [[Citet*:See &kitchin-2015-examp page 2]]
+- =[[Citep:See &kitchin-2015-examp page 2]]= :: [[Citep:See &kitchin-2015-examp page 2]]
+- =[[Citep*:See &kitchin-2015-examp page 2]]= :: [[Citep*:See &kitchin-2015-examp page 2]]
+- =[[Citealt:See &kitchin-2015-examp page 2]]= :: [[Citealt:See &kitchin-2015-examp page 2]]
+- =[[Citealt*:See &kitchin-2015-examp page 2]]= :: [[Citealt*:See &kitchin-2015-examp page 2]]
+- =[[Citealp:See &kitchin-2015-examp page 2]]= :: [[Citealp:See &kitchin-2015-examp page 2]]
+- =[[Citealp*:See &kitchin-2015-examp page 2]]= :: [[Citealp*:See &kitchin-2015-examp page 2]]
+- =[[Citeauthor:See &kitchin-2015-examp page 2]]= :: [[Citeauthor:See &kitchin-2015-examp page 2]]
+- =[[Citeauthor*:See &kitchin-2015-examp page 2]]= :: [[Citeauthor*:See &kitchin-2015-examp page 2]]
+
+
+*** biblatex users  <<sec-biblatex-users>>
+
+In the latex header you specify the style and bibliography file using addbibresource. Here is an example:
+
+#+BEGIN_EXAMPLE
+#+latex_header: \usepackage[citestyle=authoryear-icomp,bibstyle=authoryear, hyperref=true,backref=true,maxcitenames=3,url=true,backend=biber,natbib=true] {biblatex}
+#+latex_header: \addbibresource{tests/test-1.bib}
+#+END_EXAMPLE
+
+Sometimes it is necessary to tell bibtex what dialect you are using to support the different bibtex entries that are possible in biblatex. You can do it like this globally.
+
+#+BEGIN_SRC emacs-lisp
+(setq bibtex-dialect 'biblatex)
+#+END_SRC
+
+#+RESULTS:
+: biblatex
+
+Or like this in a bibtex file:
+#+BEGIN_EXAMPLE
+% -*- mode:bibtex; eval: (bibtex-set-dialect 'biblatex); -*-
+#+END_EXAMPLE
+
+Make sure you invoke biblatex in the org-latex-pdf-process. Here is one way to do it.
+
+#+BEGIN_SRC emacs-lisp
+(setq  org-latex-pdf-process '("latexmk -shell-escape -bibtex -pdf %f"))
+#+END_SRC
+
+Finally, where you want the bibliography put this empty link:
+
+#+BEGIN_EXAMPLE
+[[printbibliography:]]
+#+END_EXAMPLE
+
+The regular biblatex cite links support common pre/post notes, and multiple keys. These are:
+
+#+BEGIN_SRC emacs-lisp :exports both
+org-ref-biblatex-types
+#+END_SRC
+
+#+RESULTS:
+| Cite         |
+| parencite    |
+| Parencite    |
+| footcite     |
+| footcitetext |
+| textcite     |
+| Textcite     |
+| smartcite    |
+| Smartcite    |
+| cite*        |
+| parencite*   |
+| supercite    |
+| autocite     |
+| Autocite     |
+| autocite*    |
+| Autocite*    |
+| Citeauthor*  |
+| citetitle    |
+| citetitle*   |
+| citedate     |
+| citedate*    |
+| citeurl      |
+| fullcite     |
+| footfullcite |
+| notecite     |
+| Notecite     |
+| pnotecite    |
+| Pnotecite    |
+| fnotecite    |
+
+The multitype links support common pre/postnotes, and individual pre/post notes.  These are the multicite commands:
+
+#+BEGIN_SRC emacs-lisp :exports both
+org-ref-biblatex-multitypes
+#+END_SRC
+
+#+RESULTS:
+| cites         |
+| Cites         |
+| parencites    |
+| Parencites    |
+| footcites     |
+| footcitetexts |
+| smartcites    |
+| Smartcites    |
+| textcites     |
+| Textcites     |
+| supercites    |
+| autocites     |
+| Autocites     |
+
+
+Here is a full example. This only exports correctly in biblatex or with CSL, so I include it as an example here.
+
+#+BEGIN_EXAMPLE
+ [[cites:See; in &kitchin-2015-examp page 1;in &kitchin-2015-data-surfac-scien page 2;and in &kitchin-2016-autom-data page 3; for examples]]
+#+END_EXAMPLE
+
+
+** Other exports
+index:export!html index:export!ascii  index:export!latex  index:export!markdown  index:export!odt
+
+All other exports are handled by citeproc now. This is done by preprocessing in a dedicated exporter called org-ref. There is a new entry in the export menu
+
+| C-c C-e r h | html       |
+| C-c C-e r m | md         |
+| C-c C-e r a | ascii      |
+| C-c C-c r o | odt        |
+| C-c C-e r l | latex      |
+| C-c C-c r O | org buffer |
+
+
+* org-ref-export
+
+org-ref now supports the use of citeproc-el to export citations to non-LaTeX backends. See section [[sec-other-forms]] for more details. You can also use [[./org-ref-natbib-bbl-citeproc.el]]
+
+* org-refproc
+
+org-ref also supports exporting cross-references to other formats using [[./org-ref-refproc.el]]. This library also works by pre-processing a copy of the buffer to convert org-ref cross-reference links to org-syntax before exporting to the target backend. This even support cleveref style links with automatic prefixing and sorting. Compression of the references is not yet supported.
+
+See  [[./examples/refproc.org]] for a pretty comprehensive set of examples.
+
+* Other libraries in org-ref
+
+These are mostly functions for adding entries to bibtex files, modifying entries or for operating on bibtex files. Some new org-mode links are defined.
+
+** doi-utils
+index:doi
+
+This library adds two extremely useful tools for getting bibtex entries and pdf files of journal manuscripts. Add this to your emacs setup:
+#+BEGIN_SRC emacs-lisp
+(require 'doi-utils)
+#+END_SRC
+
+This provides two important commands:
+
+- ~doi-utils-add-bibtex-entry-from-doi~
+This will prompt you for a DOI, and a bibtex file, and then try to get the bibtex entry. Adds the entry to the bibtex file if successful. Automatically calls ~org-ref-clean-bibtex-entry~.
+
+- ~doi-utils-add-entry-from-crossref-query~
+This will prompt you for a query string, which is usually the title of an article, or a free-form text citation of an article. Searches using [[https://www.crossref.org/][Crossref.org]], then prompts in the minibuffer with a list of matching items, which you can choose from to insert a new bibtex entry into a bibtex file. Also calls ~org-ref-clean-bibtex-entry~.
+
+This library also redefines the org-mode doi link. Now, when you click on this link you will get a menu of options, e.g. to open a bibtex entry or a pdf if you have it, or to search the doi in some scientific search engines. Try it out  doi:10.1021/jp511426q.
+
+*** Bibtex key format
+
+The key is formatted according to the settings of bibtex-autokey-* variables. I use these settings. Look at the documentation of them to see how to get the format you want. The function (bibtex-generate-autokey) does this.
+
+The settings I use are:
+
+#+BEGIN_SRC emacs-lisp
+(setq bibtex-autokey-year-length 4
+       bibtex-autokey-name-year-separator "-"
+       bibtex-autokey-year-title-separator "-"
+       bibtex-autokey-titleword-separator "-"
+       bibtex-autokey-titlewords 2
+       bibtex-autokey-titlewords-stretch 1
+       bibtex-autokey-titleword-length 5)
+#+END_SRC
+
+*** Troubleshooting doi-utils
+
+Occasionally weird things happen with a DOI. The first thing you should check is if the json data for the DOI can be retrieved. You can do that at the command line, or in a sh block like this:
+
+#+BEGIN_SRC sh
+curl -LH "Accept: application/citeproc+json" "http://doi.org/10.1021/jp511426q"
+#+END_SRC
+
+If you do not get json data, doi-utils will not be able to generate the bibtex entry.
+
+Not all PDFs can be retrieved. doi-utils uses a set of functions to attempt this. Here is the list.
+
+#+BEGIN_SRC emacs-lisp :exports both
+doi-utils-pdf-url-functions
+#+END_SRC
+
+#+RESULTS:
+| aps-pdf-url                 |
+| science-pdf-url             |
+| nature-pdf-url              |
+| wiley-pdf-url               |
+| springer-chapter-pdf-url    |
+| springer-pdf-url            |
+| acs-pdf-url-1               |
+| acs-pdf-url-2               |
+| acs-pdf-url-3               |
+| iop-pdf-url                 |
+| jstor-pdf-url               |
+| aip-pdf-url                 |
+| science-direct-pdf-url      |
+| linkinghub-elsevier-pdf-url |
+| tandfonline-pdf-url         |
+| ecs-pdf-url                 |
+| ecst-pdf-url                |
+| rsc-pdf-url                 |
+| pnas-pdf-url                |
+| copernicus-pdf-url          |
+| sage-pdf-url                |
+| jneurosci-pdf-url           |
+| ieee-pdf-url                |
+| ieee2-pdf-url               |
+| ieee3-pdf-url               |
+| acm-pdf-url                 |
+| osa-pdf-url                 |
+| asme-biomechanical-pdf-url  |
+| siam-pdf-url                |
+| agu-pdf-url                 |
+| plos-pdf-url                |
+| generic-full-pdf-url        |
+
+You can check if a url for the PDF can be found like this. If you get a url, you can probably download a pdf.
+
+#+BEGIN_SRC emacs-lisp :exports both
+(doi-utils-get-pdf-url "10.1021/jp511426q")
+#+END_SRC
+
+#+RESULTS:
+: https://pubs.acs.org/doi/pdf/10.1021/jp511426q
+
+** org-ref-bibtex
+
+These are functions I use often in bibtex files.
+
+*** Generate new bibtex files with adapted journal names
+
+The variable ~org-ref-bibtex-journal-abbreviations~ contains a mapping of a short string to a full journal title, and an abbreviated journal title. We can use these to create new versions of a bibtex file with full or abbreviated journal titles. You can add new strings like this:
+
+#+BEGIN_SRC emacs-lisp
+(add-to-list 'org-ref-bibtex-journal-abbreviations
+  '("JIR" "Journal of Irreproducible Research" "J. Irrep. Res."))
+#+END_SRC
+
+- org-ref-bibtex-generate-longtitles :: Generate a bib file with long titles as
+     defined in `org-ref-bibtex-journal-abbreviations'
+- org-ref-bibtex-generate-shorttitles :: Generate a bib file with short titles as
+     defined in `org-ref-bibtex-journal-abbreviations'
+
+*** Modifying bibtex entries
+
+- org-ref-stringify-journal-name :: replace a journal name with a string in
+     `org-ref-bibtex-journal-abbreviations'
+- org-ref-set-journal-string :: in a bibtex entry run this to replace the journal
+     with a string selected interactively.
+
+- org-ref-title-case-article :: title case the title in an article entry.
+- org-ref-title-case :: title case the title for entries listed in `org-ref-title-case-types'.
+- org-ref-sentence-case-article :: sentence case the title in an article entry.
+
+- org-ref-replace-nonascii :: replace nonascii characters in a bibtex
+     entry. Replacements are in `org-ref-nonascii-latex-replacements'. This
+     function is a hook function in org-ref-clean-bibtex-entry.
+
+The non-ascii characters are looked up in a list of cons cells. You can add your own non-ascii replacements like this. Note backslashes must be escaped doubly, so one =\= is =\\\\= in the cons cell.
+
+#+BEGIN_SRC emacs-lisp
+(add-to-list 'org-ref-nonascii-latex-replacements
+  '("æ" . "{\\\\ae}"))
+#+END_SRC
+
+These functions are compatible with ~bibtex-map-entries~, so it is possible to conveniently apply them to all the entries in a file like this:
+
+#+BEGIN_SRC emacs-lisp
+(bibtex-map-entries 'org-ref-title-case-article)
+#+END_SRC
+
+*** Bibtex entry navigation
+
+- org-ref-bibtex-next-entry :: bound to M-n
+- org-ref-bibtex-previous-entry :: bound to M-p
+
+*** Hydra menus for bibtex entries and files
+
+- Functions to act on a bibtex entry or file
+  - org-ref-bibtex-hydra/body :: gives a hydra menu to a lot of useful functions
+       like opening the pdf, or the entry in a browser, or searching in a
+       variety of scientific search engines.
+  - org-ref-bibtex-new-entry/body :: gives a hydra menu to add new bibtex entries.
+  - org-ref-bibtex-file/body :: gives a hydra menu of actions for the bibtex file.
+
+You will want to bind the hydra menus to a key. You only need to bind the first one, as the second and third can be accessed from the first hydra.
+
+*** Formatted bibtex entry citations
+
+If you click on a citation link, there should be a menu option to copy a formatted citation, which will copy the citation string to the clipboard. This is a lightly formatted version using bibtex-completion.
+
+If you are on a bibtex entry, the `org-ref-bibtex-hydra/body' has an option to copy a formatted citation for the entry your cursor is in.
+
+
+** org-ref-wos
+This is a small utility for Web of Science/Knowledge (WOK) (http://apps.webofknowledge.com).
+
+#+BEGIN_SRC emacs-lisp
+(require 'org-ref-wos)
+#+END_SRC
+
+#+RESULTS:
+: org-ref-wos
+
+- wos :: Convenience function to open WOK in a browser.
+- wos-search :: Search WOK with the selected text or word at point
+
+There is also a new org-mode link that opens a search: [[wos-search:alloy and segregation]]
+
+** org-ref-scopus
+This is a small utility to interact with Scopus (http://www.scopus.com). Scopus is search engine for scientific literature. It is owned by Elsevier. You must have a license to use it (usually provided by your research institution).
+
+#+BEGIN_SRC emacs-lisp
+(require 'org-ref-scopus)
+#+END_SRC
+
+#+RESULTS:
+: org-ref-scopus
+
+Interactive functions:
+
+- scopus :: Convenience function to open Scopus in a browser.
+- scopus-basic-search :: Prompts for a query and opens it in a browser.
+- scopus-advanced-search :: Prompts for an advanced query and opens it in a browser.
+
+Some new links:
+Open a basic search in Scopus: [[scopus-search:alloy Au segregation]]
+
+Open an advanced search in Scopus: scopus-advanced-search:au-id(7004212771). See http://www.scopus.com/search/form.url?display=advanced&clear=t for details on the codes and syntax, and http://help.elsevier.com/app/answers/detail/a_id/2347/p/8150/incidents.c$portal_account_name/26389.
+
+A functional link to a document in Scopus by its "EID": eid:2-s2.0-72649092395. Clicking on this link will open a hydra menu to open the document in Scopus, find different kinds of related documents by keywords, authors or references, and to open a page in Scopus of citing documents.
+
+There is also a scopusid link for authors that will open their author page in Scopus: scopusid:7004212771
+
+** org-ref-isbn
+index:isbn
+
+#+BEGIN_SRC emacs-lisp
+(require 'org-ref-isbn)
+#+END_SRC
+
+#+RESULTS:
+: org-ref-isbn
+
+This library provides some functions to get bibtex entries for books from their ISBN.
+
+- isbn-to-bibtex
+- isbn-to-bibtex-lead
+
+It also provides some variables for customizing the bibtex entry.
+
+- org-ref-isbn-clean-bibtex-entry-hook
+- org-ref-isbn-exclude-fields
+- org-ref-isbn-field-name-replacements
+
+** org-ref-pubmed
+index:pubmed
+
+[[http://www.ncbi.nlm.nih.gov/pubmed][PubMed]] comprises more than 24 million citations for biomedical literature from MEDLINE, life science journals, and online books. Citations may include links to full-text content from PubMed Central and publisher web sites. This library provides some functions to initiate searches of PubMed from Emacs, and to link to PubMed content.
+
+#+BEGIN_SRC emacs-lisp
+(require 'org-ref-pubmed)
+#+END_SRC
+
+#+RESULTS:
+: org-ref-pubmed
+
+This library provides a number of new org-mode links to PubMed entries. See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details of these identifiers. These links open the page in PubMed for the identifier.
+
+pmcid:PMC3498956
+
+pmid:23162369
+
+nihmsid:NIHMS395714
+
+Also, you can retrieve a bibtex entry for a PMID with
+
+- ~pubmed-insert-bibtex-from-pmid~
+
+There are some utility functions that may be helpful.
+
+- pubmed :: Open [[http://www.ncbi.nlm.nih.gov/pubmed][PubMed]] in a browser
+- pubmed-advanced :: Open [[http://www.ncbi.nlm.nih.gov/pubmed/advanced][PubMed]] at advanced search page.
+- pubmed-simple-search :: Prompts you for a simple query and opens it in PubMed.
+
+There is a new org-mode link to PubMed searches: [[pubmed-search:alloy segregation]]
+
+** org-ref-arxiv
+index:arxiv
+
+This library provides an org-mode link to http://arxiv.org entries:  arxiv:cond-mat/0410285, and a function to get a bibtex entry and pdfs for arxiv entries:
+
+#+BEGIN_SRC emacs-lisp
+(require 'org-ref-arxiv)
+#+END_SRC
+
+#+RESULTS:
+: org-ref-arxiv
+
+- ~arxiv-add-bibtex-entry~
+- ~arxiv-get-pdf~
+
+** org-ref-sci-id
+
+index:orcid [[index:researcher id]]
+
+#+BEGIN_SRC emacs-lisp
+(require 'org-ref-sci-id)
+#+END_SRC
+
+#+RESULTS:
+: org-ref-sci-id
+
+This package just defines two new org-mode links for http://www.orcid.org, and http://www.researcherid.com. Here are two examples:
+
+orcid:0000-0003-2625-9232
+
+researcherid:A-2363-2010
+
+** x2bib
+index:bibtex!conversion
+
+#+BEGIN_SRC emacs-lisp
+(require 'x2bib)
+#+END_SRC
+
+#+RESULTS:
+: x2bib
+
+If you find you need to convert some bibliographies in some format into bibtex, this library is a starting point. This code is mostly wrappers around the command line utilities at http://sourceforge.net/p/bibutils/home/Bibutils. I thankfully have not had to use this often, but it is here when I need it again.
+
+- ris2bib :: Convert an RIS file to a bibtex file.
+- medxml2bib :: Convert PubMed XML to bibtex.
+- clean-entries :: Map over a converted bibtex file and "clean it".
+
+** org-ref-latex
+
+This provides some org-ref like capabilities in LaTeX files, e.g. the links are clickable with tooltips.
+
+** org-ref-pdf
+
+=org-ref-pdf= allows Emacs to get bibliography information from pdf files that contain a DOI. You must have =pdftotext= installed where Emacs can find it. This library is known to not work on Windows very well.
+
+** org-ref-url-utils
+
+Allows you to drag-n-drop a webpage from a browser onto a bibtex file to add a bibtex entry (as long as it is from a recognized publisher that org-ref knows about). This library does not work well on Windows.
+
+* Appendix
+
+** Other things org-ref supports
+
+*** org-completion
+index:completion index:link!completion
+
+Most org-ref links support org-mode completion. You can type ~C-c C-l~ to insert a link. You will get completion of the link type, type some characters and press tab. When you select the type, press tab to see the completion options. This works for the following link types:
+
+- bibliography
+- bibliographystyle
+- all cite types
+- ref
+
+*** Indexes
+index:index
+
+org-ref provides links to support making an index in LaTeX. (http://en.wikibooks.org/wiki/LaTeX/Indexing).
+
+- index :: creates an index entry.
+- printindex :: Generates a temporary index of clickable entries. Exports to the LaTeX command.
+
+You will need to use the makeidx package, and use this in the LaTeX header.
+
+#+begin_example
+#+LATEX_HEADER: \usepackage{makeidx}
+#+LATEX_HEADER: \makeindex
+#+end_example
+
+You will have to incorporate running makeindex into your PDF build command.
+
+This is not supported in anything but LaTeX export.
+
+*** Glossaries and acronyms
+index:glossary
+
+org-ref provides some support for glossary and acronym definitions.
+- gls :: a reference to a term
+- glspl :: plural reference to a term
+- Gsl :: capitalized reference to a term
+- Glspl :: capitalized plural reference to a term
+- gslink :: Link to alternative text in the link description.
+- glssymbol :: The symbol term
+- glsdesc :: The description of the term
+
+- ac :: a reference to an acronym
+- Ac :: capitalized reference to an acronym
+- acp :: a plural reference to an acronym
+- Acp :: capitalized plural reference to an acronym
+- acrshort :: Short version of the acronym
+- acrfull :: The full definition of the acronym
+- acrlong :: The full definition of the acronym with (abbrv).
+
+There are two useful commands:
+- org-ref-add-glossary-entry :: Add a new entry to the file
+- org-ref-add-acronym-entry :: Add a new acronym to the file
+
+Here is an example of glossary link for an [[gls:acronym][acronym]] and an actual [[acrshort:tla][TLA]]. Each link has a tool tip on it that shows up when you hover the mouse over it. These links will export as the LaTeX commands need by the glossaries package.
+
+You will need to incorporate running the command makeglossaries into your PDF build command. You also need use the glossaries LaTeX package.
+
+Here is a minimal working example of an org file that makes a glossary.
+
+#+BEGIN_SRC org
+,#+latex_header: \usepackage{glossaries}
+,#+latex_header: \makeglossaries
+
+,#+latex_header_extra: \newglossaryentry{computer}{name=computer,description={A machine}}
+,#+latex_header_extra: \newacronym{tla}{TLA}{Three letter acronym}
+
+A gls:computer is good for computing. Gls:computer is capitalized. We can also use a bunch of glspl:computer to make a cluster. Glspl:computer are the wave of the future. Don't forget what a ac:tla is.
+
+\printglossaries
+#+END_SRC
+
+This is not supported in anything but LaTeX export.
+
+If you have a lot of glossary entries and you want to have them in an external file, you can put them in a tex file, and then include them in the org file like this. Here the glossary entries are saved in a file in the same directory as glossary.tex. This should still work with the tooltips.
+
+#+BEGIN_EXAMPLE
+#+latex_header: \loadglsentries[main]{glossary}
+#+END_EXAMPLE
+
+Finally, you can define the glossary entries in org tables like this. They will be deleted before a LaTeX export.
+
+#+BEGIN_EXAMPLE
+,#+title: Test
+,#+latex_header: \usepackage{glossaries}
+,#+latex_header: \makeglossaries
+
+
+# This will not show in your export. It must be named glossary
+,#+name: glossary
+| label | name  | description   |
+|-------+-------+---------------|
+| tree  | Tree  | A woody plant |
+| shrub | Shrub | A woody bush  |
+
+Checkout how a gls:tree differs from a gls:shrub.
+
+
+,#+name: acronyms
+| Key  | Short | Long                           |
+|------+-------+--------------------------------|
+| mimo |       | multiple-input multiple output |
+| qos  | QoS   | quality-of-service             |
+| bb   | BB    | branch and bound               |
+
+
+First ac:bb. Second ac:bb. First ac:qos. Second ac:qos.
+
+# This is where your glossary and acronym entries will be put.
+,#+latex: \printglossaries
+#+END_EXAMPLE
+
+\glsaddall
+\printglossaries
+
+
+** Other forms of this document <<sec-other-forms>>
+
+*** Build notes
+
+Before building this file you need to require the following libraries so the links will be resolved.
+
+ #+BEGIN_SRC emacs-lisp :results silent
+(require 'org-ref-wos)
+(require 'org-ref-scopus)
+(require 'org-ref-pubmed)
+(require 'org-ref-sci-id)
+ #+END_SRC
+
+
+*** PDF
+
+You may want to build a pdf of this file. Here is an emacs-lisp block that will create and open the PDF.
+
+ #+BEGIN_SRC emacs-lisp :results silent
+(let ((org-export-with-broken-links t)
+      (org-latex-pdf-process
+       '("pdflatex -interaction nonstopmode -shell-escape -output-directory %o %f"
+        "bibtex %b"
+        "makeindex %b"
+        "pdflatex -interaction nonstopmode -shell-escape -output-directory %o %f"
+        "pdflatex -interaction nonstopmode -shell-escape -output-directory %o %f")))
+  (org-open-file (org-latex-export-to-pdf)))
+ #+END_SRC
+
+*** Best practices for other formats
+
+org-ref relies on bibtex entries for bibliographies. Bibtex was designed for LaTeX export, and it is common to have LaTeX markup in the BibTeX entries to get the highest quality output in LaTeX (e.g. properly formatted equations, chemical formulas, accents in author names, etc.). This markup will usually not export correctly to other formats without some translation efforts.
+
+It is not generally possible to have a single BibTeX file that easily, and correctly exports to all backends. If perfection in your exports is needed, you need separate bibtex files for each backend, where the markup is intended for that backend. For example you might have "\ce{H2O}" in an entry intended for LaTeX export, but "H<sub>2</sub>O" in an entry for HTML export, and "H_{2}O" for org export.
+
+Maybe you could try an approach where your bibtex file is only org-mode, and then generate a bibtex file by "export" so that at export time it would be in the right format. I haven't tried that yet. It sounds complicated.
+
+
+*** Other formats using CSL
+
+org-ref supports export to other formats using [[https://github.com/andras-simonyi/citeproc-el][citeproc]] in a preprocessing filter. This works by modifying a copy of your org-file during the export to replace the citation and bibliography links with formatted text using the CSL. These functions are defined in [[./org-ref-export.el]]. You set the style with `org-ref-csl-default-style' or with a =CSL-KEYWORD=. See  [[./examples/basic-csl.org]] for an example.
+
+org-ref provides a new exporter for convenience with the following export options: After C-c C-e r
+
+| a | to ascii and open      |                                                                 |
+| h | to html and open       |                                                                 |
+| l | to latex and open      | all cite links and bibliography are exported to latex           |
+| o | to OpenOffice and open |                                                                 |
+| O | to org buffer          | only goes to a buffer so you don't overwrite the current buffer |
+| e | to email               |                                                                 |
+
+These links will run export commands to get this document in different formats. It is worth noting that if your bibtex entries use LaTeX markup (e.g. subscripts, superscripts, chemical equations, etc.) in them, it will probably not render faithfully in the alternative backend. It is in general difficult to have a single format in bibtex that correctly renders in all backends. I don't know of a great solution for this, since LaTeX and CSL use different citation processors.
+
+[[elisp:(org-ref-export-to-html)]]
+
+[[elisp:(org-ref-export-to-latex)]]
+
+[[elisp:(org-ref-export-to-ascii)]]
+
+[[elisp:(org-ref-export-to-odt)]]
+
+[[elisp:(org-ref-export-to-message)]] export to body of an ascii email message
+
+Some basic styles are provide in [[./citeproc/csl-locales/]], and a US-English locale in [[./citeproc/csl-locales/]].
+
+#+BEGIN_SRC sh :exports both
+ls citeproc/csl-styles
+#+END_SRC
+
+#+RESULTS:
+| apa-5th-edition.csl                  |
+| apa-numeric-superscript-brackets.csl |
+| chicago-author-date-16th-edition.csl |
+| elsevier-harvard.csl                 |
+| elsevier-with-titles.csl             |
+
+
+An alternative to this exporter is to use an  `org-export-before-parsing-hook' to do the pre-processing like this. This should work for most backends with the usual export keys and commands.
+
+#+BEGIN_SRC emacs-lisp
+(add-hook 'org-export-before-parsing-hook 'org-ref-csl-preprocess-buffer)
+#+END_SRC
+
+Here is an example to generate a docx file from this document!
+
+#+BEGIN_SRC emacs-lisp
+(require 'ox-pandoc)
+(let ((org-export-before-parsing-hook '(org-ref-csl-preprocess-buffer)))
+  (org-open-file (plist-get (org-pandoc-export-to-docx) 'output-file) 'system))
+#+END_SRC
+
+#+RESULTS:
+
+*** Other formats without using CSL
+
+An alternative approach to using citeproc is to use LaTeX/bibtex more directly. [[./org-ref-natbib-bbl-citeproc.el]] defines another pre-processor that uses LaTeX and natbib/bibtex to create citations and bibliographies. The bbl file is still intended for consumption by LaTeX. org-ref does some light processing to remove LaTeX artifacts, but it is not complete so some artifacts may still appear in your export (e.g. LaTeX commands that are not handled, some backslashes, etc).
+
+Here is an example how to export to HTML with the bbl file produced by LaTeX and bibtex. Your org-file must compile without error once with LaTeX and once with bibtex.
+
+#+BEGIN_SRC emacs-lisp :exports none :results silent
+(let ((org-export-before-parsing-hook '(org-ref-bbl-preprocess)))
+  (org-open-file (org-html-export-to-html)))
+#+END_SRC
+
+The natbib options for [super, numbers, authoryear] are supported, and citation options [square, round, angle, curly], and separators [comma, colon, semicolon] are supported. You can also use [sort, compress, sort&compress] for numeric styles. The longnamesfirst option is not currently supported.
+
+The bibliography entries are formatted from the bbl file. See these examples [[./examples/bbl-super.org]], [[./examples/bbl-numbers.org]] and [[./examples/bbl-authoryear.org]].
+
+* Index
+
+This is a functional link that will open a buffer of clickable index entries:
+# This eliminates the duplicate Index section name
+@@latex:\renewcommand{\indexname}{}@@
+[[printindex:]]
+
+* References
+
+<<bibliographystyle link>>
+bibliographystyle:unsrtnat
+
+<<bibliography link>>
+bibliography:org-ref.bib
diff --git a/elpa/org-ref-20230507.1420/x2bib.el b/elpa/org-ref-20230507.1420/x2bib.el
new file mode 100644 (file)
index 0000000..52c6ffe
--- /dev/null
@@ -0,0 +1,145 @@
+;;; x2bib.el --- Bibliography conversion to Bibtex
+
+;;; Header:
+
+;;; Commentary:
+
+;; This module is more for my convenience to convert bibliography files to
+;; bibtex. This can be done at the command line, for example, but I want to do
+;; it in Emacs. There are a few scenarios where this happens.
+
+;; 1. Someone sends me a non-Bibtex file (Endnote, etc...)
+;; 2. From some online search I select many references and there is no export to
+;; Bibtex option, e.g. from Web of Science.
+
+;; This code is mostly wrappers around the command line utilities at
+;; http://sourceforge.net/p/bibutils/home/Bibutils.
+;;
+;; on a Mac: brew install bibutils
+
+;; Here are the commands that are available.
+
+;; bib2xml       - convert BibTeX to MODS XML intermediate
+;; biblatex2xml  - convert BibLaTeX to MODS XML intermediate
+;; copac2xml     - convert COPAC format references to MODS XML intermediate
+;; end2xml       - convert EndNote (Refer format) to MODS XML intermediate
+;; endx2xml      - convert EndNote XML to MODS XML intermediate
+;; isi2xml       - convert ISI web of science to MODS XML intermediate
+;; med2xml       - convert Pubmed XML references to MODS XML intermediate
+;; modsclean     - a MODS to MODS converter for testing puposes mostly
+;; ris2xml       - convert RIS format to MODS XML intermediate
+;; xml2ads       - convert MODS XML intermediate into Smithsonian Astrophysical
+;;                 Observatory (SAO)/National Aeronautics and Space
+;;                 Administration (NASA) Astrophyics Data System or ADS
+;;                 reference format (converter submitted by Richard Mathar)
+;;                 xml2bib - convert MODS XML intermediate into BibTeX
+;; xml2end       - convert MODS XML intermediate into format for EndNote
+;; xml2isi       - convert MODS XML intermediate to ISI format
+;; xml2ris       - convert MODS XML intermediate into RIS format
+;; xml2wordbib   - convert MODS XML intermediate into Word 2007 bibliography format
+
+
+;;; Code:
+(require 'bibtex)
+(require 'org-ref-core)
+
+;;* RIS to bibtex
+
+;; RIS can be pretty easily exported from Endnote. Here is a function to read an
+;; RIS file and convert it to bibtex which is inserted at point. Note that there
+;; is often other output from the commands. We try to comment them out here, but
+;; you should probably inspect the entries, and do other bibtex file compliance
+;; checks.
+
+;;;###autoload
+(defun ris2bib (risfile &optional verbose)
+  "Convert RISFILE to bibtex and insert at point.
+Without a prefix arg, stderr is diverted.
+If VERBOSE is non-nil show command output.
+If the region is active, assume it is a ris entry
+and convert it to bib format in place."
+  (interactive
+   (list (if (not (region-active-p))
+             (read-file-name "RIS file:"))
+         (prefix-numeric-value current-prefix-arg)))
+  (let ((result
+         (if risfile
+             (shell-command-to-string
+              (concat
+               (format
+                "ris2xml %s | xml2bib -w"
+                risfile)
+               (unless verbose " 2> /dev/null")))
+           (progn
+             (shell-command-on-region (region-beginning) (region-end)
+                                      "ris2xml 2> /dev/null | xml2bib -w 2> /dev/null" nil
+                                      t)
+                  nil))))
+    ;; make some lines into comments.
+    (when result
+      (setq result (replace-regexp-in-string
+                    "^xml2bib:"
+                    "% xml2bib:"
+                    result))
+      (setq result (replace-regexp-in-string
+                    "^ris2xml:"
+                    "% ris2xml"
+                    result))
+      (setq result (replace-regexp-in-string
+                    "^ Defaulting"
+                    "% Defaulting"
+                    result))
+      (insert result))))
+
+;;* Pubmed XML to bibtex
+
+;; In http://www.ncbi.nlm.nih.gov/pubmed/ you can select entries, and then send
+;; them to a file. If you choose Pubmed XML as the format, then you can use this
+;; function to convert it to bibtex.
+
+;;;###autoload
+(defun medxml2bib (medfile &optional verbose)
+  "Convert MEDFILE (in Pubmed xml) to bibtex and insert at point.
+Without a prefix arg, stderr is diverted.
+Display output if VERBOSE is non-nil."
+  (interactive
+   (list (read-file-name "MED file:")
+         (prefix-numeric-value current-prefix-arg)))
+  (let ((result (shell-command-to-string
+                 (concat
+                  (format
+                   "med2xml %s | xml2bib -w"
+                   medfile)
+                  (unless verbose " 2> /dev/null")))))
+    ;; make some lines into comments.
+    (setq result (replace-regexp-in-string
+                  "^xml2bib:"
+                  "% xml2bib:"
+                  result))
+    (setq result (replace-regexp-in-string
+                  "^med2xml:"
+                  "% med2xml"
+                  result))
+    (setq result (replace-regexp-in-string
+                  "^   Defaulting"
+                  "%   Defaulting"
+                  result))
+    (insert result)))
+
+;;* Clean up all the entries
+
+;; Finally, after you put the new entries in, you probably need to do some clean
+;; up actions. This little function does that.
+
+;;;###autoload
+(defun clean-entries ()
+  "Map over bibtex entries and clean them."
+  (interactive)
+  (bibtex-map-entries
+   (lambda (a b c)
+     (ignore-errors
+       (org-ref-clean-bibtex-entry)))))
+
+(provide 'x2bib)
+
+;;; x2bib.el ends here