]> git.donarmstrong.com Git - org-ref.git/commitdiff
Merge remote-tracking branch 'origin/master'
authorDon Armstrong <don@donarmstrong.com>
Mon, 1 Jun 2015 15:14:41 +0000 (08:14 -0700)
committerDon Armstrong <don@donarmstrong.com>
Mon, 1 Jun 2015 15:14:41 +0000 (08:14 -0700)
Conflicts:
Makefile
org-ref.org

20 files changed:
.gitignore
.travis.yml [new file with mode: 0644]
Cask [new file with mode: 0644]
Makefile [deleted file]
README.org
arxiv.el
doi-utils.el [new file with mode: 0644]
doi-utils.org [deleted file]
isbn.el [new file with mode: 0644]
jmax-bibtex.el
org-ref-test.el [new file with mode: 0644]
org-ref.bib [new file with mode: 0644]
org-ref.el [new file with mode: 0644]
org-ref.org [deleted file]
pubmed.el [new file with mode: 0644]
pubmed.org [deleted file]
sci-id.el [new file with mode: 0644]
test.bib
wos.el [new file with mode: 0644]
x2bib.el [new file with mode: 0644]

index 356702b5f740fa45751c0da765600dd2124105fd..db157c44d972f96e98e3ec41d681c20af82b42ef 100644 (file)
@@ -1,2 +1,23 @@
-*.el
-*.elc
\ No newline at end of file
+*.elc
+/dist/
+/.cask/
+/.projectile
+/doi-utils.org.orig
+/pubmed.org.orig
+/doi-utils-2.el
+/org-ref.org.orig
+/org-ref.html
+/org-ref.bbl
+/org-ref.blg
+/org-ref.pdf
+/org-ref.tex
+/org-ref.ilg
+/org-ref.ind
+/org-ref.lof
+/org-ref.lot
+/test.bbl
+/test.blg
+/test.html
+/test.org
+/test.pdf
+/test.tex
diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..d51906f
--- /dev/null
@@ -0,0 +1,20 @@
+language: emacs-lisp
+
+env:
+  matrix:
+    - emacs=emacs-snapshot
+
+before_install:
+  - sudo add-apt-repository -y ppa:ubuntu-elisp/ppa
+  - sudo apt-get update -qq
+  - sudo apt-get install -qq $emacs
+
+  # Install cask dependencies
+  - curl -fsSLo /tmp/cask-master.zip https://github.com/cask/cask/archive/master.zip
+  - sudo unzip -qq -d /opt /tmp/cask-master.zip
+  - sudo ln -sf /opt/cask-master/bin/cask /usr/local/bin/cask
+  - cask
+
+script:
+  - emacs --version
+  - make test
\ No newline at end of file
diff --git a/Cask b/Cask
new file mode 100644 (file)
index 0000000..b1b0bd3
--- /dev/null
+++ b/Cask
@@ -0,0 +1,17 @@
+(source gnu)
+(source melpa)
+
+(package-file "org-ref.el")
+
+(development
+ (depends-on "ecukes")
+ (depends-on "ert-runner")
+ (depends-on "el-mock")
+ (depends-on "dash")
+ (depends-on "helm")
+ (depends-on "helm-bibtex")
+ (depends-on "s")
+ (depends-on "f")
+ (depends-on "hydra")
+ (depends-on "key-chord")
+ (depends-on "parsebib"))
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index bb522b5..0000000
--- a/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/make -f
-
-WHICH_EMACS:=$(shell which emacs >/dev/null 2>&1 || echo "fail")
-
-ELC_FILES=
-ifeq ($(strip $(WHICH_EMACS)),)
-ELC_FILES=$(patsubst %.el,%.elc,$(wildcard *.el)) org-ref.elc doi-utils.elc pubmed.elc
-endif
-
-all: $(ELC_FILES)
-
-EMACS=emacs
-
-%.elc: %.el
-       $(EMACS) -q -no-site-file -L . -L .. -L ../helm --no-site-file -batch -f batch-byte-compile $<;
-
-
-%.el: %.org
-       $(EMACS) -batch -q -no-site-file --visit $< --funcall org-babel-tangle
-
-
index 90a2443bef864edd1b7083e9873507dee4212ce7..3f3489b3b37eb9a7690834325c94830ed22f0cfc 100644 (file)
@@ -1,26 +1,60 @@
+# -*- org-edit-src-content-indentation: 0; -*-
 #+TITLE: org-ref: citations, cross-references, indexes, glossaries and bibtex utilities for org-mode
 
+#+BEGIN_HTML
+<a href="https://travis-ci.org/jkitchin/org-ref"><img src="https://travis-ci.org/jkitchin/org-ref.svg?branch=master"></a>
+#+END_HTML
+
 See http://www.youtube.com/watch?v=Zya8SfmCtFA and https://www.youtube.com/watch?v=JyvpSVl4_dg for examples of org-ref in action.
 
 [[./org-ref.org]] contains all documentation and installation instructions.
 
-[[./doi-utils.org]] contains functions for downloading bibtex entries from  a DOI, and redefines the org-mode doi link so it has more functionality. 
-
-[[./jmax-bibtex.el]] contains some utility functions:
 
-1. jmax-bibtex runs a menu command with actions to run on a bibtex entry including looking up the doi for the entry in a variety of places, e.g. web of science related/citing articles, Google Scholar, Pubmed, and crossref, or opening a PDF associated with the entry.
+* Installation
+We are slowly moving towards getting org-ref in MELPA. Until then, here are some directions that will probably help install org-ref.
 
-2. Bind M-n/M-p to next/previous bibtex entry.
+You should clone this repository somewhere.
 
-3. Sentence/title casing the title of a bibtex entry
+You should set these variables. Here is an example of how mine are set in an init.el file.
+#+BEGIN_SRC emacs-lisp
+(setq reftex-default-bibliography '("~/Dropbox/bibliography/references.bib"))
 
-4. Function to replace non-ascii characters in bibtex entries
+;; see org-ref for use of these variables
+(setq org-ref-bibliography-notes "~/Dropbox/bibliography/notes.org"
+      org-ref-default-bibliography '("~/Dropbox/bibliography/references.bib")
+      org-ref-pdf-directory "~/Dropbox/bibliography/bibtex-pdfs/")
+#+END_SRC
 
-5. Functions to replace journal names with @string entries, and corresponding short/long names.
+You may want to set some convenient keys for working in your bibtex file:
 
-To install this, add the org-ref repo directory to your load-path, and 
+#+BEGIN_SRC emacs-lisp
+(global-set-key [f10] 'org-ref-open-bibtex-notes)
+(global-set-key [f11] 'org-ref-open-bibtex-pdf)
+(global-set-key [f12] 'org-ref-open-in-browser)
+#+END_SRC
 
+Add the directory you cloned org-ref into to your load-path, and require the features you want.
 #+BEGIN_SRC emacs-lisp
 (add-to-list 'load-path "path-to-org-ref")
+;; make sure you have dash, helm, helm-bibtex, ebib, s, f, hydra and key-chord
+;; in your load-path
+(require 'org-ref)
+
+;; optional but very useful libraries in org-ref
+(require 'doi-utils)
 (require 'jmax-bibtex)
+(require 'pubmed)
+(require 'arxiv)
+(require 'sci-id)
 #+END_SRC
+
+Please report errors here:  [[https://github.com/jkitchin/org-ref/issues][issue]]s.
+
+* Contributors
+I would like to thank the following [[https://github.com/jkitchin/org-ref/graphs/contributors][contributors]] to org-ref
+
+- https://github.com/divinenephron
+- https://github.com/OlafMerkert
+- https://github.com/prtkm
+
+And everyone who has filed an [[https://github.com/jkitchin/org-ref/issues][issue]], or asked about org-ref on the [[http://orgmode.org/community.html][org-mode Mailing list]].
index c5548c13c1111474d25951501c9a9d5bd02e27d4..4ca96afa9f6e24964776a0c49a43215d74cdba69 100644 (file)
--- a/arxiv.el
+++ b/arxiv.el
@@ -1,3 +1,32 @@
+;;; arxiv.el --- arxiv utilities for org-mode        -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; this library creates a new org-link for Arxiv (http://arxiv.org/) entries,
+;; and provides functions to retrieve bibtex entries from an Arxiv number.
+;;
+;; An Arxiv number might look like: cond-mat/0410285 or 1503.01742
+
+;;; Code:
+;; * The org-mode link
+;; this just makes a clickable link that opens the entry.
 (org-add-link-type
  "arxiv"
  ;; clicking
      (format "\\url{http://arxiv.org/abs/%s}" keyword)))))
 
 ;; arxiv:cond-mat/0410285
+
+;; * Getting a bibtex entry for an arxiv article
+;; For an arxiv article, there is a link to a NASA ADS page like this:
+;; http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:1503.01742
+;; On that page, there is a link to a bibtex entry:
+;; http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=2015arXiv150301742H&data_type=BIBTEX&db_key=PRE&nocookieset=1
+;;
+;; It looks like you need to get a Bibliographic code from the arxiv number to
+;; then get the bibtex entry.
+
+(defun arxiv-get-bibliographic-code (arxiv-number)
+  "Get Bibliographic code for ARXIV-NUMBER."
+  (with-current-buffer
+      (url-retrieve-synchronously
+       (concat
+       "http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:"
+       arxiv-number))
+    (search-forward-regexp "name=\\\"bibcode\\\" value=\\\"\\(.*\\)\\\"")
+    (match-string 1)))
+
+(defun arxiv-get-bibtex-entry (arxiv-bibliographic-code)
+  "Get bibtex entry for ARXIV-BIBLIOGRAPHIC-CODE"
+  (with-current-buffer
+      (url-retrieve-synchronously
+       (format
+       "http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=%s&data_type=BIBTEX&db_key=PRE&nocookieset=1"
+       arxiv-bibliographic-code))
+    (goto-char  url-http-end-of-headers)
+    (if (search-forward  "Retrieved 1 abstracts" (point-max) t)
+       (progn
+         (forward-line)
+         (buffer-substring (point) (point-max)))
+      (error "Did not get one entry: %s" (buffer-substring (point) (point-max))))))
+
+
+(defun arxiv-add-bibtex-entry (arxiv-number bibfile)
+  "Add bibtex entry for ARXIV-NUMBER to BIBFILE."
+ (interactive
+   (list (read-string "arxiv: ")
+        ;;  now get the bibfile to add it to
+        (ido-completing-read
+         "Bibfile: "
+         (append (f-entries "." (lambda (f) (f-ext? f "bib")))
+                 org-ref-default-bibliography))))
+ (save-window-excursion
+   (find-file bibfile)
+   (goto-char (point-max))
+   (when (not (looking-at "^")) (insert "\n"))
+   (insert (arxiv-get-bibtex-entry (arxiv-get-bibliographic-code arxiv-number)))
+   (save-buffer)))
+
+
+(defun arxiv-get-pdf (arxiv-number pdf)
+  "Retrieve a pdf for ARXIV-NUMBER and save it to PDF."
+  (interactive "sarxiv: \nsPDF: ")
+  (let ((pdf-url (with-current-buffer
+                    (url-retrieve-synchronously
+                     (concat
+                      "http://arxiv.org/abs/" arxiv-number))
+                  ;; <meta name="citation_pdf_url" content="http://arxiv.org/pdf/0801.1144" />
+                  (search-forward-regexp
+                   "name=\\\"citation_pdf_url\\\" content=\\\"\\(.*\\)\\\"")
+                  (match-string 1))))
+    (url-copy-file pdf-url pdf)
+    ;; now check if we got a pdf
+    (with-temp-buffer
+      (insert-file-contents pdf)
+      ;; PDFS start with %PDF-1.x as the first few characters.
+      (if (not (string= (buffer-substring 1 6) "%PDF-"))
+         (progn
+           (message "%s" (buffer-string))
+           (delete-file pdf))
+       (message "%s saved" pdf)))
+
+    (org-open-file pdf)))
+
+(provide 'arxiv)
+;;; arxiv.el ends here
diff --git a/doi-utils.el b/doi-utils.el
new file mode 100644 (file)
index 0000000..fa79d57
--- /dev/null
@@ -0,0 +1,972 @@
+;;; doi-utils.el --- DOI utilities for making bibtex entries
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; Keywords: convenience
+;; Version: 0.1
+;; Package-Requires: ((org-ref))
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides functionality to download PDFs and bibtex entries from a DOI, as well as to update a bibtex entry from a DOI.  It depends slightly on org-ref, to determine where to save pdf files too, and where to insert bibtex entries in the default bibliography.
+
+;; The principle commands you will use from here are:
+
+;; - doi-utils-get-bibtex-entry-pdf with the cursor in a bibtex entry.
+;; - doi-utils-insert-bibtex-entry-from-doi to insert a bibtex entry at your cursor, clean it and try to get a pdf.
+;; - doi-utils-add-bibtex-entry-from-doi to add an entry to your default bibliography (cleaned with pdf if possible).
+;; - doi-utils-add-bibtex-entry-from-region to add an entry from a highlighed doi to your default bibliography.
+;; - doi-utils-update-bibtex-entry-from-doi with cursor in an entry to update its fields.
+
+(require 'json)
+
+;;; Code:
+;; * Getting pdf files from a DOI
+;; The idea here is simple. When you visit http://dx.doi.org/doi, you get redirected to the journal site. Once you have the url for the article, you can usually compute the url to the pdf, or find it in the page. Then you simply download it.
+
+;; There are some subtleties in doing this that are described here. To get the redirect, we have to use url-retrieve, and a callback function. The callback does not return anything, so we communicate through global variables. url-retrieve is asynchronous, so we have to make sure to wait for it to finish.
+
+(defvar *doi-utils-waiting* t
+  "Stores waiting state for url retrieval.")
+
+(defvar *doi-utils-redirect* nil
+  "Stores redirect url from a callback function.")
+
+(defun doi-utils-redirect-callback (&optional status)
+  "Callback for `url-retrieve' to set the redirect.
+Optional argument STATUS Unknown why this is optional."
+  (when (plist-get status :error)
+    (signal (car (plist-get status :error)) (cdr(plist-get status :error))))
+  (when (plist-get status :redirect) ;  is nil if there none
+    (message "redirects = %s" (plist-get status :redirect))
+    (message "*doi-utils-redirect* set to %s"
+            (setq *doi-utils-redirect* (plist-get status :redirect))))
+  ;; we have done our job, so we are not waiting any more.
+  (setq *doi-utils-waiting* nil))
+
+;; To actually get the redirect we use url-retrieve like this.
+
+(defun doi-utils-get-redirect (doi)
+  "Get redirect url from dx.DOI.org/doi."
+  ;; we are going to wait until the url-retrieve is done
+  (setq *doi-utils-waiting* t)
+  ;; start with no redirect. it will be set in the callback.
+  (setq *doi-utils-redirect* nil)
+  (url-retrieve
+   (format "http://dx.doi.org/%s" doi)
+   'doi-utils-redirect-callback)
+  ; I suspect we need to wait here for the asynchronous process to
+  ; finish. we loop and sleep until the callback says it is done via
+  ; `*doi-utils-waiting*'. this works as far as i can tell. Before I
+  ; had to run this a few times to get it to work, which i suspect
+  ; just gave the first one enough time to finish.
+  (while *doi-utils-waiting* (sleep-for 0.1)))
+
+;; Once we have a redirect for a particular doi, we need to compute the url to the pdf. We do this with a series of functions. Each function takes a single argument, the redirect url. If it knows how to compute the pdf url it does, and returns it. We store the functions in a variable:
+
+(defvar doi-utils-pdf-url-functions nil
+  "List of functions that return a url to a pdf from a redirect url.  Each function takes one argument, the redirect url.  The function must return a pdf-url, or nil.")
+
+
+;; ** APS journals
+
+(defun aps-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://journals.aps.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "/abstract/" "/pdf/" *doi-utils-redirect*)))
+
+
+;; ** Science
+
+(defun science-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://www.sciencemag.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf")))
+
+
+;; ** Nature
+
+(defun nature-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://www.nature.com" *doi-utils-redirect*)
+    (let ((result *doi-utils-redirect*))
+      (setq result (replace-regexp-in-string "/full/" "/pdf/" result))
+      (replace-regexp-in-string "\.html$" "\.pdf" result))))
+
+
+;; ** Wiley
+;; http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/abstract
+;; http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/pdf
+
+;; It appears that it is not enough to use the pdf url above. That takes you to an html page. The actual link to teh pdf is embedded in that page. This is how ScienceDirect does things too.
+
+;; This is where the link is hidden:
+
+;; <iframe id="pdfDocument" src="http://onlinelibrary.wiley.com/store/10.1002/anie.201402680/asset/6397_ftp.pdf?v=1&amp;t=hwut2142&amp;s=d4bb3cd4ad20eb733836717f42346ffb34017831" width="100%" height="675px"></iframe>
+
+
+(defun doi-utils-get-wiley-pdf-url (redirect-url)
+  "Wileyscience direct hides the pdf url in html.
+We get it out here by parsing the html.
+Argument REDIRECT-URL URL you are redirected to."
+  (setq *doi-utils-waiting* t)
+  (url-retrieve redirect-url
+               (lambda (status)
+                 (goto-char (point-min))
+                 (re-search-forward "<iframe id=\"pdfDocument\" src=\"\\([^\"]*\\)\"" nil)
+                 (setq *doi-utils-pdf-url* (match-string 1)
+                       *doi-utils-waiting* nil)))
+  (while *doi-utils-waiting* (sleep-for 0.1))
+  *doi-utils-pdf-url*)
+
+(defun wiley-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://onlinelibrary.wiley.com" *doi-utils-redirect*)
+    (doi-utils-get-wiley-pdf-url
+     (replace-regexp-in-string "/abstract" "/pdf" *doi-utils-redirect*))
+   *doi-utils-pdf-url*))
+
+
+;; ** Springer
+
+(defun springer-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://link.springer.com" *doi-utils-redirect*)
+    (replace-regexp-in-string "/article/" "/content/pdf/" (concat *doi-utils-redirect* ".pdf"))))
+
+
+;; ** ACS
+;; here is a typical url http://pubs.acs.org/doi/abs/10.1021/nl500037x
+;; the pdf is found at http://pubs.acs.org/doi/pdf/10.1021/nl500037x
+
+;; we just change /abs/ to /pdf/.
+
+(defun acs-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://pubs.acs.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "/abs/" "/pdf/" *doi-utils-redirect*)))
+
+
+;; ** IOP
+
+(defun iop-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://iopscience.iop.org" *doi-utils-redirect*)
+    (let ((tail (replace-regexp-in-string
+                "^http://iopscience.iop.org" "" *doi-utils-redirect*)))
+      (concat "http://iopscience.iop.org" tail
+             "/pdf" (replace-regexp-in-string "/" "_" tail) ".pdf"))))
+
+
+;; ** JSTOR
+
+(defun jstor-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://www.jstor.org" *doi-utils-redirect*)
+    (concat (replace-regexp-in-string "/stable/" "/stable/pdfplus/" *doi-utils-redirect*) ".pdf")))
+
+
+;; ** AIP
+
+(defun aip-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://scitation.aip.org" *doi-utils-redirect*)
+    ;; get stuff after content
+    (let (p1 p2 s p3)
+      (setq p2 (replace-regexp-in-string
+               "^http://scitation.aip.org/" "" *doi-utils-redirect*))
+      (setq s (split-string p2 "/"))
+      (setq p1 (mapconcat 'identity (-remove-at-indices '(0 6) s) "/"))
+      (setq p3 (concat "/" (nth 0 s) (nth 1 s) "/" (nth 2 s) "/" (nth 3 s)))
+      (format "http://scitation.aip.org/deliver/fulltext/%s.pdf?itemId=/%s&mimeType=pdf&containerItemId=%s"
+             p1 p2 p3))))
+
+;; ** Taylor and Francis
+
+(defun tandfonline-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://www.tandfonline.com" *doi-utils-redirect*)
+    (replace-regexp-in-string "/abs/\\|/full/" "/pdf/" *doi-utils-redirect*)))
+
+;; ** ECS
+
+(defun ecs-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://jes.ecsdl.org" *doi-utils-redirect*)
+    (replace-regexp-in-string "\.abstract$" ".full.pdf" *doi-utils-redirect*)))
+
+;; http://ecst.ecsdl.org/content/25/2/2769
+;; http://ecst.ecsdl.org/content/25/2/2769.full.pdf
+
+
+(defun ecst-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://ecst.ecsdl.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf")))
+
+
+
+;; ** RSC
+
+(defun rsc-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://pubs.rsc.org" *doi-utils-redirect*)
+    (let ((url (downcase *doi-utils-redirect*)))
+      (setq url (replace-regexp-in-string "articlelanding" "articlepdf" url))
+      url)))
+
+;; ** Elsevier/ScienceDirect
+;; You cannot compute these pdf links; they are embedded in the redirected pages.
+
+(defvar *doi-utils-pdf-url* nil
+  "Stores url to pdf download from a callback function.")
+
+(defun doi-utils-get-science-direct-pdf-url (redirect-url)
+  "Science direct hides the pdf url in html.  W get it out here.
+REDIRECT-URL is where the pdf url will be in."
+  (setq *doi-utils-waiting* t)
+  (url-retrieve redirect-url
+               (lambda (status)
+                 (beginning-of-buffer)
+                 (re-search-forward "pdfurl=\"\\([^\"]*\\)\"" nil t)
+                 (setq *doi-utils-pdf-url* (match-string 1)
+                       *doi-utils-waiting* nil)))
+  (while *doi-utils-waiting* (sleep-for 0.1))
+  *doi-utils-pdf-url*)
+
+
+(defun science-direct-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://www.sciencedirect.com" *doi-utils-redirect*)
+    (doi-utils-get-science-direct-pdf-url *doi-utils-redirect*)
+    *doi-utils-pdf-url*))
+
+;; sometimes I get
+;; http://linkinghub.elsevier.com/retrieve/pii/S0927025609004558
+;; which actually redirect to
+;; http://www.sciencedirect.com/science/article/pii/S0927025609004558
+(defun linkinghub-elsevier-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match
+        "^http://linkinghub.elsevier.com/retrieve" *doi-utils-redirect*)
+    (let ((second-redirect (replace-regexp-in-string
+                           "http://linkinghub.elsevier.com/retrieve"
+                           "http://www.sciencedirect.com/science/article"
+                           *doi-utils-redirect*)))
+      (message "getting pdf url from %s" second-redirect)
+      *doi-utils-pdf-url*)))
+
+;; ** PNAS
+;; http://www.pnas.org/content/early/2014/05/08/1319030111
+;; http://www.pnas.org/content/early/2014/05/08/1319030111.full.pdf
+
+;; with supporting info
+;; http://www.pnas.org/content/early/2014/05/08/1319030111.full.pdf+html?with-ds=yes
+
+(defun pnas-pdf-url (*doi-utils-redirect*)
+  "Get url to the pdf from *DOI-UTILS-REDIRECT*."
+  (when (string-match "^http://www.pnas.org" *doi-utils-redirect*)
+    (concat *doi-utils-redirect* ".full.pdf?with-ds=yes")))
+
+
+;; ** Add all functions
+
+(setq doi-utils-pdf-url-functions
+      (list
+       'aps-pdf-url
+       'science-pdf-url
+       'nature-pdf-url
+       'wiley-pdf-url
+       'springer-pdf-url
+       'acs-pdf-url
+       'iop-pdf-url
+       'jstor-pdf-url
+       'aip-pdf-url
+       'science-direct-pdf-url
+       'linkinghub-elsevier-pdf-url
+       'tandfonline-pdf-url
+       'ecs-pdf-url
+       'ecst-pdf-url
+       'rsc-pdf-url
+       'pnas-pdf-url))
+
+;; ** Get the pdf url for a doi
+
+(defun doi-utils-get-pdf-url (doi)
+  "Return a url to a pdf for the DOI if one can be calculated.
+Loops through the functions in `doi-utils-pdf-url-functions'
+until one is found."
+  (doi-utils-get-redirect doi)
+
+  (unless *doi-utils-redirect*
+    (error "No redirect found for %s" doi))
+  (message "applying functions")
+  (catch 'pdf-url
+    (dolist (func doi-utils-pdf-url-functions)
+     (message "calling %s" func)
+      (let ((this-pdf-url (funcall func *doi-utils-redirect*)))
+(message "t: %s" this-pdf-url)
+       (when this-pdf-url
+          (message "found pdf url: %s" this-pdf-url)
+         (throw 'pdf-url this-pdf-url))))))
+
+;; ** Finally, download the pdf
+
+(defun doi-utils-get-bibtex-entry-pdf ()
+  "Download pdf for entry at point if the pdf does not already exist locally.
+The entry must have a doi.  The pdf will be saved
+to `org-ref-pdf-directory', by the name %s.pdf where %s is the
+bibtex label.  Files will not be overwritten.  The pdf will be
+checked to make sure it is a pdf, and not some html failure
+page.  you must have permission to access the pdf.  We open the pdf
+at the end."
+  (interactive)
+  (save-excursion
+    (bibtex-beginning-of-entry)
+    (let (;; get doi, removing http://dx.doi.org/ if it is there.
+         (doi (replace-regexp-in-string
+               "http://dx.doi.org/" ""
+               (bibtex-autokey-get-field "doi")))
+         (key)
+         (pdf-url)
+         (pdf-file)
+         (content))
+      ;; get the key and build pdf filename.
+      (re-search-forward bibtex-entry-maybe-empty-head)
+      (setq key (match-string bibtex-key-in-head))
+      (setq pdf-file (concat org-ref-pdf-directory key ".pdf"))
+
+      ;; now get file if needed.
+      (when (and doi (not (file-exists-p pdf-file)))
+       (setq pdf-url (doi-utils-get-pdf-url doi))
+       (if pdf-url
+           (progn
+             (url-copy-file pdf-url pdf-file)
+             ;; now check if we got a pdf
+             (with-temp-buffer
+               (insert-file-contents pdf-file)
+               ;; PDFS start with %PDF-1.x as the first few characters.
+               (if (not (string= (buffer-substring 1 6) "%PDF-"))
+                   (progn
+                     (message "%s" (buffer-string))
+                     (delete-file pdf-file))
+                 (message "%s saved" pdf-file)))
+
+             (when (file-exists-p pdf-file)
+               (org-open-file pdf-file)))
+         (message "No pdf-url found for %s at %s" doi *doi-utils-redirect* ))
+         pdf-file))))
+
+;; * Getting bibtex entries from a DOI
+
+;; I [[http://homepages.see.leeds.ac.uk/~eeaol/notes/2013/02/doi-metadata/][found]] you can download metadata about a DOI from http://dx.doi.org. You just have to construct the right http request to get it. Here is a function that gets the metadata as a plist in emacs.
+
+(defun doi-utils-get-json-metadata (doi)
+  "Try to get json metadata for DOI.  Open the DOI in a browser if we do not get it."
+  (let ((url-request-method "GET")
+       (url-mime-accept-string "application/citeproc+json")
+       (json-object-type 'plist)
+       (json-data))
+    (with-current-buffer
+       (url-retrieve-synchronously
+        (concat "http://dx.doi.org/" doi))
+      (setq json-data (buffer-substring url-http-end-of-headers (point-max)))
+      (if (string-match "Resource not found" json-data)
+         (progn
+           (browse-url (concat "http://dx.doi.org/" doi))
+           (error "Resource not found.  Opening website"))
+       (json-read-from-string json-data)))))
+
+;; 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.
+
+
+(defun doi-utils-expand-template (s)
+  "Expand a string template S containing %{} with the eval of its contents."
+  (replace-regexp-in-string "%{\\([^}]+\\)}"
+                            (lambda (arg)
+                              (let ((sexp (substring arg 2 -1)))
+                                (format "%s" (eval (read sexp))))) s))
+
+
+;; 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.
+
+
+(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))))
+
+;; 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.
+
+(setq doi-utils-bibtex-type-generators nil)
+
+(defun doi-utils-concat-prepare (lst &optional acc)
+  "Minimize the number of args passed to `concat' from LST.
+Given a list LST of strings and other expressions, which are
+intended to be passed to `concat', concat any subsequent strings,
+minimising the number of arguments being passed to `concat'
+without changing the results.  ACC is the list of additional
+expressions."
+  (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)
+
+(doi-utils-def-bibtex-type inbook ("book-chapter")
+                           author title booktitle series publisher year pages doi url)
+
+
+
+;; With the code generating the bibtex entry in place, we can glue it to the json retrieval code.
+
+(defun doi-utils-doi-to-bibtex-string (doi)
+  "Return a bibtex entry as a string for the DOI.  Not all types are supported yet."
+  (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 "%s not supported yet\n%S." type results))))
+
+;; That is just the string for the entry. To be useful, we need a function that inserts the string into a buffer. This function will insert the string at the cursor, clean the entry, try to get the pdf, and create a notes entry for you.
+
+
+(defun doi-utils-insert-bibtex-entry-from-doi (doi)
+  "Insert bibtex entry from a DOI.
+Also cleans entry using org-ref, and tries to download the corresponding pdf."
+  (interactive "sDOI :")
+  (insert (doi-utils-doi-to-bibtex-string doi))
+  (backward-char)
+  ;; set date added for the record
+  (bibtex-set-field "DATE_ADDED" (current-time-string))
+  (if (bibtex-key-in-head nil)
+       (org-ref-clean-bibtex-entry t)
+     (org-ref-clean-bibtex-entry))
+   ;; try to get pdf
+   (doi-utils-get-bibtex-entry-pdf)
+   (save-selected-window
+     (org-ref-open-bibtex-notes)))
+
+
+;; It may be you are in some other place when you want to add a bibtex entry. This next function will open the first entry in org-ref-default-bibliography go to the end, and add the entry. You can sort it later.
+
+
+(defun doi-utils-add-bibtex-entry-from-doi (doi bibfile)
+  "Add entry to end of a file in in the current directory ending
+with .bib or in `org-ref-default-bibliography'. If you have an
+active region that starts like a DOI, that will be the initial
+prompt. If no region is selected and the first entry of the
+kill-ring starts like a DOI, then that is the intial
+prompt. Otherwise, you have to type or pste in a DOI."
+  (interactive
+   (list (read-string "DOI: "
+                    ;; now set initial input
+                    (cond
+                     ;; If region is active and it starts like a doi we want it.
+                     ((and  (region-active-p)
+                             (s-match "^10" (buffer-substring
+                                             (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))
+                          (car kill-ring)))
+                     ;; otherwise, we have no initial input. You
+                     ;; will have to type it in.
+                     (t
+                      nil)))
+        ;;  now get the bibfile to add it to
+        (ido-completing-read
+         "Bibfile: "
+         (append (f-entries "." (lambda (f) (f-ext? f "bib")))
+                 org-ref-default-bibliography))))
+  ;; Wrap in save-window-excursion to restore your window arrangement after this
+  ;; is done.
+  (save-window-excursion
+    (with-current-buffer
+      (find-file-noselect bibfile)
+      ;; Check if the doi already exists
+      (goto-char (point-min))
+      (if (search-forward doi nil t)
+         (message "%s is already in this file" doi)
+       (end-of-buffer)
+       (insert "\n\n")
+       (doi-utils-insert-bibtex-entry-from-doi doi)
+       (save-buffer)))))
+
+
+;; * Updating bibtex entries
+;; I wrote this code because it is pretty common for me to copy bibtex entries from ASAP articles that are incomplete, e.g. no page numbers because it is not in print yet. I wanted a convenient way to update an entry from its DOI. Basically, we get the metadata, and update the fields in the entry.
+
+;; There is not bibtex set field function, so I wrote this one.
+
+
+(defun bibtex-set-field (field value &optional nodelim)
+  "Set FIELD to VALUE in bibtex file.  create field if it does not exist.
+Optional argument NODELIM see `bibtex-make-field'."
+  (interactive "sfield: \nsvalue: ")
+  (bibtex-beginning-of-entry)
+  (let ((found))
+    (if (setq found (bibtex-search-forward-field field t))
+       ;; we found a field
+       (progn
+         (goto-char (car (cdr found)))
+         (when value
+           (bibtex-kill-field)
+           (bibtex-make-field field nil nil nodelim)
+           (backward-char)
+           (insert value)))
+      ;; make a new field
+      (message "new field being made")
+      (bibtex-beginning-of-entry)
+      (forward-line) (beginning-of-line)
+      (bibtex-next-field nil)
+      (forward-char)
+      (bibtex-make-field field nil nil nodelim)
+      (backward-char)
+      (insert value))))
+
+
+;; The updating function for a whole entry looks like this. We get all the keys from the json plist metadata, and update the fields if they exist.
+
+
+(defun plist-get-keys (plist)
+   "Return keys in a PLIST."
+  (cl-loop
+   for key in results by #'cddr collect key))
+
+(defun doi-utils-update-bibtex-entry-from-doi (doi)
+  "Update fields in a bibtex entry from the DOI.  Every field will be updated, so previous change will be lost."
+  (interactive (list
+               (or (replace-regexp-in-string "http://dx.doi.org/" "" (bibtex-autokey-get-field "doi"))
+                   (read-string "DOI: "))))
+  (let* ((results (doi-utils-get-json-metadata doi))
+        (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))
+        (year (format "%s"
+                      (elt
+                       (elt
+                        (plist-get
+                         (plist-get results :issued) :date-parts) 0) 0)))
+       (volume (plist-get results :volume))
+       (number (or (plist-get results :issue) ""))
+       (pages (or (plist-get results :page) ""))
+       (url (or (plist-get results :URL) ""))
+       (doi (plist-get results :DOI)))
+
+    ;; map the json fields to bibtex fields. The code each field is mapped to is evaluated.
+    (setq mapping '((:author . (bibtex-set-field "author" author))
+                   (:title . (bibtex-set-field "title" title))
+                   (:container-title . (bibtex-set-field "journal" journal))
+                   (:issued . (bibtex-set-field "year" year))
+                   (:volume . (bibtex-set-field "volume" volume))
+                   (:issue . (bibtex-set-field "number" number))
+                   (:page . (bibtex-set-field "pages" pages))
+                   (:DOI . (bibtex-set-field "doi" doi))
+                   (:URL . (bibtex-set-field "url" url))))
+
+    ;; now we have code to run for each entry. we map over them and evaluate the code
+    (mapcar
+     (lambda (key)
+       (eval (cdr (assoc key mapping))))
+     (plist-get-keys results)))
+
+  ; reclean entry, but keep key if it exists.
+  (if (bibtex-key-in-head)
+      (org-ref-clean-bibtex-entry t)
+    (org-ref-clean-bibtex-entry)))
+
+
+;; A downside to updating an entry is it overwrites what you have already fixed. So, we next develop a function to update the field at point.
+
+
+(defun doi-utils-update-field ()
+  "Update the field at point in the bibtex entry.
+Data is retrieved from the doi in the entry."
+  (interactive)
+  (let* ((doi (bibtex-autokey-get-field "doi"))
+        (results (doi-utils-get-json-metadata doi))
+        (field (car (bibtex-find-text-internal nil nil ","))))
+    (cond
+     ((string= field "volume")
+      (bibtex-set-field field (plist-get results :volume)))
+     ((string= field "number")
+      (bibtex-set-field field (plist-get results :issue)))
+     ((string= field "pages")
+      (bibtex-set-field field (plist-get results :page)))
+     ((string= field "year")
+      (bibtex-set-field field (plist-get results :year)))
+     (t
+      (message "%s not supported yet." field)))))
+
+
+
+;; * DOI functions for WOS
+;; I came across this API http://wokinfo.com/media/pdf/OpenURL-guide.pdf to make links to the things I am interested in here. Based on that document, here are three links based on a doi:10.1021/jp047349j that take you to different Web Of Science (WOS) pages.
+
+
+;; 1. go to article in WOS: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/10.1021/jp047349j
+;; 2. citing articles: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F10.1021/jp047349j&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.citing=yes
+;; 3. related articles: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F10.1021/jp047349j&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.related=yes
+
+;; These are pretty easy to construct, so we can write functions that will create them and open the url in our browser. There are some other options that could be considered, but since we usually have a doi, it seems like the best way to go for creating the links. Here are the functions.
+
+(defun doi-utils-wos (doi)
+  "Open Web of Science entry for DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/%s" doi)))
+
+(defun doi-utils-wos-citing (doi)
+  "Open Web of Science citing articles entry for DOI.
+May be empty if none are found."
+  (interactive "sDOI: ")
+  (browse-url
+   (concat
+    "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F"
+    doi
+    "&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.citing=yes")))
+
+(defun doi-utils-wos-related (doi)
+  "Open Web of Science related articles page for DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (concat "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F"
+          doi
+          "&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.related=yes")))
+
+
+
+
+;; * A new doi link for org-mode
+;; The idea is to add a menu to the doi link, so rather than just clicking to open the article, you can do other things.
+;; 1. open doi
+;; 2. open in wos
+;; 3. open citing articles
+;; 4. open related articles
+;; 5. open bibtex entry
+;; 6. get bibtex entry
+
+
+(defun doi-utils-open (doi)
+  "Open DOI in browser."
+ (interactive "sDOI: ")
+ (browse-url (concat "http://dx.doi.org/" doi)))
+
+
+(defun doi-utils-open-bibtex (doi)
+  "Search through variable `reftex-default-bibliography' for DOI."
+  (interactive "sDOI: ")
+  (catch 'file
+    (dolist (f reftex-default-bibliography)
+      (find-file f)
+      (when (search-forward doi (point-max) t)
+       (bibtex-beginning-of-entry)
+       (throw 'file t)))))
+
+
+(defun doi-utils-crossref (doi)
+  "Search DOI in CrossRef."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://search.crossref.org/?q=%s" doi)))
+
+
+(defun doi-utils-google-scholar (doi)
+  "Google scholar the DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://scholar.google.com/scholar?q=%s" doi)))
+
+
+(defun doi-utils-pubmed (doi)
+  "Search Pubmed for the DOI."
+  (interactive "sDOI: ")
+  (browse-url
+   (format
+    "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s"
+    (url-hexify-string doi))))
+
+
+(defvar doi-link-menu-funcs '()
+ "Functions to run in doi menu.
+Each entry is a list of (key menu-name function).  The function
+must take one argument, the doi.")
+
+(setq doi-link-menu-funcs
+      '(("o" "pen" doi-utils-open)
+       ("w" "os" doi-utils-wos)
+       ("c" "iting articles" doi-utils-wos-citing)
+       ("r" "elated articles" doi-utils-wos-related)
+        ("s" "Google Scholar" doi-utils-google-scholar)
+        ("f" "CrossRef" doi-utils-crossref)
+        ("p" "ubmed" doi-utils-pubmed)
+       ("b" "open in bibtex" doi-utils-open-bibtex)
+       ("g" "et bibtex entry" doi-utils-add-bibtex-entry-from-doi)))
+
+
+(defun doi-link-menu (link-string)
+   "Generate the link menu message, get choice and execute it.
+Options are stored in `doi-link-menu-funcs'.
+Argument LINK-STRING Passed in on link click."
+   (interactive)
+   (message
+   (concat
+    (mapconcat
+     (lambda (tup)
+       (concat "[" (elt tup 0) "]"
+              (elt tup 1) " "))
+     doi-link-menu-funcs "") ": "))
+   (let* ((input (read-char-exclusive))
+         (choice (assoc
+                  (char-to-string input) doi-link-menu-funcs)))
+     (when choice
+       (funcall
+       (elt
+        choice
+        2)
+       link-string))))
+
+(org-add-link-type
+ "doi"
+ 'doi-link-menu)
+
+
+;; * Getting a doi for a bibtex entry missing one
+;; Some bibtex entries do not have a DOI, maybe because they were entered by hand, or copied from a source that did not have it available. Here we develop some functions to help you find the DOI using Crossref.
+
+;; Here is our example bibtex entry.
+;; #+BEGIN_SRC bibtex
+;; @article{deml-2014-oxide,
+;;   author =   {Ann M. Deml and Vladan Stevanovi{\'c} and
+;;                   Christopher L. Muhich and Charles B. Musgrave and
+;;                   Ryan O'Hayre},
+;;   title =    {Oxide Enthalpy of Formation and Band Gap Energy As
+;;                   Accurate Descriptors of Oxygen Vacancy Formation
+;;                   Energetics},
+;;   journal =  {Energy Environ. Sci.},
+;;   volume =   7,
+;;   number =   6,
+;;   pages =    1996,
+;;   year =     2014,
+;;   doi =              {10.1039/c3ee43874k,
+;;   url =              {http://dx.doi.org/10.1039/c3ee43874k}},
+
+;; }
+
+
+;; The idea is to query Crossref in a way that is likely to give us a hit relevant to the entry.
+
+;; According to http://search.crossref.org/help/api we can send a query with a free form citation that may give us something back. We do this to get a list of candidates, and run a helm command to get the doi.
+
+
+
+(defun doi-utils-crossref-citation-query ()
+  "Query Crossref with the title of the bibtex entry at point to
+get a list of possible matches. This opens a helm buffer to
+select an entry. The default action inserts a doi and url field
+in the bibtex entry at point. The second action opens the doi
+url. If there is already a doi field, the function raises an
+error."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (let* ((entry (bibtex-parse-entry))
+        (json-string)
+        (json-data)
+        (doi))
+    (unless (string= ""(reftex-get-bib-field "doi" entry))
+      (error "Entry already has a doi field"))
+
+    (with-current-buffer
+       (url-retrieve-synchronously
+        (concat
+         "http://search.crossref.org/dois?q="
+         (url-hexify-string (org-ref-bib-citation))))
+      (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" (org-ref-bib-citation)))
+          (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 doi and url field" . (lambda (doi)
+                                                               (bibtex-make-field "doi")
+                                                               (backward-char)
+                                                               ;; crossref returns doi url, but I prefer only a doi for the doi field
+                                                               (insert (replace-regexp-in-string "^http://dx.doi.org/" "" doi))
+                                                               (when (string= ""(reftex-get-bib-field "url" entry))
+                                                                 (bibtex-make-field "url")
+                                                                 (backward-char)
+                                                                 (insert doi))))
+                               ("Open url" . (lambda (doi)
+                                               (browse-url doi))))))))
+      (helm :sources '(source)))))
+
+
+
+;; * Debugging a DOI
+;; I wrote this function to help debug a DOI. This function generates an org-buffer with the doi, gets the json metadata, shows the bibtex entry, and the pdf link for it.
+
+(defun doi-utils-debug (doi)
+  "Generate an org-buffer showing data about DOI."
+  (interactive "sDOI: ")
+  (switch-to-buffer "*debug-doi*")
+  (erase-buffer)
+  (org-mode)
+  (insert (concat "doi:" doi) "\n\n")
+  (insert "* JSON
+" (format "%s" (doi-utils-get-json-metadata doi)) "
+
+* Bibtex
+
+" (doi-utils-doi-to-bibtex-string doi) "
+
+* PDF
+" (doi-utils-get-pdf-url doi)))
+
+;; * 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.
+
+(defun doi-utils-add-entry-from-crossref-query (query bibtex-file)
+  "Search Crossref with QUERY and use helm to select an entry to add to BIBTEX-FILE."
+  (interactive (list
+               (read-string
+                "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)))))
+
+;; * The end
+(provide 'doi-utils)
+;;; doi-utils.el ends here
diff --git a/doi-utils.org b/doi-utils.org
deleted file mode 100644 (file)
index a29996f..0000000
+++ /dev/null
@@ -1,1386 +0,0 @@
-#+TITLE: DOI utilities for making bibtex entries and downloading pdfs
-
-This package provides functionality to download PDFs and bibtex entries from a DOI, as well as to update a bibtex entry from a DOI. It depends slightly on org-ref, to determine where to save pdf files too, and where to insert bibtex entries in the default bibliography.
-
-The principle commands you will use from here are:
-
-- doi-utils-get-bibtex-entry-pdf with the cursor in a bibtex entry.
-- doi-utils-insert-bibtex-entry-from-doi to insert a bibtex entry at your cursor, clean it and try to get a pdf.
-- doi-utils-add-bibtex-entry-from-doi to add an entry to your default bibliography (cleaned with pdf if possible).
-- doi-utils-add-bibtex-entry-from-region to add an entry from a highlighed doi to your default bibliography.
-- doi-utils-update-bibtex-entry-from-doi with cursor in an entry to update its fields.
-
-* Header
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-;;; doi-utils.el --- get bibtex entries and pdfs from a DOI
-
-;; Copyright(C) 2014 John Kitchin
-
-;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
-;; This file is not currently part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
-
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program ; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;;
-;; Lisp code to generate and update bibtex entries from a DOI, and to
-;; download pdfs from publisher websites from a DOI.
-;;
-;; Package-Requires: ((org-ref))
-
-(require 'json)
-#+END_SRC
-
-* Getting pdf files from a DOI
-The idea here is simple. When you visit http://dx.doi.org/doi, you get redirected to the journal site. Once you have the url for the article, you can usually compute the url to the pdf, or find it in the page. Then you simply download it.
-
-There are some subtleties in doing this that are described here. To get the redirect, we have to use url-retrieve, and a callback function. The callback does not return anything, so we communicate through global variables. url-retrieve is asynchronous, so we have to make sure to wait for it to finish.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defvar *doi-utils-waiting* t
-  "stores waiting state for url retrieval.")
-
-(defvar *doi-utils-redirect* nil
-  "stores redirect url from a callback function")
-
-(defun doi-utils-redirect-callback (&optional status)
-  "callback for url-retrieve to set the redirect"
-  (when (plist-get status :error)
-    (signal (car (plist-get status :error)) (cdr(plist-get status :error))))
-  (when (plist-get status :redirect) ;  is nil if there none
-    (message "redirects = %s" (plist-get status :redirect))
-    (message "*doi-utils-redirect* set to %s"
-            (setq *doi-utils-redirect* (plist-get status :redirect))))
-  ;; we have done our job, so we are not waiting any more.
-  (setq *doi-utils-waiting* nil))
-#+END_SRC
-
-To actually get the redirect we use url-retrieve like this.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun doi-utils-get-redirect (doi)
-  "get redirect url from dx.doi.org/doi"
-  ;; we are going to wait until the url-retrieve is done
-  (setq *doi-utils-waiting* t)
-  ;; start with no redirect. it will be set in the callback.
-  (setq *doi-utils-redirect* nil)
-  (url-retrieve
-   (format "http://dx.doi.org/%s" doi)
-   'doi-utils-redirect-callback)
-  ; I suspect we need to wait here for the asynchronous process to
-  ; finish. we loop and sleep until the callback says it is done via
-  ; `*doi-utils-waiting*'. this works as far as i can tell. Before I
-  ; had to run this a few times to get it to work, which i suspect
-  ; just gave the first one enough time to finish.
-  (while *doi-utils-waiting* (sleep-for 0.1)))
-#+END_SRC
-
-Once we have a redirect for a particular doi, we need to compute the url to the pdf. We do this with a series of functions. Each function takes a single argument, the redirect url. If it knows how to compute the pdf url it does, and returns it. We store the functions in a variable:
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defvar doi-utils-pdf-url-functions nil
-  "list of functions that return a url to a pdf from a redirect url. Each function takes one argument, the redirect url. The function must return a pdf-url, or nil.")
-#+END_SRC
-
-** APS journals
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun aps-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://journals.aps.org" *doi-utils-redirect*)
-    (replace-regexp-in-string "/abstract/" "/pdf/" *doi-utils-redirect*)))
-#+END_SRC
-
-** Science
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun science-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://www.sciencemag.org" *doi-utils-redirect*)
-    (concat *doi-utils-redirect* ".full.pdf")))
-#+END_SRC
-
-** Nature
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun nature-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://www.nature.com" *doi-utils-redirect*)
-    (let ((result *doi-utils-redirect*))
-      (setq result (replace-regexp-in-string "/full/" "/pdf/" result))
-      (replace-regexp-in-string "\.html$" "\.pdf" result))))
-#+END_SRC
-
-** Wiley
-http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/abstract
-http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/pdf
-
-It appears that it is not enough to use the pdf url above. That takes you to an html page. The actual link to teh pdf is embedded in that page. This is how ScienceDirect does things too.
-
-This is where the link is hidden:
-
-<iframe id="pdfDocument" src="http://onlinelibrary.wiley.com/store/10.1002/anie.201402680/asset/6397_ftp.pdf?v=1&amp;t=hwut2142&amp;s=d4bb3cd4ad20eb733836717f42346ffb34017831" width="100%" height="675px"></iframe>
-
-
-
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun doi-utils-get-wiley-pdf-url (redirect-url)
-  "wileyscience direct hides the pdf url in html. we get it out here"
-  (setq *doi-utils-waiting* t)
-  (url-retrieve redirect-url
-               (lambda (status)
-                 (beginning-of-buffer)
-                 (re-search-forward "<iframe id=\"pdfDocument\" src=\"\\([^\"]*\\)\"" nil)
-                 (setq *doi-utils-pdf-url* (match-string 1)
-                       ,*doi-utils-waiting* nil)))
-  (while *doi-utils-waiting* (sleep-for 0.1))
-  ,*doi-utils-pdf-url*)
-
-(defun wiley-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://onlinelibrary.wiley.com" *doi-utils-redirect*)
-   (doi-utils-get-wiley-pdf-url (replace-regexp-in-string "/abstract" "/pdf" *doi-utils-redirect*))
-   ,*doi-utils-pdf-url*))
-#+END_SRC
-
-** Springer
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun springer-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://link.springer.com" *doi-utils-redirect*)
-    (replace-regexp-in-string "/article/" "/content/pdf/" (concat *doi-utils-redirect* ".pdf"))))
-#+END_SRC
-
-** ACS
-here is a typical url http://pubs.acs.org/doi/abs/10.1021/nl500037x
-the pdf is found at http://pubs.acs.org/doi/pdf/10.1021/nl500037x
-
-we just change /abs/ to /pdf/.
-
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun acs-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://pubs.acs.org" *doi-utils-redirect*)
-    (replace-regexp-in-string "/abs/" "/pdf/" *doi-utils-redirect*)))
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(acs-pdf-url  "http://pubs.acs.org/doi/abs/10.1021/nl500037x")
-#+END_SRC
-
-#+RESULTS:
-: http://pubs.acs.org/doi/pdf/10.1021/nl500037x
-
-** IOP
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun iop-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://iopscience.iop.org" *doi-utils-redirect*)
-    (let ((tail (replace-regexp-in-string "^http://iopscience.iop.org" "" *doi-utils-redirect*)))
-      (concat "http://iopscience.iop.org" tail "/pdf" (replace-regexp-in-string "/" "_" tail) ".pdf"))))
-#+END_SRC
-
-** JSTOR
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun jstor-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://www.jstor.org" *doi-utils-redirect*)
-    (concat (replace-regexp-in-string "/stable/" "/stable/pdfplus/" *doi-utils-redirect*) ".pdf")))
-#+END_SRC
-
-** AIP
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun aip-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://scitation.aip.org" *doi-utils-redirect*)
-    ;; get stuff after content
-    (let (p1 p2 s p3)
-      (setq p2 (replace-regexp-in-string "^http://scitation.aip.org/" "" *doi-utils-redirect*))
-      (setq s (split-string p2 "/"))
-      (setq p1 (mapconcat 'identity (-remove-at-indices '(0 6) s) "/"))
-      (setq p3 (concat "/" (nth 0 s) (nth 1 s) "/" (nth 2 s) "/" (nth 3 s)))
-      (format "http://scitation.aip.org/deliver/fulltext/%s.pdf?itemId=/%s&mimeType=pdf&containerItemId=%s"
-             p1 p2 p3))))
-#+END_SRC
-
-** Taylor and Francis
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun tandfonline-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://www.tandfonline.com" *doi-utils-redirect*)
-    (replace-regexp-in-string "/abs/\\|/full/" "/pdf/" *doi-utils-redirect*)))
-#+END_SRC
-** ECS
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun ecs-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://jes.ecsdl.org" *doi-utils-redirect*)
-    (replace-regexp-in-string "\.abstract$" ".full.pdf" *doi-utils-redirect*)))
-#+END_SRC
-
-http://ecst.ecsdl.org/content/25/2/2769
-http://ecst.ecsdl.org/content/25/2/2769.full.pdf
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun ecst-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://ecst.ecsdl.org" *doi-utils-redirect*)
-    (concat *doi-utils-redirect* ".full.pdf")))
-#+END_SRC
-
-
-** RSC
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun rsc-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://pubs.rsc.org" *doi-utils-redirect*)
-    (let ((url (downcase *doi-utils-redirect*)))
-      (setq url (replace-regexp-in-string "articlelanding" "articlepdf" url))
-      url)))
-#+END_SRC
-
-** Elsevier/ScienceDirect
-You cannot compute these pdf links; they are embedded in the redirected pages.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defvar *doi-utils-pdf-url* nil
-  "stores url to pdf download from a callback function")
-
-(defun doi-utils-get-science-direct-pdf-url (redirect-url)
-  "science direct hides the pdf url in html. we get it out here"
-  (setq *doi-utils-waiting* t)
-  (url-retrieve redirect-url
-               (lambda (status)
-                 (beginning-of-buffer)
-                 (re-search-forward "pdfurl=\"\\([^\"]*\\)\"" nil t)
-                 (setq *doi-utils-pdf-url* (match-string 1)
-                       ,*doi-utils-waiting* nil)))
-  (while *doi-utils-waiting* (sleep-for 0.1))
-  ,*doi-utils-pdf-url*)
-
-
-(defun science-direct-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://www.sciencedirect.com" *doi-utils-redirect*)
-    (doi-utils-get-science-direct-pdf-url *doi-utils-redirect*)
-    ,*doi-utils-pdf-url*))
-
-;; sometimes I get
-;; http://linkinghub.elsevier.com/retrieve/pii/S0927025609004558
-;; which actually redirect to
-;; http://www.sciencedirect.com/science/article/pii/S0927025609004558
-(defun linkinghub-elsevier-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://linkinghub.elsevier.com/retrieve" *doi-utils-redirect*)
-    (let ((second-redirect (replace-regexp-in-string
-                           "http://linkinghub.elsevier.com/retrieve"
-                           "http://www.sciencedirect.com/science/article"
-                           ,*doi-utils-redirect*)))
-      (message "getting pdf url from %s" second-redirect)
-      ;(doi-utils-get-science-direct-pdf-url second-redirect)
-      ,*doi-utils-pdf-url*)))
-#+END_SRC
-
-** PNAS
-http://www.pnas.org/content/early/2014/05/08/1319030111
-http://www.pnas.org/content/early/2014/05/08/1319030111.full.pdf
-
-with supporting info
-http://www.pnas.org/content/early/2014/05/08/1319030111.full.pdf+html?with-ds=yes
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun pnas-pdf-url (*doi-utils-redirect*)
-  (when (string-match "^http://www.pnas.org" *doi-utils-redirect*)
-    (concat *doi-utils-redirect* ".full.pdf?with-ds=yes")))
-#+END_SRC
-
-** Add all functions
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(setq doi-utils-pdf-url-functions
-      (list
-       'aps-pdf-url
-       'science-pdf-url
-       'nature-pdf-url
-       'wiley-pdf-url
-       'springer-pdf-url
-       'acs-pdf-url
-       'iop-pdf-url
-       'jstor-pdf-url
-       'aip-pdf-url
-       'science-direct-pdf-url
-       'linkinghub-elsevier-pdf-url
-       'tandfonline-pdf-url
-       'ecs-pdf-url
-       'ecst-pdf-url
-       'rsc-pdf-url
-       'pnas-pdf-url))
-#+END_SRC
-
-** Get the pdf url for a doi
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun doi-utils-get-pdf-url (doi)
-  "returns a url to a pdf for the doi if one can be
-calculated. Loops through the functions in `doi-utils-pdf-url-functions'
-until one is found"
-  (doi-utils-get-redirect doi)
-
-  (unless *doi-utils-redirect*
-    (error "No redirect found for %s" doi))
-  (message "applying functions")
-  (catch 'pdf-url
-    (dolist (func doi-utils-pdf-url-functions)
-     (message "calling %s" func)
-      (let ((this-pdf-url (funcall func *doi-utils-redirect*)))
-(message "t: %s" this-pdf-url)
-       (when this-pdf-url
-          (message "found pdf url: %s" this-pdf-url)
-         (throw 'pdf-url this-pdf-url))))))
-#+END_SRC
-
-#+RESULTS:
-: doi-utils-get-pdf-url
-
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(doi-utils-get-pdf-url "10.1126/science.1158722")
-#+END_SRC
-
-#+RESULTS:
-: http://www.sciencemag.org/content/321/5890/792.full.pdf
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(doi-utils-get-pdf-url  "10.1021/nl500037x")
-#+END_SRC
-
-#+RESULTS:
-: http://pubs.acs.org/doi/pdf/10.1021/nl500037x
-
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(doi-utils-get-pdf-url  "10.1002/anie.201402680")
-#+END_SRC
-
-#+RESULTS:
-: http://onlinelibrary.wiley.com/doi/10.1002/anie.201402680/pdf
-
-** Finally, download the pdf
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun doi-utils-get-bibtex-entry-pdf ()
-  "download pdf for entry at point if the pdf does not already
-exist locally. The entry must have a doi. The pdf will be saved
-to `org-ref-pdf-directory', by the name %s.pdf where %s is the
-bibtex label. Files will not be overwritten. The pdf will be
-checked to make sure it is a pdf, and not some html failure
-page. you must have permission to access the pdf. We open the pdf
-at the end."
-  (interactive)
-  (save-excursion
-    (bibtex-beginning-of-entry)
-    (let (;; get doi, removing http://dx.doi.org/ if it is there.
-         (doi (replace-regexp-in-string
-               "http://dx.doi.org/" ""
-               (bibtex-autokey-get-field "doi")))
-         (key)
-         (pdf-url)
-         (pdf-file)
-         (content))
-      ;; get the key and build pdf filename.
-      (re-search-forward bibtex-entry-maybe-empty-head)
-      (setq key (match-string bibtex-key-in-head))
-      (setq pdf-file (concat org-ref-pdf-directory key ".pdf"))
-
-      ;; now get file if needed.
-      (when (and doi (not (file-exists-p pdf-file)))
-       (setq pdf-url (doi-utils-get-pdf-url doi))
-       (if pdf-url
-           (progn
-             (url-copy-file pdf-url pdf-file)
-             ;; now check if we got a pdf
-             (with-temp-buffer
-               (insert-file-contents pdf-file)
-               ;; PDFS start with %PDF-1.x as the first few characters.
-               (if (not (string= (buffer-substring 1 6) "%PDF-"))
-                   (progn
-                     (message "%s" (buffer-string))
-                     (delete-file pdf-file))
-                 (message "%s saved" pdf-file)))
-
-             (when (file-exists-p pdf-file)
-               (org-open-file pdf-file)))
-         (message "No pdf-url found for %s at %s" doi *doi-utils-redirect* ))
-         pdf-file))))
-#+END_SRC
-
-* Getting bibtex entries from a DOI
-
-I [[http://homepages.see.leeds.ac.uk/~eeaol/notes/2013/02/doi-metadata/][found]] you can download metadata about a DOI from http://dx.doi.org. You just have to construct the right http request to get it. Here is a function that gets the metadata as a plist in emacs.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun doi-utils-get-json-metadata (doi)
-  "Try to get json metadata for DOI. Open the DOI in a browser if we do not get it."
-  (let ((url-request-method "GET")
-       (url-mime-accept-string "application/citeproc+json")
-       (json-object-type 'plist)
-       (json-data))
-    (with-current-buffer
-       (url-retrieve-synchronously
-        (concat "http://dx.doi.org/" doi))
-      (setq json-data (buffer-substring url-http-end-of-headers (point-max)))
-      (if (string-match "Resource not found" json-data)
-         (progn
-           (browse-url (concat "http://dx.doi.org/" doi))
-           (error "Resource not found. Opening website."))
-       (json-read-from-string json-data)))))
-#+END_SRC
-
-#+RESULTS:
-: doi-utils-get-json-metadata
-
-For example:
-#+BEGIN_SRC emacs-lisp :tangle no
-(doi-utils-get-json-metadata "10.1103/PhysRevLett.99.016105")
-#+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 | [] |
-
-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.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun doi-utils-expand-template (s)
-  "expand a template containing %{} with the eval of its contents"
-  (replace-regexp-in-string "%{\\([^}]+\\)}"
-                            (lambda (arg)
-                              (let ((sexp (substring arg 2 -1)))
-                                (format "%s" (eval (read sexp))))) s))
-#+END_SRC
-
-Now we define a function that fills in that template from the metadata.
-
-#+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)))))
-#+END_SRC
-
-#+RESULTS:
-: doi-utils-doi-to-bibtex-string
-
-To see that in action:
-#+BEGIN_SRC emacs-lisp :tangle no
-(doi-utils-doi-to-bibtex-string "10.1103/PhysRevLett.99.016105")
-#+END_SRC
-
-#+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},
-}
-#+end_example
-
-That is just the string for the entry. To be useful, we need a function that inserts the string into a buffer. This function will insert the string at the cursor, clean the entry, try to get the pdf, and create a notes entry for you.
-
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun doi-utils-insert-bibtex-entry-from-doi (doi)
-  "insert bibtex entry from a doi. Also cleans entry using
-org-ref, and tries to download the corresponding pdf."
-  (interactive "sDOI :")
-  (insert (doi-utils-doi-to-bibtex-string doi))
-  (backward-char)
-  (if (bibtex-key-in-head nil)
-       (org-ref-clean-bibtex-entry t)
-     (org-ref-clean-bibtex-entry))
-   ;; try to get pdf
-   (doi-utils-get-bibtex-entry-pdf)
-   (save-selected-window
-     (org-ref-open-bibtex-notes)))
-#+END_SRC
-
-It may be you are in some other place when you want to add a bibtex entry. This next function will open the first entry in org-ref-default-bibliography go to the end, and add the entry. You can sort it later.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun doi-utils-add-bibtex-entry-from-doi (doi bibfile)
-  "Add entry to end of a file in in the current directory ending
-with .bib or in `org-ref-default-bibliography'. If you have an
-active region that starts like a DOI, that will be the initial
-prompt. If no region is selected and the first entry of the
-kill-ring starts like a DOI, then that is the intial
-prompt. Otherwise, you have to type or pste in a DOI."
-  (interactive
-   (list (read-input "DOI: "
-                    ;; now set initial input
-                    (cond
-                     ;; If region is active and it starts like a doi we want it.
-                     ((and  (region-active-p)
-                             (s-match "^10" (buffer-substring
-                                             (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))
-                          (car kill-ring)))
-                     ;; otherwise, we have no initial input. You
-                     ;; will have to type it in.
-                     (t
-                      nil)))
-        ;;  now get the bibfile to add it to
-        (ido-completing-read
-         "Bibfile: "
-         (append (f-entries "." (lambda (f) (f-ext? f "bib")))
-                 org-ref-default-bibliography))))
-  ;; Wrap in save-window-excursion to restore your window arrangement after this
-  ;; is done.
-  (save-window-excursion
-    (find-file bibfile)
-    ;; Check if the doi already exists
-    (goto-char (point-min))
-    (if (search-forward doi nil t)
-       (message "%s is already in this file" doi)
-      (end-of-buffer)
-      (insert "\n\n")
-      (doi-utils-insert-bibtex-entry-from-doi doi)
-      (save-buffer))))
-#+END_SRC
-
-
-* Updating bibtex entries
-I wrote this code because it is pretty common for me to copy bibtex entries from ASAP articles that are incomplete, e.g. no page numbers because it is not in print yet. I wanted a convenient way to update an entry from its DOI. Basically, we get the metadata, and update the fields in the entry.
-
-There is not bibtex set field function, so I wrote this one.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun bibtex-set-field (field value &optional nodelim)
-  "set field to value in bibtex file. create field if it does not exist"
-  (interactive "sfield: \nsvalue: ")
-  (bibtex-beginning-of-entry)
-  (let ((found))
-    (if (setq found (bibtex-search-forward-field field t))
-       ;; we found a field
-       (progn
-         (goto-char (car (cdr found)))
-         (when value
-           (bibtex-kill-field)
-           (bibtex-make-field field nil nil nodelim)
-           (backward-char)
-           (insert value)))
-      ;; make a new field
-      (message "new field being made")
-      (bibtex-beginning-of-entry)
-      (forward-line) (beginning-of-line)
-      (bibtex-next-field nil)
-      (forward-char)
-      (bibtex-make-field field nil nil nodelim)
-      (backward-char)
-      (insert value))))
-#+END_SRC
-
-The updating function looks like this. We get all the keys from the json plist metadata, and update the fields if they exist.
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun plist-get-keys (plist)
-   "return keys in a plist"
-  (loop
-   for key in results by #'cddr collect key))
-
-(defun doi-utils-update-bibtex-entry-from-doi (doi)
-  "update fields in a bibtex entry from the doi. Every field will be updated, so previous changes will be lost."
-  (interactive (list
-               (or (replace-regexp-in-string "http://dx.doi.org/" "" (bibtex-autokey-get-field "doi"))
-                   (read-string "DOI: "))))
-  (let* ((results (doi-utils-get-json-metadata doi))
-        (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))
-        (year (format "%s"
-                      (elt
-                       (elt
-                        (plist-get
-                         (plist-get results :issued) :date-parts) 0) 0)))
-       (volume (plist-get results :volume))
-       (number (or (plist-get results :issue) ""))
-       (pages (or (plist-get results :page) ""))
-       (url (or (plist-get results :URL) ""))
-       (doi (plist-get results :DOI)))
-
-    ;; map the json fields to bibtex fields. The code each field is mapped to is evaluated.
-    (setq mapping '((:author . (bibtex-set-field "author" author))
-                   (:title . (bibtex-set-field "title" title))
-                   (:container-title . (bibtex-set-field "journal" journal))
-                   (:issued . (bibtex-set-field "year" year))
-                   (:volume . (bibtex-set-field "volume" volume))
-                   (:issue . (bibtex-set-field "number" number))
-                   (:page . (bibtex-set-field "pages" pages))
-                   (:DOI . (bibtex-set-field "doi" doi))
-                   (:URL . (bibtex-set-field "url" url))))
-
-    ;; now we have code to run for each entry. we map over them and evaluate the code
-    (mapcar
-     (lambda (key)
-       (eval (cdr (assoc key mapping))))
-     (plist-get-keys results)))
-
-  ; reclean entry, but keep key if it exists.
-  (if (bibtex-key-in-head)
-      (org-ref-clean-bibtex-entry t)
-    (org-ref-clean-bibtex-entry)))
-#+END_SRC
-* DOI functions for WOS
-I came across this API http://wokinfo.com/media/pdf/OpenURL-guide.pdf to make links to the things I am interested in here. Based on that document, here are three links based on a doi:10.1021/jp047349j that take you to different Web Of Science (WOS) pages.
-
-
-1. go to article in WOS: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/10.1021/jp047349j
-2. citing articles: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F10.1021/jp047349j&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.citing=yes
-3. related articles: http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F10.1021/jp047349j&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.related=yes
-
-These are pretty easy to construct, so we can write functions that will create them and open the url in our browser. There are some other options that could be considered, but since we usually have a doi, it seems like the best way to go for creating the links. Here are the functions.
-
-#+BEGIN_SRC emacs-lisp  :tangle doi-utils.el
-(defun doi-utils-wos (doi)
-  "Open Web of Science entry for DOI"
-  (interactive "sDOI: ")
-  (browse-url
-   (format
-    "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/%s" doi)))
-
-(defun doi-utils-wos-citing (doi)
-  "Open Web of Science citing articles entry. May be empty if none are found"
-  (interactive "sDOI: ")
-  (browse-url
-   (concat
-    "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F"
-    doi
-    "&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.citing=yes")))
-
-(defun doi-utils-wos-related (doi)
-  "Open Web of Science related articles page."
-  (interactive "sDOI: ")
-  (browse-url
-   (concat "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info%3Adoi%2F"
-          doi
-          "&svc_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Asch_svc&svc.related=yes")))
-
-#+END_SRC
-
-* A new doi link for org-mode
-The idea is to add a menu to the doi link, so rather than just clicking to open the article, you can do other things.
-1. open doi
-2. open in wos
-3. open citing articles
-4. open related articles
-5. open bibtex entry
-6. get bibtex entry
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el :results silent
-(defun doi-utils-open (doi)
- (interactive "sDOI: ")
- (browse-url (concat "http://dx.doi.org/" doi)))
-
-
-(defun doi-utils-open-bibtex (doi)
-  "Search through `reftex-default-bibliography' for DOI."
-  (interactive "sDOI: ")
-  (catch 'file
-    (dolist (f reftex-default-bibliography)
-      (find-file f)
-      (when (search-forward doi (point-max) t)
-       (bibtex-beginning-of-entry)
-       (throw 'file t)))))
-
-
-(defun doi-utils-crossref (doi)
-  "Search DOI in CrossRef."
-  (interactive "sDOI: ")
-  (browse-url
-   (format
-    "http://search.crossref.org/?q=%s" doi)))
-
-
-(defun doi-utils-google-scholar (doi)
-  "Google scholar the word at point or selection."
-  (interactive "sDOI: ")
-  (browse-url
-   (format
-    "http://scholar.google.com/scholar?q=%s" doi)))
-
-
-(defun doi-utils-pubmed (doi)
-  "Pubmed the word at point or selection."
-  (interactive "sDOI: ")
-  (browse-url
-   (format
-    "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s"
-    (url-hexify-string doi))))
-
-
-(defvar doi-link-menu-funcs '()
- "Functions to run in doi menu. Each entry is a list of (key menu-name function).
-The function must take one argument, the doi.")
-
-(setq doi-link-menu-funcs
-      '(("o" "pen" doi-utils-open)
-       ("w" "os" doi-utils-wos)
-       ("c" "iting articles" doi-utils-wos-citing)
-       ("r" "elated articles" doi-utils-wos-related)
-        ("s" "Google Scholar" doi-utils-google-scholar)
-        ("f" "CrossRef" doi-utils-crossref)
-        ("p" "ubmed" doi-utils-pubmed)
-       ("b" "open in bibtex" doi-utils-open-bibtex)
-       ("g" "et bibtex entry" doi-utils-add-bibtex-entry-from-doi)))
-
-
-(defun doi-link-menu (link-string)
-   "Generate the link menu message, get choice and execute it.
-Options are stored in `doi-link-menu-funcs'."
-   (interactive)
-   (message
-   (concat
-    (mapconcat
-     (lambda (tup)
-       (concat "[" (elt tup 0) "]"
-              (elt tup 1) " "))
-     doi-link-menu-funcs "") ": "))
-   (let* ((input (read-char-exclusive))
-         (choice (assoc
-                  (char-to-string input) doi-link-menu-funcs)))
-     (when choice
-       (funcall
-       (elt
-        choice
-        2)
-       link-string))))
-
-(org-add-link-type
- "doi"
- 'doi-link-menu)
-#+END_SRC
-
-doi:10.1021/jp047349j
-
-
-* Getting a doi for a bibtex entry missing one
-Some bibtex entries do not have a DOI, maybe because they were entered by hand, or copied from a source that did not have it available. Here we develop some functions to help you find the DOI using Crossref.
-
-Here is our example bibtex entry.
-#+BEGIN_SRC bibtex
-@article{deml-2014-oxide,
-  author =      {Ann M. Deml and Vladan Stevanovi{\'c} and
-                  Christopher L. Muhich and Charles B. Musgrave and
-                  Ryan O'Hayre},
-  title =       {Oxide Enthalpy of Formation and Band Gap Energy As
-                  Accurate Descriptors of Oxygen Vacancy Formation
-                  Energetics},
-  journal =     {Energy Environ. Sci.},
-  volume =      7,
-  number =      6,
-  pages =       1996,
-  year =        2014,
-  doi =                 {10.1039/c3ee43874k,
-  url =                 {http://dx.doi.org/10.1039/c3ee43874k}},
-
-}
-
-
-#+END_SRC
-
-The idea is to query Crossref in a way that is likely to give us a hit relevant to the entry.
-
-According to http://search.crossref.org/help/api we can send a query with a free form citation that may give us something back. We do this to get a list of candidates, and run a helm command to get the doi.
-
-
-#+BEGIN_SRC emacs-lisp :tangle doi-utils.el
-(defun doi-utils-crossref-citation-query ()
-  "Query Crossref with the title of the bibtex entry at point to
-get a list of possible matches. This opens a helm buffer to
-select an entry. The default action inserts a doi and url field
-in the bibtex entry at point. The second action opens the doi
-url. If there is already a doi field, the function raises an
-error."
-  (interactive)
-  (bibtex-beginning-of-entry)
-  (let* ((entry (bibtex-parse-entry))
-        (json-string)
-        (json-data)
-        (doi))
-    (unless (string= ""(reftex-get-bib-field "doi" entry))
-      (error "Entry already has a doi field"))
-
-    (with-current-buffer
-       (url-retrieve-synchronously
-        (concat
-         "http://search.crossref.org/dois?q="
-         (url-hexify-string (org-ref-bib-citation))))
-      (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" (org-ref-bib-citation)))
-          (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 doi and url field" . (lambda (doi)
-                                                               (bibtex-make-field "doi")
-                                                               (backward-char)
-                                                               ;; crossref returns doi url, but I prefer only a doi for the doi field
-                                                               (insert (replace-regexp-in-string "^http://dx.doi.org/" "" doi))
-                                                               (when (string= ""(reftex-get-bib-field "url" entry))
-                                                                 (bibtex-make-field "url")
-                                                                 (backward-char)
-                                                                 (insert doi))))
-                               ("Open url" . (lambda (doi)
-                                               (browse-url doi))))))))
-      (helm :sources '(source)))))
-#+END_SRC
-
-#+RESULTS:
-: doi-utils-crossref-citation-query
-
-
-
-* 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
-
-#+name: json
-#+BEGIN_EXAMPLE
-[
-  {
-    "doi": "http://dx.doi.org/10.1039/c3ee43874k",
-    "score": 4.7002907,
-    "normalizedScore": 100,
-    "title": "Oxide enthalpy of formation and band gap energy as accurate descriptors of oxygen vacancy formation energetics",
-    "fullCitation": "Ann M. Deml, Vladan Stevanović, 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",
-    "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",
-    "year": "2014"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1103/physrevb.86.085123",
-    "score": 1.129964,
-    "normalizedScore": 24,
-    "title": "Composition-dependent oxygen vacancy formation in multicomponent wide-band-gap oxides",
-    "fullCitation": "Altynbek Murat, Julia E. Medvedeva, 2012, 'Composition-dependent oxygen vacancy formation in multicomponent wide-band-gap oxides', <i>Physical Review B</i>, vol. 86, no. 8",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1103%2Fphysrevb.86.085123&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Composition-dependent+oxygen+vacancy+formation+in+multicomponent+wide-band-gap+oxides&amp;rft.jtitle=Physical+Review+B&amp;rft.date=2012&amp;rft.volume=86&amp;rft.issue=8&amp;rft.aufirst=Altynbek&amp;rft.aulast=Murat&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Altynbek+Murat&amp;rft.au=+Julia+E.+Medvedeva",
-    "year": "2012"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1021/cm5033755",
-    "score": 0.94063884,
-    "normalizedScore": 20,
-    "title": " Tunable Oxygen Vacancy Formation Energetics in the Complex Perovskite Oxide Sr  x  La  1– x  Mn  y  Al  1– y  O 3 ",
-    "fullCitation": "Ann M. Deml, Vladan Stevanović, Aaron M. Holder, Michael Sanders, Ryan O’Hayre, Charles B. Musgrave, 2014, ' Tunable Oxygen Vacancy Formation Energetics in the Complex Perovskite Oxide Sr  x  La  1– x  Mn  y  Al  1– y  O 3 ', <i>Chemistry of Materials</i>, vol. 26, no. 22, pp. 6595-6602",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1021%2Fcm5033755&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=+Tunable+Oxygen+Vacancy+Formation+Energetics+in+the+Complex+Perovskite+Oxide+Sr++x++La++1%E2%80%93+x++Mn++y++Al++1%E2%80%93+y++O+3+&amp;rft.jtitle=Chemistry+of+Materials&amp;rft.date=2014&amp;rft.volume=26&amp;rft.issue=22&amp;rft.spage=6595&amp;rft.epage=6602&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=+Aaron+M.+Holder&amp;rft.au=+Michael+Sanders&amp;rft.au=+Ryan+O%E2%80%99Hayre&amp;rft.au=+Charles+B.+Musgrave",
-    "year": "2014"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1103/physrevb.37.5905",
-    "score": 0.8346345,
-    "normalizedScore": 17,
-    "title": "Oxygen-vacancy-formation enthalpy in YBa_{2}(Cu_{0.985}Fe_{0.015})_{3}O_{7-δ} oxide superconductor",
-    "fullCitation": "Chuck Blue, Khaled Elgaid, Ivan Zitkovsky, P. Boolchand, Darl McDaniel, W. Joiner, Jean Oostens, Warren Huff, 1988, 'Oxygen-vacancy-formation enthalpy in YBa_{2}(Cu_{0.985}Fe_{0.015})_{3}O_{7-δ} oxide superconductor', <i>Physical Review B</i>, vol. 37, no. 10, pp. 5905-5908",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1103%2Fphysrevb.37.5905&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Oxygen-vacancy-formation+enthalpy+in+YBa_%7B2%7D%28Cu_%7B0.985%7DFe_%7B0.015%7D%29_%7B3%7DO_%7B7-%CE%B4%7D+oxide+superconductor&amp;rft.jtitle=Physical+Review+B&amp;rft.date=1988&amp;rft.volume=37&amp;rft.issue=10&amp;rft.spage=5905&amp;rft.epage=5908&amp;rft.aufirst=Chuck&amp;rft.aulast=Blue&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Chuck+Blue&amp;rft.au=+Khaled+Elgaid&amp;rft.au=+Ivan+Zitkovsky&amp;rft.au=+P.+Boolchand&amp;rft.au=+Darl+McDaniel&amp;rft.au=+W.+Joiner&amp;rft.au=+Jean+Oostens&amp;rft.au=+Warren+Huff",
-    "year": "1988"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1063/1.1732384",
-    "score": 0.7613335,
-    "normalizedScore": 16,
-    "title": "Enthalpy of Formation of Oxygen Vacancies in Barium Oxide",
-    "fullCitation": "H. Holloway, 1962, 'Enthalpy of Formation of Oxygen Vacancies in Barium Oxide', <i>The Journal of Chemical Physics</i>, vol. 36, no. 11, p. 2820",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1063%2F1.1732384&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Enthalpy+of+Formation+of+Oxygen+Vacancies+in+Barium+Oxide&amp;rft.jtitle=The+Journal+of+Chemical+Physics&amp;rft.date=1962&amp;rft.volume=36&amp;rft.issue=11&amp;rft.spage=2820&amp;rft.aufirst=H.&amp;rft.aulast=Holloway&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=H.+Holloway",
-    "year": "1962"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1002/crat.2170221219",
-    "score": 0.73206276,
-    "normalizedScore": 15,
-    "title": "Vacancy formation enthalpy in AgZn alloys",
-    "fullCitation": "St. Chabik, 1987, 'Vacancy formation enthalpy in AgZn alloys', <i>Crystal Research and Technology</i>, vol. 22, no. 12, pp. 1523-1527",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1002%2Fcrat.2170221219&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Vacancy+formation+enthalpy+in+AgZn+alloys&amp;rft.jtitle=Crystal+Research+and+Technology&amp;rft.date=1987&amp;rft.volume=22&amp;rft.issue=12&amp;rft.spage=1523&amp;rft.epage=1527&amp;rft.aufirst=St.&amp;rft.aulast=Chabik&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=St.+Chabik",
-    "year": "1987"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1007/s10562-013-0985-7",
-    "score": 0.692246,
-    "normalizedScore": 14,
-    "title": "Methane Oxidation by Lanthanum Oxide Doped with Cu, Zn, Mg, Fe, Nb, Ti, Zr, or Ta: The Connection Between the Activation Energy and the Energy of Oxygen-Vacancy Formation",
-    "fullCitation": "Alan R. Derk, Bo Li, Sudhanshu Sharma, George M. Moore, Eric W. McFarland, Horia Metiu, 2013, 'Methane Oxidation by Lanthanum Oxide Doped with Cu, Zn, Mg, Fe, Nb, Ti, Zr, or Ta: The Connection Between the Activation Energy and the Energy of Oxygen-Vacancy Formation', <i>Catalysis Letters</i>, vol. 143, no. 5, pp. 406-410",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1007%2Fs10562-013-0985-7&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Methane+Oxidation+by+Lanthanum+Oxide+Doped+with+Cu%2C+Zn%2C+Mg%2C+Fe%2C+Nb%2C+Ti%2C+Zr%2C+or+Ta%3A+The+Connection+Between+the+Activation+Energy+and+the+Energy+of+Oxygen-Vacancy+Formation&amp;rft.jtitle=Catalysis+Letters&amp;rft.date=2013&amp;rft.volume=143&amp;rft.issue=5&amp;rft.spage=406&amp;rft.epage=410&amp;rft.aufirst=Alan+R.&amp;rft.aulast=Derk&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Alan+R.+Derk&amp;rft.au=+Bo+Li&amp;rft.au=+Sudhanshu+Sharma&amp;rft.au=+George+M.+Moore&amp;rft.au=+Eric+W.+McFarland&amp;rft.au=+Horia+Metiu",
-    "year": "2013"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1039/c3cp55214d",
-    "score": 0.6675249,
-    "normalizedScore": 14,
-    "title": "Oxygen vacancy formation and annihilation in lanthanum cerium oxide as a metal reactive oxide on 4H-silicon carbide",
-    "fullCitation": "Way Foong Lim, Kuan Yew Cheong, 2014, 'Oxygen vacancy formation and annihilation in lanthanum cerium oxide as a metal reactive oxide on 4H-silicon carbide', <i>Physical Chemistry Chemical Physics</i>, vol. 16, no. 15, p. 7015",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1039%2Fc3cp55214d&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Oxygen+vacancy+formation+and+annihilation+in+lanthanum+cerium+oxide+as+a+metal+reactive+oxide+on+4H-silicon+carbide&amp;rft.jtitle=Physical+Chemistry+Chemical+Physics&amp;rft.date=2014&amp;rft.volume=16&amp;rft.issue=15&amp;rft.spage=7015&amp;rft.aufirst=Way+Foong&amp;rft.aulast=Lim&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Way+Foong+Lim&amp;rft.au=+Kuan+Yew+Cheong",
-    "year": "2014"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1021/cm052543j",
-    "score": 0.6519111,
-    "normalizedScore": 13,
-    "title": "Energetics of Bulk and Nano-Akaganeite, β-FeOOH:  Enthalpy of Formation, Surface Enthalpy, and Enthalpy of Water Adsorption",
-    "fullCitation": "Lena Mazeina, Suraj Deore, Alexandra Navrotsky, 2006, 'Energetics of Bulk and Nano-Akaganeite, β-FeOOH:  Enthalpy of Formation, Surface Enthalpy, and Enthalpy of Water Adsorption', <i>Chemistry of Materials</i>, vol. 18, no. 7, pp. 1830-1838",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1021%2Fcm052543j&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Energetics+of+Bulk+and+Nano-Akaganeite%2C+%CE%B2-FeOOH%3A%C2%A0+Enthalpy+of+Formation%2C+Surface+Enthalpy%2C+and+Enthalpy+of+Water+Adsorption&amp;rft.jtitle=Chemistry+of+Materials&amp;rft.date=2006&amp;rft.volume=18&amp;rft.issue=7&amp;rft.spage=1830&amp;rft.epage=1838&amp;rft.aufirst=Lena&amp;rft.aulast=Mazeina&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Lena+Mazeina&amp;rft.au=+Suraj+Deore&amp;rft.au=+Alexandra+Navrotsky",
-    "year": "2006"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1063/1.1677897",
-    "score": 0.6344446,
-    "normalizedScore": 13,
-    "title": "Thermochemical and Theoretical Investigations of the Sodium-Oxygen System. I. The Standard Enthalpy of Formation of Sodium Oxide (Na2O)",
-    "fullCitation": "P. A. G. O'Hare, 1972, 'Thermochemical and Theoretical Investigations of the Sodium-Oxygen System. I. The Standard Enthalpy of Formation of Sodium Oxide (Na2O)', <i>The Journal of Chemical Physics</i>, vol. 56, no. 9, p. 4513",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1063%2F1.1677897&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Thermochemical+and+Theoretical+Investigations+of+the+Sodium-Oxygen+System.+I.+The+Standard+Enthalpy+of+Formation+of+Sodium+Oxide+%28Na2O%29&amp;rft.jtitle=The+Journal+of+Chemical+Physics&amp;rft.date=1972&amp;rft.volume=56&amp;rft.issue=9&amp;rft.spage=4513&amp;rft.aufirst=P.+A.+G.&amp;rft.aulast=O%27Hare&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=P.+A.+G.+O%27Hare",
-    "year": "1972"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1063/1.1679492",
-    "score": 0.6344446,
-    "normalizedScore": 13,
-    "title": "Erratum: Thermochemical and theoretical investigations of the sodium-oxygen system. I. The standard enthalpy of formation of sodium oxide (Na2O)",
-    "fullCitation": "P. A. G. O'Hare, 1973, 'Erratum: Thermochemical and theoretical investigations of the sodium-oxygen system. I. The standard enthalpy of formation of sodium oxide (Na2O)', <i>The Journal of Chemical Physics</i>, vol. 58, no. 5, p. 2196",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1063%2F1.1679492&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Erratum%3A+Thermochemical+and+theoretical+investigations+of+the+sodium-oxygen+system.+I.+The+standard+enthalpy+of+formation+of+sodium+oxide+%28Na2O%29&amp;rft.jtitle=The+Journal+of+Chemical+Physics&amp;rft.date=1973&amp;rft.volume=58&amp;rft.issue=5&amp;rft.spage=2196&amp;rft.aufirst=P.+A.+G.&amp;rft.aulast=O%27Hare&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=P.+A.+G.+O%27Hare",
-    "year": "1973"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1002/pssb.19680250249",
-    "score": 0.62748235,
-    "normalizedScore": 13,
-    "title": "On enthalpy calculation of vacancy formation in inorganic substances",
-    "fullCitation": "B. N. Oshcherin, 1968, 'On enthalpy calculation of vacancy formation in inorganic substances', <i>Physica Status Solidi (b)</i>, vol. 25, no. 2, pp. K123-K125",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1002%2Fpssb.19680250249&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=On+enthalpy+calculation+of+vacancy+formation+in+inorganic+substances&amp;rft.jtitle=Physica+Status+Solidi+%28b%29&amp;rft.date=1968&amp;rft.volume=25&amp;rft.issue=2&amp;rft.spage=K123&amp;rft.epage=K125&amp;rft.aufirst=B.+N.&amp;rft.aulast=Oshcherin&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=B.+N.+Oshcherin",
-    "year": "1968"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1002/pssb.2221040224",
-    "score": 0.62748235,
-    "normalizedScore": 13,
-    "title": "Vacancy Formation Enthalpy in Cadmium by Positron Lifetime Measurements",
-    "fullCitation": "P. Mascher, L. Breitenhuber, W. Puff, 1981, 'Vacancy Formation Enthalpy in Cadmium by Positron Lifetime Measurements', <i>physica status solidi (b)</i>, vol. 104, no. 2, pp. 601-605",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1002%2Fpssb.2221040224&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Vacancy+Formation+Enthalpy+in+Cadmium+by+Positron+Lifetime+Measurements&amp;rft.jtitle=physica+status+solidi+%28b%29&amp;rft.date=1981&amp;rft.volume=104&amp;rft.issue=2&amp;rft.spage=601&amp;rft.epage=605&amp;rft.aufirst=P.&amp;rft.aulast=Mascher&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=P.+Mascher&amp;rft.au=+L.+Breitenhuber&amp;rft.au=+W.+Puff",
-    "year": "1981"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1016/0375-9601(79)90707-2",
-    "score": 0.62748235,
-    "normalizedScore": 13,
-    "title": "Vacancy formation enthalpy in γ cerium from positron annihilation",
-    "fullCitation": "M. Boidron, R. Paulin, 1979, 'Vacancy formation enthalpy in γ cerium from positron annihilation', <i>Physics Letters A</i>, vol. 73, no. 3, pp. 200-202",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1016%2F0375-9601%2879%2990707-2&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Vacancy+formation+enthalpy+in+%CE%B3+cerium+from+positron+annihilation&amp;rft.jtitle=Physics+Letters+A&amp;rft.date=1979&amp;rft.volume=73&amp;rft.issue=3&amp;rft.spage=200&amp;rft.epage=202&amp;rft.aufirst=M.&amp;rft.aulast=Boidron&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=M.+Boidron&amp;rft.au=+R.+Paulin",
-    "year": "1979"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1016/0036-9748(83)90449-0",
-    "score": 0.62748235,
-    "normalizedScore": 13,
-    "title": "Estimation of the vacancy formation enthalpy of metals",
-    "fullCitation": "Alcides R. Patete, Joachim P. Neumann, 1983, 'Estimation of the vacancy formation enthalpy of metals', <i>Scripta Metallurgica</i>, vol. 17, no. 8, pp. 1047-1048",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1016%2F0036-9748%2883%2990449-0&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Estimation+of+the+vacancy+formation+enthalpy+of+metals&amp;rft.jtitle=Scripta+Metallurgica&amp;rft.date=1983&amp;rft.volume=17&amp;rft.issue=8&amp;rft.spage=1047&amp;rft.epage=1048&amp;rft.aufirst=Alcides+R.&amp;rft.aulast=Patete&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Alcides+R.+Patete&amp;rft.au=+Joachim+P.+Neumann",
-    "year": "1983"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1039/c3ja50034a",
-    "score": 0.62469214,
-    "normalizedScore": 13,
-    "title": "Formation of an oxygen vacancy-dinitrogen complex in nitrogen-doped hafnium oxide",
-    "fullCitation": "Mino Yang, Jee-Hwan Bae, Cheol-Woong Yang, Anass Benayad, Hionsuck Baik, 2013, 'Formation of an oxygen vacancy-dinitrogen complex in nitrogen-doped hafnium oxide', <i>Journal of Analytical Atomic Spectrometry</i>, vol. 28, no. 4, p. 482",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1039%2Fc3ja50034a&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Formation+of+an+oxygen+vacancy-dinitrogen+complex+in+nitrogen-doped+hafnium+oxide&amp;rft.jtitle=Journal+of+Analytical+Atomic+Spectrometry&amp;rft.date=2013&amp;rft.volume=28&amp;rft.issue=4&amp;rft.spage=482&amp;rft.aufirst=Mino&amp;rft.aulast=Yang&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Mino+Yang&amp;rft.au=+Jee-Hwan+Bae&amp;rft.au=+Cheol-Woong+Yang&amp;rft.au=+Anass+Benayad&amp;rft.au=+Hionsuck+Baik",
-    "year": "2013"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1016/0021-9517(81)90023-3",
-    "score": 0.62469214,
-    "normalizedScore": 13,
-    "title": "SCF-SW-X$alpha; calculations of the removal of oxygen from oxide surfaces by vacancy formation and crystallographic shear mechanisms",
-    "fullCitation": "E BROCAWIK, 1981, 'SCF-SW-X$alpha; calculations of the removal of oxygen from oxide surfaces by vacancy formation and crystallographic shear mechanisms', <i>Journal of Catalysis</i>, vol. 72, no. 2, pp. 379-382",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1016%2F0021-9517%2881%2990023-3&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=SCF-SW-X%24alpha%3B+calculations+of+the+removal+of+oxygen+from+oxide+surfaces+by+vacancy+formation+and+crystallographic+shear+mechanisms&amp;rft.jtitle=Journal+of+Catalysis&amp;rft.date=1981&amp;rft.volume=72&amp;rft.issue=2&amp;rft.spage=379&amp;rft.epage=382&amp;rft.aufirst=E&amp;rft.aulast=BROCAWIK&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=E+BROCAWIK",
-    "year": "1981"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1063/1.2335842",
-    "score": 0.62469214,
-    "normalizedScore": 13,
-    "title": "Bulk and surface oxygen vacancy formation and diffusion in single crystals, ultrathin films, and metal grown oxide structures",
-    "fullCitation": "J. Carrasco, N. Lopez, F. Illas, H.-J. Freund, 2006, 'Bulk and surface oxygen vacancy formation and diffusion in single crystals, ultrathin films, and metal grown oxide structures', <i>The Journal of Chemical Physics</i>, vol. 125, no. 7, p. 074711",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1063%2F1.2335842&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Bulk+and+surface+oxygen+vacancy+formation+and+diffusion+in+single+crystals%2C+ultrathin+films%2C+and+metal+grown+oxide+structures&amp;rft.jtitle=The+Journal+of+Chemical+Physics&amp;rft.date=2006&amp;rft.volume=125&amp;rft.issue=7&amp;rft.spage=074711&amp;rft.aufirst=J.&amp;rft.aulast=Carrasco&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=J.+Carrasco&amp;rft.au=+N.+Lopez&amp;rft.au=+F.+Illas&amp;rft.au=+H.-J.+Freund",
-    "year": "2006"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1016/j.ijhydene.2011.12.079",
-    "score": 0.6176822,
-    "normalizedScore": 13,
-    "title": "Oxygen vacancy formation on the Ni/Ce0.75Zr0.25O2(111) surface. A DFT+U study",
-    "fullCitation": "Delfina García Pintos, Alfredo Juan, Beatriz Irigoyen, 2012, 'Oxygen vacancy formation on the Ni/Ce0.75Zr0.25O2(111) surface. A DFT+U study', <i>International Journal of Hydrogen Energy</i>, vol. 37, no. 19, pp. 14937-14944",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1016%2Fj.ijhydene.2011.12.079&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Oxygen+vacancy+formation+on+the+Ni%2FCe0.75Zr0.25O2%28111%29+surface.+A+DFT%2BU+study&amp;rft.jtitle=International+Journal+of+Hydrogen+Energy&amp;rft.date=2012&amp;rft.volume=37&amp;rft.issue=19&amp;rft.spage=14937&amp;rft.epage=14944&amp;rft.aufirst=Delfina&amp;rft.aulast=Garc%C3%ADa+Pintos&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Delfina+Garc%C3%ADa+Pintos&amp;rft.au=+Alfredo+Juan&amp;rft.au=+Beatriz+Irigoyen",
-    "year": "2012"
-  },
-  {
-    "doi": "http://dx.doi.org/10.1103/physrevb.90.144105",
-    "score": 0.6172708,
-    "normalizedScore": 13,
-    "title": "Vacancy formation enthalpy of filled <span class=\"aps-inline-formula\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>d</mi></math></span>-band noble metals by hybrid functionals",
-    "fullCitation": "Weiwei Xing, Peitao Liu, Xiyue Cheng, Haiyang Niu, Hui Ma, Dianzhong Li, Yiyi Li, Xing-Qiu Chen, 2014, 'Vacancy formation enthalpy of filled &lt;span class=&quot;aps-inline-formula&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/math&gt;&lt;/span&gt;-band noble metals by hybrid functionals', <i>Physical Review B</i>, vol. 90, no. 14",
-    "coins": "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1103%2Fphysrevb.90.144105&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Vacancy+formation+enthalpy+of+filled+%3Cspan+class%3D%22aps-inline-formula%22%3E%3Cmath+xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1998%2FMath%2FMathML%22%3E%3Cmi%3Ed%3C%2Fmi%3E%3C%2Fmath%3E%3C%2Fspan%3E-band+noble+metals+by+hybrid+functionals&amp;rft.jtitle=Physical+Review+B&amp;rft.date=2014&amp;rft.volume=90&amp;rft.issue=14&amp;rft.aufirst=Weiwei&amp;rft.aulast=Xing&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Weiwei+Xing&amp;rft.au=+Peitao+Liu&amp;rft.au=+Xiyue+Cheng&amp;rft.au=+Haiyang+Niu&amp;rft.au=+Hui+Ma&amp;rft.au=+Dianzhong+Li&amp;rft.au=+Yiyi+Li&amp;rft.au=+Xing-Qiu+Chen",
-    "year": "2014"
-  }
-]
-#+END_EXAMPLE
-
-
-#+BEGIN_SRC emacs-lisp :var data=json  :results value raw
-(let ((json-object-type 'plist)
-      (json (json-read-from-string data)))
-(aref json 0))
-#+END_SRC
-
-#+RESULTS:
-((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) (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) (title . Oxide enthalpy of formation and band gap energy as accurate descriptors of oxygen vacancy formation energetics) (normalizedScore . 100) (score . 4.7002907) (doi . http://dx.doi.org/10.1039/c3ee43874k))
-
-
-
-Here is a list of helm candidates
-#+BEGIN_SRC emacs-lisp :var data=json :results code
-(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
-(((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")
-  (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")
-  (title . "Oxide enthalpy of formation and band gap energy as accurate descriptors of oxygen vacancy formation energetics")
-  (normalizedScore . 100)
-  (score . 4.7002907)
-  (doi . "http://dx.doi.org/10.1039/c3ee43874k"))
- ((fullCitation . "Altynbek Murat, Julia E. Medvedeva, 2012, 'Composition-dependent oxygen vacancy formation in multicomponent wide-band-gap oxides', <i>Physical Review B</i>, vol. 86, no. 8")
-  (year . "2012")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1103%2Fphysrevb.86.085123&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Composition-dependent+oxygen+vacancy+formation+in+multicomponent+wide-band-gap+oxides&amp;rft.jtitle=Physical+Review+B&amp;rft.date=2012&amp;rft.volume=86&amp;rft.issue=8&amp;rft.aufirst=Altynbek&amp;rft.aulast=Murat&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Altynbek+Murat&amp;rft.au=+Julia+E.+Medvedeva")
-  (fullCitation . "Altynbek Murat, Julia E. Medvedeva, 2012, 'Composition-dependent oxygen vacancy formation in multicomponent wide-band-gap oxides', <i>Physical Review B</i>, vol. 86, no. 8")
-  (title . "Composition-dependent oxygen vacancy formation in multicomponent wide-band-gap oxides")
-  (normalizedScore . 24)
-  (score . 1.129964)
-  (doi . "http://dx.doi.org/10.1103/physrevb.86.085123"))
- ((fullCitation . "Ann M. Deml, Vladan Stevanovi\304\207, Aaron M. Holder, Michael Sanders, Ryan O\342\200\231Hayre, Charles B. Musgrave, 2014, ' Tunable Oxygen Vacancy Formation Energetics in the Complex Perovskite Oxide Sr  x  La  1\342\200\223 x  Mn  y  Al  1\342\200\223 y  O 3 ', <i>Chemistry of Materials</i>, vol. 26, no. 22, pp. 6595-6602")
-  (year . "2014")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1021%2Fcm5033755&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=+Tunable+Oxygen+Vacancy+Formation+Energetics+in+the+Complex+Perovskite+Oxide+Sr++x++La++1%E2%80%93+x++Mn++y++Al++1%E2%80%93+y++O+3+&amp;rft.jtitle=Chemistry+of+Materials&amp;rft.date=2014&amp;rft.volume=26&amp;rft.issue=22&amp;rft.spage=6595&amp;rft.epage=6602&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=+Aaron+M.+Holder&amp;rft.au=+Michael+Sanders&amp;rft.au=+Ryan+O%E2%80%99Hayre&amp;rft.au=+Charles+B.+Musgrave")
-  (fullCitation . "Ann M. Deml, Vladan Stevanovi\304\207, Aaron M. Holder, Michael Sanders, Ryan O\342\200\231Hayre, Charles B. Musgrave, 2014, ' Tunable Oxygen Vacancy Formation Energetics in the Complex Perovskite Oxide Sr  x  La  1\342\200\223 x  Mn  y  Al  1\342\200\223 y  O 3 ', <i>Chemistry of Materials</i>, vol. 26, no. 22, pp. 6595-6602")
-  (title . " Tunable Oxygen Vacancy Formation Energetics in the Complex Perovskite Oxide Sr  x  La  1\342\200\223 x  Mn  y  Al  1\342\200\223 y  O 3 ")
-  (normalizedScore . 20)
-  (score . 0.94063884)
-  (doi . "http://dx.doi.org/10.1021/cm5033755"))
- ((fullCitation . "Chuck Blue, Khaled Elgaid, Ivan Zitkovsky, P. Boolchand, Darl McDaniel, W. Joiner, Jean Oostens, Warren Huff, 1988, 'Oxygen-vacancy-formation enthalpy in YBa_{2}(Cu_{0.985}Fe_{0.015})_{3}O_{7-\316\264} oxide superconductor', <i>Physical Review B</i>, vol. 37, no. 10, pp. 5905-5908")
-  (year . "1988")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1103%2Fphysrevb.37.5905&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Oxygen-vacancy-formation+enthalpy+in+YBa_%7B2%7D%28Cu_%7B0.985%7DFe_%7B0.015%7D%29_%7B3%7DO_%7B7-%CE%B4%7D+oxide+superconductor&amp;rft.jtitle=Physical+Review+B&amp;rft.date=1988&amp;rft.volume=37&amp;rft.issue=10&amp;rft.spage=5905&amp;rft.epage=5908&amp;rft.aufirst=Chuck&amp;rft.aulast=Blue&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Chuck+Blue&amp;rft.au=+Khaled+Elgaid&amp;rft.au=+Ivan+Zitkovsky&amp;rft.au=+P.+Boolchand&amp;rft.au=+Darl+McDaniel&amp;rft.au=+W.+Joiner&amp;rft.au=+Jean+Oostens&amp;rft.au=+Warren+Huff")
-  (fullCitation . "Chuck Blue, Khaled Elgaid, Ivan Zitkovsky, P. Boolchand, Darl McDaniel, W. Joiner, Jean Oostens, Warren Huff, 1988, 'Oxygen-vacancy-formation enthalpy in YBa_{2}(Cu_{0.985}Fe_{0.015})_{3}O_{7-\316\264} oxide superconductor', <i>Physical Review B</i>, vol. 37, no. 10, pp. 5905-5908")
-  (title . "Oxygen-vacancy-formation enthalpy in YBa_{2}(Cu_{0.985}Fe_{0.015})_{3}O_{7-\316\264} oxide superconductor")
-  (normalizedScore . 17)
-  (score . 0.8346345)
-  (doi . "http://dx.doi.org/10.1103/physrevb.37.5905"))
- ((fullCitation . "H. Holloway, 1962, 'Enthalpy of Formation of Oxygen Vacancies in Barium Oxide', <i>The Journal of Chemical Physics</i>, vol. 36, no. 11, p. 2820")
-  (year . "1962")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1063%2F1.1732384&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Enthalpy+of+Formation+of+Oxygen+Vacancies+in+Barium+Oxide&amp;rft.jtitle=The+Journal+of+Chemical+Physics&amp;rft.date=1962&amp;rft.volume=36&amp;rft.issue=11&amp;rft.spage=2820&amp;rft.aufirst=H.&amp;rft.aulast=Holloway&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=H.+Holloway")
-  (fullCitation . "H. Holloway, 1962, 'Enthalpy of Formation of Oxygen Vacancies in Barium Oxide', <i>The Journal of Chemical Physics</i>, vol. 36, no. 11, p. 2820")
-  (title . "Enthalpy of Formation of Oxygen Vacancies in Barium Oxide")
-  (normalizedScore . 16)
-  (score . 0.7613335)
-  (doi . "http://dx.doi.org/10.1063/1.1732384"))
- ((fullCitation . "St. Chabik, 1987, 'Vacancy formation enthalpy in AgZn alloys', <i>Crystal Research and Technology</i>, vol. 22, no. 12, pp. 1523-1527")
-  (year . "1987")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1002%2Fcrat.2170221219&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Vacancy+formation+enthalpy+in+AgZn+alloys&amp;rft.jtitle=Crystal+Research+and+Technology&amp;rft.date=1987&amp;rft.volume=22&amp;rft.issue=12&amp;rft.spage=1523&amp;rft.epage=1527&amp;rft.aufirst=St.&amp;rft.aulast=Chabik&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=St.+Chabik")
-  (fullCitation . "St. Chabik, 1987, 'Vacancy formation enthalpy in AgZn alloys', <i>Crystal Research and Technology</i>, vol. 22, no. 12, pp. 1523-1527")
-  (title . "Vacancy formation enthalpy in AgZn alloys")
-  (normalizedScore . 15)
-  (score . 0.73206276)
-  (doi . "http://dx.doi.org/10.1002/crat.2170221219"))
- ((fullCitation . "Alan R. Derk, Bo Li, Sudhanshu Sharma, George M. Moore, Eric W. McFarland, Horia Metiu, 2013, 'Methane Oxidation by Lanthanum Oxide Doped with Cu, Zn, Mg, Fe, Nb, Ti, Zr, or Ta: The Connection Between the Activation Energy and the Energy of Oxygen-Vacancy Formation', <i>Catalysis Letters</i>, vol. 143, no. 5, pp. 406-410")
-  (year . "2013")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1007%2Fs10562-013-0985-7&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Methane+Oxidation+by+Lanthanum+Oxide+Doped+with+Cu%2C+Zn%2C+Mg%2C+Fe%2C+Nb%2C+Ti%2C+Zr%2C+or+Ta%3A+The+Connection+Between+the+Activation+Energy+and+the+Energy+of+Oxygen-Vacancy+Formation&amp;rft.jtitle=Catalysis+Letters&amp;rft.date=2013&amp;rft.volume=143&amp;rft.issue=5&amp;rft.spage=406&amp;rft.epage=410&amp;rft.aufirst=Alan+R.&amp;rft.aulast=Derk&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Alan+R.+Derk&amp;rft.au=+Bo+Li&amp;rft.au=+Sudhanshu+Sharma&amp;rft.au=+George+M.+Moore&amp;rft.au=+Eric+W.+McFarland&amp;rft.au=+Horia+Metiu")
-  (fullCitation . "Alan R. Derk, Bo Li, Sudhanshu Sharma, George M. Moore, Eric W. McFarland, Horia Metiu, 2013, 'Methane Oxidation by Lanthanum Oxide Doped with Cu, Zn, Mg, Fe, Nb, Ti, Zr, or Ta: The Connection Between the Activation Energy and the Energy of Oxygen-Vacancy Formation', <i>Catalysis Letters</i>, vol. 143, no. 5, pp. 406-410")
-  (title . "Methane Oxidation by Lanthanum Oxide Doped with Cu, Zn, Mg, Fe, Nb, Ti, Zr, or Ta: The Connection Between the Activation Energy and the Energy of Oxygen-Vacancy Formation")
-  (normalizedScore . 14)
-  (score . 0.692246)
-  (doi . "http://dx.doi.org/10.1007/s10562-013-0985-7"))
- ((fullCitation . "Way Foong Lim, Kuan Yew Cheong, 2014, 'Oxygen vacancy formation and annihilation in lanthanum cerium oxide as a metal reactive oxide on 4H-silicon carbide', <i>Physical Chemistry Chemical Physics</i>, vol. 16, no. 15, p. 7015")
-  (year . "2014")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1039%2Fc3cp55214d&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Oxygen+vacancy+formation+and+annihilation+in+lanthanum+cerium+oxide+as+a+metal+reactive+oxide+on+4H-silicon+carbide&amp;rft.jtitle=Physical+Chemistry+Chemical+Physics&amp;rft.date=2014&amp;rft.volume=16&amp;rft.issue=15&amp;rft.spage=7015&amp;rft.aufirst=Way+Foong&amp;rft.aulast=Lim&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Way+Foong+Lim&amp;rft.au=+Kuan+Yew+Cheong")
-  (fullCitation . "Way Foong Lim, Kuan Yew Cheong, 2014, 'Oxygen vacancy formation and annihilation in lanthanum cerium oxide as a metal reactive oxide on 4H-silicon carbide', <i>Physical Chemistry Chemical Physics</i>, vol. 16, no. 15, p. 7015")
-  (title . "Oxygen vacancy formation and annihilation in lanthanum cerium oxide as a metal reactive oxide on 4H-silicon carbide")
-  (normalizedScore . 14)
-  (score . 0.6675249)
-  (doi . "http://dx.doi.org/10.1039/c3cp55214d"))
- ((fullCitation . "Lena Mazeina, Suraj Deore, Alexandra Navrotsky, 2006, 'Energetics of Bulk and Nano-Akaganeite, \316\262-FeOOH:\302\240 Enthalpy of Formation, Surface Enthalpy, and Enthalpy of Water Adsorption', <i>Chemistry of Materials</i>, vol. 18, no. 7, pp. 1830-1838")
-  (year . "2006")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1021%2Fcm052543j&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Energetics+of+Bulk+and+Nano-Akaganeite%2C+%CE%B2-FeOOH%3A%C2%A0+Enthalpy+of+Formation%2C+Surface+Enthalpy%2C+and+Enthalpy+of+Water+Adsorption&amp;rft.jtitle=Chemistry+of+Materials&amp;rft.date=2006&amp;rft.volume=18&amp;rft.issue=7&amp;rft.spage=1830&amp;rft.epage=1838&amp;rft.aufirst=Lena&amp;rft.aulast=Mazeina&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=Lena+Mazeina&amp;rft.au=+Suraj+Deore&amp;rft.au=+Alexandra+Navrotsky")
-  (fullCitation . "Lena Mazeina, Suraj Deore, Alexandra Navrotsky, 2006, 'Energetics of Bulk and Nano-Akaganeite, \316\262-FeOOH:\302\240 Enthalpy of Formation, Surface Enthalpy, and Enthalpy of Water Adsorption', <i>Chemistry of Materials</i>, vol. 18, no. 7, pp. 1830-1838")
-  (title . "Energetics of Bulk and Nano-Akaganeite, \316\262-FeOOH:\302\240 Enthalpy of Formation, Surface Enthalpy, and Enthalpy of Water Adsorption")
-  (normalizedScore . 13)
-  (score . 0.6519111)
-  (doi . "http://dx.doi.org/10.1021/cm052543j"))
- ((fullCitation . "P. A. G. O'Hare, 1972, 'Thermochemical and Theoretical Investigations of the Sodium-Oxygen System. I. The Standard Enthalpy of Formation of Sodium Oxide (Na2O)', <i>The Journal of Chemical Physics</i>, vol. 56, no. 9, p. 4513")
-  (year . "1972")
-  (coins . "ctx_ver=Z39.88-2004&amp;rft_id=info%3Adoi%2Fhttp%3A%2F%2Fdx.doi.org%2F10.1063%2F1.1677897&amp;rfr_id=info%3Asid%2Fcrossref.org%3Asearch&amp;rft.atitle=Thermochemical+and+Theoretical+Investigations+of+the+Sodium-Oxygen+System.+I.+The+Standard+Enthalpy+of+Formation+of+Sodium+Oxide+%28Na2O%29&amp;rft.jtitle=The+Journal+of+Chemical+Physics&amp;rft.date=1972&amp;rft.volume=56&amp;rft.issue=9&amp;rft.spage=4513&amp;rft.aufirst=P.+A.+G.&amp;rft.aulast=O%27Hare&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rft.genre=article&amp;rft.au=P.+A.+G.+O%27Hare")
-  (fullCitation . "P. A. G. O'Hare, 1972, 'Thermochemical and Theoretical Investigations of the Sodium-Oxygen System. I. The Standard Enthalpy of Formation of Sodium Oxide (Na2O)', <i>The Journal of Chemical Physics</i>, vol. 56, no. 9, p. 4513")
-  (title . "Thermochemical and Theoretical Investigations of the Sodium-Oxygen System. I. The Standard Enthalpy of Formation of Sodium Oxide (Na2O)")
-  (normalizedScore . 13)
-  (score . 0.6344446)
-  (doi . "http://dx.doi.org/10.1063/1.1677897"))
- ...)
-#+END_SRC
-
-
-* 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
-
-
-
-* 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
-
-
-
-
-
-#+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
diff --git a/isbn.el b/isbn.el
new file mode 100644 (file)
index 0000000..a759bc0
--- /dev/null
+++ b/isbn.el
@@ -0,0 +1,123 @@
+;;; isbn.el --- utilities for generating bibtex entries from an ISBN  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+;; * ISBN utility
+
+;; I found this on the web. It can be handy, but the bibtex entry has a lot of stuff in it.
+
+(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)))
+
+;; Here we get isbn metadata and build a bibtex entry.
+;; http://xisbn.worldcat.org/xisbnadmin/doc/api.htm#getmetadata
+
+(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-string
+     "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
+                  (cl-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-string
+                    (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)))
+
+(provide 'isbn)
+;;; isbn.el ends here
index e792ffa01f13682bca8081bc18cefb52b527e1b7..695cf87ddaac5df83ccea07c3f0df680c4438861 100644 (file)
 ;;; jmax-bibtex.el --- jmax-bibtex utilities
 
+;; Copyright(C) 2014 John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; URL: https://github.com/jkitchin/org-ref
+;; Version: 0.1
+;; Keywords: org-mode, bibtex
+;; Package-Requires: ((org-ref) (s) (dash) (doi-utils) (key-chord))
+
+;; This file is not currently part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program ; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
 ;;; Commentary:
-;; Requires: s.el, dash.el, org-ref.el, doi-utils.el
+
+;; jmax-bibtex-generate-longtitles
+;; jmax-bibtex-generate-shorttitles
+;; jmax-stringify-journal-name :: replace a journal name with a string in
+;; `jmax-bibtex-journal-abbreviations'
+;; jmax-set-journal-string :: in a bibtex entry run this to replace the
+;; journal with a string
+;;
+;; jmax-title-case-article :: title case the title in an article
+;; jmax-sentence-case-article :: sentence case the title in an article.
+
+;; jmax-replace-nonascii :: replace nonascii characters in a bibtex
+;; entry. Replacements are in `jmax-nonascii-latex-replacements'.
+;;
+;; jmax-title-case-article
+;; jmax-sentence-case-article
+;;
+;; jmax-bibtex-next-entry :: bound to M-n
+;; jmax-bibtex-previous-entry :: bound to M-p
+;;
+;; Functions to act on a bibtex entry or file
+;; jmax-bibtex-hydra/body gives a hydra menu to a lot of useful functions.
+;; jmax-bibtex-new-entry/body gives a hydra menu to add new bibtex entries.
+;; jmax-bibtex-file/body gives a hydra menu of actions for the bibtex file
+;;
+;; jmax-bibtex :: a deprecated menu of actions
+
+(require 'hydra)
+(require 'key-chord)
 
 ;;; Code:
+;; * Custom variables
+(defgroup jmax-bibtex nil
+  "Customization group for jmax-bibtex.")
+
+
+(defcustom jmax-bibtex-hydra-key-chord
+  nil
+  "key-chord to run `jmax-bibtex-hydra'.
+I like \"jj\""
+  :type 'string
+  :group 'jmax-bibtex)
 
+
+(defcustom jmax-bibtex-hydra-key-binding
+  nil
+  "key-binding to run `jmax-bibtex-hydra'.
+I like \C-cj."
+  :type 'string
+  :group 'jmax-bibtex)
+
+;; * Journal abbreviations
 (defvar jmax-bibtex-journal-abbreviations
-  '(("ACAT" "ACS Catalysis" "ACS Catal.")
-    ("AM" "Acta Materialia" "Acta Mater.")
-    ("AMM" "Acta Metallurgica et Materialia" "Acta Metall. Mater.")
-    ("AMiner" "American Mineralogist" "Am. Mineral.")
-    ("AngC" "Angewandte Chemie-International Edition" "Angew. Chem. Int. Edit.")
-    ("APLM" "APL Materials" "APL Mat.")
-    ("ACBE" "Applied Catalysis B: Environmental" "Appl. Catal. B-Environ.")
-    ("APL" "Applied Physics Letters" "Appl. Phys. Lett.")
-    ("ASS" "Applied Surface Science" "Appl. Surf. Sci.")
-    ("CL" "Catalysis Letters" "Catal. Lett.")
-    ("CST" "Catalysis Science & Technology" "Catal. Sci. Technol.")
-    ("CT" "Catalysis Today" "Catal. Today")
-    ("CPL" "Chemical Physics Letters" "Chem. Phys. Lett")
-    ("CR" "Chemical Reviews" "Chem. Rev.")
-    ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
-    ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
-    ("CM" "Chemistry of Materials" "Chem. Mater.")
-    ("CSA" "Colloids and Surfaces, A: Physicochemical and Engineering Aspects" "Colloids Surf., A")
-    ("CPMS" "Computational Materials Science" "Comp. Mater. Sci.")
-    ("CPC" "Computer Physics Communications" "Comput. Phys. Commun.")
-    ("CGD" "Crystal Growth \\& Design" "Cryst. Growth Des.")
-    ("CEC" "CrystEngComm" "CrystEngComm")
-    ("ECST" "ECS Transactions" "ECS Trans.")
-    ("EES" "Energy \\& Environmental Science" "Energy Environ. Sci.")
-    ("HPR" "High Pressure Research" "High Pressure Res.")
-    ("IC" "Inorganic Chemistry" "Inorg. Chem.")
-    ("IECR" "Industrial \\& Engineering Chemistry Research" "Ind. Eng. Chem. Res.")
-    ("JJAP" "Japanese Journal of Applied Physics" "Jpn. J. Appl. Phys.")
-    ("JMatR" "Journal of  Materials Research" "J. Mater. Res.")
-    ("JALC" "Journal of Alloys and Compounds" "J. Alloy Compd.")
-    ("JAC" "Journal of Applied Crystallography" "J. Appl. Crystallogr.")
-    ("JAP" "Journal of Applied Physics" "J. Appl. Phys.")
-    ("JC" "Journal of Catalysis" "J. Catal.")
-    ("JCP" "Journal of Chemical Physics" "J. Chem. Phys.")
-    ("JCC" "Journal of Computational Chemistry" "J. Comput. Chem.")
-    ("JCG" "Journal of Crystal Growth" "J. Crys. Growth")
-    ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
-    ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
-    ("JMSL" "Journal of Materials Science Letters" "J. Mater. Sci. Lett.")
-    ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
-    ("JPE" "Journal of Phase Equilibria" "J. Phase Equilib.")
-    ("JPCS" "Journal of Physics and Chemistry of Solids" "J. Phys. Chem. Solids")
-    ("JPCM" "Journal of Physics: Condensed Matter" "J. Phys.: Condens. Matter")
-    ("JSSC" "Journal of Solid State Chemistry" "J. Solid State Chem.")
-    ("JACerS" "Journal of the American Ceramic Society" "J. Am. Ceram. Soc.")
-    ("JACS" "Journal of the American Chemical Society" "J. Am. Chem. Soc.")
-    ("JES" "Journal of The Electrochemical Society" "J. Electrochem. Soc.")
-    ("JEaC" "Journal of Electroanalytical Chemistry" "J. Electroanal. Chem.")
-    ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
-    ("JVST" "Journal of Vacuum Science \\& Technology A" "J. Vac. Sci. Technol. A")
-    ("ML" "Materials Letters" "Mater. Lett.")
-    ("MSE-BS" "Materials Science and Engineering B" "Mat. Sci. Eng. B-Solid")
-    ("MOLSIM" "Molecular Simulation" "Mol. Sim.")
-    ("Nature" "Nature" "Nature")
-    ("NM" "Nature Materials" "Nat. Mater.")
-    ("PML" "Philosophical Magazine Letters" "Phil. Mag. Lett.")
-    ("PMA" "Philosophical Magazine A" "Phil. Mag. A")
-    ("PA" "Physica A: Statistical Mechanics and its Applications" "Physica A")
-    ("PB" "Physica B-Condensed Matter" "Physica B")
-    ("PCCP" "Physical Chemistry Chemical Physics" "Phys. Chem. Chem. Phys.")
-    ("PSSB" "physica status solidi (b)" "Phys. Status Solidi B")
-    ("PRA" "Physical Review A" "Phys. Rev. A")
-    ("PRB" "Physical Review B" "Phys. Rev. B")
-    ("PRL" "Physical Review Letters" "Phys. Rev. Lett.")
-    ("PCM" "Physics and Chemistry of Minerals" "Phys. Chem. Miner.")
-    ("PSurfSci" "Progress in Surface Science" "Prog. Surf. Sci.")
-    ("Science" "Science" "Science")
-    ("SABC" "Sensors and Actuators B: Chemical" "Sensor. Actuat. B-Chem.")
-    ("SS" "Surface Science" "Surf. Sci.")
-    ("EPJB" "The European Physical Journal B" "Eur. Phys. J. B")
-    ("JPC" "The Journal of Physical Chemistry" "J. Phys. Chem.")
-    ("JPCB" "The Journal of Physical Chemistry B" "J. Phys. Chem. B")
-    ("JPCC" "The Journal of Physical Chemistry C" "J. Phys. Chem. C")
-    ("JPCL" "The Journal of Physical Chemistry Letters" "J. Phys. Chem. Lett.")
-    ("JCP" "The Journal of Chemical Physics" "J. Chem. Phys.")
-    ("MSMSE" "Modelling and Simulation in Materials Science and Engineering" "Modell. Simul. Mater. Sci. Eng.")
-    ("TSF" "Thin Solid Films" "Thin Solid Films")
-    ("TC" "Topics in Catalysis" "Top. Catal.")
-    ("WR" "Water Research" "Water Res."))
+  '()
   "List of (string journal-full-name journal-abbreviation).  Find abbreviations at http://cassi.cas.org/search.jsp.")
 
+(setq jmax-bibtex-journal-abbreviations
+      '(("ACR" "Accounts of Chemical Research" "Acc. Chem. Res.")
+       ("ACAT" "ACS Catalysis" "ACS Catal.")
+       ("AM" "Acta Materialia" "Acta Mater.")
+       ("AMM" "Acta Metallurgica et Materialia" "Acta Metall. Mater.")
+       ("AEM" "Advanced Energy Materials" "Adv. Energy Mater.")
+       ("AAMI" "ACS Applied Materials \\& Interfaces"
+        "ACS Appl. Mater. Interfaces")
+       ("AMiner" "American Mineralogist" "Am. Mineral.")
+       ("AngC" "Angewandte Chemie-International Edition"
+        "Angew. Chem. Int. Edit.")
+       ("APLM" "APL Materials" "APL Mat.")
+       ("ACBE" "Applied Catalysis B: Environmental" "Appl. Catal. B-Environ.")
+       ("APL" "Applied Physics Letters" "Appl. Phys. Lett.")
+       ("ASS" "Applied Surface Science" "Appl. Surf. Sci.")
+       ("CL" "Catalysis Letters" "Catal. Lett.")
+       ("CC" "Catalysis Communications" "Catal. Commun.")
+       ("CST" "Catalysis Science & Technology" "Catal. Sci. Technol.")
+       ("CT" "Catalysis Today" "Catal. Today")
+       ("ChC" "Chemical Communications" "Chem. Commun.")
+       ("CPL" "Chemical Physics Letters" "Chem. Phys. Lett")
+       ("CR" "Chemical Reviews" "Chem. Rev.")
+       ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
+       ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.")
+       ("CM" "Chemistry of Materials" "Chem. Mater.")
+       ("CSA" "Colloids and Surfaces, A: Physicochemical and Engineering Aspects"
+        "Colloids Surf., A")
+       ("CF" "Combustion and Flame" "Combust. Flame")
+       ("CPMS" "Computational Materials Science" "Comp. Mater. Sci.")
+       ("CPC" "Computer Physics Communications" "Comput. Phys. Commun.")
+       ("CSE" "Computing in Science \\& Engineering" "Comput. Sci. Eng.")
+       ("CGD" "Crystal Growth \\& Design" "Cryst. Growth Des.")
+       ("CEC" "CrystEngComm" "CrystEngComm")
+       ("EA" "Electrochimica Acta" "Electrochim. Acta")
+       ("ECST" "ECS Transactions" "ECS Trans.")
+       ("EES" "Energy \\& Environmental Science" "Energy Environ. Sci.")
+       ("HPR" "High Pressure Research" "High Pressure Res.")
+       ("IC" "Inorganic Chemistry" "Inorg. Chem.")
+       ("IECR" "Industrial \\& Engineering Chemistry Research"
+        "Ind. Eng. Chem. Res.")
+       ("JJAP" "Japanese Journal of Applied Physics" "Jpn. J. Appl. Phys.")
+       ("JMatR" "Journal of  Materials Research" "J. Mater. Res.")
+       ("JALC" "Journal of Alloys and Compounds" "J. Alloy Compd.")
+       ("JAC" "Journal of Applied Crystallography" "J. Appl. Crystallogr.")
+       ("JAE" "Journal of Applied Electrochemistry" "J. Appl. Electrochem.")
+       ("JAP" "Journal of Applied Physics" "J. Appl. Phys.")
+       ("JC" "Journal of Catalysis" "J. Catal.")
+       ("JCP" "Journal of Chemical Physics" "J. Chem. Phys.")
+       ("JCC" "Journal of Computational Chemistry" "J. Comput. Chem.")
+       ("JCG" "Journal of Crystal Growth" "J. Crys. Growth")
+       ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
+       ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.")
+       ("JMSL" "Journal of Materials Science Letters" "J. Mater. Sci. Lett.")
+       ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
+       ("JPE" "Journal of Phase Equilibria" "J. Phase Equilib.")
+       ("JPCS" "Journal of Physics and Chemistry of Solids"
+        "J. Phys. Chem. Solids")
+       ("JPCM" "Journal of Physics: Condensed Matter"
+        "J. Phys.: Condens. Matter")
+       ("JPS" "Journal of Power Sources" "J. Power Sources")
+       ("JSSC" "Journal of Solid State Chemistry" "J. Solid State Chem.")
+       ("JACerS" "Journal of the American Ceramic Society" "J. Am. Ceram. Soc.")
+       ("JACS" "Journal of the American Chemical Society" "J. Am. Chem. Soc.")
+       ("JASIST" "Journal of the American Society for Information Science and Technology"
+        "J. Am. Soc. Inf. Sci. Technol.")
+       ("JES" "Journal of The Electrochemical Society" "J. Electrochem. Soc.")
+       ("JEaC" "Journal of Electroanalytical Chemistry" "J. Electroanal. Chem.")
+       ("JMS" "Journal of Membrane Science" "J. Memb. Sci.")
+       ("JRS" "Journal of Raman Spectroscopy" "J. Raman Spectrosc.")
+       ("JVST" "Journal of Vacuum Science \\& Technology A"
+        "J. Vac. Sci. Technol. A")
+       ("ML" "Materials Letters" "Mater. Lett.")
+       ("MSE-BS" "Materials Science and Engineering B" "Mat. Sci. Eng. B-Solid")
+       ("MOLSIM" "Molecular Simulation" "Mol. Sim.")
+       ("Nature" "Nature" "Nature")
+       ("NM" "Nature Materials" "Nat. Mater.")
+       ("NC" "Nature Chemistry" "Nat. Chem.")
+       ("PML" "Philosophical Magazine Letters" "Phil. Mag. Lett.")
+       ("PMA" "Philosophical Magazine A" "Phil. Mag. A")
+       ("PA" "Physica A: Statistical Mechanics and its Applications" "Physica A")
+       ("PB" "Physica B-Condensed Matter" "Physica B")
+       ("PCCP" "Physical Chemistry Chemical Physics" "Phys. Chem. Chem. Phys.")
+       ("PSSB" "physica status solidi (b)" "Phys. Status Solidi B")
+       ("PRA" "Physical Review A" "Phys. Rev. A")
+       ("PRB" "Physical Review B" "Phys. Rev. B")
+       ("PRL" "Physical Review Letters" "Phys. Rev. Lett.")
+       ("PCM" "Physics and Chemistry of Minerals" "Phys. Chem. Miner.")
+       ("PNAS" "Proceedings of the National Academy of Sciences of the United States of America"
+        "Proc. Natl. Acad. Sci. U. S. A.")
+       ("PSurfSci" "Progress in Surface Science" "Prog. Surf. Sci.")
+       ("Science" "Science" "Science")
+       ("SM" "Scripta Materialia" "Scr. Mater.")
+       ("SABC" "Sensors and Actuators B: Chemical" "Sensor. Actuat. B-Chem.")
+       ("SS" "Surface Science" "Surf. Sci.")
+       ("EPJB" "The European Physical Journal B" "Eur. Phys. J. B")
+       ("JPC" "The Journal of Physical Chemistry" "J. Phys. Chem.")
+       ("JPCB" "The Journal of Physical Chemistry B" "J. Phys. Chem. B")
+       ("JPCC" "The Journal of Physical Chemistry C" "J. Phys. Chem. C")
+       ("JPCL" "The Journal of Physical Chemistry Letters"
+        "J. Phys. Chem. Lett.")
+       ("JCP" "The Journal of Chemical Physics" "J. Chem. Phys.")
+       ("MSMSE" "Modelling and Simulation in Materials Science and Engineering"
+        "Modell. Simul. Mater. Sci. Eng.")
+       ("TSF" "Thin Solid Films" "Thin Solid Films")
+       ("TC" "Topics in Catalysis" "Top. Catal.")
+       ("WR" "Water Research" "Water Res.")))
+
 
 (defun jmax-bibtex-generate-longtitles ()
   "Generate longtitles.bib which are @string definitions.
@@ -137,6 +239,24 @@ START and END allow you to use this with `bibtex-map-entries'"
        (bibtex-set-field "journal" bstring t)
         (bibtex-fill-entry)))))
 
+(defun jmax-helm-set-journal-string ()
+  "Helm interface to set a journal string."
+  (interactive)
+  (bibtex-set-field
+   "journal"
+   (helm :sources `((name . "journal")
+                   (candidates . ,(mapcar
+                                   (lambda (x)
+                                     (cons (format "%s | %s"  (nth 1 x) (nth 2 x))
+                                           (car x)))
+                                   jmax-bibtex-journal-abbreviations))
+                   (action . (lambda (x) (identity x))))
+        :input (s-trim (bibtex-autokey-get-field "journal")))
+   t)
+  (bibtex-fill-entry)
+  (bibtex-clean-entry))
+
+
 (defun jmax-set-journal-string (full-journal-name)
   "Set a bibtex journal name to the string that represents FULL-JOURNAL-NAME.
 This is defined in `jmax-bibtex-journal-abbreviations'."
@@ -156,6 +276,7 @@ This is defined in `jmax-bibtex-journal-abbreviations'."
     (bibtex-fill-entry)
     (bibtex-clean-entry)))
 
+;; * Non-ascii character replacement
 ;; see https://github.com/fxcoudert/tools/blob/master/doi2bib for more replacements
 (defvar jmax-nonascii-latex-replacements
   '()
@@ -199,15 +320,20 @@ This is defined in `jmax-bibtex-journal-abbreviations'."
        ("⇌" . "$\\\\leftrightharpoons$")
        ("×" . "$\\\\times$")
        ("°" . "$\\\\deg$")
+       ("ş" . "{\\\\c{s}}")
+       ("ı" . "i")                    ; I think this is a turkish i
        ;; I think these are non-ascii spaces. there seems to be more than one.
        (" " . " ")
        (" " . " ")
        ("–" . "-")
        ("−" . "-")
        ("–" . "-")
+       ("—" . "-")
        ("‘" . "'")
        ("’" . "'")
+       ("’" . "'")
        ("“" . "\"")
+       ("’" . "'")
        ("”" . "\"")))
 
 (defun jmax-replace-nonascii ()
@@ -220,11 +346,12 @@ This is defined in `jmax-bibtex-journal-abbreviations'."
     (dolist (char (mapcar (lambda (x) (car x)) jmax-nonascii-latex-replacements))
       (while (re-search-forward char nil t)
        (replace-match (cdr (assoc char jmax-nonascii-latex-replacements))))
-      (goto-char (point-min)))))
+      (goto-char (point-min))))
+  (save-buffer))
 
 (add-hook 'org-ref-clean-bibtex-entry-hook 'jmax-replace-nonascii)
 
-
+;; * Title case transformations
 (defvar jmax-lower-case-words
   '("a" "an" "on" "and" "for"
     "the" "of" "in")
@@ -326,9 +453,7 @@ all the title entries in articles."
       (bibtex-clean-entry)
       (bibtex-fill-entry))))
 
-
-
-
+;; * Navigation in bibtex file
 (defun jmax-bibtex-next-entry (&optional n)
   "Jump to the beginning of the next bibtex entry.
 N is a prefix argument.  If it is numeric, jump that many entries
@@ -366,9 +491,9 @@ N is a prefix argument.  If it is numeric, jump that many entries back."
 ;; add to bibtex-mode-hook
 (add-hook 'bibtex-mode-hook 'jmax-bibtex-mode-keys)
 
-
+;; * Functions to act on an entry with a doi
 (defun jmax-bibtex-entry-doi ()
-  "get doi from entry at point"
+  "Get doi from entry at point."
   (interactive)
   (save-excursion
     (bibtex-beginning-of-entry)
@@ -376,54 +501,159 @@ N is a prefix argument.  If it is numeric, jump that many entries back."
 
 
 (defun jmax-bibtex-wos ()
-  "Open bibtex entry in Web Of Science if there is a DOI"
+  "Open bibtex entry in Web Of Science if there is a DOI."
   (interactive)
   (doi-utils-wos (jmax-bibtex-entry-doi)))
 
 
 (defun jmax-bibtex-wos-citing ()
-  "Open citing articles for bibtex entry in Web Of Science if there is a DOI"
+  "Open citing articles for bibtex entry in Web Of Science if there is a DOI."
   (interactive)
   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
 
 
 (defun jmax-bibtex-wos-related ()
-  "Open related articles for bibtex entry in Web Of Science if there is a DOI"
+  "Open related articles for bibtex entry in Web Of Science if there is a DOI."
   (interactive)
   (doi-utils-wos-related (jmax-bibtex-entry-doi)))
 
 
 (defun jmax-bibtex-wos-citing ()
-  "Open citing articles for bibtex entry in Web Of Science if there is a DOI"
+  "Open citing articles for bibtex entry in Web Of Science if there is a DOI."
   (interactive)
   (doi-utils-wos-citing (jmax-bibtex-entry-doi)))
 
 
 (defun jmax-bibtex-crossref ()
+  "Open the bibtex entry in Crossref by its doi."
   (interactive)
   (doi-utils-crossref (jmax-bibtex-entry-doi)))
 
 
 (defun jmax-bibtex-google-scholar ()
+  "Open the bibtex entry at point in google-scholar by its doi."
   (interactive)
   (doi-utils-google-scholar (jmax-bibtex-entry-doi)))
 
 
 (defun jmax-bibtex-pubmed ()
+  "Open the bibtex entry at point in Pubmed by its doi."
   (interactive)
   (doi-utils-pubmed (jmax-bibtex-entry-doi)))
 
 
 (defun jmax-bibtex-pdf (doi)
-  "thin wrapper to get `jmax-bibtex' to open pdf"
+  "Open the pdf for the bibtex entry at point.
+Thin wrapper to get `jmax-bibtex' to open pdf, because it calls
+functions with a DOI argument."
   (interactive)
   (org-ref-open-bibtex-pdf))
 
 
-
+;; * Hydra menus
+;; ** Hydra menu for bibtex entries
+;; hydra menu for actions on bibtex entries
+(defhydra jmax-bibtex-hydra (:color blue)
+   "
+_p_: Open pdf     _y_: Copy key               _n_: New entry     _w_: WOS
+_b_: Open url     _f_: Copy formatted entry   _o_: Copy entry    _c_: WOS citing
+_r_: Refile entry _k_: Add keywords           _d_: delete entry  _a_: WOS related
+_e_: Email entry  _K_: Edit keywords          _L_: clean entry   _P_: Pubmed
+_U_: Update entry _N_: Open notes             _R_: Crossref      _g_: Google Scholar
+_s_: Sort entry   _a_: Remove nonascii        _h_: helm-bibtex   _q_: quit
+_u_: Update field _F_: file funcs
+_T_: Title case
+_S_: Sentence case
+"
+   ("p" org-ref-open-bibtex-pdf)
+   ("P" jmax-bibtex-pubmed)
+   ("w" jmax-bibtex-wos)
+   ("c" jmax-bibtex-wos-citing)
+   ("a" jmax-bibtex-wos-related)
+   ("R" jmax-bibtex-crossref)
+   ("g" jmax-bibtex-google-scholar)
+   ("n" jmax-bibtex-new-entry/body)
+   ("N" org-ref-open-bibtex-notes)
+   ("o" bibtex-copy-entry-as-kill)
+   ("d" bibtex-kill-entry)
+   ("L" org-ref-clean-bibtex-entry)
+   ("y" (kill-new  (bibtex-autokey-get-field "=key=")))
+   ("f" bibtex-copy-summary-as-kill)
+   ("k" helm-tag-bibtex-entry)
+   ("K" (lambda ()
+         (interactive)
+         (org-ref-set-bibtex-keywords
+          (read-string "Keywords: "
+                       (bibtex-autokey-get-field "keywords"))
+          t)))
+   ("b" org-ref-open-in-browser)
+   ("r" (lambda () (interactive)
+         (bibtex-beginning-of-entry)
+         (bibtex-kill-entry)
+         (find-file (ido-completing-read
+                     "Bibtex file: "
+                     (f-entries "." (lambda (f) (f-ext? f "bib")))))
+         (goto-char (point-max))
+         (bibtex-yank)
+         (save-buffer)
+         (kill-buffer)))
+   ("e" email-bibtex-entry)
+   ("U" (doi-utils-update-bibtex-entry-from-doi (jmax-bibtex-entry-doi)))
+   ("u" doi-utils-update-field)
+   ("F" jmax-bibtex-file/body)
+   ("h" helm-bibtex)
+   ("a" jmax-replace-nonascii)
+   ("s" org-ref-sort-bibtex-entry)
+   ("T" jmax-title-case-article)
+   ("S" jmax-sentence-case-article)
+   ("q" nil))
+
+;; create key-chord and key binding for hydra
+(when jmax-bibtex-hydra-key-chord
+  (key-chord-define-global
+   jmax-bibtex-hydra-key-chord
+   'jmax-bibtex-hydra/body))
+
+
+(when jmax-bibtex-hydra-key-binding
+  (global-set-key jmax-bibtex-hydra-key-binding 'jmax-bibtex-hydra/body))
+
+;; ** Hydra menu for new bibtex entries
+;; A hydra for adding new bibtex entries.
+(defhydra jmax-bibtex-new-entry (:color blue)
+  "New Bibtex entry:"
+  ("a" bibtex-Article "Article")
+  ("b" bibtex-Book "Book")
+  ("i" bibtex-InBook "In book")
+  ("l" bibtex-Booklet "Booklet")
+  ("P" bibtex-Proceedings "Proceedings")
+  ("p" bibtex-InProceedings "In proceedings")
+  ("m" bibtex-Misc "Misc.")
+  ("M" bibtex-Manual "Manual")
+  ("T" bibtex-PhdThesis "PhD Thesis")
+  ("t" bibtex-MastersThesis "MS Thesis")
+  ("R" bibtex-TechReport "Report")
+  ("u" bibtex-Unpublished "unpublished")
+  ("c" bibtex-InCollection "Article in collection")
+  ("q" nil "quit"))
+
+
+;; ** Hydra menu of functions to act on a bibtex file.
+(defhydra jmax-bibtex-file (:color blue)
+  "Bibtex file functions: "
+  ("v" bibtex-validate "Validate entries")
+  ("s" bibtex-sort-buffer "Sort entries")
+  ("r" bibtex-reformat "Reformat entries")
+  ("c" bibtex-count-entries "Count entries")
+  ("p" org-ref-build-full-bibliography "PDF bibliography"))
+
+
+;; * DEPRECATED bibtex menu
 (defvar jmax-bibtex-menu-funcs '()
- "Functions to run in doi menu. Each entry is a list of (key menu-name function).
-The function must take one argument, the doi.")
+ "Functions to run in doi menu.
+Each entry is a list of (key menu-name function).  The function
+must take one argument, the doi.  This is somewhat deprecated, as
+I prefer the hydra interfaces above.")
 
 (setq jmax-bibtex-menu-funcs
       '(("p" "df" jmax-bibtex-pdf)
@@ -439,7 +669,7 @@ The function must take one argument, the doi.")
 
 (defun jmax-bibtex ()
   "Menu command to run in a bibtex entry.
-Functions from `jmax-bibtex-menu-funcs'. They all rely on the
+Functions from `jmax-bibtex-menu-funcs'.  They all rely on the
 entry having a doi."
 
   (interactive)
@@ -464,6 +694,7 @@ entry having a doi."
 
 (defalias 'jb 'jmax-bibtex)
 
+;; * The end
 (provide 'jmax-bibtex)
 
 ;;; jmax-bibtex.el ends here
diff --git a/org-ref-test.el b/org-ref-test.el
new file mode 100644 (file)
index 0000000..1f1eec5
--- /dev/null
@@ -0,0 +1,5 @@
+(when (require 'undercover nil t)
+  (undercover "doi.el" (:exclude "*-test.el")))
+
+(ert-deftest plain-and-simple ()
+  (should t))
diff --git a/org-ref.bib b/org-ref.bib
new file mode 100644 (file)
index 0000000..eea27fb
--- /dev/null
@@ -0,0 +1,170 @@
+@book{Dominik201408,
+  keywords = {org-mode},
+  url = {http://amazon.com/o/ASIN/9881327709/},
+  isbn = 9789881327703,
+  year = 2014,
+  publisher = {Samurai Media Limited},
+  author = {Carsten Dominik},
+  title = {The Org Mode 8 Reference Manual - Organize your life with GNU
+                  Emacs},
+}
+@article{xu-2015-relat-between,
+  title =       {Relationships Between the Surface Electronic and Chemical
+                  Properties of Doped 4d and 5d Late Transition Metal Dioxides},
+  eid =                 104703,
+  url =
+                  "http://scitation.aip.org/content/aip/journal/jcp/142/10/10.1063/1.4914093",
+  doi =                 {10.1063/1.4914093},
+  year =        2015,
+  pages =       104703,
+  number =      10,
+  volume =      142,
+  journal =     "The Journal of Chemical Physics",
+  keywords =    {DESC0004031, early-career, orgmode},
+  author =      "Xu, Zhongnan and Kitchin, John R.",
+}
+
+@article{xu-2015-linear-respon,
+  title =       {A Linear Response {DFT}+{U} Study of Trends in the Oxygen
+                  Evolution Activity of Transition Metal Rutile Dioxides},
+  eprint =      { http://dx.doi.org/10.1021/jp511426q },
+  url =                 { http://dx.doi.org/10.1021/jp511426q },
+  doi =                 {10.1021/jp511426q},
+  year =        2015,
+  pages =       {4827-4833},
+  number =      9,
+  volume =      119,
+  journal =     {The Journal of Physical Chemistry C},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Xu, Zhongnan and Rossmeisl, Jan and Kitchin, John R.},
+}
+
+@article{boes-2015-suppor-infor,
+  title =       {Supporting Information: Estimating Bulk-Composition-Dependent
+                  \ce{H2} Adsorption Energies on \ce{Cu_{x}Pd_{1-x}} Alloy (111)
+                  Surfaces},
+  url =
+                  {http://pubs.acs.org/doi/suppl/10.1021/cs501585k/suppl_file/cs501585k_si_001.pdf},
+  doi =                 {10.1021/cs501585k},
+  year =        2015,
+  pages =       {1020-1026},
+  volume =      5,
+  journal =     {ACS Catalysis},
+  keywords =    {orgmode},
+  author =      {Jacob R. Boes and Gamze Gumuslu and James B. Miller and Andrew
+                  J. Gellman and John R. Kitchin},
+}
+
+@article{boes-2015-estim-bulk,
+  title =       {Estimating Bulk-Composition-Dependent \ce{H2} Adsorption
+                  Energies on \ce{Cu_{x}Pd_{1-x}} Alloy (111) Surfaces},
+  url =                 {http://dx.doi.org/10.1021/cs501585k},
+  doi =                 {10.1021/cs501585k},
+  year =        2015,
+  pages =       {1020-1026},
+  volume =      5,
+  keywords =    {orgmode},
+  journal =     {ACS Catalysis},
+  author =      {Jacob R. Boes and Gamze Gumuslu and James B. Miller and Andrew
+                  J. Gellman and John R. Kitchin},
+}
+
+@article{curnan-2014-effec-concen,
+  title =       {Effects of Concentration, Crystal Structure, Magnetism, and
+                  Electronic Structure Method on First-Principles Oxygen Vacancy
+                  Formation Energy Trends in Perovskites},
+  eprint =      { http://dx.doi.org/10.1021/jp507957n },
+  url =                 {http://dx.doi.org/10.1021/jp507957n},
+  doi =                 {10.1021/jp507957n},
+  year =        2014,
+  pages =       {28776-28790},
+  number =      49,
+  volume =      118,
+  journal =     {The Journal of Physical Chemistry C},
+  keywords =    {orgmode, },
+  author =      {Curnan, Matthew T. and Kitchin, John R.},
+}
+
+@article{miller-2014-simul-temper,
+  title =       {Simulating Temperature Programmed Desorption of Oxygen on
+                  {P}t(111) Using {DFT} Derived Coverage Dependent Desorption
+                  Barriers},
+  url =                 {http://dx.doi.org/10.1007/s11244-013-0166-3},
+  doi =                 {10.1007/s11244-013-0166-3},
+  year =        2014,
+  pages =       {106-117},
+  number =      {1-4},
+  volume =      57,
+  journal =     {Topics in Catalysis},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Spencer D. Miller and Vladimir V. Pushkarev and Andrew
+                  J. Gellman and John R. Kitchin},
+}
+
+@article{xu-2014-probin-cover,
+  title =       {Probing the Coverage Dependence of Site and Adsorbate
+                  Configurational Correlations on (111) Surfaces of Late
+                  Transition Metals},
+  url =                 {http://dx.doi.org/10.1021/jp508805h},
+  doi =                 {10.1021/jp508805h},
+  year =        2014,
+  pages =       {25597-25602},
+  number =      44,
+  volume =      118,
+  journal =     {J. Phys. Chem. C},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Zhongnan Xu and John R. Kitchin},
+}
+
+@article{xu-2014-relat-elect,
+  title =       {Relating the Electronic Structure and Reactivity of the 3d
+                  Transition Metal Monoxide Surfaces},
+  abstract =    "Abstract We performed a series of density functional theory
+                  calculations of dissociative oxygen adsorption on fcc metals
+                  and their corresponding rocksalt monoxides to elucidate the
+                  relationship between the oxide electronic structure and its
+                  corresponding reactivity. We decomposed the dissociative
+                  adsorption energy of oxygen on an oxide surface into a sum of
+                  the adsorption energy on the metal and a change in adsorption
+                  energy caused by both expanding and oxidizing the lattice. We
+                  were able to identify the key features of the electronic
+                  structure that explains the trends in adsorption energies on
+                  3d transition metal monoxide surfaces. ",
+  issn =        "1566-7367",
+  url =                 {http://dx.doi.org/10.1016/j.catcom.2013.10.028},
+  doi =                 {10.1016/j.catcom.2013.10.028},
+  year =        2014,
+  pages =       {60-64},
+  volume =      52,
+  journal =     {Catalysis Communications},
+  keywords =    {DESC0004031, early-career, orgmode, },
+  author =      {Zhongnan Xu and John R. Kitchin},
+}
+
+@article{mehta-2014-ident-poten,
+  title =       {Identifying Potential \ce{BO2} Oxide Polymorphs for Epitaxial
+                  Growth Candidates},
+  eprint =      {http://pubs.acs.org/doi/pdf/10.1021/am4059149},
+  url =                 {http://dx.doi.org/10.1021/am4059149},
+  doi =                 {10.1021/am4059149},
+  year =        2014,
+  pages =       {3630-3639},
+  number =      5,
+  volume =      6,
+  journal =     {ACS Appl. Mater. Interfaces},
+  keywords =    {orgmode, },
+  author =      {Prateek Mehta and Paul A. Salvador and John R. Kitchin},
+}
+
+@article{hallenbeck-2013-effec,
+  title =       {Effects of \ce{O_2} and \ce{SO_2} on the Capture Capacity of a
+                  Primary-Amine Based Polymeric \ce{CO_2} Sorbent},
+  eprint =      "http://pubs.acs.org/doi/pdf/10.1021/ie400582a",
+  url =                 "http://pubs.acs.org/doi/abs/10.1021/ie400582a",
+  doi =                 "10.1021/ie400582a",
+  year =        2013,
+  pages =       "10788-10794",
+  journal =     "Industrial \& Engineering Chemistry Research",
+  keywords =    {RUA, orgmode},
+  author =      "Hallenbeck, Alexander P. and Kitchin, John R.",
+}
diff --git a/org-ref.el b/org-ref.el
new file mode 100644 (file)
index 0000000..edc7adf
--- /dev/null
@@ -0,0 +1,3506 @@
+;;; org-ref.el --- cite and cross-reference in org-mode
+
+;; Copyright(C) 2014 John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; URL: https://github.com/jkitchin/org-ref
+;; Version: 0.2
+;; Keywords: org-mode, cite, ref, label
+;; Package-Requires: ((org) (dash) (helm) (helm-bibtex) (hydra))
+
+;; This file is not currently part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program ; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; Lisp code to setup bibliography cite, ref and label org-mode links.
+;; also sets up reftex and helm for org-mode citations.  The links are
+;; clickable and do things that are useful.  You should really read
+;; org-ref.org for details.
+;;
+
+;;; Code:
+
+(require 'reftex-cite)
+(require 'dash)
+(require 'helm)
+(require 'helm-config)
+(require 'helm-bibtex)
+(require 'org)
+(require 'org-element)
+
+;; * Custom variables
+(defgroup org-ref nil
+  "Customization group for org-ref.")
+
+(defcustom org-ref-bibliography-notes
+  nil
+  "Filename where you will put all your notes about an entry in the default bibliography."
+  :type 'file
+  :group 'org-ref)
+
+(defcustom org-ref-default-bibliography
+  nil
+  "List of bibtex files to search for.
+You should use full-paths for each file."
+  :type '(repeat :tag "List of bibtex files" file)
+  :group 'org-ref)
+
+(defcustom org-ref-pdf-directory
+  nil
+  "Directory where pdfs are stored by key.  put a trailing / in."
+  :type 'directory
+  :group 'org-ref)
+
+(defcustom org-ref-default-citation-link
+  "cite"
+  "The default type of citation link to use."
+  :type 'string
+  :group 'org-ref)
+
+(defcustom org-ref-insert-cite-key
+  "C-c ]"
+  "Keyboard shortcut to insert a citation."
+  :type 'string
+  :group 'org-ref)
+
+(defcustom org-ref-bibliography-entry-format
+  '(("article" . "%a, %t, <i>%j</i>, <b>%v(%n)</b>, %p (%y). <a href=\"%U\">link</a>. <a href=\"http://dx.doi.org/%D\">doi</a>.")
+
+    ("book" . "%a, %t, %u (%y).")
+    ("techreport" . "%a, %t, %i, %u (%y).")
+    ("proceedings" . "%e, %t in %S, %u (%y).")
+    ("inproceedings" . "%a, %t, %p, in %b, edited by %e, %u (%y)"))
+  "String to format an entry.  Just the reference, no numbering at the beginning, etc... see the `org-ref-reftex-format-citation' docstring for the escape codes."
+  :type 'string
+  :group 'org-ref)
+
+(defcustom org-ref-note-title-format
+  "** TODO %y - %t"
+  "String to format the title of a note. See the `org-ref-reftex-format-citation' docstring for the escape codes."
+  :type 'string
+  :group 'org-ref)
+
+(defcustom org-ref-open-notes-function
+  (lambda ()
+    (org-show-entry)
+    (show-branches)
+    (show-children)
+    (org-cycle '(64))
+    ;;(org-tree-to-indirect-buffer)
+    (outline-previous-visible-heading 1)
+    (recenter-top-bottom 0))
+  "User-defined way to open a notes entry.  This is excecuted after the entry is found, with the cursor at the beginning of the headline.  The default setting fully expands the notes, and moves the headline to the top of the buffer."
+:type 'function
+:group 'org-ref)
+
+
+(defcustom org-ref-open-pdf-function
+   'org-ref-open-pdf-at-point
+   "User-defined function to open a pdf from a link.  The
+function must get the key at point, and derive a path to the pdf
+file, then open it.  The default function is
+`org-ref-open-pdf-at-point'."
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-get-pdf-filename-function
+  'org-ref-get-pdf-filename
+  "User-defined function to get a filename from a bibtex key.
+The function must take a key as an argument, and return the path
+to the corresponding filename. The default is
+`org-ref-get-pdf-filename'. An alternative value is
+`org-ref-get-mendeley-filename'.")
+
+
+(defcustom org-ref-insert-cite-function
+  'org-ref-helm-insert-cite-link
+  "Function to call to insert citation links.  The default is `org-ref-helm-insert-cite-link' which uses `helm-bibtex'.  `org-ref' modifies `helm-bibtex' a little bit to give `org-mode' citations, and to reorder default actions.  You may use `org-ref-insert-cite-link' if you like the reftex interface."
+ :type 'function
+ :group 'org-ref)
+
+
+(defcustom org-ref-cite-onclick-function
+  'org-ref-cite-click-helm
+  "Function that runs when you click on a cite link.  The function must take no arguments.  You may also use `org-ref-cite-onclick-minibuffer-menu' if you do not like helm.  If you like `hydra', consider using `org-ref-cite-hydra'."
+ :type 'function
+ :group 'org-ref)
+
+
+(defcustom org-ref-show-citation-on-enter t
+  "If non-nil add a hook function to show the citation summary in the minibuffer."
+ :group 'org-ref)
+
+(defcustom org-ref-cite-types
+  '("cite" "nocite" ;; the default latex cite commands
+    ;; natbib cite commands, http://ctan.unixbrain.com/macros/latex/contrib/natbib/natnotes.pdf
+    "citet" "citet*" "citep" "citep*"
+    "citealt" "citealt*" "citealp" "citealp*"
+    "citenum" "citetext"
+    "citeauthor" "citeauthor*"
+    "citeyear" "citeyear*"
+    "Citet" "Citep" "Citealt" "Citealp" "Citeauthor"
+    ;; biblatex commands
+    ;; http://ctan.mirrorcatalogs.com/macros/latex/contrib/biblatex/doc/biblatex.pdf
+    "Cite"
+    "parencite" "Parencite"
+    "footcite" "footcitetext"
+    "textcite" "Textcite"
+    "smartcite" "Smartcite"
+    "cite*" "parencite*" "supercite"
+    "autocite" "Autocite" "autocite*" "Autocite*"
+    "Citeauthor*"
+    "citetitle" "citetitle*"
+    "citedate" "citedate*"
+    "citeurl"
+    "fullcite" "footfullcite"
+    ;; "volcite" "Volcite" cannot support the syntax
+    "notecite" "Notecite"
+    "pnotecite" "Pnotecite"
+    "fnotecite"
+    ;; multicites. Very limited support for these.
+    "cites" "Cites" "parencites" "Parencites"
+    "footcites" "footcitetexts"
+    "smartcites" "Smartcites" "textcites" "Textcites"
+    "supercites" "autocites" "Autocites"
+    ;; for the bibentry package
+    "bibentry"
+    )
+  "List of citation types known in `org-ref'."
+  :type '(repeat :tag "List of citation types" string)
+  :group 'org-ref)
+
+(defcustom org-ref-clean-bibtex-entry-hook nil
+  "Hook that is run in `org-ref-clean-bibtex-entry'.  The functions should take no arguments, and operate on the bibtex entry at point."
+  :group 'org-ref
+  :type 'hook)
+
+(defvar org-ref-bibliography-files
+  nil
+  "Variable to hold bibliography files to be searched.")
+
+;; * org-mode / reftex setup
+(require 'reftex)
+(defun org-mode-reftex-setup ()
+  "Setup `org-mode' and reftex for org-ref."
+    (and (buffer-file-name)
+         (file-exists-p (buffer-file-name))
+        (global-auto-revert-mode t))
+    (make-local-variable 'reftex-cite-format)
+    (setq reftex-cite-format 'org))
+
+;; define key for inserting citations
+(define-key org-mode-map
+  (kbd org-ref-insert-cite-key)
+  org-ref-insert-cite-function)
+
+(add-hook 'org-mode-hook 'org-mode-reftex-setup)
+
+(eval-after-load 'reftex-vars
+  '(progn
+      (add-to-list 'reftex-cite-format-builtin
+                   '(org "Org-mode citation"
+                         ((?\C-m . "cite:%l")     ; default
+                         (?d . ",%l")            ; for appending
+                         (?a . "autocite:%l")
+                         (?t . "citet:%l")
+                         (?T . "citet*:%l")
+                         (?p . "citep:%l")
+                         (?P . "citep*:%l")
+                         (?h . "citeauthor:%l")
+                         (?H . "citeauthor*:%l")
+                         (?y . "citeyear:%l")
+                         (?x . "citetext:%l")
+                         (?n . "nocite:%l")
+                         )))))
+
+;; * Messages for link at cursor
+(defvar org-ref-message-timer nil
+  "Variable to store the link message timer in.")
+
+
+(defun org-ref-show-link-messages ()
+  "Turn on link messages.
+You will see a message in the minibuffer when on a cite, ref or label link."
+  (interactive)
+  (or org-ref-message-timer
+      (setq org-ref-message-timer
+           (run-with-idle-timer 0.5 t 'org-ref-link-message))))
+
+
+(defun org-ref-cancel-link-messages ()
+  "Stop showing messages in minibuffer when on a link."
+  (interactive)
+  (cancel-timer org-ref-message-timer)
+  (setq org-ref-message-timer nil))
+
+
+(when org-ref-show-citation-on-enter
+  (org-ref-show-link-messages))
+
+;; ** Messages for context under mouse pointer
+
+(defvar org-ref-last-mouse-pos nil
+ "Stores last mouse position for use in `org-ref-mouse-message'.")
+
+(defun org-ref-can-move-p ()
+  "See if a character is under the mouse.  If so return the position for `goto-char'."
+  (let* ((line (cddr org-ref-last-mouse-pos))
+        (col  (cadr org-ref-last-mouse-pos)))
+    (save-excursion
+      (goto-char (window-start))
+      (forward-line line)
+      (if
+         (> (- (line-end-position) (line-beginning-position)) col)
+         (progn  (forward-char col) (point))
+       nil))))
+
+
+(defun org-ref-mouse-message ()
+  "Display message for link under mouse cursor."
+  (interactive)
+  (when (not (equal (mouse-position) org-ref-last-mouse-pos))
+    (setq org-ref-last-mouse-pos (mouse-position))
+    (let ((p (org-ref-can-move-p)))
+      (when p
+         (save-excursion
+           (goto-char p)
+           (org-ref-link-message))))))
+
+
+(defvar org-ref-message-timer-mouse nil
+  "Store mouse timer.")
+
+
+(defvar org-ref-mouse-message-interval 0.5
+  "How often to run the mouse message timer in seconds.")
+
+
+(defun org-ref-mouse-messages-on ()
+  "Turn on mouse messages."
+  (interactive)
+  (or org-ref-message-timer-mouse
+      (setq org-ref-message-timer-mouse
+           (run-at-time "0.5 sec"
+                        org-ref-mouse-message-interval
+                        'org-ref-mouse-message))))
+
+
+(defun org-ref-mouse-messages-off ()
+  "Turn off mouse messages."
+  (interactive)
+  (cancel-timer org-ref-message-timer-mouse)
+  (setq org-ref-message-timer-mouse nil)
+  (message "Mouse messages are off"))
+
+;; Colorizing org-ref links
+(defcustom org-ref-colorize-links
+  t
+  "When non-nil, change colors of links."
+  :group 'org-ref)
+
+
+(defcustom org-ref-cite-color
+  "forest green"
+  "Color of cite like links."
+  :group 'org-ref)
+
+
+(defcustom org-ref-ref-color
+  "dark red"
+  "Color of ref like links."
+  :group 'org-ref)
+
+
+(defcustom org-ref-label-color
+  "dark magenta"
+  "Color of label links."
+  :group 'org-ref)
+
+
+(defvar org-ref-cite-re nil
+ "Regexp for cite links.")
+
+
+(setq org-ref-cite-re
+      (concat "\\(" (mapconcat
+                    (lambda (x)
+                      (replace-regexp-in-string "\*" "\\\\*" x)
+                      )
+                    org-ref-cite-types "\\|") "\\)"
+  ":\\([a-zA-Z0-9-_:\\./]*,?\\)*"))
+
+
+(defvar org-ref-label-re
+  "label:\\([a-zA-Z0-9-_:]*,?\\)*")
+
+
+(defvar org-ref-ref-re
+  "\\(eq\\)?ref:\\([a-zA-Z0-9-_:]*,?\\)*")
+
+
+(defface org-ref-cite-face
+  `((t (:inherit org-link :foreground ,org-ref-cite-color)))
+  "Color for cite-like links in org-ref.")
+
+
+(defface org-ref-label-face
+  `((t (:inherit org-link :foreground ,org-ref-label-color)))
+  "Color for ref links in org-ref.")
+
+
+(defface org-ref-ref-face
+  `((t (:inherit org-link :foreground ,org-ref-ref-color)))
+  "Face for ref links in org-ref.")
+
+
+(defun org-ref-colorize-links ()
+  "Colorize org-ref links."
+  (hi-lock-mode 1)
+  (highlight-regexp org-ref-cite-re 'org-ref-cite-face)
+  (highlight-regexp org-ref-label-re 'org-ref-label-face)
+  (highlight-regexp org-ref-ref-re 'org-ref-ref-face))
+
+
+(when org-ref-colorize-links
+  (add-hook 'org-mode-hook 'org-ref-colorize-links))
+
+;; * General org-ref utilities
+(defun org-ref-strip-string (string)
+  "Strip leading and trailing whitespace from the STRING."
+  (replace-regexp-in-string
+   (concat search-whitespace-regexp "$" ) ""
+   (replace-regexp-in-string
+    (concat "^" search-whitespace-regexp ) "" string)))
+
+(defun org-ref-split-and-strip-string (string)
+  "Split key-string and strip keys in STRING.
+Assumes the key-string is comma delimited."
+  (mapcar 'org-ref-strip-string (split-string string ",")))
+
+(defun org-ref-reftex-get-bib-field (field entry &optional format)
+  "Similar to reftex-get-bib-field, but removes enclosing braces and quotes in FIELD in the bibtex ENTRY.
+Optional argument FORMAT bibtex format."
+  (let ((result))
+    (setq result (reftex-get-bib-field field entry format))
+    (when (and (not (string= result "")) (string= "{" (substring result 0 1)))
+      (setq result (substring result 1 -1)))
+    (when (and (not (string= result "")) (string= "\"" (substring result 0 1)))
+      (setq result (substring result 1 -1)))
+      result))
+
+(defun org-ref-reftex-format-citation (entry format)
+  "Return a formatted string for the bibtex ENTRY (from bibtex-parse-entry) according to the FORMAT argument.
+The format is a string with these percent escapes.
+
+In the format, the following percent escapes will be expanded.
+
+%l   The BibTeX label of the citation.
+%a   List of author names, see also `reftex-cite-punctuation'.
+%2a  Like %a, but abbreviate more than 2 authors like Jones et al.
+%A   First author name only.
+%e   Works like %a, but on list of editor names. (%2e and %E work a well)
+
+It is also possible to access all other BibTeX database fields:
+%b booktitle     %c chapter        %d edition    %h howpublished
+%i institution   %j journal        %k key        %m month
+%n number        %o organization   %p pages      %P first page
+%r address       %s school         %u publisher  %t title
+%v volume        %y year
+%B booktitle, abbreviated          %T title, abbreviated
+%U url
+%D doi
+%S series
+
+Usually, only %l is needed.  The other stuff is mainly for the echo area
+display, and for (setq reftex-comment-citations t).
+
+%< as a special operator kills punctuation and space around it after the
+string has been formatted.
+
+A pair of square brackets indicates an optional argument, and RefTeX
+will prompt for the values of these arguments.
+
+Beware that all this only works with BibTeX database files.  When
+citations are made from the \bibitems in an explicit thebibliography
+environment, only %l is available."
+  ;; Format a citation from the info in the BibTeX ENTRY
+  (unless (stringp format) (setq format "\\cite{%l}"))
+
+  (if (and reftex-comment-citations
+           (string-match "%l" reftex-cite-comment-format))
+      (error "Reftex-cite-comment-format contains invalid %%l"))
+
+  (while (string-match
+          "\\(\\`\\|[^%]\\)\\(\\(%\\([0-9]*\\)\\([a-zA-Z]\\)\\)[.,;: ]*\\)"
+          format)
+    (let ((n (string-to-number (match-string 4 format)))
+          (l (string-to-char (match-string 5 format)))
+          rpl b e)
+      (save-match-data
+        (setq rpl
+              (cond
+               ((= l ?l) (concat
+                          (org-ref-reftex-get-bib-field "&key" entry)
+                          (if reftex-comment-citations
+                              reftex-cite-comment-format
+                            "")))
+               ((= l ?a) (replace-regexp-in-string
+                          "\n\\|\t\\|\s+" " "
+                          (reftex-format-names
+                           (reftex-get-bib-names "author" entry)
+                           (or n 2))))
+               ((= l ?A) (replace-regexp-in-string
+                          "\n\\|\t\\|\s+" " "
+                          (car (reftex-get-bib-names "author" entry))))
+               ((= l ?b) (org-ref-reftex-get-bib-field "booktitle" entry "in: %s"))
+               ((= l ?B) (reftex-abbreviate-title
+                          (org-ref-reftex-get-bib-field "booktitle" entry "in: %s")))
+               ((= l ?c) (org-ref-reftex-get-bib-field "chapter" entry))
+               ((= l ?d) (org-ref-reftex-get-bib-field "edition" entry))
+               ((= l ?D) (org-ref-reftex-get-bib-field "doi" entry))
+               ((= l ?e) (reftex-format-names
+                          (reftex-get-bib-names "editor" entry)
+                          (or n 2)))
+               ((= l ?E) (car (reftex-get-bib-names "editor" entry)))
+               ((= l ?h) (org-ref-reftex-get-bib-field "howpublished" entry))
+               ((= l ?i) (org-ref-reftex-get-bib-field "institution" entry))
+               ((= l ?j) (let ((jt (reftex-get-bib-field "journal" entry)))
+                           (if (string= "" jt)
+                               (reftex-get-bib-field "journaltitle" entry)
+                             jt)))
+               ((= l ?k) (org-ref-reftex-get-bib-field "=key=" entry))
+               ((= l ?m) (org-ref-reftex-get-bib-field "month" entry))
+               ((= l ?n) (org-ref-reftex-get-bib-field "number" entry))
+               ((= l ?o) (org-ref-reftex-get-bib-field "organization" entry))
+               ((= l ?p) (org-ref-reftex-get-bib-field "pages" entry))
+               ((= l ?P) (car (split-string
+                               (org-ref-reftex-get-bib-field "pages" entry)
+                               "[- .]+")))
+               ((= l ?s) (org-ref-reftex-get-bib-field "school" entry))
+               ((= l ?S) (org-ref-reftex-get-bib-field "series" entry))
+               ((= l ?u) (org-ref-reftex-get-bib-field "publisher" entry))
+               ((= l ?U) (org-ref-reftex-get-bib-field "url" entry))
+               ((= l ?r) (org-ref-reftex-get-bib-field "address" entry))
+              ;; strip enclosing brackets from title if they are there
+               ((= l ?t) (replace-regexp-in-string
+                          "\n\\|\t\\|\s+" " "
+                          (org-ref-reftex-get-bib-field "title" entry)))
+               ((= l ?T) (reftex-abbreviate-title
+                          ((replace-regexp-in-string
+                            "\n\\|\t\\|\s+" " "
+                            (org-ref-reftex-get-bib-field "title" entry)))))
+               ((= l ?v) (org-ref-reftex-get-bib-field "volume" entry))
+               ((= l ?y) (org-ref-reftex-get-bib-field "year" entry)))))
+
+      (if (string= rpl "")
+          (setq b (match-beginning 2) e (match-end 2))
+        (setq b (match-beginning 3) e (match-end 3)))
+      (setq format (concat (substring format 0 b) rpl (substring format e)))))
+  (while (string-match "%%" format)
+    (setq format (replace-match "%" t t format)))
+  (while (string-match "[ ,.;:]*%<" format)
+    (setq format (replace-match "" t t format)))
+  format)
+
+(defun org-ref-get-bibtex-entry-citation (key)
+  "Return a string for the bibliography entry corresponding to KEY.
+Format according to the type in `org-ref-bibliography-entry-format'."
+
+  (let ((org-ref-bibliography-files (org-ref-find-bibliography))
+       (file) (entry) (bibtex-entry) (entry-type) (format))
+
+    (setq file (catch 'result
+                (cl-loop for file in org-ref-bibliography-files do
+                         (if (org-ref-key-in-file-p key (file-truename file))
+                             (throw 'result file)
+                           (message "%s not found in %s"
+                                    key (file-truename file))))))
+
+    (with-temp-buffer
+      (insert-file-contents file)
+      (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+      (bibtex-search-entry key nil 0)
+      (setq bibtex-entry (bibtex-parse-entry))
+      ;; downcase field names so they work in the format-citation code
+      (dolist (cons-cell bibtex-entry)
+       (setf (car cons-cell) (downcase (car cons-cell))))
+      (setq entry-type (downcase (cdr (assoc "=type=" bibtex-entry))))
+      (setq format (cdr (assoc entry-type org-ref-bibliography-entry-format)))
+      (if format
+         (setq entry  (org-ref-reftex-format-citation bibtex-entry format))
+       ;; if no format, we use the bibtex entry itself as a fallback
+       (save-restriction
+         (bibtex-narrow-to-entry)
+         (setq entry (buffer-string)))))
+    entry))
+
+(defun org-ref-get-bibtex-keys ()
+  "Return a list of unique keys in the buffer."
+  (let ((keys '()))
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (link)
+       (let ((plist (nth 1 link)))
+         (when (-contains? org-ref-cite-types (plist-get plist ':type))
+           (dolist
+               (key
+                (org-ref-split-and-strip-string (plist-get plist ':path)))
+             (when (not (-contains? keys key))
+               (setq keys (append keys (list key))))))))
+      ;; set with-affiliated to get keys in captions
+      nil nil nil t)
+    ;; Sort keys alphabetically
+    (setq keys (cl-sort keys 'string-lessp :key 'downcase))
+    keys))
+
+(defun org-ref-get-bibtex-entry-html (key)
+  "Return an html string for the bibliography entry corresponding to KEY."
+  (let ((output))
+    (setq output (org-ref-get-bibtex-entry-citation key))
+    ;; unescape the &
+    (setq output (replace-regexp-in-string "\\\\&" "&" output))
+    ;; hack to replace {} around text
+    (setq output (replace-regexp-in-string "{" "" output))
+    (setq output (replace-regexp-in-string "}" "" output))
+    ;; get rid of empty parens
+    (setq output (replace-regexp-in-string "()" "" output))
+    ;; get rid of empty link and doi
+    (setq output (replace-regexp-in-string " <a href=\"\">link</a>\\." "" output))
+    ;; change double dash to single dash
+    (setq output (replace-regexp-in-string "--" "-" output))
+    (setq output (replace-regexp-in-string " <a href=\"http://dx\\.doi\\.org/\">doi</a>\\." "" output))
+    (format "<li><a id=\"%s\">[%s] %s</a></li>"
+           key key output)))
+
+(defun org-ref-get-html-bibliography ()
+  "Create an html bibliography when there are keys."
+  (let ((keys (org-ref-get-bibtex-keys)))
+    (when keys
+      (concat "<h1>Bibliography</h1>
+<ul>"
+             (mapconcat (lambda (x) (org-ref-get-bibtex-entry-html x)) keys "\n")
+             "\n</ul>"))))
+
+(defun org-ref-get-bibtex-entry-org (key)
+  "Return an org string for the bibliography entry corresponding to KEY."
+  (let ((org-ref-bibliography-files (org-ref-find-bibliography))
+       (file) (entry) (bibtex-entry) (entry-type) (format))
+
+    (setq file (catch 'result
+                (cl-loop for file in org-ref-bibliography-files do
+                      (if (org-ref-key-in-file-p key (file-truename file))
+                          (throw 'result file)
+                        (message "%s not found in %s" key (file-truename file))))))
+
+    (with-temp-buffer
+      (insert-file-contents file)
+      (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+      (bibtex-search-entry key nil 0)
+      (setq entry (bibtex-parse-entry))
+      (format "** %s - %s
+  :PROPERTIES:
+  %s
+  :END:
+" (org-ref-reftex-get-bib-field "author" entry)
+(org-ref-reftex-get-bib-field "title" entry)
+(concat "   :CUSTOM_ID: " (org-ref-reftex-get-bib-field "=key=" entry) "\n"
+       (mapconcat (lambda (element) (format "   :%s: %s"
+                                            (upcase (car element))
+                                            (cdr element)))
+                  entry
+                  "\n"))))))
+
+(defun org-ref-get-org-bibliography ()
+  "Create an org bibliography when there are keys."
+  (let ((keys (org-ref-get-bibtex-keys)))
+    (when keys
+      (concat "* Bibliography
+"
+             (mapconcat (lambda (x) (org-ref-get-bibtex-entry-org x)) keys "\n")
+             "\n"))))
+
+(defun org-ref-get-bibtex-entry-ascii (key)
+  "Return an ascii string for the bibliography entry corresponding to KEY."
+
+  (format "[%s] %s" key (org-ref-get-bibtex-entry-citation key)))
+
+(defun org-ref-get-ascii-bibliography ()
+  "Create an html bibliography when there are keys."
+  (let ((keys (org-ref-get-bibtex-keys)))
+    (when keys
+      (concat
+"Bibliography
+=============
+"
+             (mapconcat (lambda (x) (org-ref-get-bibtex-entry-ascii x)) keys "\n")
+             "\n"))))
+
+;; * Links
+;; ** bibliography and bibliographystyle
+(org-add-link-type "bibliography"
+                  ;; this code is run on clicking. The bibliography
+                  ;; may contain multiple files. this code finds the
+                  ;; one you clicked on and opens it.
+                  (lambda (link-string)
+                      ;; get link-string boundaries we have to go to the
+                      ;; beginning of the line, and then search forward
+                    (let* ((bibfile)
+                           ;; object is the link you clicked on
+                           (object (org-element-context))
+                           (link-string-beginning)
+                           (link-string-end)
+                           (cp (point)))
+                    (save-excursion
+                      (goto-char (org-element-property :begin object))
+                      (search-forward link-string nil nil 1)
+                      (setq link-string-beginning (match-beginning 0))
+                      (setq link-string-end (match-end 0)))
+
+                    ;; Make sure point is in the link-path.
+                    (if (< cp link-string-beginning)
+                        (goto-char link-string-beginning))
+                    ;; We set the reftex-default-bibliography
+                    ;; here. it should be a local variable only in
+                    ;; the current buffer. We need this for using
+                    ;; reftex to do citations.
+                    (set (make-local-variable 'reftex-default-bibliography)
+                         (split-string
+                          (org-element-property :path object) ","))
+
+                    (let (key-beginning key-end)
+                      ;; now if we have comma separated bibliographies
+                      ;; we find the one clicked on. we want to
+                      ;; search forward to next comma from point
+                      (save-excursion
+                        (if (search-forward "," link-string-end 1 1)
+                            ;; we found a match
+                            (setq key-end (- (match-end 0) 1))
+                          ;; no comma found so take the point
+                          (setq key-end (point))))
+                      ;; and backward to previous comma from point
+                      (save-excursion
+                        (if (search-backward "," link-string-beginning 1 1)
+                            ;; we found a match
+                            (setq key-beginning (+ (match-beginning 0) 1))
+                          (setq key-beginning (point)))) ; no match found
+                      ;; save the key we clicked on.
+                      (setq bibfile (org-ref-strip-string
+                                     (buffer-substring key-beginning key-end)))
+                      ;; open file on click
+                      (find-file bibfile))))
+
+                  ;; formatting code
+                  (lambda (keyword desc format)
+                    (cond
+                     ((eq format 'org) (org-ref-get-org-bibliography))
+                      ((eq format 'ascii) (org-ref-get-ascii-bibliography))
+                     ((eq format 'html) (org-ref-get-html-bibliography))
+                     ((eq format 'latex)
+                      ;; write out the latex bibliography command
+                      (format "\\bibliography{%s}"
+                              (replace-regexp-in-string
+                               "\\.bib" ""
+                               (mapconcat
+                                'identity
+                                (mapcar 'expand-file-name
+                                        (split-string keyword ","))
+                                ",")))))))
+
+(org-add-link-type "nobibliography"
+                  ;; this code is run on clicking. The bibliography
+                  ;; may contain multiple files. this code finds the
+                  ;; one you clicked on and opens it.
+                  (lambda (link-string)
+                      ;; get link-string boundaries
+                      ;; we have to go to the beginning of the line, and then search forward
+
+                    (let* ((bibfile)
+                           ;; object is the link you clicked on
+                           (object (org-element-context))
+
+                           (link-string-beginning)
+                           (link-string-end))
+
+                    (save-excursion
+                      (goto-char (org-element-property :begin object))
+                      (search-forward link-string nil nil 1)
+                      (setq link-string-beginning (match-beginning 0))
+                      (setq link-string-end (match-end 0)))
+
+                      ;; We set the reftex-default-bibliography
+                      ;; here. it should be a local variable only in
+                      ;; the current buffer. We need this for using
+                      ;; reftex to do citations.
+                      (set (make-local-variable 'reftex-default-bibliography)
+                           (split-string (org-element-property :path object) ","))
+
+                      (let (key-beginning key-end)
+                        ;; now if we have comma separated bibliographies
+                        ;; we find the one clicked on. we want to
+                        ;; search forward to next comma from point
+                        (save-excursion
+                          (if (search-forward "," link-string-end 1 1)
+                              (setq key-end (- (match-end 0) 1)) ; we found a match
+                            (setq key-end (point)))) ; no comma found so take the point
+                        ;; and backward to previous comma from point
+                        (save-excursion
+                          (if (search-backward "," link-string-beginning 1 1)
+                              (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
+                            (setq key-beginning (point)))) ; no match found
+                        ;; save the key we clicked on.
+                        (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
+                        (find-file bibfile)))) ; open file on click
+
+                    ;; formatting code
+                  (lambda (keyword desc format)
+                    (cond
+                     ((eq format 'org) (org-ref-get-org-bibliography))
+                      ((eq format 'ascii) (org-ref-get-ascii-bibliography))
+                     ((eq format 'html) (org-ref-get-html-bibliography))
+                     ((eq format 'latex)
+                      ;; write out the latex bibliography command
+                      (format "\\nobibliography{%s}"
+                              (replace-regexp-in-string  "\\.bib" "" (mapconcat 'identity
+                                                                                (mapcar 'expand-file-name
+                                                                                        (split-string keyword ","))
+                                                                                ",")))))))
+
+(org-add-link-type "printbibliography"
+                  (lambda (arg) (message "Nothing implemented for clicking here."))
+                  (lambda (keyword desc format)
+                    (cond
+                      ((eq format 'org) (org-ref-get-org-bibliography))
+                      ((eq format 'html) (org-ref-get-html-bibliography))
+                     ((eq format 'latex)
+                      ;; write out the biblatex bibliography command
+                      "\\printbibliography"))))
+
+(org-add-link-type "bibliographystyle"
+                  (lambda (arg) (message "Nothing implemented for clicking here."))
+                  (lambda (keyword desc format)
+                    (cond
+                     ((eq format 'latex)
+                      ;; write out the latex bibliography command
+                      (format "\\bibliographystyle{%s}" keyword))
+                     ;; Other styles should not have an output for this
+                     (t
+                      ""))))
+
+
+(defun org-bibliographystyle-complete-link (&optional arg)
+  "Completion function for bibliographystyle link.
+ARG does nothing."
+  (format "bibliographystyle:%s" (ido-completing-read
+                                 "style: "
+                                 '("unsrt" "plain" "alpha"
+                                   ;; natbib
+                                   ;; https://www.sharelatex.com/learn/Natbib_bibliography_styles
+                                   "dinat" "humannat" "plainnat"
+                                   "abbrnat" "unsrtnat" "rusnat"
+                                   "ksfhnat"))))
+
+
+(defun org-bibliography-complete-link (&optional arg)
+  "Completion function for bibliography link.
+ARG does nothing."
+  (format "bibliography:%s" (read-file-name "enter file: " nil nil t)))
+
+
+(defun org-ref-insert-bibliography-link ()
+  "Insert a bibliography with completion."
+  (interactive)
+  (insert (org-bibliography-complete-link)))
+
+;; ** addbibresource
+
+(org-add-link-type "addbibresource"
+                  ;; this code is run on clicking. The addbibresource
+                  ;; may contain multiple files. this code finds the
+                  ;; one you clicked on and opens it.
+                  (lambda (link-string)
+                      ;; get link-string boundaries
+                      ;; we have to go to the beginning of the line, and then search forward
+
+                    (let* ((bibfile)
+                           ;; object is the link you clicked on
+                           (object (org-element-context))
+
+                           (link-string-beginning)
+                           (link-string-end))
+
+                    (save-excursion
+                      (goto-char (org-element-property :begin object))
+                      (search-forward link-string nil nil 1)
+                      (setq link-string-beginning (match-beginning 0))
+                      (setq link-string-end (match-end 0)))
+
+                      ;; We set the reftex-default-addbibresource
+                      ;; here. it should be a local variable only in
+                      ;; the current buffer. We need this for using
+                      ;; reftex to do citations.
+                      (set (make-local-variable 'reftex-default-addbibresource)
+                           (split-string (org-element-property :path object) ","))
+
+                      (let (key-beginning key-end)
+                        ;; now if we have comma separated bibliographies
+                        ;; we find the one clicked on. we want to
+                        ;; search forward to next comma from point
+                        (save-excursion
+                          (if (search-forward "," link-string-end 1 1)
+                              (setq key-end (- (match-end 0) 1)) ; we found a match
+                            (setq key-end (point)))) ; no comma found so take the point
+                        ;; and backward to previous comma from point
+                        (save-excursion
+                          (if (search-backward "," link-string-beginning 1 1)
+                              (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
+                            (setq key-beginning (point)))) ; no match found
+                        ;; save the key we clicked on.
+                        (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
+                        (find-file bibfile)))) ; open file on click
+
+                    ;; formatting code
+                  (lambda (keyword desc format)
+                    (cond
+                     ((eq format 'html) (format "")); no output for html
+                     ((eq format 'latex)
+                        ;; write out the latex addbibresource command
+                      (format "\\addbibresource{%s}" keyword)))))
+
+;; ** List of figures
+(defun org-ref-list-of-figures (&optional arg)
+  "Generate buffer with list of figures in them.
+ARG does nothing."
+  (interactive)
+  (save-excursion (widen)
+  (let* ((c-b (buffer-name))
+        (counter 0)
+        (list-of-figures
+         (org-element-map (org-element-parse-buffer) 'link
+           (lambda (link)
+             "create a link for to the figure"
+             (when
+                 (and (string= (org-element-property :type link) "file")
+                      (string-match-p
+                       "[^.]*\\.\\(png\\|jpg\\|eps\\|pdf\\)$"
+                       (org-element-property :path link)))
+               (cl-incf counter)
+
+               (let* ((start (org-element-property :begin link))
+                      (parent (car (cdr (org-element-property :parent link))))
+                      (caption (cl-caaar (plist-get parent :caption)))
+                      (name (plist-get parent :name)))
+                 (if caption
+                     (format
+                      "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]] %s\n"
+                      c-b start counter (or name "") caption)
+                   (format
+                    "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]]\n"
+                    c-b start counter (or name "")))))))))
+    (switch-to-buffer "*List of Figures*")
+    (setq buffer-read-only nil)
+    (org-mode)
+    (erase-buffer)
+    (insert (mapconcat 'identity list-of-figures ""))
+    (setq buffer-read-only t)
+    (use-local-map (copy-keymap org-mode-map))
+    (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
+
+(org-add-link-type
+ "list-of-figures"
+ 'org-ref-list-of-figures ; on click
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\listoffigures")))))
+
+;; ** List of tables
+(defun org-ref-list-of-tables (&optional arg)
+  "Generate a buffer with a list of tables.
+ARG does nothing."
+  (interactive)
+  (save-excursion
+  (widen)
+  (let* ((c-b (buffer-name))
+        (counter 0)
+        (list-of-tables
+         (org-element-map (org-element-parse-buffer 'element) 'table
+           (lambda (table)
+             "create a link for to the table"
+             (cl-incf counter)
+             (let ((start (org-element-property :begin table))
+                   (name  (org-element-property :name table))
+                   (caption (cl-caaar (org-element-property :caption table))))
+               (if caption
+                   (format
+                    "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]] %s\n"
+                    c-b start counter (or name "") caption)
+                 (format
+                  "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]]\n"
+                  c-b start counter (or name ""))))))))
+    (switch-to-buffer "*List of Tables*")
+    (setq buffer-read-only nil)
+    (org-mode)
+    (erase-buffer)
+    (insert (mapconcat 'identity list-of-tables ""))
+    (setq buffer-read-only t)
+    (use-local-map (copy-keymap org-mode-map))
+    (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
+
+(org-add-link-type
+ "list-of-tables"
+ 'org-ref-list-of-tables
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\listoftables")))))
+
+
+;; ** label link
+(defun org-ref-count-labels (label)
+  "Counts number of matches for LABEL in the document."
+  (+ (count-matches (format "label:%s\\b[^-:]" label) (point-min) (point-max))
+     ;; for tblname, it is not enough to get word boundary
+     ;; tab-little and tab-little-2 match then.
+     (count-matches (format "^#\\+tblname:\\s-*%s\\b[^-:]" label) (point-min) (point-max))
+     (count-matches (format "\\label{%s}" label) (point-min) (point-max))
+     ;; this is the org-format #+label:
+     (count-matches (format "^#\\+label:\\s-*%s\\b[^-:]" label) (point-min) (point-max))
+     (let ((custom-id-count 0))
+       (org-map-entries
+       (lambda ()
+         (when (string= label (org-entry-get (point) "CUSTOM_ID"))
+           (setq custom-id-count (+ 1 custom-id-count)))))
+       custom-id-count)))
+
+(org-add-link-type
+ "label"
+ (lambda (label)
+   "on clicking count the number of label tags used in the buffer. A number greater than one means multiple labels!"
+   (let ((count (org-ref-count-labels label)))
+   (message (format "%s occurence%s"
+                   count
+                   (if (or (= count 0)
+                             (> count 1))
+                       "s"
+                     ""))
+                   (org-ref-count-labels label))))
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'html) (format "<div id=\"%s\">" keyword))
+    ((eq format 'latex)
+     (format "\\label{%s}" keyword)))))
+
+(defun org-label-store-link ()
+  "Store a link to a label.  The output will be a ref to that label."
+  ;; First we have to make sure we are on a label link.
+  (let* ((object (org-element-context)))
+    (when (and (equal (org-element-type object) 'link)
+               (equal (org-element-property :type object) "label"))
+      (org-store-link-props
+       :type "ref"
+       :link (concat "ref:" (org-element-property :path object))))
+
+    ;; Store link on table
+    (when (equal (org-element-type object) 'table)
+      (org-store-link-props
+       :type "ref"
+       :link (concat "ref:" (org-element-property :name object))))
+
+    ;; store link on heading with custom_id
+    ;; this is not a ref link, but it is still what you want
+    (when (and (equal (org-element-type object) 'headline)
+              (org-entry-get (point) "CUSTOM_ID"))
+      (org-store-link-props
+       :type "custom_id"
+       :link (format "[[#%s]]" (org-entry-get (point) "CUSTOM_ID"))))
+
+    ;; and to #+label: lines
+
+    (when (and (equal (org-element-type object) 'paragraph)
+              (org-element-property :name object))
+      (org-store-link-props
+       :type "ref"
+       :link (concat "ref:" (org-element-property :name object))))))
+
+(add-hook 'org-store-link-functions 'org-label-store-link)
+
+;; ** ref link
+(org-add-link-type
+ "ref"
+ (lambda (label)
+   "on clicking goto the label. Navigate back with C-c &"
+   (org-mark-ring-push)
+   ;; next search from beginning of the buffer
+   ;; it is possible you would not find the label if narrowing is in effect
+   (widen)
+   (unless
+       (or
+       ;; our label links
+       (progn
+         (goto-char (point-min))
+         (re-search-forward (format "label:%s\\b" label) nil t))
+
+       ;; a latex label
+       (progn
+         (goto-char (point-min))
+         (re-search-forward (format "\\label{%s}" label) nil t))
+
+       ;; #+label: name  org-definition
+       (progn
+         (goto-char (point-min))
+         (re-search-forward
+          (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
+
+       ;; org tblname
+       (progn
+         (goto-char (point-min))
+         (re-search-forward
+          (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t)))
+
+     ;; we did not find anything, so go back to where we came
+     (org-mark-ring-goto)
+     (error "%s not found" label))
+   (org-show-entry)
+   (message "go back with (org-mark-ring-goto) `C-c &`"))
+ ;formatting
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'html) (format "<a href=\"#%s\">%s</a>" keyword keyword))
+    ((eq format 'latex)
+     (format "\\ref{%s}" keyword)))))
+
+
+(defun org-ref-get-org-labels ()
+ "Return a list of #+LABEL: labels."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((matches '()))
+      (while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" (point-max) t)
+       ;; do not do this for tables. We get those in `org-ref-get-tblnames'.
+       ;; who would have thought you have save match data here? Trust me. When
+       ;; I wrote this, you did.
+       (unless (save-match-data  (equal (car (org-element-at-point)) 'table))
+         (add-to-list 'matches (match-string-no-properties 1) t)))
+      matches)))
+
+
+(defun org-ref-get-custom-ids ()
+ "Return a list of custom_id properties in the buffer."
+ (let ((results '()) custom_id)
+   (org-map-entries
+    (lambda ()
+      (let ((custom_id (org-entry-get (point) "CUSTOM_ID")))
+       (when (not (null custom_id))
+         (setq results (append results (list custom_id)))))))
+   results))
+
+
+(defun org-ref-get-latex-labels ()
+  "Return list of matchin LaTeX defined labels in buffer."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((matches '()))
+      (while (re-search-forward "\\\\label{\\([a-zA-z0-9:-]*\\)}" (point-max) t)
+       (add-to-list 'matches (match-string-no-properties 1) t))
+      matches)))
+
+
+(defun org-ref-get-tblnames ()
+  "Return list of table names in the buffer."
+  (org-element-map (org-element-parse-buffer 'element) 'table
+    (lambda (table)
+      (org-element-property :name table))))
+
+
+(defun org-ref-get-labels ()
+  "Return a list of labels in the buffer that you can make a ref link to.
+This is used to complete ref links and in helm menus."
+  (save-excursion
+    (save-restriction
+      (widen)
+      (goto-char (point-min))
+      (let ((matches '()))
+        ;; these are the org-ref label:stuff  kinds
+       (while (re-search-forward
+               "[^#+]label:\\([a-zA-z0-9:-]*\\)" (point-max) t)
+         (add-to-list 'matches (match-string-no-properties 1) t))
+       ;; now add all the other kinds of labels.
+       (append matches
+               ;; #+label:
+               (org-ref-get-org-labels)
+               ;; \label{}
+               (org-ref-get-latex-labels)
+               ;; #+tblname: and actually #+label
+               (org-ref-get-tblnames)
+               ;; CUSTOM_IDs
+               (org-ref-get-custom-ids))))))
+
+
+(defun org-ref-helm-insert-label-link ()
+  "Insert a label link. helm just shows you what labels already exist.
+If you are on a label link, replace it."
+  (interactive)
+  (let* ((labels (org-ref-get-labels))
+        (cb (current-buffer)))
+    (helm :sources `(((name . "Existing labels")
+                     (candidates . ,labels)
+                     ;; default action is to open to the label
+                     (action . (lambda (label)
+                                 ;; unfortunately I do not have markers here
+                                 (org-open-link-from-string
+                                  (format "ref:%s" label))))
+                     ;; if you select a label, replace current one
+                     (action . (lambda (label)
+                                 (switch-to-buffer ,cb)
+                                 (cond
+                                  ;;  no prefix or on a link
+                                  ((equal helm-current-prefix-arg nil)
+                                   (let* ((object (org-element-context))
+                                          (last-char (save-excursion
+                                                       (goto-char (org-element-property :end object))
+                                                       (backward-char)
+                                                       (if (looking-at " ")
+                                                           " "
+                                                         ""))))
+                                     (when (-contains? '("label")
+                                                       (org-element-property :type object))
+                                         ;; we are on a link, so replace it.
+                                       (setf
+                                          (buffer-substring
+                                           (org-element-property :begin object)
+                                           (org-element-property :end object))
+                                          (concat
+                                           (replace-regexp-in-string
+                                            (org-element-property :path object)
+                                            label
+                                            (org-element-property :raw-link object))
+                                           last-char)))))
+                                  ;; no prefix options defined
+                                  ))))
+                    ;; no matching selection creates a new label
+                    ((name . "Create new label")
+                     (dummy)
+                     ;; default action creates a new label, or replaces old one
+                     (action .  (lambda (label)
+                                  (switch-to-buffer ,cb)
+                                  (let* ((object (org-element-context))
+                                         (last-char (save-excursion
+                                                      (goto-char (org-element-property :end object))
+                                                      (backward-char)
+                                                      (if (looking-at " ")
+                                                          " "
+                                                        ""))))
+                                    (if (-contains? '("label")
+                                                    (org-element-property :type object))
+                                        ;; we are on a link, so replace it.
+                                        (setf
+                                         (buffer-substring
+                                          (org-element-property :begin object)
+                                          (org-element-property :end object))
+                                         (concat
+                                          (replace-regexp-in-string
+                                           (org-element-property :path object)
+                                           helm-pattern
+                                           (org-element-property :raw-link object))
+                                          last-char))
+                                      ;; new link
+                                      (insert
+                                       (concat
+                                        "label:"
+                                        (or label
+                                            helm-pattern))))))))))))
+
+
+(defun org-ref-complete-link (&optional arg)
+  "Completion function for ref links.
+Optional argument ARG Does nothing."
+  (let ((label))
+    (setq label (completing-read "label: " (org-ref-get-labels)))
+    (format "ref:%s" label)))
+
+
+(defun org-ref-insert-ref-link ()
+  "Completion function for a ref link."
+ (interactive)
+ (insert (org-ref-complete-link)))
+
+
+(defun org-ref-helm-insert-ref-link ()
+  "Helm menu to insert ref links to labels in the document.
+If you are on link, replace with newly selected label.
+Use C-u to insert a different kind of ref link.
+Use C-u C-u to insert a [[#custom-id]] link"
+  (interactive)
+  (let* ((labels (org-ref-get-labels))
+        (bs (buffer-string))
+        (contexts (with-temp-buffer
+                    (insert bs)
+                    (mapcar 'org-ref-get-label-context labels)))
+        (cb (current-buffer)))
+
+    (helm :input (thing-at-point 'word)
+         :sources `(((name . "Available labels to ref")
+                     (candidates . ,(cl-loop for label in labels
+                                             for context in contexts
+                                             ;; we do some kludgy adding spaces
+                                             ;; and bars to make it "easier" to
+                                             ;; see in helm.
+                                             collect (cons (concat
+                                                            label "\n"
+                                                            (mapconcat
+                                                             (lambda (x)
+                                                               (concat "   |" x))
+                                                             (split-string context "\n")
+                                                             "\n"
+                                                             ) "\n\n") label)))
+                     ;; default action to replace or insert ref link.
+                     (action . (lambda (label)
+                                 (switch-to-buffer ,cb)
+
+                                 (cond
+                                  ;;  no prefix or on a link
+                                  ((equal helm-current-prefix-arg nil)
+                                   (let* ((object (org-element-context))
+                                          (last-char (save-excursion
+                                                       (goto-char (org-element-property :end object))
+                                                       (backward-char)
+                                                       (if (looking-at " ")
+                                                           " "
+                                                         ""))))
+                                     (if (-contains? '("ref" "eqref" "pageref" "nameref")
+                                                     (org-element-property :type object))
+                                         ;; we are on a link, so replace it.
+                                         (setf
+                                          (buffer-substring
+                                           (org-element-property :begin object)
+                                           (org-element-property :end object))
+                                          (concat
+                                           (replace-regexp-in-string
+                                            (org-element-property :path object)
+                                            label
+                                            (org-element-property :raw-link object))
+                                           last-char))
+                                       ;; insert a new link
+                                       (insert
+                                        (concat
+                                         "ref:" label))
+                                       )))
+                                  ;; one prefix, alternate ref link
+                                  ((equal helm-current-prefix-arg '(4))
+                                   (insert
+                                    (concat
+                                     (helm :sources '((name . "Ref link types")
+                                                      (candidates . ("ref" "eqref" "pageref" "nameref"))
+                                                      (action . (lambda (x) x))))
+                                     ":" label)))
+                                  ;; two prefixes, insert section custom-id link
+                                  ((equal helm-current-prefix-arg '(16))
+                                   (insert
+                                    (format "[[#%s]]" label)))
+                                  ))
+                             ))))))
+
+;; *** pageref link
+(org-add-link-type
+ "pageref"
+ (lambda (label)
+   "on clicking goto the label. Navigate back with C-c &"
+   (org-mark-ring-push)
+   ;; next search from beginning of the buffer
+   (widen)
+   (unless
+       (or
+       ;; our label links
+       (progn
+         (goto-char (point-min))
+         (re-search-forward (format "label:%s\\b" label) nil t))
+
+       ;; a latex label
+       (progn
+         (goto-char (point-min))
+         (re-search-forward (format "\\label{%s}" label) nil t))
+
+       ;; #+label: name  org-definition
+       (progn
+         (goto-char (point-min))
+         (re-search-forward
+          (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
+
+       ;; org tblname
+       (progn
+         (goto-char (point-min))
+         (re-search-forward
+          (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t)))
+     ;; we did not find anything, so go back to where we came
+     (org-mark-ring-goto)
+     (error "%s not found" label))
+   (message "go back with (org-mark-ring-goto) `C-c &`"))
+ ;formatting
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'html) (format "(<pageref>%s</pageref>)" path))
+    ((eq format 'latex)
+     (format "\\pageref{%s}" keyword)))))
+
+
+(defun org-pageref-complete-link (&optional arg)
+  "Completion function for ref links.
+Optional argument ARG Does nothing."
+  (let ((label))
+    (setq label (completing-read "label: " (org-ref-get-labels)))
+    (format "ref:%s" label)))
+
+
+(defun org-pageref-insert-ref-link ()
+  "Insert a pageref link with completion."
+ (interactive)
+ (insert (org-pageref-complete-link)))
+
+
+;; *** nameref link
+(org-add-link-type
+ "nameref"
+ (lambda (label)
+   "on clicking goto the label. Navigate back with C-c &"
+   (org-mark-ring-push)
+   ;; next search from beginning of the buffer
+   (widen)
+   (unless
+       (or
+       ;; a latex label
+       (progn
+         (goto-char (point-min))
+         (re-search-forward (format "\\label{%s}" label) nil t))
+       )
+     ;; we did not find anything, so go back to where we came
+     (org-mark-ring-goto)
+     (error "%s not found" label))
+   (message "go back with (org-mark-ring-goto) `C-c &`"))
+ ;formatting
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'html) (format "(<nameref>%s</nameref>)" path))
+    ((eq format 'latex)
+     (format "\\nameref{%s}" keyword)))))
+
+;; *** eqref link
+
+(org-add-link-type
+ "eqref"
+ (lambda (label)
+   "on clicking goto the label. Navigate back with C-c &"
+   (org-mark-ring-push)
+   ;; next search from beginning of the buffer
+   (widen)
+   (goto-char (point-min))
+   (unless
+       (or
+       ;; search forward for the first match
+       ;; our label links
+       (re-search-forward (format "label:%s" label) nil t)
+       ;; a latex label
+       (re-search-forward (format "\\label{%s}" label) nil t)
+       ;; #+label: name  org-definition
+       (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
+     (org-mark-ring-goto)
+     (error "%s not found" label))
+   (message "go back with (org-mark-ring-goto) `C-c &`"))
+ ;formatting
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'latex) (format "\\eqref{%s}" keyword))
+    ;;considering the fact that latex's the standard of math formulas, just use mathjax to render the html
+    ;;customize the variable 'org-html-mathjax-template' and 'org-html-mathjax-options' refering to  'autonumber'
+    ((eq format 'html) (format "\\eqref{%s}" keyword)))))
+
+;; ** cite link
+
+(defun org-ref-get-bibtex-key-under-cursor ()
+  "Return key under the bibtex cursor.
+We search forward from
+point to get a comma, or the end of the link, and then backwards
+to get a comma, or the beginning of the link.  that delimits the
+keyword we clicked on.  We also strip the text properties."
+  (let* ((object (org-element-context))
+        (link-string (org-element-property :path object)))
+    ;; you may click on the part before the citations. here we make
+    ;; sure to move to the beginning so you get the first citation.
+    (let ((cp (point)))
+      (goto-char (org-element-property :begin object))
+      (search-forward link-string (org-element-property :end object))
+      (goto-char (match-beginning 0))
+      ;; check if we clicked before the path and move as needed.
+      (unless (< cp (point))
+       (goto-char cp)))
+
+    (if (not (org-element-property :contents-begin object))
+       ;; this means no description in the link
+       (progn
+         ;; we need the link path start and end
+         (let (link-string-beginning link-string-end)
+           (save-excursion
+             (goto-char (org-element-property :begin object))
+             (search-forward link-string nil nil 1)
+             (setq link-string-beginning (match-beginning 0))
+             (setq link-string-end (match-end 0)))
+
+           (let (key-beginning key-end)
+             ;; The key is the text between commas, or the link boundaries
+             (save-excursion
+               (if (search-forward "," link-string-end t 1)
+                   (setq key-end (- (match-end 0) 1)) ; we found a match
+                 (setq key-end link-string-end))) ; no comma found so take the end
+             ;; and backward to previous comma from point which defines the start character
+             (save-excursion
+               (if (search-backward "," link-string-beginning 1 1)
+                   (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
+                 (setq key-beginning link-string-beginning))) ; no match found
+             ;; save the key we clicked on.
+             (let ((bibtex-key
+                    (org-ref-strip-string
+                     (buffer-substring key-beginning key-end))))
+               (set-text-properties 0 (length bibtex-key) nil bibtex-key)
+               bibtex-key))))
+      ;; link with description. assume only one key
+      link-string)))
+
+(defun org-ref-find-bibliography ()
+  "Find the bibliography in the buffer.
+This function sets and returns cite-bibliography-files, which is a list of files
+either from bibliography:f1.bib,f2.bib
+\bibliography{f1,f2}
+internal bibliographies
+
+falling back to what the user has set in `org-ref-default-bibliography'"
+  (catch 'result
+    (save-excursion
+      (goto-char (point-min))
+      ;;  look for a bibliography link
+      (when (re-search-forward "\\<bibliography:\\([^\]\|\n]+\\)" nil t)
+       (setq org-ref-bibliography-files
+             (mapcar 'org-ref-strip-string (split-string (match-string 1) ",")))
+       (throw 'result org-ref-bibliography-files))
+
+
+      ;; we did not find a bibliography link. now look for \bibliography
+      (goto-char (point-min))
+      (when (re-search-forward "\\\\bibliography{\\([^}]+\\)}" nil t)
+       ;; split, and add .bib to each file
+       (setq org-ref-bibliography-files
+             (mapcar (lambda (x) (concat x ".bib"))
+                     (mapcar 'org-ref-strip-string
+                             (split-string (match-string 1) ","))))
+       (throw 'result org-ref-bibliography-files))
+
+      ;; no bibliography found. maybe we need a biblatex addbibresource
+      (goto-char (point-min))
+      ;;  look for a bibliography link
+      (when (re-search-forward "addbibresource:\\([^\]\|\n]+\\)" nil t)
+       (setq org-ref-bibliography-files
+             (mapcar 'org-ref-strip-string (split-string (match-string 1) ",")))
+       (throw 'result org-ref-bibliography-files))
+
+      ;; we did not find anything. use defaults
+      (setq org-ref-bibliography-files org-ref-default-bibliography)))
+
+    ;; set reftex-default-bibliography so we can search
+    (set (make-local-variable 'reftex-default-bibliography) org-ref-bibliography-files)
+    org-ref-bibliography-files)
+
+(defun org-ref-key-in-file-p (key filename)
+  "Determine if the KEY is in the FILENAME."
+  (save-current-buffer
+    (let ((bibtex-files (list filename)))
+      ;; This is something I am trying because when the bibtex file is open, and
+      ;; you have added to it, the only way I find to get the update to update
+      ;; is to close it and reopen it. or to save it and revert it.
+      (when (get-file-buffer filename)
+       (set-buffer (get-file-buffer filename))
+       (save-buffer)
+       (revert-buffer t t))
+      (bibtex-search-entry key t))))
+
+(defun org-ref-get-bibtex-key-and-file (&optional key)
+  "Return the bibtex KEY and file that it is in.  If no key is provided, get one under point."
+ (let ((org-ref-bibliography-files (org-ref-find-bibliography))
+       (file))
+   (unless key
+     (setq key (org-ref-get-bibtex-key-under-cursor)))
+   (setq file     (catch 'result
+                   (cl-loop for file in org-ref-bibliography-files do
+                            (if (org-ref-key-in-file-p key (file-truename file))
+                                (throw 'result file)))))
+   (cons key file)))
+
+;; *** key at point functions
+
+(defun org-ref-get-pdf-filename (key)
+  "Return the pdf filename associated with a bibtex KEY."
+  (format (concat org-ref-pdf-directory "%s.pdf") key))
+
+
+(defun org-ref-get-mendeley-filename (key)
+  "Return the pdf filename indicated by mendeley file field.
+Falls back to org-ref-get-pdf-filename if file filed does not exist.
+Contributed by https://github.com/autosquid."
+  (let* ((results (org-ref-get-bibtex-key-and-file key))
+        (bibfile (cdr results)))
+    (with-temp-buffer
+      (insert-file-contents bibfile)
+      (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+      (bibtex-search-entry key nil 0)
+      (setq entry (bibtex-parse-entry))
+      (let ((e (org-ref-reftex-get-bib-field "file" entry)))
+       (if (> (length e) 4)
+           (remove-if
+            (lambda (ch)
+              (find ch "{}\\"))
+            (format "/%s" (subseq e 1 (- (length e) 4))))
+         (format (concat org-ref-pdf-directory "%s.pdf") key))))))
+
+
+(defun org-ref-open-pdf-at-point ()
+  "Open the pdf for bibtex key under point if it exists."
+  (interactive)
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+         (pdf-file (funcall org-ref-get-pdf-filename-function key)))
+    (if (file-exists-p pdf-file)
+       (org-open-file pdf-file)
+(message "no pdf found for %s" key))))
+
+
+(defun org-ref-open-url-at-point ()
+  "Open the url for bibtex key under point."
+  (interactive)
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+        (bibfile (cdr results)))
+    (save-excursion
+      (with-temp-buffer
+        (insert-file-contents bibfile)
+        (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+        (bibtex-search-entry key)
+        ;; I like this better than bibtex-url which does not always find
+        ;; the urls
+        (catch 'done
+          (let ((url (bibtex-autokey-get-field "url")))
+            (when  url
+              (browse-url (s-trim url))
+              (throw 'done nil)))
+
+          (let ((doi (bibtex-autokey-get-field "doi")))
+            (when doi
+              (if (string-match "^http" doi)
+                  (browse-url doi)
+                (browse-url (format "http://dx.doi.org/%s" (s-trim doi))))
+              (throw 'done nil))))))))
+
+
+(defun org-ref-open-notes-at-point ()
+  "Open the notes for bibtex key under point."
+  (interactive)
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+        (bibfile (cdr results)))
+    (save-excursion
+      (with-temp-buffer
+        (insert-file-contents bibfile)
+        (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+        (bibtex-search-entry key)
+        (org-ref-open-bibtex-notes)))))
+
+
+(defun org-ref-citation-at-point ()
+  "Give message of current citation at point."
+  (interactive)
+  (let* ((cb (current-buffer))
+       (results (org-ref-get-bibtex-key-and-file))
+       (key (car results))
+       (bibfile (cdr results)))
+    (message "%s" (progn
+                   (with-temp-buffer
+                      (insert-file-contents bibfile)
+                      (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+                      (bibtex-search-entry key)
+                      (org-ref-bib-citation))))))
+
+
+(defun org-ref-open-citation-at-point ()
+  "Open bibtex file to key at point."
+  (interactive)
+  (let* ((cb (current-buffer))
+       (results (org-ref-get-bibtex-key-and-file))
+       (key (car results))
+       (bibfile (cdr results)))
+    (find-file bibfile)
+    (bibtex-search-entry key)))
+
+;; *** cite menu
+
+(defvar org-ref-cite-menu-funcs '()
+ "Functions to run on cite click menu.
+Each entry is a list of (key menu-name function).
+The function must take no arguments and work on the key at point.  Do not modify this variable, it is set to empty in the menu click function, and functions are conditionally added to it.")
+
+
+(defvar org-ref-user-cite-menu-funcs
+  '(("C" "rossref" org-ref-crossref-at-point)
+    ("y" "Copy entry to file" org-ref-copy-entry-at-point-to-file)
+    ("s" "Copy summary" org-ref-copy-entry-as-summary))
+  "User-defined functions to run on bibtex key at point.")
+
+
+(defun org-ref-copy-entry-as-summary ()
+  "Copy the bibtex entry for the citation at point as a summary."
+  (interactive)
+    (save-window-excursion
+      (org-ref-open-citation-at-point)
+      (kill-new (org-ref-bib-citation))))
+
+
+(defun org-ref-copy-entry-at-point-to-file ()
+  "Copy the bibtex entry for the citation at point to NEW-FILE.
+Prompt for NEW-FILE includes bib files in `org-ref-default-bibliography', and bib files in current working directory.  You can also specify a new file."
+  (interactive)
+  (let ((new-file (ido-completing-read
+                  "Copy to bibfile: "
+                  (append org-ref-default-bibliography
+                          (f-entries "." (lambda (f) (f-ext? f "bib"))))))
+       (key (org-ref-get-bibtex-key-under-cursor)))
+    (save-window-excursion
+      (org-ref-open-citation-at-point)
+      (bibtex-copy-entry-as-kill))
+
+    (let ((bibtex-files (list (file-truename new-file))))
+      (if (assoc key (bibtex-global-key-alist))
+         (message "That key already exists in %s" new-file)
+       ;; add to file
+       (save-window-excursion
+         (find-file new-file)
+         (goto-char (point-max))
+          ;; make sure we are at the beginning of a line.
+         (unless (looking-at "^") (insert "\n\n"))
+         (bibtex-yank)
+         (save-buffer))))))
+
+
+(defun org-ref-get-doi-at-point ()
+  "Get doi for key at point."
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+        (bibfile (cdr results))
+         doi)
+    (save-excursion
+      (with-temp-buffer
+        (insert-file-contents bibfile)
+        (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+        (bibtex-search-entry key)
+       (setq doi (bibtex-autokey-get-field "doi"))
+       ;; in case doi is a url, remove the url part.
+       (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))))
+
+
+;; **** functions that operate on key at point for click menu
+(defun org-ref-wos-at-point ()
+  "Open the doi in wos for bibtex key under point."
+  (interactive)
+  (doi-utils-wos (org-ref-get-doi-at-point)))
+
+
+(defun org-ref-wos-citing-at-point ()
+  "Open the doi in wos citing articles for bibtex key under point."
+  (interactive)
+  (doi-utils-wos-citing (org-ref-get-doi-at-point)))
+
+
+(defun org-ref-wos-related-at-point ()
+  "Open the doi in wos related articles for bibtex key under point."
+  (interactive)
+  (doi-utils-wos-related (org-ref-get-doi-at-point)))
+
+
+(defun org-ref-google-scholar-at-point ()
+  "Open the doi in google scholar for bibtex key under point."
+  (interactive)
+  (doi-utils-google-scholar (org-ref-get-doi-at-point)))
+
+
+(defun org-ref-pubmed-at-point ()
+  "Open the doi in pubmed for bibtex key under point."
+  (interactive)
+  (doi-utils-pubmed (org-ref-get-doi-at-point)))
+
+
+(defun org-ref-crossref-at-point ()
+  "Open the doi in crossref for bibtex key under point."
+  (interactive)
+  (doi-utils-crossref (org-ref-get-doi-at-point)))
+
+;; *** Minibuffer menu
+
+(defun org-ref-cite-onclick-minibuffer-menu (&optional link-string)
+  "Action when a cite link is clicked on.
+Provides a menu of context sensitive actions.  If the bibtex entry
+has a pdf, you get an option to open it.  If there is a doi, you
+get a lot of options.  LINK-STRING is used by the link function."
+  (interactive)
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+         (pdf-file (funcall org-ref-get-pdf-filename-function key))
+         (bibfile (cdr results))
+        (url (save-excursion
+               (with-temp-buffer
+                 (insert-file-contents bibfile)
+                  (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+                 (bibtex-search-entry key)
+                 (bibtex-autokey-get-field "url"))))
+        (doi (save-excursion
+               (with-temp-buffer
+                 (insert-file-contents bibfile)
+                  (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+                 (bibtex-search-entry key)
+                 ;; I like this better than bibtex-url which does not always find
+                 ;; the urls
+                 (bibtex-autokey-get-field "doi")))))
+
+    (when (string= "" doi) (setq doi nil))
+    (when (string= "" url) (setq url nil))
+    (setq org-ref-cite-menu-funcs '())
+
+    ;; open action
+    (when
+       bibfile
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       '("o" "pen" org-ref-open-citation-at-point)))
+
+    ;; pdf
+    (when (file-exists-p pdf-file)
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       `("p" "df" ,org-ref-open-pdf-function) t))
+
+    ;; notes
+    (add-to-list
+     'org-ref-cite-menu-funcs
+     '("n" "otes" org-ref-open-notes-at-point) t)
+
+    ;; url
+    (when (or url doi)
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       '("u" "rl" org-ref-open-url-at-point) t))
+
+    ;; doi funcs
+    (when doi
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       '("w" "os" org-ref-wos-at-point) t)
+
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       '("c" "iting" org-ref-wos-citing-at-point) t)
+
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       '("r" "elated" org-ref-wos-related-at-point) t)
+
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       '("g" "oogle scholar" org-ref-google-scholar-at-point) t)
+
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       '("P" "ubmed" org-ref-pubmed-at-point) t))
+
+    ;; add user functions
+    (dolist (tup org-ref-user-cite-menu-funcs)
+      (add-to-list
+       'org-ref-cite-menu-funcs
+       tup t))
+
+    ;; finally quit
+    (add-to-list
+     'org-ref-cite-menu-funcs
+     '("q" "uit" (lambda ())) t)
+
+    ;; now we make a menu
+    ;; construct menu string as a message
+    (message
+     (concat
+      (let* ((results (org-ref-get-bibtex-key-and-file))
+            (key (car results))
+            (bibfile (cdr results)))
+       (save-excursion
+         (with-temp-buffer
+           (insert-file-contents bibfile)
+            (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+           (bibtex-search-entry key)
+           (org-ref-bib-citation))))
+      "\n"
+      (mapconcat
+       (lambda (tup)
+        (concat "[" (elt tup 0) "]"
+                (elt tup 1) " "))
+       org-ref-cite-menu-funcs "")))
+    ;; get the input
+    (let* ((input (read-char-exclusive))
+          (choice (assoc
+                   (char-to-string input) org-ref-cite-menu-funcs)))
+      ;; now run the function (2nd element in choice)
+      (when choice
+       (funcall
+        (elt
+         choice
+         2))))))
+
+;; *** Generation of the cite links
+(defmacro org-ref-make-completion-function (type)
+  "Macro to make a link completion function for a link of TYPE."
+  `(defun ,(intern (format "org-%s-complete-link" type)) (&optional arg)
+     (interactive)
+     (format "%s:%s"
+            ,type
+            (completing-read
+             "bibtex key: "
+             (let ((bibtex-files (org-ref-find-bibliography)))
+               (bibtex-global-key-alist))))))
+
+(defmacro org-ref-make-format-function (type)
+  "Macro to make a format function for a link of TYPE."
+  `(defun ,(intern (format "org-ref-format-%s" type)) (keyword desc format)
+     (cond
+      ((eq format 'org)
+       (mapconcat
+       (lambda (key)
+         (format "[[#%s][%s]]" key key))
+       (org-ref-split-and-strip-string keyword) ","))
+
+      ((eq format 'ascii)
+       (concat "["
+              (mapconcat
+               (lambda (key)
+                 (format "%s" key))
+               (org-ref-split-and-strip-string keyword) ",") "]"))
+
+      ((eq format 'html)
+       (mapconcat
+       (lambda (key)
+         (format "<a href=\"#%s\">%s</a>" key key))
+       (org-ref-split-and-strip-string keyword) ","))
+
+      ((eq format 'latex)
+       (if (string= (substring type -1) "s")
+          ;; biblatex format for multicite commands, which all end in s. These are formated as \cites{key1}{key2}...
+          (concat "\\" ,type (mapconcat (lambda (key) (format "{%s}"  key))
+                                        (org-ref-split-and-strip-string keyword) ""))
+        ;; bibtex format
+       (concat "\\" ,type (when desc (org-ref-format-citation-description desc)) "{"
+              (mapconcat (lambda (key) key) (org-ref-split-and-strip-string keyword) ",")
+              "}")))
+      ;; for markdown we generate pandoc citations
+      ((eq format 'md)
+       (cond
+       (desc  ;; pre and or post text
+        (let* ((text (split-string desc "::"))
+               (pre (car text))
+               (post (cadr text)))
+          (concat
+           (format "[@%s," keyword)
+           (when pre (format " %s" pre))
+           (when post (format ", %s" post))
+           "]")))
+       (t
+        (format "[%s]"
+                (mapconcat
+                 (lambda (key) (concat "@" key))
+                 (org-ref-split-and-strip-string keyword)
+                 "; "))))))))
+
+(defun org-ref-format-citation-description (desc)
+  "Return formatted citation description.
+If the cite link has a DESC (description), it is optional text
+for the citation command.  You can specify pre and post text by
+separating these with ::, for example [[cite:key][pre text::post
+text]]."
+  (cond
+   ((string-match "::" desc)
+    (format "[%s][%s]" (car (setq results (split-string desc "::"))) (cadr results)))
+   (t (format "[%s]" desc))))
+
+(defun org-ref-define-citation-link (type &optional key)
+  "Add a citation link of TYPE for org-ref.
+With optional KEY, set the reftex binding. For example:
+\(org-ref-define-citation-link \"citez\" ?z) will create a new
+citez link, with reftex key of z, and the completion function."
+  (interactive "sCitation Type: \ncKey: ")
+
+  ;; create the formatting function
+  (eval `(org-ref-make-format-function ,type))
+
+  (eval-expression
+   `(org-add-link-type
+     ,type
+     org-ref-cite-onclick-function
+     (quote ,(intern (format "org-ref-format-%s" type)))))
+
+  ;; create the completion function
+  (eval `(org-ref-make-completion-function ,type))
+
+  ;; store new type so it works with adding citations, which checks
+  ;; for existence in this list
+  (add-to-list 'org-ref-cite-types type)
+
+  ;; and finally if a key is specified, we modify the reftex menu
+  (when key
+    (setf (nth 2 (assoc 'org reftex-cite-format-builtin))
+         (append (nth 2 (assoc 'org reftex-cite-format-builtin))
+                 `((,key  . ,(concat type ":%l")))))))
+
+;; create all the link types and their completion functions
+(mapcar 'org-ref-define-citation-link org-ref-cite-types)
+
+(defun org-ref-insert-cite-link (alternative-cite)
+  "Insert a default citation link using reftex.
+If you are on a link, it appends to the end of the link,
+otherwise, a new link is inserted.  Use a prefix
+arg (ALTERNATIVE-CITE) to get a menu of citation types."
+  (interactive "P")
+  (org-ref-find-bibliography)
+  (let* ((object (org-element-context))
+        (link-string-beginning (org-element-property :begin object))
+        (link-string-end (org-element-property :end object))
+        (path (org-element-property :path object)))
+
+    (if (not alternative-cite)
+
+       (cond
+        ;; case where we are in a link
+        ((and (equal (org-element-type object) 'link)
+              (-contains? org-ref-cite-types (org-element-property :type object)))
+         (goto-char link-string-end)
+         ;; sometimes there are spaces at the end of the link
+         ;; this code moves point pack until no spaces are there
+         (while (looking-back " ") (backward-char))
+         (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ","))))
+
+        ;; We are next to a link, and we want to append
+        ((save-excursion
+           (backward-char)
+           (and (equal (org-element-type (org-element-context)) 'link)
+                (-contains? org-ref-cite-types (org-element-property :type (org-element-context)))))
+         (while (looking-back " ") (backward-char))
+         (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ","))))
+
+        ;; insert fresh link
+        (t
+         (insert
+          (concat org-ref-default-citation-link
+                  ":"
+                  (mapconcat 'identity (reftex-citation t) ",")))))
+
+      ;; you pressed a C-u so we run this code
+      (reftex-citation))))
+
+(defun org-ref-insert-cite-with-completion (type)
+  "Insert a cite link of TYPE with completion."
+  (interactive (list (ido-completing-read "Type: " org-ref-cite-types)))
+  (insert (funcall (intern (format "org-%s-complete-link" type)))))
+
+(defun org-ref-store-bibtex-entry-link ()
+  "Save a citation link to the current bibtex entry.  Save in the default link type."
+  (interactive)
+  (let ((link (concat org-ref-default-citation-link
+                ":"
+                (save-excursion
+                  (bibtex-beginning-of-entry)
+                  (reftex-get-bib-field "=key=" (bibtex-parse-entry))))))
+    (message "saved %s" link)
+    (push (list link) org-stored-links)
+    (car org-stored-links)))
+
+;; ** Index link
+(org-add-link-type
+ "index"
+ (lambda (path)
+   (occur path))
+
+ (lambda (path desc format)
+   (cond
+    ((eq format 'latex)
+      (format "\\index{%s}" path)))))
+
+;; this will generate a temporary index of entries in the file.
+(org-add-link-type
+ "printindex"
+ (lambda (path)
+   (let ((*index-links* '())
+        (*initial-letters* '()))
+
+     ;; get links
+     (org-element-map (org-element-parse-buffer) 'link
+       (lambda (link)
+        (let ((type (nth 0 link))
+              (plist (nth 1 link)))
+
+          (when (equal (plist-get plist ':type) "index")
+            (add-to-list
+             '*index-links*
+             (cons (plist-get plist :path)
+                   (format
+                    "[[elisp:(progn (switch-to-buffer \"%s\") (goto-char %s))][%s]]"
+(current-buffer)
+                    (plist-get plist :begin)  ;; position of link
+                    ;; grab a description
+                    (save-excursion
+                      (goto-char (plist-get plist :begin))
+                      (if (thing-at-point 'sentence)
+                          ;; get a sentence
+                          (replace-regexp-in-string
+                           "\n" "" (thing-at-point 'sentence))
+                        ;; or call it a link
+                        "link")))))))))
+
+     ;; sort the links
+     (setq *index-links*  (cl-sort *index-links* 'string-lessp :key 'car))
+
+     ;; now first letters
+     (dolist (link *index-links*)
+       (add-to-list '*initial-letters* (substring (car link) 0 1) t))
+
+     ;; now create the index
+     (switch-to-buffer (get-buffer-create "*index*"))
+     (org-mode)
+     (erase-buffer)
+     (insert "#+TITLE: Index\n\n")
+     (dolist (letter *initial-letters*)
+       (insert (format "* %s\n" (upcase letter)))
+       ;; now process the links
+       (while (and
+              *index-links*
+              (string= letter (substring (car (car *index-links*)) 0 1)))
+        (let ((link (pop *index-links*)))
+          (insert (format "%s %s\n\n" (car link) (cdr link))))))
+     (switch-to-buffer "*index*")))
+ ;; formatting
+ (lambda (path desc format)
+   (cond
+    ((eq format 'latex)
+      (format "\\printindex")))))
+
+;; ** Glossary link
+(org-add-link-type
+ "newglossaryentry"
+ nil ;; no follow action
+ (lambda (path desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\newglossaryentry{%s}{%s}" path desc)))))
+
+
+;; link to entry
+(org-add-link-type
+ "gls"
+  nil ;; no follow action
+ (lambda (path desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\gls{%s}" path)))))
+
+;; plural
+(org-add-link-type
+ "glspl"
+  nil ;; no follow action
+ (lambda (path desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\glspl{%s}" path)))))
+
+;; capitalized link
+(org-add-link-type
+ "Gls"
+  nil ;; no follow action
+ (lambda (path desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\Gls{%s}" path)))))
+
+;; capitalized link
+(org-add-link-type
+ "Glspl"
+  nil ;; no follow action
+ (lambda (path desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\Glspl{%s}" path)))))
+
+;; * Utilities
+;; ** create text citations from a bibtex entry
+(defun org-ref-bib-citation ()
+  "From a bibtex entry, create and return a simple citation string.
+This assumes you are in an article."
+  (bibtex-set-dialect nil t)
+  (bibtex-beginning-of-entry)
+  (let* ((cb (current-buffer))
+        (bibtex-expand-strings t)
+        (entry (cl-loop for (key . value) in (bibtex-parse-entry t)
+                        collect (cons (downcase key) value)))
+        (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
+        (year  (reftex-get-bib-field "year" entry))
+        (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
+        (key (reftex-get-bib-field "=key=" entry))
+        (journal (let ((jt (reftex-get-bib-field "journal" entry)))
+                    (if (string= "" jt)
+                        (reftex-get-bib-field "journaltitle" entry)
+                      jt)))
+        (volume (reftex-get-bib-field "volume" entry))
+        (pages (reftex-get-bib-field "pages" entry))
+        (doi (reftex-get-bib-field "doi" entry))
+        (url (reftex-get-bib-field "url" entry))
+        )
+    ;;authors, "title", Journal, vol(iss):pages (year).
+    (format "%s, \"%s\", %s, %s:%s (%s)"
+           author title journal  volume pages year)))
+
+(defun org-ref-bib-html-citation ()
+  "From a bibtex entry, create and return a simple citation with html links."
+  (bibtex-beginning-of-entry)
+  (let* ((cb (current-buffer))
+        (bibtex-expand-strings t)
+        (entry (cl-loop for (key . value) in (bibtex-parse-entry t)
+                        collect (cons (downcase key) value)))
+        (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
+        (year  (reftex-get-bib-field "year" entry))
+        (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
+        (key (reftex-get-bib-field "=key=" entry))
+        (journal (reftex-get-bib-field "journal" entry))
+        (volume (reftex-get-bib-field "volume" entry))
+        (pages (reftex-get-bib-field "pages" entry))
+        (doi (reftex-get-bib-field "doi" entry))
+        (url (reftex-get-bib-field "url" entry)))
+    ;;authors, "title", Journal, vol(iss):pages (year).
+    (concat (format "%s, \"%s\", %s, %s:%s (%s)."
+                   author title journal  volume pages year)
+           (when url (format " <a href=\"%s\">link</a>" url))
+           (when doi
+             (format " <a href=\"http://dx.doi.org/%s\">doi</a>" doi)))))
+
+;; ** Open pdf in bibtex entry
+(defun org-ref-open-bibtex-pdf ()
+  "Open pdf for a bibtex entry, if it exists.
+assumes point is in
+the entry of interest in the bibfile.  but does not check that."
+  (interactive)
+  (save-excursion
+    (bibtex-beginning-of-entry)
+    (let* ((bibtex-expand-strings t)
+           (entry (bibtex-parse-entry t))
+           (key (reftex-get-bib-field "=key=" entry))
+           (pdf (format (concat org-ref-pdf-directory "%s.pdf") key)))
+      (message "%s" pdf)
+      (if (file-exists-p pdf)
+          (org-open-link-from-string (format "[[file:%s]]" pdf))
+        (ding)))))
+
+;; ** Open notes from bibtex entry
+
+(defun org-ref-open-bibtex-notes ()
+  "From a bibtex entry, open the notes if they exist, and create a heading if they do not.
+
+I never did figure out how to use reftex to make this happen
+non-interactively. the reftex-format-citation function did not
+work perfectly; there were carriage returns in the strings, and
+it did not put the key where it needed to be. so, below I replace
+the carriage returns and extra spaces with a single space and
+construct the heading by hand."
+  (interactive)
+
+  (bibtex-beginning-of-entry)
+  (let* ((cb (current-buffer))
+        (bibtex-expand-strings t)
+        (entry (cl-loop for (key . value) in (bibtex-parse-entry t)
+                        collect (cons (downcase key) value)))
+        (key (reftex-get-bib-field "=key=" entry)))
+
+    ;; save key to clipboard to make saving pdf later easier by pasting.
+    (with-temp-buffer
+      (insert key)
+      (kill-ring-save (point-min) (point-max)))
+
+    ;; now look for entry in the notes file
+    (if  org-ref-bibliography-notes
+       (find-file-other-window org-ref-bibliography-notes)
+      (error "Org-ref-bib-bibliography-notes is not set to anything"))
+
+    (goto-char (point-min))
+    ;; put new entry in notes if we don't find it.
+    (if (re-search-forward (format ":Custom_ID: %s$" key) nil 'end)
+       (funcall org-ref-open-notes-function)
+      ;; no entry found, so add one
+      (insert (org-ref-reftex-format-citation entry (concat "\n" org-ref-note-title-format)))
+      (insert (org-ref-reftex-format-citation
+               entry
+               (concat "
+ :PROPERTIES:
+  :Custom_ID: %k
+  :AUTHOR: %9a
+  :JOURNAL: %j
+  :YEAR: %y
+  :VOLUME: %v
+  :PAGES: %p
+  :DOI: %D
+  :URL: %U
+ :END:
+"
+                       (format "[[cite:%s]] [[file:%s/%s.pdf][pdf]]\n\n"
+                               key org-ref-pdf-directory key))))
+      (save-buffer))))
+
+(defun org-ref-open-notes-from-reftex ()
+  "Call reftex, and open notes for selected entry."
+  (interactive)
+  (let ((bibtex-key )))
+
+  ;; now look for entry in the notes file
+  (if  org-ref-bibliography-notes
+      (find-file-other-window org-ref-bibliography-notes)
+    (error "Org-ref-bib-bibliography-notes is not set to anything"))
+
+  (goto-char (point-min))
+
+  (re-search-forward (format
+                      ":Custom_ID: %s$"
+                      (cl-first (reftex-citation t)) nil 'end))
+  (funcall org-ref-open-notes-function))
+
+;; ** Open bibtex entry in browser
+(defun org-ref-open-in-browser ()
+  "Open the bibtex entry at point in a browser using the url field or doi field."
+(interactive)
+(save-excursion
+  (bibtex-beginning-of-entry)
+  (catch 'done
+    (let ((url (bibtex-autokey-get-field "url")))
+      (when  url
+        (browse-url url)
+        (throw 'done nil)))
+
+    (let ((doi (bibtex-autokey-get-field "doi")))
+      (when doi
+        (if (string-match "^http" doi)
+            (browse-url doi)
+          (browse-url (format "http://dx.doi.org/%s" doi)))
+        (throw 'done nil)))
+    (message "No url or doi found"))))
+
+;; ** upload entry to citeulike
+
+(defun org-ref-upload-bibtex-entry-to-citeulike ()
+  "With point in  a bibtex entry get bibtex string and submit to citeulike.
+
+Relies on the python script /upload_bibtex_citeulike.py being in the user directory."
+  (interactive)
+  (message "uploading to citeulike")
+  (save-restriction
+    (bibtex-narrow-to-entry)
+    (let ((startpos (point-min))
+          (endpos (point-max))
+          (bibtex-string (buffer-string))
+          (script (concat "python " starter-kit-dir "/upload_bibtex_citeulike.py&")))
+      (with-temp-buffer (insert bibtex-string)
+                        (shell-command-on-region (point-min) (point-max) script t nil nil t)))))
+
+;; ** Build a pdf of the bibtex file
+(defun org-ref-build-full-bibliography ()
+  "Build pdf of all bibtex entries, and open it."
+  (interactive)
+  (let* ((bibfile (file-name-nondirectory (buffer-file-name)))
+       (bib-base (file-name-sans-extension bibfile))
+       (texfile (concat bib-base ".tex"))
+       (pdffile (concat bib-base ".pdf")))
+    (find-file texfile)
+    (erase-buffer)
+    (insert (format "\\documentclass[12pt]{article}
+\\usepackage[version=3]{mhchem}
+\\usepackage{url}
+\\usepackage[numbers]{natbib}
+\\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue, pdfstartview=FitH]{hyperref}
+\\usepackage{doi}
+\\begin{document}
+\\nocite{*}
+\\bibliographystyle{unsrtnat}
+\\bibliography{%s}
+\\end{document}" bib-base))
+    (save-buffer)
+    (shell-command (concat "pdflatex " bib-base))
+    (shell-command (concat "bibtex " bib-base))
+    (shell-command (concat "pdflatex " bib-base))
+    (shell-command (concat "pdflatex " bib-base))
+    (kill-buffer texfile)
+    (org-open-file pdffile)
+    ))
+
+;; ** Extract bibtex entries in org-file
+
+(defun org-ref-extract-bibtex-entries ()
+  "Extract the bibtex entries referred to by cite links in the current buffer into a src block at the bottom of the current buffer.
+
+If no bibliography is in the buffer the variable
+`reftex-default-bibliography' is used."
+  (interactive)
+  (let* ((temporary-file-directory (file-name-directory (buffer-file-name)))
+         (tempname (make-temp-file "extract-bib"))
+         (contents (buffer-string))
+         (cb (current-buffer))
+        basename texfile bibfile results)
+
+    ;; open tempfile and insert org-buffer contents
+    (find-file tempname)
+    (insert contents)
+    (setq basename (file-name-sans-extension
+                   (file-name-nondirectory buffer-file-name))
+         texfile (concat tempname ".tex")
+         bibfile (concat tempname ".bib"))
+
+    ;; see if we have a bibliography, and insert the default one if not.
+    (save-excursion
+      (goto-char (point-min))
+      (unless (re-search-forward "^bibliography:" (point-max) 'end)
+       (insert (format "\nbibliography:%s"
+                       (mapconcat 'identity reftex-default-bibliography ",")))))
+    (save-buffer)
+
+    ;; get a latex file and extract the references
+    (org-latex-export-to-latex)
+    (find-file texfile)
+    (reftex-parse-all)
+    (reftex-create-bibtex-file bibfile)
+    (save-buffer)
+    ;; save results of the references
+    (setq results (buffer-string))
+
+    ;; kill buffers. these are named by basename, not full path
+    (kill-buffer (concat basename ".bib"))
+    (kill-buffer (concat basename ".tex"))
+    (kill-buffer basename)
+
+    (delete-file bibfile)
+    (delete-file texfile)
+    (delete-file tempname)
+
+    ;; Now back to the original org buffer and insert the results
+    (switch-to-buffer cb)
+    (when (not (string= "" results))
+      (save-excursion
+        (goto-char (point-max))
+        (insert "\n\n")
+       (org-insert-heading)
+       (insert (format " Bibtex entries
+
+#+BEGIN_SRC text :tangle %s
+%s
+#+END_SRC" (concat (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) ".bib") results))))))
+
+;; ** Find bad citations
+(require 'cl)
+
+(defun index (substring list)
+  "Return the index of SUBSTRING in a LIST of strings."
+  (let ((i 0)
+       (found nil))
+    (dolist (arg list i)
+      (if (string-match (concat "^" substring "$") arg)
+         (progn
+           (setq found t)
+           (return i)))
+      (setq i (+ i 1)))
+    ;; return counter if found, otherwise return nil
+    (if found i nil)))
+
+
+(defun org-ref-find-bad-citations ()
+  "Create a list of citation keys in an org-file that do not have a bibtex entry in the known bibtex files.
+
+Makes a new buffer with clickable links."
+  (interactive)
+  ;; generate the list of bibtex-keys and cited keys
+  (let* ((bibtex-files (org-ref-find-bibliography))
+         (bibtex-file-path (mapconcat (lambda (x) (file-name-directory (file-truename x))) bibtex-files ":"))
+        (bibtex-keys (mapcar (lambda (x) (car x)) (bibtex-global-key-alist)))
+        (bad-citations '()))
+
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (link)
+       (let ((plist (nth 1 link)))
+         (when (-contains? org-ref-cite-types (plist-get plist :type))
+           (dolist (key (org-ref-split-and-strip-string (plist-get plist :path)))
+             (when (not (index key bibtex-keys))
+               (setq
+                bad-citations
+                (append
+                 bad-citations
+                 `(,(format "%s [[elisp:(progn (switch-to-buffer-other-frame \"%s\")(goto-char %s))][not found here]]\n"
+                            key
+                            (buffer-name)
+                            (plist-get plist :begin)))))
+               )))))
+      ;; set with-affilates to t to get citations in a caption
+      nil nil nil t)
+
+    (if bad-citations
+      (progn
+       (switch-to-buffer-other-window "*Missing citations*")
+       (org-mode)
+       (erase-buffer)
+       (insert "* List of bad cite links\n")
+       (insert (mapconcat 'identity bad-citations ""))
+                                       ;(setq buffer-read-only t)
+       (use-local-map (copy-keymap org-mode-map))
+       (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))
+
+      (when (get-buffer "*Missing citations*")
+          (kill-buffer "*Missing citations*"))
+      (message "No bad cite links found"))))
+
+;; ** helm interface to bad citations, labels, refs and files in orgfile
+(defun org-ref-bad-cite-candidates ()
+  "Return a list of conses (key . marker) where key does not exist in the known bibliography files, and marker points to the key."
+  (let* ((cp (point))                  ; save to return to later
+        (bibtex-files (org-ref-find-bibliography))
+         (bibtex-file-path (mapconcat
+                           (lambda (x)
+                             (file-name-directory (file-truename x)))
+                           bibtex-files ":"))
+        (bibtex-keys (mapcar (lambda (x) (car x))
+                             (bibtex-global-key-alist)))
+        (bad-citations '()))
+
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (link)
+       (let ((plist (nth 1 link)))
+         (when (-contains? org-ref-cite-types (plist-get plist :type))
+           (dolist (key (org-ref-split-and-strip-string (plist-get plist :path)) )
+             (when (not (index key bibtex-keys))
+               (goto-char (plist-get plist :begin))
+               (re-search-forward key)
+               (push (cons key (point-marker)) bad-citations)))
+           )))
+      ;; add with-affiliates to get cites in caption
+      nil nil nil t)
+    (goto-char cp)
+    bad-citations))
+
+
+(defun org-ref-bad-ref-candidates ()
+  "Return a list of conses (ref . marker) where ref is a ref link that does not point to anything (i.e. a label)."
+  ;; first get a list of legitimate labels
+  (let ((cp (point))
+       (labels (org-ref-get-labels))
+       (bad-refs '()))
+    ;; now loop over ref links
+    (goto-char (point-min))
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (link)
+       (let ((plist (nth 1 link)))
+         (when (or  (equal (plist-get plist ':type) "ref")
+                    (equal (plist-get plist ':type) "eqref")
+                    (equal (plist-get plist ':type) "pageref")
+                    (equal (plist-get plist ':type) "nameref"))
+           (unless (-contains? labels (plist-get plist :path))
+             (goto-char (plist-get plist :begin))
+             (add-to-list
+              'bad-refs
+              (cons (plist-get plist :path)
+                    (point-marker))))))))
+    (goto-char cp)
+    bad-refs))
+
+
+(defun org-ref-bad-label-candidates ()
+  "Return a list of labels where label is multiply defined."
+  (let ((labels (org-ref-get-labels))
+       (multiple-labels '()))
+    (when (not (= (length labels)
+                 (length (-uniq labels))))
+      (dolist (label labels)
+       (when (> (-count (lambda (a)
+                          (equal a label))
+                        labels) 1)
+         ;; this is a multiply defined label.
+         (let ((cp (point)))
+           (goto-char (point-min))
+           (while (re-search-forward
+                   (format  "[^#+]label:%s\\s-" label) nil t)
+             (push (cons label (point-marker)) multiple-labels))
+           (goto-char (point-min))
+           (while (re-search-forward
+                   (format  "\\label{%s}\\s-?" label) nil t)
+             (push (cons label (point-marker)) multiple-labels))
+
+           (goto-char (point-min))
+           (while (re-search-forward
+                   (format  "^#\\+label:\\s-*%s" label) nil t)
+             (push (cons label (point-marker)) multiple-labels))
+
+           (goto-char (point-min))
+           (while (re-search-forward
+                   (format   "^#\\+tblname:\\s-*%s" label) nil t)
+             (push (cons label (point-marker)) multiple-labels))
+           (goto-char cp)))))
+      multiple-labels))
+
+(defun org-ref-bad-file-link-candidates ()
+  "Return list of conses (link . marker) wehre the file in the link does not exist."
+  (let* ((bad-files '()))
+    (org-element-map (org-element-parse-buffer) 'link
+      (lambda (link)
+       (let ((type (org-element-property :type link)))
+         (when (or  (string= "file" type)
+                    (string= "attachfile" type))
+           (unless (file-exists-p (org-element-property :path link))
+             (add-to-list 'bad-files
+                          (cons (org-element-property :path link)
+                                (save-excursion
+                                  (goto-char
+                                   (org-element-property :begin link))
+                                  (point-marker)))))))))
+    ;; Let us also check \attachfile{fname}
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward "\\attachfile{\\(.*\\)}" nil t)
+       (unless (file-exists-p (match-string 1))
+         (add-to-list 'bad-files (cons (match-string 1) (point-marker))))))
+    bad-files))
+
+;;;###autoload
+(defun org-ref ()
+  "Opens a helm interface to actions for org-ref.
+Shows bad citations, ref links and labels"
+  (interactive)
+  (let ((cb (current-buffer))
+       (bad-citations (org-ref-bad-cite-candidates))
+       (bad-refs (org-ref-bad-ref-candidates))
+       (bad-labels (org-ref-bad-label-candidates))
+       (bad-files (org-ref-bad-file-link-candidates)))
+
+    (helm :sources `(((name . "Bad citations")
+                      (candidates . ,bad-citations)
+                      (action . (lambda (marker)
+                                  (switch-to-buffer (marker-buffer marker))
+                                  (goto-char marker))))
+                    ;;
+                    ((name . "Bad Labels")
+                     (candidates . ,bad-labels)
+                     (action . (lambda (marker)
+                                  (switch-to-buffer (marker-buffer marker))
+                                  (goto-char marker))))
+                    ;;
+                    ((name . "Bad ref links")
+                     (candidates . ,bad-refs)
+                     (action . (lambda (marker)
+                                         (switch-to-buffer (marker-buffer marker))
+                                         (goto-char marker))))
+                    ;;
+                    ((name . "Bad file links")
+                     (candidates . ,bad-files)
+                     (lambda (marker)
+                                  (switch-to-buffer (marker-buffer marker))
+                                  (goto-char marker)))
+                    ;;
+                    ((name . "Utilities")
+                     (candidates . (("Check buffer again" . org-ref)
+                                    ("Insert citation" . helm-bibtex)
+                                    ("Insert label link" . org-ref-helm-insert-label-link)
+                                    ("Insert ref link" . org-ref-helm-insert-ref-link)
+                                    ("List of figures" . org-ref-list-of-figures)
+                                    ("List of tables" . org-ref-list-of-tables)
+                                    ("Table of contents" . nil)
+                                    ))
+                     (action . (lambda (x)
+                                 (switch-to-buffer ,cb)
+                                 (funcall x))))
+                    ;;
+                    ((name . "Export functions")
+                     (candidates . (("Extract cited entries" . org-ref-extract-bibtex-entries)
+                                    ("Export to html and open" . (lambda () (org-open-file (org-html-export-to-html))))
+                                    ("Export to pdf and open" . (lambda ()
+                                                                  (org-open-file (org-latex-export-to-pdf))))
+                                    ("Export to manuscript pdf and open" . ox-manuscript-export-and-build-and-open)
+                                    ("Export submission manuscript pdf and open" . ox-manuscript-build-submission-manuscript-and-open)
+
+                                    ))
+                     (action . (lambda (x)
+                                 (switch-to-buffer ,cb)
+                                 (funcall x))))))))
+
+;; ** Find non-ascii charaters
+(defun org-ref-find-non-ascii-characters ()
+  "Find non-ascii characters in the buffer.  Useful for cleaning up bibtex files."
+  (interactive)
+  (occur "[^[:ascii:]]"))
+
+;; ** Sort fields in a bibtex entry
+
+(defun org-ref-sort-bibtex-entry ()
+  "Sort fields of entry in standard order and downcase them."
+  (interactive)
+  (bibtex-beginning-of-entry)
+  (let* ((master '("author" "title" "journal" "volume" "number" "pages" "year" "doi" "url"))
+        (entry (bibtex-parse-entry))
+        (entry-fields)
+        (other-fields)
+        (type (cdr (assoc "=type=" entry)))
+        (key (cdr (assoc "=key=" entry))))
+
+    ;; these are the fields we want to order that are in this entry
+    (setq entry-fields (mapcar (lambda (x) (car x)) entry))
+    ;; we do not want to reenter these fields
+    (setq entry-fields (remove "=key=" entry-fields))
+    (setq entry-fields (remove "=type=" entry-fields))
+
+    ;;these are the other fields in the entry
+    (setq other-fields (remove-if-not (lambda(x) (not (member x master))) entry-fields))
+
+    (cond
+     ;; right now we only resort articles
+     ((string= (downcase type) "article")
+      (bibtex-kill-entry)
+      (insert
+       (concat "@article{" key ",\n"
+              (mapconcat
+               (lambda (field)
+                 (when (member field entry-fields)
+                   (format "%s = %s," (downcase field) (cdr (assoc field entry))))) master "\n")
+              (mapconcat
+               (lambda (field)
+                 (format "%s = %s," (downcase field) (cdr (assoc field entry)))) other-fields "\n")
+              "\n}\n\n"))
+      (bibtex-find-entry key)
+      (bibtex-fill-entry)
+      (bibtex-clean-entry)
+       ))))
+
+;; ** Clean a bibtex entry
+(defun org-ref-clean-bibtex-entry(&optional keep-key)
+  "clean and replace the key in a bibtex function. When keep-key is t, do not replace it. You can use a prefix to specify the key should be kept"
+  (interactive "P")
+  (bibtex-beginning-of-entry)
+(end-of-line)
+  ;; some entries do not have a key or comma in first line. We check and add it, if needed.
+  (unless (string-match ",$" (thing-at-point 'line))
+    (end-of-line)
+    (insert ","))
+
+  ;; check for empty pages, and put eid or article id in its place
+  (let ((entry (bibtex-parse-entry))
+       (pages (bibtex-autokey-get-field "pages"))
+       (year (bibtex-autokey-get-field "year"))
+        (doi  (bibtex-autokey-get-field "doi"))
+        ;; The Journal of Chemical Physics uses eid
+       (eid (bibtex-autokey-get-field "eid")))
+
+    ;; replace http://dx.doi.org/ in doi. some journals put that in,
+    ;; but we only want the doi.
+    (when (string-match "^http://dx.doi.org/" doi)
+      (bibtex-beginning-of-entry)
+      (goto-char (car (cdr (bibtex-search-forward-field "doi" t))))
+      (bibtex-kill-field)
+      (bibtex-make-field "doi")
+      (backward-char)
+      (insert (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))
+
+    ;; asap articles often set year to 0, which messes up key
+    ;; generation. fix that.
+    (when (string= "0" year)
+      (bibtex-beginning-of-entry)
+      (goto-char (car (cdr (bibtex-search-forward-field "year" t))))
+      (bibtex-kill-field)
+      (bibtex-make-field "year")
+      (backward-char)
+      (insert (read-string "Enter year: ")))
+
+    ;; fix pages if they are empty if there is an eid to put there.
+    (when (string= "-" pages)
+      (when eid
+       (bibtex-beginning-of-entry)
+       ;; this seems like a clunky way to set the pages field.But I
+       ;; cannot find a better way.
+       (goto-char (car (cdr (bibtex-search-forward-field "pages" t))))
+       (bibtex-kill-field)
+       (bibtex-make-field "pages")
+       (backward-char)
+       (insert eid)))
+
+    ;; replace naked & with \&
+    (save-restriction
+      (bibtex-narrow-to-entry)
+      (bibtex-beginning-of-entry)
+      (message "checking &")
+      (replace-regexp " & " " \\\\& ")
+      (widen))
+
+    ;; generate a key, and if it duplicates an existing key, edit it.
+    (unless keep-key
+      (let ((key (bibtex-generate-autokey)))
+
+       ;; first we delete the existing key
+       (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)))
+       ;; check if the key is in the buffer
+       (when (save-excursion
+               (bibtex-search-entry key))
+         (save-excursion
+           (bibtex-search-entry key)
+           (bibtex-copy-entry-as-kill)
+           (switch-to-buffer-other-window "*duplicate entry*")
+           (bibtex-yank))
+         (setq key (bibtex-read-key "Duplicate Key found, edit: " key)))
+
+       (insert key)
+       (kill-new key))) ;; save key for pasting
+
+    ;; run hooks. each of these operates on the entry with no arguments.
+    ;; this did not work like  i thought, it gives a symbolp error.
+    ;; (run-hooks org-ref-clean-bibtex-entry-hook)
+    (mapcar (lambda (x)
+             (save-restriction
+               (save-excursion
+                 (funcall x))))
+           org-ref-clean-bibtex-entry-hook)
+
+    ;; sort fields within entry
+    (org-ref-sort-bibtex-entry)
+    ;; check for non-ascii characters
+    (occur "[^[:ascii:]]")
+    ))
+
+(defun org-ref-get-citation-year (key)
+  "Get the year of an entry with KEY.  Return year as a string."
+  (let* ((results (org-ref-get-bibtex-key-and-file key))
+        (bibfile (cdr results)))
+    (with-temp-buffer
+      (insert-file-contents bibfile)
+      (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+      (bibtex-search-entry key nil 0)
+      (prog1 (reftex-get-bib-field "year" (bibtex-parse-entry t))
+        ))))
+
+;; ** Sort cite in cite link
+(defun org-ref-sort-citation-link ()
+ "Replace link at point with sorted link by year."
+ (interactive)
+ (let* ((object (org-element-context))
+        (type (org-element-property :type object))
+       (begin (org-element-property :begin object))
+       (end (org-element-property :end object))
+       (link-string (org-element-property :path object))
+       keys years data)
+  (setq keys (org-ref-split-and-strip-string link-string))
+  (setq years (mapcar 'org-ref-get-citation-year keys))
+  (setq data (mapcar* (lambda (a b) `(,a . ,b)) years keys))
+  (setq data (cl-sort data (lambda (x y) (< (string-to-number (car x)) (string-to-number (car y))))))
+  ;; now get the keys separated by commas
+  (setq keys (mapconcat (lambda (x) (cdr x)) data ","))
+  ;; and replace the link with the sorted keys
+  (cl--set-buffer-substring begin end (concat type ":" keys))))
+
+;; ** Shift-arrow sorting of keys in a cite link
+
+(defun org-ref-swap-keys (i j keys)
+ "Swap the KEYS in a list with index I and J."
+ (let ((tempi (nth i keys)))
+   (setf (nth i keys) (nth j keys))
+   (setf (nth j keys) tempi))
+  keys)
+
+
+(defun org-ref-swap-citation-link (direction)
+ "Move citation at point in DIRECTION +1 is to the right, -1 to the left."
+ (interactive)
+ (let* ((object (org-element-context))
+        (type (org-element-property :type object))
+       (begin (org-element-property :begin object))
+       (end (org-element-property :end object))
+       (link-string (org-element-property :path object))
+       key keys i)
+   ;;   We only want this to work on citation links
+   (when (-contains? org-ref-cite-types type)
+        (setq key (org-ref-get-bibtex-key-under-cursor))
+       (setq keys (org-ref-split-and-strip-string link-string))
+        (setq i (index key keys))  ;; defined in org-ref
+       (if (> direction 0) ;; shift right
+           (org-ref-swap-keys i (+ i 1) keys)
+         (org-ref-swap-keys i (- i 1) keys))
+       (setq keys (mapconcat 'identity keys ","))
+       ;; and replace the link with the sorted keys
+       (cl--set-buffer-substring
+        begin end
+        (concat
+         type ":" keys
+         ;; It seems the space at the end can get consumed, so we see if there
+         ;; is a space, and add it if so. Sometimes there is a comma or period,
+         ;; then we do not want a space.
+         (when
+             (save-excursion
+               (goto-char end)
+               (looking-back " ")) " ")))
+       ;; now go forward to key so we can move with the key
+       (re-search-forward key)
+       (goto-char (match-beginning 0)))))
+
+;; add hooks to make it work
+(add-hook 'org-shiftright-hook (lambda () (org-ref-swap-citation-link 1)))
+(add-hook 'org-shiftleft-hook (lambda () (org-ref-swap-citation-link -1)))
+
+;; ** context around org-ref links
+(defun org-ref-get-label-context (label)
+  "Return a string of context around a LABEL."
+  (save-excursion
+    (catch 'result
+      (goto-char (point-min))
+      (when (re-search-forward
+            (format "label:%s\\b" label) nil t)
+       (throw 'result (buffer-substring
+                       (progn
+                         (previous-line)
+                         (beginning-of-line)
+                         (point))
+                       (progn
+                         (forward-line 4)
+                         (point)))))
+
+      (goto-char (point-min))
+      (when (re-search-forward
+            (format "\\label{%s}" label) nil t)
+       (throw 'result (buffer-substring
+                       (progn
+                         (previous-line)
+                         (beginning-of-line)
+                         (point))
+                       (progn
+                         (forward-line 4)
+                         (point)))))
+
+      (goto-char (point-min))
+      (when (re-search-forward
+            (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t)
+       (throw 'result (buffer-substring
+                       (progn
+                         (previous-line)
+                         (beginning-of-line)
+                         (point))
+                       (progn
+                         (forward-line 4)
+                         (point)))))
+
+      (goto-char (point-min))
+      (when (re-search-forward
+            (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t)
+       (throw 'result (buffer-substring
+                       (progn
+                         (previous-line)
+                         (beginning-of-line)
+                         (point))
+                       (progn
+                         (forward-line 4)
+                         (point)))))
+      (throw 'result "!!! NO CONTEXT FOUND !!!"))))
+
+
+(defun org-ref-link-message ()
+  "Print a minibuffer message about the link that point is on."
+  (interactive)
+  (save-restriction
+    (widen)
+    (when (eq major-mode 'org-mode)
+      (let* ((object (org-element-context))
+            (type (org-element-property :type object)))
+       (save-excursion
+         (cond
+          ;; cite links
+          ((-contains? org-ref-cite-types type)
+           (message (org-ref-get-citation-string-at-point)))
+
+          ;; message some context about the label we are referring to
+          ((string= type "ref")
+           (message "%scount: %s"
+                    (org-ref-get-label-context
+                     (org-element-property :path object))
+                    (org-ref-count-labels
+                     (org-element-property :path object))))
+
+          ((string= type "eqref")
+           (message "%scount: %s"
+                    (org-ref-get-label-context
+                     (org-element-property :path object))
+                    (org-ref-count-labels
+                     (org-element-property :path object))))
+
+          ;; message the count
+          ((string= type "label")
+           (let ((count (org-ref-count-labels
+                         (org-element-property :path object))))
+             ;; get plurality on occurrence correct
+             (message (concat
+                       (number-to-string count)
+                       " occurence"
+                       (when (or (= count 0)
+                                 (> count 1))
+                         "s")))))
+
+          ((string= type "custom-id")
+           (save-excursion
+             (org-open-link-from-string
+              (format "[[#%s]]" (org-element-property :path object)))
+             (message "%s" (org-get-heading))))
+
+          ;; check if the bibliography files exist.
+          ((string= type "bibliography")
+           (let* ((bibfile)
+                  ;; object is the link you clicked on
+                  (object (org-element-context))
+                  (link-string (org-element-property :path object))
+                  (link-string-beginning)
+                  (link-string-end))
+             (save-excursion
+               (goto-char (org-element-property :begin object))
+               (search-forward link-string nil nil 1)
+               (setq link-string-beginning (match-beginning 0))
+               (setq link-string-end (match-end 0)))
+
+             ;; make sure we are in link and not before the :
+             (when (> link-string-beginning (point))
+               (goto-char link-string-beginning))
+
+             (let (key-beginning key-end)
+               ;; now if we have comma separated bibliographies
+               ;; we find the one clicked on. we want to
+               ;; search forward to next comma from point
+               (save-excursion
+                 (if (search-forward "," link-string-end 1 1)
+                     (setq key-end (- (match-end 0) 1)) ; we found a match
+                   (setq key-end (point)))) ; no comma found so take the point
+
+               ;; and backward to previous comma from point
+               (save-excursion
+                 (if (search-backward "," link-string-beginning 1 1)
+                     (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
+                   (setq key-beginning (point)))) ; no match found
+               ;; save the key we clicked on.
+               (setq bibfile
+                     (org-ref-strip-string
+                      (buffer-substring key-beginning key-end)))
+               (if (file-exists-p bibfile)
+                   (message "%s exists." bibfile)
+                 (message "!!! %s NOT FOUND !!!" bibfile)))))))))))
+
+;; ** aliases
+(defalias 'oro 'org-ref-open-citation-at-point)
+(defalias 'orc 'org-ref-citation-at-point)
+(defalias 'orp 'org-ref-open-pdf-at-point)
+(defalias 'oru 'org-ref-open-url-at-point)
+(defalias 'orn 'org-ref-open-notes-at-point)
+(defalias 'ornr 'org-ref-open-notes-from-reftex)
+
+(defalias 'orib 'org-ref-insert-bibliography-link)
+(defalias 'oric 'org-ref-insert-cite-link)
+(defalias 'orir 'org-ref-insert-ref-link)
+(defalias 'orsl 'org-ref-store-bibtex-entry-link)
+
+(defalias 'orcb 'org-ref-clean-bibtex-entry)
+
+;; * Helm bibtex setup
+
+(setq helm-bibtex-additional-search-fields '(keywords))
+
+(defun helm-bibtex-candidates-formatter (candidates source)
+  "Formats BibTeX entries for display in results list.
+Argument CANDIDATES helm candidates.
+Argument SOURCE the helm source."
+  (cl-loop
+   with width = (with-helm-window (helm-bibtex-window-width))
+   for entry in candidates
+   for entry = (cdr entry)
+   for entry-key = (helm-bibtex-get-value "=key=" entry)
+   if (assoc-string "author" entry 'case-fold)
+     for fields = '("author" "title" "year" "=has-pdf=" "=has-note=" "=type=")
+   else
+     for fields = '("editor" "title" "year" "=has-pdf=" "=has-note=" "=type=")
+   for fields = (--map (helm-bibtex-clean-string
+                        (helm-bibtex-get-value it entry " "))
+                       fields)
+   for fields = (-update-at 0 'helm-bibtex-shorten-authors fields)
+   for fields = (append fields
+                        (list  (or (helm-bibtex-get-value "keywords" entry)
+                                   "" )))
+   collect
+   (cons (s-format "$0 $1 $2 $3 $4$5 $6" 'elt
+                   (-zip-with (lambda (f w) (truncate-string-to-width f w 0 ?\s))
+                              fields (list 36 (- width 85) 4 1 1 7 7)))
+         entry-key)))
+
+;; * org-ref bibtex keywords
+;; adapted from bibtex-utils.el
+;; these are candidates for selecting keywords/tags
+(defun org-ref-bibtex-keywords ()
+  "Get keywords defined in current bibtex file.
+These are in the keywords field, and are comma or semicolon separated."
+  (save-excursion
+    (goto-char (point-min))
+    (let (keywords kstring)
+      (while (re-search-forward "^\\s-*keywords.*{\\([^}]+\\)}" nil t)
+        ;; TWS - remove newlines/multiple spaces:
+       (setq kstring (replace-regexp-in-string "[ \t\n]+" " " (match-string 1)))
+       (mapc
+        (lambda (v)
+          (add-to-list 'keywords v t))
+        (split-string kstring "\\(,\\|;\\)[ \n]*\\|{\\|}" t)))
+      keywords)))
+
+
+(defun org-ref-set-bibtex-keywords (keywords &optional arg)
+  "Add KEYWORDS to a bibtex entry.
+If KEYWORDS is a list, it is converted to a comma-separated
+string.  The KEYWORDS are added to the beginning of the
+field.  Otherwise KEYWORDS should be a string of comma-separate
+keywords.  Optional argument ARG prefix arg to replace keywords."
+  (interactive "sKeywords: \nP")
+  (bibtex-set-field
+   "keywords"
+   (if arg
+       ;; replace with arg
+       (if (listp keywords)
+          (mapconcat 'identity keywords ", ")
+        keywords)
+     ;; else concatentate
+     (concat
+      (if (listp keywords)
+         (mapconcat 'identity keywords ", ")
+        keywords)
+      (when (not (string= "" (bibtex-autokey-get-field "keywords")))
+       (concat ", "  (bibtex-autokey-get-field "keywords"))))))
+  (save-buffer))
+
+
+(defun helm-tag-bibtex-entry ()
+  "Helm interface to add keywords to a bibtex entry.
+Run this with the point in a bibtex entry."
+  (interactive)
+  (let ((keyword-source `((name . "Existing keywords")
+                         (candidates . ,(org-ref-bibtex-keywords))
+                         (action . (lambda (candidate)
+                                     (org-ref-set-bibtex-keywords
+                                      (mapconcat
+                                       'identity
+                                       (helm-marked-candidates)
+                                       ", "))))))
+       (fallback-source `((name . "Add new keywords")
+                          (dummy)
+                          (action . (lambda (candidate)
+                                      (org-ref-set-bibtex-keywords helm-pattern)
+                                      )))))
+    (helm :sources '(keyword-source fallback-source))))
+
+(defun helm-bibtex-show-entry (key)
+  "Show the entry for KEY in the BibTeX file.
+The original function in `helm-bibtex' has a bug where it finds the
+first key that partially matches.  This version avoids that."
+  (catch 'break
+    (dolist (bibtex-file (if (listp helm-bibtex-bibliography)
+                             helm-bibtex-bibliography
+                           (list helm-bibtex-bibliography)))
+      (let ((buf (helm-bibtex-buffer-visiting bibtex-file))
+            (entries '()))
+        (find-file bibtex-file)
+        (bibtex-map-entries
+        (lambda (key start end)
+          (add-to-list 'entries (cons key start))))
+        (if (assoc key entries)
+           (progn
+             (goto-char (cdr (assoc key entries)))
+             (throw 'break t))
+          (unless buf
+            (kill-buffer)))))))
+
+(defun org-ref-helm-tag-entries (candidates)
+  "Set tags on selected bibtex entries from `helm-bibtex'.
+User is prompted for tags.  This function is called from `helm-bibtex'.
+Argument CANDIDATES helm candidates."
+  (message "")
+  (let ((keywords (read-string "Keywords (comma separated): ")))
+    (cl-loop for key in (helm-marked-candidates)
+            do
+            (save-window-excursion
+              (helm-bibtex-show-entry key)
+              (bibtex-set-field
+               "keywords"
+               (concat
+                keywords
+                ", " (bibtex-autokey-get-field "keywords")))
+              (save-buffer)))))
+
+(setq helm-source-bibtex
+      '((name                                      . "BibTeX entries")
+       (init                                      . helm-bibtex-init)
+       (candidates                                . helm-bibtex-candidates)
+       (filtered-candidate-transformer            . helm-bibtex-candidates-formatter)
+       (action . (("Insert citation"              . helm-bibtex-insert-citation)
+                  ("Show entry"                   . helm-bibtex-show-entry)
+                  ("Open PDF file (if present)"   . helm-bibtex-open-pdf)
+                  ("Open URL or DOI in browser"   . helm-bibtex-open-url-or-doi)
+                  ("Insert formatted reference"   . helm-bibtex-insert-reference)
+                  ("Insert BibTeX key"            . helm-bibtex-insert-key)
+                  ("Insert BibTeX entry"          . helm-bibtex-insert-bibtex)
+                  ("Attach PDF to email"          . helm-bibtex-add-PDF-attachment)
+                  ("Edit notes"                   . helm-bibtex-edit-notes)
+                   ("Add keywords to entries"      . org-ref-helm-tag-entries)
+                  ))))
+
+(defun helm-bibtex-format-org-ref (keys)
+  "Insert selected KEYS as cite link. Append KEYS if you are on a link.
+Technically, this function should return a string that is inserted by helm. This function does the insertion and gives helm an empty string to insert. This lets us handle appending to a link properly.
+
+In the helm-bibtex buffer, C-u will give you a helm menu to select a new link type for the selected entries.
+
+C-u C-u will change the key at point to the selected keys."
+  (let* ((object (org-element-context))
+        (last-char (save-excursion
+                     (when (org-element-property :end object)
+                       (goto-char (org-element-property :end object))
+                       (unless (bobp)
+                         (backward-char))
+                       (if (looking-at " ")
+                           " "
+                         "")))))
+    (cond
+     ;; case where we are in a link
+     ((and (equal (org-element-type object) 'link)
+          (-contains?
+           org-ref-cite-types
+           (org-element-property :type object)))
+      (cond
+       ;; no prefix. append keys
+       ((equal helm-current-prefix-arg nil)
+       (goto-char (org-element-property :end object))
+       (while (looking-back " ") (backward-char))
+       (insert (concat "," (mapconcat 'identity keys ","))))
+       ;; double prefix, replace key at point
+       ((equal helm-current-prefix-arg '(16))
+       (setf (buffer-substring
+              (org-element-property :begin object)
+              (org-element-property :end object))
+             (concat
+              (replace-regexp-in-string
+               (car (org-ref-get-bibtex-key-and-file)) ; key
+               (mapconcat 'identity keys ",")          ; new keys
+               (org-element-property :raw-link object))
+              ;; replace space at end to avoid collapsing into next word.
+              last-char))
+       ;; and we want to go to the end of the new link
+       (goto-char
+        (org-element-property :end (org-element-context))))
+       (t
+       (message "Not found"))))
+
+     ;; We are next to a link, and we want to append
+     ;; next to a link means one character back is on a link.
+     ((save-excursion
+       (unless (bobp) (backward-char))
+       (and (equal (org-element-type (org-element-context)) 'link)
+            (-contains?
+             org-ref-cite-types
+             (org-element-property :type (org-element-context)))))
+      (while (looking-back " ") (backward-char))
+      (insert (concat "," (mapconcat 'identity keys ","))))
+
+     ;; insert fresh link
+     (t
+      ;;(message-box "fresh link")
+      (insert
+       (concat (if (equal helm-current-prefix-arg '(4))
+                  (helm :sources `((name . "link types")
+                                   (candidates . ,org-ref-cite-types)
+                                   (action . (lambda (x) x))))
+               org-ref-default-citation-link)
+              ":"
+              (s-join "," keys))))))
+  ;; return empty string for helm
+  "")
+
+(setq helm-bibtex-format-citation-functions
+      '((org-mode . helm-bibtex-format-org-ref)))
+
+;;;###autoload
+(defun org-ref-helm-insert-cite-link (arg)
+  "org-ref function to use helm-bibtex to insert a citation link.
+With one prefix arg, insert a ref link.
+With two prefix args, insert a label link."
+  (interactive "P")
+  (cond
+   ((equal arg nil)
+     (let ((helm-bibtex-bibliography (org-ref-find-bibliography)))
+       (helm-bibtex)))
+   ((equal arg '(4))
+    (org-ref-helm-insert-ref-link))
+   ((equal arg '(16))
+    (org-ref-helm-insert-label-link))))
+
+
+;; add our own fallback entries where we want them. These appear in reverse order of adding in the menu
+(setq helm-bibtex-fallback-options
+      (-insert-at 1 '("Crossref" . "http://search.crossref.org/?q=%s") helm-bibtex-fallback-options))
+
+(setq helm-bibtex-fallback-options
+      (-insert-at
+       1
+       '("Scopus" . "http://www.scopus.com/scopus/search/submit/xadvanced.url?searchfield=TITLE-ABS-KEY(%s)")
+       helm-bibtex-fallback-options))
+
+(setq helm-bibtex-fallback-options
+      (-insert-at 1 '("WOS" . "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary") helm-bibtex-fallback-options))
+
+(defun org-ref-get-citation-string-at-point ()
+  "Get a string of a formatted citation."
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+        (bibfile (cdr results)))
+    (if bibfile
+       (save-excursion
+         (with-temp-buffer
+           (insert-file-contents bibfile)
+            (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+           (bibtex-search-entry key)
+           (org-ref-bib-citation)))
+      "!!! No entry found !!!" )))
+
+
+(defun org-ref-cite-candidates ()
+  "Generate the list of possible candidates for click actions on a cite link.
+Checks for pdf and doi, and add appropriate functions."
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+         (pdf-file (funcall org-ref-get-pdf-filename-function key))
+         (bibfile (cdr results))
+        (url (save-excursion
+               (with-temp-buffer
+                 (insert-file-contents bibfile)
+                  (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+                 (bibtex-search-entry key)
+                 (bibtex-autokey-get-field "url"))))
+        (doi (save-excursion
+               (with-temp-buffer
+                 (insert-file-contents bibfile)
+                  (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
+                 (bibtex-search-entry key)
+                 ;; I like this better than bibtex-url which does not always find
+                 ;; the urls
+                 (bibtex-autokey-get-field "doi"))))
+        (candidates `(("Quit" . org-ref-citation-at-point)
+                      ("Open bibtex entry" . org-ref-open-citation-at-point))))
+    ;; for some reason, when there is no doi or url, they are returned as "". I
+    ;; prefer nil so we correct this here.
+    (when (string= doi "") (setq doi nil))
+    (when (string= url "") (setq url nil))
+
+    ;; Conditional pdf functions
+    (if (file-exists-p pdf-file)
+       (add-to-list
+        'candidates
+        '("Open pdf" . org-ref-open-pdf-at-point)
+        t)
+      (add-to-list
+       'candidates
+       '("Try to get pdf" . (lambda ()
+                             (save-window-excursion
+                               (org-ref-open-citation-at-point)
+                                (bibtex-beginning-of-entry)
+                               (doi-utils-get-bibtex-entry-pdf))))
+       t))
+
+
+    (add-to-list
+     'candidates
+     '("Open notes" . org-ref-open-notes-at-point)
+     t)
+
+    ;; conditional url and doi functions
+    (when (or url doi)
+      (add-to-list
+       'candidates
+       '("Open in browser" . org-ref-open-url-at-point)
+       t))
+
+    (when doi
+      (mapc (lambda (x)
+             (add-to-list 'candidates x t))
+           `(("WOS" . org-ref-wos-at-point)
+             ("Related articles in WOS" . org-ref-wos-related-at-point)
+             ("Citing articles in WOS" . org-ref-wos-citing-at-point)
+             ("Google Scholar" . org-ref-google-scholar-at-point)
+             ("Pubmed" . org-ref-pubmed-at-point)
+             ("Crossref" . org-ref-crossref-at-point)
+             )))
+
+    (add-to-list
+     'candidates
+     '("Copy formatted citation to clipboard" . org-ref-copy-entry-as-summary)
+     t)
+
+    (add-to-list
+     'candidates
+     '("Copy key to clipboard" . (lambda ()
+                                 (kill-new
+                                  (car (org-ref-get-bibtex-key-and-file)))))
+     t)
+
+    (add-to-list
+     'candidates
+     '("Copy bibtex entry to file" . org-ref-copy-entry-at-point-to-file)
+     t)
+
+    (add-to-list
+     'candidates
+     '("Email bibtex entry and pdf" . (lambda ()
+                 (save-excursion
+                   (org-ref-open-citation-at-point)
+                   (email-bibtex-entry))))
+     t)
+  ;; finally return a numbered list of the candidates
+  (cl-loop for i from 0
+          for cell in candidates
+          collect (cons (format "%2s. %s" i (car cell))
+                        (cdr cell)))))
+
+
+(defvar org-ref-helm-user-candidates '()
+  "List of user-defined candidates to act when clicking on a cite link.
+This is a list of cons cells '((\"description\" . action)). The action function should not take an argument, and should assume point is on the cite key of interest.")
+
+;; example of adding your own function
+(add-to-list
+ 'org-ref-helm-user-candidates
+ '("Open pdf in emacs" . (lambda ()
+                          (find-file
+                           (concat
+                            org-ref-pdf-directory
+                            (car (org-ref-get-bibtex-key-and-file))
+                            ".pdf"))))
+ t)
+
+;;;###autoload
+(defun org-ref-cite-click-helm (key)
+  "Open helm for actions on a cite link.
+subtle points.
+
+1. get name and candidates before entering helm because we need
+the org-buffer.
+
+2. switch back to the org buffer before evaluating the
+action.  most of them need the point and buffer.
+
+KEY is returned for the selected item(s) in helm."
+  (interactive)
+  (let ((name (org-ref-get-citation-string-at-point))
+       (candidates (org-ref-cite-candidates))
+       (cb (current-buffer)))
+
+    (helm :sources `(((name . ,name)
+                     (candidates . ,candidates)
+                     (action . (lambda (f)
+                                 (switch-to-buffer cb)
+                                 (funcall f))))
+                    ((name . "User functions")
+                     (candidates . ,org-ref-helm-user-candidates)
+                     (action . (lambda (f)
+                                 (switch-to-buffer cb)
+                                 (funcall f))))
+                    ))))
+
+;; * Hydra menus in org-ref
+
+(when (featurep 'hydra)
+  (require 'hydra)
+  (setq hydra-is-helpful t)
+
+  (defhydra org-ref-cite-hydra (:color blue)
+    "
+_p_: Open pdf     _w_: WOS          _g_: Google Scholar _K_: Copy citation to clipboard
+_u_: Open url     _r_: WOS related  _P_: Pubmed         _k_: Copy key to clipboard
+_n_: Open notes   _c_: WOS citing   _C_: Crossref       _f_: Copy bibtex entry to file
+_o_: Open entry   _e_: Email entry and pdf
+"
+    ("o" org-ref-open-citation-at-point nil)
+    ("p" org-ref-open-pdf-at-point nil)
+    ("n" org-ref-open-notes-at-point nil)
+    ("u" org-ref-open-url-at-point nil)
+    ("w" org-ref-wos-at-point nil)
+    ("r" org-ref-wos-related-at-point nil)
+    ("c" org-ref-wos-citing-at-point nil)
+    ("g" org-ref-google-scholar-at-point nil)
+    ("P" org-ref-pubmed-at-point nil)
+    ("C" org-ref-crossref-at-point nil)
+    ("K" org-ref-copy-entry-as-summary nil)
+    ("k" (progn
+          (kill-new
+           (car (org-ref-get-bibtex-key-and-file)))) nil)
+    ("f" org-ref-copy-entry-at-point-to-file nil)
+
+    ("e" (save-excursion
+          (org-ref-open-citation-at-point)
+          (email-bibtex-entry)) nil)))
+
+;; * org-ref-help
+(defun org-ref-help ()
+  "Open the org-ref manual."
+  (interactive)
+  (find-file (expand-file-name
+             "org-ref.org"
+             (file-name-directory
+              (find-library-name "org-ref")))))
+
+;; * org-ref menu
+(defun org-ref-org-menu ()
+  "Add org-ref menu to the Org menu."
+
+  (easy-menu-change
+   '("Org") "org-ref"
+   '( ["Insert citation" org-ref-helm-insert-cite-link]
+      ["Insert ref" org-ref-helm-insert-ref-link]
+      ["Insert label" org-ref-helm-insert-label-link]
+      "--"
+      ["List of figures" org-ref-list-of-figures]
+      ["List of tables" org-ref-list-of-tables]
+      ["Extract bibtex entries" org-ref-extract-bibtex-entries]
+      ["Check org-file" org-ref]
+      "--"
+      ["Help" org-ref-help]
+      ["Customize org-ref" (customize-group 'org-ref)])
+   "Show/Hide")
+
+  (easy-menu-change '("Org") "--" nil "Show/Hide"))
+
+(add-hook 'org-mode-hook 'org-ref-org-menu)
+
+;; * The end
+(provide 'org-ref)
+
+;;; org-ref.el ends here
diff --git a/org-ref.org b/org-ref.org
deleted file mode 100644 (file)
index 6124b7f..0000000
+++ /dev/null
@@ -1,3670 +0,0 @@
-#+TITLE: Org-ref - The best reference handling for org-mode
-#+AUTHOR: John Kitchin
-#+DATE: April 29, 2014
-
-* Introduction
-
-This document is an experiment at creating a literate program to provide similar features as reftex for org-mode referencing. These features include:
-
-1. using completion to create links
-2. storing links to places,
-3. Clickable links that do useful things
-4. Exportable links to LaTeX
-5. Utility functions for dealing with bibtex files and org-files
-
-Some additional features include
-1. Get minibuffer messages for the cite/ref/label link under point
-
-With helm integration (default) you can:
-
-1. C-c ] to insert a citation link
-  in helm-bibtex
-   - Enter to insert or append citation(s)
-   - C-u Enter to insert an alternative cite link
-   - C-u C-u Enter to replace the citation at point
-2. C-u C-c ] to insert a ref link with helm completion
-3. C-u C-u C-c ] to insert a label with completion
-4. M-x org-ref to get a helm completion buffer with link checks, utilities and export options
-
-** Header
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-;;; org-ref.el --- setup bibliography, cite, ref and label org-mode links.
-
-;; Copyright(C) 2014 John Kitchin
-
-;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
-;; This file is not currently part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
-
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program ; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;;
-;; Lisp code to setup bibliography cite, ref and label org-mode links.  also
-;; sets up reftex and helm for org-mode citations. The links are clickable and
-;; do things that are useful. You should really read org-ref.org for details.
-;;
-;; Package-Requires: ((dash) (helm) (helm-bibtex))
-#+END_SRC
-
-** requires
-The only external require is reftex-cite
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(require 'reftex-cite)
-(require 'dash)
-(require 'helm)
-(require 'helm-bibtex)
-(require 'org)
-(require 'cl-lib)
-#+END_SRC
-
-** Custom variables
-There are some variables needed later to tell this library where you store your pdf files, where your notes file is, and your default bibliography. This variable is similar to the reftex-default-bibliography. I do not remember why I made it separate.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defgroup org-ref nil
-  "customization group for org-ref")
-
-(defcustom org-ref-bibliography-notes
-  nil
-  "filename to where you will put all your notes about an entry in
-  the default bibliography."
-  :type 'file
-  :group 'org-ref)
-
-(defcustom org-ref-default-bibliography
-  nil
-  "list of bibtex files to search for. You should use full-paths for each file."
-  :type '(repeat :tag "List of bibtex files" file)
-  :group 'org-ref)
-
-(defcustom org-ref-pdf-directory
-  nil
-  "directory where pdfs are stored by key. put a trailing / in"
-  :type 'directory
-  :group 'org-ref)
-
-(defcustom org-ref-default-citation-link
-  "cite"
-  "The default type of citation link to use"
-  :type 'string
-  :group 'org-ref)
-
-(defcustom org-ref-insert-cite-key
-  "C-c ]"
-  "Keyboard shortcut to insert a citation."
-  :type 'string
-  :group 'org-ref)
-
-(defcustom org-ref-bibliography-entry-format
-  '(("article" . "%a, %t, <i>%j</i>, <b>%v(%n)</b>, %p (%y). <a href=\"%U\">link</a>. <a href=\"http://dx.doi.org/%D\">doi</a>.")
-
-    ("book" . "%a, %t, %u (%y).")
-
-    ("proceedings" . "%e, %t in %S, %u (%y).")
-
-    ("inproceedings" . "%a, %t, %p, in %b, edited by %e, %u (%y)"))
-
-  "string to format an entry. Just the reference, no numbering at the beginning, etc... see the `org-ref-reftex-format-citation' docstring for the escape codes."
-  :type 'string
-  :group 'org-ref)
-
-(defcustom org-ref-open-notes-function
-  (lambda ()
-    (org-show-entry)
-    (show-branches)
-    (show-children)
-    (org-cycle '(64))
-    ;;(org-tree-to-indirect-buffer)
-    (outline-previous-visible-heading 1)
-    (recenter-top-bottom 0))
-  "User-defined way to open a notes entry. This is excecuted after the entry is found, with the cursor at the beginning of the headline. The default setting fully expands the notes, and moves the headline to the top of the buffer"
-:type 'function
-:group 'org-ref)
-
-
-(defcustom org-ref-open-pdf-function
-   'org-ref-open-pdf-at-point
-"User-defined function to open a pdf from a link. The function must get the key at point, and derive a path to the pdf file, then open it. The default function is `org-ref-open-pdf-at-point'."
-  :type 'function
-  :group 'org-ref)
-
-
-(defcustom org-ref-insert-cite-function
-  'org-ref-helm-insert-cite-link
-  "Function to call to insert citation links. The default is `org-ref-helm-insert-cite-link' which uses `helm-bibtex'. org-ref modifies helm-bibtex a little bit to give org-mode citations, and to reorder default actions. You may use `org-ref-insert-cite-link' if you like the reftex interface."
- :type 'function
- :group 'org-ref)
-
-
-(defcustom org-ref-cite-onclick-function
-  'org-ref-cite-click-helm
-  "Function that runs when you click on a cite link. The function must take no arguments. You may also use `org-ref-cite-onclick-minibuffer-menu' if you do not like helm."
- :type 'function
- :group 'org-ref)
-
-(defcustom org-ref-show-citation-on-enter t
-  "If non-nil add a hook function to show the citation summary in
-  the minibuffer just by putting the cursor in a link"
- :group 'org-ref)
-
-#+END_SRC
-
-This next variable determines the citation types that are available in org-ref. Links for each one are automatically generated, and completion functions are automatically generated. Users may add to this list in their own init files.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defcustom org-ref-cite-types
-  '("cite" "nocite" ;; the default latex cite commands
-    ;; natbib cite commands, http://ctan.unixbrain.com/macros/latex/contrib/natbib/natnotes.pdf
-    "citet" "citet*" "citep" "citep*"
-    "citealt" "citealt*" "citealp" "citealp*"
-    "citenum" "citetext"
-    "citeauthor" "citeauthor*"
-    "citeyear" "citeyear*"
-    "Citet" "Citep" "Citealt" "Citealp" "Citeauthor"
-    ;; biblatex commands
-    ;; http://ctan.mirrorcatalogs.com/macros/latex/contrib/biblatex/doc/biblatex.pdf
-    "Cite"
-    "parencite" "Parencite"
-    "footcite" "footcitetext"
-    "textcite" "Textcite"
-    "smartcite" "Smartcite"
-    "cite*" "parencite*" "supercite"
-    "autocite" "Autocite" "autocite*" "Autocite*"
-    "Citeauthor*"
-    "citetitle" "citetitle*"
-    "citedate" "citedate*"
-    "citeurl"
-    "fullcite" "footfullcite"
-    ;; "volcite" "Volcite" cannot support the syntax
-    "notecite" "Notecite"
-    "pnotecite" "Pnotecite"
-    "fnotecite"
-    ;; multicites. Very limited support for these.
-    "cites" "Cites" "parencites" "Parencites"
-    "footcites" "footcitetexts"
-    "smartcites" "Smartcites" "textcites" "Textcites"
-    "supercites" "autocites" "Autocites"
-    ;; for the bibentry package
-    "bibentry"
-    )
-  "List of citation types known in org-ref"
-  :type '(repeat :tag "List of citation types" string)
-  :group 'org-ref)
-#+END_SRC
-
-We need a hook variable to store user-defined bibtex entry cleaning functions
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defcustom org-ref-clean-bibtex-entry-hook nil
-  "Hook that is run in org-ref-clean-bibtex-entry. The functions should take no arguments, and operate on the bibtex entry at point."
-  :group 'org-ref
-  :type 'hook)
-#+END_SRC
-
-** Program variables
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defvar org-ref-bibliography-files
-  nil
-  "variable to hold bibliography files to be searched")
-#+END_SRC
-
-** org-mode / reftex setup
-
-We setup reftex here. We use a custom insert cite link function defined here: [[*org-ref-insert-cite-link][org-ref-insert-cite-link]]. We setup reftex to use our org citation format.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(require 'reftex)
-(defun org-mode-reftex-setup ()
-    (and (buffer-file-name)
-         (file-exists-p (buffer-file-name))
-        (global-auto-revert-mode t)
-        ;; I do not remember why I put this next line in. It doesn't
-        ;; work for org-files. Nothing very bad happens, but it gives
-        ;; an annoying error. Commenting it out for now.
-         ;(reftex-parse-all
-        )
-    (make-local-variable 'reftex-cite-format)
-    (setq reftex-cite-format 'org))
-
-;; define key for inserting citations
-(define-key org-mode-map
-  (kbd org-ref-insert-cite-key)
-  org-ref-insert-cite-function)
-
-(add-hook 'org-mode-hook 'org-mode-reftex-setup)
-
-(eval-after-load 'reftex-vars
-  '(progn
-      (add-to-list 'reftex-cite-format-builtin
-                   '(org "Org-mode citation"
-                         ((?\C-m . "cite:%l")     ; default
-                         (?d . ",%l")            ; for appending
-                         (?a . "autocite:%l")
-                         (?t . "citet:%l")
-                         (?T . "citet*:%l")
-                         (?p . "citep:%l")
-                         (?P . "citep*:%l")
-                         (?h . "citeauthor:%l")
-                         (?H . "citeauthor*:%l")
-                         (?y . "citeyear:%l")
-                         (?x . "citetext:%l")
-                         (?n . "nocite:%l")
-                         )))))
-#+END_SRC
-
-You may want to add new formats to the reftex-cite-format-builtin variable. Here is an example of adding two new formats. Note that this does not create the links.
-
-#+BEGIN_SRC emacs-lisp :tangle no
-;; add new format
-(setf (nth 2 (assoc 'org reftex-cite-format-builtin))
-      (append (nth 2 (assoc 'org reftex-cite-format-builtin)) '((?W  . "textcite:%l")
-            (?z  . "newcite:%l"))))
-#+END_SRC
-
-You can define a new citation link like this:
-#+BEGIN_SRC emacs-lisp :tangle no
-(org-ref-define-citation-link "citez" ?z)
-#+END_SRC
-
-** Messages for link at cursor
-Here we setup code that shows you a context message for the element under the cursor when emacs is idle.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defvar org-ref-message-timer nil
-  "Variable to store the link message timer in.")
-
-
-(defun org-ref-show-link-messages ()
-  "Turn on link messages. You will see a message in the
-minibuffer when on a cite, ref or label link."
-  (interactive)
-  (or org-ref-message-timer
-      (setq org-ref-message-timer
-           (run-with-idle-timer 0.5 t 'org-ref-link-message))))
-
-
-(defun org-ref-cancel-link-messages ()
-  "Stop showing messages in minibuffer when on a link."
-  (interactive)
-  (cancel-timer org-ref-message-timer)
-  (setq org-ref-message-timer nil))
-
-
-(when org-ref-show-citation-on-enter
-  (org-ref-show-link-messages))
-
-;; this approach caused the selected region to not be highlighted any more.
-; (add-hook 'post-command-hook 'org-ref-link-message))
-; (remove-hook 'post-command-hook 'org-ref-link-message))
-#+END_SRC
-
-** Messages for context under mouse pointer
-Sometimes, when reading a document, I actually use the mouse more than the cursor. This code enables the mouse cursor to trigger a message in the minibuffer about what is under the cursor. I run this on a timer.
-
-The basic idea here is to get the mouse position, and if we can determine there is a character that (point) can move to, we move (point) and run the org-ref-link-message function. Since this runs on a timer, we store the last mouse position, and only run the function when the mouse has moved to avoid getting messages every time the timer runs.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defvar org-ref-last-mouse-pos nil
- "Stores last mouse position for use in `org-ref-mouse-message'.")
-
-(defun org-ref-can-move-p ()
-  "See if a character is under the mouse. If so return the position for `goto-char'."
-  (let* ((line (cddr org-ref-last-mouse-pos))
-        (col  (cadr org-ref-last-mouse-pos)))
-    (save-excursion
-      (goto-char (window-start))
-      (forward-line line)
-      (if
-         (> (- (line-end-position) (line-beginning-position)) col)
-         (progn  (forward-char col) (point))
-       nil))))
-
-
-(defun org-ref-mouse-message ()
-  "Display message for link under mouse cursor"
-  (interactive)
-  (when (not (equal (mouse-position) org-ref-last-mouse-pos))
-    (setq org-ref-last-mouse-pos (mouse-position))
-    (let ((p (org-ref-can-move-p)))
-      (when p
-         (save-excursion
-           (goto-char p)
-           (org-ref-link-message))))))
-
-
-(defvar org-ref-message-timer-mouse nil
-  "Store mouse timer.")
-
-
-(defvar org-ref-mouse-message-interval 0.5
-  "How often to run the mouse message timer in seconds")
-
-
-(defun org-ref-mouse-messages-on ()
-  "Turn on mouse messages."
-  (interactive)
-  (or org-ref-message-timer-mouse
-      (setq org-ref-message-timer-mouse
-           (run-at-time "0.5 sec"
-                        org-ref-mouse-message-interval
-                        'org-ref-mouse-message))))
-
-
-(defun org-ref-mouse-messages-off ()
-  "Turn off mouse messages"
-  (interactive)
-  (cancel-timer org-ref-message-timer-mouse)
-  (setq org-ref-message-timer-mouse nil)
-  (message "Mouse messages are off"))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-mouse-messages-off
-
-** Color-coded links
-Here we make the org-ref links a different color.
-
-citations are green
-refs are blue
-labels are black
-
-mailto:john
-
-cite:sokalski-2012-optim-ta,zhang-2011-spatial-tio2,li-2012-heter-ceram,li-2013-photoc
-
-cite*:sokalski-2012-optim-ta,zhang-2011-spatial-tio2,li-2012-heter-ceram,li-2013-photoc
-
-citenum:sokalski-2012-optim-ta,zhang-2011-spatial-tio2,li-2012-heter-ceram,li-2013-photoc
-
-ref:test
-
-label:test
-
-#+BEGIN_SRC emacs-lisp
-(defcustom org-ref-colorize-links
-  t
-  "When non-nil, change colors of links"
-  :group 'org-ref)
-
-(defcustom org-ref-cite-color
-  "forest green"
-  "Color of cite like links"
-  :group 'org-ref)
-
-
-(defcustom org-ref-ref-color
-  "dark red"
-  "Color of ref like links"
-  :group 'org-ref)
-
-
-(defcustom org-ref-label-color
-  "black"
-  "Color of label links"
-  :group 'org-ref)
-
-
-(defvar org-ref-cite-re nil
- "regexp for cite links")
-
-
-(setq org-ref-cite-re
-      (concat "\\(" (mapconcat
-                    (lambda (x)
-                      (replace-regexp-in-string "\*" "\\\\*" x)
-                      )
-                    org-ref-cite-types "\\|") "\\)"
-  ":\\([a-zA-Z0-9-_:]*,?\\)*"))
-
-
-(setq org-ref-label-re
-      "label:\\([a-zA-Z0-9-_:]*,?\\)*")
-
-
-(setq org-ref-ref-re
-      "ref:\\([a-zA-Z0-9-_:]*,?\\)*")
-
-
-(defface org-ref-cite-face
-  `((t (:inherit org-link :foreground ,org-ref-cite-color)))
-  "Color for cite-like links in org-ref.")
-
-
-(defface org-ref-label-face
-  `((t (:inherit org-link :foreground ,org-ref-label-color)))
-  "Color for ref links in org-ref.")
-
-
-(defface org-ref-ref-face
-  `((t (:inherit org-link :foreground ,org-ref-ref-color)))
-  "Face for ref links in org-ref.")
-
-
-(when org-ref-colorize-links
-  (highlight-regexp org-ref-cite-re 'org-ref-cite-face)
-  (highlight-regexp org-ref-label-re 'org-ref-label-face)
-  (highlight-regexp org-ref-ref-re 'org-ref-ref-face))
-#+END_SRC
-
-#+RESULTS:
-
-
-* Links
-Most of this library is the creation of functional links to help with references and citations.
-** General utilities
-We need several general utilities for this module. They are organized here. We frequently need to remove white space from the front and back of a string. Here we do that for a string.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-strip-string (string)
-  "strip leading and trailing whitespace from the string"
-  (replace-regexp-in-string
-   (concat search-whitespace-regexp "$" ) ""
-   (replace-regexp-in-string
-    (concat "^" search-whitespace-regexp ) "" string)))
-#+END_SRC
-
-It is helpful to make the previous function operate on a list of strings here.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-split-and-strip-string (string)
-  "split key-string and strip keys. Assumes the key-string is comma delimited"
-  (mapcar 'org-ref-strip-string (split-string string ",")))
-#+END_SRC
-
-** bibliography and bibliographystyle
-*** An html bibliography
-
-Reftex is no longer being developed. I want a url and doi option for formatting, so I am modifying this [[file:emacs-24.3/lisp/textmodes/reftex-cite.el::(defun%20reftex-format-citation%20(entry%20format)][function]] from reftex-cite to provide that. We need to modify the reftex-get-bib-field code a bit to remove enclosing braces and quotes so we can make nice looking links.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-reftex-get-bib-field (field entry &optional format)
-  "similar to reftex-get-bib-field, but removes enclosing braces and quotes"
-  (let ((result))
-    (setq result (reftex-get-bib-field field entry format))
-    (when (and (not (string= result "")) (string= "{" (substring result 0 1)))
-      (setq result (substring result 1 -1)))
-    (when (and (not (string= result "")) (string= "\"" (substring result 0 1)))
-      (setq result (substring result 1 -1)))
-      result))
-
-(defun org-ref-reftex-format-citation (entry format)
-  "return a formatted string for the bibtex entry (from bibtex-parse-entry) according
-to the format argument. The format is a string with these percent escapes.
-
-In the format, the following percent escapes will be expanded.
-
-%l   The BibTeX label of the citation.
-%a   List of author names, see also `reftex-cite-punctuation'.
-%2a  Like %a, but abbreviate more than 2 authors like Jones et al.
-%A   First author name only.
-%e   Works like %a, but on list of editor names. (%2e and %E work a well)
-
-It is also possible to access all other BibTeX database fields:
-%b booktitle     %c chapter        %d edition    %h howpublished
-%i institution   %j journal        %k key        %m month
-%n number        %o organization   %p pages      %P first page
-%r address       %s school         %u publisher  %t title
-%v volume        %y year
-%B booktitle, abbreviated          %T title, abbreviated
-%U url
-%D doi
-%S series
-
-Usually, only %l is needed.  The other stuff is mainly for the echo area
-display, and for (setq reftex-comment-citations t).
-
-%< as a special operator kills punctuation and space around it after the
-string has been formatted.
-
-A pair of square brackets indicates an optional argument, and RefTeX
-will prompt for the values of these arguments.
-
-Beware that all this only works with BibTeX database files.  When
-citations are made from the \bibitems in an explicit thebibliography
-environment, only %l is available."
-  ;; Format a citation from the info in the BibTeX ENTRY
-
-  (unless (stringp format) (setq format "\\cite{%l}"))
-
-  (if (and reftex-comment-citations
-           (string-match "%l" reftex-cite-comment-format))
-      (error "reftex-cite-comment-format contains invalid %%l"))
-
-  (while (string-match
-          "\\(\\`\\|[^%]\\)\\(\\(%\\([0-9]*\\)\\([a-zA-Z]\\)\\)[.,;: ]*\\)"
-          format)
-    (let ((n (string-to-number (match-string 4 format)))
-          (l (string-to-char (match-string 5 format)))
-          rpl b e)
-      (save-match-data
-        (setq rpl
-              (cond
-               ((= l ?l) (concat
-                          (org-ref-reftex-get-bib-field "&key" entry)
-                          (if reftex-comment-citations
-                              reftex-cite-comment-format
-                            "")))
-               ((= l ?a) (reftex-format-names
-                          (reftex-get-bib-names "author" entry)
-                          (or n 2)))
-               ((= l ?A) (car (reftex-get-bib-names "author" entry)))
-               ((= l ?b) (org-ref-reftex-get-bib-field "booktitle" entry "in: %s"))
-               ((= l ?B) (reftex-abbreviate-title
-                          (org-ref-reftex-get-bib-field "booktitle" entry "in: %s")))
-               ((= l ?c) (org-ref-reftex-get-bib-field "chapter" entry))
-               ((= l ?d) (org-ref-reftex-get-bib-field "edition" entry))
-               ((= l ?D) (org-ref-reftex-get-bib-field "doi" entry))
-               ((= l ?e) (reftex-format-names
-                          (reftex-get-bib-names "editor" entry)
-                          (or n 2)))
-               ((= l ?E) (car (reftex-get-bib-names "editor" entry)))
-               ((= l ?h) (org-ref-reftex-get-bib-field "howpublished" entry))
-               ((= l ?i) (org-ref-reftex-get-bib-field "institution" entry))
-               ((= l ?j) (org-ref-reftex-get-bib-field "journal" entry))
-               ((= l ?k) (org-ref-reftex-get-bib-field "key" entry))
-               ((= l ?m) (org-ref-reftex-get-bib-field "month" entry))
-               ((= l ?n) (org-ref-reftex-get-bib-field "number" entry))
-               ((= l ?o) (org-ref-reftex-get-bib-field "organization" entry))
-               ((= l ?p) (org-ref-reftex-get-bib-field "pages" entry))
-               ((= l ?P) (car (split-string
-                               (org-ref-reftex-get-bib-field "pages" entry)
-                               "[- .]+")))
-               ((= l ?s) (org-ref-reftex-get-bib-field "school" entry))
-               ((= l ?S) (org-ref-reftex-get-bib-field "series" entry))
-               ((= l ?u) (org-ref-reftex-get-bib-field "publisher" entry))
-               ((= l ?U) (org-ref-reftex-get-bib-field "url" entry))
-               ((= l ?r) (org-ref-reftex-get-bib-field "address" entry))
-              ;; strip enclosing brackets from title if they are there
-               ((= l ?t) (org-ref-reftex-get-bib-field "title" entry))
-               ((= l ?T) (reftex-abbreviate-title
-                          (org-ref-reftex-get-bib-field "title" entry)))
-               ((= l ?v) (org-ref-reftex-get-bib-field "volume" entry))
-               ((= l ?y) (org-ref-reftex-get-bib-field "year" entry)))))
-
-      (if (string= rpl "")
-          (setq b (match-beginning 2) e (match-end 2))
-        (setq b (match-beginning 3) e (match-end 3)))
-      (setq format (concat (substring format 0 b) rpl (substring format e)))))
-  (while (string-match "%%" format)
-    (setq format (replace-match "%" t t format)))
-  (while (string-match "[ ,.;:]*%<" format)
-    (setq format (replace-match "" t t format)))
-  ;; also replace carriage returns, tabs, and multiple whitespaces
-  (setq format (replace-regexp-in-string "\n\\|\t\\|\s+" " " format))
-  format)
-
-(defun org-ref-get-bibtex-entry-citation (key)
-  "returns a string for the bibliography entry corresponding to key, and formatted according to the type in `org-ref-bibliography-entry-format'"
-
-  (let ((org-ref-bibliography-files (org-ref-find-bibliography))
-       (file) (entry) (bibtex-entry) (entry-type) (format))
-
-    (setq file (catch 'result
-                (cl-loop for file in org-ref-bibliography-files do
-                      (if (org-ref-key-in-file-p key (file-truename file))
-                          (throw 'result file)
-                        (message "%s not found in %s" key (file-truename file))))))
-
-    (with-temp-buffer
-      (insert-file-contents file)
-      (bibtex-search-entry key nil 0)
-      (setq bibtex-entry (bibtex-parse-entry))
-      (setq entry-type (downcase (cdr (assoc "=type=" bibtex-entry))))
-      (setq format (cdr (assoc entry-type org-ref-bibliography-entry-format)))
-      (if format
-         (setq entry  (org-ref-reftex-format-citation bibtex-entry format))
-       (save-restriction
-         (bibtex-narrow-to-entry)
-         (setq entry (buffer-string)))))
-    entry))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-reftex-format-citation
-
-Here is how to use the function. You call it with point in an entry in a bibtex file.
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(let((org-ref-bibliography-entry-format   "%a, %t, <i>%j</i>, <b>%v(%n)</b>, %p (%y). <a href=\"%U\">link</a>. <a href=\"http://dx.doi.org/%D\">doi</a>."))
-  (org-ref-get-bibtex-entry-citation  "armiento-2014-high"))
-#+END_SRC
-#+RESULTS:
-: Armiento, Kozinsky, Hautier, , Fornari \& Ceder, High-throughput screening of perovskite alloys for  piezoelectric performance and thermodynamic  stability, <i>Phys. Rev. B</i>, <b>89()</b>, 134103 (2014). <a href="http://link.aps.org/doi/10.1103/PhysRevB.89.134103">link</a>. <a href="http://dx.doi.org/10.1103/PhysRevB.89.134103">doi</a>.
-
-I am not sure why full author names are not used.
-
-This code provides some functions to generate a simple sorted bibliography in html. First we get all the keys in the buffer.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-bibtex-keys ()
-  "Return a list of unique keys in the buffer."
-  (let ((keys '()))
-    (org-element-map (org-element-parse-buffer) 'link
-      (lambda (link)
-       (let ((plist (nth 1 link)))
-         (when (-contains? org-ref-cite-types (plist-get plist ':type))
-           (dolist
-               (key
-                (org-ref-split-and-strip-string (plist-get plist ':path)))
-             (when (not (-contains? keys key))
-               (setq keys (append keys (list key))))))))
-      ;; set with-affiliated to get keys in captions
-      nil nil nil t)
-    ;; Sort keys alphabetically
-    (setq keys (cl-sort keys 'string-lessp :key 'downcase))
-    keys))
-#+END_SRC
-
-This function gets the html for one entry.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-bibtex-entry-html (key)
-  "returns an html string for the bibliography entry corresponding to key"
-
-  (format "<li><a id=\"%s\">[%s] %s</a></li>" key key (org-ref-get-bibtex-entry-citation key)))
-#+END_SRC
-
-Now, we map over the whole list of keys, and the whole bibliography, formatted as an unordered list.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-html-bibliography ()
-  "Create an html bibliography when there are keys"
-  (let ((keys (org-ref-get-bibtex-keys)))
-    (when keys
-      (concat "<h1>Bibliography</h1>
-<ul>"
-             (mapconcat (lambda (x) (org-ref-get-bibtex-entry-html x)) keys "\n")
-             "\n</ul>"))))
-#+END_SRC
-
-I do not have plans to make a numbered bibliography with numbered citations anytime soon. This will require changing the way the citation links are exported, and keeping track of the numbers.
-
-*** An org bibliography
-You can export an org-file to an org-file or org-buffer (org-org-epxort-as-org). In this case, it would be useful convert the cite links to links to custom_ids, and the bibliography link to a first-level heading Bibliography with org-bibtex like headings for each entry. This code should enable this. Right now, it does not appear to work for org export though.
-
-First, we get the string for a single entry.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-bibtex-entry-org (key)
-  "returns an org string for the bibliography entry corresponding to key"
-  (let ((org-ref-bibliography-files (org-ref-find-bibliography))
-       (file) (entry) (bibtex-entry) (entry-type) (format))
-
-    (setq file (catch 'result
-                (cl-loop for file in org-ref-bibliography-files do
-                      (if (org-ref-key-in-file-p key (file-truename file))
-                          (throw 'result file)
-                        (message "%s not found in %s" key (file-truename file))))))
-
-    (with-temp-buffer
-      (insert-file-contents file)
-      (bibtex-search-entry key nil 0)
-      (setq entry (bibtex-parse-entry))
-      (format "** %s - %s
-  :PROPERTIES:
-  %s
-  :END:
-" (org-ref-reftex-get-bib-field "author" entry)
-(org-ref-reftex-get-bib-field "title" entry)
-(concat "   :CUSTOM_ID: " (org-ref-reftex-get-bib-field "=key=" entry) "\n"
-       (mapconcat (lambda (element) (format "   :%s: %s"
-                                            (upcase (car element))
-                                            (cdr element)))
-                  entry
-                  "\n"))))))
-#+END_SRC
-
-Now, we loop over the keys, and combine all the entries into a bibliography.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-org-bibliography ()
-  "Create an org bibliography when there are keys"
-  (let ((keys (org-ref-get-bibtex-keys)))
-    (when keys
-      (concat "* Bibliography
-"
-             (mapconcat (lambda (x) (org-ref-get-bibtex-entry-org x)) keys "\n")
-             "\n"))))
-#+END_SRC
-
-*** An ascii bibliography
-
-This function gets the html for one entry.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-bibtex-entry-ascii (key)
-  "returns an ascii string for the bibliography entry corresponding to key"
-
-  (format "[%s] %s" key (org-ref-get-bibtex-entry-citation key)))
-#+END_SRC
-
-Now, we map over the whole list of keys, and the whole bibliography, formatted as an unordered list.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-ascii-bibliography ()
-  "Create an html bibliography when there are keys"
-  (let ((keys (org-ref-get-bibtex-keys)))
-    (when keys
-      (concat
-"Bibliography
-=============
-"
-             (mapconcat (lambda (x) (org-ref-get-bibtex-entry-ascii x)) keys "\n")
-             "\n"))))
-#+END_SRC
-
-
-*** the links
-We use a link for the bibliography so that we can click on it to open the bibliography file. The link may have more than one bibliography file in it, separated by commas. Clicking opens the file under the cursor. The bibliographies should be full filenames with the bib extension. Clicking on this link makes reftex-default-bibliography local and sets it to the list of files in the link. We need this to use reftex's searching capability.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type "bibliography"
-                  ;; this code is run on clicking. The bibliography
-                  ;; may contain multiple files. this code finds the
-                  ;; one you clicked on and opens it.
-                  (lambda (link-string)
-                      ;; get link-string boundaries
-                      ;; we have to go to the beginning of the line, and then search forward
-
-                    (let* ((bibfile)
-                           ;; object is the link you clicked on
-                           (object (org-element-context))
-                           (link-string-beginning)
-                           (link-string-end))
-
-                    (save-excursion
-                      (goto-char (org-element-property :begin object))
-                      (search-forward link-string nil nil 1)
-                      (setq link-string-beginning (match-beginning 0))
-                      (setq link-string-end (match-end 0)))
-
-                      ;; We set the reftex-default-bibliography
-                      ;; here. it should be a local variable only in
-                      ;; the current buffer. We need this for using
-                      ;; reftex to do citations.
-                      (set (make-local-variable 'reftex-default-bibliography)
-                           (split-string (org-element-property :path object) ","))
-
-                      ;; now if we have comma separated bibliographies
-                      ;; we find the one clicked on. we want to
-                      ;; search forward to next comma from point
-                      (save-excursion
-                        (if (search-forward "," link-string-end 1 1)
-                            (setq key-end (- (match-end 0) 1)) ; we found a match
-                          (setq key-end (point)))) ; no comma found so take the point
-                      ;; and backward to previous comma from point
-                      (save-excursion
-                        (if (search-backward "," link-string-beginning 1 1)
-                            (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
-                          (setq key-beginning (point)))) ; no match found
-                      ;; save the key we clicked on.
-                      (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
-                      (find-file bibfile))) ; open file on click
-
-                    ;; formatting code
-                  (lambda (keyword desc format)
-                    (cond
-                     ((eq format 'org) (org-ref-get-org-bibliography))
-                      ((eq format 'ascii) (org-ref-get-ascii-bibliography))
-                     ((eq format 'html) (org-ref-get-html-bibliography))
-                     ((eq format 'latex)
-                      ;; write out the latex bibliography command
-                      (format "\\bibliography{%s}" (replace-regexp-in-string  "\\.bib" "" (mapconcat 'identity
-                                                                                                     (mapcar 'expand-file-name
-                                                                                                             (split-string keyword ","))
-                                                                                                     ",")))))))
-
-#+END_SRC
-
-Believe it or not, sometimes it makes sense /not/ to include the bibliography in a document (e.g. when you are required to submit references as a separate file). To generate the references,  in another file, you must make a little tex file with these contents, and then compile it.
-
-#+BEGIN_LaTeX
-  \input{project-description.bbl}
-#+END_LaTeX
-
-Here, we make a =nobibliography= link that acts like the bibliography, enables creation of the bbl file, but does not put an actual bibliography in the file.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type "nobibliography"
-                  ;; this code is run on clicking. The bibliography
-                  ;; may contain multiple files. this code finds the
-                  ;; one you clicked on and opens it.
-                  (lambda (link-string)
-                      ;; get link-string boundaries
-                      ;; we have to go to the beginning of the line, and then search forward
-
-                    (let* ((bibfile)
-                           ;; object is the link you clicked on
-                           (object (org-element-context))
-
-                           (link-string-beginning)
-                           (link-string-end))
-
-                    (save-excursion
-                      (goto-char (org-element-property :begin object))
-                      (search-forward link-string nil nil 1)
-                      (setq link-string-beginning (match-beginning 0))
-                      (setq link-string-end (match-end 0)))
-
-                      ;; We set the reftex-default-bibliography
-                      ;; here. it should be a local variable only in
-                      ;; the current buffer. We need this for using
-                      ;; reftex to do citations.
-                      (set (make-local-variable 'reftex-default-bibliography)
-                           (split-string (org-element-property :path object) ","))
-
-                      ;; now if we have comma separated bibliographies
-                      ;; we find the one clicked on. we want to
-                      ;; search forward to next comma from point
-                      (save-excursion
-                        (if (search-forward "," link-string-end 1 1)
-                            (setq key-end (- (match-end 0) 1)) ; we found a match
-                          (setq key-end (point)))) ; no comma found so take the point
-                      ;; and backward to previous comma from point
-                      (save-excursion
-                        (if (search-backward "," link-string-beginning 1 1)
-                            (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
-                          (setq key-beginning (point)))) ; no match found
-                      ;; save the key we clicked on.
-                      (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
-                      (find-file bibfile))) ; open file on click
-
-                    ;; formatting code
-                  (lambda (keyword desc format)
-                    (cond
-                     ((eq format 'org) (org-ref-get-org-bibliography))
-                      ((eq format 'ascii) (org-ref-get-ascii-bibliography))
-                     ((eq format 'html) (org-ref-get-html-bibliography))
-                     ((eq format 'latex)
-                      ;; write out the latex bibliography command
-
-;                     (format "{\\setbox0\\vbox{\\bibliography{%s}}}"
-;                             (replace-regexp-in-string  "\\.bib" "" (mapconcat 'identity
-;                                                                               (mapcar 'expand-file-name
-;                                                                                       (split-string keyword ","))
-;                                                                               ",")))
-
-                      (format "\\nobibliography{%s}"
-                              (replace-regexp-in-string  "\\.bib" "" (mapconcat 'identity
-                                                                                (mapcar 'expand-file-name
-                                                                                        (split-string keyword ","))
-                                                                                ",")))
-
-                      ))))
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type "printbibliography"
-                  (lambda (arg) (message "Nothing implemented for clicking here."))
-                  (lambda (keyword desc format)
-                    (cond
-                      ((eq format 'org) (org-ref-get-org-bibliography))
-                      ((eq format 'html) (org-ref-get-html-bibliography))
-                     ((eq format 'latex)
-                      ;; write out the biblatex bibliography command
-                      "\\printbibliography"))
-))
-#+END_SRC
-
-We also create a bibliographystyle link. There is nothing to do on clicking here, and we create it for consistency. This sets the style for latex export, so use something appropriate there, e.g. unsrt, plain, plainnat, ...
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type "bibliographystyle"
-                  (lambda (arg) (message "Nothing implemented for clicking here."))
-                  (lambda (keyword desc format)
-                    (cond
-                     ((eq format 'latex)
-                      ;; write out the latex bibliography command
-                      (format "\\bibliographystyle{%s}" keyword)))))
-#+END_SRC
-
-*** Completion for bibliography link
-It would be nice
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-bibliography-complete-link (&optional arg)
- (format "bibliography:%s" (read-file-name "enter file: " nil nil t)))
-
-(defun org-ref-insert-bibliography-link ()
-  "insert a bibliography with completion"
-  (interactive)
-  (insert (org-bibliography-complete-link)))
-#+END_SRC
-
-** addbibresource
-This is apparently used for biblatex.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type "addbibresource"
-                  ;; this code is run on clicking. The addbibresource
-                  ;; may contain multiple files. this code finds the
-                  ;; one you clicked on and opens it.
-                  (lambda (link-string)
-                      ;; get link-string boundaries
-                      ;; we have to go to the beginning of the line, and then search forward
-
-                    (let* ((bibfile)
-                           ;; object is the link you clicked on
-                           (object (org-element-context))
-
-                           (link-string-beginning)
-                           (link-string-end))
-
-                    (save-excursion
-                      (goto-char (org-element-property :begin object))
-                      (search-forward link-string nil nil 1)
-                      (setq link-string-beginning (match-beginning 0))
-                      (setq link-string-end (match-end 0)))
-
-                      ;; We set the reftex-default-addbibresource
-                      ;; here. it should be a local variable only in
-                      ;; the current buffer. We need this for using
-                      ;; reftex to do citations.
-                      (set (make-local-variable 'reftex-default-addbibresource)
-                           (split-string (org-element-property :path object) ","))
-
-                      ;; now if we have comma separated bibliographies
-                      ;; we find the one clicked on. we want to
-                      ;; search forward to next comma from point
-                      (save-excursion
-                        (if (search-forward "," link-string-end 1 1)
-                            (setq key-end (- (match-end 0) 1)) ; we found a match
-                          (setq key-end (point)))) ; no comma found so take the point
-                      ;; and backward to previous comma from point
-                      (save-excursion
-                        (if (search-backward "," link-string-beginning 1 1)
-                            (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
-                          (setq key-beginning (point)))) ; no match found
-                      ;; save the key we clicked on.
-                      (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
-                      (find-file bibfile))) ; open file on click
-
-                    ;; formatting code
-                  (lambda (keyword desc format)
-                    (cond
-                     ((eq format 'html) (format "")); no output for html
-                     ((eq format 'latex)
-                        ;; write out the latex addbibresource command
-                      (format "\\addbibresource{%s}" keyword)))))
-#+END_SRC
-
-** List of Figures
-
-In long documents, a list of figures is not uncommon. Here we create a clickable link that generates a temporary buffer containing a list of figures in the document, and their captions. We make a function that can be called interactively, and define a link type that is rendered in LaTeX to create the list of figures.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-list-of-figures (&optional arg)
-  "Generate buffer with list of figures in them"
-  (interactive)
-  (save-excursion (widen)
-  (let* ((c-b (buffer-name))
-        (counter 0)
-        (list-of-figures
-         (org-element-map (org-element-parse-buffer) 'link
-           (lambda (link)
-             "create a link for to the figure"
-             (when
-                 (and (string= (org-element-property :type link) "file")
-                      (string-match-p
-                       "[^.]*\\.\\(png\\|jpg\\|eps\\|pdf\\)$"
-                       (org-element-property :path link)))
-               (incf counter)
-
-               (let* ((start (org-element-property :begin link))
-                      (parent (car (cdr (org-element-property :parent link))))
-                      (caption (caaar (plist-get parent :caption)))
-                      (name (plist-get parent :name)))
-                 (if caption
-                     (format
-                      "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]] %s\n"
-                      c-b start counter (or name "") caption)
-                   (format
-                    "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]]\n"
-                    c-b start counter (or name "")))))))))
-    (switch-to-buffer "*List of Figures*")
-    (setq buffer-read-only nil)
-    (org-mode)
-    (erase-buffer)
-    (insert (mapconcat 'identity list-of-figures ""))
-    (setq buffer-read-only t)
-    (use-local-map (copy-keymap org-mode-map))
-    (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
-
-(org-add-link-type
- "list-of-figures"
- 'org-ref-list-of-figures ; on click
- (lambda (keyword desc format)
-   (cond
-    ((eq format 'latex)
-     (format "\\listoffigures")))))
-#+END_SRC
-
-** List of Tables
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-list-of-tables (&optional arg)
-  "Generate a buffer with a list of tables"
-  (interactive)
-  (save-excursion
-  (widen)
-  (let* ((c-b (buffer-name))
-        (counter 0)
-        (list-of-tables
-         (org-element-map (org-element-parse-buffer 'element) 'table
-           (lambda (table)
-             "create a link for to the table"
-             (incf counter)
-             (let ((start (org-element-property :begin table))
-                   (name  (org-element-property :name table))
-                   (caption (caaar (org-element-property :caption table))))
-               (if caption
-                   (format
-                    "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]] %s\n"
-                    c-b start counter (or name "") caption)
-                 (format
-                  "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]]\n"
-                  c-b start counter (or name ""))))))))
-    (switch-to-buffer "*List of Tables*")
-    (setq buffer-read-only nil)
-    (org-mode)
-    (erase-buffer)
-    (insert (mapconcat 'identity list-of-tables ""))
-    (setq buffer-read-only t)
-    (use-local-map (copy-keymap org-mode-map))
-    (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
-
-(org-add-link-type
- "list-of-tables"
- 'org-ref-list-of-tables
- (lambda (keyword desc format)
-   (cond
-    ((eq format 'latex)
-     (format "\\listoftables")))))
-#+END_SRC
-** label
-
-The label link provides a way to create labels in org-mode. We make it clickable because we want to make sure labels are unique. This code will tell you how many instances of a label are found.  We search for label links, LaTeX labels, and org-mode format for labels, tblnames too.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-count-labels (label)
-  "Counts number of matches for label in the document"
-  (+ (count-matches (format "label:%s\\b[^-:]" label) (point-min) (point-max))
-     ;; for tblname, it is not enough to get word boundary
-     ;; tab-little and tab-little-2 match then.
-     (count-matches (format "^#\\+tblname:\\s-*%s\\b[^-:]" label) (point-min) (point-max))
-     (count-matches (format "\\label{%s}" label) (point-min) (point-max))
-     ;; this is the org-format #+label:
-     (count-matches (format "^#\\+label:\\s-*%s\\b[^-:]" label) (point-min) (point-max))
-     (let ((custom-id-count 0))
-       (org-map-entries
-       (lambda ()
-         (when (string= label (org-entry-get (point) "CUSTOM_ID"))
-           (setq custom-id-count (+ 1 custom-id-count)))))
-       custom-id-count)))
-
-(org-add-link-type
- "label"
- (lambda (label)
-   "on clicking count the number of label tags used in the buffer. A number greater than one means multiple labels!"
-   (let ((count (org-ref-count-labels label)))
-   (message (format "%s occurence%s"
-                   count
-                   (if (or (= count 0)
-                             (> count 1))
-                       "s"
-                     ""))
-                   (org-ref-count-labels label))))
- (lambda (keyword desc format)
-   (cond
-    ((eq format 'html) (format "(<label>%s</label>)" path))
-    ((eq format 'latex)
-     (format "\\label{%s}" keyword)))))
-#+END_SRC
-
-We want to store links on labels, so you can put the cursor on the label, press C-c l, and later use C-c C-l to insert a link to the label. We also want to store links to tables with a table name, and for sections with CUSTOM_ID.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-label-store-link ()
-  "store a link to a label. The output will be a ref to that label"
-  ;; First we have to make sure we are on a label link.
-  (let* ((object (org-element-context)))
-    (when (and (equal (org-element-type object) 'link)
-               (equal (org-element-property :type object) "label"))
-      (org-store-link-props
-       :type "ref"
-       :link (concat "ref:" (org-element-property :path object))))
-
-    ;; Store link on table
-    (when (equal (org-element-type object) 'table)
-      (org-store-link-props
-       :type "ref"
-       :link (concat "ref:" (org-element-property :name object))))
-
-;; it turns out this does not work. you can already store a link to a heading with a CUSTOM_ID
-    ;; store link on heading with custom_id
-;    (when (and (equal (org-element-type object) 'headline)
-;             (org-entry-get (point) "CUSTOM_ID"))
-;      (org-store-link-props
-;       :type "ref"
-;       :link (concat "ref:" (org-entry-get (point) "CUSTOM_ID"))))
-
-    ;; and to #+label: lines
-    (when (and (equal (org-element-type object) 'paragraph)
-              (org-element-property :name object))
-      (org-store-link-props
-       :type "ref"
-       :link (concat "ref:" (org-element-property :name object))))
-))
-
-(add-hook 'org-store-link-functions 'org-label-store-link)
-#+END_SRC
-** ref
-
-The ref link allows you make links to labels. Clicking on the link takes you to the label, and provides a mark to go back to.
-
-At the moment, ref links are not usable for section links. You need [[#CUSTOM_ID]] type links.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(org-add-link-type
- "ref"
- (lambda (label)
-   "on clicking goto the label. Navigate back with C-c &"
-   (org-mark-ring-push)
-   ;; next search from beginning of the buffer
-
-   ;; it is possible you would not find the label if narrowing is in effect
-   (widen)
-
-   (unless
-       (or
-       ;; our label links
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "label:%s\\b" label) nil t))
-
-       ;; a latex label
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "\\label{%s}" label) nil t))
-
-       ;; #+label: name  org-definition
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
-
-       ;; org tblname
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t))
-
-;; Commented out because these ref links do not actually translate correctly in LaTeX.
-;; you need [[#label]] links.
-       ;; CUSTOM_ID
-;      (progn
-;        (goto-char (point-min))
-;        (re-search-forward (format ":CUSTOM_ID:\s-*\\(%s\\)" label) nil t))
-       )
-     ;; we did not find anything, so go back to where we came
-     (org-mark-ring-goto)
-     (error "%s not found" label))
-   (org-show-entry)
-   (message "go back with (org-mark-ring-goto) `C-c &`"))
- ;formatting
- (lambda (keyword desc format)
-   (cond
-    ((eq format 'html) (format "(<ref>%s</ref>)" path))
-    ((eq format 'latex)
-     (format "\\ref{%s}" keyword)))))
-#+END_SRC
-
-It would be nice to use completion to enter a ref link, where a list of labels is provided. The following code searches the buffer for org and latex labels, custom_ids, and table names as potential items to make a ref link to.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-org-labels ()
- "Return a list of #+LABEL: labels."
-  (save-excursion
-    (goto-char (point-min))
-    (let ((matches '()))
-      (while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" (point-max) t)
-       (add-to-list 'matches (match-string-no-properties 1) t))
-matches)))
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-custom-ids ()
- "Return a list of custom_id properties in the buffer."
- (let ((results '()) custom_id)
-   (org-map-entries
-    (lambda ()
-      (let ((custom_id (org-entry-get (point) "CUSTOM_ID")))
-       (when (not (null custom_id))
-         (setq results (append results (list custom_id)))))))
-results))
-#+END_SRC
-
-Here we get a list of the labels defined as raw latex labels, e.g. \label{eqtre}.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-latex-labels ()
-  (save-excursion
-    (goto-char (point-min))
-    (let ((matches '()))
-      (while (re-search-forward "\\\\label{\\([a-zA-z0-9:-]*\\)}" (point-max) t)
-       (add-to-list 'matches (match-string-no-properties 1) t))
-matches)))
-#+END_SRC
-
-Finally, we get the table names.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-tblnames ()
-  "Return list of table names in the buffer."
-  (org-element-map (org-element-parse-buffer 'element) 'table
-    (lambda (table)
-      (org-element-property :name table))))
-#+END_SRC
-
-Now, we can put all the labels together which will give us a list of candidates.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-get-labels ()
-  "Returns a list of labels in the buffer that you can make a ref link to.
-This is used to auto-complete ref links and in helm menus."
-  (save-excursion
-    (save-restriction
-      (widen)
-      (goto-char (point-min))
-      (let ((matches '()))
-        ;; these are the label:stuff  kinds
-       (while (re-search-forward "[^#+]label:\\([a-zA-z0-9:-]*\\)" (point-max) t)
-         (add-to-list 'matches (match-string-no-properties 1) t))
-       (append matches
-               (org-ref-get-org-labels)
-               (org-ref-get-latex-labels)
-               (org-ref-get-tblnames)
-               (org-ref-get-custom-ids))))))
-#+END_SRC
-
-Let us make a helm function to insert a label link. This will help you enter unique labels by showing matching labels until they are all gone and you are left with a unique one. If you are on a link, it means you want to replace it.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-helm-insert-label-link ()
-  "Insert a label link. helm just shows you what labels already exist.
-If you are on a label link, replace it."
-  (interactive)
-  (let* ((labels (org-ref-get-labels))
-        (cb (current-buffer)))
-    (helm :sources `(((name . "Existing labels")
-                     (candidates . ,labels)
-                     ;; default action is to open to the label
-                     (action . (lambda (label)
-                                 ;; unfortunately I do not have markers here
-                                 (org-open-link-from-string (format "ref:%s" label))))
-                     ;; if you select a label, replace current one
-                     (action . (lambda (label)
-                                 (switch-to-buffer ,cb)
-                                 (cond
-                                  ;;  no prefix or on a link
-                                  ((equal helm-current-prefix-arg nil)
-                                   (let* ((object (org-element-context))
-                                          (last-char (save-excursion
-                                                       (goto-char (org-element-property :end object))
-                                                       (backward-char)
-                                                       (if (looking-at " ")
-                                                           " "
-                                                         ""))))
-                                     (when (-contains? '("label")
-                                                       (org-element-property :type object))
-                                         ;; we are on a link, so replace it.
-                                       (setf
-                                          (buffer-substring
-                                           (org-element-property :begin object)
-                                           (org-element-property :end object))
-                                          (concat
-                                           (replace-regexp-in-string
-                                            (org-element-property :path object)
-                                            label
-                                            (org-element-property :raw-link object))
-                                           last-char)))))
-                                  ;; no prefix options defined
-                                  ))))
-                    ;; no matching selection creates a new label
-                    ((name . "Create new label")
-                     (dummy)
-                     ;; default action creates a new label, or replaces old one
-                     (action .  (lambda (label)
-                                  (switch-to-buffer ,cb)
-                                  (let* ((object (org-element-context))
-                                         (last-char (save-excursion
-                                                      (goto-char (org-element-property :end object))
-                                                      (backward-char)
-                                                      (if (looking-at " ")
-                                                          " "
-                                                        ""))))
-                                    (if (-contains? '("label")
-                                                    (org-element-property :type object))
-                                        ;; we are on a link, so replace it.
-                                        (setf
-                                         (buffer-substring
-                                          (org-element-property :begin object)
-                                          (org-element-property :end object))
-                                         (concat
-                                          (replace-regexp-in-string
-                                           (org-element-property :path object)
-                                           helm-pattern
-                                           (org-element-property :raw-link object))
-                                          last-char))
-                                      ;; new link
-                                      (insert
-                                       (concat
-                                        "label:"
-                                        (or label
-                                            helm-pattern))))))))))))
-#+END_SRC
-
-Now we create a completion function. This works from the org-machinery, e.g. if you type C-c C-l to insert a link, and use completion by pressing tab.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-complete-link (&optional arg)
-  "Completion function for ref links"
-  (let ((label))
-    (setq label (completing-read "label: " (org-ref-get-labels)))
-    (format "ref:%s" label)))
-#+END_SRC
-
-Alternatively, you may want to just call a function that inserts a link with completion:
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-insert-ref-link ()
- (interactive)
- (insert (org-ref-complete-link)))
-#+END_SRC
-
-Another alternative ref insertion is to use helm.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-helm-insert-ref-link ()
-  "Helm menu to insert ref links to labels in the document.
-If you are on link, replace with newly selected label.
-Use C-u to insert a different kind of ref link.
-Use C-u C-u to insert a [[#custom-id]] link
-"
-  (interactive)
-  (let* ((labels (org-ref-get-labels))
-        (bs (buffer-string))
-        (contexts (with-temp-buffer
-                    (insert bs)
-                    (mapcar 'org-ref-get-label-context labels)))
-        (cb (current-buffer)))
-
-    (helm :input (thing-at-point 'word)
-         :sources `(((name . "Available labels to ref")
-                     (candidates . ,(cl-loop for label in labels
-                                          for context in contexts
-                                          ;; we do some kludgy adding spaces
-                                          ;; and bars to make it "easier" to
-                                          ;; see in helm.
-                                          collect (cons (concat
-                                                         label "\n"
-                                                         (mapconcat
-                                                          (lambda (x)
-                                                            (concat "   |" x))
-                                                          (split-string context "\n")
-                                                          "\n"
-                                                          ) "\n\n") label)))
-                     ;; default action to replace or insert ref link.
-                     (action . (lambda (label)
-                                 (switch-to-buffer ,cb)
-
-                                 (cond
-                                  ;;  no prefix or on a link
-                                  ((equal helm-current-prefix-arg nil)
-                                   (let* ((object (org-element-context))
-                                          (last-char (save-excursion
-                                                       (goto-char (org-element-property :end object))
-                                                       (backward-char)
-                                                       (if (looking-at " ")
-                                                           " "
-                                                         ""))))
-                                     (if (-contains? '("ref" "eqref" "pageref" "nameref")
-                                                     (org-element-property :type object))
-                                         ;; we are on a link, so replace it.
-                                         (setf
-                                          (buffer-substring
-                                           (org-element-property :begin object)
-                                           (org-element-property :end object))
-                                          (concat
-                                           (replace-regexp-in-string
-                                            (org-element-property :path object)
-                                            label
-                                            (org-element-property :raw-link object))
-                                           last-char))
-                                       ;; insert a new link
-                                       (insert
-                                        (concat
-                                         "ref:" label))
-                                       )))
-                                  ;; one prefix, alternate ref link
-                                  ((equal helm-current-prefix-arg '(4))
-                                   (insert
-                                    (concat
-                                     (helm :sources '((name . "Ref link types")
-                                                      (candidates . ("ref" "eqref" "pageref" "nameref"))
-                                                      (action . (lambda (x) x))))
-                                     ":" label)))
-                                  ;; two prefixes, insert section custom-id link
-                                  ((equal helm-current-prefix-arg '(16))
-                                   (insert
-                                    (format "[[#%s]]" label)))
-                                  ))
-                             ))))))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-helm-insert-ref-link
-
-** pageref
-
-This refers to the page of a label in LaTeX.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(org-add-link-type
- "pageref"
- (lambda (label)
-   "on clicking goto the label. Navigate back with C-c &"
-   (org-mark-ring-push)
-   ;; next search from beginning of the buffer
-   (widen)
-   (unless
-       (or
-       ;; our label links
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "label:%s\\b" label) nil t))
-
-       ;; a latex label
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "\\label{%s}" label) nil t))
-
-       ;; #+label: name  org-definition
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
-
-       ;; org tblname
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t))
-
-;; Commented out because these ref links do not actually translate correctly in LaTeX.
-;; you need [[#label]] links.
-       ;; CUSTOM_ID
-;      (progn
-;        (goto-char (point-min))
-;        (re-search-forward (format ":CUSTOM_ID:\s-*\\(%s\\)" label) nil t))
-       )
-     ;; we did not find anything, so go back to where we came
-     (org-mark-ring-goto)
-     (error "%s not found" label))
-   (message "go back with (org-mark-ring-goto) `C-c &`"))
- ;formatting
- (lambda (keyword desc format)
-   (cond
-    ((eq format 'html) (format "(<pageref>%s</pageref>)" path))
-    ((eq format 'latex)
-     (format "\\pageref{%s}" keyword)))))
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-pageref-complete-link (&optional arg)
-  "Completion function for ref links"
-  (let ((label))
-    (setq label (completing-read "label: " (org-ref-get-labels)))
-    (format "ref:%s" label)))
-#+END_SRC
-
-Alternatively, you may want to just call a function that inserts a link with completion:
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-pageref-insert-ref-link ()
- (interactive)
- (insert (org-pageref-complete-link)))
-#+END_SRC
-
-** nameref
-
-The nameref link allows you make links to the text of a section with a label. Clicking on the link takes you to the label, and provides a mark to go back to. This only works if you put a raw latex label in the headline.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(org-add-link-type
- "nameref"
- (lambda (label)
-   "on clicking goto the label. Navigate back with C-c &"
-   (org-mark-ring-push)
-   ;; next search from beginning of the buffer
-   (widen)
-   (unless
-       (or
-       ;; a latex label
-       (progn
-         (goto-char (point-min))
-         (re-search-forward (format "\\label{%s}" label) nil t))
-       )
-     ;; we did not find anything, so go back to where we came
-     (org-mark-ring-goto)
-     (error "%s not found" label))
-   (message "go back with (org-mark-ring-goto) `C-c &`"))
- ;formatting
- (lambda (keyword desc format)
-   (cond
-    ((eq format 'html) (format "(<nameref>%s</nameref>)" path))
-    ((eq format 'latex)
-     (format "\\nameref{%s}" keyword)))))
-#+END_SRC
-
-** eqref
-This is just the LaTeX ref for equations. On export, the reference is enclosed in parentheses.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(org-add-link-type
- "eqref"
- (lambda (label)
-   "on clicking goto the label. Navigate back with C-c &"
-   (org-mark-ring-push)
-   ;; next search from beginning of the buffer
-   (widen)
-   (goto-char (point-min))
-   (unless
-       (or
-       ;; search forward for the first match
-       ;; our label links
-       (re-search-forward (format "label:%s" label) nil t)
-       ;; a latex label
-       (re-search-forward (format "\\label{%s}" label) nil t)
-       ;; #+label: name  org-definition
-       (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
-     (org-mark-ring-goto)
-     (error "%s not found" label))
-   (message "go back with (org-mark-ring-goto) `C-c &`"))
- ;formatting
- (lambda (keyword desc format)
-   (cond
-    ((eq format 'html) (format "(<eqref>%s</eqref>)" path))
-    ((eq format 'latex)
-     (format "\\eqref{%s}" keyword)))))
-#+END_SRC
-
-** cite
-This is the main reason this library exists. We want the following behavior. A cite link should be able to contain multiple bibtex keys. You should be able to click on the link, and get a brief citation of the entry for that key, and a menu of options to open the bibtex file, open a pdf if you have it, open your notes on the entry, or open a url if it exists. You should be able to insert new references onto an existing cite link, or create new ones easily. The following code implements these features.
-
-*** Implementing the click actions of cite
-
-**** Getting the key we clicked on
-The first thing we need is to get the bibtex key we clicked on.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-get-bibtex-key-under-cursor ()
-  "returns key under the bibtex cursor. We search forward from
-point to get a comma, or the end of the link, and then backwards
-to get a comma, or the beginning of the link. that delimits the
-keyword we clicked on. We also strip the text properties."
-  (interactive)
-  (let* ((object (org-element-context))
-        (link-string (org-element-property :path object)))
-    ;; you may click on the part before the citations. here we make
-    ;; sure to move to the beginning so you get the first citation.
-    (let ((cp (point)))
-      (goto-char (org-element-property :begin object))
-      (search-forward link-string (org-element-property :end object))
-      (goto-char (match-beginning 0))
-      ;; check if we clicked before the path and move as needed.
-      (unless (< cp (point))
-       (goto-char cp)))
-
-    (if (not (org-element-property :contents-begin object))
-       ;; this means no description in the link
-       (progn
-         ;; we need the link path start and end
-         (save-excursion
-           (goto-char (org-element-property :begin object))
-           (search-forward link-string nil nil 1)
-           (setq link-string-beginning (match-beginning 0))
-           (setq link-string-end (match-end 0)))
-
-         ;; The key is the text between commas, or the link boundaries
-         (save-excursion
-           (if (search-forward "," link-string-end t 1)
-               (setq key-end (- (match-end 0) 1)) ; we found a match
-             (setq key-end link-string-end))) ; no comma found so take the end
-         ;; and backward to previous comma from point which defines the start character
-         (save-excursion
-           (if (search-backward "," link-string-beginning 1 1)
-               (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
-             (setq key-beginning link-string-beginning))) ; no match found
-         ;; save the key we clicked on.
-         (setq bibtex-key (org-ref-strip-string (buffer-substring key-beginning key-end)))
-         (set-text-properties 0 (length bibtex-key) nil bibtex-key)
-         bibtex-key)
-      ;; link with description. assume only one key
-      link-string)))
-#+END_SRC
-
-We also need to find which bibliography file that key is in. For that, we need to know which bibliography files are referred to in the file. If none are specified with a bibliography link, we use the default bibliography. This function searches for a bibliography link, and then the LaTeX bibliography link. We also consider the addbibresource link which is used with biblatex.
-
-**** Getting the bibliographies
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-find-bibliography ()
-  "find the bibliography in the buffer.
-This function sets and returns cite-bibliography-files, which is a list of files
-either from bibliography:f1.bib,f2.bib
-\bibliography{f1,f2}
-internal bibliographies
-
-falling back to what the user has set in org-ref-default-bibliography
-"
-  (interactive)
-  (catch 'result
-    (save-excursion
-      (goto-char (point-min))
-      ;;  look for a bibliography link
-      (when (re-search-forward "\\<bibliography:\\([^\]\|\n]+\\)" nil t)
-       (setq org-ref-bibliography-files
-             (mapcar 'org-ref-strip-string (split-string (match-string 1) ",")))
-       (throw 'result org-ref-bibliography-files))
-
-
-      ;; we did not find a bibliography link. now look for \bibliography
-      (goto-char (point-min))
-      (when (re-search-forward "\\\\bibliography{\\([^}]+\\)}" nil t)
-       ;; split, and add .bib to each file
-       (setq org-ref-bibliography-files
-             (mapcar (lambda (x) (concat x ".bib"))
-                     (mapcar 'org-ref-strip-string
-                             (split-string (match-string 1) ","))))
-       (throw 'result org-ref-bibliography-files))
-
-      ;; no bibliography found. maybe we need a biblatex addbibresource
-      (goto-char (point-min))
-      ;;  look for a bibliography link
-      (when (re-search-forward "addbibresource:\\([^\]\|\n]+\\)" nil t)
-       (setq org-ref-bibliography-files
-             (mapcar 'org-ref-strip-string (split-string (match-string 1) ",")))
-       (throw 'result org-ref-bibliography-files))
-
-      ;; we did not find anything. use defaults
-      (setq org-ref-bibliography-files org-ref-default-bibliography)))
-
-    ;; set reftex-default-bibliography so we can search
-    (set (make-local-variable 'reftex-default-bibliography) org-ref-bibliography-files)
-    org-ref-bibliography-files)
-#+END_SRC
-
-**** Finding the bibliography file a key is in
-Now, we can see if an entry is in a file.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-key-in-file-p (key filename)
-  "determine if the key is in the file"
-  (interactive "skey: \nsFile: ")
-  (save-current-buffer
-    (let ((bibtex-files (list filename)))
-      (bibtex-search-entry key t))))
-#+END_SRC
-
-Finally, we want to know which file the key is in.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-bibtex-key-and-file (&optional key)
-  "returns the bibtex key and file that it is in. If no key is provided, get one under point"
- (interactive)
- (let ((org-ref-bibliography-files (org-ref-find-bibliography))
-       (file))
-   (unless key
-     (setq key (org-ref-get-bibtex-key-under-cursor)))
-   (setq file     (catch 'result
-                   (cl-loop for file in org-ref-bibliography-files do
-                         (if (org-ref-key-in-file-p key (file-truename file))
-                             (throw 'result file)))))
-   (cons key file)))
-#+END_SRC
-
-**** convenience functions to act on citation at point
-     :PROPERTIES:
-     :ID:       af0b2a82-a7c9-4c08-9dac-09f93abc4a92
-     :END:
-We need some convenience functions to open act on the citation at point. These will get the pdf, open the url, or open the notes.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-open-pdf-at-point ()
-  "open the pdf for bibtex key under point if it exists"
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file))
-        (key (car results))
-         (pdf-file (format (concat org-ref-pdf-directory "%s.pdf") key)))
-    (if (file-exists-p pdf-file)
-       (org-open-file pdf-file)
-(message "no pdf found for %s" key))))
-
-
-(defun org-ref-open-url-at-point ()
-  "open the url for bibtex key under point."
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file))
-        (key (car results))
-        (bibfile (cdr results)))
-    (save-excursion
-      (with-temp-buffer
-        (insert-file-contents bibfile)
-        (bibtex-search-entry key)
-        ;; I like this better than bibtex-url which does not always find
-        ;; the urls
-        (catch 'done
-          (let ((url (bibtex-autokey-get-field "url")))
-            (when  url
-              (browse-url url)
-              (throw 'done nil)))
-
-          (let ((doi (bibtex-autokey-get-field "doi")))
-            (when doi
-              (if (string-match "^http" doi)
-                  (browse-url doi)
-                (browse-url (format "http://dx.doi.org/%s" doi)))
-              (throw 'done nil))))))))
-
-
-(defun org-ref-open-notes-at-point ()
-  "open the notes for bibtex key under point."
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file))
-        (key (car results))
-        (bibfile (cdr results)))
-    (save-excursion
-      (with-temp-buffer
-        (insert-file-contents bibfile)
-        (bibtex-search-entry key)
-        (org-ref-open-bibtex-notes)))))
-
-
-(defun org-ref-citation-at-point ()
-  "give message of current citation at point"
-  (interactive)
-  (let* ((cb (current-buffer))
-       (results (org-ref-get-bibtex-key-and-file))
-       (key (car results))
-       (bibfile (cdr results)))
-    (message "%s" (progn
-                   (with-temp-buffer
-                      (insert-file-contents bibfile)
-                      (bibtex-search-entry key)
-                      (org-ref-bib-citation))))))
-
-
-(defun org-ref-open-citation-at-point ()
-  "open bibtex file to key at point"
-  (interactive)
-  (let* ((cb (current-buffer))
-       (results (org-ref-get-bibtex-key-and-file))
-       (key (car results))
-       (bibfile (cdr results)))
-    (find-file bibfile)
-    (bibtex-search-entry key)))
-#+END_SRC
-
-**** the actual minibuffer menu
-Now, we create the menu. This is a rewrite of the cite action. This makes the function extendable by users.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defvar org-ref-cite-menu-funcs '()
- "Functions to run on cite click menu. Each entry is a list of (key menu-name function).
-The function must take no arguments and work on the key at point. Do not modify this variable, it is set to empty in the menu click function, and functions are conditionally added to it.")
-
-
-(defvar org-ref-user-cite-menu-funcs
-  '(("C" "rossref" org-ref-crossref-at-point)
-    ("y" "Copy entry to file" org-ref-copy-entry-at-point-to-file)
-    ("s" "Copy summary" org-ref-copy-entry-as-summary))
-  "user-defined functions to run on bibtex key at point.")
-
-
-(defun org-ref-copy-entry-as-summary ()
-  "Copy the bibtex entry for the citation at point as a summary."
-  (interactive)
-    (save-window-excursion
-      (org-ref-open-citation-at-point)
-      (kill-new (org-ref-bib-citation))))
-
-
-(defun org-ref-copy-entry-at-point-to-file ()
-  "Copy the bibtex entry for the citation at point to NEW-FILE.
-Prompt for NEW-FILE includes bib files in org-ref-default-bibliography, and bib files in current working directory. You can also specify a new file."
-  (interactive)
-  (let ((new-file (ido-completing-read
-                  "Copy to bibfile: "
-                  (append org-ref-default-bibliography
-                          (f-entries "." (lambda (f) (f-ext? f "bib"))))))
-       (key (org-ref-get-bibtex-key-under-cursor)))
-    (save-window-excursion
-      (org-ref-open-citation-at-point)
-      (bibtex-copy-entry-as-kill))
-
-    (let ((bibtex-files (list (file-truename new-file))))
-      (if (assoc key (bibtex-global-key-alist))
-         (message "That key already exists in %s" new-file)
-       ;; add to file
-       (save-window-excursion
-         (find-file new-file)
-         (goto-char (point-max))
-          ;; make sure we are at the beginning of a line.
-         (unless (looking-at "^") (insert "\n\n"))
-         (bibtex-yank)
-         (save-buffer))))))
-
-
-(defun org-ref-get-doi-at-point ()
-  "Get doi for key at point."
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file))
-        (key (car results))
-        (bibfile (cdr results))
-         doi)
-    (save-excursion
-      (with-temp-buffer
-        (insert-file-contents bibfile)
-        (bibtex-search-entry key)
-       (setq doi (bibtex-autokey-get-field "doi"))
-       ;; in case doi is a url, remove the url part.
-       (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))))
-
-
-;; functions that operate on key at point for click menu
-(defun org-ref-wos-at-point ()
-  "open the doi in wos for bibtex key under point."
-  (interactive)
-  (doi-utils-wos (org-ref-get-doi-at-point)))
-
-
-(defun org-ref-wos-citing-at-point ()
-  "open the doi in wos citing articles for bibtex key under point."
-  (interactive)
-  (doi-utils-wos-citing (org-ref-get-doi-at-point)))
-
-
-(defun org-ref-wos-related-at-point ()
-  "open the doi in wos related articles for bibtex key under point."
-  (interactive)
-  (doi-utils-wos-related (org-ref-get-doi-at-point)))
-
-
-(defun org-ref-google-scholar-at-point ()
-  "open the doi in google scholar for bibtex key under point."
-  (interactive)
-  (doi-utils-google-scholar (org-ref-get-doi-at-point)))
-
-
-(defun org-ref-pubmed-at-point ()
-  "open the doi in pubmed for bibtex key under point."
-  (interactive)
-  (doi-utils-pubmed (org-ref-get-doi-at-point)))
-
-
-(defun org-ref-crossref-at-point ()
-  "open the doi in crossref for bibtex key under point."
-  (interactive)
-  (doi-utils-crossref (org-ref-get-doi-at-point)))
-
-
-(defun org-ref-cite-onclick-minibuffer-menu (&optional link-string)
-  "action when a cite link is clicked on.
-Provides a menu of context sensitive actions. If the bibtex entry has a pdf, you get an option to open it. If there is a doi, you get a lot of options."
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file))
-        (key (car results))
-         (pdf-file (format (concat org-ref-pdf-directory "%s.pdf") key))
-         (bibfile (cdr results))
-        (url (save-excursion
-               (with-temp-buffer
-                 (insert-file-contents bibfile)
-                 (bibtex-search-entry key)
-                 (bibtex-autokey-get-field "url"))))
-        (doi (save-excursion
-               (with-temp-buffer
-                 (insert-file-contents bibfile)
-                 (bibtex-search-entry key)
-                 ;; I like this better than bibtex-url which does not always find
-                 ;; the urls
-                 (bibtex-autokey-get-field "doi")))))
-
-    (when (string= "" doi) (setq doi nil))
-    (when (string= "" url) (setq url nil))
-    (setq org-ref-cite-menu-funcs '())
-
-    ;; open action
-    (when
-       bibfile
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       '("o" "pen" org-ref-open-citation-at-point)))
-
-    ;; pdf
-    (when (file-exists-p pdf-file)
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       `("p" "df" ,org-ref-open-pdf-function) t))
-
-    ;; notes
-    (add-to-list
-     'org-ref-cite-menu-funcs
-     '("n" "otes" org-ref-open-notes-at-point) t)
-
-    ;; url
-    (when (or url doi)
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       '("u" "rl" org-ref-open-url-at-point) t))
-
-    ;; doi funcs
-    (when doi
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       '("w" "os" org-ref-wos-at-point) t)
-
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       '("c" "iting" org-ref-wos-citing-at-point) t)
-
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       '("r" "elated" org-ref-wos-related-at-point) t)
-
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       '("g" "oogle scholar" org-ref-google-scholar-at-point) t)
-
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       '("P" "ubmed" org-ref-pubmed-at-point) t))
-
-    ;; add user functions
-    (dolist (tup org-ref-user-cite-menu-funcs)
-      (add-to-list
-       'org-ref-cite-menu-funcs
-       tup t))
-
-    ;; finally quit
-    (add-to-list
-     'org-ref-cite-menu-funcs
-     '("q" "uit" (lambda ())) t)
-
-    ;; now we make a menu
-    ;; construct menu string as a message
-    (message
-     (concat
-      (let* ((results (org-ref-get-bibtex-key-and-file))
-            (key (car results))
-            (bibfile (cdr results)))
-       (save-excursion
-         (with-temp-buffer
-           (insert-file-contents bibfile)
-           (bibtex-search-entry key)
-           (org-ref-bib-citation))))
-      "\n"
-      (mapconcat
-       (lambda (tup)
-        (concat "[" (elt tup 0) "]"
-                (elt tup 1) " "))
-       org-ref-cite-menu-funcs "")))
-    ;; get the input
-    (let* ((input (read-char-exclusive))
-          (choice (assoc
-                   (char-to-string input) org-ref-cite-menu-funcs)))
-      ;; now run the function (2nd element in choice)
-      (when choice
-       (funcall
-        (elt
-         choice
-         2))))))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-cite-onclick-minibuffer-menu
-
-*** A function to format a cite link
-
-Next, we define a formatting function for the cite link. This is done so that the cite link definition is very short, and easy to change. You just need to specify the functions in the definition. This function is deprecated. The formatting is defined later automatically.
-
-#+BEGIN_SRC emacs-lisp  :tangle no
-;(defun org-ref-cite-link-format (keyword desc format)
-;   (cond
-;    ((eq format 'html) (mapconcat (lambda (key) (format "<a name=\"#%s\">%s</a>" key key) (org-ref-split-and-strip-string keyword) ",")))
-;    ((eq format 'latex)
-;     (concat "\\cite" (when desc (format "[%s]" desc)) "{"
-;           (mapconcat (lambda (key) key) (org-ref-split-and-strip-string keyword) ",")
-;           "}"))))
-#+END_SRC
-
-*** The actual cite link
-Finally, we define the cite link. This is deprecated; the links are autogenerated later. This is here for memory.
-
-#+BEGIN_SRC emacs-lisp :tangle no
-;(org-add-link-type
-; "cite"
-; 'org-ref-cite-onclick-minibuffer-menu
-; 'org-ref-cite-link-format)
-#+END_SRC
-
-*** Automatic definition of the cite links
-There are many different kinds of citations in LaTeX, but they are all variants of a basic syntax of \citetype[optional text]{label1,label2}. Here we use lisp to generate the link definitions. We define a function that creates the code to create the link, and then we evaluate it. We also create the completion function for the new link, and add it to the list of known links.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defmacro org-ref-make-completion-function (type)
-  `(defun ,(intern (format "org-%s-complete-link" type)) (&optional arg)
-     (interactive)
-     (format "%s:%s"
-            ,type
-            (completing-read
-             "bibtex key: "
-             (let ((bibtex-files (org-ref-find-bibliography)))
-               (bibtex-global-key-alist))))))
-#+END_SRC
-
-We will want to generate formatting functions for each citation type. The reason for doing this is so we can on the fly change the formatting later.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defmacro org-ref-make-format-function (type)
-  `(defun ,(intern (format "org-ref-format-%s" type)) (keyword desc format)
-     (cond
-      ((eq format 'org)
-       (mapconcat
-       (lambda (key)
-         (format "[[#%s][%s]]" key key))
-       (org-ref-split-and-strip-string keyword) ","))
-
-      ((eq format 'ascii)
-       (concat "["
-              (mapconcat
-               (lambda (key)
-                 (format "%s" key))
-               (org-ref-split-and-strip-string keyword) ",") "]"))
-
-      ((eq format 'html)
-       (mapconcat
-       (lambda (key)
-         (format "<a href=\"#%s\">%s</a>" key key))
-       (org-ref-split-and-strip-string keyword) ","))
-
-      ((eq format 'latex)
-       (if (string= (substring type -1) "s")
-          ;; biblatex format for multicite commands, which all end in s. These are formated as \cites{key1}{key2}...
-          (concat "\\" ,type (mapconcat (lambda (key) (format "{%s}"  key))
-                                        (org-ref-split-and-strip-string keyword) ""))
-        ;; bibtex format
-       (concat "\\" ,type (when desc (org-ref-format-citation-description desc)) "{"
-              (mapconcat (lambda (key) key) (org-ref-split-and-strip-string keyword) ",")
-              "}")))
-      ;; for markdown we generate pandoc citations
-      ((eq format 'md)
-       (cond
-       (desc  ;; pre and or post text
-        (let* ((text (split-string desc "::"))
-               (pre (car text))
-               (post (cadr text)))
-          (concat
-           (format "[@%s," keyword)
-           (when pre (format " %s" pre))
-           (when post (format ", %s" post))
-           "]")))
-       (t
-        (format "[%s]"
-                (mapconcat
-                 (lambda (key) (concat "@" key))
-                 (org-ref-split-and-strip-string keyword)
-                 "; "))))))))
-#+END_SRC
-
-
-
-We create the links by mapping the function onto the list of defined link types.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-format-citation-description (desc)
-  "return formatted citation description. if the cite link has a description, it is optional text for the citation command. You can specify pre and post text by separating these with ::."
-  (interactive)
-  (cond
-   ((string-match "::" desc)
-    (format "[%s][%s]" (car (setq results (split-string desc "::"))) (cadr results)))
-   (t (format "[%s]" desc))))
-
-(defun org-ref-define-citation-link (type &optional key)
-  "add a citation link for org-ref. With optional key, set the reftex binding. For example:
-(org-ref-define-citation-link \"citez\" ?z) will create a new citez link, with reftex key of z,
-and the completion function."
-  (interactive "sCitation Type: \ncKey: ")
-
-  ;; create the formatting function
-  (eval `(org-ref-make-format-function ,type))
-
-  (eval-expression
-   `(org-add-link-type
-     ,type
-     org-ref-cite-onclick-function
-     (quote ,(intern (format "org-ref-format-%s" type)))))
-
-  ;; create the completion function
-  (eval `(org-ref-make-completion-function ,type))
-
-  ;; store new type so it works with adding citations, which checks
-  ;; for existence in this list
-  (add-to-list 'org-ref-cite-types type)
-
-  ;; and finally if a key is specified, we modify the reftex menu
-  (when key
-    (setf (nth 2 (assoc 'org reftex-cite-format-builtin))
-         (append (nth 2 (assoc 'org reftex-cite-format-builtin))
-                 `((,key  . ,(concat type ":%l")))))))
-
-;; create all the link types and their completion functions
-(mapcar 'org-ref-define-citation-link org-ref-cite-types)
-#+END_SRC
-
-*** org-ref-insert-cite-link
-We need a convenient method to insert links. In reftex you use the keystroke C-c ], which gives you a minibuffer to search the bibtex files from. This function is bound to that same keystroke here [[*org-mode%20/%20reftex%20setup][org-mode / reftex setup]]. This function will append to a cite link if you call it while on a link.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-insert-cite-link (alternative-cite)
-  "Insert a default citation link using reftex. If you are on a link, it
-appends to the end of the link, otherwise, a new link is
-inserted. Use a prefix arg to get a menu of citation types."
-  (interactive "P")
-  (org-ref-find-bibliography)
-  (let* ((object (org-element-context))
-        (link-string-beginning (org-element-property :begin object))
-        (link-string-end (org-element-property :end object))
-        (path (org-element-property :path object)))
-
-    (if (not alternative-cite)
-
-       (cond
-        ;; case where we are in a link
-        ((and (equal (org-element-type object) 'link)
-              (-contains? org-ref-cite-types (org-element-property :type object)))
-         (goto-char link-string-end)
-         ;; sometimes there are spaces at the end of the link
-         ;; this code moves point pack until no spaces are there
-         (while (looking-back " ") (backward-char))
-         (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ","))))
-
-        ;; We are next to a link, and we want to append
-        ((save-excursion
-           (backward-char)
-           (and (equal (org-element-type (org-element-context)) 'link)
-                (-contains? org-ref-cite-types (org-element-property :type (org-element-context)))))
-         (while (looking-back " ") (backward-char))
-         (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ","))))
-
-        ;; insert fresh link
-        (t
-         (insert
-          (concat org-ref-default-citation-link
-                  ":"
-                  (mapconcat 'identity (reftex-citation t) ",")))))
-
-      ;; you pressed a C-u so we run this code
-      (reftex-citation)))
-  )
-#+END_SRC
-cite:zhou-2004-first-lda-u,paier-2006-errat,boes-2015-estim-bulk
-
-
-#+RESULTS:
-: org-ref-insert-cite-link
-
-*** Completion in cite links
-If you know the specific bibtex key, you may like to use completion directly. You use this with the org-mode machinery and tab completion. Here is the prototypical completion function. These are now all created when the links are created.
-
-#+BEGIN_SRC emacs-lisp  :tangle no
-(defun org-cite-complete-link (&optional arg)
-  "Completion function for cite links"
-  (format "%s:%s"
-          org-ref-default-citation-link
-         (completing-read
-          "bibtex key: "
-          (let ((bibtex-files (org-ref-find-bibliography)))
-            (bibtex-global-key-alist)))))
-#+END_SRC
-
-Alternatively, you may shortcut the org-machinery with this command. You will be prompted for a citation type, and then offered key completion.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-insert-cite-with-completion (type)
-  "Insert a cite link with completion"
-  (interactive (list (ido-completing-read "Type: " org-ref-cite-types)))
-  (insert (funcall (intern (format "org-%s-complete-link" type)))))
-#+END_SRC
-
-** Storing links to a bibtex entry
-org-mode already defines a store link function for bibtex entries. It does not store the link I want though, it only stores a brief citation of the entry. I want a citation link. Here is a function to do that.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-store-bibtex-entry-link ()
-  "Save a citation link to the current bibtex entry. Saves in the default link type."
-  (interactive)
-  (let ((link (concat org-ref-default-citation-link
-                ":"
-                (save-excursion
-                  (bibtex-beginning-of-entry)
-                  (reftex-get-bib-field "=key=" (bibtex-parse-entry))))))
-    (message "saved %s" link)
-    (push (list link) org-stored-links)
-    (car org-stored-links)))
-#+END_SRC
-
-** Index entries
-org-ref minimally supports index entries. To make an index in a file, you should put in the LaTeX header these lines
-
-
-#+LATEX_HEADER: \usepackage{makeidx}
-#+LATEX_HEADER: \makeindex
-
-
-Finally, put \makeindex at the end of the document where you want the index to appear. You will need to run the makeindex program at an appropriate point in your LaTeX to pdf, or use ox-manuscript, which will do it for you.
-
-
-Use index links to create entries (see http://en.wikibooks.org/wiki/LaTeX/Indexing). Clicking on an index link runs occur on the buffer for the entry. The link exports to LaTeX. Some links may need to be enclosed in double brackets if they have spaces in them.
-
-
-index:hello
-index:hello!Peter
-[[index:hello!Sam@\textsl{Sam}]]
-[[index:Lin@\textbf{Lin}]]
-[[index:Joe|textit]]
-[[index:Lin@\textbf{Lin}]]
-[[index:Peter|see {hello}]]
-[[index:Jen|seealso{Jenny}]]
-
-index:encodings!input!cp850
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type
- "index"
- (lambda (path)
-   (occur path))
-
- (lambda (path desc format)
-   (cond
-    ((eq format 'latex)
-      (format "\\index{%s}" path)))))
-
-;; this will generate a temporary index of entries in the file.
-(org-add-link-type
- "printindex"
- (lambda (path)
-   (let ((*index-links* '())
-        (*initial-letters* '()))
-
-     ;; get links
-     (org-element-map (org-element-parse-buffer) 'link
-       (lambda (link)
-        (let ((type (nth 0 link))
-              (plist (nth 1 link)))
-
-          (when (equal (plist-get plist ':type) "index")
-            (add-to-list
-             '*index-links*
-             (cons (plist-get plist :path)
-                   (format
-                    "[[elisp:(progn (switch-to-buffer \"%s\") (goto-char %s))][%s]]"
-(current-buffer)
-                    (plist-get plist :begin)  ;; position of link
-                    ;; grab a description
-                    (save-excursion
-                      (goto-char (plist-get plist :begin))
-                      (if (thing-at-point 'sentence)
-                          ;; get a sentence
-                          (replace-regexp-in-string
-                           "\n" "" (thing-at-point 'sentence))
-                        ;; or call it a link
-                        "link")))))))))
-
-     ;; sort the links
-     (setq *index-links*  (cl-sort *index-links* 'string-lessp :key 'car))
-
-     ;; now first letters
-     (dolist (link *index-links*)
-       (add-to-list '*initial-letters* (substring (car link) 0 1) t))
-
-     ;; now create the index
-     (switch-to-buffer (get-buffer-create "*index*"))
-     (org-mode)
-     (erase-buffer)
-     (insert "#+TITLE: Index\n\n")
-     (dolist (letter *initial-letters*)
-       (insert (format "* %s\n" (upcase letter)))
-       ;; now process the links
-       (while (and
-              ,*index-links*
-              (string= letter (substring (car (car *index-links*)) 0 1)))
-        (let ((link (pop *index-links*)))
-          (insert (format "%s %s\n\n" (car link) (cdr link))))))
-     (switch-to-buffer "*index*")))
- ;; formatting
- (lambda (path desc format)
-   (cond
-    ((eq format 'latex)
-      (format "\\printindex")))))
-#+END_SRC
-
-#+RESULTS:
-| lambda | (path)             | (let ((*index-links* (quote nil)) (*initial-letters* (quote nil))) (org-element-map (org-element-parse-buffer) (quote link) (lambda (link) (let ((type (nth 0 link)) (plist (nth 1 link))) (when (equal (plist-get plist (quote :type)) index) (add-to-list (quote *index-links*) (cons (plist-get plist :path) (format [[elisp:(progn (switch-to-buffer "%s") (goto-char %s))][%s]] (current-buffer) (plist-get plist :begin) (save-excursion (goto-char (plist-get plist :begin)) (if (thing-at-point (quote sentence)) (replace-regexp-in-string \n  (thing-at-point (quote sentence))) link))))))))) (setq *index-links* (cl-sort *index-links* (quote string-lessp) :key (quote car))) (dolist (link *index-links*) (add-to-list (quote *initial-letters*) (substring (car link) 0 1) t)) (switch-to-buffer (get-buffer-create *index*)) (org-mode) (erase-buffer) (insert #+TITLE: Index\n\n) (dolist (letter *initial-letters*) (insert (format * %s\n (upcase letter))) (while (and *index-links* (string= letter (substring (car (car *index-links*)) 0 1))) (let ((link (pop *index-links*))) (insert (format %s %s\n\n (car link) (cdr link)))))) (switch-to-buffer *index*)) |
-| lambda | (path desc format) | (cond ((eq format (quote latex)) (format \printindex)))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
-
-** Glossary
-org-ref provides some minimal support for a glossary. See http://en.wikibooks.org/wiki/LaTeX/Glossary for details. You need to put these lines in the header.
-
-#+LATEX_HEADER: \usepackage{glossaries}
-#+LATEX_HEADER: \makeglossaries
-
-And at the end of the document put \makeglossaries.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type
- "newglossaryentry"
- nil ;; no follow action
- (lambda (path desc format)
-   (cond
-    ((eq format 'latex)
-     (format "\\newglossaryentry{%s}{%s}" path desc)))))
-
-
-;; link to entry
-(org-add-link-type
- "gls"
-  nil ;; no follow action
- (lambda (path desc format)
-   (cond
-    ((eq format 'latex)
-     (format "\\gls{%s}" path)))))
-
-;; plural
-(org-add-link-type
- "glspl"
-  nil ;; no follow action
- (lambda (path desc format)
-   (cond
-    ((eq format 'latex)
-     (format "\\glspl{%s}" path)))))
-
-;; capitalized link
-(org-add-link-type
- "Gls"
-  nil ;; no follow action
- (lambda (path desc format)
-   (cond
-    ((eq format 'latex)
-     (format "\\Gls{%s}" path)))))
-
-;; capitalized link
-(org-add-link-type
- "Glspl"
-  nil ;; no follow action
- (lambda (path desc format)
-   (cond
-    ((eq format 'latex)
-     (format "\\Glspl{%s}" path)))))
-#+END_SRC
-
-* Utilities
-** create simple text citation from bibtex entry
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-bib-citation ()
-  "From a bibtex entry, create and return a simple citation string.
-This assumes you are in an article."
-
-  (bibtex-beginning-of-entry)
-  (let* ((cb (current-buffer))
-        (bibtex-expand-strings t)
-        (entry (cl-loop for (key . value) in (bibtex-parse-entry t)
-                     collect (cons (downcase key) value)))
-        (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
-        (year  (reftex-get-bib-field "year" entry))
-        (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
-        (key (reftex-get-bib-field "=key=" entry))
-        (journal (reftex-get-bib-field "journal" entry))
-        (volume (reftex-get-bib-field "volume" entry))
-        (pages (reftex-get-bib-field "pages" entry))
-        (doi (reftex-get-bib-field "doi" entry))
-        (url (reftex-get-bib-field "url" entry))
-        )
-    ;;authors, "title", Journal, vol(iss):pages (year).
-    (format "%s, \"%s\", %s, %s:%s (%s)"
-           author title journal  volume pages year)))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-bib-citation
-
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-bib-html-citation ()
-  "from a bibtex entry, create and return a simple citation with html links."
-
-  (bibtex-beginning-of-entry)
-  (let* ((cb (current-buffer))
-        (bibtex-expand-strings t)
-        (entry (cl-loop for (key . value) in (bibtex-parse-entry t)
-                     collect (cons (downcase key) value)))
-        (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
-        (year  (reftex-get-bib-field "year" entry))
-        (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
-        (key (reftex-get-bib-field "=key=" entry))
-        (journal (reftex-get-bib-field "journal" entry))
-        (volume (reftex-get-bib-field "volume" entry))
-        (pages (reftex-get-bib-field "pages" entry))
-        (doi (reftex-get-bib-field "doi" entry))
-        (url (reftex-get-bib-field "url" entry))
-        )
-    ;;authors, "title", Journal, vol(iss):pages (year).
-    (concat (format "%s, \"%s\", %s, %s:%s (%s)."
-                   author title journal  volume pages year)
-           (when url (format " <a href=\"%s\">link</a>" url))
-           (when doi (format " <a href=\"http://dx.doi.org/%s\">doi</a>" doi)))
-    ))
-#+END_SRC
-
-** open pdf from bibtex
-We bind this to a key here: [[*key%20bindings%20for%20utilities][key bindings for utilities]].
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-open-bibtex-pdf ()
-  "open pdf for a bibtex entry, if it exists. assumes point is in
-the entry of interest in the bibfile. but does not check that."
-  (interactive)
-  (save-excursion
-    (bibtex-beginning-of-entry)
-    (let* ((bibtex-expand-strings t)
-           (entry (bibtex-parse-entry t))
-           (key (reftex-get-bib-field "=key=" entry))
-           (pdf (format (concat org-ref-pdf-directory "%s.pdf") key)))
-      (message "%s" pdf)
-      (if (file-exists-p pdf)
-          (org-open-link-from-string (format "[[file:%s]]" pdf))
-        (ding)))))
-#+END_SRC
-
-** open notes from bibtex
-We bind this to a key here [[*key%20bindings%20for%20utilities][key bindings for utilities]].
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-open-bibtex-notes ()
-  "from a bibtex entry, open the notes if they exist, and create a heading if they do not.
-
-I never did figure out how to use reftex to make this happen
-non-interactively. the reftex-format-citation function did not
-work perfectly; there were carriage returns in the strings, and
-it did not put the key where it needed to be. so, below I replace
-the carriage returns and extra spaces with a single space and
-construct the heading by hand."
-  (interactive)
-
-  (bibtex-beginning-of-entry)
-  (let* ((cb (current-buffer))
-        (bibtex-expand-strings t)
-        (entry (cl-loop for (key . value) in (bibtex-parse-entry t)
-                     collect (cons (downcase key) value)))
-        (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
-        (year  (reftex-get-bib-field "year" entry))
-        (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
-        (key (reftex-get-bib-field "=key=" entry))
-        (journal (reftex-get-bib-field "journal" entry))
-        (volume (reftex-get-bib-field "volume" entry))
-        (pages (reftex-get-bib-field "pages" entry))
-        (doi (reftex-get-bib-field "doi" entry))
-        (url (reftex-get-bib-field "url" entry))
-        )
-
-    ;; save key to clipboard to make saving pdf later easier by pasting.
-    (with-temp-buffer
-      (insert key)
-      (kill-ring-save (point-min) (point-max)))
-
-    ;; now look for entry in the notes file
-    (if  org-ref-bibliography-notes
-       (find-file-other-window org-ref-bibliography-notes)
-      (error "org-ref-bib-bibliography-notes is not set to anything"))
-
-    (goto-char (point-min))
-    ;; put new entry in notes if we don't find it.
-    (if (re-search-forward (format ":Custom_ID: %s$" key) nil 'end)
-       (funcall org-ref-open-notes-function)
-      ;; no entry found, so add one
-      (insert (format "\n** TODO %s - %s" year title))
-      (insert (format"
- :PROPERTIES:
-  :Custom_ID: %s
-  :AUTHOR: %s
-  :JOURNAL: %s
-  :YEAR: %s
-  :VOLUME: %s
-  :PAGES: %s
-  :DOI: %s
-  :URL: %s
- :END:
-[[cite:%s]] [[file:%s/%s.pdf][pdf]]\n\n"
-key author journal year volume pages doi url key org-ref-pdf-directory key))
-(save-buffer))))
-#+END_SRC
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-open-notes-from-reftex ()
-  "Call reftex, and open notes for selected entry."
-  (interactive)
-  (let ((bibtex-key )))
-
-    ;; now look for entry in the notes file
-    (if  org-ref-bibliography-notes
-       (find-file-other-window org-ref-bibliography-notes)
-      (error "org-ref-bib-bibliography-notes is not set to anything"))
-
-    (goto-char (point-min))
-
-    (re-search-forward (format
-                       ":Custom_ID: %s$"
-                       (first (reftex-citation t)) nil 'end))
-    (funcall org-ref-open-notes-function))
-#+END_SRC
-
-** open url in browser from bibtex
-
-We bind this to a key here [[*key%20bindings%20for%20utilities][key bindings for utilities]].
-
-+ This function may be duplicative of bibtex-url. But I think my function is better unless you do some complicated customization of bibtex-generate-url-list.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-open-in-browser ()
-  "Open the bibtex entry at point in a browser using the url field or doi field"
-(interactive)
-(save-excursion
-  (bibtex-beginning-of-entry)
-  (catch 'done
-    (let ((url (bibtex-autokey-get-field "url")))
-      (when  url
-        (browse-url url)
-        (throw 'done nil)))
-
-    (let ((doi (bibtex-autokey-get-field "doi")))
-      (when doi
-        (if (string-match "^http" doi)
-            (browse-url doi)
-          (browse-url (format "http://dx.doi.org/%s" doi)))
-        (throw 'done nil)))
-    (message "No url or doi found"))))
-#+END_SRC
-
-** citeulike
-   I discovered you could upload a bibtex entry to citeulike using http requests. The upload is actually done by a [[*The%20upload%20script][python script]], because it was easy to write. Here is the emacs command to do this. It is not a fast operation, and  do not use it frequently.
-
-*** function to upload bibtex to citeulike
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-upload-bibtex-entry-to-citeulike ()
-  "with point in  a bibtex entry get bibtex string and submit to citeulike.
-
-Relies on the python script /upload_bibtex_citeulike.py being in the user directory."
-  (interactive)
-  (message "uploading to citeulike")
-  (save-restriction
-    (bibtex-narrow-to-entry)
-    (let ((startpos (point-min))
-          (endpos (point-max))
-          (bibtex-string (buffer-string))
-          (script (concat "python " starter-kit-dir "/upload_bibtex_citeulike.py&")))
-      (with-temp-buffer (insert bibtex-string)
-                        (shell-command-on-region (point-min) (point-max) script t nil nil t)))))
-#+END_SRC
-
-*** The upload script
-Here is the python script for uploading.
-
-*************** TODO document how to get the cookies
-*************** END
-
-# :tangle upload_bibtex_citeulike.py
-#+BEGIN_SRC python
-#!python
-import pickle, requests, sys
-
-# reload cookies
-with open('c:/Users/jkitchin/Dropbox/blogofile-jkitchin.github.com/_blog/cookies.pckl', 'rb') as f:
-    cookies = pickle.load(f)
-
-url = 'http://www.citeulike.org/profile/jkitchin/import_do'
-
-bibtex = sys.stdin.read()
-
-data = {'pasted':bibtex,
-        'to_read':2,
-        'tag_parsing':'simple',
-        'strip_brackets':'no',
-        'update_id':'bib-key',
-        'btn_bibtex':'Import BibTeX file ...'}
-
-headers = {'content-type': 'multipart/form-data',
-           'User-Agent':'jkitchin/johnrkitchin@gmail.com bibtexupload'}
-
-r = requests.post(url, headers=headers, data=data, cookies=cookies, files={})
-print r
-#+END_SRC
-
-** Build a pdf from a bibtex file
-   It is useful to have a pdf version of an entire bibliography to check it for formatting, spelling, or to share it. This function creates a pdf from a bibtex file. I only include the packages  I commonly use in my bitex files.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-build-full-bibliography ()
-  "build pdf of all bibtex entries, and open it."
-  (interactive)
-  (let* ((bibfile (file-name-nondirectory (buffer-file-name)))
-       (bib-base (file-name-sans-extension bibfile))
-       (texfile (concat bib-base ".tex"))
-       (pdffile (concat bib-base ".pdf")))
-    (find-file texfile)
-    (erase-buffer)
-    (insert (format "\\documentclass[12pt]{article}
-\\usepackage[version=3]{mhchem}
-\\usepackage{url}
-\\usepackage[numbers]{natbib}
-\\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue, pdfstartview=FitH]{hyperref}
-\\usepackage{doi}
-\\begin{document}
-\\nocite{*}
-\\bibliographystyle{unsrtnat}
-\\bibliography{%s}
-\\end{document}" bib-base))
-    (save-buffer)
-    (shell-command (concat "pdflatex " bib-base))
-    (shell-command (concat "bibtex " bib-base))
-    (shell-command (concat "pdflatex " bib-base))
-    (shell-command (concat "pdflatex " bib-base))
-    (kill-buffer texfile)
-    (org-open-file pdffile)
-    ))
-#+END_SRC
-
-** Extract bibtex entries cited in an org-file
-When you use your default bibliography file, and you want to send an org-file to a collaborator, you may need to include bibtex entries so the other person can see them. This function does that and puts the entries in a section at the end of the document that can be tangled to a bib-file.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(defun org-ref-extract-bibtex-entries ()
-  "extract the bibtex entries referred to by cite links in the current buffer into a src block at the bottom of the current buffer.
-
-If no bibliography is in the buffer the `reftex-default-bibliography' is used."
-  (interactive)
-  (let* ((temporary-file-directory (file-name-directory (buffer-file-name)))
-         (tempname (make-temp-file "extract-bib"))
-         (contents (buffer-string))
-         (cb (current-buffer))
-        basename texfile bibfile results)
-
-    ;; open tempfile and insert org-buffer contents
-    (find-file tempname)
-    (insert contents)
-    (setq basename (file-name-sans-extension
-                   (file-name-nondirectory buffer-file-name))
-         texfile (concat tempname ".tex")
-         bibfile (concat tempname ".bib"))
-
-    ;; see if we have a bibliography, and insert the default one if not.
-    (save-excursion
-      (goto-char (point-min))
-      (unless (re-search-forward "^bibliography:" (point-max) 'end)
-       (insert (format "\nbibliography:%s"
-                       (mapconcat 'identity reftex-default-bibliography ",")))))
-    (save-buffer)
-
-    ;; get a latex file and extract the references
-    (org-latex-export-to-latex)
-    (find-file texfile)
-    (reftex-parse-all)
-    (reftex-create-bibtex-file bibfile)
-    (save-buffer)
-    ;; save results of the references
-    (setq results (buffer-string))
-
-    ;; kill buffers. these are named by basename, not full path
-    (kill-buffer (concat basename ".bib"))
-    (kill-buffer (concat basename ".tex"))
-    (kill-buffer basename)
-
-    (delete-file bibfile)
-    (delete-file texfile)
-    (delete-file tempname)
-
-    ;; Now back to the original org buffer and insert the results
-    (switch-to-buffer cb)
-    (when (not (string= "" results))
-      (save-excursion
-        (goto-char (point-max))
-        (insert "\n\n")
-       (org-insert-heading)
-       (insert (format " Bibtex entries
-
-,#+BEGIN_SRC text :tangle %s
-%s
-,#+END_SRC" (concat (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) ".bib") results))))))
-#+END_SRC
-
-** Find bad cite links
-   :PROPERTIES:
-   :ID:       8515E800-EDA0-4B2A-85FD-55B6FF849203
-   :END:
-Depending on how you enter citations, you may have citations with no corresponding bibtex entry. This function finds them and gives you a clickable table to navigate to them.
-
-#+BEGIN_SRC emacs-lisp  :tangle org-ref.el
-(require 'cl)
-
-(defun index (substring list)
-  "return the index of string in a list of strings"
-  (let ((i 0)
-       (found nil))
-    (dolist (arg list i)
-      (if (string-match (concat "^" substring "$") arg)
-         (progn
-           (setq found t)
-           (return i)))
-      (setq i (+ i 1)))
-    ;; return counter if found, otherwise return nil
-    (if found i nil)))
-
-
-(defun org-ref-find-bad-citations ()
-  "Create a list of citation keys in an org-file that do not have a bibtex entry in the known bibtex files.
-
-Makes a new buffer with clickable links."
-  (interactive)
-  ;; generate the list of bibtex-keys and cited keys
-  (let* ((bibtex-files (org-ref-find-bibliography))
-         (bibtex-file-path (mapconcat (lambda (x) (file-name-directory (file-truename x))) bibtex-files ":"))
-        (bibtex-keys (mapcar (lambda (x) (car x)) (bibtex-global-key-alist)))
-        (bad-citations '()))
-
-    (org-element-map (org-element-parse-buffer) 'link
-      (lambda (link)
-       (let ((plist (nth 1 link)))
-         (when (-contains? org-ref-cite-types (plist-get plist :type))
-           (dolist (key (org-ref-split-and-strip-string (plist-get plist :path)))
-             (when (not (index key bibtex-keys))
-               (message-box "%s" link)
-               (setq
-                bad-citations
-                (append
-                 bad-citations
-                 `(,(format "%s [[elisp:(progn (switch-to-buffer-other-frame \"%s\")(goto-char %s))][not found here]]\n"
-                            key
-                            (buffer-name)
-                            (plist-get plist :begin)))))
-               )))))
-      ;; set with-affilates to t to get citations in a caption
-      nil nil nil t)
-
-    (if bad-citations
-      (progn
-       (switch-to-buffer-other-window "*Missing citations*")
-       (org-mode)
-       (erase-buffer)
-       (insert "* List of bad cite links\n")
-       (insert (mapconcat 'identity bad-citations ""))
-                                       ;(setq buffer-read-only t)
-       (use-local-map (copy-keymap org-mode-map))
-       (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))
-
-      (when (get-buffer "*Missing citations*")
-          (kill-buffer "*Missing citations*"))
-      (message "No bad cite links found"))))
-#+END_SRC
-
-** helm interface to org-ref
-In [[id:8515E800-EDA0-4B2A-85FD-55B6FF849203][Find bad cite links]] we wrote a function that finds bad links and creates a buffer of links to them.
-
-Here we develop a similar idea, but instead of an org-buffer with links, we create helm sources for bad cite links, bad ref links, and multiple labels.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-bad-cite-candidates ()
-  "Returns a list of conses (key . marker) where key does not exist in the known bibliography files, and marker points to the key."
-  (let* ((cp (point))                  ; save to return to later
-        (bibtex-files (org-ref-find-bibliography))
-         (bibtex-file-path (mapconcat
-                           (lambda (x)
-                             (file-name-directory (file-truename x)))
-                           bibtex-files ":"))
-        (bibtex-keys (mapcar (lambda (x) (car x))
-                             (bibtex-global-key-alist)))
-        (bad-citations '()))
-
-    (org-element-map (org-element-parse-buffer) 'link
-      (lambda (link)
-       (let ((plist (nth 1 link)))
-         (when (-contains? org-ref-cite-types (plist-get plist :type))
-           (dolist (key (org-ref-split-and-strip-string (plist-get plist :path)) )
-             (when (not (index key bibtex-keys))
-               (goto-char (plist-get plist :begin))
-               (re-search-forward key)
-               (push (cons key (point-marker)) bad-citations)))
-           )))
-      ;; add with-affiliates to get cites in caption
-      nil nil nil t)
-    (goto-char cp)
-    bad-citations))
-
-
-(defun org-ref-bad-ref-candidates ()
-  "Returns a list of conses (ref . marker) where ref is a ref link that does not point to anything (i.e. a label)."
-  ;; first get a list of legitimate labels
-  (let ((cp (point))
-       (labels (org-ref-get-labels))
-       (bad-refs '()))
-    ;; now loop over ref links
-    (goto-char (point-min))
-    (org-element-map (org-element-parse-buffer) 'link
-      (lambda (link)
-       (let ((plist (nth 1 link)))
-         (when (or  (equal (plist-get plist ':type) "ref")
-                    (equal (plist-get plist ':type) "eqref")
-                    (equal (plist-get plist ':type) "pageref")
-                    (equal (plist-get plist ':type) "nameref"))
-           (unless (-contains? labels (plist-get plist :path))
-             (goto-char (plist-get plist :begin))
-             (add-to-list
-              'bad-refs
-              (cons (plist-get plist :path)
-                    (point-marker))))))))
-    (goto-char cp)
-    bad-refs))
-
-
-(defun org-ref-bad-label-candidates ()
-  "Return a list of labels where label is multiply defined."
-  (let ((labels (org-ref-get-labels))
-       (multiple-labels '()))
-    (when (not (= (length labels)
-                 (length (-uniq labels))))
-      (dolist (label labels)
-       (when (> (-count (lambda (a)
-                          (equal a label))
-                        labels) 1)
-         ;; this is a multiply defined label.
-         (let ((cp (point)))
-           (goto-char (point-min))
-           (while (re-search-forward
-                   (format  "[^#+]label:%s\\s-" label) nil t)
-             (push (cons label (point-marker)) multiple-labels))
-
-           (goto-char (point-min))
-           (while (re-search-forward
-                   (format  "\\label{%s}\\s-?" label) nil t)
-             (push (cons label (point-marker)) multiple-labels))
-
-           (goto-char (point-min))
-           (while (re-search-forward
-                   (format  "^#\\+label:\\s-*%s" label) nil t)
-             (push (cons label (point-marker)) multiple-labels))
-
-           (goto-char (point-min))
-           (while (re-search-forward
-                   (format   "^#\\+tblname:\\s-*%s" label) nil t)
-             (push (cons label (point-marker)) multiple-labels))
-           (goto-char cp)))))
-      multiple-labels))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-bad-label-candidates
-
-Now, we have a functions for candidates, we can make helm sources for each one, and then run a helm command to view them.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref ()
-  "Opens a helm interface to actions for org-ref.
-Shows bad citations, ref links and labels"
-  (interactive)
-  (let ((cb (current-buffer))
-       (bad-citations (org-ref-bad-cite-candidates))
-       (bad-refs (org-ref-bad-ref-candidates))
-       (bad-labels (org-ref-bad-label-candidates)))
-
-    (helm :sources `(((name . "Bad citations")
-                      (candidates . ,bad-citations)
-                      (action . (lambda (marker)
-                                  (switch-to-buffer (marker-buffer marker))
-                                  (goto-char marker))))
-                    ;;
-                    ((name . "Bad Labels")
-                     (candidates . ,bad-labels)
-                     (action . (lambda (marker)
-                                  (switch-to-buffer (marker-buffer marker))
-                                  (goto-char marker))))
-                    ;;
-                    ((name . "Bad ref links")
-                     (candidates . ,bad-refs)
-                     (action . (lambda (marker)
-                                         (switch-to-buffer (marker-buffer marker))
-                                         (goto-char marker))))
-                    ;;
-                    ((name . "Utilities")
-                     (candidates . (("Check buffer again" . org-ref)
-                                    ("Insert citation" . helm-bibtex)
-                                    ("Insert label link" . org-ref-helm-insert-label-link)
-                                    ("Insert ref link" . org-ref-helm-insert-ref-link)
-                                    ("List of figures" . org-ref-list-of-figures)
-                                    ("List of tables" . org-ref-list-of-tables)
-                                    ("Table of contents" . nil)
-                                    ))
-                     (action . (lambda (x)
-                                 (switch-to-buffer ,cb)
-                                 (funcall x))))
-                    ;;
-                    ((name . "Export functions")
-                     (candidates . (("Extract cited entries" . org-ref-extract-bibtex-entries)
-                                    ("Export to html and open" . (lambda () (org-open-file (org-html-export-to-html))))
-                                    ("Export to pdf and open" . (lambda ()
-                                                                  (org-open-file (org-latex-export-to-pdf))))
-                                    ("Export to manuscript pdf and open" . ox-manuscript-export-and-build-and-open)
-                                    ("Export submission manuscript pdf and open" . ox-manuscript-build-submission-manuscript-and-open)
-
-                                    ))
-                     (action . (lambda (x)
-                                 (switch-to-buffer ,cb)
-                                 (funcall x))))
-                     ))))
-#+END_SRC
-
-
-** Finding non-ascii characters
-I like my bibtex files to be 100% ascii. This function finds the non-ascii characters so you can replace them.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-find-non-ascii-characters ()
-  "finds non-ascii characters in the buffer. Useful for cleaning up bibtex files"
-  (interactive)
-  (occur "[^[:ascii:]]"))
-#+END_SRC
-
-** Resort a bibtex entry
-I like neat and orderly bibtex entries.That means the fields are in a standard order that I like. This function reorders the fields in an entry for articles, and makes sure the fields are in lowercase.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-sort-bibtex-entry ()
-  "sort fields of entry in standard order and downcase them"
-  (interactive)
-  (bibtex-beginning-of-entry)
-  (let* ((master '("author" "title" "journal" "volume" "number" "pages" "year" "doi" "url"))
-        (entry (bibtex-parse-entry))
-        (entry-fields)
-        (other-fields)
-        (type (cdr (assoc "=type=" entry)))
-        (key (cdr (assoc "=key=" entry))))
-
-    ;; these are the fields we want to order that are in this entry
-    (setq entry-fields (mapcar (lambda (x) (car x)) entry))
-    ;; we do not want to reenter these fields
-    (setq entry-fields (remove "=key=" entry-fields))
-    (setq entry-fields (remove "=type=" entry-fields))
-
-    ;;these are the other fields in the entry
-    (setq other-fields (remove-if-not (lambda(x) (not (member x master))) entry-fields))
-
-    (cond
-     ;; right now we only resort articles
-     ((string= (downcase type) "article")
-      (bibtex-kill-entry)
-      (insert
-       (concat "@article{" key ",\n"
-              (mapconcat
-               (lambda (field)
-                 (when (member field entry-fields)
-                   (format "%s = %s," (downcase field) (cdr (assoc field entry))))) master "\n")
-              (mapconcat
-               (lambda (field)
-                 (format "%s = %s," (downcase field) (cdr (assoc field entry)))) other-fields "\n")
-              "\n}\n\n"))
-      (bibtex-find-entry key)
-      (bibtex-fill-entry)
-      (bibtex-clean-entry)
-       ))))
-#+END_SRC
-
-** Clean a bibtex entry
-   I like neat and orderly bibtex entries. This code will eventually replace the key with my style key, clean the entry, and sort the fields in the order I like them.
-see [[file:emacs-24.3/lisp/textmodes/bibtex.el::bibtex-autokey-before-presentation-function]] for how to set a function that checks for uniqueness of the key.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-clean-bibtex-entry(&optional keep-key)
-  "clean and replace the key in a bibtex function. When keep-key is t, do not replace it. You can use a prefix to specify the key should be kept"
-  (interactive "P")
-  (bibtex-beginning-of-entry)
-(end-of-line)
-  ;; some entries do not have a key or comma in first line. We check and add it, if needed.
-  (unless (string-match ",$" (thing-at-point 'line))
-    (end-of-line)
-    (insert ","))
-
-  ;; check for empty pages, and put eid or article id in its place
-  (let ((entry (bibtex-parse-entry))
-       (pages (bibtex-autokey-get-field "pages"))
-       (year (bibtex-autokey-get-field "year"))
-        (doi  (bibtex-autokey-get-field "doi"))
-        ;; The Journal of Chemical Physics uses eid
-       (eid (bibtex-autokey-get-field "eid")))
-
-    ;; replace http://dx.doi.org/ in doi. some journals put that in,
-    ;; but we only want the doi.
-    (when (string-match "^http://dx.doi.org/" doi)
-      (bibtex-beginning-of-entry)
-      (goto-char (car (cdr (bibtex-search-forward-field "doi" t))))
-      (bibtex-kill-field)
-      (bibtex-make-field "doi")
-      (backward-char)
-      (insert (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))
-
-    ;; asap articles often set year to 0, which messes up key
-    ;; generation. fix that.
-    (when (string= "0" year)
-      (bibtex-beginning-of-entry)
-      (goto-char (car (cdr (bibtex-search-forward-field "year" t))))
-      (bibtex-kill-field)
-      (bibtex-make-field "year")
-      (backward-char)
-      (insert (read-string "Enter year: ")))
-
-    ;; fix pages if they are empty if there is an eid to put there.
-    (when (string= "-" pages)
-      (when eid
-       (bibtex-beginning-of-entry)
-       ;; this seems like a clunky way to set the pages field.But I
-       ;; cannot find a better way.
-       (goto-char (car (cdr (bibtex-search-forward-field "pages" t))))
-       (bibtex-kill-field)
-       (bibtex-make-field "pages")
-       (backward-char)
-       (insert eid)))
-
-    ;; replace naked & with \&
-    (save-restriction
-      (bibtex-narrow-to-entry)
-      (bibtex-beginning-of-entry)
-      (message "checking &")
-      (replace-regexp " & " " \\\\& ")
-      (widen))
-
-    ;; generate a key, and if it duplicates an existing key, edit it.
-    (unless keep-key
-      (let ((key (bibtex-generate-autokey)))
-
-       ;; first we delete the existing key
-       (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)))
-       ;; check if the key is in the buffer
-       (when (save-excursion
-               (bibtex-search-entry key))
-         (save-excursion
-           (bibtex-search-entry key)
-           (bibtex-copy-entry-as-kill)
-           (switch-to-buffer-other-window "*duplicate entry*")
-           (bibtex-yank))
-         (setq key (bibtex-read-key "Duplicate Key found, edit: " key)))
-
-       (insert key)
-       (kill-new key))) ;; save key for pasting
-
-    ;; run hooks. each of these operates on the entry with no arguments.
-    ;; this did not work like  i thought, it gives a symbolp error.
-    ;; (run-hooks org-ref-clean-bibtex-entry-hook)
-    (mapcar (lambda (x)
-             (save-restriction
-               (save-excursion
-                 (funcall x))))
-           org-ref-clean-bibtex-entry-hook)
-
-    ;; sort fields within entry
-    (org-ref-sort-bibtex-entry)
-    ;; check for non-ascii characters
-    (occur "[^[:ascii:]]")
-    ))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-clean-bibtex-entry
-
-** Sort the entries in a citation link by year
-I prefer citations in chronological order within a grouping. These functions sort the link under the cursor by year.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-citation-year (key)
-  "get the year of an entry with key. Returns year as a string."
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file key))
-        (bibfile (cdr results)))
-    (with-temp-buffer
-      (insert-file-contents bibfile)
-      (bibtex-search-entry key nil 0)
-      (prog1 (reftex-get-bib-field "year" (bibtex-parse-entry t))
-        ))))
-
-(defun org-ref-sort-citation-link ()
- "replace link at point with sorted link by year"
- (interactive)
- (let* ((object (org-element-context))
-        (type (org-element-property :type object))
-       (begin (org-element-property :begin object))
-       (end (org-element-property :end object))
-       (link-string (org-element-property :path object))
-       keys years data)
-  (setq keys (org-ref-split-and-strip-string link-string))
-  (setq years (mapcar 'org-ref-get-citation-year keys))
-  (setq data (mapcar* (lambda (a b) `(,a . ,b)) years keys))
-  (setq data (cl-sort data (lambda (x y) (< (string-to-int (car x)) (string-to-int (car y))))))
-  ;; now get the keys separated by commas
-  (setq keys (mapconcat (lambda (x) (cdr x)) data ","))
-  ;; and replace the link with the sorted keys
-  (cl--set-buffer-substring begin end (concat type ":" keys))))
-#+END_SRC
-
-** Sort entries in citation links with shift-arrow keys
-Sometimes it may be helpful to manually change the order of citations. These functions define shift-arrow functions.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-swap-keys (i j keys)
- "swap the keys in a list with index i and j"
- (let ((tempi (nth i keys)))
-   (setf (nth i keys) (nth j keys))
-   (setf (nth j keys) tempi))
-  keys)
-
-(defun org-ref-swap-citation-link (direction)
- "move citation at point in direction +1 is to the right, -1 to the left"
- (interactive)
- (let* ((object (org-element-context))
-        (type (org-element-property :type object))
-       (begin (org-element-property :begin object))
-       (end (org-element-property :end object))
-       (link-string (org-element-property :path object))
-       key keys i)
-   ;;   We only want this to work on citation links
-   (when (-contains? org-ref-cite-types type)
-        (setq key (org-ref-get-bibtex-key-under-cursor))
-       (setq keys (org-ref-split-and-strip-string link-string))
-        (setq i (index key keys))  ;; defined in org-ref
-       (if (> direction 0) ;; shift right
-           (org-ref-swap-keys i (+ i 1) keys)
-         (org-ref-swap-keys i (- i 1) keys))
-       (setq keys (mapconcat 'identity keys ","))
-       ;; and replace the link with the sorted keys
-       (cl--set-buffer-substring begin end (concat type ":" keys " "))
-       ;; now go forward to key so we can move with the key
-       (re-search-forward key)
-       (goto-char (match-beginning 0)))))
-
-;; add hooks to make it work
-(add-hook 'org-shiftright-hook (lambda () (org-ref-swap-citation-link 1)))
-(add-hook 'org-shiftleft-hook (lambda () (org-ref-swap-citation-link -1)))
-#+END_SRC
-
-** Lightweight messages about links
-To get a lighter weight message about the label, ref and cite links, we define a function that gives us the minibuffer message, without the menu. We run this in an idle timer.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-label-context (label)
-  "Return a string of context around a label."
-  (save-excursion
-    (catch 'result
-      (goto-char (point-min))
-      (when (re-search-forward
-            (format "label:%s\\b" label) nil t)
-       (throw 'result (buffer-substring
-                       (progn
-                         (previous-line)
-                         (beginning-of-line)
-                         (point))
-                       (progn
-                         (forward-line 4)
-                         (point)))))
-
-      (goto-char (point-min))
-      (when (re-search-forward
-            (format "\\label{%s}" label) nil t)
-       (throw 'result (buffer-substring
-                       (progn
-                         (previous-line)
-                         (beginning-of-line)
-                         (point))
-                       (progn
-                         (forward-line 4)
-                         (point)))))
-
-      (goto-char (point-min))
-      (when (re-search-forward
-            (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t)
-       (throw 'result (buffer-substring
-                       (progn
-                         (previous-line)
-                         (beginning-of-line)
-                         (point))
-                       (progn
-                         (forward-line 4)
-                         (point)))))
-
-      (goto-char (point-min))
-      (when (re-search-forward
-            (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t)
-       (throw 'result (buffer-substring
-                       (progn
-                         (previous-line)
-                         (beginning-of-line)
-                         (point))
-                       (progn
-                         (forward-line 4)
-                         (point)))))
-      (throw 'result "!!! NO CONTEXT FOUND !!!"))))
-
-
-(defun org-ref-link-message ()
-  "Print a minibuffer message about the link that point is on."
-  (interactive)
-  (when (eq major-mode 'org-mode)
-    (let* ((object (org-element-context))
-          (type (org-element-property :type object)))
-      (save-excursion
-       (cond
-        ;; cite links
-        ((-contains? org-ref-cite-types type)
-         (message (org-ref-get-citation-string-at-point)))
-
-        ;; message some context about the label we are referring to
-        ((string= type "ref")
-         (message "%scount: %s"
-                  (org-ref-get-label-context
-                   (org-element-property :path object))
-                  (org-ref-count-labels
-                       (org-element-property :path object))))
-
-        ((string= type "eqref")
-         (message "%scount: %s"
-                  (org-ref-get-label-context
-                   (org-element-property :path object))
-                  (org-ref-count-labels
-                       (org-element-property :path object))))
-
-        ;; message the count
-        ((string= type "label")
-         (let ((count (org-ref-count-labels
-                       (org-element-property :path object))))
-           ;; get plurality on occurrence correct
-           (message (concat
-                     (number-to-string count)
-                     " occurence"
-                     (when (or (= count 0)
-                               (> count 1))
-                       "s")))))
-
-        ((string= type "custom-id")
-         (save-excursion
-           (org-open-link-from-string
-            (format "[[#%s]]" (org-element-property :path object)))
-           (message "%s" (org-get-heading))))
-
-         ;; check if the bibliography files exist.
-        ((string= type "bibliography")
-         (let* ((bibfile)
-                ;; object is the link you clicked on
-                (object (org-element-context))
-                (link-string (org-element-property :path object))
-                (link-string-beginning)
-                (link-string-end))
-           (save-excursion
-             (goto-char (org-element-property :begin object))
-             (search-forward link-string nil nil 1)
-             (setq link-string-beginning (match-beginning 0))
-             (setq link-string-end (match-end 0)))
-
-            ;; make sure we are in link and not before the :
-           (when (> link-string-beginning (point))
-             (goto-char link-string-beginning))
-
-           ;; now if we have comma separated bibliographies
-           ;; we find the one clicked on. we want to
-           ;; search forward to next comma from point
-           (save-excursion
-             (if (search-forward "," link-string-end 1 1)
-                 (setq key-end (- (match-end 0) 1)) ; we found a match
-               (setq key-end (point)))) ; no comma found so take the point
-
-           ;; and backward to previous comma from point
-           (save-excursion
-             (if (search-backward "," link-string-beginning 1 1)
-                 (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
-               (setq key-beginning (point)))) ; no match found
-           ;; save the key we clicked on.
-           (setq bibfile
-                 (org-ref-strip-string
-                  (buffer-substring key-beginning key-end)))
-           (if (file-exists-p bibfile)
-               (message "%s exists." bibfile)
-             (message "!!! %s NOT FOUND !!!" bibfile))))
-        )))))
-#+END_SRC
-
-* Aliases
-I like convenience. Here are some aliases for faster typing.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defalias 'oro 'org-ref-open-citation-at-point)
-(defalias 'orc 'org-ref-citation-at-point)
-(defalias 'orp 'org-ref-open-pdf-at-point)
-(defalias 'oru 'org-ref-open-url-at-point)
-(defalias 'orn 'org-ref-open-notes-at-point)
-(defalias 'ornr 'org-ref-open-notes-from-reftex)
-
-(defalias 'orib 'org-ref-insert-bibliography-link)
-(defalias 'oric 'org-ref-insert-cite-link)
-(defalias 'orir 'org-ref-insert-ref-link)
-(defalias 'orsl 'org-ref-store-bibtex-entry-link)
-
-(defalias 'orcb 'org-ref-clean-bibtex-entry)
-#+END_SRC
-* Helm interface
-[[https://github.com/tmalsburg/helm-bibtex][helm-bibtex]] is a very cool interface to bibtex files. Out of the box though, it is not super convenient for org-ref. Here, we modify it to make it fit our workflow and extend it where needed.
-
-1. Make the default action to insert selected keys.
-2. Make open entry second action
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(setq helm-source-bibtex
-      '((name                                      . "BibTeX entries")
-       (init                                      . helm-bibtex-init)
-       (candidates                                . helm-bibtex-candidates)
-       (filtered-candidate-transformer            . helm-bibtex-candidates-formatter)
-       (action . (("Insert citation"              . helm-bibtex-insert-citation)
-                  ("Show entry"                   . helm-bibtex-show-entry)
-                  ("Open PDF file (if present)"   . helm-bibtex-open-pdf)
-                  ("Open URL or DOI in browser"   . helm-bibtex-open-url-or-doi)
-                  ("Insert reference"             . helm-bibtex-insert-reference)
-                  ("Insert BibTeX key"            . helm-bibtex-insert-key)
-                  ("Insert BibTeX entry"          . helm-bibtex-insert-bibtex)
-                  ("Attach PDF to email"          . helm-bibtex-add-PDF-attachment)
-                  ("Edit notes"                   . helm-bibtex-edit-notes)
-                  ))))
-#+END_SRC
-
-Now, let us define a function that inserts the cite links:
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun helm-bibtex-format-org-ref (keys)
-  "Insert selected KEYS as cite link. Append KEYS if you are on a link.
-Technically, this function should return a string that is inserted by helm. This function does the insertion and gives helm an empty string to insert. This lets us handle appending to a link properly.
-
-In the helm-bibtex buffer, C-u will give you a helm menu to select a new link type for the selected entries.
-
-C-u C-u will change the key at point to the selected keys.
-"
-  (let* ((object (org-element-context))
-        (last-char (save-excursion
-                     (goto-char (org-element-property :end object))
-                     (backward-char)
-                     (if (looking-at " ")
-                         " "
-                       ""))))
-    (cond
-     ;; case where we are in a link
-     ((and (equal (org-element-type object) 'link)
-          (-contains?
-           org-ref-cite-types
-           (org-element-property :type object)))
-      (cond
-       ;; no prefix. append keys
-       ((equal helm-current-prefix-arg nil)
-       (goto-char (org-element-property :end object))
-       (while (looking-back " ") (backward-char))
-       (insert (concat "," (mapconcat 'identity keys ","))))
-       ;; double prefix, replace key at point
-       ((equal helm-current-prefix-arg '(16))
-       (setf (buffer-substring
-              (org-element-property :begin object)
-              (org-element-property :end object))
-             (concat
-              (replace-regexp-in-string
-               (car (org-ref-get-bibtex-key-and-file)) ; key
-               (mapconcat 'identity keys ",")          ; new keys
-               (org-element-property :raw-link object))
-              ;; replace space at end to avoid collapsing into next word.
-              last-char))
-       ;; and we want to go to the end of the new link
-       (goto-char
-        (org-element-property :end (org-element-context))))
-       (t
-       (message "Not found"))))
-
-     ;; We are next to a link, and we want to append
-     ;; next to a link means one character back is on a link.
-     ((save-excursion
-       (backward-char)
-       (and (equal (org-element-type (org-element-context)) 'link)
-            (-contains?
-             org-ref-cite-types
-             (org-element-property :type (org-element-context)))))
-      (while (looking-back " ") (backward-char))
-      (insert (concat "," (mapconcat 'identity keys ","))))
-
-     ;; insert fresh link
-     (t
-      ;;(message-box "fresh link")
-      (insert
-       (concat (if (equal helm-current-prefix-arg '(4))
-                  (helm :sources `((name . "link types")
-                                   (candidates . ,org-ref-cite-types)
-                                   (action . (lambda (x) x))))
-               org-ref-default-citation-link)
-              ":"
-              (s-join "," keys))))))
-  ;; return empty string for helm
-  "")
-
-(setq helm-bibtex-format-citation-functions
-      '((org-mode . helm-bibtex-format-org-ref)))
-
-(defun org-ref-helm-insert-cite-link (arg)
-  "org-ref function to use helm-bibtex to insert a citation link.
-With one prefix arg, insert a ref link.
-With two prefix args, insert a label link."
-  (interactive "P")
-  (cond
-   ((equal arg nil)
-     (let ((helm-bibtex-bibliography (org-ref-find-bibliography)))
-       (helm-bibtex)))
-   ((equal arg '(4))
-    (org-ref-helm-insert-ref-link))
-   ((equal arg '(16))
-    (org-ref-helm-insert-label-link))))
-
-(require 'helm-bibtex)
-
-;; add our own fallback entries where we want them. These appear in reverse order of adding in the menu
-(setq helm-bibtex-fallback-options
-      (-insert-at 1 '("Crossref" . "http://search.crossref.org/?q=%s") helm-bibtex-fallback-options))
-
-(setq helm-bibtex-fallback-options
-      (-insert-at
-       1
-       '("Scopus" . "http://www.scopus.com/scopus/search/submit/xadvanced.url?searchfield=TITLE-ABS-KEY(%s)")
-       helm-bibtex-fallback-options))
-
-(setq helm-bibtex-fallback-options
-      (-insert-at 1 '("WOS" . "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary") helm-bibtex-fallback-options))
-#+END_SRC
-
-** A helm click menu
-This code provides a helm interface to things you can do when you click on a citation link. This is an alternative to the minibuffer menu.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-citation-string-at-point ()
-  "Get a string of a formatted citation"
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file))
-        (key (car results))
-        (bibfile (cdr results)))
-    (if bibfile
-       (save-excursion
-         (with-temp-buffer
-           (insert-file-contents bibfile)
-           (bibtex-search-entry key)
-           (org-ref-bib-citation)))
-      "!!! No entry found !!!" )))
-
-(defun org-ref-cite-candidates ()
-  "Generate the list of possible candidates for click actions on a cite link.
-Checks for pdf and doi, and add appropriate functions."
-  (interactive)
-  (let* ((results (org-ref-get-bibtex-key-and-file))
-        (key (car results))
-         (pdf-file (format (concat org-ref-pdf-directory "%s.pdf") key))
-         (bibfile (cdr results))
-        (url (save-excursion
-               (with-temp-buffer
-                 (insert-file-contents bibfile)
-                 (bibtex-search-entry key)
-                 (bibtex-autokey-get-field "url"))))
-        (doi (save-excursion
-               (with-temp-buffer
-                 (insert-file-contents bibfile)
-                 (bibtex-search-entry key)
-                 ;; I like this better than bibtex-url which does not always find
-                 ;; the urls
-                 (bibtex-autokey-get-field "doi"))))
-        (candidates `(("Quit" . org-ref-citation-at-point)
-                      ("Open bibtex entry" . org-ref-open-citation-at-point))))
-    ;; for some reason, when there is no doi or url, they are returned as "". I
-    ;; prefer nil so we correct this here.
-    (when (string= doi "") (setq doi nil))
-    (when (string= url "") (setq url nil))
-
-    ;; Conditional pdf functions
-    (if (file-exists-p pdf-file)
-       (add-to-list
-        'candidates
-        '("Open pdf" . org-ref-open-pdf-at-point)
-        t)
-      (add-to-list
-       'candidates
-       '("Try to get pdf" . (lambda ()
-                             (save-window-excursion
-                               (org-ref-open-citation-at-point)
-                                (bibtex-beginning-of-entry)
-                               (doi-utils-get-bibtex-entry-pdf))))
-       t))
-
-
-    (add-to-list
-     'candidates
-     '("Open notes" . org-ref-open-notes-at-point)
-     t)
-
-    ;; conditional url and doi functions
-    (when (or url doi)
-      (add-to-list
-       'candidates
-       '("Open in browser" . org-ref-open-url-at-point)
-       t))
-
-    (when doi
-      (mapc (lambda (x)
-             (add-to-list 'candidates x t))
-           `(("WOS" . org-ref-wos-at-point)
-             ("Related articles in WOS" . org-ref-wos-related-at-point)
-             ("Citing articles in WOS" . org-ref-wos-citing-at-point)
-             ("Google Scholar" . org-ref-google-scholar-at-point)
-             ("Pubmed" . org-ref-pubmed-at-point)
-             ("Crossref" . org-ref-crossref-at-point)
-             )))
-
-    (add-to-list
-     'candidates
-     '("Copy formatted citation to clipboard" . org-ref-copy-entry-as-summary)
-     t)
-
-    (add-to-list
-     'candidates
-     '("Copy key to clipboard" . (lambda ()
-                                 (kill-new
-                                  (car (org-ref-get-bibtex-key-and-file)))))
-     t)
-
-    (add-to-list
-     'candidates
-     '("Copy bibtex entry to file" . org-ref-copy-entry-at-point-to-file)
-     t)
-
-    (add-to-list
-     'candidates
-     '("Email bibtex entry and pdf" . (lambda ()
-                 (save-excursion
-                   (org-ref-open-citation-at-point)
-                   (email-bibtex-entry))))
-     t)
-  ;; finally return a numbered list of the candidates
-  (cl-loop for i from 0
-       for cell in candidates
-       collect (cons (format "%2s. %s" i (car cell))
-                     (cdr cell)))))
-
-
-(defvar org-ref-helm-user-candidates '()
-  "List of user-defined candidates to act when clicking on a cite link.
-This is a list of cons cells '((\"description\" . action)). The action function should not take an argument, and should assume point is on the cite key of interest.
-")
-
-;; example of adding your own function
-(add-to-list
- 'org-ref-helm-user-candidates
- '("Example" . (lambda () (message-box "You did it!")))
- t)
-
-(defun org-ref-cite-click-helm (key)
-  "subtle points.
-1. get name and candidates before entering helm because we need the org-buffer.
-2. switch back to the org buffer before evaluating the action. most of them need the point and buffer."
-  (interactive)
-  (let ((name (org-ref-get-citation-string-at-point))
-       (candidates (org-ref-cite-candidates))
-       (cb (current-buffer)))
-
-    (helm :sources `(((name . ,name)
-                     (candidates . ,candidates)
-                     (action . (lambda (f)
-                                 (switch-to-buffer cb)
-                                 (funcall f))))
-                    ((name . "User functions")
-                     (candidates . ,org-ref-helm-user-candidates)
-                     (action . (lambda (f)
-                                 (switch-to-buffer cb)
-                                 (funcall f))))
-                    ))))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-cite-click-helm
-
-* End of code
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(provide 'org-ref)
-#+END_SRC
-
-* Build                                                                   :noexport:
-This code will tangle the elisp code out to org-ref.el and load it.
-
-[[elisp:(progn (org-babel-tangle) (load-file "org-ref.el"))]]
-
-Alternatively you may use:
-
-[[elisp:(org-babel-load-file "org-ref.org")]]
diff --git a/pubmed.el b/pubmed.el
new file mode 100644 (file)
index 0000000..61ec861
--- /dev/null
+++ b/pubmed.el
@@ -0,0 +1,222 @@
+;;; pubmed.el --- Links and functions for Pubmed and NIH databases  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; Keywords: convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; * Introduction
+
+;; This document is an experiment at creating a literate program to provide functions for interacting with pubmed databases.
+
+;; This library provides links that go to pubmed resources, e.g.
+
+;; pmcid:PMC3498956
+;;
+;; pmid:23162369
+;;
+;; and nihmsid:NIHMS395714
+;;
+;; See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details of these identifiers.
+;;
+;; For PMID there is one interactive function that inserts a bibtex entry: pubmed-insert-bibtex-from-pmid.
+
+;; This library is complementary to [[./doi-utils.org]].
+
+;;; Code:
+
+;; * PMID (from PubMed) link and functions
+
+;; A PMID is a number that identifies an entry in the Pubmed database.  The PMID
+;; is a unique reference number for PubMed citations. The PMID is a distinctly
+;; different number from the PMCID and is used only for PubMed records.
+
+(org-add-link-type
+ "pmid"
+ ;; clicking
+ (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pubmed/%s" link-string)))
+ ;; formatting
+(lambda (keyword desc format)
+   (cond
+    ((eq format 'html)
+     (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s\">pmid:%s</a>" keyword keyword)); no output for html
+    ((eq format 'latex)
+     ;; write out the latex command
+     (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}" keyword)))))
+
+;; ** Get MEDLINE metadata
+
+;; We can get bibliographic metadata from a pmid. Here we get the MEDLINE
+;; text. The website wraps the data in <pre></pre> tags.
+
+(defun pubmed-get-medline (pmid)
+  "Get MEDLINE text for PMID as a string."
+  (with-current-buffer
+    (url-retrieve-synchronously
+     (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=medline&format=text" pmid))
+    (goto-char (point-min))
+    (let ((p1 (search-forward "<pre>"))
+         (p2 (search-forward "</pre>")))
+      (buffer-substring (+ 1 p1) (- p2 6)))))
+
+;; ** Parse the PMID MEDLINE data
+
+;; We can parse this into a data structure.
+
+(defun pubmed-parse-medline (pmid)
+  "Parse the medline text for PMID and return a list of cons cells."
+  (let ((data '())
+       (p1)
+       (p2)
+       (tag)
+       (value))
+    (with-temp-buffer (insert (pubmed-get-medline pmid))
+                     (goto-char (point-min))
+                     (while (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
+                       (setq tag (match-string 1))
+                       ;; point is at end of the search
+                       (setq p1 (point))
+                       ;; now go to next tag
+                       (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
+                       (setq p2 (- (match-beginning 1) 1))
+                       (setq value (buffer-substring p1 p2))
+                       (setq data (append data (list (cons tag value))))
+                       ;; now go back to last tag to get the next one
+                       (goto-char p1)))
+    data))
+
+;; ** PMID to bibtex entry
+
+;; The point of parsing the MEDLINE text is so we can make bibtex entries. We
+;; only support Journal articles for now.
+
+(defun pubmed-pmid-to-bibtex (pmid)
+  "Convert a PMID to a bibtex entry."
+  (let* ((data (pubmed-parse-medline pmid))
+        (type (cdr (assoc "PT" data)))
+        (title (cdr (assoc "TI" data)))
+        (authors (mapconcat 'cdr
+                            (-filter (lambda (x)
+                                       (string= (car x) "FAU"))
+                                     data)
+                            " and "))
+        (abstract (cdr (assoc "AB" data)))
+        (volume (cdr (assoc "VI" data)))
+        (issue (cdr (assoc "IP" data)))
+        (journal (cdr (assoc "JT" data)))
+        (year (cdr (assoc "DP" data)))
+        (pages (cdr (assoc "PG" data)))
+        (aid (cdr (assoc "AID" data))))
+
+    (cond
+     ((string= type "JOURNAL ARTICLE")
+      (concat "@article{,
+ author = {" authors "},
+ title = {" title "},
+ abstract = {" abstract "},
+ journal = {" journal "},
+ volume = {" volume "},
+ number = {" issue "},
+ year = {" (car (split-string year)) "},
+ pages = {" pages "},
+ doi = {" (replace-regexp-in-string " \\[doi\\]" "" aid) "},
+}"))
+    (t
+     (message "No conversion for type: %s" type)))))
+
+;; And we probably want to be able to insert a bibtex entry
+
+(defun pubmed-insert-bibtex-from-pmid (pmid)
+ "Insert a bibtex entry at point derived from PMID.
+You must clean the entry after insertion."
+ (interactive "sPMID: ")
+ (insert (pubmed-pmid-to-bibtex pmid)))
+
+;; ** PMID to xml
+
+;; We can also get xml of the MEDLINE data. The web page here also wraps the xml
+;; in a <pre> block and escapes the <> with &lt; and &gt;, which we have to
+;; undo. I have not used this code for anything, so I am not sure how good the
+;; xml code is.
+
+(defun pubmed-get-medline-xml (pmid)
+  "Get MEDLINE xml for PMID as a string."
+  (interactive)
+  (with-current-buffer
+    (url-retrieve-synchronously
+     (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=xml&format=text" pmid))
+    (goto-char (point-min))
+    (while (search-forward "&lt;" nil t)
+      (replace-match "<"))
+    (goto-char (point-min))
+    (while (search-forward "&gt;" nil t)
+      (replace-match ">"))
+    (goto-char (point-min))
+
+    (let ((p1 (search-forward "<pre>"))
+         (p2 (search-forward "</pre>")))
+      (buffer-substring (+ 1 p1) (- p2 6)))))
+
+;; * Pubmed Central (PMC) link
+
+;; A PMCID starts with PMC and is followed by numbers. The PMCID is a unique
+;; reference number or identifier that is assigned to every article that is
+;; accepted into PMC. The PMCID is also used by recipients of NIH funding to
+;; demonstrate compliance with the NIH Public Access policy. The PMCID can be
+;; found in both PMC and PubMed.
+
+;; Here we define a new link. Clicking on it simply opens a webpage to the
+;; article.
+
+(org-add-link-type
+ "pmcid"
+ ;; clicking
+ (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/%s" link-string)))
+ ;; formatting
+(lambda (keyword desc format)
+   (cond
+    ((eq format 'html)
+     (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/%s\">pmcid:%s</a>" keyword keyword))
+    ((eq format 'latex)
+     (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/%s}" keyword)))))
+
+;; * NIHMSID
+
+;; The NIHMSID is a preliminary article identifier that applies only to
+;; manuscripts deposited through the NIHMS system. The NIHMSID is only valid for
+;; compliance reporting for 90 days after the publication date of an
+;; article. Once the Web version of the NIHMS submission is approved for
+;; inclusion in PMC and the corresponding citation is in PubMed, the article
+;; will also be assigned a PMCID.
+
+(org-add-link-type
+ "nihmsid"
+ ;; clicking
+ (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s" link-string)))
+ ;; formatting
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'html)
+     (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid//%s\">nihmsid:%s</a>" keyword keyword))
+    ((eq format 'latex)
+     ;; write out the latex command
+     (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}" keyword)))))
+
+
+(provide 'pubmed)
+;;; pubmed.el ends here
diff --git a/pubmed.org b/pubmed.org
deleted file mode 100644 (file)
index 7febb4a..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-#+TITLE: Links and functions for Pubmed and NIH databases
-#+AUTHOR: John Kitchin
-#+DATE: January 5, 2015
-
-* Introduction
-
-This document is an experiment at creating a literate program to provide functions for interacting with pubmed databases.
-
-This library provides links that go to pubmed resources, e.g.
-
-pmcid:PMC3498956
-
-pmid:23162369
-
-and nihmsid:NIHMS395714
-
-See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details of these identifiers.
-
-For PMID there is one interactive function that inserts a bibtex entry: pubmed-insert-bibtex-from-pmid.
-
-This library is complementary to [[./doi-utils.org]].
-
-* Header
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el
-;;; pubmed.el --- Links and functions to interact with pubmed databases.
-
-;; Copyright(C) 2015 John Kitchin
-
-;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
-;; This file is not currently part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2, or (at
-;; your option) any later version.
-
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program ; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;;
-;; Lisp code to interact with pubmed databases, links to pubmed
-;; identifiers. See pubmed.org.
-;;;
-;; This library provides links that go to pubmed resources, e.g.
-;;
-;; pmcid:PMC3498956
-;;
-;; pmid:23162369
-;;
-;; and nihmsid:NIHMS395714
-;;
-;; See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details of these identifiers.
-;;
-;; For PMID there is one interactive function that inserts a bibtex
-;; entry: `pubmed-insert-bibtex-from-pmid`.
-#+END_SRC
-
-* PMID (from PubMed) link and functions
-A PMID is a number that identifies an entry in the Pubmed database.  The PMID is a unique reference number for PubMed citations. The PMID is a distinctly different number from the PMCID and is used only for PubMed records.
-
-
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el :results silent
-(org-add-link-type
- "pmid"
- ;; clicking
- (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pubmed/%s" link-string)))
- ;; formatting
-(lambda (keyword desc format)
-   (cond
-    ((eq format 'html)
-     (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s\">pmid:%s</a>" keyword keyword)); no output for html
-    ((eq format 'latex)
-     ;; write out the latex command
-     (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}" keyword)))))
-#+END_SRC
-
-
-
-** Get MEDLINE metadata
-We can get bibliographic metadata from a pmid. Here we get the MEDLINE text. The website wraps the data in <pre></pre> tags.
-
-
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el
-(defun pubmed-get-medline (pmid)
-  "Get MEDLINE text for PMID as a string."
-  (with-current-buffer
-    (url-retrieve-synchronously
-     (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=medline&format=text" pmid))
-    (goto-char (point-min))
-    (let ((p1 (search-forward "<pre>"))
-         (p2 (search-forward "</pre>")))
-      (buffer-substring (+ 1 p1) (- p2 6)))))
-#+END_SRC
-
-#+RESULTS:
-: pubmed-get-medline
-
-Here is sample output:
-#+BEGIN_SRC emacs-lisp
-(pubmed-get-medline "23162369")
-#+END_SRC
-
-#+RESULTS:
-#+begin_example
-PMID- 23162369
-OWN - NLM
-STAT- Publisher
-DA  - 20121119
-IS  - 1040-726X (Print)
-IS  - 1040-726X (Linking)
-VI  - 24
-IP  - 4
-DP  - 2012 Dec
-TI  - Transformational Teaching: Theoretical Underpinnings, Basic Principles, and Core 
-      Methods.
-PG  - 569-608
-AB  - Approaches to classroom instruction have evolved considerably over the past 50
-      years. This progress has been spurred by the development of several learning
-      principles and methods of instruction, including active learning,
-      student-centered learning, collaborative learning, experiential learning, and
-      problem-based learning. In the present paper, we suggest that these seemingly
-      different strategies share important underlying characteristics and can be viewed
-      as complimentary components of a broader approach to classroom instruction called
-      transformational teaching. Transformational teaching involves creating dynamic
-      relationships between teachers, students, and a shared body of knowledge to
-      promote student learning and personal growth. From this perspective, instructors 
-      are intellectual coaches who create teams of students who collaborate with each
-      other and with their teacher to master bodies of information. Teachers assume the
-      traditional role of facilitating students' acquisition of key course concepts,
-      but do so while enhancing students' personal development and attitudes toward
-      learning. They accomplish these goals by establishing a shared vision for a
-      course, providing modeling and mastery experiences, challenging and encouraging
-      students, personalizing attention and feedback, creating experiential lessons
-      that transcend the boundaries of the classroom, and promoting ample opportunities
-      for preflection and reflection. We propose that these methods are synergistically
-      related and, when used together, maximize students' potential for intellectual
-      and personal growth.
-FAU - Slavich, George M
-AU  - Slavich GM
-AD  - Cousins Center for Psychoneuroimmunology and Department of Psychiatry and
-      Biobehavioral Sciences, University of California, Los Angeles, UCLA Medical Plaza
-      300, Room 3156, Los Angeles, CA 90095-7076, USA.
-FAU - Zimbardo, Philip G
-AU  - Zimbardo PG
-LA  - ENG
-GR  - R01 AG026364/AG/NIA NIH HHS/United States
-GR  - T32 MH019925/MH/NIMH NIH HHS/United States
-PT  - JOURNAL ARTICLE
-DEP - 20120724
-TA  - Educ Psychol Rev
-JT  - Educational psychology review
-JID - 9885342
-PMC - PMC3498956
-MID - NIHMS395714
-EDAT- 2012/11/20 06:00
-MHDA- 2012/11/20 06:00
-CRDT- 2012/11/20 06:00
-PHST- 2012/07/24 [epublish]
-AID - 10.1007/s10648-012-9199-6 [doi]
-PST - ppublish
-SO  - Educ Psychol Rev. 2012 Dec;24(4):569-608. Epub 2012 Jul 24.
-#+end_example
-
-** Parse the PMID MEDLINE data
-We can parse this into a data structure
-
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el
-(defun pubmed-parse-medline (pmid)
-  "Parse the medline text for PMID and return a list of cons cells."
-  (let ((data '())
-       (p1)
-       (p2)
-       (tag)
-       (value))
-    (with-temp-buffer (insert (pubmed-get-medline pmid))
-                     (goto-char (point-min))
-                     (while (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
-                       (setq tag (match-string 1))
-                       ;; point is at end of the search
-                       (setq p1 (point))
-                       ;; now go to next tag
-                       (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
-                       (setq p2 (- (match-beginning 1) 1))
-                       (setq value (buffer-substring p1 p2))
-                       (setq data (append data (list (cons tag value))))
-                       ;; now go back to last tag to get the next one
-                       (goto-char p1)))
-    data))
-#+END_SRC
-
-#+RESULTS:
-: pubmed-parse-medline
-
-#+BEGIN_SRC emacs-lisp :results code
-(pubmed-parse-medline "23162369")
-#+END_SRC
-
-#+RESULTS:
-#+BEGIN_SRC emacs-lisp
-(("PMID" . "23162369")
- ("OWN" . "NLM")
- ("STAT" . "Publisher")
- ("DA" . "20121119")
- ("IS" . "1040-726X (Print)")
- ("IS" . "1040-726X (Linking)")
- ("VI" . "24")
- ("IP" . "4")
- ("DP" . "2012 Dec")
- ("TI" . "Transformational Teaching: Theoretical Underpinnings, Basic Principles, and Core \n      Methods.")
- ("PG" . "569-608")
- ("AB" . "Approaches to classroom instruction have evolved considerably over the past 50\n      years. This progress has been spurred by the development of several learning\n      principles and methods of instruction, including active learning,\n      student-centered learning, collaborative learning, experiential learning, and\n      problem-based learning. In the present paper, we suggest that these seemingly\n      different strategies share important underlying characteristics and can be viewed\n      as complimentary components of a broader approach to classroom instruction called\n      transformational teaching. Transformational teaching involves creating dynamic\n      relationships between teachers, students, and a shared body of knowledge to\n      promote student learning and personal growth. From this perspective, instructors \n      are intellectual coaches who create teams of students who collaborate with each\n      other and with their teacher to master bodies of information. Teachers assume the\n      traditional role of facilitating students' acquisition of key course concepts,\n      but do so while enhancing students' personal development and attitudes toward\n      learning. They accomplish these goals by establishing a shared vision for a\n      course, providing modeling and mastery experiences, challenging and encouraging\n      students, personalizing attention and feedback, creating experiential lessons\n      that transcend the boundaries of the classroom, and promoting ample opportunities\n      for preflection and reflection. We propose that these methods are synergistically\n      related and, when used together, maximize students' potential for intellectual\n      and personal growth.")
- ("FAU" . "Slavich, George M")
- ("AU" . "Slavich GM")
- ("AD" . "Cousins Center for Psychoneuroimmunology and Department of Psychiatry and\n      Biobehavioral Sciences, University of California, Los Angeles, UCLA Medical Plaza\n      300, Room 3156, Los Angeles, CA 90095-7076, USA.")
- ("FAU" . "Zimbardo, Philip G")
- ("AU" . "Zimbardo PG")
- ("LA" . "ENG")
- ("GR" . "R01 AG026364/AG/NIA NIH HHS/United States")
- ("GR" . "T32 MH019925/MH/NIMH NIH HHS/United States")
- ("PT" . "JOURNAL ARTICLE")
- ("DEP" . "20120724")
- ("TA" . "Educ Psychol Rev")
- ("JT" . "Educational psychology review")
- ("JID" . "9885342")
- ("PMC" . "PMC3498956")
- ("MID" . "NIHMS395714")
- ("EDAT" . "2012/11/20 06:00")
- ("MHDA" . "2012/11/20 06:00")
- ("CRDT" . "2012/11/20 06:00")
- ("PHST" . "2012/07/24 [epublish]")
- ("AID" . "10.1007/s10648-012-9199-6 [doi]")
- ("PST" . "ppublish")
- ("SO" . "\nSO  - "))
-#+END_SRC
-
-** PMID to bibtex entry
-The point of parsing the MEDLINE text is so we can make bibtex entries. We only support Journal articles for now.
-
-#+BEGIN_SRC emacs-lisp
-(defun pubmed-pmid-to-bibtex (pmid)
-  "Convert a PMID to a bibtex entry."
-  (let* ((data (pubmed-parse-medline pmid))
-        (type (cdr (assoc "PT" data)))
-        (title (cdr (assoc "TI" data)))
-        (authors (mapconcat 'cdr
-                            (-filter (lambda (x)
-                                       (string= (car x) "FAU"))
-                                     data)
-                            " and "))
-        (abstract (cdr (assoc "AB" data)))
-        (volume (cdr (assoc "VI" data)))
-        (issue (cdr (assoc "IP" data)))
-        (journal (cdr (assoc "JT" data)))
-        (year (cdr (assoc "DP" data)))
-        (pages (cdr (assoc "PG" data)))
-        (aid (cdr (assoc "AID" data))))
-
-    (cond
-     ((string= type "JOURNAL ARTICLE")
-      (concat "@article{,
- author = {" authors "},
- title = {" title "},
- abstract = {" abstract "},
- journal = {" journal "},
- volume = {" volume "},
- number = {" issue "},
- year = {" (car (split-string year)) "},
- pages = {" pages "},
- doi = {" (replace-regexp-in-string " \\[doi\\]" "" aid) "},
-}"))
-    (t
-     (message "No conversion for type: %s" type)))))
-#+END_SRC
-
-#+RESULTS:
-: pubmed-pmid-to-bibtex
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(pubmed-pmid-to-bibtex "23162369")
-#+END_SRC
-
-#+RESULTS:
-#+begin_example
-@article{,
- author = {Slavich, George M and Zimbardo, Philip G},
- title = {Transformational Teaching: Theoretical Underpinnings, Basic Principles, and Core 
-      Methods.},
- abstract = {Approaches to classroom instruction have evolved considerably over the past 50
-      years. This progress has been spurred by the development of several learning
-      principles and methods of instruction, including active learning,
-      student-centered learning, collaborative learning, experiential learning, and
-      problem-based learning. In the present paper, we suggest that these seemingly
-      different strategies share important underlying characteristics and can be viewed
-      as complimentary components of a broader approach to classroom instruction called
-      transformational teaching. Transformational teaching involves creating dynamic
-      relationships between teachers, students, and a shared body of knowledge to
-      promote student learning and personal growth. From this perspective, instructors 
-      are intellectual coaches who create teams of students who collaborate with each
-      other and with their teacher to master bodies of information. Teachers assume the
-      traditional role of facilitating students' acquisition of key course concepts,
-      but do so while enhancing students' personal development and attitudes toward
-      learning. They accomplish these goals by establishing a shared vision for a
-      course, providing modeling and mastery experiences, challenging and encouraging
-      students, personalizing attention and feedback, creating experiential lessons
-      that transcend the boundaries of the classroom, and promoting ample opportunities
-      for preflection and reflection. We propose that these methods are synergistically
-      related and, when used together, maximize students' potential for intellectual
-      and personal growth.},
- journal = {Educational psychology review},
- volume = {24},
- number = {4},
- year = {2012},
- pages = {569-608},
- doi = {10.1007/s10648-012-9199-6},
-}
-#+end_example
-
-And we probably want to be able to insert a bibtex entry
-
-#+BEGIN_SRC emacs-lisp
-(defun pubmed-insert-bibtex-from-pmid (pmid)
- "Insert a bibtex entry at point derived from PMID.
-You must clean the entry after insertion."
- (interactive "sPMID: ")
- (insert (pubmed-pmid-to-bibtex pmid)))
-#+END_SRC
-
-#+RESULTS:
-: pubmed-insert-bibtex-from-pmid
-
-Here is an example of a cleaned entry:
-#+BEGIN_SRC bibtex :tangle no
-@article{slavich-2012-trans-teach,
-  author =      {Slavich, George M and Zimbardo, Philip G},
-  title =       {Transformational Teaching: Theoretical
-                  Underpinnings, Basic Principles, and Core Methods.},
-  journal =     {Educational psychology review},
-  volume =      24,
-  number =      4,
-  pages =       {569-608},
-  year =        2012,
-  doi =                 {10.1007/s10648-012-9199-6},
-  abstract =    {Approaches to classroom instruction have evolved
-                  considerably over the past 50 years. This progress
-                  has been spurred by the development of several
-                  learning principles and methods of instruction,
-                  including active learning, student-centered
-                  learning, collaborative learning, experiential
-                  learning, and problem-based learning. In the present
-                  paper, we suggest that these seemingly different
-                  strategies share important underlying
-                  characteristics and can be viewed as complimentary
-                  components of a broader approach to classroom
-                  instruction called transformational
-                  teaching. Transformational teaching involves
-                  creating dynamic relationships between teachers,
-                  students, and a shared body of knowledge to promote
-                  student learning and personal growth. From this
-                  perspective, instructors are intellectual coaches
-                  who create teams of students who collaborate with
-                  each other and with their teacher to master bodies
-                  of information. Teachers assume the traditional role
-                  of facilitating students' acquisition of key course
-                  concepts, but do so while enhancing students'
-                  personal development and attitudes toward
-                  learning. They accomplish these goals by
-                  establishing a shared vision for a course, providing
-                  modeling and mastery experiences, challenging and
-                  encouraging students, personalizing attention and
-                  feedback, creating experiential lessons that
-                  transcend the boundaries of the classroom, and
-                  promoting ample opportunities for preflection and
-                  reflection. We propose that these methods are
-                  synergistically related and, when used together,
-                  maximize students' potential for intellectual and
-                  personal growth.},
-}
-#+END_SRC
-
-** PMID to xml
-We can also get xml of the MEDLINE data. The web page here also wraps the xml in a <pre> block and escapes the <> with &lt; and &gt;, which we have to undo. I have not used this code for anything, so I am not sure how good the xml code is.
-
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el
-(defun pubmed-get-medline-xml (pmid)
-  "Get MEDLINE xml for PMID as a string."
-  (interactive)
-  (with-current-buffer
-    (url-retrieve-synchronously
-     (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=xml&format=text" pmid))
-    (goto-char (point-min))
-    (while (search-forward "&lt;" nil t)
-      (replace-match "<"))
-    (goto-char (point-min))
-    (while (search-forward "&gt;" nil t)
-      (replace-match ">"))
-    (goto-char (point-min))   
-                          
-    (let ((p1 (search-forward "<pre>"))
-         (p2 (search-forward "</pre>")))
-      (buffer-substring (+ 1 p1) (- p2 6)))))
-#+END_SRC
-
-#+RESULTS:
-: pubmed-get-medline-xml
-
-#+BEGIN_SRC emacs-lisp :tangle no
-(pubmed-get-medline-xml "23162369")
-#+END_SRC
-
-#+RESULTS:
-#+begin_example
-<PubmedArticle>
-    <MedlineCitation Status="Publisher" Owner="NLM">
-        <PMID Version="1">23162369</PMID>
-        <DateCreated>
-            <Year>2012</Year>
-            <Month>11</Month>
-            <Day>19</Day>
-        </DateCreated>
-        <Article PubModel="Print-Electronic">
-            <Journal>
-                <ISSN IssnType="Print">1040-726X</ISSN>
-                <JournalIssue CitedMedium="Print">
-                    <Volume>24</Volume>
-                    <Issue>4</Issue>
-                    <PubDate>
-                        <Year>2012</Year>
-                        <Month>Dec</Month>
-                    </PubDate>
-                </JournalIssue>
-                <Title>Educational psychology review</Title>
-                <ISOAbbreviation>Educ Psychol Rev</ISOAbbreviation>
-            </Journal>
-            <ArticleTitle>Transformational Teaching: Theoretical Underpinnings, Basic Principles, and Core Methods.</ArticleTitle>
-            <Pagination>
-                <MedlinePgn>569-608</MedlinePgn>
-            </Pagination>
-            <Abstract>
-                <AbstractText>Approaches to classroom instruction have evolved considerably over the past 50 years. This progress has been spurred by the development of several learning principles and methods of instruction, including active learning, student-centered learning, collaborative learning, experiential learning, and problem-based learning. In the present paper, we suggest that these seemingly different strategies share important underlying characteristics and can be viewed as complimentary components of a broader approach to classroom instruction called transformational teaching. Transformational teaching involves creating dynamic relationships between teachers, students, and a shared body of knowledge to promote student learning and personal growth. From this perspective, instructors are intellectual coaches who create teams of students who collaborate with each other and with their teacher to master bodies of information. Teachers assume the traditional role of facilitating students' acquisition of key course concepts, but do so while enhancing students' personal development and attitudes toward learning. They accomplish these goals by establishing a shared vision for a course, providing modeling and mastery experiences, challenging and encouraging students, personalizing attention and feedback, creating experiential lessons that transcend the boundaries of the classroom, and promoting ample opportunities for preflection and reflection. We propose that these methods are synergistically related and, when used together, maximize students' potential for intellectual and personal growth.</AbstractText>
-            </Abstract>
-            <AuthorList>
-                <Author>
-                    <LastName>Slavich</LastName>
-                    <ForeName>George M</ForeName>
-                    <Initials>GM</Initials>
-                    <AffiliationInfo>
-                        <Affiliation>Cousins Center for Psychoneuroimmunology and Department of Psychiatry and Biobehavioral Sciences, University of California, Los Angeles, UCLA Medical Plaza 300, Room 3156, Los Angeles, CA 90095-7076, USA.</Affiliation>
-                    </AffiliationInfo>
-                </Author>
-                <Author>
-                    <LastName>Zimbardo</LastName>
-                    <ForeName>Philip G</ForeName>
-                    <Initials>PG</Initials>
-                </Author>
-            </AuthorList>
-            <Language>ENG</Language>
-            <GrantList>
-                <Grant>
-                    <GrantID>R01 AG026364</GrantID>
-                    <Acronym>AG</Acronym>
-                    <Agency>NIA NIH HHS</Agency>
-                    <Country>United States</Country>
-                </Grant>
-                <Grant>
-                    <GrantID>T32 MH019925</GrantID>
-                    <Acronym>MH</Acronym>
-                    <Agency>NIMH NIH HHS</Agency>
-                    <Country>United States</Country>
-                </Grant>
-            </GrantList>
-            <PublicationTypeList>
-                <PublicationType UI="">JOURNAL ARTICLE</PublicationType>
-            </PublicationTypeList>
-            <ArticleDate DateType="Electronic">
-                <Year>2012</Year>
-                <Month>7</Month>
-                <Day>24</Day>
-            </ArticleDate>
-        </Article>
-        <MedlineJournalInfo>
-            <MedlineTA>Educ Psychol Rev</MedlineTA>
-            <NlmUniqueID>9885342</NlmUniqueID>
-            <ISSNLinking>1040-726X</ISSNLinking>
-        </MedlineJournalInfo>
-    </MedlineCitation>
-    <PubmedData>
-        <History>
-            <PubMedPubDate PubStatus="epublish">
-                <Year>2012</Year>
-                <Month>7</Month>
-                <Day>24</Day>
-            </PubMedPubDate>
-            <PubMedPubDate PubStatus="entrez">
-                <Year>2012</Year>
-                <Month>11</Month>
-                <Day>20</Day>
-                <Hour>6</Hour>
-                <Minute>0</Minute>
-            </PubMedPubDate>
-            <PubMedPubDate PubStatus="pubmed">
-                <Year>2012</Year>
-                <Month>11</Month>
-                <Day>20</Day>
-                <Hour>6</Hour>
-                <Minute>0</Minute>
-            </PubMedPubDate>
-            <PubMedPubDate PubStatus="medline">
-                <Year>2012</Year>
-                <Month>11</Month>
-                <Day>20</Day>
-                <Hour>6</Hour>
-                <Minute>0</Minute>
-            </PubMedPubDate>
-        </History>
-        <PublicationStatus>ppublish</PublicationStatus>
-        <ArticleIdList>
-            <ArticleId IdType="doi">10.1007/s10648-012-9199-6</ArticleId>
-            <ArticleId IdType="pubmed">23162369</ArticleId>
-            <ArticleId IdType="pmc">PMC3498956</ArticleId>
-            <ArticleId IdType="mid">NIHMS395714</ArticleId>
-        </ArticleIdList>
-        <?nihms?>
-    </PubmedData>
-</PubmedArticle>
-
-#+end_example
-
-* Pubmed Central (PMC) link
-A PMCID starts with PMC and is followed by numbers. The PMCID is a unique reference number or identifier that is assigned to every article that is accepted into PMC. The PMCID is also used by recipients of NIH funding to demonstrate compliance with the NIH Public Access policy. The PMCID can be found in both PMC and PubMed.
-
-Here we define a new link. Clicking on it simply opens a webpage to the article.
-
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el :results silent
-(org-add-link-type
- "pmcid"
- ;; clicking
- (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/%s" link-string)))
- ;; formatting
-(lambda (keyword desc format)
-   (cond
-    ((eq format 'html)
-     (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/%s\">pmcid:%s</a>" keyword keyword))
-    ((eq format 'latex)
-     (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/%s}" keyword)))))
-#+END_SRC
-
-* NIHMSID 
-The NIHMSID is a preliminary article identifier that applies only to manuscripts deposited through the NIHMS system. The NIHMSID is only valid for compliance reporting for 90 days after the publication date of an article. Once the Web version of the NIHMS submission is approved for inclusion in PMC and the corresponding citation is in PubMed, the article will also be assigned a PMCID.
-
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el :results silent
-(org-add-link-type
- "nihmsid"
- ;; clicking
- (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s" link-string)))
- ;; formatting
-(lambda (keyword desc format)
-   (cond
-    ((eq format 'html)
-     (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid//%s\">nihmsid:%s</a>" keyword keyword))
-    ((eq format 'latex)
-     ;; write out the latex command
-     (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}" keyword)))))
-#+END_SRC
-
-
-
-
-* End of code
-#+BEGIN_SRC emacs-lisp :tangle pubmed.el
-(provide 'pubmed)
-#+END_SRC
-
-* Build                                                                   :noexport:
-This code will tangle the elisp code out to pubmed.el and load it.
-
-[[elisp:(org-babel-load-file "pubmed.org")]]
-
-
-
diff --git a/sci-id.el b/sci-id.el
new file mode 100644 (file)
index 0000000..f204c38
--- /dev/null
+++ b/sci-id.el
@@ -0,0 +1,67 @@
+;;; sci-id.el --- org-mode links for scientific IDs  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; New org-mode links for scientific IDs like orcid (http://orcid.org) and researcherid (http://www.researcherid.com)
+;; orcid:0000-0003-2625-9232
+;; researcherid:A-2363-2010
+
+;;; Code:
+(org-add-link-type
+ "orcid"
+ (lambda
+   (link-string)
+   (browse-url
+    (format "http://orcid.org/%s" link-string)))
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'html)
+     (format "<a href=\"http://orcid.org/%s\">orcid:%s</a>" keyword keyword)))))
+
+(org-add-link-type
+ "researcherid"
+ (lambda
+    (link-string)
+    (browse-url
+     (format "http://www.researcherid.com/rid/%s" link-string)))
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'html)
+     (format "<a href=\"http://www.researcherid.com/rid/%s\">ResearcherID:%s</a>"
+            keyword keyword)))))
+
+(org-add-link-type
+ "scopusid"
+ (lambda
+   (link-string)
+   (browse-url
+    (format
+     "http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s"
+     link-string)))
+ (lambda (keyword desc format)
+   (cond
+    ((eq format 'latex)
+     (format "\\href{http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s}{%s}" keyword (or desc keyword)))
+    ((eq format 'html)
+     (format "<a href=\"http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s\">scopusid:%s</a>" keyword keyword)))))
+
+(provide 'sci-id)
+;;; sci-id.el ends here
index 73a76f983bc1846f6f9bab61ac75739378a92721..3f4bc79fb84ff80ab8a4f865dd419785a05bd459 100644 (file)
--- a/test.bib
+++ b/test.bib
   doi =                 {10.1016/j.jcat.2012.12.015},
   url =                 {http://dx.doi.org/10.1016/j.jcat.2012.12.015},
 }
+
+@ARTICLE{2015arXiv150301742H,
+   author = {{Hatch}, H.~W. and {Mittal}, J. and {Shen}, V.~K.},
+    title = "{Computational Study of Trimer Self-Assembly and Fluid Phase Behavior}",
+  journal = {ArXiv e-prints},
+archivePrefix = "arXiv",
+   eprint = {1503.01742},
+ primaryClass = "cond-mat.soft",
+ keywords = {Condensed Matter - Soft Condensed Matter, Condensed Matter - Statistical Mechanics},
+     year = 2015,
+    month = mar,
+   adsurl = {http://adsabs.harvard.edu/abs/2015arXiv150301742H},
+  adsnote = {Provided by the SAO/NASA Astrophysics Data System}
+}
+
+
+
+
+@article{Brennan1,
+       Author = {Michael J. Brennan and Eduardo S. Schwartz},
+       Journal = {Journal of Financial and Quantitative Analysis},
+       Pages = {461--474},
+       Title = {Finite Difference Methods and Jump Processes Arising in the Pricing of Contingent Claims: {A} Synthesis},
+       Volume = {13},
+       Year = {1978}}
+
+
+@article{BoyleBroadieGlasserman:97,
+       author = {Phelim P. Boyle and Mark Broadie and Paul Glasserman},
+       journal = {Journal of Economic Dynamics and Control},
+       pages = {1267--1321},
+       title = {{Monte} {Carlo} Methods for Security Pricing},
+       volume = {21},
+       year = {1997}}
+
+@book{Glasserman:03,
+       address = {New York},
+       author = {Paul Glasserman},
+       publisher = {Springer},
+       title = {{Monte} {Carlo} Methods in Financial Engineering},
+       year = {2003}}
+
+
+@TechReport{ReinerRubinstein:91,
+  author =       {Eric Reiner and Mark Rubinstein},
+  title =        "Exotic Options",
+  institution =  "U.C. Berkeley",
+  year =         1991,
+  type =         "Working Paper",
+}
diff --git a/wos.el b/wos.el
new file mode 100644 (file)
index 0000000..b8bbba8
--- /dev/null
+++ b/wos.el
@@ -0,0 +1,63 @@
+;;; wos.el --- WEb of Science functions              -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015  John Kitchin
+
+;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Adds a new org-mode link for a search in Web of Science.
+
+
+;;; Code:
+(org-add-link-type
+ "wos-search"
+ (lambda (path)
+   (browse-url
+    (format  "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
+             (s-join "+"
+              (split-string path)))))
+ ;; formatting function. Assume html
+ (lambda (link desc format)
+   (format "<a href=\"%s\">%s</a>"
+           (format  "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
+             (s-join "+"
+              (split-string link)))
+           (format "wos:%s" link)
+           )))
+
+
+(defun wos-search ()
+  "Open the word at point or selection in Web of Science."
+  ;; the url was derived from this page: http://wokinfo.com/webtools/searchbox/
+  (interactive)
+  (browse-url
+   (format "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
+    (if (region-active-p)
+       (mapconcat 'identity (split-string
+                             (buffer-substring (region-beginning)
+                                               (region-end))) "+")
+      (thing-at-point 'word)))))
+
+
+(defun wos ()
+  "Open Web of Science search page in a browser."
+  (interactive)
+  (browse-url "http://apps.webofknowledge.com"))
+
+(provide 'wos)
+;;; wos.el ends here
diff --git a/x2bib.el b/x2bib.el
new file mode 100644 (file)
index 0000000..8087212
--- /dev/null
+++ b/x2bib.el
@@ -0,0 +1,108 @@
+;;; x2bib.el --- Bibliography conversion to Bibtex
+
+;;; Header:
+
+;;; Commentary:
+
+;; This module is more for my convenience to convert bibliography files to bibtex.  This can be done at the command line, for example, but I want to do it in Emacs.  There are a few scenarios where this happens.
+;; 1. Someone sends me a non-Bibtex file (Endnote, etc...)
+;; 2. From some online search I select many references and there is no export to Bibtex option, e.g. from Web of Science.
+
+;; This code is mostly wrappers around the command line utilities at http://sourceforge.net/p/bibutils/home/Bibutils.
+
+;; Here are the commands that are available.
+
+;; bib2xml     convert BibTeX to MODS XML intermediate
+;; biblatex2xml        convert BibLaTeX to MODS XML intermediate
+;; copac2xml   convert COPAC format references to MODS XML intermediate
+;; end2xml     convert EndNote (Refer format) to MODS XML intermediate
+;; endx2xml    convert EndNote XML to MODS XML intermediate
+;; isi2xml     convert ISI web of science to MODS XML intermediate
+;; med2xml     convert Pubmed XML references to MODS XML intermediate
+;; modsclean   a MODS to MODS converter for testing puposes mostly
+;; ris2xml     convert RIS format to MODS XML intermediate
+;; xml2ads     convert MODS XML intermediate into Smithsonian Astrophysical Observatory (SAO)/National Aeronautics and Space Administration (NASA) Astrophyics Data System or ADS reference format (converter submitted by Richard Mathar)
+;; xml2bib     convert MODS XML intermediate into BibTeX
+;; xml2end     convert MODS XML intermediate into format for EndNote
+;; xml2isi     convert MODS XML intermediate to ISI format
+;; xml2ris     convert MODS XML intermediate into RIS format
+;; xml2wordbib convert MODS XML intermediate into Word 2007 bibliography format
+
+
+;;; Code:
+
+;; ** RIS to bibtex
+;; RIS can be pretty easily exported from Endnote. Here is a function to read an RIS file and convert it to bibtex which is inserted at point. Note that there is often other output from the commands. We try to comment them out here, but you should probably inspect the entries, and do other bibtex file compliance checks.
+
+(defun ris2bib (risfile &optional verbose)
+  "Convert RISFILE to bibtex and insert at point.
+Without a prefix arg, stderr is diverted."
+ (interactive
+  (list (read-file-name "RIS file:")
+        (prefix-numeric-value current-prefix-arg)))
+ (let ((result (shell-command-to-string
+               (concat
+                (format
+                 "ris2xml %s | xml2bib -w"
+                 risfile)
+                (unless verbose " 2> /dev/null")))))
+   ;; make some lines into comments.
+   (setq result (replace-regexp-in-string
+                "^xml2bib:"
+                "% xml2bib:"
+                 result))
+   (setq result (replace-regexp-in-string
+                "^ris2xml:"
+                 "% ris2xml"
+                 result))
+   (setq result (replace-regexp-in-string
+                "^     Defaulting"
+                "%     Defaulting"
+                result))
+   (insert result)))
+
+;; ** Pubmed XML to bibtex
+;; In http://www.ncbi.nlm.nih.gov/pubmed/ you can select entries, and then send them to a file. If you choose Pubmed XML as the format, then you can use this function to convert it to bibtex.
+
+(defun medxml2bib (medfile &optional verbose)
+ "Convert MEDFILE (in Pubmed xml) to bibtex and insert at point.
+Without a prefix arg, stderr is diverted."
+ (interactive
+  (list (read-file-name "MED file:")
+        (prefix-numeric-value current-prefix-arg)))
+ (let ((result (shell-command-to-string
+               (concat
+                (format
+                 "med2xml %s | xml2bib -w"
+                 medfile)
+                (unless verbose " 2> /dev/null")))))
+   ;; make some lines into comments.
+   (setq result (replace-regexp-in-string
+                "^xml2bib:"
+                "% xml2bib:"
+                 result))
+   (setq result (replace-regexp-in-string
+                "^med2xml:"
+                 "% med2xml"
+                 result))
+   (setq result (replace-regexp-in-string
+                "^     Defaulting"
+                "%     Defaulting"
+                result))
+   (insert result)))
+
+;; ** Clean up all the entries
+
+;; Finally, after you put the new entries in, you probably need to do some clean up actions. This little function does that.
+
+(defun clean-entries ()
+ "Map over bibtex entries and clean them."
+ (interactive)
+ (bibtex-map-entries
+  (lambda (a b c)
+   (ignore-errors
+   (org-ref-clean-bibtex-entry)))))
+
+(provide 'x2bib)
+
+;;; x2bib.el ends here