X-Git-Url: https://git.donarmstrong.com/?p=org-ref.git;a=blobdiff_plain;f=doi-utils.org;h=e0ab22b1cd315e1601fbb1baba4c4651a227880e;hp=7a22e75452ba174a164791592dfa1987ff7d98f9;hb=4b6c705cdc23015dcdbaba4cc0366b0a08db6693;hpb=f401452f60e5a8458d70b1fc5bd5e920ff599356 diff --git a/doi-utils.org b/doi-utils.org index 7a22e75..e0ab22b 100644 --- a/doi-utils.org +++ b/doi-utils.org @@ -436,7 +436,15 @@ For example: #+END_SRC #+RESULTS: -| :volume | 99 | :indexed | (:timestamp 1399964115538.0 :date-parts [[2014 5 13]]) | :publisher | American Physical Society (APS) | :source | CrossRef | :URL | http://dx.doi.org/10.1103/PhysRevLett.99.016105 | :ISSN | [0031-9007 1079-7114] | :DOI | 10.1103/physrevlett.99.016105 | :type | journal-article | :title | Scaling Properties of Adsorption Energies for Hydrogen-Containing Molecules on Transition-Metal Surfaces | :issue | 1 | :deposited | (:timestamp 1313712000000.0 :date-parts [[2011 8 19]]) | :reference-count | 26 | :container-title | Phys. Rev. Lett. | :author | [(:given F. :family Abild-Pedersen) (:given J. :family Greeley) (:given F. :family Studt) (:given J. :family Rossmeisl) (:given T. :family Munter) (:given P. :family Moses) (:given E. :family Skúlason) (:given T. :family Bligaard) (:given J. :family Nørskov)] | :prefix | http://id.crossref.org/prefix/10.1103 | :score | 1.0 | :issued | (:date-parts [[2007 7]]) | :subject | [Physics and Astronomy(all)] | :subtitle | [] | +| :member | http://id.crossref.org/member/16 | :volume | 99 | :indexed | (:timestamp 1423435577602 :date-parts [[2015 2 8]]) | :publisher | American Physical Society (APS) | :source | CrossRef | :URL | http://dx.doi.org/10.1103/PhysRevLett.99.016105 | :ISSN | [0031-9007 1079-7114] | :DOI | 10.1103/physrevlett.99.016105 | :type | journal-article | :title | Scaling Properties of Adsorption Energies for Hydrogen-Containing Molecules on Transition-Metal Surfaces | :issue | 1 | :deposited | (:timestamp 1313712000000 :date-parts [[2011 8 19]]) | :reference-count | 26 | :container-title | Phys. Rev. Lett. | :author | [(:given F. :family Abild-Pedersen) (:given J. :family Greeley) (:given F. :family Studt) (:given J. :family Rossmeisl) (:given T. :family Munter) (:given P. :family Moses) (:given E. :family Skúlason) (:given T. :family Bligaard) (:given J. :family Nørskov)] | :prefix | http://id.crossref.org/prefix/10.1103 | :score | 1.0 | :issued | (:date-parts [[2007 7]]) | :subject | [Physics and Astronomy(all)] | :subtitle | [] | + +or for a book: +#+BEGIN_SRC emacs-lisp :tangle no +(doi-utils-get-json-metadata "10.1007/978-1-4612-4968-9") +#+END_SRC + +#+RESULTS: +| :member | nil | :indexed | (:timestamp 1423773021494 :date-parts [[2015 2 12]]) | :publisher | Springer New York | :source | CrossRef | :URL | http://dx.doi.org/10.1007/978-1-4612-4968-9 | :ISBN | [http://id.crossref.org/isbn/978-0-387-96347-1 http://id.crossref.org/isbn/978-1-4612-4968-9] | :ISSN | [0172-6056] | :DOI | 10.1007/978-1-4612-4968-9 | :type | book | :title | Constructive Combinatorics | :deposited | (:timestamp 1378684800000 :date-parts [[2013 9 9]]) | :reference-count | 0 | :container-title | Undergraduate Texts in Mathematics | :author | [(:given Dennis :family Stanton) (:given Dennis :family White)] | :prefix | none | :score | 1.0 | :issued | (:date-parts [[1986]]) | :subtitle | [] | We can use that data to construct a bibtex entry. We do that by defining a template, and filling it in. I wrote this template expansion code which makes it easy to substitute values like %{} in emacs lisp. @@ -451,63 +459,92 @@ We can use that data to construct a bibtex entry. We do that by defining a templ Now we define a function that fills in that template from the metadata. +As different bibtex types share common keys, it is advantageous to separate data extraction from json, and the formatting of the bibtex entry. + +#+BEGIN_SRC emacs-lisp :tangle doi-utils.el +(setq doi-utils-json-metadata-extract + '((type (plist-get results :type)) + (author (mapconcat (lambda (x) (concat (plist-get x :given) " " (plist-get x :family))) + (plist-get results :author) " and ")) + (title (plist-get results :title)) + (subtitle (plist-get results :subtitle)) + (journal (plist-get results :container-title)) + (series (plist-get results :container-title)) + (publisher (plist-get results :publisher)) + (volume (plist-get results :volume)) + (issue (plist-get results :issue)) + (number (plist-get results :issue)) + (year (elt (elt (plist-get (plist-get results :issued) :date-parts) 0) 0)) + (month (elt (elt (plist-get (plist-get results :issued) :date-parts) 0) 1)) + (pages (plist-get results :page)) + (doi (plist-get results :DOI)) + (url (plist-get results :URL)) + (booktitle (plist-get results :container-title)))) +#+END_SRC + +Next, we need to define the different bibtex types. Each type has a bibtex type (for output) and the type as provided in the doi record. Finally, we have to declare the fields we want to output. + +#+BEGIN_SRC emacs-lisp :tangle doi-utils.el :results none +(setq doi-utils-bibtex-type-generators nil) + +(defun doi-utils-concat-prepare (lst &optional acc) + "Given a list `lst' of strings and other expressions, which are +intented to passed to `concat', concat any subsequent strings, +minimising the number of arguments being passed to `concat' +without changing the results." + (cond ((null lst) (nreverse acc)) + ((and (stringp (car lst)) + (stringp (car acc))) + (doi-utils-concat-prepare (cdr lst) (cons (concat (car acc) (car lst)) + (cdr acc)))) + (t (doi-utils-concat-prepare (cdr lst) (cons (car lst) acc))))) + +(defmacro doi-utils-def-bibtex-type (name matching-types &rest fields) + "Define a BibTeX type identified by (symbol) `name' with +`fields' (given as symbols), matching to retrieval expressions in +`doi-utils-json-metadata-extract'. This type will only be used +when the `:type' parameter in the JSON metadata is contained in +`matching-types' - a list of strings." + `(push (lambda (type results) + (when (or ,@(mapcar (lambda (match-type) `(string= type ,match-type)) matching-types)) + (let ,(mapcar (lambda (field) + (let ((field-expr (assoc field doi-utils-json-metadata-extract))) + (if field-expr + ;; need to convert to string first + `(,(car field-expr) (format "%s" ,(cadr field-expr))) + (error "unknown bibtex field type %s" field)))) + fields) + (concat + ,@(doi-utils-concat-prepare + (-flatten + (list (concat "@" (symbol-name name) "{,\n") + ;; there seems to be some bug with mapcan, + ;; so we fall back to flatten + (mapcar (lambda (field) + `(" " ,(symbol-name field) " = {" ,field "},\n")) + fields) + "}\n"))))))) + doi-utils-bibtex-type-generators)) + +(doi-utils-def-bibtex-type article ("journal-article" "article-journal") + author title journal year volume number pages doi url) + +(doi-utils-def-bibtex-type inproceedings ("proceedings-article") + author title booktitle year month pages doi url) + +(doi-utils-def-bibtex-type book ("book") + author title series publisher year pages doi url) +#+END_SRC + +With the code generating the bibtex entry in place, we can glue it to the json retrieval code. #+BEGIN_SRC emacs-lisp :tangle doi-utils.el (defun doi-utils-doi-to-bibtex-string (doi) "return a bibtex entry as a string for the doi. Only articles are currently supported" - (let (type - results - author - title - booktitle - journal - year - volume - number - pages - month - url - json-data) - (setq results (doi-utils-get-json-metadata doi) - json-data (format "%s" results) - type (plist-get results :type) - author (mapconcat (lambda (x) (concat (plist-get x :given) " " (plist-get x :family))) - (plist-get results :author) " and ") - title (plist-get results :title) - journal (plist-get results :container-title) - volume (plist-get results :volume) - issue (plist-get results :issue) - year (elt (elt (plist-get (plist-get results :issued) :date-parts) 0) 0) - pages (plist-get results :page) - doi (plist-get results :DOI) - url (plist-get results :URL)) - (cond - ((or (string= type "journal-article") (string= type "article-journal")) - (doi-utils-expand-template "@article{, - author = {%{author}}, - title = {%{title}}, - journal = {%{journal}}, - year = {%{year}}, - volume = {%{volume}}, - number = {%{issue}}, - pages = {%{pages}}, - doi = {%{doi}}, - url = {%{url}}, -}")) - - ((string= type "proceedings-article") - (setq booktitle (plist-get results :container-title)) - (doi-utils-expand-template "@inproceedings{, - author = {%{author}}, - title = {%{title}}, - booktitle = {%{booktitle}}, - year = {%{year}}, - month = {%{month}}, - pages = {%{pages}}, - doi = {%{doi}}, - url = {%{url}}, -}")) - - (t (message-box "%s not supported yet." type))))) + (let* ((results (doi-utils-get-json-metadata doi)) + (type (plist-get results :type))) + (format "%s" results) ; json-data + (or (some (lambda (g) (funcall g type results)) doi-utils-bibtex-type-generators) + (message-box "%s not supported yet." type)))) #+END_SRC #+RESULTS: @@ -521,15 +558,35 @@ To see that in action: #+RESULTS: #+begin_example @article{, - author = {F. Abild-Pedersen and J. Greeley and F. Studt and J. Rossmeisl and T. Munter and P. Moses and E. Skúlason and T. Bligaard and J. Nørskov}, - title = {Scaling Properties of Adsorption Energies for Hydrogen-Containing Molecules on Transition-Metal Surfaces}, - journal = {Phys. Rev. Lett.}, - year = {2007}, - volume = {99}, - number = {1}, - pages = {nil}, - doi = {10.1103/physrevlett.99.016105}, - url = {http://dx.doi.org/10.1103/PhysRevLett.99.016105}, + author = {F. Abild-Pedersen and J. Greeley and F. Studt and J. Rossmeisl and T. Munter and P. Moses and E. Skúlason and T. Bligaard and J. Nørskov}, + title = {Scaling Properties of Adsorption Energies for Hydrogen-Containing Molecules on Transition-Metal Surfaces}, + journal = {Phys. Rev. Lett.}, + year = {2007}, + volume = {99}, + number = {1}, + pages = {nil}, + doi = {10.1103/physrevlett.99.016105}, + url = {http://dx.doi.org/10.1103/PhysRevLett.99.016105}, +} +#+end_example + +and for a book: + +#+BEGIN_SRC emacs-lisp :tangle no +(doi-utils-doi-to-bibtex-string "10.1007/978-1-4612-4968-9") +#+END_SRC + +#+RESULTS: +#+begin_example +@book{, + author = {Dennis Stanton and Dennis White}, + title = {Constructive Combinatorics}, + series = {Undergraduate Texts in Mathematics}, + publisher = {Springer New York}, + year = {1986}, + pages = {nil}, + doi = {10.1007/978-1-4612-4968-9}, + url = {http://dx.doi.org/10.1007/978-1-4612-4968-9}, } #+end_example @@ -915,7 +972,9 @@ The idea here is to perform a query on Crossref, get a helm buffer of candidates (cond ;; If region is active assume we want it ((region-active-p) - (buffer-substring (region-beginning) (region-end))) + (replace-regexp-in-string + "\n" " " + (buffer-substring (region-beginning) (region-end)))) ;; type or paste it in (t nil))) @@ -935,7 +994,9 @@ The idea here is to perform a query on Crossref, get a helm buffer of candidates (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" query)) + (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 @@ -1144,7 +1205,7 @@ The idea here is to perform a query on Crossref, get a helm buffer of candidates #+END_EXAMPLE -#+BEGIN_SRC emacs-lisp :var data=json :results value raw +#+BEGIN_SRC emacs-lisp :var data=json :results value raw :tangle no (let ((json-object-type 'plist) (json (json-read-from-string data))) (aref json 0)) @@ -1156,14 +1217,15 @@ The idea here is to perform a query on Crossref, get a helm buffer of candidates Here is a list of helm candidates -#+BEGIN_SRC emacs-lisp :var data=json :results code +#+BEGIN_SRC emacs-lisp :var data=json :results code :tangle no (let (;(json-object-type 'plist) (json (json-read-from-string data))) (mapcar (lambda (x) (cons (assoc 'fullCitation x) x)) json)) #+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") @@ -1256,7 +1318,7 @@ I found this on the web. It can be handy, but the bibtex entry has a lot of stuf #+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 "ISBN: ") + (interactive "sISBN: ") (browse-url (format "http://lead.to/amazon/en/?key=%s+&si=all&op=bt&bn=&so=sa&ht=us" isbn))) #+END_SRC @@ -1358,25 +1420,3 @@ entry with the generated key already exists in the file." #+RESULTS: : Loaded doi-utils.el - - - - - -#+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_SRC - -#+RESULTS: -: you chose jim@email.com