]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
update biblio
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Thu, 23 Nov 2023 18:30:47 +0000 (19:30 +0100)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Thu, 23 Nov 2023 18:30:47 +0000 (19:30 +0100)
Signed-off-by: Andreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
28 files changed:
elpa/biblio-20190624.1408/biblio-arxiv.el [deleted file]
elpa/biblio-20190624.1408/biblio-autoloads.el [deleted file]
elpa/biblio-20190624.1408/biblio-crossref.el [deleted file]
elpa/biblio-20190624.1408/biblio-dblp.el [deleted file]
elpa/biblio-20190624.1408/biblio-dissemin.el [deleted file]
elpa/biblio-20190624.1408/biblio-doi.el [deleted file]
elpa/biblio-20190624.1408/biblio-download.el [deleted file]
elpa/biblio-20190624.1408/biblio-hal.el [deleted file]
elpa/biblio-20190624.1408/biblio-ieee.el [deleted file]
elpa/biblio-20190624.1408/biblio-pkg.el [deleted file]
elpa/biblio-20190624.1408/biblio.el [deleted file]
elpa/biblio-20230202.1721/biblio-arxiv.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-autoloads.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-crossref.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-dblp.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-dissemin.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-doi.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-download.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-hal.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-ieee.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio-pkg.el [new file with mode: 0644]
elpa/biblio-20230202.1721/biblio.el [new file with mode: 0644]
elpa/biblio-core-20190624.1408/biblio-core-autoloads.el [deleted file]
elpa/biblio-core-20190624.1408/biblio-core-pkg.el [deleted file]
elpa/biblio-core-20190624.1408/biblio-core.el [deleted file]
elpa/biblio-core-20230202.1721/biblio-core-autoloads.el [new file with mode: 0644]
elpa/biblio-core-20230202.1721/biblio-core-pkg.el [new file with mode: 0644]
elpa/biblio-core-20230202.1721/biblio-core.el [new file with mode: 0644]

