Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
4.4 KiB

4 years ago
  1. ;;; biblio-crossref.el --- Lookup and import bibliographic entries from CrossRef -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2016 Clément Pit-Claudel
  3. ;; Author: Clément Pit-Claudel <clement.pitclaudel@live.com>
  4. ;; URL: http://github.com/cpitclaudel/biblio.el
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;;
  10. ;; This program is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;;
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;;
  19. ;; Lookup and download bibliographic records from CrossRef (a very nicely
  20. ;; curated metadata engine) using `crossref-lookup'.
  21. ;;
  22. ;; This file implements a backend for the `biblio' package (which see for more
  23. ;; documentation).
  24. ;;; Code:
  25. (require 'biblio-core)
  26. (require 'biblio-doi)
  27. (defcustom biblio-crossref-user-email-address nil
  28. "Email address to include in CrossRef queries, or nil.
  29. CrossRef gives priority to queries that include an email address.
  30. See URL `https://github.com/CrossRef/rest-api-doc#etiquette' for
  31. more details."
  32. :group 'biblio
  33. :type '(choice (const :tag "Do not include an email address." nil)
  34. (string :tag "Include an email address.")))
  35. (defun biblio-crossref--forward-bibtex (metadata forward-to)
  36. "Forward BibTeX for CrossRef entry METADATA to FORWARD-TO."
  37. (biblio-doi-forward-bibtex (biblio-alist-get 'doi metadata) forward-to))
  38. (defun biblio-crossref--format-affiliation (affiliation)
  39. "Format AFFILIATION for CrossRef search results."
  40. (mapconcat (apply-partially #'biblio-alist-get 'name) affiliation ", "))
  41. (defun biblio-crossref--format-author (author)
  42. "Format AUTHOR for CrossRef search results."
  43. (let-alist author
  44. (biblio-join " "
  45. .given .family (biblio-parenthesize (biblio-crossref--format-affiliation .affiliation)))))
  46. (defun biblio-crossref--extract-interesting-fields (item)
  47. "Prepare a CrossRef search result ITEM for display."
  48. (let-alist item
  49. (list (cons 'doi .DOI)
  50. (cons 'year (let ((year (aref (aref .issued.date-parts 0) 0)))
  51. (and (numberp year) (number-to-string year))))
  52. (cons 'title (biblio-join " "
  53. (biblio-join-1 ", " .title)
  54. (biblio-parenthesize (biblio-join-1 ", " .subtitle))))
  55. (cons 'authors (seq-map #'biblio-crossref--format-author .author))
  56. (cons 'publisher .publisher)
  57. (cons 'container .container-title)
  58. (cons 'references (seq-concatenate 'list (list .DOI) .isbn))
  59. (cons 'type .type)
  60. (cons 'url .URL))))
  61. (defun biblio-crossref--parse-search-results ()
  62. "Extract search results from CrossRef response."
  63. (biblio-decode-url-buffer 'utf-8)
  64. (let-alist (json-read)
  65. (unless (string= .status "ok")
  66. (display-warning 'biblio-crossref "CrossRef query failed"))
  67. (seq-map #'biblio-crossref--extract-interesting-fields .message.items)))
  68. (defun biblio-crossref--url (query)
  69. "Create a CrossRef url to look up QUERY."
  70. (format "http://api.crossref.org/works?query=%s%s"
  71. (url-encode-url query)
  72. (if biblio-crossref-user-email-address
  73. (format "&mailto=%s" (url-encode-url biblio-crossref-user-email-address)) "")))
  74. ;;;###autoload
  75. (defun biblio-crossref-backend (command &optional arg &rest more)
  76. "A CrossRef backend for biblio.el.
  77. COMMAND, ARG, MORE: See `biblio-backends'."
  78. (pcase command
  79. (`name "CrossRef")
  80. (`prompt "CrossRef query: ")
  81. (`url (biblio-crossref--url arg))
  82. (`parse-buffer (biblio-crossref--parse-search-results))
  83. (`forward-bibtex (biblio-crossref--forward-bibtex arg (car more)))
  84. (`register (add-to-list 'biblio-backends #'biblio-crossref-backend))))
  85. ;;;###autoload
  86. (add-hook 'biblio-init-hook #'biblio-crossref-backend)
  87. ;;;###autoload
  88. (defun biblio-crossref-lookup (&optional query)
  89. "Start a CrossRef search for QUERY, prompting if needed."
  90. (interactive)
  91. (biblio-lookup #'biblio-crossref-backend query))
  92. ;;;###autoload
  93. (defalias 'crossref-lookup 'biblio-crossref-lookup)
  94. (provide 'biblio-crossref)
  95. ;;; biblio-crossref.el ends here