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.

192 lines
6.1 KiB

5 years ago
  1. ;;; org-ref-isbn.el --- utilities for generating bibtex entries from an ISBN -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2015 John Kitchin
  3. ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
  4. ;; Keywords: convenience
  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. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;; Provides functions to download bibtex entries from isbn numbers.
  17. ;;; Code:
  18. (require 'f)
  19. (require 'org)
  20. (require 'org-ref-core)
  21. (defvar url-http-end-of-headers)
  22. ;;* ISBN utility
  23. (defcustom org-ref-isbn-clean-bibtex-entry-hook
  24. '(oricb-remove-enclosing-brackets
  25. oricb-clean-author-field
  26. oricb-remove-period
  27. oricb-kill-fields
  28. oricb-replace-field-names)
  29. "Hook that is run in `org-ref-isbn-clean-bibtex-entry'.
  30. The functions should have no arguments, and operate on the bibtex
  31. entry at point. You can assume point starts at the beginning of the
  32. entry. These functions are wrapped in `save-restriction' and
  33. `save-excursion' so you do not need to save the point position."
  34. :group 'org-ref-isbn
  35. :type 'hook)
  36. (defcustom org-ref-isbn-exclude-fields nil
  37. "List of bibtex fields to kill when new entry is inserted."
  38. :group 'org-ref-isbn
  39. :type '(repeat :tag "List of bibtex fields to kill" string))
  40. (defcustom org-ref-isbn-field-name-replacements nil
  41. "List of bitex field name/replacement pairs.
  42. The entries in this list are cons cells where the car is the field name
  43. and cdr is the replacement name."
  44. :group 'org-ref-isbn
  45. :type '(repeat (cons (string :tag "Field name")
  46. (string :tag "Field name replacement"))))
  47. (defun oricb-replace-field-names ()
  48. "Replace bibtex field names defined in
  49. `org-ref-isbn-field-name-replacements'."
  50. (when org-ref-isbn-field-name-replacements
  51. (mapcar (lambda (field)
  52. (bibtex-beginning-of-entry)
  53. (let ((f (bibtex-autokey-get-field (car field))))
  54. (unless (string= "" f)
  55. (goto-char (cadr (bibtex-search-forward-field (car field) t)))
  56. (bibtex-kill-field)
  57. (bibtex-make-field (cdr field))
  58. (backward-char)
  59. (insert f))))
  60. org-ref-isbn-field-name-replacements)))
  61. (defun oricb-kill-fields ()
  62. "Kill all bibtex fields defined in `org-ref-isbn-exclude-fields'."
  63. (when org-ref-isbn-exclude-fields
  64. (mapcar (lambda (field)
  65. (bibtex-beginning-of-entry)
  66. (let ((f (bibtex-autokey-get-field field)))
  67. (unless (string= "" f)
  68. (goto-char (cadr (bibtex-search-forward-field field t)))
  69. (bibtex-kill-field))))
  70. org-ref-isbn-exclude-fields)))
  71. (defun oricb-remove-enclosing-brackets ()
  72. "Remove enclosing brackets from fields."
  73. (save-restriction
  74. (bibtex-narrow-to-entry)
  75. (while (re-search-forward "\\({\\)\\(\\[\\)\\(.+\\)\\(]\\)\\(}\\)" nil t)
  76. (replace-match "\\1\\3\\5"))))
  77. (defun oricb-clean-author-field ()
  78. "Remove extra information from author's field."
  79. (goto-char (cadr (bibtex-search-forward-field "author" t)))
  80. (let ((case-fold-search nil))
  81. (when (re-search-forward "\\({\\)\\(by \\|ed. by \\|edited by \\)" nil t)
  82. (replace-match "\\1"))))
  83. (defun oricb-remove-period ()
  84. "Remove period from author's field."
  85. (goto-char (cadr (bibtex-search-forward-field "author" t)))
  86. (when (re-search-forward "\\(\\.\\)\\(}\\)" nil t)
  87. (replace-match "\\2")))
  88. ;;;###autoload
  89. (defun org-ref-isbn-clean-bibtex-entry ()
  90. "Clean a bibtex entry inserted via `isbn-to-bibtex'.
  91. See functions in `org-ref-isbn-clean-bibtex-entry-hook'."
  92. (interactive)
  93. (bibtex-beginning-of-entry)
  94. (mapc (lambda (x)
  95. (save-restriction
  96. (save-excursion
  97. (funcall x))))
  98. org-ref-isbn-clean-bibtex-entry-hook))
  99. ;; I found this on the web. It can be handy, but the bibtex entry has a lot of stuff in it.
  100. ;;;###autoload
  101. (defun isbn-to-bibtex-lead (isbn)
  102. "Search lead.to for ISBN bibtex entry.
  103. You have to copy the entry if it is on the page to your bibtex
  104. file."
  105. (interactive "sISBN: ")
  106. (browse-url
  107. (format
  108. "http://lead.to/amazon/en/?key=%s+&si=all&op=bt&bn=&so=sa&ht=us"
  109. isbn)))
  110. ;; Here we get isbn metadata and build a bibtex entry.
  111. ;; http://xisbn.worldcat.org/xisbnadmin/doc/api.htm#getmetadata
  112. ;;;###autoload
  113. (defun isbn-to-bibtex (isbn bibfile)
  114. "Get bibtex entry for ISBN and insert it into BIBFILE.
  115. Nothing happens if an entry with the generated key already exists
  116. in the file. Data comes from worldcat."
  117. (interactive
  118. (list
  119. (read-string
  120. "ISBN: "
  121. ;; now set initial input
  122. (cond
  123. ;; If region is active and it starts with a number, we use it
  124. ((and (region-active-p)
  125. (s-match "^[0-9]" (buffer-substring (region-beginning) (region-end))))
  126. (buffer-substring (region-beginning) (region-end)))
  127. ;; if first entry in kill ring starts with a number assume it is an isbn
  128. ;; and use it as the guess
  129. ((stringp (car kill-ring))
  130. (when (s-match "^[0-9]" (car kill-ring))
  131. (car kill-ring)))
  132. ;; type or paste it in
  133. (t
  134. nil)))
  135. (completing-read "Bibfile: " (org-ref-possible-bibfiles))))
  136. (let* ((url (format "https://www.ottobib.com/isbn/%s/bibtex" isbn))
  137. (entry))
  138. (with-current-buffer (url-retrieve-synchronously url t t)
  139. (goto-char (point-min))
  140. (when (re-search-forward "@[a-zA-Z]+{.+\\(\n\s+[a-z\s={\.,?:;'0-9\n}-]+\\)+}$" nil t)
  141. (setq entry (match-string 0))))
  142. (if (not entry)
  143. (message "Nothing found.")
  144. (find-file bibfile)
  145. (goto-char (point-max))
  146. (insert (with-temp-buffer
  147. (insert (concat entry "\n}"))
  148. (goto-char (point-min))
  149. (org-ref-isbn-clean-bibtex-entry)
  150. (org-ref-clean-bibtex-entry)
  151. (bibtex-fill-entry)
  152. (s-trim (buffer-string))
  153. (buffer-string)))
  154. (save-buffer))))
  155. (provide 'org-ref-isbn)
  156. ;;; org-ref-isbn.el ends here