diff --git a/elpa/biblio-20190624.1408/biblio-arxiv.el b/elpa/biblio-20190624.1408/biblio-arxiv.el
deleted file mode 100644 (file)
index e5498a2..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-;;; biblio-arxiv.el --- Lookup and import bibliographic entries from arXiv -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Lookup and download bibliographic records from arXiv using `arxiv-lookup'.
-;; When a DOI is available, the metadata is fetched from the DOI's issuer;
-;; otherwise, this package uses arXiv's metadata to generate an entry.
-;;
-;; This file implements a backend for the for the `biblio' package (which see for more
-;; documentation).
-
-;;; Code:
-
-(require 'biblio-core)
-(require 'biblio-doi)
-(require 'timezone)
-
-(defgroup biblio-arxiv nil
-  "arXiv support in biblio.el"
-  :group 'biblio)
-
-(defcustom biblio-arxiv-bibtex-header "online"
-  "Which header to use for BibTeX entries generated from arXiv metadata."
-  :group 'biblio
-  :type 'string)
-
-(defun biblio-arxiv--build-bibtex-1 (metadata)
-  "Create an unformated BibTeX record for METADATA."
-  (let-alist metadata
-    (format "@%s{NO_KEY,
-author = {%s},
-title = {{%s}},
-year = {%s},
-archivePrefix = {arXiv},
-eprint = {%s},
-primaryClass = {%s}}"
-            biblio-arxiv-bibtex-header
-            (biblio-join-1 " AND " .authors)
-            .title .year .identifier .category)))
-
-(defun biblio-arxiv--build-bibtex (metadata)
-  "Create a BibTeX record for METADATA."
-  (let-alist metadata
-    (message "Auto-generating a BibTeX entry for %S." .id)
-    (biblio-format-bibtex (biblio-arxiv--build-bibtex-1 metadata) t)))
-
-(defun biblio-arxiv--forward-bibtex (metadata forward-to)
-  "Forward BibTeX for arXiv entry METADATA to FORWARD-TO."
-  (let-alist metadata
-    (if (seq-empty-p .doi)
-        (funcall forward-to (biblio-arxiv--build-bibtex metadata))
-      (biblio-doi-forward-bibtex .doi forward-to))))
-
-(defun biblio-arxiv--format-author (author)
-  "Format AUTHOR for arXiv search results."
-  (when (eq (car-safe author) 'author)
-    (let-alist (cdr author)
-      (biblio-join " "
-        (cadr .name)
-        (biblio-parenthesize (cadr .arxiv:affiliation))))))
-
-(defun biblio-arxiv--extract-id (id)
-  "Extract identifier from ID, the URL of an arXiv abstract."
-  (replace-regexp-in-string "https?://arxiv.org/abs/" "" id))
-
-(defun biblio-arxiv--pdf-url (id)
-  "Extract PDF url from ID of an arXiv entry."
-  (when id
-    (concat "http://arxiv.org/pdf/" id)))
-
-(defun biblio-arxiv--extract-interesting-fields (entry)
-  "Prepare an arXiv search result ENTRY for display."
-  (let-alist entry
-    (let ((id (biblio-arxiv--extract-id (cadr .id))))
-      (list (cons 'doi (cadr .arxiv:doi))
-            (cons 'identifier id)
-            (cons 'year (aref (timezone-parse-date (cadr .published)) 0))
-            (cons 'title (cadr .title))
-            (cons 'authors (seq-map #'biblio-arxiv--format-author entry))
-            (cons 'container (cadr .arxiv:journal_ref))
-            (cons 'category
-                  (biblio-alist-get 'term (car .arxiv:primary_category)))
-            (cons 'references (list (cadr .arxiv:doi) id))
-            (cons 'type "eprint")
-            (cons 'url (biblio-alist-get 'href (car .link)))
-            (cons 'direct-url (biblio-arxiv--pdf-url id))))))
-
-(defun biblio-arxiv--entryp (entry)
-  "Check if ENTRY is an arXiv entry."
-  (eq (car-safe entry) 'entry))
-
-(defun biblio-arxiv--parse-search-results ()
-  "Extract search results from arXiv response."
-  (biblio-decode-url-buffer 'utf-8)
-  (let-alist (xml-parse-region (point-min) (point-max))
-    (seq-map #'biblio-arxiv--extract-interesting-fields
-             (seq-filter #'biblio-arxiv--entryp .feed))))
-
-(defun biblio-arxiv--url (query)
-  "Create an arXiv url to look up QUERY."
-  (format "http://export.arxiv.org/api/query?search_query=%s"
-          (url-encode-url query)))
-
-;;;###autoload
-(defun biblio-arxiv-backend (command &optional arg &rest more)
-  "A arXiv backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'."
-  (pcase command
-    (`name "arXiv")
-    (`prompt "arXiv query: ")
-    (`url (biblio-arxiv--url arg))
-    (`parse-buffer (biblio-arxiv--parse-search-results))
-    (`forward-bibtex (biblio-arxiv--forward-bibtex arg (car more)))
-    (`register (add-to-list 'biblio-backends #'biblio-arxiv-backend))))
-
-;;;###autoload
-(add-hook 'biblio-init-hook #'biblio-arxiv-backend)
-
-;;;###autoload
-(defun biblio-arxiv-lookup (&optional query)
-  "Start an arXiv search for QUERY, prompting if needed."
-  (interactive)
-  (biblio-lookup #'biblio-arxiv-backend query))
-
-;;;###autoload
-(defalias 'arxiv-lookup 'biblio-arxiv-lookup)
-
-(provide 'biblio-arxiv)
-;;; biblio-arxiv.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-autoloads.el b/elpa/biblio-20190624.1408/biblio-autoloads.el
deleted file mode 100644 (file)
index 1ebfebc..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-;;; biblio-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-
-(add-to-list 'load-path (directory-file-name
-                         (or (file-name-directory #$) (car load-path))))
-
-\f
-;;;### (autoloads nil "biblio-arxiv" "biblio-arxiv.el" (0 0 0 0))
-;;; Generated autoloads from biblio-arxiv.el
-
-(autoload 'biblio-arxiv-backend "biblio-arxiv" "\
-A arXiv backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'.
-
-\(fn COMMAND &optional ARG &rest MORE)" nil nil)
-
-(add-hook 'biblio-init-hook #'biblio-arxiv-backend)
-
-(autoload 'biblio-arxiv-lookup "biblio-arxiv" "\
-Start an arXiv search for QUERY, prompting if needed.
-
-\(fn &optional QUERY)" t nil)
-
-(defalias 'arxiv-lookup 'biblio-arxiv-lookup)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-arxiv" '("biblio-arxiv-")))
-
-;;;***
-\f
-;;;### (autoloads nil "biblio-crossref" "biblio-crossref.el" (0 0
-;;;;;;  0 0))
-;;; Generated autoloads from biblio-crossref.el
-
-(autoload 'biblio-crossref-backend "biblio-crossref" "\
-A CrossRef backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'.
-
-\(fn COMMAND &optional ARG &rest MORE)" nil nil)
-
-(add-hook 'biblio-init-hook #'biblio-crossref-backend)
-
-(autoload 'biblio-crossref-lookup "biblio-crossref" "\
-Start a CrossRef search for QUERY, prompting if needed.
-
-\(fn &optional QUERY)" t nil)
-
-(defalias 'crossref-lookup 'biblio-crossref-lookup)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-crossref" '("biblio-crossref-")))
-
-;;;***
-\f
-;;;### (autoloads nil "biblio-dblp" "biblio-dblp.el" (0 0 0 0))
-;;; Generated autoloads from biblio-dblp.el
-
-(autoload 'biblio-dblp-backend "biblio-dblp" "\
-A DBLP backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'.
-
-\(fn COMMAND &optional ARG &rest MORE)" nil nil)
-
-(add-hook 'biblio-init-hook #'biblio-dblp-backend)
-
-(autoload 'biblio-dblp-lookup "biblio-dblp" "\
-Start a DBLP search for QUERY, prompting if needed.
-
-\(fn &optional QUERY)" t nil)
-
-(defalias 'dblp-lookup 'biblio-dblp-lookup)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-dblp" '("biblio-dblp--")))
-
-;;;***
-\f
-;;;### (autoloads nil "biblio-dissemin" "biblio-dissemin.el" (0 0
-;;;;;;  0 0))
-;;; Generated autoloads from biblio-dissemin.el
-
-(autoload 'biblio-dissemin-lookup "biblio-dissemin" "\
-Retrieve a record by DOI from Dissemin, and display it.
-Interactively, or if CLEANUP is non-nil, pass DOI through
-`biblio-cleanup-doi'.
-
-\(fn DOI &optional CLEANUP)" t nil)
-
-(defalias 'dissemin-lookup 'biblio-dissemin-lookup)
-
-(autoload 'biblio-dissemin--register-action "biblio-dissemin" "\
-Add Dissemin to list of `biblio-selection-mode' actions.
-
-\(fn)" nil nil)
-
-(add-hook 'biblio-selection-mode-hook #'biblio-dissemin--register-action)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-dissemin" '("biblio-dissemin--")))
-
-;;;***
-\f
-;;;### (autoloads nil "biblio-doi" "biblio-doi.el" (0 0 0 0))
-;;; Generated autoloads from biblio-doi.el
-
-(autoload 'doi-insert-bibtex "biblio-doi" "\
-Insert BibTeX entry matching DOI.
-
-\(fn DOI)" t nil)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-doi" '("biblio-doi-")))
-
-;;;***
-\f
-;;;### (autoloads nil "biblio-download" "biblio-download.el" (0 0
-;;;;;;  0 0))
-;;; Generated autoloads from biblio-download.el
-
-(autoload 'biblio-download--register-action "biblio-download" "\
-Add download to list of `biblio-selection-mode' actions.
-
-\(fn)" nil nil)
-
-(add-hook 'biblio-selection-mode-hook #'biblio-download--register-action)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-download" '("biblio-download-")))
-
-;;;***
-\f
-;;;### (autoloads nil "biblio-hal" "biblio-hal.el" (0 0 0 0))
-;;; Generated autoloads from biblio-hal.el
-
-(autoload 'biblio-hal-backend "biblio-hal" "\
-A HAL backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'.
-
-\(fn COMMAND &optional ARG &rest MORE)" nil nil)
-
-(add-hook 'biblio-init-hook #'biblio-hal-backend)
-
-(autoload 'biblio-hal-lookup "biblio-hal" "\
-Start a HAL search for QUERY, prompting if needed.
-
-\(fn &optional QUERY)" t nil)
-
-(defalias 'hal-lookup 'biblio-hal-lookup)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-hal" '("biblio-hal--")))
-
-;;;***
-\f
-;;;### (autoloads nil "biblio-ieee" "biblio-ieee.el" (0 0 0 0))
-;;; Generated autoloads from biblio-ieee.el
-
-(autoload 'biblio-ieee-backend "biblio-ieee" "\
-A IEEE Xplore backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'.
-
-\(fn COMMAND &optional ARG &rest MORE)" nil nil)
-
-(add-hook 'biblio-init-hook #'biblio-ieee-backend)
-
-(autoload 'biblio-ieee-lookup "biblio-ieee" "\
-Start a IEEE search for QUERY, prompting if needed.
-
-\(fn &optional QUERY)" t nil)
-
-(defalias 'ieee-lookup 'biblio-ieee-lookup)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-ieee" '("biblio-ieee--")))
-
-;;;***
-\f
-;;;### (autoloads nil nil ("biblio-pkg.el" "biblio.el") (0 0 0 0))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; coding: utf-8
-;; End:
-;;; biblio-autoloads.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-crossref.el b/elpa/biblio-20190624.1408/biblio-crossref.el
deleted file mode 100644 (file)
index 8ad5778..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-;;; biblio-crossref.el --- Lookup and import bibliographic entries from CrossRef -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Lookup and download bibliographic records from CrossRef (a very nicely
-;; curated metadata engine) using `crossref-lookup'.
-;;
-;; This file implements a backend for the `biblio' package (which see for more
-;; documentation).
-
-;;; Code:
-
-(require 'biblio-core)
-(require 'biblio-doi)
-
-(defcustom biblio-crossref-user-email-address nil
-  "Email address to include in CrossRef queries, or nil.
-CrossRef gives priority to queries that include an email address.
-See URL `https://github.com/CrossRef/rest-api-doc#etiquette' for
-more details."
-  :group 'biblio
-  :type '(choice (const :tag "Do not include an email address." nil)
-                 (string :tag "Include an email address.")))
-
-(defun biblio-crossref--forward-bibtex (metadata forward-to)
-  "Forward BibTeX for CrossRef entry METADATA to FORWARD-TO."
-  (biblio-doi-forward-bibtex (biblio-alist-get 'doi metadata) forward-to))
-
-(defun biblio-crossref--format-affiliation (affiliation)
-  "Format AFFILIATION for CrossRef search results."
-  (mapconcat (apply-partially #'biblio-alist-get 'name) affiliation ", "))
-
-(defun biblio-crossref--format-author (author)
-  "Format AUTHOR for CrossRef search results."
-  (let-alist author
-    (biblio-join " "
-                 .given .family (biblio-parenthesize (biblio-crossref--format-affiliation .affiliation)))))
-
-(defun biblio-crossref--extract-interesting-fields (item)
-  "Prepare a CrossRef search result ITEM for display."
-  (let-alist item
-    (list (cons 'doi .DOI)
-          (cons 'year (let ((year (aref (aref .issued.date-parts 0) 0)))
-                        (and (numberp year) (number-to-string year))))
-          (cons 'title (biblio-join " "
-                         (biblio-join-1 ", " .title)
-                         (biblio-parenthesize (biblio-join-1 ", " .subtitle))))
-          (cons 'authors (seq-map #'biblio-crossref--format-author .author))
-          (cons 'publisher .publisher)
-          (cons 'container .container-title)
-          (cons 'references (seq-concatenate 'list (list .DOI) .isbn))
-          (cons 'type .type)
-          (cons 'url .URL))))
-
-(defun biblio-crossref--parse-search-results ()
-  "Extract search results from CrossRef response."
-  (biblio-decode-url-buffer 'utf-8)
-  (let-alist (json-read)
-    (unless (string= .status "ok")
-      (display-warning 'biblio-crossref "CrossRef query failed"))
-    (seq-map #'biblio-crossref--extract-interesting-fields .message.items)))
-
-(defun biblio-crossref--url (query)
-  "Create a CrossRef url to look up QUERY."
-  (format "http://api.crossref.org/works?query=%s%s"
-          (url-encode-url query)
-          (if biblio-crossref-user-email-address
-              (format "&mailto=%s" (url-encode-url biblio-crossref-user-email-address)) "")))
-
-;;;###autoload
-(defun biblio-crossref-backend (command &optional arg &rest more)
-  "A CrossRef backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'."
-  (pcase command
-    (`name "CrossRef")
-    (`prompt "CrossRef query: ")
-    (`url (biblio-crossref--url arg))
-    (`parse-buffer (biblio-crossref--parse-search-results))
-    (`forward-bibtex (biblio-crossref--forward-bibtex arg (car more)))
-    (`register (add-to-list 'biblio-backends #'biblio-crossref-backend))))
-
-;;;###autoload
-(add-hook 'biblio-init-hook #'biblio-crossref-backend)
-
-;;;###autoload
-(defun biblio-crossref-lookup (&optional query)
-  "Start a CrossRef search for QUERY, prompting if needed."
-  (interactive)
-  (biblio-lookup #'biblio-crossref-backend query))
-
-;;;###autoload
-(defalias 'crossref-lookup 'biblio-crossref-lookup)
-
-(provide 'biblio-crossref)
-;;; biblio-crossref.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-dblp.el b/elpa/biblio-20190624.1408/biblio-dblp.el
deleted file mode 100644 (file)
index 1e23c07..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-;;; biblio-dblp.el --- Lookup and import bibliographic entries from DBLP -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Lookup and download bibliographic records from DBLP (a great source of
-;; references for Computer Science papers) using `dblp-lookup'.
-;;
-;; This file implements a backend for the for the `biblio' package (which see for more
-;; documentation).
-
-;;; Code:
-
-(require 'biblio-core)
-
-(defun biblio-dblp--forward-bibtex (metadata forward-to)
-  "Forward BibTeX for DBLP entry METADATA to FORWARD-TO."
-  (let* ((source-url (biblio-alist-get 'url metadata))
-         (url (replace-regexp-in-string "/rec/" "/rec/bib2/" source-url t t)))
-    (biblio-url-retrieve url (biblio-generic-url-callback
-                              (lambda () ;; No allowed errors, so no arguments
-                                "Parse DBLP BibTeX results."
-                                (funcall forward-to
-                                         (biblio-format-bibtex
-                                          (biblio-response-as-utf-8))))))))
-
-(defun biblio-dblp--extract-interesting-fields (item)
-  "Prepare a DBLP search result ITEM for display."
-  (let-alist (biblio-alist-get 'info item)
-    (list (cons 'year (cadr .year))
-          (cons 'title (cadr .title))
-          (cons 'authors (seq-map #'cl-caddr (cdr .authors)))
-          (cons 'container (cadr .venue))
-          (cons 'references nil)
-          (cons 'type (cadr .type))
-          (cons 'url (cadr .url)))))
-
-(defun biblio-dblp--hitp (item)
-  "Check if ITEM is a DBLP hit."
-  (eq (car-safe item) 'hit))
-
-(defun biblio-dblp--parse-search-results ()
-  "Extract search results from DBLP response."
-  (biblio-decode-url-buffer 'utf-8)
-  (let-alist (car (xml-parse-region (point-min) (point-max)))
-    (unless (string= (cadr .status) "OK")
-      (display-warning 'biblio-dblp "DBLP query failed"))
-    (seq-map #'biblio-dblp--extract-interesting-fields (seq-filter #'biblio-dblp--hitp .hits))))
-
-(defun biblio-dblp--url (query)
-  "Create a DBLP url to look up QUERY."
-  (format "http://dblp.uni-trier.de/search/publ/api?q=%s&format=xml" (url-encode-url query)))
-
-;;;###autoload
-(defun biblio-dblp-backend (command &optional arg &rest more)
-  "A DBLP backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'."
-  (pcase command
-    (`name "DBLP")
-    (`prompt "DBLP query: ")
-    (`url (biblio-dblp--url arg))
-    (`parse-buffer (biblio-dblp--parse-search-results))
-    (`forward-bibtex (biblio-dblp--forward-bibtex arg (car more)))
-    (`register (add-to-list 'biblio-backends #'biblio-dblp-backend))))
-
-;;;###autoload
-(add-hook 'biblio-init-hook #'biblio-dblp-backend)
-
-;;;###autoload
-(defun biblio-dblp-lookup (&optional query)
-  "Start a DBLP search for QUERY, prompting if needed."
-  (interactive)
-  (biblio-lookup #'biblio-dblp-backend query))
-
-;;;###autoload
-(defalias 'dblp-lookup 'biblio-dblp-lookup)
-
-(provide 'biblio-dblp)
-;;; biblio-dblp.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-dissemin.el b/elpa/biblio-20190624.1408/biblio-dissemin.el
deleted file mode 100644 (file)
index 7463f7e..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-;;; biblio-dissemin.el --- Lookup bibliographic information and open access records from Dissemin -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Lookup publication records on Dissemin by DOI using `dissemin-lookup'.
-;;
-;; This package also plugs into `biblio-selection-mode' by adding an entry to
-;; the extended actions menu (`x') to quickly locate the Dissemin record of
-;; e.g. a CrossRef entry.
-
-;;; Code:
-
-(require 'biblio-core)
-
-(defun biblio-dissemin--format-author (author)
-  "Format a Dissemin AUTHOR entry."
-  (let-alist author
-    (format "%s %s" .name.first .name.last)))
-
-(defun biblio-dissemin--insert-button (url prefix)
-  "Insert a button pointing to URL, prefixed by PREFIX."
-  (unless (seq-empty-p url)
-    (insert "\n" prefix)
-    (insert (biblio-make-url-button url))))
-
-(defun biblio-dissemin--insert-record (record)
-  "Insert a Dissemin RECORD entry into the current buffer."
-  (let-alist record
-    (insert "\n\n")
-    (biblio-with-fontification 'font-lock-preprocessor-face
-      (biblio-insert-with-prefix ">> " .identifier))
-    (biblio-dissemin--insert-button .pdf_url "   ")
-    (unless (string= .pdf_url .splash_url)
-      (biblio-dissemin--insert-button .splash_url "   "))
-    (unless (seq-empty-p .abstract)
-      (insert "\n")
-      ;; (biblio-with-fontification 'font-lock-doc-face
-      (biblio-insert-with-prefix "   " .abstract))))
-
-(defun biblio-dissemin--translate-classification (classification)
-  "Translate Dissemin's CLASSIFICATION for display."
-  (pcase classification
-    (`"OA" "Available from the publisher")
-    (`"OK" "Some versions may be shared by the author")
-    (`"UNK" "Sharing policy is unclear")
-    (`"CLOSED" "Subject to a restrictive sharing policy")
-    (_ classification)))
-
-(defun biblio-dissemin--suggest-upload (doi)
-  "Insert a link to Dissemin's upload page for DOI."
-  (insert "\n\nDid you write this paper? ")
-  (biblio-with-fontification '(:weight bold)
-    (insert
-     (biblio-make-url-button (format "http://dissem.in/%s" doi) "upload it")))
-  (insert "!\n"))
-
-(defun biblio-dissemin--pretty-print (paper doi)
-  "Pretty-print a Dissemin PAPER entry (with DOI) to current buffer."
-  (let-alist paper
-    (biblio-insert-result
-     (list (cons 'title .title)
-           (cons 'authors (seq-map #'biblio-dissemin--format-author .authors))
-           (cons 'open-access-status
-                 (biblio-dissemin--translate-classification .classification)))
-     t)
-    (biblio-dissemin--insert-button .pdf_url "  ")
-    (if (seq-empty-p .records)
-        (progn (insert "\n\n(no records)")
-               (when (member .classification '("OA" "OK"))
-                 (biblio-dissemin--suggest-upload doi)))
-      (seq-do #'biblio-dissemin--insert-record .records))
-    (goto-char (point-min))))
-
-(defun biblio-dissemin--print-results (paper doi)
-  "Create a buffer for Dissemin, and print PAPER (with DOI) into it."
-  (with-current-buffer (biblio-dissemin--make-buffer)
-    (let ((inhibit-read-only t))
-      (erase-buffer)
-      (help-mode)
-      (visual-line-mode)
-      (biblio-dissemin--pretty-print paper doi))
-    (setq buffer-read-only t)
-    (pop-to-buffer (current-buffer))))
-
-(defun biblio-dissemin--make-buffer ()
-  "Create a buffer to display Dissemin results in."
-  (get-buffer-create "*Dissemin search results*"))
-
-(defun biblio-dissemin--parse-buffer ()
-  "Extract search results from DBLP response."
-  (biblio-decode-url-buffer 'utf-8)
-  (let-alist (json-read)
-    (unless (string= .status "ok")
-      (display-warning 'biblio-dissemin "Dissemin query failed"))
-    .paper))
-
-(defun biblio-dissemin--url (doi)
-  "Create a DBLP url to look up DOI."
-  (format "http://dissem.in/api/%s" (url-encode-url doi)))
-
-(defun biblio-dissemin--callback (doi)
-  "Generate a callback to parse Dissemin results for DOI."
-  (lambda () ;; no allowed errors, so no arguments
-    (biblio-dissemin--print-results (biblio-dissemin--parse-buffer) doi)))
-
-;;;###autoload
-(defun biblio-dissemin-lookup (doi &optional cleanup)
-  "Retrieve a record by DOI from Dissemin, and display it.
-Interactively, or if CLEANUP is non-nil, pass DOI through
-`biblio-cleanup-doi'."
-  (interactive "MDOI: \nd")
-  (when cleanup
-    (setq doi (biblio-cleanup-doi doi)))
-  (let ((buf (biblio-dissemin--make-buffer)))
-    (biblio-url-retrieve (biblio-dissemin--url doi)
-                         (biblio-generic-url-callback (biblio-dissemin--callback doi)))
-    buf))
-
-;;;###autoload
-(defalias 'dissemin-lookup 'biblio-dissemin-lookup)
-
-(defun biblio-dissemin--lookup-record (record)
-  "Retrieve a RECORD from Dissemin, and display it.
-RECORD is a formatted record as expected by `biblio-insert-result'."
-  (let-alist record
-    (if .doi (dissemin-lookup .doi)
-      (user-error "Dissemin needs a DOI, but this record does not contain one"))))
-
-;;;###autoload
-(defun biblio-dissemin--register-action ()
-  "Add Dissemin to list of `biblio-selection-mode' actions."
-  (add-to-list 'biblio-selection-mode-actions-alist
-               '("Dissemin (find open access copies of this article)" . biblio-dissemin--lookup-record)))
-
-;;;###autoload
-(add-hook 'biblio-selection-mode-hook #'biblio-dissemin--register-action)
-
-(provide 'biblio-dissemin)
-;;; biblio-dissemin.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-doi.el b/elpa/biblio-20190624.1408/biblio-doi.el
deleted file mode 100644 (file)
index e4b1a4e..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-;;; biblio-doi.el --- Retrieve BibTeX entries by DOI -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Retrieve and insert BibTeX records by DOI using `doi-insert-bibtex'.
-;; Information is retrieved from DOI issuing sites of each DOI using the
-;; “application/x-bibtex” and “text/bibliography” request types, falling back to
-;; CrossCite if unavailable.
-;;
-;; This package integrates with `biblio-selection-mode', and is part of the more
-;; general `biblio' package (which see for more documentation).
-
-(require 'biblio-core)
-
-;;; Code:
-
-(defun biblio-doi--dx-url (doi)
-  "Create a doi.org url for DOI."
-  (format "http://doi.org/%s" doi))
-
-(defun biblio-doi--crosscite-url (doi)
-  "Create a crosscite URL to use as a fallback for DOI.
-Not all content providers provide BibTeX formatted entries, so
-instead of failing reroute the request through crosscite, which
-requests a generic format and crates the BibTeX on its own."
-  (format "http://crosscite.org/citeproc/format?doi=%s&style=bibtex&lang=en-US" doi))
-
-(defconst biblio-doi--dx-mime-accept
-  ;; “Accept:” header; Zenodo recognize x-bibtex but not text/bibliography
-  "text/bibliography;style=bibtex, application/x-bibtex")
-
-(defun biblio-doi--set-mime-accept ()
-  "Set `url-mime-accept-string' before contacting the DOI server."
-  ;; Ugly: let-binding or buffer-locally setting `url-mime-accept-string' does
-  ;; not work, because `url-http-create-request' can be called from a
-  ;; sentinel, or from an entirely new buffer (after a redirection).
-  (setq url-mime-accept-string biblio-doi--dx-mime-accept))
-
-(defun biblio-doi--restore-mime-accept ()
-  "Restore `url-mime-accept-string'."
-  (kill-local-variable 'url-mime-accept-string)
-  (setq-default url-mime-accept-string nil))
-
-(defun biblio-doi--insert (bibtex buffer)
-  "Insert formatted BIBTEX into BUFFER."
-  (with-current-buffer buffer
-    (insert bibtex "\n\n")))
-
-(defun biblio-doi--generic-url-callback-1 (errors forward-to)
-  "Helper function for `biblio-doi--generic-url-callback'.
-ERRORS, FORWARD-TO: see there."
-  (funcall forward-to
-           (unless errors
-             (biblio-format-bibtex (biblio-response-as-utf-8)))))
-
-(defun biblio-doi--generic-url-callback (cleanup-fn forward-to)
-  "Make an URL-ready callback.
-Call CLEANUP-FN in any case, and FORWARD-TO with BibTeX source
-or nil depending on whether an error occured.  If error 406
-occurs, forward nil; otherwise, signal the error.  This is
-essentially a thin wrapper around `biblio-generic-url-callback'."
-  (biblio-generic-url-callback
-   (lambda (&optional errors)
-     "Handle response from BibTeX server."
-     (biblio-doi--generic-url-callback-1 errors forward-to))
-   cleanup-fn '(http . 406)))
-
-(defun biblio-doi--crosscite-callback (forward-to)
-  "Generate a handler for response of CrossCite server.
-FORWARD-TO is the callback to call with the results of the search."
-  (biblio-doi--generic-url-callback #'ignore forward-to))
-
-(defun biblio-doi--forward-bibtex-crosscite (doi forward-to)
-  "Forward BibTeX entry for DOI from CrossCite to FORWARD-TO."
-  (biblio-url-retrieve (biblio-doi--crosscite-url doi) (biblio-doi--crosscite-callback forward-to)))
-
-(defun biblio-doi--dx-callback (forward-to)
-  "Generate a handler for response of DX server.
-FORWARD-TO is the callback to call with the results of the search."
-  (biblio-doi--generic-url-callback #'biblio-doi--restore-mime-accept forward-to))
-
-(defun biblio-doi--forward-bibtex-dx (doi forward-to)
-  "Forward BibTeX entry for DOI from doi.org to FORWARD-TO."
-  (biblio-doi--set-mime-accept)
-  (biblio-url-retrieve (biblio-doi--dx-url doi) (biblio-doi--dx-callback forward-to)))
-
-(defun biblio-doi-forward-bibtex (doi forward-to)
-  "Pass BibTeX entry for DOI to FORWARD-TO."
-  (biblio-doi--forward-bibtex-dx
-   doi (lambda (result)
-         (if result (funcall forward-to result)
-           (biblio-doi--forward-bibtex-crosscite doi forward-to)))))
-
-;;;###autoload
-(defun doi-insert-bibtex (doi)
-  "Insert BibTeX entry matching DOI."
-  (interactive "MDOI: ")
-  (let ((target-buffer (current-buffer)))
-    (biblio-doi-forward-bibtex
-     (biblio-cleanup-doi doi)
-     (lambda (result) (biblio-doi--insert result target-buffer)))))
-
-(provide 'biblio-doi)
-;;; biblio-doi.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-download.el b/elpa/biblio-20190624.1408/biblio-download.el
deleted file mode 100644 (file)
index ef8acae..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-;;; biblio-download.el --- Lookup bibliographic information and open access records from Dissemin -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Download scientific papers directly from Emacs.
-;;
-;; This package plugs into `biblio-selection-mode' by adding an entry to the
-;; extended actions menu (`x').
-
-;;; Code:
-
-(require 'biblio-core)
-
-(defcustom biblio-download-directory nil
-  "Where to put downloaded papers."
-  :group 'biblio
-  :type 'directory)
-
-(defun biblio-download--action (record)
-  "Retrieve a RECORD from Dissemin, and display it.
-RECORD is a formatted record as expected by `biblio-insert-result'."
-  (let-alist record
-    (if .direct-url
-        (let* ((fname (concat .identifier ".pdf"))
-               (target (read-file-name "Save as (see also biblio-download-directory): "
-                                       biblio-download-directory fname nil fname)))
-          (url-copy-file .direct-url (expand-file-name target biblio-download-directory)))
-      (user-error "This record does not contain a direct URL (try arXiv or HAL)"))))
-
-;;;###autoload
-(defun biblio-download--register-action ()
-  "Add download to list of `biblio-selection-mode' actions."
-  (add-to-list 'biblio-selection-mode-actions-alist
-               '("Download this article" . biblio-download--action)))
-
-;;;###autoload
-(add-hook 'biblio-selection-mode-hook #'biblio-download--register-action)
-
-(provide 'biblio-download)
-;;; biblio-download.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-hal.el b/elpa/biblio-20190624.1408/biblio-hal.el
deleted file mode 100644 (file)
index 0d2b015..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-;;; biblio-hal.el --- Lookup and import bibliographic entries from HAL (archives ouvertes) -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Lookup and download bibliographic records from HAL using `hal-lookup'.
-;;
-;; This file implements a backend for the for the `biblio' package (which see for more
-;; documentation).
-
-;;; Code:
-
-(require 'biblio-core)
-
-(defun biblio-hal--forward-bibtex (metadata forward-to)
-  "Forward BibTeX for HAL entry METADATA to FORWARD-TO."
-  (funcall forward-to (biblio-alist-get 'bibtex metadata)))
-
-;; (defun biblio-hal--format-author (author)
-;;   "Format AUTHOR for HAL search results."
-;;   (pcase author
-;;     (`(,author . ,affiliation)
-;;      (biblio-join " " author (biblio-parenthesize affiliation)))))
-
-(defun biblio-hal--extract-interesting-fields (item)
-  "Prepare a HAL search result ITEM for display."
-  (let-alist item
-    (list (cons 'doi .doiId_s)
-          (cons 'year (aref (timezone-parse-date .producedDate_tdate) 0))
-          (cons 'bibtex .label_bibtex)
-          (cons 'title (biblio-join " "
-                         (biblio-join-1 ", " .title_s)
-                         (biblio-parenthesize
-                          (biblio-join-1 ", " .subtitle_s))))
-          (cons 'authors .authFullName_s)
-          ;; Too many institutions? (biblio-parenthesize (biblio-join-1 ", " .structName_s))
-          (cons 'publisher .journalPublisher_s)
-          (cons 'container .journalTitle_s)
-          (cons 'references (biblio-remove-empty
-                             (list .doiId_s .halId_s .arxivId_s)))
-          (cons 'type .submitType_s)
-          (cons 'url .uri_s)
-          (cons 'direct-url (car (append .files_s nil))))))
-
-(defun biblio-hal--parse-search-results ()
-  "Extract search results from HAL response."
-  (biblio-decode-url-buffer 'utf-8)
-  (let-alist (json-read)
-    (unless .response
-      (display-warning 'biblio-hal "HAL query failed"))
-    (seq-map #'biblio-hal--extract-interesting-fields .response.docs)))
-
-(defun biblio-hal--url (query)
-  "Create a HAL url to look up QUERY."
-  (format "https://api.archives-ouvertes.fr/search/?q=%s&wt=%s&fl=%s"
-          (url-encode-url query) "json"
-          (biblio-join "," ;; Use ‘*’ to show all fields
-            "arxivId_s" "halId_s" "doiId_s" ;; "journalIssn_s"
-            "title_s" "subtitle_s" "authFullName_s" "structName_s"
-            "journalPublisher_s" "submitType_s" ;; "abstract_s"
-            ;; "journalTitle_s" "volume_s" "issue_s"  "page_s" "writingDate_s"
-            "label_bibtex" "files_s" "uri_s" "producedDate_tdate")))
-
-;;;###autoload
-(defun biblio-hal-backend (command &optional arg &rest more)
-  "A HAL backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'."
-  (pcase command
-    (`name "HAL")
-    (`prompt "HAL (archives ouvertes) query: ")
-    (`url (biblio-hal--url arg))
-    (`parse-buffer (biblio-hal--parse-search-results))
-    (`forward-bibtex (biblio-hal--forward-bibtex arg (car more)))
-    (`register (add-to-list 'biblio-backends #'biblio-hal-backend))))
-
-;;;###autoload
-(add-hook 'biblio-init-hook #'biblio-hal-backend)
-
-;;;###autoload
-(defun biblio-hal-lookup (&optional query)
-  "Start a HAL search for QUERY, prompting if needed."
-  (interactive)
-  (biblio-lookup #'biblio-hal-backend query))
-
-;;;###autoload
-(defalias 'hal-lookup 'biblio-hal-lookup)
-
-(provide 'biblio-hal)
-;;; biblio-hal.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-ieee.el b/elpa/biblio-20190624.1408/biblio-ieee.el
deleted file mode 100644 (file)
index 39b16f8..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-;;; biblio-ieee.el --- Lookup and import bibliographic entries from IEEE -*- lexical-binding: t -*-
-
-;; Copyright (C) 2019  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;;
-;; Lookup and download bibliographic records from IEEE Xplore using
-;; `ieee-lookup'.
-;;
-;; This package uses `biblio-selection-mode', and plugs into the more general
-;; `biblio' package (which see for more documentation).
-
-;;; Code:
-
-(require 'biblio-core)
-(require 'biblio-doi)
-
-(defconst biblio-ieee--api-key "rfwzcsz3f9fkhklhii84xdfz"
-  "API key used to query IEEE; for use only with biblio.el!")
-
-(defconst biblio-ieee--api-root-url
-  "http://ieeexploreapi.ieee.org/api/v1/search/articles")
-
-(defun biblio-ieee--forward-bibtex (metadata forward-to)
-  "Forward BibTeX for IEEE Xplore entry METADATA to FORWARD-TO."
-  (biblio-doi-forward-bibtex (biblio-alist-get 'doi metadata) forward-to))
-
-(defun biblio-ieee--format-author (author)
-  "Format AUTHOR for IEEE Xplore search results."
-  (let-alist author
-    (biblio-join " " .full_name (biblio-parenthesize .affiliation))))
-
-(defun biblio-ieee--extract-interesting-fields (item)
-  "Prepare a IEEE Xplore search result ITEM for display."
-  (let-alist item
-    (list (cons 'doi .doi)
-          (cons 'year .publication_year)
-          (cons 'title .title)
-          (cons 'authors (seq-map #'biblio-ieee--format-author .authors.authors))
-          (cons 'publisher .publisher)
-          (cons 'container .publication_title)
-          (cons 'references (list .doi .isbn))
-          (cons 'type (or .index_terms.author_terms.terms
-                          .index_terms.ieee_terms.terms))
-          (cons 'url .abstract_url)
-          (cons 'direct-url .pdf_url)
-          (cons 'open-access-status .access_type))))
-
-(defun biblio-ieee--parse-search-results ()
-  "Extract search results from IEEE Xplore response."
-  (biblio-decode-url-buffer 'utf-8)
-  (let-alist (json-read)
-    (seq-map #'biblio-ieee--extract-interesting-fields .articles)))
-
-(defun biblio-ieee--url (query)
-  "Create an IEEE Xplore url to look up QUERY."
-  (format "%s?querytext=%s&apikey=%s"
-          biblio-ieee--api-root-url
-          (url-encode-url query)
-          (rot13 biblio-ieee--api-key)))
-
-;;;###autoload
-(defun biblio-ieee-backend (command &optional arg &rest more)
-  "A IEEE Xplore backend for biblio.el.
-COMMAND, ARG, MORE: See `biblio-backends'."
-  (pcase command
-    (`name "IEEE Xplore")
-    (`prompt "IEEE Xplore query: ")
-    (`url (biblio-ieee--url arg))
-    (`parse-buffer (biblio-ieee--parse-search-results))
-    (`forward-bibtex (biblio-ieee--forward-bibtex arg (car more)))
-    (`register (add-to-list 'biblio-backends #'biblio-ieee-backend))))
-
-;;;###autoload
-(add-hook 'biblio-init-hook #'biblio-ieee-backend)
-
-;;;###autoload
-(defun biblio-ieee-lookup (&optional query)
-  "Start a IEEE search for QUERY, prompting if needed."
-  (interactive)
-  (biblio-lookup #'biblio-ieee-backend query))
-
-;;;###autoload
-(defalias 'ieee-lookup 'biblio-ieee-lookup)
-
-(provide 'biblio-ieee)
-;;; biblio-ieee.el ends here
diff --git a/elpa/biblio-20190624.1408/biblio-pkg.el b/elpa/biblio-20190624.1408/biblio-pkg.el
deleted file mode 100644 (file)
index ffc6a5f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-(define-package "biblio" "20190624.1408" "Browse and import bibliographic references from CrossRef, arXiv, DBLP, HAL, Dissemin, and doi.org"
-  '((emacs "24.3")
-    (biblio-core "0.2")))
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
diff --git a/elpa/biblio-20190624.1408/biblio.el b/elpa/biblio-20190624.1408/biblio.el
deleted file mode 100644 (file)
index cfffbca..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-;;; biblio.el --- Browse and import bibliographic references and BibTeX records from CrossRef, arXiv, DBLP, HAL, IEEE Xplore, Dissemin, and doi.org -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; Version: 0.2
-;; Package-Requires: ((emacs "24.3") (biblio-core "0.2"))
-;; Keywords: bib, tex, convenience, hypermedia
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;; # biblio.el: An extensible Emacs package for browsing and fetching references
-;;
-;; biblio.el makes it easy to browse and gather bibliographic references and
-;; publications from various sources, by keywords or by DOI.  References are
-;; automatically fetched from well-curated sources, and formatted as BibTeX.
-;;
-;; ## Supported sources:
-;;
-;; * ‘CrossRef’, an exhaustive academic search engine (recommended)
-;; * ‘arXiv’, an archive of pre-prints in various scientific fields
-;; * ‘DBLP’, a database of Computer Science publications
-;; * ‘HAL’, a French repository of Open Access publications
-;; * ‘doi.org’, a DOI resolver (to retrieve BibTeX records from DOIs)
-;; * ‘CrossCite’, an alternative DOI resolver and BibTeX formatting service
-;; * ‘Dissemin’, a database tracking the open access status of scholarly articles
-;;
-;; ## Usage
-;;
-;; Quick start: ‘M-x biblio-lookup’.  Each source can also be accessed independently:
-;;
-;; * ‘M-x crossref-lookup’ to query CrossRef
-;; * ‘M-x arxiv-lookup` to query arXiv
-;; * `M-x dblp-lookup’ to query DBLP
-;; * ‘M-x doi-insert’ to insert a BibTeX record by DOI
-;; * ‘M-x dissemin-lookup’ to show information about the open access status of a
-;;   particular DOI
-;;
-;; Most of these commands work together: for example, ‘crossref-lookup’ displays a
-;; list of results in ‘biblio-selection-mode’.  In that mode, use:
-;;
-;; * ‘RET’ to visit the corresponding web page
-;; * ‘c’ or ‘M-w’ to copy the BibTeX record of the current entry
-;; * ‘i’ or ‘C-y’ to insert the BibTeX record of the current entry
-;; * ‘x’ to run an extended action, such as fetching a Dissemin record
-;;
-;; ‘C’ and ‘I’ do the same as ‘c’ and ‘i’, but additionally close the search window.
-;;
-;; ## Examples
-;;
-;; * To insert a clean BibTeX entry for http://doi.org/10.1145/2676726.2677006
-;;   in the current buffer, use
-;;
-;;         M-x crossref-lookup RET fiat deductive delaware RET i
-;;
-;;   (the last ‘i’ inserts the BibTeX record of the currently selected entry in
-;;    your buffer).
-;;
-;; * To find publications by computer scientist Leslie Lamport, use ‘M-x
-;;   dblp-lookup RET author:Lamport RET’ (see more info about DBLP's syntax at
-;;   <http://dblp.uni-trier.de/search/>)
-;;
-;; * To check whether an article is freely available online, use ‘x’ in the list
-;;   of results.  For example ‘M-x crossref-lookup RET Emacs stallman RET’
-;;   followed by ‘x Dissemin RET’ will help you find open access copies of
-;;   Stallman's paper on EMACS (spoiler: http://hdl.handle.net/1721.1/5736).
-;;
-;; See http://github.com/cpitclaudel/biblio.el for more information, including
-;; documentation on extending this framework.
-
-;;; Code:
-
-(require 'biblio-core)
-(require 'biblio-doi)
-(require 'biblio-arxiv)
-(require 'biblio-crossref)
-(require 'biblio-dblp)
-(require 'biblio-hal)
-(require 'biblio-ieee)
-(require 'biblio-dissemin)
-(require 'biblio-download)
-
-(provide 'biblio)
-;;; biblio.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-arxiv.el b/elpa/biblio-20230202.1721/biblio-arxiv.el
new file mode 100644 (file)
index 0000000..81660c5
--- /dev/null
@@ -0,0 +1,147 @@
+;;; biblio-arxiv.el --- Lookup and import bibliographic entries from arXiv -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Lookup and download bibliographic records from arXiv using `arxiv-lookup'.
+;; When a DOI is available, the metadata is fetched from the DOI's issuer;
+;; otherwise, this package uses arXiv's metadata to generate an entry.
+;;
+;; This file implements a backend for the for the `biblio' package (which see for more
+;; documentation).
+
+;;; Code:
+
+(require 'biblio-core)
+(require 'biblio-doi)
+(require 'timezone)
+
+(defgroup biblio-arxiv nil
+  "arXiv support in biblio.el"
+  :group 'biblio)
+
+(defcustom biblio-arxiv-bibtex-header "online"
+  "Which header to use for BibTeX entries generated from arXiv metadata."
+  :group 'biblio
+  :type 'string)
+
+(defun biblio-arxiv--build-bibtex-1 (metadata)
+  "Create an unformated BibTeX record for METADATA."
+  (let-alist metadata
+    (format "@%s{NO_KEY,
+author = {%s},
+title = {{%s}},
+year = {%s},
+archivePrefix = {arXiv},
+eprint = {%s},
+primaryClass = {%s}}"
+            biblio-arxiv-bibtex-header
+            (biblio-join-1 " AND " .authors)
+            .title .year .identifier .category)))
+
+(defun biblio-arxiv--build-bibtex (metadata)
+  "Create a BibTeX record for METADATA."
+  (let-alist metadata
+    (message "Auto-generating a BibTeX entry for %S." .id)
+    (biblio-format-bibtex (biblio-arxiv--build-bibtex-1 metadata) t)))
+
+(defun biblio-arxiv--forward-bibtex (metadata forward-to)
+  "Forward BibTeX for arXiv entry METADATA to FORWARD-TO."
+  (let-alist metadata
+    (if (seq-empty-p .doi)
+        (funcall forward-to (biblio-arxiv--build-bibtex metadata))
+      (biblio-doi-forward-bibtex .doi forward-to))))
+
+(defun biblio-arxiv--format-author (author)
+  "Format AUTHOR for arXiv search results."
+  (when (eq (car-safe author) 'author)
+    (let-alist (cdr author)
+      (biblio-join " "
+        (cadr .name)
+        (biblio-parenthesize (cadr .arxiv:affiliation))))))
+
+(defun biblio-arxiv--extract-id (id)
+  "Extract identifier from ID, the URL of an arXiv abstract."
+  (replace-regexp-in-string "https?://arxiv.org/abs/" "" id))
+
+(defun biblio-arxiv--pdf-url (id)
+  "Extract PDF url from ID of an arXiv entry."
+  (when id
+    (concat "https://arxiv.org/pdf/" id)))
+
+(defun biblio-arxiv--extract-interesting-fields (entry)
+  "Prepare an arXiv search result ENTRY for display."
+  (let-alist entry
+    (let ((id (biblio-arxiv--extract-id (cadr .id))))
+      (list (cons 'doi (cadr .arxiv:doi))
+            (cons 'identifier id)
+            (cons 'year (aref (timezone-parse-date (cadr .published)) 0))
+            (cons 'title (cadr .title))
+            (cons 'authors (seq-map #'biblio-arxiv--format-author entry))
+            (cons 'container (cadr .arxiv:journal_ref))
+            (cons 'category
+                  (biblio-alist-get 'term (car .arxiv:primary_category)))
+            (cons 'references (list (cadr .arxiv:doi) id))
+            (cons 'type "eprint")
+            (cons 'url (biblio-alist-get 'href (car .link)))
+            (cons 'direct-url (biblio-arxiv--pdf-url id))))))
+
+(defun biblio-arxiv--entryp (entry)
+  "Check if ENTRY is an arXiv entry."
+  (eq (car-safe entry) 'entry))
+
+(defun biblio-arxiv--parse-search-results ()
+  "Extract search results from arXiv response."
+  (biblio-decode-url-buffer 'utf-8)
+  (let-alist (xml-parse-region (point-min) (point-max))
+    (seq-map #'biblio-arxiv--extract-interesting-fields
+             (seq-filter #'biblio-arxiv--entryp .feed))))
+
+(defun biblio-arxiv--url (query)
+  "Create an arXiv url to look up QUERY."
+  (format "https://export.arxiv.org/api/query?search_query=%s"
+          (url-encode-url query)))
+
+;;;###autoload
+(defun biblio-arxiv-backend (command &optional arg &rest more)
+  "A arXiv backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'."
+  (pcase command
+    (`name "arXiv")
+    (`prompt "arXiv query: ")
+    (`url (biblio-arxiv--url arg))
+    (`parse-buffer (biblio-arxiv--parse-search-results))
+    (`forward-bibtex (biblio-arxiv--forward-bibtex arg (car more)))
+    (`register (add-to-list 'biblio-backends #'biblio-arxiv-backend))))
+
+;;;###autoload
+(add-hook 'biblio-init-hook #'biblio-arxiv-backend)
+
+;;;###autoload
+(defun biblio-arxiv-lookup (&optional query)
+  "Start an arXiv search for QUERY, prompting if needed."
+  (interactive)
+  (biblio-lookup #'biblio-arxiv-backend query))
+
+;;;###autoload
+(defalias 'arxiv-lookup 'biblio-arxiv-lookup)
+
+(provide 'biblio-arxiv)
+;;; biblio-arxiv.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-autoloads.el b/elpa/biblio-20230202.1721/biblio-autoloads.el
new file mode 100644 (file)
index 0000000..793e61f
--- /dev/null
@@ -0,0 +1,177 @@
+;;; biblio-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 "biblio-arxiv" "biblio-arxiv.el" (0 0 0 0))
+;;; Generated autoloads from biblio-arxiv.el
+
+(autoload 'biblio-arxiv-backend "biblio-arxiv" "\
+A arXiv backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'.
+
+\(fn COMMAND &optional ARG &rest MORE)" nil nil)
+
+(add-hook 'biblio-init-hook #'biblio-arxiv-backend)
+
+(autoload 'biblio-arxiv-lookup "biblio-arxiv" "\
+Start an arXiv search for QUERY, prompting if needed.
+
+\(fn &optional QUERY)" t nil)
+
+(defalias 'arxiv-lookup 'biblio-arxiv-lookup)
+
+(register-definition-prefixes "biblio-arxiv" '("biblio-arxiv-"))
+
+;;;***
+\f
+;;;### (autoloads nil "biblio-crossref" "biblio-crossref.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from biblio-crossref.el
+
+(autoload 'biblio-crossref-backend "biblio-crossref" "\
+A CrossRef backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'.
+
+\(fn COMMAND &optional ARG &rest MORE)" nil nil)
+
+(add-hook 'biblio-init-hook #'biblio-crossref-backend)
+
+(autoload 'biblio-crossref-lookup "biblio-crossref" "\
+Start a CrossRef search for QUERY, prompting if needed.
+
+\(fn &optional QUERY)" t nil)
+
+(defalias 'crossref-lookup 'biblio-crossref-lookup)
+
+(register-definition-prefixes "biblio-crossref" '("biblio-crossref-"))
+
+;;;***
+\f
+;;;### (autoloads nil "biblio-dblp" "biblio-dblp.el" (0 0 0 0))
+;;; Generated autoloads from biblio-dblp.el
+
+(autoload 'biblio-dblp-backend "biblio-dblp" "\
+A DBLP backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'.
+
+\(fn COMMAND &optional ARG &rest MORE)" nil nil)
+
+(add-hook 'biblio-init-hook #'biblio-dblp-backend)
+
+(autoload 'biblio-dblp-lookup "biblio-dblp" "\
+Start a DBLP search for QUERY, prompting if needed.
+
+\(fn &optional QUERY)" t nil)
+
+(defalias 'dblp-lookup 'biblio-dblp-lookup)
+
+(register-definition-prefixes "biblio-dblp" '("biblio-dblp--"))
+
+;;;***
+\f
+;;;### (autoloads nil "biblio-dissemin" "biblio-dissemin.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from biblio-dissemin.el
+
+(autoload 'biblio-dissemin-lookup "biblio-dissemin" "\
+Retrieve a record by DOI from Dissemin, and display it.
+Interactively, or if CLEANUP is non-nil, pass DOI through
+`biblio-cleanup-doi'.
+
+\(fn DOI &optional CLEANUP)" t nil)
+
+(defalias 'dissemin-lookup 'biblio-dissemin-lookup)
+
+(autoload 'biblio-dissemin--register-action "biblio-dissemin" "\
+Add Dissemin to list of `biblio-selection-mode' actions." nil nil)
+
+(add-hook 'biblio-selection-mode-hook #'biblio-dissemin--register-action)
+
+(register-definition-prefixes "biblio-dissemin" '("biblio-dissemin--"))
+
+;;;***
+\f
+;;;### (autoloads nil "biblio-doi" "biblio-doi.el" (0 0 0 0))
+;;; Generated autoloads from biblio-doi.el
+
+(autoload 'biblio-doi-insert-bibtex "biblio-doi" "\
+Insert BibTeX entry matching DOI.
+
+\(fn DOI)" t nil)
+
+(register-definition-prefixes "biblio-doi" '("biblio-doi-" "doi-insert-bibtex"))
+
+;;;***
+\f
+;;;### (autoloads nil "biblio-download" "biblio-download.el" (0 0
+;;;;;;  0 0))
+;;; Generated autoloads from biblio-download.el
+
+(autoload 'biblio-download--register-action "biblio-download" "\
+Add download to list of `biblio-selection-mode' actions." nil nil)
+
+(add-hook 'biblio-selection-mode-hook #'biblio-download--register-action)
+
+(register-definition-prefixes "biblio-download" '("biblio-download-"))
+
+;;;***
+\f
+;;;### (autoloads nil "biblio-hal" "biblio-hal.el" (0 0 0 0))
+;;; Generated autoloads from biblio-hal.el
+
+(autoload 'biblio-hal-backend "biblio-hal" "\
+A HAL backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'.
+
+\(fn COMMAND &optional ARG &rest MORE)" nil nil)
+
+(add-hook 'biblio-init-hook #'biblio-hal-backend)
+
+(autoload 'biblio-hal-lookup "biblio-hal" "\
+Start a HAL search for QUERY, prompting if needed.
+
+\(fn &optional QUERY)" t nil)
+
+(defalias 'hal-lookup 'biblio-hal-lookup)
+
+(register-definition-prefixes "biblio-hal" '("biblio-hal--"))
+
+;;;***
+\f
+;;;### (autoloads nil "biblio-ieee" "biblio-ieee.el" (0 0 0 0))
+;;; Generated autoloads from biblio-ieee.el
+
+(autoload 'biblio-ieee-backend "biblio-ieee" "\
+A IEEE Xplore backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'.
+
+\(fn COMMAND &optional ARG &rest MORE)" nil nil)
+
+(add-hook 'biblio-init-hook #'biblio-ieee-backend)
+
+(autoload 'biblio-ieee-lookup "biblio-ieee" "\
+Start a IEEE search for QUERY, prompting if needed.
+
+\(fn &optional QUERY)" t nil)
+
+(defalias 'ieee-lookup 'biblio-ieee-lookup)
+
+(register-definition-prefixes "biblio-ieee" '("biblio-ieee--"))
+
+;;;***
+\f
+;;;### (autoloads nil nil ("biblio-pkg.el" "biblio.el") (0 0 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; biblio-autoloads.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-crossref.el b/elpa/biblio-20230202.1721/biblio-crossref.el
new file mode 100644 (file)
index 0000000..f0a2534
--- /dev/null
@@ -0,0 +1,113 @@
+;;; biblio-crossref.el --- Lookup and import bibliographic entries from CrossRef -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Lookup and download bibliographic records from CrossRef (a very nicely
+;; curated metadata engine) using `crossref-lookup'.
+;;
+;; This file implements a backend for the `biblio' package (which see for more
+;; documentation).
+
+;;; Code:
+
+(require 'biblio-core)
+(require 'biblio-doi)
+
+(defcustom biblio-crossref-user-email-address nil
+  "Email address to include in CrossRef queries, or nil.
+CrossRef gives priority to queries that include an email address.
+See URL `https://github.com/CrossRef/rest-api-doc#etiquette' for
+more details."
+  :group 'biblio
+  :type '(choice (const :tag "Do not include an email address." nil)
+                 (string :tag "Include an email address.")))
+
+(defun biblio-crossref--forward-bibtex (metadata forward-to)
+  "Forward BibTeX for CrossRef entry METADATA to FORWARD-TO."
+  (biblio-doi-forward-bibtex (biblio-alist-get 'doi metadata) forward-to))
+
+(defun biblio-crossref--format-affiliation (affiliation)
+  "Format AFFILIATION for CrossRef search results."
+  (mapconcat (apply-partially #'biblio-alist-get 'name) affiliation ", "))
+
+(defun biblio-crossref--format-author (author)
+  "Format AUTHOR for CrossRef search results."
+  (let-alist author
+    (biblio-join " "
+                 .given .family (biblio-parenthesize (biblio-crossref--format-affiliation .affiliation)))))
+
+(defun biblio-crossref--extract-interesting-fields (item)
+  "Prepare a CrossRef search result ITEM for display."
+  (let-alist item
+    (list (cons 'doi .DOI)
+          (cons 'year (let ((year (aref (aref .issued.date-parts 0) 0)))
+                        (and (numberp year) (number-to-string year))))
+          (cons 'title (biblio-join " "
+                         (biblio-join-1 ", " .title)
+                         (biblio-parenthesize (biblio-join-1 ", " .subtitle))))
+          (cons 'authors (seq-map #'biblio-crossref--format-author .author))
+          (cons 'publisher .publisher)
+          (cons 'container .container-title)
+          (cons 'references (seq-concatenate 'list (list .DOI) .isbn))
+          (cons 'type .type)
+          (cons 'url .URL))))
+
+(defun biblio-crossref--parse-search-results ()
+  "Extract search results from CrossRef response."
+  (biblio-decode-url-buffer 'utf-8)
+  (let-alist (json-read)
+    (unless (string= .status "ok")
+      (display-warning 'biblio-crossref "CrossRef query failed"))
+    (seq-map #'biblio-crossref--extract-interesting-fields .message.items)))
+
+(defun biblio-crossref--url (query)
+  "Create a CrossRef url to look up QUERY."
+  (format "https://api.crossref.org/works?query=%s%s"
+          (url-encode-url query)
+          (if biblio-crossref-user-email-address
+              (format "&mailto=%s" (url-encode-url biblio-crossref-user-email-address)) "")))
+
+;;;###autoload
+(defun biblio-crossref-backend (command &optional arg &rest more)
+  "A CrossRef backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'."
+  (pcase command
+    (`name "CrossRef")
+    (`prompt "CrossRef query: ")
+    (`url (biblio-crossref--url arg))
+    (`parse-buffer (biblio-crossref--parse-search-results))
+    (`forward-bibtex (biblio-crossref--forward-bibtex arg (car more)))
+    (`register (add-to-list 'biblio-backends #'biblio-crossref-backend))))
+
+;;;###autoload
+(add-hook 'biblio-init-hook #'biblio-crossref-backend)
+
+;;;###autoload
+(defun biblio-crossref-lookup (&optional query)
+  "Start a CrossRef search for QUERY, prompting if needed."
+  (interactive)
+  (biblio-lookup #'biblio-crossref-backend query))
+
+;;;###autoload
+(defalias 'crossref-lookup 'biblio-crossref-lookup)
+
+(provide 'biblio-crossref)
+;;; biblio-crossref.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-dblp.el b/elpa/biblio-20230202.1721/biblio-dblp.el
new file mode 100644 (file)
index 0000000..5eacd2b
--- /dev/null
@@ -0,0 +1,95 @@
+;;; biblio-dblp.el --- Lookup and import bibliographic entries from DBLP -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Lookup and download bibliographic records from DBLP (a great source of
+;; references for Computer Science papers) using `dblp-lookup'.
+;;
+;; This file implements a backend for the for the `biblio' package (which see for more
+;; documentation).
+
+;;; Code:
+
+(require 'biblio-core)
+
+(defun biblio-dblp--forward-bibtex (metadata forward-to)
+  "Forward BibTeX for DBLP entry METADATA to FORWARD-TO."
+  (let* ((source-url (biblio-alist-get 'url metadata))
+         (url (replace-regexp-in-string "/rec/" "/rec/bib2/" source-url t t)))
+    (biblio-url-retrieve url (biblio-generic-url-callback
+                              (lambda () ;; No allowed errors, so no arguments
+                                "Parse DBLP BibTeX results."
+                                (funcall forward-to
+                                         (biblio-response-as-utf-8)))))))
+
+(defun biblio-dblp--extract-interesting-fields (item)
+  "Prepare a DBLP search result ITEM for display."
+  (let-alist (biblio-alist-get 'info item)
+    (list (cons 'year (cadr .year))
+          (cons 'title (cadr .title))
+          (cons 'authors (seq-map #'cl-caddr (cdr .authors)))
+          (cons 'container (cadr .venue))
+          (cons 'references nil)
+          (cons 'type (cadr .type))
+          (cons 'url (cadr .url)))))
+
+(defun biblio-dblp--hitp (item)
+  "Check if ITEM is a DBLP hit."
+  (eq (car-safe item) 'hit))
+
+(defun biblio-dblp--parse-search-results ()
+  "Extract search results from DBLP response."
+  (biblio-decode-url-buffer 'utf-8)
+  (let-alist (car (xml-parse-region (point-min) (point-max)))
+    (unless (string= (cadr .status) "OK")
+      (display-warning 'biblio-dblp "DBLP query failed"))
+    (seq-map #'biblio-dblp--extract-interesting-fields (seq-filter #'biblio-dblp--hitp .hits))))
+
+(defun biblio-dblp--url (query)
+  "Create a DBLP url to look up QUERY."
+  (format "https://dblp.uni-trier.de/search/publ/api?q=%s&format=xml" (url-encode-url query)))
+
+;;;###autoload
+(defun biblio-dblp-backend (command &optional arg &rest more)
+  "A DBLP backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'."
+  (pcase command
+    (`name "DBLP")
+    (`prompt "DBLP query: ")
+    (`url (biblio-dblp--url arg))
+    (`parse-buffer (biblio-dblp--parse-search-results))
+    (`forward-bibtex (biblio-dblp--forward-bibtex arg (car more)))
+    (`register (add-to-list 'biblio-backends #'biblio-dblp-backend))))
+
+;;;###autoload
+(add-hook 'biblio-init-hook #'biblio-dblp-backend)
+
+;;;###autoload
+(defun biblio-dblp-lookup (&optional query)
+  "Start a DBLP search for QUERY, prompting if needed."
+  (interactive)
+  (biblio-lookup #'biblio-dblp-backend query))
+
+;;;###autoload
+(defalias 'dblp-lookup 'biblio-dblp-lookup)
+
+(provide 'biblio-dblp)
+;;; biblio-dblp.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-dissemin.el b/elpa/biblio-20230202.1721/biblio-dissemin.el
new file mode 100644 (file)
index 0000000..73980ab
--- /dev/null
@@ -0,0 +1,157 @@
+;;; biblio-dissemin.el --- Lookup bibliographic information and open access records from Dissemin -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Lookup publication records on Dissemin by DOI using `dissemin-lookup'.
+;;
+;; This package also plugs into `biblio-selection-mode' by adding an entry to
+;; the extended actions menu (`x') to quickly locate the Dissemin record of
+;; e.g. a CrossRef entry.
+
+;;; Code:
+
+(require 'biblio-core)
+
+(defun biblio-dissemin--format-author (author)
+  "Format a Dissemin AUTHOR entry."
+  (let-alist author
+    (format "%s %s" .name.first .name.last)))
+
+(defun biblio-dissemin--insert-button (url prefix)
+  "Insert a button pointing to URL, prefixed by PREFIX."
+  (unless (seq-empty-p url)
+    (insert "\n" prefix)
+    (insert (biblio-make-url-button url))))
+
+(defun biblio-dissemin--insert-record (record)
+  "Insert a Dissemin RECORD entry into the current buffer."
+  (let-alist record
+    (insert "\n\n")
+    (biblio-with-fontification 'font-lock-preprocessor-face
+      (biblio-insert-with-prefix ">> " .identifier))
+    (biblio-dissemin--insert-button .pdf_url "   ")
+    (unless (string= .pdf_url .splash_url)
+      (biblio-dissemin--insert-button .splash_url "   "))
+    (unless (seq-empty-p .abstract)
+      (insert "\n")
+      ;; (biblio-with-fontification 'font-lock-doc-face
+      (biblio-insert-with-prefix "   " .abstract))))
+
+(defun biblio-dissemin--translate-classification (classification)
+  "Translate Dissemin's CLASSIFICATION for display."
+  (pcase classification
+    (`"OA" "Available from the publisher")
+    (`"OK" "Some versions may be shared by the author")
+    (`"UNK" "Sharing policy is unclear")
+    (`"CLOSED" "Subject to a restrictive sharing policy")
+    (_ classification)))
+
+(defun biblio-dissemin--suggest-upload (doi)
+  "Insert a link to Dissemin's upload page for DOI."
+  (insert "\n\nDid you write this paper? ")
+  (biblio-with-fontification '(:weight bold)
+    (insert
+     (biblio-make-url-button (format "https://dissem.in/%s" doi) "upload it")))
+  (insert "!\n"))
+
+(defun biblio-dissemin--pretty-print (paper doi)
+  "Pretty-print a Dissemin PAPER entry (with DOI) to current buffer."
+  (let-alist paper
+    (biblio-insert-result
+     (list (cons 'title .title)
+           (cons 'authors (seq-map #'biblio-dissemin--format-author .authors))
+           (cons 'open-access-status
+                 (biblio-dissemin--translate-classification .classification)))
+     t)
+    (biblio-dissemin--insert-button .pdf_url "  ")
+    (if (seq-empty-p .records)
+        (progn (insert "\n\n(no records)")
+               (when (member .classification '("OA" "OK"))
+                 (biblio-dissemin--suggest-upload doi)))
+      (seq-do #'biblio-dissemin--insert-record .records))
+    (goto-char (point-min))))
+
+(defun biblio-dissemin--print-results (paper doi)
+  "Create a buffer for Dissemin, and print PAPER (with DOI) into it."
+  (with-current-buffer (biblio-dissemin--make-buffer)
+    (let ((inhibit-read-only t))
+      (erase-buffer)
+      (help-mode)
+      (visual-line-mode)
+      (biblio-dissemin--pretty-print paper doi))
+    (setq buffer-read-only t)
+    (pop-to-buffer (current-buffer))))
+
+(defun biblio-dissemin--make-buffer ()
+  "Create a buffer to display Dissemin results in."
+  (get-buffer-create "*Dissemin search results*"))
+
+(defun biblio-dissemin--parse-buffer ()
+  "Extract search results from DBLP response."
+  (biblio-decode-url-buffer 'utf-8)
+  (let-alist (json-read)
+    (unless (string= .status "ok")
+      (display-warning 'biblio-dissemin "Dissemin query failed"))
+    .paper))
+
+(defun biblio-dissemin--url (doi)
+  "Create a DBLP url to look up DOI."
+  (format "https://dissem.in/api/%s" (url-encode-url doi)))
+
+(defun biblio-dissemin--callback (doi)
+  "Generate a callback to parse Dissemin results for DOI."
+  (lambda () ;; no allowed errors, so no arguments
+    (biblio-dissemin--print-results (biblio-dissemin--parse-buffer) doi)))
+
+;;;###autoload
+(defun biblio-dissemin-lookup (doi &optional cleanup)
+  "Retrieve a record by DOI from Dissemin, and display it.
+Interactively, or if CLEANUP is non-nil, pass DOI through
+`biblio-cleanup-doi'."
+  (interactive "MDOI: \nd")
+  (when cleanup
+    (setq doi (biblio-cleanup-doi doi)))
+  (let ((buf (biblio-dissemin--make-buffer)))
+    (biblio-url-retrieve (biblio-dissemin--url doi)
+                         (biblio-generic-url-callback (biblio-dissemin--callback doi)))
+    buf))
+
+;;;###autoload
+(defalias 'dissemin-lookup 'biblio-dissemin-lookup)
+
+(defun biblio-dissemin--lookup-record (record)
+  "Retrieve a RECORD from Dissemin, and display it.
+RECORD is a formatted record as expected by `biblio-insert-result'."
+  (let-alist record
+    (if .doi (dissemin-lookup .doi)
+      (user-error "Dissemin needs a DOI, but this record does not contain one"))))
+
+;;;###autoload
+(defun biblio-dissemin--register-action ()
+  "Add Dissemin to list of `biblio-selection-mode' actions."
+  (add-to-list 'biblio-selection-mode-actions-alist
+               '("Dissemin (find open access copies of this article)" . biblio-dissemin--lookup-record)))
+
+;;;###autoload
+(add-hook 'biblio-selection-mode-hook #'biblio-dissemin--register-action)
+
+(provide 'biblio-dissemin)
+;;; biblio-dissemin.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-doi.el b/elpa/biblio-20230202.1721/biblio-doi.el
new file mode 100644 (file)
index 0000000..308d4ef
--- /dev/null
@@ -0,0 +1,126 @@
+;;; biblio-doi.el --- Retrieve BibTeX entries by DOI -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+
+;;; Commentary:
+;;
+;; Retrieve and insert BibTeX records by DOI using `doi-insert-bibtex'.
+;; Information is retrieved from DOI issuing sites of each DOI using the
+;; “application/x-bibtex” and “text/bibliography” request types, falling back to
+;; CrossCite if unavailable.
+;;
+;; This package integrates with `biblio-selection-mode', and is part of the more
+;; general `biblio' package (which see for more documentation).
+
+(require 'biblio-core)
+
+;;; Code:
+
+(defun biblio-doi--dx-url (doi)
+  "Create a doi.org url for DOI."
+  (format "https://doi.org/%s" doi))
+
+(defun biblio-doi--crosscite-url (doi)
+  "Create a crosscite URL to use as a fallback for DOI.
+Not all content providers provide BibTeX formatted entries, so
+instead of failing reroute the request through crosscite, which
+requests a generic format and crates the BibTeX on its own."
+  (format "https://crosscite.org/citeproc/format?doi=%s&style=bibtex&lang=en-US" doi))
+
+(defconst biblio-doi--dx-mime-accept
+  ;; “Accept:” header; Zenodo recognizes x-bibtex but not text/bibliography
+  "text/bibliography;style=bibtex, application/x-bibtex")
+
+(defun biblio-doi--set-mime-accept ()
+  "Set `url-mime-accept-string' before contacting the DOI server."
+  ;; Ugly: let-binding or buffer-locally setting `url-mime-accept-string' does
+  ;; not work, because `url-http-create-request' can be called from a
+  ;; sentinel, or from an entirely new buffer (after a redirection).
+  (setq url-mime-accept-string biblio-doi--dx-mime-accept))
+
+(defun biblio-doi--restore-mime-accept ()
+  "Restore `url-mime-accept-string'."
+  (kill-local-variable 'url-mime-accept-string)
+  (setq-default url-mime-accept-string nil))
+
+(defun biblio-doi--insert (bibtex buffer)
+  "Insert formatted BIBTEX into BUFFER."
+  (with-current-buffer buffer
+    (insert bibtex "\n\n")))
+
+(defun biblio-doi--generic-url-callback-1 (errors forward-to)
+  "Helper function for `biblio-doi--generic-url-callback'.
+ERRORS, FORWARD-TO: see there."
+  (funcall forward-to (unless errors (biblio-response-as-utf-8))))
+
+(defun biblio-doi--generic-url-callback (cleanup-fn forward-to)
+  "Make an URL-ready callback.
+Call CLEANUP-FN in any case, and FORWARD-TO with BibTeX source
+or nil depending on whether an error occured.  If error 406
+occurs, forward nil; otherwise, signal the error.  This is
+essentially a thin wrapper around `biblio-generic-url-callback'."
+  (biblio-generic-url-callback
+   (lambda (&optional errors)
+     "Handle response from BibTeX server."
+     (biblio-doi--generic-url-callback-1 errors forward-to))
+   cleanup-fn '(http . 406)))
+
+(defun biblio-doi--crosscite-callback (forward-to)
+  "Generate a handler for response of CrossCite server.
+FORWARD-TO is the callback to call with the results of the search."
+  (biblio-doi--generic-url-callback #'ignore forward-to))
+
+(defun biblio-doi--forward-bibtex-crosscite (doi forward-to)
+  "Forward BibTeX entry for DOI from CrossCite to FORWARD-TO."
+  (biblio-url-retrieve (biblio-doi--crosscite-url doi) (biblio-doi--crosscite-callback forward-to)))
+
+(defun biblio-doi--dx-callback (forward-to)
+  "Generate a handler for response of DX server.
+FORWARD-TO is the callback to call with the results of the search."
+  (biblio-doi--generic-url-callback #'biblio-doi--restore-mime-accept forward-to))
+
+(defun biblio-doi--forward-bibtex-dx (doi forward-to)
+  "Forward BibTeX entry for DOI from doi.org to FORWARD-TO."
+  (biblio-doi--set-mime-accept)
+  (biblio-url-retrieve (biblio-doi--dx-url doi) (biblio-doi--dx-callback forward-to)))
+
+(defun biblio-doi-forward-bibtex (doi forward-to)
+  "Pass BibTeX entry for DOI to FORWARD-TO."
+  (biblio-doi--forward-bibtex-dx
+   doi (lambda (result)
+         (if result (funcall forward-to result)
+           (biblio-doi--forward-bibtex-crosscite doi forward-to)))))
+
+;;;###autoload
+(defun biblio-doi-insert-bibtex (doi)
+  "Insert BibTeX entry matching DOI."
+  (interactive "MDOI: ")
+  (let ((target-buffer (current-buffer)))
+    (biblio-doi-forward-bibtex
+     (biblio-cleanup-doi doi)
+     (lambda (result)
+       (biblio-doi--insert
+        (biblio-format-bibtex result biblio-bibtex-use-autokey)
+        target-buffer)))))
+
+(defalias 'doi-insert-bibtex 'biblio-doi-insert-bibtex)
+
+(provide 'biblio-doi)
+;;; biblio-doi.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-download.el b/elpa/biblio-20230202.1721/biblio-download.el
new file mode 100644 (file)
index 0000000..6e937b8
--- /dev/null
@@ -0,0 +1,58 @@
+;;; biblio-download.el --- Lookup bibliographic information and open access records from Dissemin -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Download scientific papers directly from Emacs.
+;;
+;; This package plugs into `biblio-selection-mode' by adding an entry to the
+;; extended actions menu (`x').
+
+;;; Code:
+
+(require 'biblio-core)
+
+(defcustom biblio-download-directory nil
+  "Where to put downloaded papers."
+  :group 'biblio
+  :type 'directory)
+
+(defun biblio-download--action (record)
+  "Retrieve a RECORD from Dissemin, and display it.
+RECORD is a formatted record as expected by `biblio-insert-result'."
+  (let-alist record
+    (if .direct-url
+        (let* ((fname (concat .identifier ".pdf"))
+               (target (read-file-name "Save as (see also biblio-download-directory): "
+                                       biblio-download-directory fname nil fname)))
+          (url-copy-file .direct-url (expand-file-name target biblio-download-directory)))
+      (user-error "This record does not contain a direct URL (try arXiv or HAL)"))))
+
+;;;###autoload
+(defun biblio-download--register-action ()
+  "Add download to list of `biblio-selection-mode' actions."
+  (add-to-list 'biblio-selection-mode-actions-alist
+               '("Download this article" . biblio-download--action)))
+
+;;;###autoload
+(add-hook 'biblio-selection-mode-hook #'biblio-download--register-action)
+
+(provide 'biblio-download)
+;;; biblio-download.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-hal.el b/elpa/biblio-20230202.1721/biblio-hal.el
new file mode 100644 (file)
index 0000000..d5072c6
--- /dev/null
@@ -0,0 +1,106 @@
+;;; biblio-hal.el --- Lookup and import bibliographic entries from HAL (archives ouvertes) -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Lookup and download bibliographic records from HAL using `hal-lookup'.
+;;
+;; This file implements a backend for the for the `biblio' package (which see for more
+;; documentation).
+
+;;; Code:
+
+(require 'biblio-core)
+
+(defun biblio-hal--forward-bibtex (metadata forward-to)
+  "Forward BibTeX for HAL entry METADATA to FORWARD-TO."
+  (funcall forward-to (biblio-alist-get 'bibtex metadata)))
+
+;; (defun biblio-hal--format-author (author)
+;;   "Format AUTHOR for HAL search results."
+;;   (pcase author
+;;     (`(,author . ,affiliation)
+;;      (biblio-join " " author (biblio-parenthesize affiliation)))))
+
+(defun biblio-hal--extract-interesting-fields (item)
+  "Prepare a HAL search result ITEM for display."
+  (let-alist item
+    (list (cons 'doi .doiId_s)
+          (cons 'year (aref (timezone-parse-date .producedDate_tdate) 0))
+          (cons 'bibtex .label_bibtex)
+          (cons 'title (biblio-join " "
+                         (biblio-join-1 ", " .title_s)
+                         (biblio-parenthesize
+                          (biblio-join-1 ", " .subtitle_s))))
+          (cons 'authors .authFullName_s)
+          ;; Too many institutions? (biblio-parenthesize (biblio-join-1 ", " .structName_s))
+          (cons 'publisher .journalPublisher_s)
+          (cons 'container .journalTitle_s)
+          (cons 'references (biblio-remove-empty
+                             (list .doiId_s .halId_s .arxivId_s)))
+          (cons 'type .submitType_s)
+          (cons 'url .uri_s)
+          (cons 'direct-url (car (append .files_s nil))))))
+
+(defun biblio-hal--parse-search-results ()
+  "Extract search results from HAL response."
+  (biblio-decode-url-buffer 'utf-8)
+  (let-alist (json-read)
+    (unless .response
+      (display-warning 'biblio-hal "HAL query failed"))
+    (seq-map #'biblio-hal--extract-interesting-fields .response.docs)))
+
+(defun biblio-hal--url (query)
+  "Create a HAL url to look up QUERY."
+  (format "https://api.archives-ouvertes.fr/search/?q=%s&wt=%s&fl=%s"
+          (url-encode-url query) "json"
+          (biblio-join "," ;; Use ‘*’ to show all fields
+            "arxivId_s" "halId_s" "doiId_s" ;; "journalIssn_s"
+            "title_s" "subtitle_s" "authFullName_s" "structName_s"
+            "journalPublisher_s" "submitType_s" ;; "abstract_s"
+            ;; "journalTitle_s" "volume_s" "issue_s"  "page_s" "writingDate_s"
+            "label_bibtex" "files_s" "uri_s" "producedDate_tdate")))
+
+;;;###autoload
+(defun biblio-hal-backend (command &optional arg &rest more)
+  "A HAL backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'."
+  (pcase command
+    (`name "HAL")
+    (`prompt "HAL (archives ouvertes) query: ")
+    (`url (biblio-hal--url arg))
+    (`parse-buffer (biblio-hal--parse-search-results))
+    (`forward-bibtex (biblio-hal--forward-bibtex arg (car more)))
+    (`register (add-to-list 'biblio-backends #'biblio-hal-backend))))
+
+;;;###autoload
+(add-hook 'biblio-init-hook #'biblio-hal-backend)
+
+;;;###autoload
+(defun biblio-hal-lookup (&optional query)
+  "Start a HAL search for QUERY, prompting if needed."
+  (interactive)
+  (biblio-lookup #'biblio-hal-backend query))
+
+;;;###autoload
+(defalias 'hal-lookup 'biblio-hal-lookup)
+
+(provide 'biblio-hal)
+;;; biblio-hal.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-ieee.el b/elpa/biblio-20230202.1721/biblio-ieee.el
new file mode 100644 (file)
index 0000000..26b30df
--- /dev/null
@@ -0,0 +1,103 @@
+;;; biblio-ieee.el --- Lookup and import bibliographic entries from IEEE -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Lookup and download bibliographic records from IEEE Xplore using
+;; `ieee-lookup'.
+;;
+;; This package uses `biblio-selection-mode', and plugs into the more general
+;; `biblio' package (which see for more documentation).
+
+;;; Code:
+
+(require 'biblio-core)
+(require 'biblio-doi)
+
+(defconst biblio-ieee--api-key "rfwzcsz3f9fkhklhii84xdfz"
+  "API key used to query IEEE; for use only with biblio.el!")
+
+(defconst biblio-ieee--api-root-url
+  "https://ieeexploreapi.ieee.org/api/v1/search/articles")
+
+(defun biblio-ieee--forward-bibtex (metadata forward-to)
+  "Forward BibTeX for IEEE Xplore entry METADATA to FORWARD-TO."
+  (biblio-doi-forward-bibtex (biblio-alist-get 'doi metadata) forward-to))
+
+(defun biblio-ieee--format-author (author)
+  "Format AUTHOR for IEEE Xplore search results."
+  (let-alist author
+    (biblio-join " " .full_name (biblio-parenthesize .affiliation))))
+
+(defun biblio-ieee--extract-interesting-fields (item)
+  "Prepare a IEEE Xplore search result ITEM for display."
+  (let-alist item
+    (list (cons 'doi .doi)
+          (cons 'year .publication_year)
+          (cons 'title .title)
+          (cons 'authors (seq-map #'biblio-ieee--format-author .authors.authors))
+          (cons 'publisher .publisher)
+          (cons 'container .publication_title)
+          (cons 'references (list .doi .isbn))
+          (cons 'type (or .index_terms.author_terms.terms
+                          .index_terms.ieee_terms.terms))
+          (cons 'url .abstract_url)
+          (cons 'direct-url .pdf_url)
+          (cons 'open-access-status .access_type))))
+
+(defun biblio-ieee--parse-search-results ()
+  "Extract search results from IEEE Xplore response."
+  (biblio-decode-url-buffer 'utf-8)
+  (let-alist (json-read)
+    (seq-map #'biblio-ieee--extract-interesting-fields .articles)))
+
+(defun biblio-ieee--url (query)
+  "Create an IEEE Xplore url to look up QUERY."
+  (format "%s?querytext=%s&apikey=%s"
+          biblio-ieee--api-root-url
+          (url-encode-url query)
+          (rot13 biblio-ieee--api-key)))
+
+;;;###autoload
+(defun biblio-ieee-backend (command &optional arg &rest more)
+  "A IEEE Xplore backend for biblio.el.
+COMMAND, ARG, MORE: See `biblio-backends'."
+  (pcase command
+    (`name "IEEE Xplore")
+    (`prompt "IEEE Xplore query: ")
+    (`url (biblio-ieee--url arg))
+    (`parse-buffer (biblio-ieee--parse-search-results))
+    (`forward-bibtex (biblio-ieee--forward-bibtex arg (car more)))
+    (`register (add-to-list 'biblio-backends #'biblio-ieee-backend))))
+
+;;;###autoload
+(add-hook 'biblio-init-hook #'biblio-ieee-backend)
+
+;;;###autoload
+(defun biblio-ieee-lookup (&optional query)
+  "Start a IEEE search for QUERY, prompting if needed."
+  (interactive)
+  (biblio-lookup #'biblio-ieee-backend query))
+
+;;;###autoload
+(defalias 'ieee-lookup 'biblio-ieee-lookup)
+
+(provide 'biblio-ieee)
+;;; biblio-ieee.el ends here
diff --git a/elpa/biblio-20230202.1721/biblio-pkg.el b/elpa/biblio-20230202.1721/biblio-pkg.el
new file mode 100644 (file)
index 0000000..217396d
--- /dev/null
@@ -0,0 +1,13 @@
+(define-package "biblio" "20230202.1721" "Browse and import bibliographic references from CrossRef, arXiv, DBLP, HAL, Dissemin, and doi.org"
+  '((emacs "24.3")
+    (biblio-core "0.2"))
+  :commit "ee52f6cda82ea6fbc3b400e7b12132595cc0374c" :authors
+  '(("Clément Pit-Claudel" . "clement.pitclaudelNOSPAMlive.com"))
+  :maintainer
+  '("Clément Pit-Claudel" . "clement.pitclaudelNOSPAMlive.com")
+  :keywords
+  '("bib" "tex" "convenience" "hypermedia")
+  :url "https://github.com/cpitclaudel/biblio.el")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/elpa/biblio-20230202.1721/biblio.el b/elpa/biblio-20230202.1721/biblio.el
new file mode 100644 (file)
index 0000000..949f829
--- /dev/null
@@ -0,0 +1,97 @@
+;;; biblio.el --- Browse and import bibliographic references and BibTeX records from CrossRef, arXiv, DBLP, HAL, IEEE Xplore, Dissemin, and doi.org -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; Version: 0.3
+;; Package-Requires: ((emacs "24.3") (biblio-core "0.3"))
+;; Keywords: bib, tex, convenience, hypermedia
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; # biblio.el: An extensible Emacs package for browsing and fetching references
+;;
+;; biblio.el makes it easy to browse and gather bibliographic references and
+;; publications from various sources, by keywords or by DOI.  References are
+;; automatically fetched from well-curated sources, and formatted as BibTeX.
+;;
+;; ## Supported sources:
+;;
+;; * ‘CrossRef’, an exhaustive academic search engine (recommended)
+;; * ‘arXiv’, an archive of pre-prints in various scientific fields
+;; * ‘DBLP’, a database of Computer Science publications
+;; * ‘HAL’, a French repository of Open Access publications
+;; * ‘doi.org’, a DOI resolver (to retrieve BibTeX records from DOIs)
+;; * ‘CrossCite’, an alternative DOI resolver and BibTeX formatting service
+;; * ‘Dissemin’, a database tracking the open access status of scholarly articles
+;;
+;; ## Usage
+;;
+;; Quick start: ‘M-x biblio-lookup’.  Each source can also be accessed independently:
+;;
+;; * ‘M-x crossref-lookup’ to query CrossRef
+;; * ‘M-x arxiv-lookup` to query arXiv
+;; * `M-x dblp-lookup’ to query DBLP
+;; * ‘M-x doi-insert’ to insert a BibTeX record by DOI
+;; * ‘M-x dissemin-lookup’ to show information about the open access status of a
+;;   particular DOI
+;;
+;; Most of these commands work together: for example, ‘crossref-lookup’ displays a
+;; list of results in ‘biblio-selection-mode’.  In that mode, use:
+;;
+;; * ‘RET’ to visit the corresponding web page
+;; * ‘c’ or ‘M-w’ to copy the BibTeX record of the current entry
+;; * ‘i’ or ‘C-y’ to insert the BibTeX record of the current entry
+;; * ‘x’ to run an extended action, such as fetching a Dissemin record
+;;
+;; ‘C’ and ‘I’ do the same as ‘c’ and ‘i’, but additionally close the search window.
+;;
+;; ## Examples
+;;
+;; * To insert a clean BibTeX entry for https://doi.org/10.1145/2676726.2677006
+;;   in the current buffer, use
+;;
+;;         M-x crossref-lookup RET fiat deductive delaware RET i
+;;
+;;   (the last ‘i’ inserts the BibTeX record of the currently selected entry in
+;;    your buffer).
+;;
+;; * To find publications by computer scientist Leslie Lamport, use ‘M-x
+;;   dblp-lookup RET author:Lamport RET’ (see more info about DBLP's syntax at
+;;   <https://dblp.uni-trier.de/search/>)
+;;
+;; * To check whether an article is freely available online, use ‘x’ in the list
+;;   of results.  For example ‘M-x crossref-lookup RET Emacs stallman RET’
+;;   followed by ‘x Dissemin RET’ will help you find open access copies of
+;;   Stallman's paper on EMACS (spoiler: https://hdl.handle.net/1721.1/5736).
+;;
+;; See https://github.com/cpitclaudel/biblio.el for more information, including
+;; documentation on extending this framework.
+
+;;; Code:
+
+(require 'biblio-core)
+(require 'biblio-doi)
+(require 'biblio-arxiv)
+(require 'biblio-crossref)
+(require 'biblio-dblp)
+(require 'biblio-hal)
+(require 'biblio-ieee)
+(require 'biblio-dissemin)
+(require 'biblio-download)
+
+(provide 'biblio)
+;;; biblio.el ends here
diff --git a/elpa/biblio-core-20190624.1408/biblio-core-autoloads.el b/elpa/biblio-core-20190624.1408/biblio-core-autoloads.el
deleted file mode 100644 (file)
index 78f5345..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-;;; biblio-core-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-
-(add-to-list 'load-path (directory-file-name
-                         (or (file-name-directory #$) (car load-path))))
-
-\f
-;;;### (autoloads nil "biblio-core" "biblio-core.el" (0 0 0 0))
-;;; Generated autoloads from biblio-core.el
-
-(autoload 'biblio-lookup "biblio-core" "\
-Perform a search using BACKEND, and QUERY.
-Prompt for any missing or nil arguments.  BACKEND should be a
-function obeying the interface described in the docstring of
-`biblio-backends'.  Returns the buffer in which results will be
-inserted.
-
-\(fn &optional BACKEND QUERY)" t nil)
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "biblio-core" '("biblio-")))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; coding: utf-8
-;; End:
-;;; biblio-core-autoloads.el ends here
diff --git a/elpa/biblio-core-20190624.1408/biblio-core-pkg.el b/elpa/biblio-core-20190624.1408/biblio-core-pkg.el
deleted file mode 100644 (file)
index afd6269..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-;;; -*- no-byte-compile: t -*-
-(define-package "biblio-core" "20190624.1408" "A framework for looking up and displaying bibliographic entries" '((emacs "24.3") (let-alist "1.0.4") (seq "1.11") (dash "2.12.1")) :commit "efeeab720cb8e3f95ddb4298d0cc62393cf237e9" :keywords '("bib" "tex" "convenience" "hypermedia") :authors '(("Clément Pit-Claudel" . "clement.pitclaudelNOSPAMlive.com")) :maintainer '("Clément Pit-Claudel" . "clement.pitclaudelNOSPAMlive.com") :url "http://github.com/cpitclaudel/biblio.el")
diff --git a/elpa/biblio-core-20190624.1408/biblio-core.el b/elpa/biblio-core-20190624.1408/biblio-core.el
deleted file mode 100644 (file)
index a5a2304..0000000
+++ /dev/null
@@ -1,864 +0,0 @@
-;;; biblio-core.el --- A framework for looking up and displaying bibliographic entries -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016  Clément Pit-Claudel
-
-;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
-;; Version: 0.2
-;; Package-Version: 20190624.1408
-;; Package-Requires: ((emacs "24.3") (let-alist "1.0.4") (seq "1.11") (dash "2.12.1"))
-;; Keywords: bib, tex, convenience, hypermedia
-;; URL: http://github.com/cpitclaudel/biblio.el
-
-;; 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:
-;; A framework for browsing bibliographic search results.  This is the core
-;; package; for user interfaces, see any of `biblio-crossref', `biblio-dblp', `biblio-doi',
-;; `biblio-arxiv', `biblio-hal' and `biblio-dissemin', which are part of the `biblio' package.
-
-;;; Code:
-
-(require 'bibtex)
-(require 'browse-url)
-(require 'hl-line)
-(require 'ido)
-(require 'json)
-(require 'url-queue)
-
-(require 'dash)
-(require 'let-alist)
-(require 'seq)
-
-(defvar-local biblio--target-buffer nil
-  "Buffer into which BibTeX entries should be inserted.
-This variable is local to each search results buffer.")
-
-(defvar-local biblio--search-terms nil
-  "Keywords that led to a page of bibliographic search results.")
-
-(defvar-local biblio--backend nil
-  "Backend that produced a page of bibliographic search results.")
-
-(defgroup biblio nil
-  "A browser for bibliographic information."
-  :group 'communication)
-
-(defgroup biblio-core nil
-  "Core of the biblio package."
-  :group 'biblio)
-
-(defgroup biblio-faces nil
-  "Faces of the biblio package."
-  :group 'biblio)
-
-(defcustom biblio-synchronous nil
-  "Whether bibliographic queries should be synchronous."
-  :group 'biblio-core
-  :type 'boolean)
-
-(defcustom biblio-authors-limit 10
-  "Maximum number of authors to display per paper."
-  :group 'biblio-core
-  :type 'integer)
-
-;;; Compatibility
-
-(defun biblio-alist-get (key alist)
-  "Copy of Emacs 25's `alist-get', minus default.
-Get the value associated to KEY in ALIST, or nil."
-  (cdr (assq key alist)))
-
-(defun biblio--plist-to-alist (plist)
-  "Copy of Emacs 25's `json--plist-to-alist'.
-Return an alist of the property-value pairs in PLIST."
-  (let (res)
-    (while plist
-      (let ((prop (pop plist))
-            (val (pop plist)))
-        (push (cons prop val) res)))
-    (nreverse res)))
-
-;;; Utilities
-
-(defconst biblio--bibtex-entry-format
-  (list 'opts-or-alts 'numerical-fields 'page-dashes 'whitespace
-        'inherit-booktitle 'realign 'last-comma 'delimiters
-        'unify-case 'braces 'strings 'sort-fields)
-  "Format to use in `biblio-format-bibtex'.
-See `bibtex-entry-format' for details; this list is all
-transformations, except errors for missing fields.
-Also see `biblio-cleanup-bibtex-function'.")
-
-(defun biblio--cleanup-bibtex-1 (dialect autokey)
-  "Cleanup BibTeX entry starting at point.
-DIALECT is `BibTeX' or `biblatex'.  AUTOKEY: see `biblio-format-bibtex'."
-  (let ((bibtex-entry-format biblio--bibtex-entry-format)
-        (bibtex-align-at-equal-sign t)
-        (bibtex-autokey-edit-before-use nil)
-        (bibtex-autokey-year-title-separator ":"))
-    ;; Use biblatex to allow for e.g. @Online
-    ;; Use BibTeX to allow for e.g. @TechReport
-    (bibtex-set-dialect dialect t)
-    (bibtex-clean-entry autokey)))
-
-(defun biblio--cleanup-bibtex (autokey)
-  "Default value of `biblio-cleanup-bibtex-function'.
-AUTOKEY: See biblio-format-bibtex."
-  (save-excursion
-    (when (search-forward "@data{" nil t)
-      (replace-match "@misc{")))
-  (ignore-errors ;; See https://github.com/crosscite/citeproc-doi-server/issues/12
-    (condition-case _
-        (biblio--cleanup-bibtex-1 'biblatex autokey)
-      (error (biblio--cleanup-bibtex-1 'BibTeX autokey)))))
-
-(defcustom biblio-cleanup-bibtex-function
-  #'biblio--cleanup-bibtex
-  "Function to clean up BibTeX entries.
-This function is called in a `bibtex-mode' buffer containing an
-unprocessed, potentially invalid BibTeX (or BibLaTeX) entry, and
-should clean it up in place.  It should take a single argument,
-AUTOKEY, indicating whether the entry needs a new key."
-  :group 'biblio
-  :type 'function)
-
-(defun biblio-format-bibtex (bibtex &optional autokey)
-  "Format BIBTEX entry.
-With non-nil AUTOKEY, automatically generate a key for BIBTEX."
-  (with-temp-buffer
-    (bibtex-mode)
-    (save-excursion
-      (insert (biblio-strip bibtex)))
-    (when (functionp biblio-cleanup-bibtex-function)
-      (funcall biblio-cleanup-bibtex-function autokey))
-    (if (fboundp 'font-lock-ensure) (font-lock-ensure)
-      (with-no-warnings (font-lock-fontify-buffer)))
-    (buffer-substring-no-properties (point-min) (point-max))))
-
-(defun biblio--beginning-of-response-body ()
-  "Move point to beginning of response body."
-  (goto-char (point-min))
-  (unless (re-search-forward "^\n" nil t)
-    (error "Invalid response from server: %S" (buffer-string))))
-
-(defun biblio-response-as-utf-8 ()
-  "Extract body of response."
-  (set-buffer-multibyte t)
-  (decode-coding-region (point) (point-max) 'utf-8 t))
-
-(defun biblio-decode-url-buffer (coding)
-  "Decode URL buffer with CODING."
-  (set-buffer-multibyte t) ;; URL buffer is unibyte
-  (decode-coding-region (point-min) (point-max) coding))
-
-(defun biblio--event-error-code (event)
-  "Extract HTTP error code from EVENT, if any."
-  (pcase event
-    (`(:error . (error ,source ,details))
-     (cons source details))))
-
-(eval-and-compile
-  (define-error 'biblio--url-error "URL retrieval error."))
-
-(defun biblio--throw-on-unexpected-errors (errors allowed-errors)
-  "Throw an url-error for any error in ERRORS not in ALLOWED-ERRORS."
-  (dolist (err errors)
-    (cond ((eq (car err) 'url-queue-timeout)
-           (signal 'biblio--url-error 'timeout))
-          ((not (member err allowed-errors))
-           (signal 'biblio--url-error err)))))
-
-(defun biblio--extract-errors (events)
-  "Extract errors from EVENTS."
-  (delq nil (mapcar #'biblio--event-error-code (biblio--plist-to-alist events))))
-
-(defun biblio-generic-url-callback (callback &optional cleanup-function &rest allowed-errors)
-  "Make an `url'-ready callback from CALLBACK.
-CALLBACK is called with no arguments; the buffer containing the
-server's response is current at the time of the call, and killed
-after the call returns.  Call CLEANUP-FUNCTION before checking
-for errors.  If the request returns one of the errors in
-ALLOWED-ERRORS, CALLBACK is instead called with one argument, the
-list of allowed errors that occurred instead of a buffer.  If the
-request returns another error, an exception is raised."
-  (lambda (events)
-    (let ((target-buffer (current-buffer)))
-      (unwind-protect
-          (progn
-            (funcall (or cleanup-function #'ignore))
-            (condition-case err
-                (-if-let* ((errors (biblio--extract-errors events)))
-                    (progn
-                      (biblio--throw-on-unexpected-errors errors allowed-errors)
-                      (funcall callback errors))
-                  (biblio--beginning-of-response-body)
-                  (delete-region (point-min) (point))
-                  (funcall callback))
-              (error (message "Error while processing request: %S" err))))
-        (kill-buffer target-buffer)))))
-
-(defun biblio-url-retrieve (url callback)
-  "Wrapper around `url-queue-retrieve'.
-URL and CALLBACK; see `url-queue-retrieve'"
-  (message "Fetching %s" url)
-  (if biblio-synchronous
-      (with-current-buffer (url-retrieve-synchronously url)
-        (funcall callback nil))
-    (setq url-queue-timeout 1)
-    (url-queue-retrieve url callback)))
-
-(defun biblio-strip (str)
-  "Remove spaces surrounding STR."
-  (when str
-    (->> str
-         (replace-regexp-in-string "[ \t\n\r]+\\'" "")
-         (replace-regexp-in-string "\\`[ \t\n\r]+" ""))))
-
-(defun biblio-cleanup-doi (doi)
-  "Cleanup DOI string."
-  (biblio-strip (replace-regexp-in-string "https?://\\(dx\\.\\)?doi\\.org/" "" doi)))
-
-(defun biblio-remove-empty (strs)
-  "Remove empty sequences from STRS."
-  (seq-remove #'seq-empty-p strs))
-
-(defun biblio-join-1 (sep strs)
-  "Join non-empty elements of STRS with SEP."
-  (declare (indent 1))
-  (let ((strs (biblio-remove-empty strs)))
-    (mapconcat #'identity strs sep)))
-
-(defun biblio-join (sep &rest strs)
-  "Join non-empty elements of STRS with SEP."
-  (declare (indent 1))
-  (biblio-join-1 sep strs))
-
-(defmacro biblio--with-text-property (prop value &rest body)
-  "Set PROP to VALUE on text inserted by BODY."
-  (declare (indent 2)
-           (debug t))
-  (let ((beg-var (make-symbol "beg")))
-    `(let ((,beg-var (point)))
-       ,@body
-       (put-text-property ,beg-var (point) ,prop ,value))))
-
-(defmacro biblio-with-fontification (face &rest body)
-  "Apply FACE to text inserted by BODY."
-  (declare (indent 1)
-           (debug t))
-  (let ((beg-var (make-symbol "beg")))
-    `(let ((,beg-var (point)))
-       ,@body
-       (font-lock-append-text-property ,beg-var (point) 'face ,face))))
-
-;;; Help with major mode
-
-(defsubst biblio--as-list (x)
-  "Make X a list, if it isn't."
-  (if (consp x) x (list x)))
-
-(defun biblio--map-keymap (func map)
-  "Call `map-keymap' on FUNC and MAP, and collect the results."
-  (let ((out))
-    (map-keymap (lambda (&rest args) (push (apply func args) out)) map)
-    out))
-
-(defun biblio--flatten-map (keymap &optional prefix)
-  "Flatten KEYMAP, prefixing its keys with PREFIX.
-This should really be in Emacs core (in Elisp), instead of being
-implemented in C (at least for sparse keymaps).  Don't run this on
-non-sparse keymaps."
-  (nreverse
-   (cond
-    ((keymapp keymap)
-     (seq-map (lambda (key-value)
-                "Add PREFIX to key in KEY-VALUE."
-                (cons (append prefix (biblio--as-list (car key-value)))
-                      (cdr key-value)))
-              (delq nil
-                    (apply
-                     #'seq-concatenate
-                     'list (biblio--map-keymap
-                            (lambda (k v)
-                              "Return a list of bindings in V, prefixed by K."
-                              (biblio--flatten-map v (biblio--as-list k)))
-                            keymap)))))
-    ;; This breaks if keymap is a symbol whose function cell is a keymap
-    ((symbolp keymap)
-     (list (cons prefix keymap))))))
-
-(defun biblio--group-alist (alist)
-  "Return a copy of ALIST whose keys are lists of keys, grouped by value.
-That is, if two key map to `eq' values, they are grouped."
-  (let ((map (make-hash-table :test 'eq))
-        (new-alist nil))
-    (pcase-dolist (`(,key . ,value) alist)
-      (puthash value (cons key (gethash value map)) map))
-    (pcase-dolist (`(,_ . ,value) alist)
-      (-when-let* ((keys (gethash value map)))
-        (push (cons (nreverse keys) value) new-alist)
-        (puthash value nil map)))
-    (nreverse new-alist)))
-
-(defun biblio--quote (str)
-  "Quote STR and call `substitute-command-keys' on it."
-  (if str (substitute-command-keys (concat "`" str "'")) ""))
-
-(defun biblio--quote-keys (keys)
-  "Quote and concatenate keybindings in KEYS."
-  (mapconcat (lambda (keyseq)
-               (biblio--quote (ignore-errors (help-key-description keyseq nil))))
-             keys ", "))
-
-(defun biblio--brief-docs (command)
-  "Return first line of documentation of COMMAND."
-  (let ((docs (or (ignore-errors (documentation command t)) "")))
-    (string-match "\\(.*\\)$" docs)
-    (match-string-no-properties 1 docs)))
-
-(defun biblio--help-with-major-mode-1 (keyseqs-command)
-  "Print help on KEYSEQS-COMMAND to standard output."
-  ;; (biblio-with-fontification 'font-lock-function-name-face
-  (insert (format "%s (%S)\n"
-                  (biblio--quote-keys (car keyseqs-command))
-                  (cdr keyseqs-command)))
-  (biblio-with-fontification 'font-lock-doc-face
-    (insert (format "  %s\n\n" (biblio--brief-docs (cdr keyseqs-command))))))
-
-(defun biblio--help-with-major-mode ()
-  "Display help with current major mode."
-  (let ((buf (format "*%S help*" major-mode)))
-    (with-help-window buf
-      (princ (format "Help with %s\n\n" (biblio--quote (symbol-name major-mode))))
-      (let ((bindings (nreverse
-                       (biblio--group-alist
-                        (biblio--flatten-map
-                         (current-local-map))))))
-        (with-current-buffer buf
-          (seq-do #'biblio--help-with-major-mode-1 bindings))))
-    buf))
-
-;;; Interaction
-
-(defconst biblio--search-result-marker-regexp "^> "
-  "Indicator of a search result.")
-
-(defun biblio--selection-move (move-fn search-fn)
-  "Move using MOVE-FN, then call SEARCH-FN and go to first match."
-  (let ((target (point)))
-    (save-excursion
-      (funcall move-fn)
-      (when (funcall search-fn biblio--search-result-marker-regexp nil t)
-        (setq target (match-end 0))))
-    (goto-char target)))
-
-(defun biblio-get-url (metadata)
-  "Compute a url from METADATA.
-Uses .url, and .doi as a fallback."
-  (let-alist metadata
-    (if .url .url
-      (when .doi
-        (concat "https://doi.org/" (url-encode-url .doi))))))
-
-(defun biblio--selection-browse ()
-  "Open the web page of the current entry in a web browser."
-  (interactive)
-  (-if-let* ((url (biblio-get-url (biblio--selection-metadata-at-point))))
-      (browse-url url)
-    (user-error "This record does not contain a URL")))
-
-(defun biblio--selection-browse-direct ()
-  "Open the full text of the current entry in a web browser."
-  (interactive)
-  (-if-let* ((url (biblio-alist-get 'direct-url (biblio--selection-metadata-at-point))))
-      (browse-url url)
-    (user-error "This record does not contain a direct URL (try arXiv or HAL)")))
-
-(defun biblio--selection-next ()
-  "Move to next search result."
-  (interactive)
-  (biblio--selection-move #'end-of-line #'re-search-forward))
-
-(defun biblio--selection-first ()
-  "Move to first search result."
-  (goto-char (point-min))
-  (biblio--selection-move #'ignore #'re-search-forward))
-
-(defun biblio--selection-previous ()
-  "Move to previous search result."
-  (interactive)
-  (biblio--selection-move #'beginning-of-line #'re-search-backward))
-
-(defun biblio--selection-copy-callback (bibtex entry)
-  "Add BIBTEX (from ENTRY) to kill ring."
-  (kill-new bibtex)
-  (message "Killed bibtex entry for %S."
-           (biblio--prepare-title (biblio-alist-get 'title entry))))
-
-(defun biblio--selection-copy ()
-  "Copy BibTeX of current entry at point."
-  (interactive)
-  (biblio--selection-forward-bibtex #'biblio--selection-copy-callback))
-
-(defun biblio--selection-copy-quit ()
-  "Copy BibTeX of current entry at point and close results."
-  (interactive)
-  (biblio--selection-forward-bibtex #'biblio--selection-copy-callback t))
-
-(defun biblio--target-window ()
-  "Get the window of the source buffer."
-  (get-buffer-window biblio--target-buffer))
-
-(defun biblio--selection-insert-callback (bibtex entry)
-  "Add BIBTEX (from ENTRY) to kill ring."
-  (let ((target-buffer biblio--target-buffer))
-    (with-selected-window (or (biblio--target-window) (selected-window))
-      (with-current-buffer target-buffer
-        (insert bibtex "\n\n"))))
-  (message "Inserted bibtex entry for %S."
-           (biblio--prepare-title (biblio-alist-get 'title entry))))
-
-(defun biblio--selection-insert ()
-  "Insert BibTeX of current entry into source buffer."
-  (interactive)
-  (biblio--selection-forward-bibtex #'biblio--selection-insert-callback))
-
-(defun biblio--selection-insert-quit ()
-  "Insert BibTeX of current entry into source buffer and close results."
-  (interactive)
-  (biblio--selection-forward-bibtex #'biblio--selection-insert-callback t))
-
-(defun biblio--selection-metadata-at-point ()
-  "Return the metadata of the entry at point."
-  (or (get-text-property (point) 'biblio-metadata)
-      (user-error "No entry at point")))
-
-(defun biblio--selection-forward-bibtex (forward-to &optional quit)
-  "Retrieve BibTeX for entry at point and pass it to FORWARD-TO.
-If QUIT is set, also kill the results buffer."
-  (let* ((metadata (biblio--selection-metadata-at-point))
-         (results-buffer (current-buffer)))
-    (progn
-      (funcall (biblio-alist-get 'backend metadata)
-               'forward-bibtex metadata
-               (lambda (bibtex)
-                 (with-current-buffer results-buffer
-                   (funcall forward-to (biblio-format-bibtex bibtex) metadata))))
-      (when quit (quit-window)))))
-
-(defun biblio--selection-change-buffer (buffer-name)
-  "Change buffer in which BibTeX results will be inserted.
-BUFFER-NAME is the name of the new target buffer."
-  (interactive (list (read-buffer "Buffer to insert entries into: ")))
-  (let ((buffer (get-buffer buffer-name)))
-    (if (buffer-local-value 'buffer-read-only buffer)
-        (user-error "%s is read-only" (buffer-name buffer))
-      (setq biblio--target-buffer buffer))))
-
-(defvar biblio-selection-mode-actions-alist nil
-  "An alist of extensions for `biblio-selection-mode'.
-Each element should be in the for (LABEL . FUNCTION); FUNCTION
-will be called with the metadata of the current item.")
-
-(defun biblio--completing-read-function ()
-  "Return ido, unless user picked another completion package."
-  (if (eq completing-read-function #'completing-read-default)
-      #'ido-completing-read
-    completing-read-function))
-
-(defun biblio-completing-read (prompt collection &optional predicate require-match
-                                      initial-input hist def inherit-input-method)
-  "Complete using `biblio-completing-read-function'.
-PROMPT, COLLECTION, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT,
-HIST, DEF, INHERIT-INPUT-METHOD: see `completing-read'."
-  (let ((completing-read-function (biblio--completing-read-function)))
-    (completing-read prompt collection predicate require-match
-                     initial-input hist def inherit-input-method)))
-
-(defun biblio-completing-read-alist (prompt collection &optional predicate require-match
-                                            initial-input hist def inherit-input-method)
-  "Same as `biblio-completing-read', when COLLECTION in an alist.
-Complete with the `car's, and return the `cdr' of the result.
-PROMPT, COLLECTION, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT,
-HIST, DEF, INHERIT-INPUT-METHOD: see `completing-read'."
-  (let ((choices (mapcar #'car collection)))
-    (cdr (assoc (biblio-completing-read
-                 prompt choices predicate require-match
-                 initial-input hist def inherit-input-method)
-                collection))))
-
-(defun biblio--read-selection-extended-action ()
-  "Read an action from `biblio-selection-mode-actions-alist'."
-  (biblio-completing-read-alist
-   "Action: " biblio-selection-mode-actions-alist nil t))
-
-(defun biblio--selection-extended-action (action)
-  "Run an ACTION with metadata of current entry.
-Interactively, query for ACTION from
-`biblio-selection-mode-actions-alist'."
-  (interactive (list (biblio--read-selection-extended-action)))
-  (let* ((metadata (biblio--selection-metadata-at-point)))
-    (funcall action metadata)))
-
-(defun biblio--selection-help ()
-  "Show help on local keymap."
-  (interactive)
-  (biblio--help-with-major-mode))
-
-(defvar biblio-selection-mode-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "<up>") #'biblio--selection-previous)
-    (define-key map (kbd "C-p") #'biblio--selection-previous)
-    (define-key map (kbd "<down>") #'biblio--selection-next)
-    (define-key map (kbd "C-n") #'biblio--selection-next)
-    (define-key map (kbd "RET") #'biblio--selection-browse)
-    (define-key map (kbd "<C-return>") #'biblio--selection-browse-direct)
-    (define-key map (kbd "C-RET") #'biblio--selection-browse-direct)
-    (define-key map (kbd "M-w") #'biblio--selection-copy)
-    (define-key map (kbd "c") #'biblio--selection-copy)
-    (define-key map (kbd "C-w") #'biblio--selection-copy-quit)
-    (define-key map (kbd "C") #'biblio--selection-copy-quit)
-    (define-key map (kbd "i") #'biblio--selection-insert)
-    (define-key map (kbd "C-y") #'biblio--selection-insert-quit)
-    (define-key map (kbd "I") #'biblio--selection-insert-quit)
-    (define-key map (kbd "b") #'biblio--selection-change-buffer)
-    (define-key map (kbd "x") #'biblio--selection-extended-action)
-    (define-key map (kbd "?") #'biblio--selection-help)
-    (define-key map (kbd "h") #'biblio--selection-help)
-    (define-key map (kbd "q") #'quit-window)
-    map)
-  "Keybindings for Bibliographic search results.")
-
-(defconst biblio--selection-mode-name-base "Bibliographic search results")
-
-(defun biblio--selection-mode-name ()
-  "Compute a modeline string for `biblio-selection-mode'."
-  (concat biblio--selection-mode-name-base
-          (if (bufferp biblio--target-buffer)
-              (format " (→ %s)"
-                      (buffer-name biblio--target-buffer))
-            "")))
-
-(define-derived-mode biblio-selection-mode fundamental-mode biblio--selection-mode-name-base
-  "Browse bibliographic search results.
-\\{biblio-selection-mode-map}"
-  (hl-line-mode)
-  (visual-line-mode)
-  (setq-local truncate-lines nil)
-  (setq-local cursor-type nil)
-  (setq-local buffer-read-only t)
-  (setq-local mode-name '(:eval (biblio--selection-mode-name)))
-  (setq-local
-   header-line-format
-   `(:eval
-     (concat
-      (ignore-errors
-        (propertize " " 'display '(space :align-to 0) 'face 'fringe))
-      (substitute-command-keys
-       (biblio-join "   "
-         "\\[biblio--selection-help]: Help"
-         "\\[biblio--selection-insert],\\[biblio--selection-insert-quit]: Insert BibTex"
-         "\\[biblio--selection-copy],\\[biblio--selection-copy-quit]: Copy BibTeX"
-         "\\[biblio--selection-extended-action]: Extended action"
-         "\\[biblio--selection-browse]: Open in browser"
-         "\\[biblio--selection-change-buffer]: Change buffer"))))))
-
-;;; Printing search results
-
-(defun biblio-parenthesize (str)
-  "Add parentheses to STR, if not empty."
-  (if (seq-empty-p str) ""
-    (concat "(" str ")")))
-
-(defun biblio-insert-with-prefix (prefix &rest strs)
-  "Like INSERT with PREFIX and STRS, but set `wrap-prefix'.
-That is, the inserted text gets a `wrap-prefix' made of enough
-white space to align with the end of PREFIX."
-  (declare (indent 1))
-  (biblio--with-text-property 'wrap-prefix (make-string (length prefix) ?\s)
-    (apply #'insert prefix strs)))
-
-(defface biblio-detail-header-face
-  '((t :slant normal))
-  "Face used for headers of details in `biblio-selection-mode'."
-  :group 'biblio-faces)
-
-(defun biblio--insert-detail (prefix items newline)
-  "Insert PREFIX followed by ITEMS, if ITEMS has non-empty entries.
-If ITEMS is a list or vector, join its entries with “, ”.  If
-NEWLINE is non-nil, add a newline before the main text."
-  (when (or (vectorp items) (listp items))
-    (setq items (biblio-join-1 ", " items)))
-  (unless (seq-empty-p items)
-    (when newline (insert "\n"))
-    (let ((fontified (propertize prefix 'face 'biblio-detail-header-face)))
-      (biblio-insert-with-prefix fontified items))))
-
-(defun biblio--nonempty-string-p (str)
-  "Return STR if STR is non-empty."
-  (unless (seq-empty-p str)
-    str))
-
-(defun biblio--cleanup-field (text)
-  "Cleanup TEXT for presentation to the user."
-  (when text (biblio-strip (replace-regexp-in-string "[ \r\n\t]+" " " text))))
-
-(defun biblio--prepare-authors (authors)
-  "Cleanup and join list of AUTHORS."
-  (let* ((authors (biblio-remove-empty (seq-map #'biblio-strip authors)))
-         (num-authors (length authors)))
-    ;; Only truncate when significantly above limit
-    (when (> num-authors (+ 2 biblio-authors-limit))
-      (let* ((last (nthcdr biblio-authors-limit authors)))
-        (setcar last (format "… (%d more)" (- num-authors biblio-authors-limit)))
-        (setcdr last nil)))
-    (if authors (biblio-join-1 ", " authors)
-      "(no authors)")))
-
-(defun biblio--prepare-title (title &optional year)
-  "Cleanup TITLE and add YEAR for presentation to the user."
-  (concat (or (biblio--nonempty-string-p (biblio--cleanup-field title))
-              "(no title)")
-          (if year (format " [%s]" year) "")))
-
-(defun biblio--browse-url (button)
-  "Open web browser on page pointed to by BUTTON."
-  (browse-url (button-get button 'target)))
-
-(defun biblio-make-url-button (url &optional label)
-  "Make a text button pointing to URL.
-With non-nil LABEL, use that instead of URL to label the button."
-  (unless (seq-empty-p url)
-    (with-temp-buffer
-      (insert-text-button (or label url)
-                          'target url
-                          'follow-link t
-                          'action #'biblio--browse-url)
-      (buffer-string))))
-
-(defun biblio-insert-result (item &optional no-sep)
-  "Print a (prepared) bibliographic search result ITEM.
-With NO-SEP, do not add space after the record.
-
-This command expects ITEM to be a single alist, in the following format:
-
-  ((title . \"Title of entry\")
-   (authors . (\"Author 1\" \"Author 2\" …))
-   (container . \"Where this was published (which journal, conference, …)\")
-   (type . \"Type of document (journal paper, proceedings, report, …)\")
-   (category . \"Category of this document (aka primary topic)\")
-   (publisher . \"Publisher of this document\")
-   (references . \"Identifier(s) of this document (DOI, DBLP id, Handle, …)\")
-   (open-access-status . \"Open access status of this document\")
-   (url . \"Relevant URL\")
-   (year . \"Publication year as a string, if available\")
-   (direct-url . \"Direct URL of paper (typically PDF)\"))
-
-Each of `container', `type', `category', `publisher',
-`references', and `open-access-status' may be a list; in that
-case, entries of the list are displayed comma-separated.  All
-entries are optional.
-
-`crossref--extract-interesting-fields' and `dblp--extract-interesting-fields'
-provide examples of how to build such a result."
-  (biblio--with-text-property 'biblio-metadata item
-    (let-alist item
-      (biblio-with-fontification 'font-lock-function-name-face
-        (biblio-insert-with-prefix "> " (biblio--prepare-title .title .year)))
-      (insert "\n")
-      (biblio-with-fontification 'font-lock-doc-face
-        (biblio-insert-with-prefix "  " (biblio--prepare-authors .authors)))
-      (biblio-with-fontification 'font-lock-comment-face
-        (biblio--insert-detail "  In: " .container t)
-        (biblio--insert-detail "  Type: " .type t)
-        (biblio--insert-detail "  Category: " .category t)
-        (biblio--insert-detail "  Publisher: " .publisher t)
-        (biblio--insert-detail "  References: " .references t)
-        (biblio--insert-detail "  Open Access: " .open-access-status t)
-        (biblio--insert-detail "  URL: " (list (biblio-make-url-button .url)
-                                         (biblio-make-url-button .direct-url))
-                         t))
-      (unless no-sep
-        (insert "\n\n")))))
-
-(defface biblio-results-header-face
-  '((t :height 1.5 :weight bold :inherit font-lock-preprocessor-face))
-  "Face used for general search results header in `biblio-selection-mode'."
-  :group 'biblio-faces)
-
-(defun biblio--search-results-header (&optional loading-p)
-  "Compute a header for the current `selection-mode' buffer.
-With LOADING-P, mention that results are being loaded."
-  (format "%s search results for %s%s"
-          (funcall biblio--backend 'name)
-          (biblio--quote biblio--search-terms)
-          (if loading-p " (loading…)" "")))
-
-(defun biblio--make-results-buffer (target-buffer search-terms backend)
-  "Set up the results buffer for TARGET-BUFFER, SEARCH-TERMS and BACKEND."
-  (with-current-buffer (get-buffer-create
-                        (format "*%s search*" (funcall backend 'name)))
-    (let ((inhibit-read-only t))
-      (erase-buffer)
-      (biblio-selection-mode)
-      (setq biblio--target-buffer target-buffer)
-      (setq biblio--search-terms search-terms)
-      (setq biblio--backend backend)
-      (biblio--insert-header (biblio--search-results-header t))
-      (setq buffer-read-only t)
-      (current-buffer))))
-
-(defun biblio--insert-header (header)
-  "Prettify and insert HEADER in current buffer."
-  (when header
-    (biblio--with-text-property 'line-spacing 0.5
-      (biblio--with-text-property 'line-height 1.75
-        (biblio-with-fontification 'biblio-results-header-face
-          (insert header "\n"))))))
-
-(defun biblio-insert-results (items &optional header)
-  "Populate current buffer with ITEMS and HEADER, then display it."
-  (let ((inhibit-read-only t))
-    (erase-buffer)
-    (biblio--insert-header header)
-    (seq-do #'biblio-insert-result items))
-  (pop-to-buffer (current-buffer))
-  (biblio--selection-first)
-  (hl-line-highlight))
-
-(defun biblio--tag-backend (backend items)
-  "Add (backend . BACKEND) to each alist in ITEMS."
-  (seq-map (lambda (i) (cons `(backend . ,backend) i)) items))
-
-(defun biblio--callback (results-buffer backend)
-  "Generate a search results callback for RESULTS-BUFFER.
-Results are parsed with (BACKEND 'parse-buffer)."
-  (biblio-generic-url-callback
-   (lambda () ;; no allowed errors, so no arguments
-     "Parse results of bibliographic search."
-     (let ((results (biblio--tag-backend backend (funcall backend 'parse-buffer))))
-       (with-current-buffer results-buffer
-         (biblio-insert-results results (biblio--search-results-header)))
-       (message "Tip: learn to browse results with `h'")))))
-
-;;; Searching
-
-(defvar biblio--search-history nil)
-
-(defvar biblio-backends nil
-  "List of biblio backends.
-This list is generally populated through `biblio-init-hook',
-which is called by `biblio-collect-backends'.
-
-
-Each backend is a function that take a variable number of
-arguments.  The first argument is a command; the rest are
-arguments to this specific command.  The command is one of the
-following:
-
-`name': (no arguments) The name of the backend, displayed when picking a
-backend from a list.
-
-`prompt': (no arguments) The string used when querying the user for a search
-term to feed this backend.
-
-`url': (one argument, QUERY) Create a URL to query the backend's API.
-
-`parse-buffer': (no arguments) Parse the contents of the current
-buffer and return a list of results.  At the time of the call,
-the current buffer contains the results of querying a url
-returned by (THIS-BACKEND `url' QUERY).  The format of individual
-results is described in the docstring of `biblio-insert-result').
-
-`forward-bibtex': (two arguments, METADATA and FORWARD-TO)
-Produce a BibTeX record from METADATA (one of the elements of the
-list produced by `parse-buffer') and call FORWARD-TO on it.
-
-For examples of backends, see one of `biblio-crossref-backend',
-`biblio-dblp-backend', `biblio-arxiv-backend', etc.
-
-
-To register your backend automatically, you may want to add a
-`register' command:
-
-`register': Add the current backend to `biblio-backends'.
-Something like (add-to-list \\='biblio-backends \\='THIS-BACKEND).
-
-Then it's enough to add your backend to `biblio-init-hook':
-
-;;;###autoload
-\(add-hook \\='biblio-init-hook \\='YOUR-BACKEND-HERE).")
-
-(defvar biblio-init-hook nil
-  "Hook run before every search.
-Each function is called with one argument, `register'.  This
-makes it possible to register backends by adding them directly to
-this hook, and making them react to `register' by adding
-themselves to biblio-backends.")
-
-(defun biblio-collect-backends ()
-  "Populate `biblio-backends' and return that."
-  (run-hook-with-args 'biblio-init-hook 'register)
-  biblio-backends)
-
-(defun biblio--named-backends ()
-  "Collect an alist of (NAME . BACKEND)."
-  (seq-map (lambda (b) (cons (funcall b 'name) b)) (biblio-collect-backends)))
-
-(defun biblio--read-backend ()
-  "Run `biblio-init-hook', then read a backend from `biblio-backend'."
-  (biblio-completing-read-alist "Backend: " (biblio--named-backends) nil t))
-
-(defun biblio--read-query (backend)
-  "Interactively read a query.
-Get prompt string from BACKEND."
-  (let* ((prompt (funcall backend 'prompt)))
-    (read-string prompt nil 'biblio--search-history)))
-
-(defun biblio--lookup-1 (backend query)
-  "Just like `biblio-lookup' on BACKEND and QUERY, but never prompt."
-  (let ((results-buffer (biblio--make-results-buffer (current-buffer) query backend)))
-    (biblio-url-retrieve
-     (funcall backend 'url query)
-     (biblio--callback results-buffer backend))
-    results-buffer))
-
-;;;###autoload
-(defun biblio-lookup (&optional backend query)
-  "Perform a search using BACKEND, and QUERY.
-Prompt for any missing or nil arguments.  BACKEND should be a
-function obeying the interface described in the docstring of
-`biblio-backends'.  Returns the buffer in which results will be
-inserted."
-  (interactive)
-  (unless backend (setq backend (biblio--read-backend)))
-  (unless query (setq query (biblio--read-query backend)))
-  (biblio--lookup-1 backend query))
-
-(defun biblio-kill-buffers ()
-  "Kill all `biblio-selection-mode' buffers."
-  (interactive)
-  (dolist (buf (buffer-list))
-    (when (and (buffer-live-p buf)
-               (eq (buffer-local-value 'major-mode buf)
-                   'biblio-selection-mode))
-      (kill-buffer buf))))
-
-;; Local Variables:
-;; nameless-current-name: "biblio"
-;; checkdoc-arguments-in-order-flag: nil
-;; End:
-
-(provide 'biblio-core)
-;;; biblio-core.el ends here
diff --git a/elpa/biblio-core-20230202.1721/biblio-core-autoloads.el b/elpa/biblio-core-20230202.1721/biblio-core-autoloads.el
new file mode 100644 (file)
index 0000000..13b191e
--- /dev/null
@@ -0,0 +1,35 @@
+;;; biblio-core-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 "biblio-core" "biblio-core.el" (0 0 0 0))
+;;; Generated autoloads from biblio-core.el
+
+(autoload 'biblio-lookup "biblio-core" "\
+Perform a search using BACKEND, and QUERY.
+Prompt for any missing or nil arguments.  BACKEND should be a
+function obeying the interface described in the docstring of
+`biblio-backends'.  Returns the buffer in which results will be
+inserted.
+
+\(fn &optional BACKEND QUERY)" t nil)
+
+(register-definition-prefixes "biblio-core" '("biblio-"))
+
+;;;***
+\f
+;;;### (autoloads nil nil ("biblio-core-pkg.el") (0 0 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; biblio-core-autoloads.el ends here
diff --git a/elpa/biblio-core-20230202.1721/biblio-core-pkg.el b/elpa/biblio-core-20230202.1721/biblio-core-pkg.el
new file mode 100644 (file)
index 0000000..f3c7c00
--- /dev/null
@@ -0,0 +1,17 @@
+(define-package "biblio-core" "20230202.1721" "A framework for looking up and displaying bibliographic entries"
+  '((emacs "24.3")
+    (let-alist "1.0.4")
+    (seq "1.11")
+    (dash "2.12.1"))
+  :commit "ee52f6cda82ea6fbc3b400e7b12132595cc0374c" :authors
+  '(("Clément Pit-Claudel" . "clement.pitclaudelNOSPAMlive.com"))
+  :maintainers
+  '(("Clément Pit-Claudel" . "clement.pitclaudelNOSPAMlive.com"))
+  :maintainer
+  '("Clément Pit-Claudel" . "clement.pitclaudelNOSPAMlive.com")
+  :keywords
+  '("bib" "tex" "convenience" "hypermedia")
+  :url "https://github.com/cpitclaudel/biblio.el")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/elpa/biblio-core-20230202.1721/biblio-core.el b/elpa/biblio-core-20230202.1721/biblio-core.el
new file mode 100644 (file)
index 0000000..917346c
--- /dev/null
@@ -0,0 +1,900 @@
+;;; biblio-core.el --- A framework for looking up and displaying bibliographic entries -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016  Clément Pit-Claudel
+
+;; Author: Clément Pit-Claudel <clement.pitclaudelNOSPAMlive.com>
+;; Version: 0.3
+;; Package-Requires: ((emacs "24.3") (let-alist "1.0.4") (seq "1.11") (dash "2.12.1"))
+;; Keywords: bib, tex, convenience, hypermedia
+;; URL: https://github.com/cpitclaudel/biblio.el
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; A framework for browsing bibliographic search results.  This is the core
+;; package; for user interfaces, see any of `biblio-crossref', `biblio-dblp', `biblio-doi',
+;; `biblio-arxiv', `biblio-hal' and `biblio-dissemin', which are part of the `biblio' package.
+
+;;; Code:
+
+(require 'bibtex)
+(require 'browse-url)
+(require 'hl-line)
+(require 'ido)
+(require 'json)
+(require 'url-queue)
+
+(require 'dash)
+(require 'let-alist)
+(require 'seq)
+
+(defvar-local biblio--target-buffer nil
+  "Buffer into which BibTeX entries should be inserted.
+This variable is local to each search results buffer.")
+
+(defvar-local biblio--search-terms nil
+  "Keywords that led to a page of bibliographic search results.")
+
+(defvar-local biblio--backend nil
+  "Backend that produced a page of bibliographic search results.")
+
+(defgroup biblio nil
+  "A browser for bibliographic information."
+  :group 'communication)
+
+(defgroup biblio-core nil
+  "Core of the biblio package."
+  :group 'biblio)
+
+(defgroup biblio-faces nil
+  "Faces of the biblio package."
+  :group 'biblio)
+
+(defcustom biblio-synchronous nil
+  "Whether bibliographic queries should be synchronous."
+  :group 'biblio-core
+  :type 'boolean)
+
+(defcustom biblio-authors-limit 10
+  "Maximum number of authors to display per paper."
+  :group 'biblio-core
+  :type 'integer)
+
+;;; Compatibility
+
+(defun biblio-alist-get (key alist)
+  "Copy of Emacs 25's `alist-get', minus default.
+Get the value associated to KEY in ALIST, or nil."
+  (cdr (assq key alist)))
+
+(defun biblio--plist-to-alist (plist)
+  "Copy of Emacs 25's `json--plist-to-alist'.
+Return an alist of the property-value pairs in PLIST."
+  (let (res)
+    (while plist
+      (let ((prop (pop plist))
+            (val (pop plist)))
+        (push (cons prop val) res)))
+    (nreverse res)))
+
+;;; Utilities
+
+(defconst biblio--bibtex-entry-format
+  (list 'opts-or-alts 'numerical-fields 'page-dashes 'whitespace
+        'inherit-booktitle 'realign 'last-comma 'delimiters
+        'unify-case 'braces 'strings 'sort-fields)
+  "Format to use in `biblio-format-bibtex'.
+See `bibtex-entry-format' for details; this list is all
+transformations, except errors for missing fields.
+Also see `biblio-cleanup-bibtex-function'.")
+
+(defun biblio--cleanup-bibtex-1 (dialect autokey)
+  "Cleanup BibTeX entry starting at point.
+DIALECT is `BibTeX' or `biblatex'.  AUTOKEY: see `biblio-format-bibtex'."
+  (let ((bibtex-entry-format biblio--bibtex-entry-format)
+        (bibtex-align-at-equal-sign t)
+        (bibtex-autokey-edit-before-use nil))
+    ;; Use biblatex to allow for e.g. @Online
+    ;; Use BibTeX to allow for e.g. @TechReport
+    (bibtex-set-dialect dialect t)
+    (bibtex-clean-entry autokey)))
+
+(defun biblio--cleanup-bibtex (autokey)
+  "Default value of `biblio-cleanup-bibtex-function'.
+AUTOKEY: See `biblio-format-bibtex'."
+  (save-excursion
+    (when (search-forward "@data{" nil t)
+      (replace-match "@misc{")))
+  (ignore-errors ;; See https://github.com/crosscite/citeproc-doi-server/issues/12
+    (condition-case _
+        (biblio--cleanup-bibtex-1 'biblatex autokey)
+      (error (biblio--cleanup-bibtex-1 'BibTeX autokey)))))
+
+(defcustom biblio-cleanup-bibtex-function
+  #'biblio--cleanup-bibtex
+  "Function to clean up BibTeX entries.
+This function is called in a `bibtex-mode' buffer containing an
+unprocessed, potentially invalid BibTeX (or BibLaTeX) entry, and
+should clean it up in place.  It should take a single argument,
+AUTOKEY, indicating whether the entry needs a new key."
+  :group 'biblio
+  :type 'function)
+
+(defun biblio-format-bibtex (bibtex &optional autokey)
+  "Format BIBTEX entry.
+With non-nil AUTOKEY, automatically generate a key for BIBTEX."
+  (with-temp-buffer
+    (bibtex-mode)
+    (save-excursion
+      (insert (biblio-strip bibtex)))
+    (if (fboundp 'font-lock-ensure) (font-lock-ensure)
+      (with-no-warnings (font-lock-fontify-buffer)))
+    (when (functionp biblio-cleanup-bibtex-function)
+      (funcall biblio-cleanup-bibtex-function autokey))
+    (buffer-substring-no-properties (point-min) (point-max))))
+
+(defun biblio--beginning-of-response-body ()
+  "Move point to beginning of response body."
+  (goto-char (point-min))
+  (unless (re-search-forward "^\n" nil t)
+    (error "Invalid response from server: %S" (buffer-string))))
+
+(defun biblio-response-as-utf-8 ()
+  "Extract body of response."
+  (set-buffer-multibyte t)
+  (decode-coding-region (point) (point-max) 'utf-8 t))
+
+(defun biblio-decode-url-buffer (coding)
+  "Decode URL buffer with CODING."
+  (set-buffer-multibyte t) ;; URL buffer is unibyte
+  (decode-coding-region (point-min) (point-max) coding))
+
+(defun biblio--event-error-code (event)
+  "Extract HTTP error code from EVENT, if any."
+  (pcase event
+    (`(:error . (error ,source ,details))
+     (cons source details))))
+
+(eval-and-compile
+  (define-error 'biblio--url-error "URL retrieval error."))
+
+(defun biblio--throw-on-unexpected-errors (errors allowed-errors)
+  "Throw an url-error for any error in ERRORS not in ALLOWED-ERRORS."
+  (dolist (err errors)
+    (cond ((eq (car err) 'url-queue-timeout)
+           (signal 'biblio--url-error 'timeout))
+          ((not (member err allowed-errors))
+           (signal 'biblio--url-error err)))))
+
+(defun biblio--extract-errors (events)
+  "Extract errors from EVENTS."
+  (delq nil (mapcar #'biblio--event-error-code (biblio--plist-to-alist events))))
+
+(defun biblio-generic-url-callback (callback &optional cleanup-function &rest allowed-errors)
+  "Make an `url'-ready callback from CALLBACK.
+CALLBACK is called with no arguments; the buffer containing the
+server's response is current at the time of the call, and killed
+after the call returns.  Call CLEANUP-FUNCTION before checking
+for errors.  If the request returns one of the errors in
+ALLOWED-ERRORS, CALLBACK is instead called with one argument, the
+list of allowed errors that occurred instead of a buffer.  If the
+request returns another error, an exception is raised."
+  (lambda (events)
+    (let ((target-buffer (current-buffer)))
+      (unwind-protect
+          (progn
+            (funcall (or cleanup-function #'ignore))
+            (condition-case err
+                (-if-let* ((errors (biblio--extract-errors events)))
+                    (progn
+                      (biblio--throw-on-unexpected-errors errors allowed-errors)
+                      (funcall callback errors))
+                  (biblio--beginning-of-response-body)
+                  (delete-region (point-min) (point))
+                  (funcall callback))
+              (error (message "Error while processing request: %S" err))))
+        (kill-buffer target-buffer)))))
+
+(defun biblio-url-retrieve (url callback)
+  "Wrapper around `url-queue-retrieve'.
+URL and CALLBACK; see `url-queue-retrieve'"
+  (message "Fetching %s" url)
+  (if biblio-synchronous
+      (with-current-buffer (url-retrieve-synchronously url)
+        (funcall callback nil))
+    (setq url-queue-timeout 5)
+    (url-queue-retrieve url callback)))
+
+(defun biblio-strip (str)
+  "Remove spaces surrounding STR."
+  (when str
+    (->> str
+         (replace-regexp-in-string "[ \t\n\r]+\\'" "")
+         (replace-regexp-in-string "\\`[ \t\n\r]+" ""))))
+
+(defun biblio-cleanup-doi (doi)
+  "Cleanup DOI string."
+  (biblio-strip (replace-regexp-in-string "https?://\\(dx\\.\\)?doi\\.org/" "" doi)))
+
+(defun biblio-remove-empty (strs)
+  "Remove empty sequences from STRS."
+  (seq-remove #'seq-empty-p strs))
+
+(defun biblio-join-1 (sep strs)
+  "Join non-empty elements of STRS with SEP."
+  (declare (indent 1))
+  (let ((strs (biblio-remove-empty strs)))
+    (mapconcat #'identity strs sep)))
+
+(defun biblio-join (sep &rest strs)
+  "Join non-empty elements of STRS with SEP."
+  (declare (indent 1))
+  (biblio-join-1 sep strs))
+
+(defmacro biblio--with-text-property (prop value &rest body)
+  "Set PROP to VALUE on text inserted by BODY."
+  (declare (indent 2)
+           (debug t))
+  (let ((beg-var (make-symbol "beg")))
+    `(let ((,beg-var (point)))
+       ,@body
+       (put-text-property ,beg-var (point) ,prop ,value))))
+
+(defmacro biblio-with-fontification (face &rest body)
+  "Apply FACE to text inserted by BODY."
+  (declare (indent 1)
+           (debug t))
+  (let ((beg-var (make-symbol "beg")))
+    `(let ((,beg-var (point)))
+       ,@body
+       (font-lock-append-text-property ,beg-var (point) 'face ,face))))
+
+;;; Help with major mode
+
+(defsubst biblio--as-list (x)
+  "Make X a list, if it isn't."
+  (if (consp x) x (list x)))
+
+(defun biblio--map-keymap (func map)
+  "Call `map-keymap' on FUNC and MAP, and collect the results."
+  (let ((out))
+    (map-keymap (lambda (&rest args) (push (apply func args) out)) map)
+    out))
+
+(defun biblio--flatten-map (keymap &optional prefix)
+  "Flatten KEYMAP, prefixing its keys with PREFIX.
+This should really be in Emacs core (in Elisp), instead of being
+implemented in C (at least for sparse keymaps).  Don't run this on
+non-sparse keymaps."
+  (nreverse
+   (cond
+    ((keymapp keymap)
+     (seq-map (lambda (key-value)
+                "Add PREFIX to key in KEY-VALUE."
+                (cons (append prefix (biblio--as-list (car key-value)))
+                      (cdr key-value)))
+              (delq nil
+                    (apply
+                     #'seq-concatenate
+                     'list (biblio--map-keymap
+                            (lambda (k v)
+                              "Return a list of bindings in V, prefixed by K."
+                              (biblio--flatten-map v (biblio--as-list k)))
+                            keymap)))))
+    ;; FIXME This breaks if keymap is a symbol whose function cell is a keymap
+    ((symbolp keymap)
+     (list (cons prefix keymap))))))
+
+(defun biblio--group-alist (alist)
+  "Return a copy of ALIST whose keys are lists of keys, grouped by value.
+That is, if two key map to `eq' values, they are grouped."
+  (let ((map (make-hash-table :test 'eq))
+        (new-alist nil))
+    (pcase-dolist (`(,key . ,value) alist)
+      (puthash value (cons key (gethash value map)) map))
+    (pcase-dolist (`(,_ . ,value) alist)
+      (-when-let* ((keys (gethash value map)))
+        (push (cons (nreverse keys) value) new-alist)
+        (puthash value nil map)))
+    (nreverse new-alist)))
+
+(defun biblio--quote (str)
+  "Quote STR and call `substitute-command-keys' on it."
+  (if str (substitute-command-keys (concat "`" str "'")) ""))
+
+(defun biblio--quote-keys (keys)
+  "Quote and concatenate keybindings in KEYS."
+  (mapconcat (lambda (keyseq)
+               (biblio--quote (ignore-errors (help-key-description keyseq nil))))
+             keys ", "))
+
+(defun biblio--brief-docs (command)
+  "Return first line of documentation of COMMAND."
+  (let ((docs (or (ignore-errors (documentation command t)) "")))
+    (string-match "\\(.*\\)$" docs)
+    (match-string-no-properties 1 docs)))
+
+(defun biblio--help-with-major-mode-1 (keyseqs-command)
+  "Print help on KEYSEQS-COMMAND to standard output."
+  (insert (biblio--quote-keys (car keyseqs-command)) " ")
+  (insert (propertize "\t" 'display '(space :align-to 10)))
+  (insert-text-button (format "%S" (cdr keyseqs-command)))
+  (insert "\n")
+  (biblio-with-fontification '(font-lock-comment-face (:height 0.95))
+    (insert (format "  %s\n" (biblio--brief-docs (cdr keyseqs-command)))))
+  (biblio-with-fontification '(:height 0.3)
+    (insert "\n")))
+
+(defun biblio--help-with-major-mode ()
+  "Display help with current major mode."
+  (let ((buf (format "*%S help*" major-mode)))
+    (with-help-window buf
+      (princ (format "Help with %s\n\n" (biblio--quote (symbol-name major-mode))))
+      (let ((bindings (nreverse
+                       (biblio--group-alist
+                        (biblio--flatten-map
+                         (current-local-map))))))
+        (with-current-buffer buf
+          (seq-do #'biblio--help-with-major-mode-1 bindings))))
+    buf))
+
+;;; Interaction
+
+(defconst biblio--search-result-marker-regexp "^> "
+  "Indicator of a search result.")
+
+(defun biblio--selection-move (move-fn search-fn)
+  "Move using MOVE-FN, then call SEARCH-FN and go to first match."
+  (let ((target (point)))
+    (save-excursion
+      (funcall move-fn)
+      (when (funcall search-fn biblio--search-result-marker-regexp nil t)
+        (setq target (match-end 0))))
+    (goto-char target)))
+
+(defun biblio-get-url (metadata)
+  "Compute a url from METADATA.
+Uses .url, and .doi as a fallback."
+  (let-alist metadata
+    (if .url .url
+      (when .doi
+        (concat "https://doi.org/" (url-encode-url .doi))))))
+
+(defun biblio--selection-browse ()
+  "Open the web page of the current entry in a web browser."
+  (interactive)
+  (-if-let* ((url (biblio-get-url (biblio--selection-metadata-at-point))))
+      (browse-url url)
+    (user-error "This record does not contain a URL")))
+
+(defun biblio--selection-browse-direct ()
+  "Open the full text of the current entry in a web browser."
+  (interactive)
+  (-if-let* ((url (biblio-alist-get 'direct-url (biblio--selection-metadata-at-point))))
+      (browse-url url)
+    (user-error "This record does not contain a direct URL (try arXiv or HAL)")))
+
+(defun biblio--selection-next ()
+  "Move to next search result."
+  (interactive)
+  (biblio--selection-move #'end-of-line #'re-search-forward))
+
+(defun biblio--selection-first ()
+  "Move to first search result."
+  (goto-char (point-min))
+  (biblio--selection-move #'ignore #'re-search-forward))
+
+(defun biblio--selection-previous ()
+  "Move to previous search result."
+  (interactive)
+  (biblio--selection-move #'beginning-of-line #'re-search-backward))
+
+(defun biblio--selection-copy-callback (bibtex entry)
+  "Add BIBTEX (from ENTRY) to kill ring."
+  (kill-new bibtex)
+  (message "Killed bibtex entry for %S."
+           (biblio--prepare-title (biblio-alist-get 'title entry))))
+
+(defun biblio--selection-copy ()
+  "Copy BibTeX of current entry at point."
+  (interactive)
+  (biblio--selection-forward-bibtex #'biblio--selection-copy-callback))
+
+(defun biblio--selection-copy-quit ()
+  "Copy BibTeX of current entry at point and close results."
+  (interactive)
+  (biblio--selection-forward-bibtex #'biblio--selection-copy-callback t))
+
+(defun biblio--target-window ()
+  "Get the window of the source buffer."
+  (get-buffer-window biblio--target-buffer))
+
+(defun biblio--selection-insert-callback (bibtex entry)
+  "Add BIBTEX (from ENTRY) to kill ring."
+  (let ((target-buffer biblio--target-buffer))
+    (with-selected-window (or (biblio--target-window) (selected-window))
+      (with-current-buffer target-buffer
+        (insert bibtex "\n\n"))))
+  (message "Inserted bibtex entry for %S."
+           (biblio--prepare-title (biblio-alist-get 'title entry))))
+
+(defun biblio--selection-insert ()
+  "Insert BibTeX of current entry into source buffer."
+  (interactive)
+  (biblio--selection-forward-bibtex #'biblio--selection-insert-callback))
+
+(defun biblio--selection-insert-quit ()
+  "Insert BibTeX of current entry into source buffer and close results."
+  (interactive)
+  (biblio--selection-forward-bibtex #'biblio--selection-insert-callback t))
+
+(defun biblio--selection-metadata-at-point ()
+  "Return the metadata of the entry at point."
+  (or (get-text-property (point) 'biblio-metadata)
+      (user-error "No entry at point")))
+
+(defcustom biblio-bibtex-use-autokey nil
+  "Whether to generate new BibTeX keys for inserted entries."
+  :type '(choice (const :tag "Keep original BibTeX keys" nil)
+                 (const :tag "Generate new BibTeX keys" t))
+  :group 'biblio
+  :package-version '(biblio . "0.2.1"))
+
+(defun biblio--selection-forward-bibtex (forward-to &optional quit)
+  "Retrieve BibTeX for entry at point and pass it to FORWARD-TO.
+If QUIT is set, also kill the results buffer."
+  (let* ((metadata (biblio--selection-metadata-at-point))
+         (results-buffer (current-buffer)))
+    (progn
+      (funcall (biblio-alist-get 'backend metadata)
+               'forward-bibtex metadata
+               (lambda (bibtex)
+                 (with-current-buffer results-buffer
+                   (funcall
+                    forward-to
+                    (biblio-format-bibtex bibtex biblio-bibtex-use-autokey)
+                    metadata))))
+      (when quit (quit-window)))))
+
+(defun biblio--selection-change-buffer (buffer-name)
+  "Change buffer in which BibTeX results will be inserted.
+BUFFER-NAME is the name of the new target buffer."
+  (interactive (list (read-buffer "Buffer to insert entries into: ")))
+  (let ((buffer (get-buffer buffer-name)))
+    (if (buffer-local-value 'buffer-read-only buffer)
+        (user-error "%s is read-only" (buffer-name buffer))
+      (setq biblio--target-buffer buffer))))
+
+(defvar biblio-selection-mode-actions-alist nil
+  "An alist of extensions for `biblio-selection-mode'.
+Each element should be in the for (LABEL . FUNCTION); FUNCTION
+will be called with the metadata of the current item.")
+
+(defun biblio--completing-read-function ()
+  "Return ido, unless user picked another completion package."
+  (if (and (eq completing-read-function #'completing-read-default)
+           (not (catch 'advised ;; https://github.com/cpitclaudel/biblio.el/issues/55
+                  (advice-mapc (lambda (&rest _args) (throw 'advised t))
+                               'completing-read-default))))
+      #'ido-completing-read
+    completing-read-function))
+
+(defun biblio-completing-read (prompt collection &optional predicate require-match
+                                      initial-input hist def inherit-input-method)
+  "Complete using `biblio-completing-read-function'.
+PROMPT, COLLECTION, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT,
+HIST, DEF, INHERIT-INPUT-METHOD: see `completing-read'."
+  (let ((completing-read-function (biblio--completing-read-function)))
+    (completing-read prompt collection predicate require-match
+                     initial-input hist def inherit-input-method)))
+
+(defun biblio-completing-read-alist (prompt collection &optional predicate require-match
+                                            initial-input hist def inherit-input-method)
+  "Same as `biblio-completing-read', when COLLECTION in an alist.
+Complete with the `car's, and return the `cdr' of the result.
+PROMPT, COLLECTION, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT,
+HIST, DEF, INHERIT-INPUT-METHOD: see `completing-read'."
+  (let ((choices (mapcar #'car collection)))
+    (cdr (assoc (biblio-completing-read
+                 prompt choices predicate require-match
+                 initial-input hist def inherit-input-method)
+                collection))))
+
+(defun biblio--read-selection-extended-action ()
+  "Read an action from `biblio-selection-mode-actions-alist'."
+  (biblio-completing-read-alist
+   "Action: " biblio-selection-mode-actions-alist nil t))
+
+(defun biblio--selection-extended-action (action)
+  "Run an ACTION with metadata of current entry.
+Interactively, query for ACTION from
+`biblio-selection-mode-actions-alist'."
+  (interactive (list (biblio--read-selection-extended-action)))
+  (let* ((metadata (biblio--selection-metadata-at-point)))
+    (funcall action metadata)))
+
+(defun biblio--selection-help ()
+  "Show help on local keymap."
+  (interactive)
+  (biblio--help-with-major-mode))
+
+(defvar biblio-selection-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "<up>") #'biblio--selection-previous)
+    (define-key map (kbd "C-p") #'biblio--selection-previous)
+    (define-key map (kbd "p") #'biblio--selection-previous)
+    (define-key map (kbd "<down>") #'biblio--selection-next)
+    (define-key map (kbd "C-n") #'biblio--selection-next)
+    (define-key map (kbd "n") #'biblio--selection-next)
+    (define-key map (kbd "RET") #'biblio--selection-browse)
+    (define-key map (kbd "<C-return>") #'biblio--selection-browse-direct)
+    (define-key map (kbd "C-RET") #'biblio--selection-browse-direct)
+    (define-key map (kbd "M-w") #'biblio--selection-copy)
+    (define-key map (kbd "c") #'biblio--selection-copy)
+    (define-key map (kbd "C-w") #'biblio--selection-copy-quit)
+    (define-key map (kbd "C") #'biblio--selection-copy-quit)
+    (define-key map (kbd "i") #'biblio--selection-insert)
+    (define-key map (kbd "C-y") #'biblio--selection-insert-quit)
+    (define-key map (kbd "I") #'biblio--selection-insert-quit)
+    (define-key map (kbd "b") #'biblio--selection-change-buffer)
+    (define-key map (kbd "x") #'biblio--selection-extended-action)
+    (define-key map (kbd "?") #'biblio--selection-help)
+    (define-key map (kbd "h") #'biblio--selection-help)
+    (define-key map (kbd "q") #'quit-window)
+    map)
+  "Keybindings for Bibliographic search results.")
+
+(defconst biblio--selection-mode-name-base "Bibliographic search results")
+
+(defun biblio--selection-mode-name ()
+  "Compute a modeline string for `biblio-selection-mode'."
+  (concat biblio--selection-mode-name-base
+          (if (bufferp biblio--target-buffer)
+              (format " (→ %s)"
+                      (buffer-name biblio--target-buffer))
+            "")))
+
+(defface biblio-highlight-extend-face `((t (:inherit highlight
+                                                    ,@(and (>= emacs-major-version 27) '(:extend t)))))
+  "Face used for highlighting lines."
+  :group 'biblio-faces)
+
+(define-derived-mode biblio-selection-mode fundamental-mode biblio--selection-mode-name-base
+  "Browse bibliographic search results.
+\\{biblio-selection-mode-map}"
+  (setq-local hl-line-face 'biblio-highlight-extend-face)
+  (hl-line-mode 1)
+  (visual-line-mode)
+  (setq-local truncate-lines nil)
+  (setq-local cursor-type nil)
+  (setq-local buffer-read-only t)
+  (setq-local mode-name '(:eval (biblio--selection-mode-name)))
+  (setq-local
+   header-line-format
+   `(:eval
+     (concat
+      (ignore-errors
+        (propertize " " 'display '(space :align-to 0) 'face 'fringe))
+      (substitute-command-keys
+       (biblio-join "   "
+         "\\[biblio--selection-help]: Help"
+         "\\[biblio--selection-insert],\\[biblio--selection-insert-quit]: Insert BibTex"
+         "\\[biblio--selection-copy],\\[biblio--selection-copy-quit]: Copy BibTeX"
+         "\\[biblio--selection-extended-action]: Extended action"
+         "\\[biblio--selection-browse]: Open in browser"
+         "\\[biblio--selection-change-buffer]: Change buffer"))))))
+
+;;; Printing search results
+
+(defun biblio-parenthesize (str)
+  "Add parentheses to STR, if not empty."
+  (if (seq-empty-p str) ""
+    (concat "(" str ")")))
+
+(defun biblio-insert-with-prefix (prefix &rest strs)
+  "Like INSERT with PREFIX and STRS, but set `wrap-prefix'.
+That is, the inserted text gets a `wrap-prefix' made of enough
+white space to align with the end of PREFIX."
+  (declare (indent 1))
+  (biblio--with-text-property 'wrap-prefix (make-string (length prefix) ?\s)
+    (apply #'insert prefix strs)))
+
+(defface biblio-detail-header-face
+  '((t :slant normal))
+  "Face used for headers of details in `biblio-selection-mode'."
+  :group 'biblio-faces)
+
+(defun biblio--insert-detail (prefix items newline)
+  "Insert PREFIX followed by ITEMS, if ITEMS has non-empty entries.
+If ITEMS is a list or vector, join its entries with “, ”.  If
+NEWLINE is non-nil, add a newline before the main text."
+  (when (or (vectorp items) (listp items))
+    (setq items (biblio-join-1 ", " items)))
+  (unless (seq-empty-p items)
+    (when newline (insert "\n"))
+    (let ((fontified (propertize prefix 'face 'biblio-detail-header-face)))
+      (biblio-insert-with-prefix fontified items))))
+
+(defun biblio--nonempty-string-p (str)
+  "Return STR if STR is non-empty."
+  (unless (seq-empty-p str)
+    str))
+
+(defun biblio--cleanup-field (text)
+  "Cleanup TEXT for presentation to the user."
+  (when text (biblio-strip (replace-regexp-in-string "[ \r\n\t]+" " " text))))
+
+(defun biblio--prepare-authors (authors)
+  "Cleanup and join list of AUTHORS."
+  (let* ((authors (biblio-remove-empty (seq-map #'biblio-strip authors)))
+         (num-authors (length authors)))
+    ;; Only truncate when significantly above limit
+    (when (> num-authors (+ 2 biblio-authors-limit))
+      (let* ((last (nthcdr biblio-authors-limit authors)))
+        (setcar last (format "… (%d more)" (- num-authors biblio-authors-limit)))
+        (setcdr last nil)))
+    (if authors (biblio-join-1 ", " authors)
+      "(no authors)")))
+
+(defun biblio--prepare-title (title &optional year)
+  "Cleanup TITLE and add YEAR for presentation to the user."
+  (concat (or (biblio--nonempty-string-p (biblio--cleanup-field title))
+              "(no title)")
+          (if year (format " [%s]" year) "")))
+
+(defun biblio--browse-url (button)
+  "Open web browser on page pointed to by BUTTON."
+  (browse-url (button-get button 'target)))
+
+(defun biblio-make-url-button (url &optional label)
+  "Make a text button pointing to URL.
+With non-nil LABEL, use that instead of URL to label the button."
+  (unless (seq-empty-p url)
+    (with-temp-buffer
+      (insert-text-button (or label url)
+                          'target url
+                          'follow-link t
+                          'action #'biblio--browse-url)
+      (buffer-string))))
+
+(defun biblio--references-redundant-p (references url)
+  "Check whether REFERENCES are all containted in URL.
+
+This is commonly the case with DOIs, which don't need to be
+displayed if they are already in the `dx.doi.org' url."
+  (and (stringp url)
+       (seq-every-p (lambda (ref) (string-match-p (regexp-quote ref) url))
+                    references)))
+
+(defun biblio-insert-result (item &optional no-sep)
+  "Print a (prepared) bibliographic search result ITEM.
+With NO-SEP, do not add space after the record.
+
+This command expects ITEM to be a single alist, in the following format:
+
+  ((title . \"Title of entry\")
+   (authors . (\"Author 1\" \"Author 2\" …))
+   (container . \"Where this was published (which journal, conference, …)\")
+   (type . \"Type of document (journal paper, proceedings, report, …)\")
+   (category . \"Category of this document (aka primary topic)\")
+   (publisher . \"Publisher of this document\")
+   (references . \"Identifier(s) of this document (DOI, DBLP id, Handle, …)\")
+   (open-access-status . \"Open access status of this document\")
+   (url . \"Relevant URL\")
+   (year . \"Publication year as a string, if available\")
+   (direct-url . \"Direct URL of paper (typically PDF)\"))
+
+Each of `container', `type', `category', `publisher',
+`references', and `open-access-status' may be a list; in that
+case, entries of the list are displayed comma-separated.  All
+entries are optional.
+
+`crossref--extract-interesting-fields' and `dblp--extract-interesting-fields'
+provide examples of how to build such a result."
+  (biblio--with-text-property 'biblio-metadata item
+    (let-alist item
+      (biblio-with-fontification 'font-lock-function-name-face
+        (biblio-insert-with-prefix "> " (biblio--prepare-title .title .year)))
+      (insert "\n")
+      (biblio-with-fontification 'font-lock-doc-face
+        (biblio-insert-with-prefix "  " (biblio--prepare-authors .authors)))
+      (biblio-with-fontification 'font-lock-comment-face
+        (biblio--insert-detail "  In: " .container t)
+        (biblio--insert-detail "  Type: " .type t)
+        (biblio--insert-detail "  Category: " .category t)
+        (biblio--insert-detail "  Publisher: " .publisher t)
+        ;; (-when-let* ((year (and (numberp .year) (number-to-string .year))))
+        ;;   (if .publisher
+        ;;       (insert (format " (%s)" year))
+        ;;     (biblio--insert-detail "  Publication date: " year t)))
+        (let ((references (remq nil .references)))
+          (unless (biblio--references-redundant-p references .url)
+            (biblio--insert-detail "  References: " references t)))
+        (biblio--insert-detail "  Open Access: " .open-access-status t)
+        (biblio--insert-detail "  URL: " (list (biblio-make-url-button .url)
+                                         (biblio-make-url-button .direct-url))
+                         t))
+      (unless no-sep
+        (insert "\n\n")))))
+
+(defface biblio-results-header-face
+  '((t :height 1.5 :weight bold :inherit font-lock-preprocessor-face))
+  "Face used for general search results header in `biblio-selection-mode'."
+  :group 'biblio-faces)
+
+(defun biblio--search-results-header (&optional loading-p)
+  "Compute a header for the current `selection-mode' buffer.
+With LOADING-P, mention that results are being loaded."
+  (format "%s search results for %s%s"
+          (funcall biblio--backend 'name)
+          (biblio--quote biblio--search-terms)
+          (if loading-p " (loading…)" "")))
+
+(defun biblio--make-results-buffer (target-buffer search-terms backend)
+  "Set up the results buffer for TARGET-BUFFER, SEARCH-TERMS and BACKEND."
+  (with-current-buffer (get-buffer-create
+                        (format "*%s search*" (funcall backend 'name)))
+    (let ((inhibit-read-only t))
+      (erase-buffer)
+      (biblio-selection-mode)
+      (setq biblio--target-buffer target-buffer)
+      (setq biblio--search-terms search-terms)
+      (setq biblio--backend backend)
+      (biblio--insert-header (biblio--search-results-header t))
+      (setq buffer-read-only t)
+      (current-buffer))))
+
+(defun biblio--insert-header (header)
+  "Prettify and insert HEADER in current buffer."
+  (when header
+    (biblio--with-text-property 'line-spacing 0.5
+      (biblio--with-text-property 'line-height 1.75
+        (biblio-with-fontification 'biblio-results-header-face
+          (insert header "\n"))))))
+
+(defun biblio-insert-results (items &optional header)
+  "Populate current buffer with ITEMS and HEADER, then display it."
+  (let ((inhibit-read-only t))
+    (erase-buffer)
+    (biblio--insert-header header)
+    (seq-do #'biblio-insert-result items))
+  (pop-to-buffer (current-buffer))
+  (biblio--selection-first)
+  (hl-line-highlight))
+
+(defun biblio--tag-backend (backend items)
+  "Add (backend . BACKEND) to each alist in ITEMS."
+  (seq-map (lambda (i) (cons `(backend . ,backend) i)) items))
+
+(defun biblio--callback (results-buffer backend)
+  "Generate a search results callback for RESULTS-BUFFER.
+Results are parsed with (BACKEND 'parse-buffer)."
+  (biblio-generic-url-callback
+   (lambda () ;; no allowed errors, so no arguments
+     "Parse results of bibliographic search."
+     (let ((results (biblio--tag-backend backend (funcall backend 'parse-buffer))))
+       (with-current-buffer results-buffer
+         (biblio-insert-results results (biblio--search-results-header)))
+       (message "Tip: learn to browse results with `h'")))))
+
+;;; Searching
+
+(defvar biblio--search-history nil)
+
+(defvar biblio-backends nil
+  "List of biblio backends.
+This list is generally populated through `biblio-init-hook',
+which is called by `biblio-collect-backends'.
+
+
+Each backend is a function that take a variable number of
+arguments.  The first argument is a command; the rest are
+arguments to this specific command.  The command is one of the
+following:
+
+`name': (no arguments) The name of the backend, displayed when picking a
+backend from a list.
+
+`prompt': (no arguments) The string used when querying the user for a search
+term to feed this backend.
+
+`url': (one argument, QUERY) Create a URL to query the backend's API.
+
+`parse-buffer': (no arguments) Parse the contents of the current
+buffer and return a list of results.  At the time of the call,
+the current buffer contains the results of querying a url
+returned by (THIS-BACKEND `url' QUERY).  The format of individual
+results is described in the docstring of `biblio-insert-result').
+
+`forward-bibtex': (two arguments, METADATA and FORWARD-TO)
+Produce a BibTeX record from METADATA (one of the elements of the
+list produced by `parse-buffer') and call FORWARD-TO on it.
+
+For examples of backends, see one of `biblio-crossref-backend',
+`biblio-dblp-backend', `biblio-arxiv-backend', etc.
+
+
+To register your backend automatically, you may want to add a
+`register' command:
+
+`register': Add the current backend to `biblio-backends'.
+Something like (add-to-list \\='biblio-backends \\='THIS-BACKEND).
+
+Then it's enough to add your backend to `biblio-init-hook':
+
+;;;###autoload
+\(add-hook \\='biblio-init-hook \\='YOUR-BACKEND-HERE).")
+
+(defvar biblio-init-hook nil
+  "Hook run before every search.
+Each function is called with one argument, `register'.  This
+makes it possible to register backends by adding them directly to
+this hook, and making them react to `register' by adding
+themselves to biblio-backends.")
+
+(defun biblio-collect-backends ()
+  "Populate `biblio-backends' and return that."
+  (run-hook-with-args 'biblio-init-hook 'register)
+  biblio-backends)
+
+(defun biblio--named-backends ()
+  "Collect an alist of (NAME . BACKEND)."
+  (seq-map (lambda (b) (cons (funcall b 'name) b)) (biblio-collect-backends)))
+
+(defun biblio--read-backend ()
+  "Run `biblio-init-hook', then read a backend from `biblio-backend'."
+  (biblio-completing-read-alist "Backend: " (biblio--named-backends) nil t))
+
+(defun biblio--read-query (backend)
+  "Interactively read a query.
+Get prompt string from BACKEND."
+  (let* ((prompt (funcall backend 'prompt)))
+    (read-string prompt nil 'biblio--search-history)))
+
+(defun biblio--lookup-1 (backend query)
+  "Just like `biblio-lookup' on BACKEND and QUERY, but never prompt."
+  (let ((results-buffer (biblio--make-results-buffer (current-buffer) query backend)))
+    (biblio-url-retrieve
+     (funcall backend 'url query)
+     (biblio--callback results-buffer backend))
+    results-buffer))
+
+;;;###autoload
+(defun biblio-lookup (&optional backend query)
+  "Perform a search using BACKEND, and QUERY.
+Prompt for any missing or nil arguments.  BACKEND should be a
+function obeying the interface described in the docstring of
+`biblio-backends'.  Returns the buffer in which results will be
+inserted."
+  (interactive)
+  (unless backend (setq backend (biblio--read-backend)))
+  (unless query (setq query (biblio--read-query backend)))
+  (biblio--lookup-1 backend query))
+
+(defun biblio-kill-buffers ()
+  "Kill all `biblio-selection-mode' buffers."
+  (interactive)
+  (dolist (buf (buffer-list))
+    (when (and (buffer-live-p buf)
+               (eq (buffer-local-value 'major-mode buf)
+                   'biblio-selection-mode))
+      (kill-buffer buf))))
+
+;; Local Variables:
+;; nameless-current-name: "biblio"
+;; checkdoc-arguments-in-order-flag: nil
+;; End:
+
+(provide 'biblio-core)
+;;; biblio-core.el ends here