From: Andreas Gerler Date: Thu, 23 Nov 2023 18:30:47 +0000 (+0100) Subject: update biblio X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=1e09c024e2c634b18c64ba80e3abddf1ae49ce11;p=emacsconfig.git update biblio Signed-off-by: Andreas Gerler --- diff --git a/elpa/biblio-20190624.1408/biblio-arxiv.el b/elpa/biblio-20190624.1408/biblio-arxiv.el deleted file mode 100644 index e5498a26..00000000 --- a/elpa/biblio-20190624.1408/biblio-arxiv.el +++ /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 -;; 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 . - -;;; 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 index 1ebfebc7..00000000 --- a/elpa/biblio-20190624.1408/biblio-autoloads.el +++ /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)))) - - -;;;### (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-"))) - -;;;*** - -;;;### (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-"))) - -;;;*** - -;;;### (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--"))) - -;;;*** - -;;;### (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--"))) - -;;;*** - -;;;### (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-"))) - -;;;*** - -;;;### (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-"))) - -;;;*** - -;;;### (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--"))) - -;;;*** - -;;;### (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--"))) - -;;;*** - -;;;### (autoloads nil nil ("biblio-pkg.el" "biblio.el") (0 0 0 0)) - -;;;*** - -;; 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 index 8ad57784..00000000 --- a/elpa/biblio-20190624.1408/biblio-crossref.el +++ /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 -;; 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 . - -;;; 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 index 1e23c076..00000000 --- a/elpa/biblio-20190624.1408/biblio-dblp.el +++ /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 -;; 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 . - -;;; 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 index 7463f7e3..00000000 --- a/elpa/biblio-20190624.1408/biblio-dissemin.el +++ /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 -;; 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 . - -;;; 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 index e4b1a4e9..00000000 --- a/elpa/biblio-20190624.1408/biblio-doi.el +++ /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 -;; 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 . - - -;;; 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 index ef8acaeb..00000000 --- a/elpa/biblio-20190624.1408/biblio-download.el +++ /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 -;; 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 . - -;;; 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 index 0d2b0154..00000000 --- a/elpa/biblio-20190624.1408/biblio-hal.el +++ /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 -;; 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 . - -;;; 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 index 39b16f8e..00000000 --- a/elpa/biblio-20190624.1408/biblio-ieee.el +++ /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 -;; 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 . - -;;; 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 index ffc6a5fc..00000000 --- a/elpa/biblio-20190624.1408/biblio-pkg.el +++ /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 index cfffbca9..00000000 --- a/elpa/biblio-20190624.1408/biblio.el +++ /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 -;; 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 . - -;;; 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 -;; ) -;; -;; * 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 index 00000000..81660c56 --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-arxiv.el @@ -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 +;; 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 . + +;;; 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 index 00000000..793e61f8 --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-autoloads.el @@ -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)))) + + +;;;### (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-")) + +;;;*** + +;;;### (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-")) + +;;;*** + +;;;### (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--")) + +;;;*** + +;;;### (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--")) + +;;;*** + +;;;### (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")) + +;;;*** + +;;;### (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-")) + +;;;*** + +;;;### (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--")) + +;;;*** + +;;;### (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--")) + +;;;*** + +;;;### (autoloads nil nil ("biblio-pkg.el" "biblio.el") (0 0 0 0)) + +;;;*** + +;; 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 index 00000000..f0a25347 --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-crossref.el @@ -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 +;; 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 . + +;;; 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 index 00000000..5eacd2be --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-dblp.el @@ -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 +;; 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 . + +;;; 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 index 00000000..73980ab4 --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-dissemin.el @@ -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 +;; 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 . + +;;; 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 index 00000000..308d4efe --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-doi.el @@ -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 +;; 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 . + + +;;; 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 index 00000000..6e937b85 --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-download.el @@ -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 +;; 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 . + +;;; 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 index 00000000..d5072c67 --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-hal.el @@ -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 +;; 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 . + +;;; 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 index 00000000..26b30dfe --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-ieee.el @@ -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 +;; 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 . + +;;; 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 index 00000000..217396dd --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio-pkg.el @@ -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.pitclaudel@live.com")) + :maintainer + '("Clément Pit-Claudel" . "clement.pitclaudel@live.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 index 00000000..949f8290 --- /dev/null +++ b/elpa/biblio-20230202.1721/biblio.el @@ -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 +;; 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 . + +;;; 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 +;; ) +;; +;; * 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 index 78f53452..00000000 --- a/elpa/biblio-core-20190624.1408/biblio-core-autoloads.el +++ /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)))) - - -;;;### (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-"))) - -;;;*** - -;; 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 index afd62697..00000000 --- a/elpa/biblio-core-20190624.1408/biblio-core-pkg.el +++ /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.pitclaudel@live.com")) :maintainer '("Clément Pit-Claudel" . "clement.pitclaudel@live.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 index a5a2304d..00000000 --- a/elpa/biblio-core-20190624.1408/biblio-core.el +++ /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 -;; 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 . - -;;; 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 "") #'biblio--selection-previous) - (define-key map (kbd "C-p") #'biblio--selection-previous) - (define-key map (kbd "") #'biblio--selection-next) - (define-key map (kbd "C-n") #'biblio--selection-next) - (define-key map (kbd "RET") #'biblio--selection-browse) - (define-key map (kbd "") #'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 index 00000000..13b191e0 --- /dev/null +++ b/elpa/biblio-core-20230202.1721/biblio-core-autoloads.el @@ -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)))) + + +;;;### (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-")) + +;;;*** + +;;;### (autoloads nil nil ("biblio-core-pkg.el") (0 0 0 0)) + +;;;*** + +;; 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 index 00000000..f3c7c00d --- /dev/null +++ b/elpa/biblio-core-20230202.1721/biblio-core-pkg.el @@ -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.pitclaudel@live.com")) + :maintainers + '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) + :maintainer + '("Clément Pit-Claudel" . "clement.pitclaudel@live.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 index 00000000..917346c2 --- /dev/null +++ b/elpa/biblio-core-20230202.1721/biblio-core.el @@ -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 +;; 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 . + +;;; 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 "") #'biblio--selection-previous) + (define-key map (kbd "C-p") #'biblio--selection-previous) + (define-key map (kbd "p") #'biblio--selection-previous) + (define-key map (kbd "") #'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 "") #'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