X-Git-Url: https://git.donarmstrong.com/?p=org-ref.git;a=blobdiff_plain;f=doi-utils.org;h=68c74bcc3fde4ff88d3daa94bc5b934e99ddc400;hp=b8e6d3c7102c48a0fc59f5e14a4f4823fe3e05ec;hb=b27a82139b93605379c12ce4221581990de2da44;hpb=d40ccca9dd2b3003258ad6d5d63b35b946e3f54a diff --git a/doi-utils.org b/doi-utils.org index b8e6d3c..68c74bc 100644 --- a/doi-utils.org +++ b/doi-utils.org @@ -570,7 +570,7 @@ prompt. Otherwise, you have to type or pste in a DOI." (s-match "^10" (buffer-substring (region-beginning) (region-end)))) - (buffer-susbstring (region-beginning) (region-end))) + (buffer-substring (region-beginning) (region-end))) ;; if the first entry in the kill-ring looks ;; like a DOI, let's use it. ((if (s-match "^10" (car kill-ring)) @@ -903,7 +903,61 @@ error." +* Adding a bibtex entry from a crossref query +The idea here is to perform a query on Crossref, get a helm buffer of candidates, and select the entry(ies) you want to add to your bibtex file. You can select a region, e.g. a free form citation, or set of words, or you can type the query in by hand. +#+BEGIN_SRC emacs-lisp :tangle doi-utils.el +(defun doi-utils-add-entry-from-crossref-query (query bibtex-file) + (interactive (list + (read-input + "Query: " + ;; now set initial input + (cond + ;; If region is active assume we want it + ((region-active-p) + (replace-regexp-in-string + "\n" " " + (buffer-substring (region-beginning) (region-end)))) + ;; type or paste it in + (t + nil))) + (ido-completing-read + "Bibfile: " + (append (f-entries "." (lambda (f) (f-ext? f "bib"))) + org-ref-default-bibliography)))) + (let* ((json-string) + (json-data) + (doi)) + + (with-current-buffer + (url-retrieve-synchronously + (concat + "http://search.crossref.org/dois?q=" + (url-hexify-string query))) + (setq json-string (buffer-substring url-http-end-of-headers (point-max))) + (setq json-data (json-read-from-string json-string))) + + (let* ((name (format "Crossref hits for %s" + ;; remove carriage returns. they cause problems in helm. + (replace-regexp-in-string "\n" " " query))) + (helm-candidates (mapcar (lambda (x) + (cons + (concat + (cdr (assoc 'fullCitation x)) + " " + (cdr (assoc 'doi x))) + (cdr (assoc 'doi x)))) + json-data)) + (source `((name . ,name) + (candidates . ,helm-candidates) + ;; just return the candidate + (action . (("Insert bibtex entry" . (lambda (doi) + (doi-utils-add-bibtex-entry-from-doi + (replace-regexp-in-string "^http://dx.doi.org/" "" doi) ,bibtex-file))) + ("Open url" . (lambda (doi) + (browse-url doi)))))))) + (helm :sources '(source))))) +#+END_SRC ** json @@ -1113,7 +1167,8 @@ Here is a list of helm candidates #+END_SRC #+RESULTS: -#+BEGIN_SRC emacs-lisp +#+BEGIN_SRC emacs-lisp :tangle no + (((fullCitation . "Ann M. Deml, Vladan Stevanovi\304\207, Christopher L. Muhich, Charles B. Musgrave, Ryan O'Hayre, 2014, 'Oxide enthalpy of formation and band gap energy as accurate descriptors of oxygen vacancy formation energetics', Energy & Environmental Science, vol. 7, no. 6, p. 1996") (year . "2014") (coins . "ctx_ver=Z39.88-2004&rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1039%2Fc3ee43874k&rfr_id=info%3Asid%2Fcrossref.org%3Asearch&rft.atitle=Oxide+enthalpy+of+formation+and+band+gap+energy+as+accurate+descriptors+of+oxygen+vacancy+formation+energetics&rft.jtitle=Energy+%26+Environmental+Science&rft.date=2014&rft.volume=7&rft.issue=6&rft.spage=1996&rft.aufirst=Ann+M.&rft.aulast=Deml&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&rft.genre=article&rft.au=Ann+M.+Deml&rft.au=+Vladan+Stevanovi%C4%87&rft.au=+Christopher+L.+Muhich&rft.au=+Charles+B.+Musgrave&rft.au=+Ryan+O%27Hayre") @@ -1197,36 +1252,114 @@ Here is a list of helm candidates ...) #+END_SRC -* end of file -#+BEGIN_SRC emacs-lisp :tangle doi-utils.el -(provide 'doi-utils) -#+END_SRC -* load -#+BEGIN_SRC emacs-lisp :tangle no -(org-babel-load-file "doi-utils.org") -#+END_SRC -#+RESULTS: -: Loaded doi-utils.el +* ISBN utility +These are not really doi utilities, but for now I am putting them here. +I found this on the web. It can be handy, but the bibtex entry has a lot of stuff in it. + +#+BEGIN_SRC emacs-lisp :tangle doi-utils.el +(defun isbn-to-bibtex-lead (isbn) + "Search lead.to for ISBN bibtex entry. You have to copy the entry if it is on the page to your bibtex file." + (interactive "sISBN: ") +(browse-url +(format "http://lead.to/amazon/en/?key=%s+&si=all&op=bt&bn=&so=sa&ht=us" isbn))) +#+END_SRC +Here we get isbn metadata and build a bibtex entry. +http://xisbn.worldcat.org/xisbnadmin/doc/api.htm#getmetadata +#+BEGIN_SRC emacs-lisp :tangle doi-utils.el +(defun isbn-to-bibtex (isbn bibfile) + "Get bibtex entry for ISBN and insert it into BIBFILE unless an +entry with the generated key already exists in the file." + (interactive + (list + (read-input + "ISBN: " + ;; now set initial input + (cond + ;; If region is active and it starts with a number, we use it + ((and (region-active-p) + (s-match "^[0-9]" (buffer-substring (region-beginning) (region-end)))) + (buffer-substring (region-beginning) (region-end))) + ;; if first entry in kill ring starts with a number assume it is an isbn + ;; and use it as the guess + ((if (s-match "^[0-9]" (car kill-ring)) + (car kill-ring))) + ;; type or paste it in + (t + nil))) + (ido-completing-read + "Bibfile: " + (append (f-entries "." (lambda (f) (f-ext? f "bib"))) + org-ref-default-bibliography)))) + + (let* ((results (with-current-buffer + (url-retrieve-synchronously + (format + "http://xisbn.worldcat.org/webservices/xid/isbn/%s?method=getMetadata&format=json&fl=*" + isbn)) + (json-read-from-string + (buffer-substring url-http-end-of-headers (point-max))))) + (status (cdr (nth 1 results))) + (metadata (aref (cdar results) 0)) + (new-entry) + (new-key)) + + ;; check if we got something + (unless (string= "ok" status) + (error "Status is %s" status)) + + ;; construct an alphabetically sorted bibtex entry. I assume ISBN numbers go + ;; with book entries. + (setq new-entry + (concat "\n@book{,\n" + (mapconcat + 'identity + (loop for field in (-sort 'string-lessp (mapcar 'car metadata)) + collect + (format " %s={%s}," field (cdr (assoc field metadata)))) + "\n") + "\n}\n")) + + ;; build entry in temp buffer to get the key so we can check for duplicates + (setq new-entry (with-temp-buffer + (insert new-entry) + (org-ref-clean-bibtex-entry) + (setq new-key (bibtex-key-in-head)) + (buffer-string))) + (find-file bibfile) + (goto-char (point-min)) + (when (search-forward new-key nil t) + (beep) + (setq new-key (read-input + (format "%s already exists. Enter new key (C-g to cancel): " new-key) + new-key))) + (goto-char (point-max)) + (insert new-entry) + ;; set key. It is simplest to just replace it, even if it is the same. + (bibtex-beginning-of-entry) + (re-search-forward bibtex-entry-maybe-empty-head) + (if (match-beginning bibtex-key-in-head) + (delete-region (match-beginning bibtex-key-in-head) + (match-end bibtex-key-in-head))) + (insert new-key) + (bibtex-fill-entry) + (save-buffer))) +#+END_SRC -#+BEGIN_SRC emacs-lisp -(setq data '(("John" . "john@email.com") - ("Jim" . "jim@email.com") - ("Jane" . "jane@email.com") - ("Jill" . "jill@email.com"))) -(setq some-helm-source - `((name . "HELM at the Emacs") - (candidates . ,(mapcar 'car data)) - (action . (lambda (candidate) - (message-box "%s" (cdr (assoc candidate data))))))) -(message-box "you chose %s" (helm :sources '(some-helm-source))) +* end of file +#+BEGIN_SRC emacs-lisp :tangle doi-utils.el +(provide 'doi-utils) +#+END_SRC +* load +#+BEGIN_SRC emacs-lisp :tangle no +(org-babel-load-file "doi-utils.org") #+END_SRC #+RESULTS: -: you chose jim@email.com +: Loaded doi-utils.el