]> git.donarmstrong.com Git - org-ref.git/blobdiff - doi-utils.org
reimplement doi-utils-doi-to-bibtex-string
[org-ref.git] / doi-utils.org
index a29996f6810caf99fed664eba77bf3da816567b1..44e3317f42956f29ce8186e30538e2571152e0b3 100644 (file)
@@ -451,6 +451,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 :notangle doi-utils.el
+(defmacro defpar (name &optional value)
+  `(progn (defvar ,name)
+          (setf ,name ,value)))
+
+(defpar 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))
+      (journal    (plist-get results :container-title))
+      (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 :notangle doi-utils.el
+(defvar doi-utils-bibtex-type-generators nil)
+
+(defun 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)))
+         (concat-prepare (cdr lst) (cons (concat (car acc) (car lst))
+                                         (cdr acc))))
+        (t (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) (or (assoc field doi-utils-json-metadata-extract)
+                                          (error "unknown bibtex field type %s" field)))
+                           fields)
+               (concat
+                ,@(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)
+                                    `(,(concat "  " (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)
+#+END_SRC
+
+With the code generating the bibtex entry in place, we can glue it to the json retrieval code.
+#+BEGIN_SRC emacs-lisp :notangle 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* ((results (doi-utils-get-json-metadata doi))
+         (type (plist-get results :type)))
+    (format "%s" results) ; json-data
+    (some (lambda (g) (funcall g type results)) doi-utils-bibtex-type-generators)
+    (message-box "%s not supported yet." type)))
+#+END_SRC
+
+
 #+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"
@@ -1148,7 +1234,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))
@@ -1160,14 +1246,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', <i>Energy &amp; Environmental Science</i>, vol. 7, no. 6, p. 1996")
   (year . "2014")
   (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1039%2Fc3ee43874k&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Oxide+enthalpy+of+formation+and+band+gap+energy+as+accurate+descriptors+of+oxygen+vacancy+formation+energetics&amp;rft.jtitle=Energy+%26+Environmental+Science&amp;rft.date=2014&amp;rft.volume=7&amp;rft.issue=6&amp;rft.spage=1996&amp;rft.aufirst=Ann+M.&amp;rft.aulast=Deml&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Ann+M.+Deml&amp;rft.au=+Vladan+Stevanovi%C4%87&amp;rft.au=+Christopher+L.+Muhich&amp;rft.au=+Charles+B.+Musgrave&amp;rft.au=+Ryan+O%27Hayre")
@@ -1362,25 +1449,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