add set dialect to org-ref-bib-citation
[org-ref.git] / isbn.el
1 ;;; isbn.el --- utilities for generating bibtex entries from an ISBN  -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2015  John Kitchin
4
5 ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
6 ;; Keywords: convenience
7
8 ;; This program is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation, either version 3 of the License, or
11 ;; (at your option) any later version.
12
13 ;; This program is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Commentary:
22
23 ;;
24
25 ;;; Code:
26
27 ;; * ISBN utility
28
29 ;; I found this on the web. It can be handy, but the bibtex entry has a lot of stuff in it.
30
31 (defun isbn-to-bibtex-lead (isbn)
32  "Search lead.to for ISBN bibtex entry.
33 You have to copy the entry if it is on the page to your bibtex
34 file."
35  (interactive "sISBN: ")
36  (browse-url
37   (format
38    "http://lead.to/amazon/en/?key=%s+&si=all&op=bt&bn=&so=sa&ht=us"
39    isbn)))
40
41 ;; Here we get isbn metadata and build a bibtex entry.
42 ;; http://xisbn.worldcat.org/xisbnadmin/doc/api.htm#getmetadata
43
44 (defun isbn-to-bibtex (isbn bibfile)
45   "Get bibtex entry for ISBN and insert it into BIBFILE unless an
46 entry with the generated key already exists in the file."
47   (interactive
48    (list
49     (read-string
50      "ISBN: "
51      ;; now set initial input
52      (cond
53       ;; If region is active and it starts with a number, we use it
54       ((and  (region-active-p)
55              (s-match "^[0-9]" (buffer-substring (region-beginning) (region-end))))
56        (buffer-substring (region-beginning) (region-end)))
57       ;; if first entry in kill ring starts with a number assume it is an isbn
58       ;; and use it as the guess
59       ((if (s-match "^[0-9]" (car kill-ring))
60            (car kill-ring)))
61       ;; type or paste it in
62       (t
63        nil)))
64     (ido-completing-read
65      "Bibfile: "
66      (append (f-entries "." (lambda (f) (f-ext? f "bib")))
67              org-ref-default-bibliography))))
68
69   (let* ((results (with-current-buffer
70                       (url-retrieve-synchronously
71                        (format
72                         "http://xisbn.worldcat.org/webservices/xid/isbn/%s?method=getMetadata&format=json&fl=*"
73                         isbn))
74                     (json-read-from-string
75                      (buffer-substring url-http-end-of-headers (point-max)))))
76          (status (cdr (nth 1 results)))
77          (metadata (aref (cdar results) 0))
78          (new-entry)
79          (new-key))
80
81     ;; check if we got something
82     (unless (string= "ok" status)
83       (error "Status is %s" status))
84
85     ;; construct an alphabetically sorted bibtex entry. I assume ISBN numbers go
86     ;; with book entries.
87     (setq new-entry
88           (concat "\n@book{,\n"
89                   (mapconcat
90                    'identity
91                    (cl-loop for field in (-sort 'string-lessp (mapcar 'car metadata))
92                             collect
93                             (format "  %s={%s}," field (cdr (assoc field metadata))))
94                    "\n")
95                   "\n}\n"))
96
97     ;; build entry in temp buffer to get the key so we can check for duplicates
98     (setq new-entry (with-temp-buffer
99                       (insert new-entry)
100                       (org-ref-clean-bibtex-entry)
101                       (setq new-key (bibtex-key-in-head))
102                       (buffer-string)))
103     (find-file bibfile)
104     (goto-char (point-min))
105     (when (search-forward new-key nil t)
106       (beep)
107       (setq new-key (read-string
108                      (format  "%s already exists. Enter new key (C-g to cancel): " new-key)
109                      new-key)))
110     (goto-char (point-max))
111     (insert new-entry)
112     ;; set key. It is simplest to just replace it, even if it is the same.
113     (bibtex-beginning-of-entry)
114     (re-search-forward bibtex-entry-maybe-empty-head)
115     (if (match-beginning bibtex-key-in-head)
116         (delete-region (match-beginning bibtex-key-in-head)
117                        (match-end bibtex-key-in-head)))
118     (insert new-key)
119     (bibtex-fill-entry)
120     (save-buffer)))
121
122 (provide 'isbn)
123 ;;; isbn.el ends here