polish link timer code.
[org-ref.git] / org-ref.org
1 #+TITLE: Org-ref - The best reference handling for org-mode
2 #+AUTHOR: John Kitchin
3 #+DATE: April 29, 2014
4
5 * Introduction
6
7 This document is an experiment at creating a literate program to provide similar features as reftex for org-mode referencing. These features include:
8
9 1. using completion to create links
10 2. storing links to places,
11 3. Clickable links that do useful things
12 4. Exportable links to LaTeX
13 5. Utility functions for dealing with bibtex files and org-files
14
15 Some additional features include
16 1. Get minibuffer messages for the cite/ref/label link under point
17
18 With helm integration (default) you can:
19
20 1. C-c ] to insert a citation link
21   in helm-bibtex
22    - Enter to insert or append citation(s)
23    - C-u Enter to insert an alternative cite link
24    - C-u C-u Enter to replace the citation at point
25 2. C-u C-c ] to insert a ref link with helm completion
26 3. C-u C-u C-c ] to insert a label with completion
27 4. M-x org-ref to get a helm completion buffer with link checks, utilities and export options
28
29 ** Header
30 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
31 ;;; org-ref.el --- setup bibliography, cite, ref and label org-mode links.
32
33 ;; Copyright(C) 2014 John Kitchin
34
35 ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
36 ;; This file is not currently part of GNU Emacs.
37
38 ;; This program is free software; you can redistribute it and/or
39 ;; modify it under the terms of the GNU General Public License as
40 ;; published by the Free Software Foundation; either version 2, or (at
41 ;; your option) any later version.
42
43 ;; This program is distributed in the hope that it will be useful, but
44 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
45 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
46 ;; General Public License for more details.
47
48 ;; You should have received a copy of the GNU General Public License
49 ;; along with this program ; see the file COPYING.  If not, write to
50 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
51 ;; Boston, MA 02111-1307, USA.
52
53 ;;; Commentary:
54 ;;
55 ;; Lisp code to setup bibliography cite, ref and label org-mode links.  also
56 ;; sets up reftex and helm for org-mode citations. The links are clickable and
57 ;; do things that are useful. You should really read org-ref.org for details.
58 ;;
59 ;; Package-Requires: ((dash) (helm) (helm-bibtex))
60 #+END_SRC
61
62 ** requires
63 The only external require is reftex-cite
64
65 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
66 (require 'reftex-cite)
67 (require 'dash)
68 (require 'helm)
69 (require 'helm-bibtex)
70 #+END_SRC
71
72 ** Custom variables
73 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.
74
75 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
76 (defgroup org-ref nil
77   "customization group for org-ref")
78
79 (defcustom org-ref-bibliography-notes
80   nil
81   "filename to where you will put all your notes about an entry in
82   the default bibliography."
83   :type 'file
84   :group 'org-ref)
85
86 (defcustom org-ref-default-bibliography
87   nil
88   "list of bibtex files to search for. You should use full-paths for each file."
89   :type '(repeat :tag "List of bibtex files" file)
90   :group 'org-ref)
91
92 (defcustom org-ref-pdf-directory
93   nil
94   "directory where pdfs are stored by key. put a trailing / in"
95   :type 'directory
96   :group 'org-ref)
97
98 (defcustom org-ref-default-citation-link
99   "cite"
100   "The default type of citation link to use"
101   :type 'string
102   :group 'org-ref)
103
104 (defcustom org-ref-insert-cite-key
105   "C-c ]"
106   "Keyboard shortcut to insert a citation."
107   :type 'string
108   :group 'org-ref)
109
110 (defcustom org-ref-bibliography-entry-format
111   '(("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>.")
112
113     ("book" . "%a, %t, %u (%y).")
114
115     ("proceedings" . "%e, %t in %S, %u (%y).")
116
117     ("inproceedings" . "%a, %t, %p, in %b, edited by %e, %u (%y)"))
118
119   "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."
120   :type 'string
121   :group 'org-ref)
122
123 (defcustom org-ref-open-notes-function
124   (lambda ()
125     (org-show-entry)
126     (show-branches)
127     (show-children)
128     (org-cycle '(64))
129     ;;(org-tree-to-indirect-buffer)
130     (outline-previous-visible-heading 1)
131     (recenter-top-bottom 0))
132   "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"
133 :type 'function
134 :group 'org-ref)
135
136
137 (defcustom org-ref-open-pdf-function
138    'org-ref-open-pdf-at-point
139 "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'."
140   :type 'function
141   :group 'org-ref)
142
143
144 (defcustom org-ref-insert-cite-function
145   'org-ref-helm-insert-cite-link
146   "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."
147  :type 'function
148  :group 'org-ref)
149
150
151 (defcustom org-ref-cite-onclick-function
152   'org-ref-cite-click-helm
153   "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."
154  :type 'function
155  :group 'org-ref)
156
157 (defcustom org-ref-show-citation-on-enter t
158   "If non-nil add a hook function to show the citation summary in
159   the minibuffer just by putting the cursor in a link"
160  :group 'org-ref)
161
162 #+END_SRC
163
164 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.
165
166 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
167 (defcustom org-ref-cite-types
168   '("cite" "nocite" ;; the default latex cite commands
169     ;; natbib cite commands, http://ctan.unixbrain.com/macros/latex/contrib/natbib/natnotes.pdf
170     "citet" "citet*" "citep" "citep*"
171     "citealt" "citealt*" "citealp" "citealp*"
172     "citenum" "citetext"
173     "citeauthor" "citeauthor*"
174     "citeyear" "citeyear*"
175     "Citet" "Citep" "Citealt" "Citealp" "Citeauthor"
176     ;; biblatex commands
177     ;; http://ctan.mirrorcatalogs.com/macros/latex/contrib/biblatex/doc/biblatex.pdf
178     "Cite"
179     "parencite" "Parencite"
180     "footcite" "footcitetext"
181     "textcite" "Textcite"
182     "smartcite" "Smartcite"
183     "cite*" "parencite*" "supercite"
184     "autocite" "Autocite" "autocite*" "Autocite*"
185     "Citeauthor*"
186     "citetitle" "citetitle*"
187     "citedate" "citedate*"
188     "citeurl"
189     "fullcite" "footfullcite"
190     ;; "volcite" "Volcite" cannot support the syntax
191     "notecite" "Notecite"
192     "pnotecite" "Pnotecite"
193     "fnotecite"
194     ;; multicites. Very limited support for these.
195     "cites" "Cites" "parencites" "Parencites"
196     "footcites" "footcitetexts"
197     "smartcites" "Smartcites" "textcites" "Textcites"
198     "supercites" "autocites" "Autocites"
199     ;; for the bibentry package
200     "bibentry"
201     )
202   "List of citation types known in org-ref"
203   :type '(repeat :tag "List of citation types" string)
204   :group 'org-ref)
205 #+END_SRC
206
207 We need a hook variable to store user-defined bibtex entry cleaning functions
208 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
209 (defcustom org-ref-clean-bibtex-entry-hook nil
210   "Hook that is run in org-ref-clean-bibtex-entry. The functions should take no arguments, and operate on the bibtex entry at point."
211   :group 'org-ref
212   :type 'hook)
213 #+END_SRC
214
215 ** Program variables
216 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
217 (defvar org-ref-bibliography-files
218   nil
219   "variable to hold bibliography files to be searched")
220 #+END_SRC
221
222 ** org-mode / reftex setup
223
224 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.
225
226 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
227 (require 'reftex)
228 (defun org-mode-reftex-setup ()
229     (and (buffer-file-name)
230          (file-exists-p (buffer-file-name))
231          (global-auto-revert-mode t)
232          ;; I do not remember why I put this next line in. It doesn't
233          ;; work for org-files. Nothing very bad happens, but it gives
234          ;; an annoying error. Commenting it out for now.
235          ;(reftex-parse-all
236          )
237     (make-local-variable 'reftex-cite-format)
238     (setq reftex-cite-format 'org))
239
240 ;; define key for inserting citations
241 (define-key org-mode-map
242   (kbd org-ref-insert-cite-key)
243   org-ref-insert-cite-function)
244
245 (add-hook 'org-mode-hook 'org-mode-reftex-setup)
246
247 (eval-after-load 'reftex-vars
248   '(progn
249       (add-to-list 'reftex-cite-format-builtin
250                    '(org "Org-mode citation"
251                          ((?\C-m . "cite:%l")     ; default
252                           (?d . ",%l")            ; for appending
253                           (?a . "autocite:%l")
254                           (?t . "citet:%l")
255                           (?T . "citet*:%l")
256                           (?p . "citep:%l")
257                           (?P . "citep*:%l")
258                           (?h . "citeauthor:%l")
259                           (?H . "citeauthor*:%l")
260                           (?y . "citeyear:%l")
261                           (?x . "citetext:%l")
262                           (?n . "nocite:%l")
263                           )))))
264 #+END_SRC
265
266 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.
267
268 #+BEGIN_SRC emacs-lisp :tangle no
269 ;; add new format
270 (setf (nth 2 (assoc 'org reftex-cite-format-builtin))
271       (append (nth 2 (assoc 'org reftex-cite-format-builtin)) '((?W  . "textcite:%l")
272             (?z  . "newcite:%l"))))
273 #+END_SRC
274
275 You can define a new citation link like this:
276 #+BEGIN_SRC emacs-lisp :tangle no
277 (org-ref-define-citation-link "citez" ?z)
278 #+END_SRC
279
280 ** Messages for link at cursor
281 Here we setup code that shows you a context message for the element under the cursor when emacs is idle.
282 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
283 (defvar org-ref-message-timer nil
284   "Variable to store the link message timer in.")
285
286
287 (when org-ref-show-citation-on-enter
288  (setq org-ref-message-timer
289        (run-with-idle-timer 0.5 t 'org-ref-link-message)))
290
291
292 (defun org-ref-show-link-messages ()
293   "Turn on link messages. You will see a message in the
294 minibuffer when on a cite, ref or label link."
295   (interactive)
296   (or org-ref-message-timer
297       (setq org-ref-message-timer
298             (run-with-idle-timer 0.5 t 'org-ref-link-message))))
299
300
301 (defun org-ref-cancel-link-messages ()
302   "Stop showing messages in minibuffer when on a link."
303   (interactive)
304   (cancel-timer org-ref-message-timer)
305   (setq org-ref-message-timer nil))
306
307 ;; this approach caused the selected region to not be highlighted any more.
308 ; (add-hook 'post-command-hook 'org-ref-link-message))
309 ; (remove-hook 'post-command-hook 'org-ref-link-message))
310 #+END_SRC
311
312 ** Messages for context under mouse pointer
313 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.
314
315 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.
316
317 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
318 (defvar org-ref-last-mouse-pos nil
319  "Stores last mouse position for use in `org-ref-mouse-message'.")
320
321 (defun org-ref-can-move-p ()
322   "See if a character is under the mouse. If so return the position for `goto-char'."
323   (let* ((line (cddr org-ref-last-mouse-pos))
324          (col  (cadr org-ref-last-mouse-pos)))
325     (save-excursion
326       (goto-char (window-start))
327       (forward-line line)
328       (if
329           (> (- (line-end-position) (line-beginning-position)) col)
330           (progn  (forward-char col) (point))
331         nil))))
332
333
334 (defun org-ref-mouse-message ()
335   "Display message for link under mouse cursor"
336   (interactive)
337   (when (not (equal (mouse-position) org-ref-last-mouse-pos))
338     (setq org-ref-last-mouse-pos (mouse-position))
339     (let ((p (org-ref-can-move-p)))
340       (when p
341           (save-excursion
342             (goto-char p)
343             (org-ref-link-message))))))
344
345
346 (defvar org-ref-message-timer-mouse nil
347   "Store mouse timer.")
348
349
350 (defvar org-ref-mouse-message-interval 0.5
351   "How often to run the mouse message timer in seconds")
352
353
354 (defun org-ref-mouse-messages-on ()
355   "Turn on mouse messages."
356   (interactive)
357   (or org-ref-message-timer-mouse
358       (setq org-ref-message-timer-mouse
359             (run-at-time "0.5 sec"
360                          org-ref-mouse-message-interval
361                          'org-ref-mouse-message))))
362
363
364 (defun org-ref-mouse-messages-off ()
365   "Turn off mouse messages"
366   (interactive)
367   (cancel-timer org-ref-message-timer-mouse)
368   (setq org-ref-message-timer-mouse nil)
369   (message "Mouse messages are off"))
370 #+END_SRC
371
372 #+RESULTS:
373 : org-ref-mouse-messages-off
374
375 * Links
376 Most of this library is the creation of functional links to help with references and citations.
377 ** General utilities
378 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.
379
380 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
381 (defun org-ref-strip-string (string)
382   "strip leading and trailing whitespace from the string"
383   (replace-regexp-in-string
384    (concat search-whitespace-regexp "$" ) ""
385    (replace-regexp-in-string
386     (concat "^" search-whitespace-regexp ) "" string)))
387 #+END_SRC
388
389 It is helpful to make the previous function operate on a list of strings here.
390
391 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
392 (defun org-ref-split-and-strip-string (string)
393   "split key-string and strip keys. Assumes the key-string is comma delimited"
394   (mapcar 'org-ref-strip-string (split-string string ",")))
395 #+END_SRC
396
397 ** bibliography and bibliographystyle
398 *** An html bibliography
399
400 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.
401
402 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
403 (defun org-ref-reftex-get-bib-field (field entry &optional format)
404   "similar to reftex-get-bib-field, but removes enclosing braces and quotes"
405   (let ((result))
406     (setq result (reftex-get-bib-field field entry format))
407     (when (and (not (string= result "")) (string= "{" (substring result 0 1)))
408       (setq result (substring result 1 -1)))
409     (when (and (not (string= result "")) (string= "\"" (substring result 0 1)))
410       (setq result (substring result 1 -1)))
411       result))
412
413 (defun org-ref-reftex-format-citation (entry format)
414   "return a formatted string for the bibtex entry (from bibtex-parse-entry) according
415 to the format argument. The format is a string with these percent escapes.
416
417 In the format, the following percent escapes will be expanded.
418
419 %l   The BibTeX label of the citation.
420 %a   List of author names, see also `reftex-cite-punctuation'.
421 %2a  Like %a, but abbreviate more than 2 authors like Jones et al.
422 %A   First author name only.
423 %e   Works like %a, but on list of editor names. (%2e and %E work a well)
424
425 It is also possible to access all other BibTeX database fields:
426 %b booktitle     %c chapter        %d edition    %h howpublished
427 %i institution   %j journal        %k key        %m month
428 %n number        %o organization   %p pages      %P first page
429 %r address       %s school         %u publisher  %t title
430 %v volume        %y year
431 %B booktitle, abbreviated          %T title, abbreviated
432 %U url
433 %D doi
434 %S series
435
436 Usually, only %l is needed.  The other stuff is mainly for the echo area
437 display, and for (setq reftex-comment-citations t).
438
439 %< as a special operator kills punctuation and space around it after the
440 string has been formatted.
441
442 A pair of square brackets indicates an optional argument, and RefTeX
443 will prompt for the values of these arguments.
444
445 Beware that all this only works with BibTeX database files.  When
446 citations are made from the \bibitems in an explicit thebibliography
447 environment, only %l is available."
448   ;; Format a citation from the info in the BibTeX ENTRY
449
450   (unless (stringp format) (setq format "\\cite{%l}"))
451
452   (if (and reftex-comment-citations
453            (string-match "%l" reftex-cite-comment-format))
454       (error "reftex-cite-comment-format contains invalid %%l"))
455
456   (while (string-match
457           "\\(\\`\\|[^%]\\)\\(\\(%\\([0-9]*\\)\\([a-zA-Z]\\)\\)[.,;: ]*\\)"
458           format)
459     (let ((n (string-to-number (match-string 4 format)))
460           (l (string-to-char (match-string 5 format)))
461           rpl b e)
462       (save-match-data
463         (setq rpl
464               (cond
465                ((= l ?l) (concat
466                           (org-ref-reftex-get-bib-field "&key" entry)
467                           (if reftex-comment-citations
468                               reftex-cite-comment-format
469                             "")))
470                ((= l ?a) (reftex-format-names
471                           (reftex-get-bib-names "author" entry)
472                           (or n 2)))
473                ((= l ?A) (car (reftex-get-bib-names "author" entry)))
474                ((= l ?b) (org-ref-reftex-get-bib-field "booktitle" entry "in: %s"))
475                ((= l ?B) (reftex-abbreviate-title
476                           (org-ref-reftex-get-bib-field "booktitle" entry "in: %s")))
477                ((= l ?c) (org-ref-reftex-get-bib-field "chapter" entry))
478                ((= l ?d) (org-ref-reftex-get-bib-field "edition" entry))
479                ((= l ?D) (org-ref-reftex-get-bib-field "doi" entry))
480                ((= l ?e) (reftex-format-names
481                           (reftex-get-bib-names "editor" entry)
482                           (or n 2)))
483                ((= l ?E) (car (reftex-get-bib-names "editor" entry)))
484                ((= l ?h) (org-ref-reftex-get-bib-field "howpublished" entry))
485                ((= l ?i) (org-ref-reftex-get-bib-field "institution" entry))
486                ((= l ?j) (org-ref-reftex-get-bib-field "journal" entry))
487                ((= l ?k) (org-ref-reftex-get-bib-field "key" entry))
488                ((= l ?m) (org-ref-reftex-get-bib-field "month" entry))
489                ((= l ?n) (org-ref-reftex-get-bib-field "number" entry))
490                ((= l ?o) (org-ref-reftex-get-bib-field "organization" entry))
491                ((= l ?p) (org-ref-reftex-get-bib-field "pages" entry))
492                ((= l ?P) (car (split-string
493                                (org-ref-reftex-get-bib-field "pages" entry)
494                                "[- .]+")))
495                ((= l ?s) (org-ref-reftex-get-bib-field "school" entry))
496                ((= l ?S) (org-ref-reftex-get-bib-field "series" entry))
497                ((= l ?u) (org-ref-reftex-get-bib-field "publisher" entry))
498                ((= l ?U) (org-ref-reftex-get-bib-field "url" entry))
499                ((= l ?r) (org-ref-reftex-get-bib-field "address" entry))
500                ;; strip enclosing brackets from title if they are there
501                ((= l ?t) (org-ref-reftex-get-bib-field "title" entry))
502                ((= l ?T) (reftex-abbreviate-title
503                           (org-ref-reftex-get-bib-field "title" entry)))
504                ((= l ?v) (org-ref-reftex-get-bib-field "volume" entry))
505                ((= l ?y) (org-ref-reftex-get-bib-field "year" entry)))))
506
507       (if (string= rpl "")
508           (setq b (match-beginning 2) e (match-end 2))
509         (setq b (match-beginning 3) e (match-end 3)))
510       (setq format (concat (substring format 0 b) rpl (substring format e)))))
511   (while (string-match "%%" format)
512     (setq format (replace-match "%" t t format)))
513   (while (string-match "[ ,.;:]*%<" format)
514     (setq format (replace-match "" t t format)))
515   ;; also replace carriage returns, tabs, and multiple whitespaces
516   (setq format (replace-regexp-in-string "\n\\|\t\\|\s+" " " format))
517   format)
518
519 (defun org-ref-get-bibtex-entry-citation (key)
520   "returns a string for the bibliography entry corresponding to key, and formatted according to the type in `org-ref-bibliography-entry-format'"
521
522   (let ((org-ref-bibliography-files (org-ref-find-bibliography))
523         (file) (entry) (bibtex-entry) (entry-type) (format))
524
525     (setq file (catch 'result
526                  (loop for file in org-ref-bibliography-files do
527                        (if (org-ref-key-in-file-p key (file-truename file))
528                            (throw 'result file)
529                          (message "%s not found in %s" key (file-truename file))))))
530
531     (with-temp-buffer
532       (insert-file-contents file)
533       (bibtex-search-entry key nil 0)
534       (setq bibtex-entry (bibtex-parse-entry))
535       (setq entry-type (downcase (cdr (assoc "=type=" bibtex-entry))))
536       (setq format (cdr (assoc entry-type org-ref-bibliography-entry-format)))
537       (if format
538           (setq entry  (org-ref-reftex-format-citation bibtex-entry format))
539         (save-restriction
540           (bibtex-narrow-to-entry)
541           (setq entry (buffer-string)))))
542     entry))
543 #+END_SRC
544
545 #+RESULTS:
546 : org-ref-reftex-format-citation
547
548 Here is how to use the function. You call it with point in an entry in a bibtex file.
549
550 #+BEGIN_SRC emacs-lisp :tangle no
551 (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>."))
552   (org-ref-get-bibtex-entry-citation  "armiento-2014-high"))
553 #+END_SRC
554 #+RESULTS:
555 : 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>.
556
557 I am not sure why full author names are not used.
558
559 This code provides some functions to generate a simple sorted bibliography in html. First we get all the keys in the buffer.
560
561 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
562 (defun org-ref-get-bibtex-keys ()
563   "Return a list of unique keys in the buffer."
564   (let ((keys '()))
565     (org-element-map (org-element-parse-buffer) 'link
566       (lambda (link)
567         (let ((plist (nth 1 link)))
568           (when (-contains? org-ref-cite-types (plist-get plist ':type))
569             (dolist
570                 (key
571                  (org-ref-split-and-strip-string (plist-get plist ':path)))
572               (when (not (-contains? keys key))
573                 (setq keys (append keys (list key))))))))
574       ;; set with-affiliated to get keys in captions
575       nil nil nil t)
576     ;; Sort keys alphabetically
577     (setq keys (cl-sort keys 'string-lessp :key 'downcase))
578     keys))
579 #+END_SRC
580
581 This function gets the html for one entry.
582
583 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
584 (defun org-ref-get-bibtex-entry-html (key)
585   "returns an html string for the bibliography entry corresponding to key"
586
587   (format "<li><a id=\"%s\">[%s] %s</a></li>" key key (org-ref-get-bibtex-entry-citation key)))
588 #+END_SRC
589
590 Now, we map over the whole list of keys, and the whole bibliography, formatted as an unordered list.
591
592 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
593 (defun org-ref-get-html-bibliography ()
594   "Create an html bibliography when there are keys"
595   (let ((keys (org-ref-get-bibtex-keys)))
596     (when keys
597       (concat "<h1>Bibliography</h1>
598 <ul>"
599               (mapconcat (lambda (x) (org-ref-get-bibtex-entry-html x)) keys "\n")
600               "\n</ul>"))))
601 #+END_SRC
602
603 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.
604
605 *** An org bibliography
606 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.
607
608 First, we get the string for a single entry.
609 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
610 (defun org-ref-get-bibtex-entry-org (key)
611   "returns an org string for the bibliography entry corresponding to key"
612   (let ((org-ref-bibliography-files (org-ref-find-bibliography))
613         (file) (entry) (bibtex-entry) (entry-type) (format))
614
615     (setq file (catch 'result
616                  (loop for file in org-ref-bibliography-files do
617                        (if (org-ref-key-in-file-p key (file-truename file))
618                            (throw 'result file)
619                          (message "%s not found in %s" key (file-truename file))))))
620
621     (with-temp-buffer
622       (insert-file-contents file)
623       (bibtex-search-entry key nil 0)
624       (setq entry (bibtex-parse-entry))
625       (format "** %s - %s
626   :PROPERTIES:
627   %s
628   :END:
629 " (org-ref-reftex-get-bib-field "author" entry)
630 (org-ref-reftex-get-bib-field "title" entry)
631 (concat "   :CUSTOM_ID: " (org-ref-reftex-get-bib-field "=key=" entry) "\n"
632         (mapconcat (lambda (element) (format "   :%s: %s"
633                                              (upcase (car element))
634                                              (cdr element)))
635                    entry
636                    "\n"))))))
637 #+END_SRC
638
639 Now, we loop over the keys, and combine all the entries into a bibliography.
640 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
641 (defun org-ref-get-org-bibliography ()
642   "Create an org bibliography when there are keys"
643   (let ((keys (org-ref-get-bibtex-keys)))
644     (when keys
645       (concat "* Bibliography
646 "
647               (mapconcat (lambda (x) (org-ref-get-bibtex-entry-org x)) keys "\n")
648               "\n"))))
649 #+END_SRC
650
651 *** An ascii bibliography
652
653 This function gets the html for one entry.
654
655 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
656 (defun org-ref-get-bibtex-entry-ascii (key)
657   "returns an ascii string for the bibliography entry corresponding to key"
658
659   (format "[%s] %s" key (org-ref-get-bibtex-entry-citation key)))
660 #+END_SRC
661
662 Now, we map over the whole list of keys, and the whole bibliography, formatted as an unordered list.
663
664 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
665 (defun org-ref-get-ascii-bibliography ()
666   "Create an html bibliography when there are keys"
667   (let ((keys (org-ref-get-bibtex-keys)))
668     (when keys
669       (concat
670 "Bibliography
671 =============
672 "
673               (mapconcat (lambda (x) (org-ref-get-bibtex-entry-ascii x)) keys "\n")
674               "\n"))))
675 #+END_SRC
676
677
678 *** the links
679 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.
680
681 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
682 (org-add-link-type "bibliography"
683                    ;; this code is run on clicking. The bibliography
684                    ;; may contain multiple files. this code finds the
685                    ;; one you clicked on and opens it.
686                    (lambda (link-string)
687                        ;; get link-string boundaries
688                        ;; we have to go to the beginning of the line, and then search forward
689
690                      (let* ((bibfile)
691                             ;; object is the link you clicked on
692                             (object (org-element-context))
693                             (link-string-beginning)
694                             (link-string-end))
695
696                      (save-excursion
697                        (goto-char (org-element-property :begin object))
698                        (search-forward link-string nil nil 1)
699                        (setq link-string-beginning (match-beginning 0))
700                        (setq link-string-end (match-end 0)))
701
702                        ;; We set the reftex-default-bibliography
703                        ;; here. it should be a local variable only in
704                        ;; the current buffer. We need this for using
705                        ;; reftex to do citations.
706                        (set (make-local-variable 'reftex-default-bibliography)
707                             (split-string (org-element-property :path object) ","))
708
709                        ;; now if we have comma separated bibliographies
710                        ;; we find the one clicked on. we want to
711                        ;; search forward to next comma from point
712                        (save-excursion
713                          (if (search-forward "," link-string-end 1 1)
714                              (setq key-end (- (match-end 0) 1)) ; we found a match
715                            (setq key-end (point)))) ; no comma found so take the point
716                        ;; and backward to previous comma from point
717                        (save-excursion
718                          (if (search-backward "," link-string-beginning 1 1)
719                              (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
720                            (setq key-beginning (point)))) ; no match found
721                        ;; save the key we clicked on.
722                        (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
723                        (find-file bibfile))) ; open file on click
724
725                      ;; formatting code
726                    (lambda (keyword desc format)
727                      (cond
728                       ((eq format 'org) (org-ref-get-org-bibliography))
729                       ((eq format 'ascii) (org-ref-get-ascii-bibliography))
730                       ((eq format 'html) (org-ref-get-html-bibliography))
731                       ((eq format 'latex)
732                        ;; write out the latex bibliography command
733                        (format "\\bibliography{%s}" (replace-regexp-in-string  "\\.bib" "" (mapconcat 'identity
734                                                                                                       (mapcar 'expand-file-name
735                                                                                                               (split-string keyword ","))
736                                                                                                       ",")))))))
737
738 #+END_SRC
739
740 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.
741
742 #+BEGIN_LaTeX
743   \input{project-description.bbl}
744 #+END_LaTeX
745
746 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.
747
748 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
749 (org-add-link-type "nobibliography"
750                    ;; this code is run on clicking. The bibliography
751                    ;; may contain multiple files. this code finds the
752                    ;; one you clicked on and opens it.
753                    (lambda (link-string)
754                        ;; get link-string boundaries
755                        ;; we have to go to the beginning of the line, and then search forward
756
757                      (let* ((bibfile)
758                             ;; object is the link you clicked on
759                             (object (org-element-context))
760
761                             (link-string-beginning)
762                             (link-string-end))
763
764                      (save-excursion
765                        (goto-char (org-element-property :begin object))
766                        (search-forward link-string nil nil 1)
767                        (setq link-string-beginning (match-beginning 0))
768                        (setq link-string-end (match-end 0)))
769
770                        ;; We set the reftex-default-bibliography
771                        ;; here. it should be a local variable only in
772                        ;; the current buffer. We need this for using
773                        ;; reftex to do citations.
774                        (set (make-local-variable 'reftex-default-bibliography)
775                             (split-string (org-element-property :path object) ","))
776
777                        ;; now if we have comma separated bibliographies
778                        ;; we find the one clicked on. we want to
779                        ;; search forward to next comma from point
780                        (save-excursion
781                          (if (search-forward "," link-string-end 1 1)
782                              (setq key-end (- (match-end 0) 1)) ; we found a match
783                            (setq key-end (point)))) ; no comma found so take the point
784                        ;; and backward to previous comma from point
785                        (save-excursion
786                          (if (search-backward "," link-string-beginning 1 1)
787                              (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
788                            (setq key-beginning (point)))) ; no match found
789                        ;; save the key we clicked on.
790                        (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
791                        (find-file bibfile))) ; open file on click
792
793                      ;; formatting code
794                    (lambda (keyword desc format)
795                      (cond
796                       ((eq format 'org) (org-ref-get-org-bibliography))
797                       ((eq format 'ascii) (org-ref-get-ascii-bibliography))
798                       ((eq format 'html) (org-ref-get-html-bibliography))
799                       ((eq format 'latex)
800                        ;; write out the latex bibliography command
801
802 ;                      (format "{\\setbox0\\vbox{\\bibliography{%s}}}"
803 ;                              (replace-regexp-in-string  "\\.bib" "" (mapconcat 'identity
804 ;                                                                                (mapcar 'expand-file-name
805 ;                                                                                        (split-string keyword ","))
806 ;                                                                                ",")))
807
808                        (format "\\nobibliography{%s}"
809                                (replace-regexp-in-string  "\\.bib" "" (mapconcat 'identity
810                                                                                  (mapcar 'expand-file-name
811                                                                                          (split-string keyword ","))
812                                                                                  ",")))
813
814                        ))))
815 #+END_SRC
816
817 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
818 (org-add-link-type "printbibliography"
819                    (lambda (arg) (message "Nothing implemented for clicking here."))
820                    (lambda (keyword desc format)
821                      (cond
822                       ((eq format 'org) (org-ref-get-org-bibliography))
823                       ((eq format 'html) (org-ref-get-html-bibliography))
824                       ((eq format 'latex)
825                        ;; write out the biblatex bibliography command
826                        "\\printbibliography"))
827 ))
828 #+END_SRC
829
830 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, ...
831
832 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
833 (org-add-link-type "bibliographystyle"
834                    (lambda (arg) (message "Nothing implemented for clicking here."))
835                    (lambda (keyword desc format)
836                      (cond
837                       ((eq format 'latex)
838                        ;; write out the latex bibliography command
839                        (format "\\bibliographystyle{%s}" keyword)))))
840 #+END_SRC
841
842 *** Completion for bibliography link
843 It would be nice
844
845 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
846 (defun org-bibliography-complete-link (&optional arg)
847  (format "bibliography:%s" (read-file-name "enter file: " nil nil t)))
848
849 (defun org-ref-insert-bibliography-link ()
850   "insert a bibliography with completion"
851   (interactive)
852   (insert (org-bibliography-complete-link)))
853 #+END_SRC
854
855 ** addbibresource
856 This is apparently used for biblatex.
857 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
858 (org-add-link-type "addbibresource"
859                    ;; this code is run on clicking. The addbibresource
860                    ;; may contain multiple files. this code finds the
861                    ;; one you clicked on and opens it.
862                    (lambda (link-string)
863                        ;; get link-string boundaries
864                        ;; we have to go to the beginning of the line, and then search forward
865
866                      (let* ((bibfile)
867                             ;; object is the link you clicked on
868                             (object (org-element-context))
869
870                             (link-string-beginning)
871                             (link-string-end))
872
873                      (save-excursion
874                        (goto-char (org-element-property :begin object))
875                        (search-forward link-string nil nil 1)
876                        (setq link-string-beginning (match-beginning 0))
877                        (setq link-string-end (match-end 0)))
878
879                        ;; We set the reftex-default-addbibresource
880                        ;; here. it should be a local variable only in
881                        ;; the current buffer. We need this for using
882                        ;; reftex to do citations.
883                        (set (make-local-variable 'reftex-default-addbibresource)
884                             (split-string (org-element-property :path object) ","))
885
886                        ;; now if we have comma separated bibliographies
887                        ;; we find the one clicked on. we want to
888                        ;; search forward to next comma from point
889                        (save-excursion
890                          (if (search-forward "," link-string-end 1 1)
891                              (setq key-end (- (match-end 0) 1)) ; we found a match
892                            (setq key-end (point)))) ; no comma found so take the point
893                        ;; and backward to previous comma from point
894                        (save-excursion
895                          (if (search-backward "," link-string-beginning 1 1)
896                              (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
897                            (setq key-beginning (point)))) ; no match found
898                        ;; save the key we clicked on.
899                        (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
900                        (find-file bibfile))) ; open file on click
901
902                      ;; formatting code
903                    (lambda (keyword desc format)
904                      (cond
905                       ((eq format 'html) (format "")); no output for html
906                       ((eq format 'latex)
907                          ;; write out the latex addbibresource command
908                        (format "\\addbibresource{%s}" keyword)))))
909 #+END_SRC
910
911 ** List of Figures
912
913 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.
914
915 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
916 (defun org-ref-list-of-figures (&optional arg)
917   "Generate buffer with list of figures in them"
918   (interactive)
919   (save-excursion (widen)
920   (let* ((c-b (buffer-name))
921          (counter 0)
922          (list-of-figures
923           (org-element-map (org-element-parse-buffer) 'link
924             (lambda (link)
925               "create a link for to the figure"
926               (when
927                   (and (string= (org-element-property :type link) "file")
928                        (string-match-p
929                         "[^.]*\\.\\(png\\|jpg\\|eps\\|pdf\\)$"
930                         (org-element-property :path link)))
931                 (incf counter)
932
933                 (let* ((start (org-element-property :begin link))
934                        (parent (car (cdr (org-element-property :parent link))))
935                        (caption (caaar (plist-get parent :caption)))
936                        (name (plist-get parent :name)))
937                   (if caption
938                       (format
939                        "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]] %s\n"
940                        c-b start counter (or name "") caption)
941                     (format
942                      "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]]\n"
943                      c-b start counter (or name "")))))))))
944     (switch-to-buffer "*List of Figures*")
945     (setq buffer-read-only nil)
946     (org-mode)
947     (erase-buffer)
948     (insert (mapconcat 'identity list-of-figures ""))
949     (setq buffer-read-only t)
950     (use-local-map (copy-keymap org-mode-map))
951     (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
952
953 (org-add-link-type
954  "list-of-figures"
955  'org-ref-list-of-figures ; on click
956  (lambda (keyword desc format)
957    (cond
958     ((eq format 'latex)
959      (format "\\listoffigures")))))
960 #+END_SRC
961
962 ** List of Tables
963
964 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
965 (defun org-ref-list-of-tables (&optional arg)
966   "Generate a buffer with a list of tables"
967   (interactive)
968   (save-excursion
969   (widen)
970   (let* ((c-b (buffer-name))
971          (counter 0)
972          (list-of-tables
973           (org-element-map (org-element-parse-buffer 'element) 'table
974             (lambda (table)
975               "create a link for to the table"
976               (incf counter)
977               (let ((start (org-element-property :begin table))
978                     (name  (org-element-property :name table))
979                     (caption (caaar (org-element-property :caption table))))
980                 (if caption
981                     (format
982                      "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]] %s\n"
983                      c-b start counter (or name "") caption)
984                   (format
985                    "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]]\n"
986                    c-b start counter (or name ""))))))))
987     (switch-to-buffer "*List of Tables*")
988     (setq buffer-read-only nil)
989     (org-mode)
990     (erase-buffer)
991     (insert (mapconcat 'identity list-of-tables ""))
992     (setq buffer-read-only t)
993     (use-local-map (copy-keymap org-mode-map))
994     (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
995
996 (org-add-link-type
997  "list-of-tables"
998  'org-ref-list-of-tables
999  (lambda (keyword desc format)
1000    (cond
1001     ((eq format 'latex)
1002      (format "\\listoftables")))))
1003 #+END_SRC
1004 ** label
1005
1006 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.
1007
1008 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1009 (defun org-ref-count-labels (label)
1010   "Counts number of matches for label in the document"
1011   (+ (count-matches (format "label:%s\\b[^-:]" label) (point-min) (point-max))
1012      ;; for tblname, it is not enough to get word boundary
1013      ;; tab-little and tab-little-2 match then.
1014      (count-matches (format "^#\\+tblname:\\s-*%s\\b[^-:]" label) (point-min) (point-max))
1015      (count-matches (format "\\label{%s}" label) (point-min) (point-max))
1016      ;; this is the org-format #+label:
1017      (count-matches (format "^#\\+label:\\s-*%s\\b[^-:]" label) (point-min) (point-max))
1018      (let ((custom-id-count 0))
1019        (org-map-entries
1020         (lambda ()
1021           (when (string= label (org-entry-get (point) "CUSTOM_ID"))
1022             (setq custom-id-count (+ 1 custom-id-count)))))
1023        custom-id-count)))
1024
1025 (org-add-link-type
1026  "label"
1027  (lambda (label)
1028    "on clicking count the number of label tags used in the buffer. A number greater than one means multiple labels!"
1029    (let ((count (org-ref-count-labels label)))
1030    (message (format "%s occurence%s"
1031                     count
1032                     (if (or (= count 0)
1033                               (> count 1))
1034                         "s"
1035                       ""))
1036                     (org-ref-count-labels label))))
1037  (lambda (keyword desc format)
1038    (cond
1039     ((eq format 'html) (format "(<label>%s</label>)" path))
1040     ((eq format 'latex)
1041      (format "\\label{%s}" keyword)))))
1042 #+END_SRC
1043
1044 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.
1045
1046 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1047 (defun org-label-store-link ()
1048   "store a link to a label. The output will be a ref to that label"
1049   ;; First we have to make sure we are on a label link.
1050   (let* ((object (org-element-context)))
1051     (when (and (equal (org-element-type object) 'link)
1052                (equal (org-element-property :type object) "label"))
1053       (org-store-link-props
1054        :type "ref"
1055        :link (concat "ref:" (org-element-property :path object))))
1056
1057     ;; Store link on table
1058     (when (equal (org-element-type object) 'table)
1059       (org-store-link-props
1060        :type "ref"
1061        :link (concat "ref:" (org-element-property :name object))))
1062
1063 ;; it turns out this does not work. you can already store a link to a heading with a CUSTOM_ID
1064     ;; store link on heading with custom_id
1065 ;    (when (and (equal (org-element-type object) 'headline)
1066 ;              (org-entry-get (point) "CUSTOM_ID"))
1067 ;      (org-store-link-props
1068 ;       :type "ref"
1069 ;       :link (concat "ref:" (org-entry-get (point) "CUSTOM_ID"))))
1070
1071     ;; and to #+label: lines
1072     (when (and (equal (org-element-type object) 'paragraph)
1073                (org-element-property :name object))
1074       (org-store-link-props
1075        :type "ref"
1076        :link (concat "ref:" (org-element-property :name object))))
1077 ))
1078
1079 (add-hook 'org-store-link-functions 'org-label-store-link)
1080 #+END_SRC
1081 ** ref
1082
1083 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.
1084
1085 At the moment, ref links are not usable for section links. You need [[#CUSTOM_ID]] type links.
1086
1087 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1088 (org-add-link-type
1089  "ref"
1090  (lambda (label)
1091    "on clicking goto the label. Navigate back with C-c &"
1092    (org-mark-ring-push)
1093    ;; next search from beginning of the buffer
1094
1095    ;; it is possible you would not find the label if narrowing is in effect
1096    (widen)
1097
1098    (unless
1099        (or
1100         ;; our label links
1101         (progn
1102           (goto-char (point-min))
1103           (re-search-forward (format "label:%s\\b" label) nil t))
1104
1105         ;; a latex label
1106         (progn
1107           (goto-char (point-min))
1108           (re-search-forward (format "\\label{%s}" label) nil t))
1109
1110         ;; #+label: name  org-definition
1111         (progn
1112           (goto-char (point-min))
1113           (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
1114
1115         ;; org tblname
1116         (progn
1117           (goto-char (point-min))
1118           (re-search-forward (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t))
1119
1120 ;; Commented out because these ref links do not actually translate correctly in LaTeX.
1121 ;; you need [[#label]] links.
1122         ;; CUSTOM_ID
1123 ;       (progn
1124 ;         (goto-char (point-min))
1125 ;         (re-search-forward (format ":CUSTOM_ID:\s-*\\(%s\\)" label) nil t))
1126         )
1127      ;; we did not find anything, so go back to where we came
1128      (org-mark-ring-goto)
1129      (error "%s not found" label))
1130    (org-show-entry)
1131    (message "go back with (org-mark-ring-goto) `C-c &`"))
1132  ;formatting
1133  (lambda (keyword desc format)
1134    (cond
1135     ((eq format 'html) (format "(<ref>%s</ref>)" path))
1136     ((eq format 'latex)
1137      (format "\\ref{%s}" keyword)))))
1138 #+END_SRC
1139
1140 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.
1141
1142 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1143 (defun org-ref-get-org-labels ()
1144  "Return a list of #+LABEL: labels."
1145   (save-excursion
1146     (goto-char (point-min))
1147     (let ((matches '()))
1148       (while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" (point-max) t)
1149         (add-to-list 'matches (match-string-no-properties 1) t))
1150 matches)))
1151 #+END_SRC
1152
1153 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1154 (defun org-ref-get-custom-ids ()
1155  "Return a list of custom_id properties in the buffer."
1156  (let ((results '()) custom_id)
1157    (org-map-entries
1158     (lambda ()
1159       (let ((custom_id (org-entry-get (point) "CUSTOM_ID")))
1160         (when (not (null custom_id))
1161           (setq results (append results (list custom_id)))))))
1162 results))
1163 #+END_SRC
1164
1165 Here we get a list of the labels defined as raw latex labels, e.g. \label{eqtre}.
1166 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1167 (defun org-ref-get-latex-labels ()
1168   (save-excursion
1169     (goto-char (point-min))
1170     (let ((matches '()))
1171       (while (re-search-forward "\\\\label{\\([a-zA-z0-9:-]*\\)}" (point-max) t)
1172         (add-to-list 'matches (match-string-no-properties 1) t))
1173 matches)))
1174 #+END_SRC
1175
1176 Finally, we get the table names.
1177
1178 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1179 (defun org-ref-get-tblnames ()
1180   "Return list of table names in the buffer."
1181   (org-element-map (org-element-parse-buffer 'element) 'table
1182     (lambda (table)
1183       (org-element-property :name table))))
1184 #+END_SRC
1185
1186 Now, we can put all the labels together which will give us a list of candidates.
1187
1188 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1189 (defun org-ref-get-labels ()
1190   "Returns a list of labels in the buffer that you can make a ref link to.
1191 This is used to auto-complete ref links and in helm menus."
1192   (save-excursion
1193     (save-restriction
1194       (widen)
1195       (goto-char (point-min))
1196       (let ((matches '()))
1197         ;; these are the label:stuff  kinds
1198         (while (re-search-forward "[^#+]label:\\([a-zA-z0-9:-]*\\)" (point-max) t)
1199           (add-to-list 'matches (match-string-no-properties 1) t))
1200         (append matches
1201                 (org-ref-get-org-labels)
1202                 (org-ref-get-latex-labels)
1203                 (org-ref-get-tblnames)
1204                 (org-ref-get-custom-ids))))))
1205 #+END_SRC
1206
1207 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.
1208 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1209 (defun org-ref-helm-insert-label-link ()
1210   "Insert a label link. helm just shows you what labels already exist.
1211 If you are on a label link, replace it."
1212   (interactive)
1213   (let* ((labels (org-ref-get-labels))
1214          (cb (current-buffer)))
1215     (helm :sources `(((name . "Existing labels")
1216                       (candidates . ,labels)
1217                       ;; default action is to open to the label
1218                       (action . (lambda (label)
1219                                   ;; unfortunately I do not have markers here
1220                                   (org-open-link-from-string (format "ref:%s" label))))
1221                       ;; if you select a label, replace current one
1222                       (action . (lambda (label)
1223                                   (switch-to-buffer ,cb)
1224                                   (cond
1225                                    ;;  no prefix or on a link
1226                                    ((equal helm-current-prefix-arg nil)
1227                                     (let* ((object (org-element-context))
1228                                            (last-char (save-excursion
1229                                                         (goto-char (org-element-property :end object))
1230                                                         (backward-char)
1231                                                         (if (looking-at " ")
1232                                                             " "
1233                                                           ""))))
1234                                       (when (-contains? '("label")
1235                                                         (org-element-property :type object))
1236                                           ;; we are on a link, so replace it.
1237                                         (setf
1238                                            (buffer-substring
1239                                             (org-element-property :begin object)
1240                                             (org-element-property :end object))
1241                                            (concat
1242                                             (replace-regexp-in-string
1243                                              (org-element-property :path object)
1244                                              label
1245                                              (org-element-property :raw-link object))
1246                                             last-char)))))
1247                                    ;; no prefix options defined
1248                                    ))))
1249                      ;; no matching selection creates a new label
1250                      ((name . "Create new label")
1251                       (dummy)
1252                       ;; default action creates a new label, or replaces old one
1253                       (action .  (lambda (label)
1254                                    (switch-to-buffer ,cb)
1255                                    (let* ((object (org-element-context))
1256                                           (last-char (save-excursion
1257                                                        (goto-char (org-element-property :end object))
1258                                                        (backward-char)
1259                                                        (if (looking-at " ")
1260                                                            " "
1261                                                          ""))))
1262                                      (if (-contains? '("label")
1263                                                      (org-element-property :type object))
1264                                          ;; we are on a link, so replace it.
1265                                          (setf
1266                                           (buffer-substring
1267                                            (org-element-property :begin object)
1268                                            (org-element-property :end object))
1269                                           (concat
1270                                            (replace-regexp-in-string
1271                                             (org-element-property :path object)
1272                                             helm-pattern
1273                                             (org-element-property :raw-link object))
1274                                            last-char))
1275                                        ;; new link
1276                                        (insert
1277                                         (concat
1278                                          "label:"
1279                                          (or label
1280                                              helm-pattern))))))))))))
1281 #+END_SRC
1282
1283 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.
1284
1285 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1286 (defun org-ref-complete-link (&optional arg)
1287   "Completion function for ref links"
1288   (let ((label))
1289     (setq label (completing-read "label: " (org-ref-get-labels)))
1290     (format "ref:%s" label)))
1291 #+END_SRC
1292
1293 Alternatively, you may want to just call a function that inserts a link with completion:
1294
1295 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1296 (defun org-ref-insert-ref-link ()
1297  (interactive)
1298  (insert (org-ref-complete-link)))
1299 #+END_SRC
1300
1301 Another alternative ref insertion is to use helm.
1302
1303 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1304 (defun org-ref-helm-insert-ref-link ()
1305   "Helm menu to insert ref links to labels in the document.
1306 If you are on link, replace with newly selected label.
1307 Use C-u to insert a different kind of ref link.
1308 Use C-u C-u to insert a [[#custom-id]] link
1309 "
1310   (interactive)
1311   (let* ((labels (org-ref-get-labels))
1312          (bs (buffer-string))
1313          (contexts (with-temp-buffer
1314                      (insert bs)
1315                      (mapcar 'org-ref-get-label-context labels)))
1316          (cb (current-buffer)))
1317
1318     (helm :input (thing-at-point 'word)
1319           :sources `(((name . "Available labels to ref")
1320                       (candidates . ,(loop for label in labels
1321                                            for context in contexts
1322                                            ;; we do some kludgy adding spaces
1323                                            ;; and bars to make it "easier" to
1324                                            ;; see in helm.
1325                                            collect (cons (concat
1326                                                           label "\n"
1327                                                           (mapconcat
1328                                                            (lambda (x)
1329                                                              (concat "   |" x))
1330                                                            (split-string context "\n")
1331                                                            "\n"
1332                                                            ) "\n\n") label)))
1333                       ;; default action to replace or insert ref link.
1334                       (action . (lambda (label)
1335                                   (switch-to-buffer ,cb)
1336
1337                                   (cond
1338                                    ;;  no prefix or on a link
1339                                    ((equal helm-current-prefix-arg nil)
1340                                     (let* ((object (org-element-context))
1341                                            (last-char (save-excursion
1342                                                         (goto-char (org-element-property :end object))
1343                                                         (backward-char)
1344                                                         (if (looking-at " ")
1345                                                             " "
1346                                                           ""))))
1347                                       (if (-contains? '("ref" "eqref" "pageref" "nameref")
1348                                                       (org-element-property :type object))
1349                                           ;; we are on a link, so replace it.
1350                                           (setf
1351                                            (buffer-substring
1352                                             (org-element-property :begin object)
1353                                             (org-element-property :end object))
1354                                            (concat
1355                                             (replace-regexp-in-string
1356                                              (org-element-property :path object)
1357                                              label
1358                                              (org-element-property :raw-link object))
1359                                             last-char))
1360                                         ;; insert a new link
1361                                         (insert
1362                                          (concat
1363                                           "ref:" label))
1364                                         )))
1365                                    ;; one prefix, alternate ref link
1366                                    ((equal helm-current-prefix-arg '(4))
1367                                     (insert
1368                                      (concat
1369                                       (helm :sources '((name . "Ref link types")
1370                                                        (candidates . ("ref" "eqref" "pageref" "nameref"))
1371                                                        (action . (lambda (x) x))))
1372                                       ":" label)))
1373                                    ;; two prefixes, insert section custom-id link
1374                                    ((equal helm-current-prefix-arg '(16))
1375                                     (insert
1376                                      (format "[[#%s]]" label)))
1377                                    ))
1378                               ))))))
1379 #+END_SRC
1380
1381 #+RESULTS:
1382 : org-ref-helm-insert-ref-link
1383
1384 ** pageref
1385
1386 This refers to the page of a label in LaTeX.
1387
1388 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1389 (org-add-link-type
1390  "pageref"
1391  (lambda (label)
1392    "on clicking goto the label. Navigate back with C-c &"
1393    (org-mark-ring-push)
1394    ;; next search from beginning of the buffer
1395    (widen)
1396    (unless
1397        (or
1398         ;; our label links
1399         (progn
1400           (goto-char (point-min))
1401           (re-search-forward (format "label:%s\\b" label) nil t))
1402
1403         ;; a latex label
1404         (progn
1405           (goto-char (point-min))
1406           (re-search-forward (format "\\label{%s}" label) nil t))
1407
1408         ;; #+label: name  org-definition
1409         (progn
1410           (goto-char (point-min))
1411           (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
1412
1413         ;; org tblname
1414         (progn
1415           (goto-char (point-min))
1416           (re-search-forward (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t))
1417
1418 ;; Commented out because these ref links do not actually translate correctly in LaTeX.
1419 ;; you need [[#label]] links.
1420         ;; CUSTOM_ID
1421 ;       (progn
1422 ;         (goto-char (point-min))
1423 ;         (re-search-forward (format ":CUSTOM_ID:\s-*\\(%s\\)" label) nil t))
1424         )
1425      ;; we did not find anything, so go back to where we came
1426      (org-mark-ring-goto)
1427      (error "%s not found" label))
1428    (message "go back with (org-mark-ring-goto) `C-c &`"))
1429  ;formatting
1430  (lambda (keyword desc format)
1431    (cond
1432     ((eq format 'html) (format "(<pageref>%s</pageref>)" path))
1433     ((eq format 'latex)
1434      (format "\\pageref{%s}" keyword)))))
1435 #+END_SRC
1436
1437 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1438 (defun org-pageref-complete-link (&optional arg)
1439   "Completion function for ref links"
1440   (let ((label))
1441     (setq label (completing-read "label: " (org-ref-get-labels)))
1442     (format "ref:%s" label)))
1443 #+END_SRC
1444
1445 Alternatively, you may want to just call a function that inserts a link with completion:
1446
1447 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1448 (defun org-pageref-insert-ref-link ()
1449  (interactive)
1450  (insert (org-pageref-complete-link)))
1451 #+END_SRC
1452
1453 ** nameref
1454
1455 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.
1456
1457 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1458 (org-add-link-type
1459  "nameref"
1460  (lambda (label)
1461    "on clicking goto the label. Navigate back with C-c &"
1462    (org-mark-ring-push)
1463    ;; next search from beginning of the buffer
1464    (widen)
1465    (unless
1466        (or
1467         ;; a latex label
1468         (progn
1469           (goto-char (point-min))
1470           (re-search-forward (format "\\label{%s}" label) nil t))
1471         )
1472      ;; we did not find anything, so go back to where we came
1473      (org-mark-ring-goto)
1474      (error "%s not found" label))
1475    (message "go back with (org-mark-ring-goto) `C-c &`"))
1476  ;formatting
1477  (lambda (keyword desc format)
1478    (cond
1479     ((eq format 'html) (format "(<nameref>%s</nameref>)" path))
1480     ((eq format 'latex)
1481      (format "\\nameref{%s}" keyword)))))
1482 #+END_SRC
1483
1484 ** eqref
1485 This is just the LaTeX ref for equations. On export, the reference is enclosed in parentheses.
1486
1487 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1488 (org-add-link-type
1489  "eqref"
1490  (lambda (label)
1491    "on clicking goto the label. Navigate back with C-c &"
1492    (org-mark-ring-push)
1493    ;; next search from beginning of the buffer
1494    (widen)
1495    (goto-char (point-min))
1496    (unless
1497        (or
1498         ;; search forward for the first match
1499         ;; our label links
1500         (re-search-forward (format "label:%s" label) nil t)
1501         ;; a latex label
1502         (re-search-forward (format "\\label{%s}" label) nil t)
1503         ;; #+label: name  org-definition
1504         (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
1505      (org-mark-ring-goto)
1506      (error "%s not found" label))
1507    (message "go back with (org-mark-ring-goto) `C-c &`"))
1508  ;formatting
1509  (lambda (keyword desc format)
1510    (cond
1511     ((eq format 'html) (format "(<eqref>%s</eqref>)" path))
1512     ((eq format 'latex)
1513      (format "\\eqref{%s}" keyword)))))
1514 #+END_SRC
1515
1516 ** cite
1517 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.
1518
1519 *** Implementing the click actions of cite
1520
1521 **** Getting the key we clicked on
1522 The first thing we need is to get the bibtex key we clicked on.
1523
1524 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1525 (defun org-ref-get-bibtex-key-under-cursor ()
1526   "returns key under the bibtex cursor. We search forward from
1527 point to get a comma, or the end of the link, and then backwards
1528 to get a comma, or the beginning of the link. that delimits the
1529 keyword we clicked on. We also strip the text properties."
1530   (interactive)
1531   (let* ((object (org-element-context))
1532          (link-string (org-element-property :path object)))
1533     ;; you may click on the part before the citations. here we make
1534     ;; sure to move to the beginning so you get the first citation.
1535     (let ((cp (point)))
1536       (goto-char (org-element-property :begin object))
1537       (search-forward link-string (org-element-property :end object))
1538       (goto-char (match-beginning 0))
1539       ;; check if we clicked before the path and move as needed.
1540       (unless (< cp (point))
1541         (goto-char cp)))
1542
1543     (if (not (org-element-property :contents-begin object))
1544         ;; this means no description in the link
1545         (progn
1546           ;; we need the link path start and end
1547           (save-excursion
1548             (goto-char (org-element-property :begin object))
1549             (search-forward link-string nil nil 1)
1550             (setq link-string-beginning (match-beginning 0))
1551             (setq link-string-end (match-end 0)))
1552
1553           ;; The key is the text between commas, or the link boundaries
1554           (save-excursion
1555             (if (search-forward "," link-string-end t 1)
1556                 (setq key-end (- (match-end 0) 1)) ; we found a match
1557               (setq key-end link-string-end))) ; no comma found so take the end
1558           ;; and backward to previous comma from point which defines the start character
1559           (save-excursion
1560             (if (search-backward "," link-string-beginning 1 1)
1561                 (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
1562               (setq key-beginning link-string-beginning))) ; no match found
1563           ;; save the key we clicked on.
1564           (setq bibtex-key (org-ref-strip-string (buffer-substring key-beginning key-end)))
1565           (set-text-properties 0 (length bibtex-key) nil bibtex-key)
1566           bibtex-key)
1567       ;; link with description. assume only one key
1568       link-string)))
1569 #+END_SRC
1570
1571 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.
1572
1573 **** Getting the bibliographies
1574 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1575 (defun org-ref-find-bibliography ()
1576   "find the bibliography in the buffer.
1577 This function sets and returns cite-bibliography-files, which is a list of files
1578 either from bibliography:f1.bib,f2.bib
1579 \bibliography{f1,f2}
1580 internal bibliographies
1581
1582 falling back to what the user has set in org-ref-default-bibliography
1583 "
1584   (interactive)
1585   (catch 'result
1586     (save-excursion
1587       (goto-char (point-min))
1588       ;;  look for a bibliography link
1589       (when (re-search-forward "\\<bibliography:\\([^\]\|\n]+\\)" nil t)
1590         (setq org-ref-bibliography-files
1591               (mapcar 'org-ref-strip-string (split-string (match-string 1) ",")))
1592         (throw 'result org-ref-bibliography-files))
1593
1594
1595       ;; we did not find a bibliography link. now look for \bibliography
1596       (goto-char (point-min))
1597       (when (re-search-forward "\\\\bibliography{\\([^}]+\\)}" nil t)
1598         ;; split, and add .bib to each file
1599         (setq org-ref-bibliography-files
1600               (mapcar (lambda (x) (concat x ".bib"))
1601                       (mapcar 'org-ref-strip-string
1602                               (split-string (match-string 1) ","))))
1603         (throw 'result org-ref-bibliography-files))
1604
1605       ;; no bibliography found. maybe we need a biblatex addbibresource
1606       (goto-char (point-min))
1607       ;;  look for a bibliography link
1608       (when (re-search-forward "addbibresource:\\([^\]\|\n]+\\)" nil t)
1609         (setq org-ref-bibliography-files
1610               (mapcar 'org-ref-strip-string (split-string (match-string 1) ",")))
1611         (throw 'result org-ref-bibliography-files))
1612
1613       ;; we did not find anything. use defaults
1614       (setq org-ref-bibliography-files org-ref-default-bibliography)))
1615
1616     ;; set reftex-default-bibliography so we can search
1617     (set (make-local-variable 'reftex-default-bibliography) org-ref-bibliography-files)
1618     org-ref-bibliography-files)
1619 #+END_SRC
1620
1621 **** Finding the bibliography file a key is in
1622 Now, we can see if an entry is in a file.
1623
1624 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1625 (defun org-ref-key-in-file-p (key filename)
1626   "determine if the key is in the file"
1627   (interactive "skey: \nsFile: ")
1628   (save-current-buffer
1629     (let ((bibtex-files (list filename)))
1630       (bibtex-search-entry key t))))
1631 #+END_SRC
1632
1633 Finally, we want to know which file the key is in.
1634
1635 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1636 (defun org-ref-get-bibtex-key-and-file (&optional key)
1637   "returns the bibtex key and file that it is in. If no key is provided, get one under point"
1638  (interactive)
1639  (let ((org-ref-bibliography-files (org-ref-find-bibliography))
1640        (file))
1641    (unless key
1642      (setq key (org-ref-get-bibtex-key-under-cursor)))
1643    (setq file     (catch 'result
1644                     (loop for file in org-ref-bibliography-files do
1645                           (if (org-ref-key-in-file-p key (file-truename file))
1646                               (throw 'result file)))))
1647    (cons key file)))
1648 #+END_SRC
1649
1650 **** convenience functions to act on citation at point
1651      :PROPERTIES:
1652      :ID:       af0b2a82-a7c9-4c08-9dac-09f93abc4a92
1653      :END:
1654 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.
1655
1656 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1657 (defun org-ref-open-pdf-at-point ()
1658   "open the pdf for bibtex key under point if it exists"
1659   (interactive)
1660   (let* ((results (org-ref-get-bibtex-key-and-file))
1661          (key (car results))
1662          (pdf-file (format (concat org-ref-pdf-directory "%s.pdf") key)))
1663     (if (file-exists-p pdf-file)
1664         (org-open-file pdf-file)
1665 (message "no pdf found for %s" key))))
1666
1667
1668 (defun org-ref-open-url-at-point ()
1669   "open the url for bibtex key under point."
1670   (interactive)
1671   (let* ((results (org-ref-get-bibtex-key-and-file))
1672          (key (car results))
1673          (bibfile (cdr results)))
1674     (save-excursion
1675       (with-temp-buffer
1676         (insert-file-contents bibfile)
1677         (bibtex-search-entry key)
1678         ;; I like this better than bibtex-url which does not always find
1679         ;; the urls
1680         (catch 'done
1681           (let ((url (bibtex-autokey-get-field "url")))
1682             (when  url
1683               (browse-url url)
1684               (throw 'done nil)))
1685
1686           (let ((doi (bibtex-autokey-get-field "doi")))
1687             (when doi
1688               (if (string-match "^http" doi)
1689                   (browse-url doi)
1690                 (browse-url (format "http://dx.doi.org/%s" doi)))
1691               (throw 'done nil))))))))
1692
1693
1694 (defun org-ref-open-notes-at-point ()
1695   "open the notes for bibtex key under point."
1696   (interactive)
1697   (let* ((results (org-ref-get-bibtex-key-and-file))
1698          (key (car results))
1699          (bibfile (cdr results)))
1700     (save-excursion
1701       (with-temp-buffer
1702         (insert-file-contents bibfile)
1703         (bibtex-search-entry key)
1704         (org-ref-open-bibtex-notes)))))
1705
1706
1707 (defun org-ref-citation-at-point ()
1708   "give message of current citation at point"
1709   (interactive)
1710   (let* ((cb (current-buffer))
1711         (results (org-ref-get-bibtex-key-and-file))
1712         (key (car results))
1713         (bibfile (cdr results)))
1714     (message "%s" (progn
1715                     (with-temp-buffer
1716                       (insert-file-contents bibfile)
1717                       (bibtex-search-entry key)
1718                       (org-ref-bib-citation))))))
1719
1720
1721 (defun org-ref-open-citation-at-point ()
1722   "open bibtex file to key at point"
1723   (interactive)
1724   (let* ((cb (current-buffer))
1725         (results (org-ref-get-bibtex-key-and-file))
1726         (key (car results))
1727         (bibfile (cdr results)))
1728     (find-file bibfile)
1729     (bibtex-search-entry key)))
1730 #+END_SRC
1731
1732 **** the actual minibuffer menu
1733 Now, we create the menu. This is a rewrite of the cite action. This makes the function extendable by users.
1734
1735 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
1736 (defvar org-ref-cite-menu-funcs '()
1737  "Functions to run on cite click menu. Each entry is a list of (key menu-name function).
1738 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.")
1739
1740
1741 (defvar org-ref-user-cite-menu-funcs
1742   '(("C" "rossref" org-ref-crossref-at-point)
1743     ("y" "Copy entry to file" org-ref-copy-entry-at-point-to-file)
1744     ("s" "Copy summary" org-ref-copy-entry-as-summary))
1745   "user-defined functions to run on bibtex key at point.")
1746
1747
1748 (defun org-ref-copy-entry-as-summary ()
1749   "Copy the bibtex entry for the citation at point as a summary."
1750   (interactive)
1751     (save-window-excursion
1752       (org-ref-open-citation-at-point)
1753       (kill-new (org-ref-bib-citation))))
1754
1755
1756 (defun org-ref-copy-entry-at-point-to-file ()
1757   "Copy the bibtex entry for the citation at point to NEW-FILE.
1758 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."
1759   (interactive)
1760   (let ((new-file (ido-completing-read
1761                    "Copy to bibfile: "
1762                    (append org-ref-default-bibliography
1763                            (f-entries "." (lambda (f) (f-ext? f "bib"))))))
1764         (key (org-ref-get-bibtex-key-under-cursor)))
1765     (save-window-excursion
1766       (org-ref-open-citation-at-point)
1767       (bibtex-copy-entry-as-kill))
1768
1769     (let ((bibtex-files (list (file-truename new-file))))
1770       (if (assoc key (bibtex-global-key-alist))
1771           (message "That key already exists in %s" new-file)
1772         ;; add to file
1773         (save-window-excursion
1774           (find-file new-file)
1775           (goto-char (point-max))
1776           ;; make sure we are at the beginning of a line.
1777           (unless (looking-at "^") (insert "\n\n"))
1778           (bibtex-yank)
1779           (save-buffer))))))
1780
1781
1782 (defun org-ref-get-doi-at-point ()
1783   "Get doi for key at point."
1784   (interactive)
1785   (let* ((results (org-ref-get-bibtex-key-and-file))
1786          (key (car results))
1787          (bibfile (cdr results))
1788          doi)
1789     (save-excursion
1790       (with-temp-buffer
1791         (insert-file-contents bibfile)
1792         (bibtex-search-entry key)
1793         (setq doi (bibtex-autokey-get-field "doi"))
1794         ;; in case doi is a url, remove the url part.
1795         (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))))
1796
1797
1798 ;; functions that operate on key at point for click menu
1799 (defun org-ref-wos-at-point ()
1800   "open the doi in wos for bibtex key under point."
1801   (interactive)
1802   (doi-utils-wos (org-ref-get-doi-at-point)))
1803
1804
1805 (defun org-ref-wos-citing-at-point ()
1806   "open the doi in wos citing articles for bibtex key under point."
1807   (interactive)
1808   (doi-utils-wos-citing (org-ref-get-doi-at-point)))
1809
1810
1811 (defun org-ref-wos-related-at-point ()
1812   "open the doi in wos related articles for bibtex key under point."
1813   (interactive)
1814   (doi-utils-wos-related (org-ref-get-doi-at-point)))
1815
1816
1817 (defun org-ref-google-scholar-at-point ()
1818   "open the doi in google scholar for bibtex key under point."
1819   (interactive)
1820   (doi-utils-google-scholar (org-ref-get-doi-at-point)))
1821
1822
1823 (defun org-ref-pubmed-at-point ()
1824   "open the doi in pubmed for bibtex key under point."
1825   (interactive)
1826   (doi-utils-pubmed (org-ref-get-doi-at-point)))
1827
1828
1829 (defun org-ref-crossref-at-point ()
1830   "open the doi in crossref for bibtex key under point."
1831   (interactive)
1832   (doi-utils-crossref (org-ref-get-doi-at-point)))
1833
1834
1835 (defun org-ref-cite-onclick-minibuffer-menu (&optional link-string)
1836   "action when a cite link is clicked on.
1837 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."
1838   (interactive)
1839   (let* ((results (org-ref-get-bibtex-key-and-file))
1840          (key (car results))
1841          (pdf-file (format (concat org-ref-pdf-directory "%s.pdf") key))
1842          (bibfile (cdr results))
1843          (url (save-excursion
1844                 (with-temp-buffer
1845                   (insert-file-contents bibfile)
1846                   (bibtex-search-entry key)
1847                   (bibtex-autokey-get-field "url"))))
1848          (doi (save-excursion
1849                 (with-temp-buffer
1850                   (insert-file-contents bibfile)
1851                   (bibtex-search-entry key)
1852                   ;; I like this better than bibtex-url which does not always find
1853                   ;; the urls
1854                   (bibtex-autokey-get-field "doi")))))
1855
1856     (when (string= "" doi) (setq doi nil))
1857     (when (string= "" url) (setq url nil))
1858     (setq org-ref-cite-menu-funcs '())
1859
1860     ;; open action
1861     (when
1862         bibfile
1863       (add-to-list
1864        'org-ref-cite-menu-funcs
1865        '("o" "pen" org-ref-open-citation-at-point)))
1866
1867     ;; pdf
1868     (when (file-exists-p pdf-file)
1869       (add-to-list
1870        'org-ref-cite-menu-funcs
1871        `("p" "df" ,org-ref-open-pdf-function) t))
1872
1873     ;; notes
1874     (add-to-list
1875      'org-ref-cite-menu-funcs
1876      '("n" "otes" org-ref-open-notes-at-point) t)
1877
1878     ;; url
1879     (when (or url doi)
1880       (add-to-list
1881        'org-ref-cite-menu-funcs
1882        '("u" "rl" org-ref-open-url-at-point) t))
1883
1884     ;; doi funcs
1885     (when doi
1886       (add-to-list
1887        'org-ref-cite-menu-funcs
1888        '("w" "os" org-ref-wos-at-point) t)
1889
1890       (add-to-list
1891        'org-ref-cite-menu-funcs
1892        '("c" "iting" org-ref-wos-citing-at-point) t)
1893
1894       (add-to-list
1895        'org-ref-cite-menu-funcs
1896        '("r" "elated" org-ref-wos-related-at-point) t)
1897
1898       (add-to-list
1899        'org-ref-cite-menu-funcs
1900        '("g" "oogle scholar" org-ref-google-scholar-at-point) t)
1901
1902       (add-to-list
1903        'org-ref-cite-menu-funcs
1904        '("P" "ubmed" org-ref-pubmed-at-point) t))
1905
1906     ;; add user functions
1907     (dolist (tup org-ref-user-cite-menu-funcs)
1908       (add-to-list
1909        'org-ref-cite-menu-funcs
1910        tup t))
1911
1912     ;; finally quit
1913     (add-to-list
1914      'org-ref-cite-menu-funcs
1915      '("q" "uit" (lambda ())) t)
1916
1917     ;; now we make a menu
1918     ;; construct menu string as a message
1919     (message
1920      (concat
1921       (let* ((results (org-ref-get-bibtex-key-and-file))
1922              (key (car results))
1923              (bibfile (cdr results)))
1924         (save-excursion
1925           (with-temp-buffer
1926             (insert-file-contents bibfile)
1927             (bibtex-search-entry key)
1928             (org-ref-bib-citation))))
1929       "\n"
1930       (mapconcat
1931        (lambda (tup)
1932          (concat "[" (elt tup 0) "]"
1933                  (elt tup 1) " "))
1934        org-ref-cite-menu-funcs "")))
1935     ;; get the input
1936     (let* ((input (read-char-exclusive))
1937            (choice (assoc
1938                     (char-to-string input) org-ref-cite-menu-funcs)))
1939       ;; now run the function (2nd element in choice)
1940       (when choice
1941         (funcall
1942          (elt
1943           choice
1944           2))))))
1945 #+END_SRC
1946
1947 #+RESULTS:
1948 : org-ref-cite-onclick-minibuffer-menu
1949
1950 *** A function to format a cite link
1951
1952 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.
1953
1954 #+BEGIN_SRC emacs-lisp  :tangle no
1955 ;(defun org-ref-cite-link-format (keyword desc format)
1956 ;   (cond
1957 ;    ((eq format 'html) (mapconcat (lambda (key) (format "<a name=\"#%s\">%s</a>" key key) (org-ref-split-and-strip-string keyword) ",")))
1958 ;    ((eq format 'latex)
1959 ;     (concat "\\cite" (when desc (format "[%s]" desc)) "{"
1960 ;            (mapconcat (lambda (key) key) (org-ref-split-and-strip-string keyword) ",")
1961 ;            "}"))))
1962 #+END_SRC
1963
1964 *** The actual cite link
1965 Finally, we define the cite link. This is deprecated; the links are autogenerated later. This is here for memory.
1966
1967 #+BEGIN_SRC emacs-lisp :tangle no
1968 ;(org-add-link-type
1969 ; "cite"
1970 ; 'org-ref-cite-onclick-minibuffer-menu
1971 ; 'org-ref-cite-link-format)
1972 #+END_SRC
1973
1974 *** Automatic definition of the cite links
1975 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.
1976
1977 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1978 (defmacro org-ref-make-completion-function (type)
1979   `(defun ,(intern (format "org-%s-complete-link" type)) (&optional arg)
1980      (interactive)
1981      (format "%s:%s"
1982              ,type
1983              (completing-read
1984               "bibtex key: "
1985               (let ((bibtex-files (org-ref-find-bibliography)))
1986                 (bibtex-global-key-alist))))))
1987 #+END_SRC
1988
1989 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.
1990
1991 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
1992 (defmacro org-ref-make-format-function (type)
1993   `(defun ,(intern (format "org-ref-format-%s" type)) (keyword desc format)
1994      (cond
1995       ((eq format 'org)
1996        (mapconcat
1997         (lambda (key)
1998           (format "[[#%s][%s]]" key key))
1999         (org-ref-split-and-strip-string keyword) ","))
2000
2001       ((eq format 'ascii)
2002        (concat "["
2003                (mapconcat
2004                 (lambda (key)
2005                   (format "%s" key))
2006                 (org-ref-split-and-strip-string keyword) ",") "]"))
2007
2008       ((eq format 'html)
2009        (mapconcat
2010         (lambda (key)
2011           (format "<a href=\"#%s\">%s</a>" key key))
2012         (org-ref-split-and-strip-string keyword) ","))
2013
2014       ((eq format 'latex)
2015        (if (string= (substring type -1) "s")
2016            ;; biblatex format for multicite commands, which all end in s. These are formated as \cites{key1}{key2}...
2017            (concat "\\" ,type (mapconcat (lambda (key) (format "{%s}"  key))
2018                                          (org-ref-split-and-strip-string keyword) ""))
2019          ;; bibtex format
2020        (concat "\\" ,type (when desc (org-ref-format-citation-description desc)) "{"
2021                (mapconcat (lambda (key) key) (org-ref-split-and-strip-string keyword) ",")
2022                "}")))
2023       ;; for markdown we generate pandoc citations
2024       ((eq format 'md)
2025        (cond
2026         (desc  ;; pre and or post text
2027          (let* ((text (split-string desc "::"))
2028                 (pre (car text))
2029                 (post (cadr text)))
2030            (concat
2031             (format "[@%s," keyword)
2032             (when pre (format " %s" pre))
2033             (when post (format ", %s" post))
2034             "]")))
2035         (t
2036          (format "[%s]"
2037                  (mapconcat
2038                   (lambda (key) (concat "@" key))
2039                   (org-ref-split-and-strip-string keyword)
2040                   "; "))))))))
2041 #+END_SRC
2042
2043
2044
2045 We create the links by mapping the function onto the list of defined link types.
2046
2047 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2048 (defun org-ref-format-citation-description (desc)
2049   "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 ::."
2050   (interactive)
2051   (cond
2052    ((string-match "::" desc)
2053     (format "[%s][%s]" (car (setq results (split-string desc "::"))) (cadr results)))
2054    (t (format "[%s]" desc))))
2055
2056 (defun org-ref-define-citation-link (type &optional key)
2057   "add a citation link for org-ref. With optional key, set the reftex binding. For example:
2058 (org-ref-define-citation-link \"citez\" ?z) will create a new citez link, with reftex key of z,
2059 and the completion function."
2060   (interactive "sCitation Type: \ncKey: ")
2061
2062   ;; create the formatting function
2063   (eval `(org-ref-make-format-function ,type))
2064
2065   (eval-expression
2066    `(org-add-link-type
2067      ,type
2068      org-ref-cite-onclick-function
2069      (quote ,(intern (format "org-ref-format-%s" type)))))
2070
2071   ;; create the completion function
2072   (eval `(org-ref-make-completion-function ,type))
2073
2074   ;; store new type so it works with adding citations, which checks
2075   ;; for existence in this list
2076   (add-to-list 'org-ref-cite-types type)
2077
2078   ;; and finally if a key is specified, we modify the reftex menu
2079   (when key
2080     (setf (nth 2 (assoc 'org reftex-cite-format-builtin))
2081           (append (nth 2 (assoc 'org reftex-cite-format-builtin))
2082                   `((,key  . ,(concat type ":%l")))))))
2083
2084 ;; create all the link types and their completion functions
2085 (mapcar 'org-ref-define-citation-link org-ref-cite-types)
2086 #+END_SRC
2087
2088 *** org-ref-insert-cite-link
2089 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.
2090
2091 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
2092 (defun org-ref-insert-cite-link (alternative-cite)
2093   "Insert a default citation link using reftex. If you are on a link, it
2094 appends to the end of the link, otherwise, a new link is
2095 inserted. Use a prefix arg to get a menu of citation types."
2096   (interactive "P")
2097   (org-ref-find-bibliography)
2098   (let* ((object (org-element-context))
2099          (link-string-beginning (org-element-property :begin object))
2100          (link-string-end (org-element-property :end object))
2101          (path (org-element-property :path object)))
2102
2103     (if (not alternative-cite)
2104
2105         (cond
2106          ;; case where we are in a link
2107          ((and (equal (org-element-type object) 'link)
2108                (-contains? org-ref-cite-types (org-element-property :type object)))
2109           (goto-char link-string-end)
2110           ;; sometimes there are spaces at the end of the link
2111           ;; this code moves point pack until no spaces are there
2112           (while (looking-back " ") (backward-char))
2113           (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ","))))
2114
2115          ;; We are next to a link, and we want to append
2116          ((save-excursion
2117             (backward-char)
2118             (and (equal (org-element-type (org-element-context)) 'link)
2119                  (-contains? org-ref-cite-types (org-element-property :type (org-element-context)))))
2120           (while (looking-back " ") (backward-char))
2121           (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ","))))
2122
2123          ;; insert fresh link
2124          (t
2125           (insert
2126            (concat org-ref-default-citation-link
2127                    ":"
2128                    (mapconcat 'identity (reftex-citation t) ",")))))
2129
2130       ;; you pressed a C-u so we run this code
2131       (reftex-citation)))
2132   )
2133 #+END_SRC
2134 cite:zhou-2004-first-lda-u,paier-2006-errat,boes-2015-estim-bulk
2135
2136
2137 #+RESULTS:
2138 : org-ref-insert-cite-link
2139
2140 *** Completion in cite links
2141 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.
2142
2143 #+BEGIN_SRC emacs-lisp  :tangle no
2144 (defun org-cite-complete-link (&optional arg)
2145   "Completion function for cite links"
2146   (format "%s:%s"
2147           org-ref-default-citation-link
2148           (completing-read
2149            "bibtex key: "
2150            (let ((bibtex-files (org-ref-find-bibliography)))
2151              (bibtex-global-key-alist)))))
2152 #+END_SRC
2153
2154 Alternatively, you may shortcut the org-machinery with this command. You will be prompted for a citation type, and then offered key completion.
2155
2156 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2157 (defun org-ref-insert-cite-with-completion (type)
2158   "Insert a cite link with completion"
2159   (interactive (list (ido-completing-read "Type: " org-ref-cite-types)))
2160   (insert (funcall (intern (format "org-%s-complete-link" type)))))
2161 #+END_SRC
2162
2163 ** Storing links to a bibtex entry
2164 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.
2165
2166 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2167 (defun org-ref-store-bibtex-entry-link ()
2168   "Save a citation link to the current bibtex entry. Saves in the default link type."
2169   (interactive)
2170   (let ((link (concat org-ref-default-citation-link
2171                  ":"
2172                  (save-excursion
2173                    (bibtex-beginning-of-entry)
2174                    (reftex-get-bib-field "=key=" (bibtex-parse-entry))))))
2175     (message "saved %s" link)
2176     (push (list link) org-stored-links)
2177     (car org-stored-links)))
2178 #+END_SRC
2179
2180 ** Index entries
2181 org-ref minimally supports index entries. To make an index in a file, you should put in the LaTeX header these lines
2182
2183
2184 #+LATEX_HEADER: \usepackage{makeidx}
2185 #+LATEX_HEADER: \makeindex
2186
2187
2188 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.
2189
2190
2191 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.
2192
2193
2194 index:hello
2195 index:hello!Peter
2196 [[index:hello!Sam@\textsl{Sam}]]
2197 [[index:Lin@\textbf{Lin}]]
2198 [[index:Joe|textit]]
2199 [[index:Lin@\textbf{Lin}]]
2200 [[index:Peter|see {hello}]]
2201 [[index:Jen|seealso{Jenny}]]
2202
2203 index:encodings!input!cp850
2204
2205 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2206 (org-add-link-type
2207  "index"
2208  (lambda (path)
2209    (occur path))
2210
2211  (lambda (path desc format)
2212    (cond
2213     ((eq format 'latex)
2214       (format "\\index{%s}" path)))))
2215
2216 ;; this will generate a temporary index of entries in the file.
2217 (org-add-link-type
2218  "printindex"
2219  (lambda (path)
2220    (let ((*index-links* '())
2221          (*initial-letters* '()))
2222
2223      ;; get links
2224      (org-element-map (org-element-parse-buffer) 'link
2225        (lambda (link)
2226          (let ((type (nth 0 link))
2227                (plist (nth 1 link)))
2228
2229            (when (equal (plist-get plist ':type) "index")
2230              (add-to-list
2231               '*index-links*
2232               (cons (plist-get plist :path)
2233                     (format
2234                      "[[elisp:(progn (switch-to-buffer \"%s\") (goto-char %s))][%s]]"
2235 (current-buffer)
2236                      (plist-get plist :begin)  ;; position of link
2237                      ;; grab a description
2238                      (save-excursion
2239                        (goto-char (plist-get plist :begin))
2240                        (if (thing-at-point 'sentence)
2241                            ;; get a sentence
2242                            (replace-regexp-in-string
2243                             "\n" "" (thing-at-point 'sentence))
2244                          ;; or call it a link
2245                          "link")))))))))
2246
2247      ;; sort the links
2248      (setq *index-links*  (cl-sort *index-links* 'string-lessp :key 'car))
2249
2250      ;; now first letters
2251      (dolist (link *index-links*)
2252        (add-to-list '*initial-letters* (substring (car link) 0 1) t))
2253
2254      ;; now create the index
2255      (switch-to-buffer (get-buffer-create "*index*"))
2256      (org-mode)
2257      (erase-buffer)
2258      (insert "#+TITLE: Index\n\n")
2259      (dolist (letter *initial-letters*)
2260        (insert (format "* %s\n" (upcase letter)))
2261        ;; now process the links
2262        (while (and
2263                ,*index-links*
2264                (string= letter (substring (car (car *index-links*)) 0 1)))
2265          (let ((link (pop *index-links*)))
2266            (insert (format "%s %s\n\n" (car link) (cdr link))))))
2267      (switch-to-buffer "*index*")))
2268  ;; formatting
2269  (lambda (path desc format)
2270    (cond
2271     ((eq format 'latex)
2272       (format "\\printindex")))))
2273 #+END_SRC
2274
2275 #+RESULTS:
2276 | 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*)) |
2277 | lambda | (path desc format) | (cond ((eq format (quote latex)) (format \printindex)))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
2278
2279 ** Glossary
2280 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.
2281
2282 #+LATEX_HEADER: \usepackage{glossaries}
2283 #+LATEX_HEADER: \makeglossaries
2284
2285 And at the end of the document put \makeglossaries.
2286
2287 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2288 (org-add-link-type
2289  "newglossaryentry"
2290  nil ;; no follow action
2291  (lambda (path desc format)
2292    (cond
2293     ((eq format 'latex)
2294      (format "\\newglossaryentry{%s}{%s}" path desc)))))
2295
2296
2297 ;; link to entry
2298 (org-add-link-type
2299  "gls"
2300   nil ;; no follow action
2301  (lambda (path desc format)
2302    (cond
2303     ((eq format 'latex)
2304      (format "\\gls{%s}" path)))))
2305
2306 ;; plural
2307 (org-add-link-type
2308  "glspl"
2309   nil ;; no follow action
2310  (lambda (path desc format)
2311    (cond
2312     ((eq format 'latex)
2313      (format "\\glspl{%s}" path)))))
2314
2315 ;; capitalized link
2316 (org-add-link-type
2317  "Gls"
2318   nil ;; no follow action
2319  (lambda (path desc format)
2320    (cond
2321     ((eq format 'latex)
2322      (format "\\Gls{%s}" path)))))
2323
2324 ;; capitalized link
2325 (org-add-link-type
2326  "Glspl"
2327   nil ;; no follow action
2328  (lambda (path desc format)
2329    (cond
2330     ((eq format 'latex)
2331      (format "\\Glspl{%s}" path)))))
2332 #+END_SRC
2333
2334 * Utilities
2335 ** create simple text citation from bibtex entry
2336
2337 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2338 (defun org-ref-bib-citation ()
2339   "From a bibtex entry, create and return a simple citation string.
2340 This assumes you are in an article."
2341
2342   (bibtex-beginning-of-entry)
2343   (let* ((cb (current-buffer))
2344          (bibtex-expand-strings t)
2345          (entry (loop for (key . value) in (bibtex-parse-entry t)
2346                       collect (cons (downcase key) value)))
2347          (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
2348          (year  (reftex-get-bib-field "year" entry))
2349          (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
2350          (key (reftex-get-bib-field "=key=" entry))
2351          (journal (reftex-get-bib-field "journal" entry))
2352          (volume (reftex-get-bib-field "volume" entry))
2353          (pages (reftex-get-bib-field "pages" entry))
2354          (doi (reftex-get-bib-field "doi" entry))
2355          (url (reftex-get-bib-field "url" entry))
2356          )
2357     ;;authors, "title", Journal, vol(iss):pages (year).
2358     (format "%s, \"%s\", %s, %s:%s (%s)"
2359             author title journal  volume pages year)))
2360 #+END_SRC
2361
2362 #+RESULTS:
2363 : org-ref-bib-citation
2364
2365
2366 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2367 (defun org-ref-bib-html-citation ()
2368   "from a bibtex entry, create and return a simple citation with html links."
2369
2370   (bibtex-beginning-of-entry)
2371   (let* ((cb (current-buffer))
2372          (bibtex-expand-strings t)
2373          (entry (loop for (key . value) in (bibtex-parse-entry t)
2374                       collect (cons (downcase key) value)))
2375          (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
2376          (year  (reftex-get-bib-field "year" entry))
2377          (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
2378          (key (reftex-get-bib-field "=key=" entry))
2379          (journal (reftex-get-bib-field "journal" entry))
2380          (volume (reftex-get-bib-field "volume" entry))
2381          (pages (reftex-get-bib-field "pages" entry))
2382          (doi (reftex-get-bib-field "doi" entry))
2383          (url (reftex-get-bib-field "url" entry))
2384          )
2385     ;;authors, "title", Journal, vol(iss):pages (year).
2386     (concat (format "%s, \"%s\", %s, %s:%s (%s)."
2387                     author title journal  volume pages year)
2388             (when url (format " <a href=\"%s\">link</a>" url))
2389             (when doi (format " <a href=\"http://dx.doi.org/%s\">doi</a>" doi)))
2390     ))
2391 #+END_SRC
2392
2393 ** open pdf from bibtex
2394 We bind this to a key here: [[*key%20bindings%20for%20utilities][key bindings for utilities]].
2395 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2396 (defun org-ref-open-bibtex-pdf ()
2397   "open pdf for a bibtex entry, if it exists. assumes point is in
2398 the entry of interest in the bibfile. but does not check that."
2399   (interactive)
2400   (save-excursion
2401     (bibtex-beginning-of-entry)
2402     (let* ((bibtex-expand-strings t)
2403            (entry (bibtex-parse-entry t))
2404            (key (reftex-get-bib-field "=key=" entry))
2405            (pdf (format (concat org-ref-pdf-directory "%s.pdf") key)))
2406       (message "%s" pdf)
2407       (if (file-exists-p pdf)
2408           (org-open-link-from-string (format "[[file:%s]]" pdf))
2409         (ding)))))
2410 #+END_SRC
2411
2412 ** open notes from bibtex
2413 We bind this to a key here [[*key%20bindings%20for%20utilities][key bindings for utilities]].
2414
2415 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2416 (defun org-ref-open-bibtex-notes ()
2417   "from a bibtex entry, open the notes if they exist, and create a heading if they do not.
2418
2419 I never did figure out how to use reftex to make this happen
2420 non-interactively. the reftex-format-citation function did not
2421 work perfectly; there were carriage returns in the strings, and
2422 it did not put the key where it needed to be. so, below I replace
2423 the carriage returns and extra spaces with a single space and
2424 construct the heading by hand."
2425   (interactive)
2426
2427   (bibtex-beginning-of-entry)
2428   (let* ((cb (current-buffer))
2429          (bibtex-expand-strings t)
2430          (entry (loop for (key . value) in (bibtex-parse-entry t)
2431                       collect (cons (downcase key) value)))
2432          (title (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "title" entry)))
2433          (year  (reftex-get-bib-field "year" entry))
2434          (author (replace-regexp-in-string "\n\\|\t\\|\s+" " " (reftex-get-bib-field "author" entry)))
2435          (key (reftex-get-bib-field "=key=" entry))
2436          (journal (reftex-get-bib-field "journal" entry))
2437          (volume (reftex-get-bib-field "volume" entry))
2438          (pages (reftex-get-bib-field "pages" entry))
2439          (doi (reftex-get-bib-field "doi" entry))
2440          (url (reftex-get-bib-field "url" entry))
2441          )
2442
2443     ;; save key to clipboard to make saving pdf later easier by pasting.
2444     (with-temp-buffer
2445       (insert key)
2446       (kill-ring-save (point-min) (point-max)))
2447
2448     ;; now look for entry in the notes file
2449     (if  org-ref-bibliography-notes
2450         (find-file-other-window org-ref-bibliography-notes)
2451       (error "org-ref-bib-bibliography-notes is not set to anything"))
2452
2453     (goto-char (point-min))
2454     ;; put new entry in notes if we don't find it.
2455     (if (re-search-forward (format ":Custom_ID: %s$" key) nil 'end)
2456         (funcall org-ref-open-notes-function)
2457       ;; no entry found, so add one
2458       (insert (format "\n** TODO %s - %s" year title))
2459       (insert (format"
2460  :PROPERTIES:
2461   :Custom_ID: %s
2462   :AUTHOR: %s
2463   :JOURNAL: %s
2464   :YEAR: %s
2465   :VOLUME: %s
2466   :PAGES: %s
2467   :DOI: %s
2468   :URL: %s
2469  :END:
2470 [[cite:%s]] [[file:%s/%s.pdf][pdf]]\n\n"
2471 key author journal year volume pages doi url key org-ref-pdf-directory key))
2472 (save-buffer))))
2473 #+END_SRC
2474
2475 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2476 (defun org-ref-open-notes-from-reftex ()
2477   "Call reftex, and open notes for selected entry."
2478   (interactive)
2479   (let ((bibtex-key )))
2480
2481     ;; now look for entry in the notes file
2482     (if  org-ref-bibliography-notes
2483         (find-file-other-window org-ref-bibliography-notes)
2484       (error "org-ref-bib-bibliography-notes is not set to anything"))
2485
2486     (goto-char (point-min))
2487
2488     (re-search-forward (format
2489                         ":Custom_ID: %s$"
2490                         (first (reftex-citation t)) nil 'end))
2491     (funcall org-ref-open-notes-function))
2492 #+END_SRC
2493
2494 ** open url in browser from bibtex
2495
2496 We bind this to a key here [[*key%20bindings%20for%20utilities][key bindings for utilities]].
2497
2498 + 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.
2499
2500 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2501 (defun org-ref-open-in-browser ()
2502   "Open the bibtex entry at point in a browser using the url field or doi field"
2503 (interactive)
2504 (save-excursion
2505   (bibtex-beginning-of-entry)
2506   (catch 'done
2507     (let ((url (bibtex-autokey-get-field "url")))
2508       (when  url
2509         (browse-url url)
2510         (throw 'done nil)))
2511
2512     (let ((doi (bibtex-autokey-get-field "doi")))
2513       (when doi
2514         (if (string-match "^http" doi)
2515             (browse-url doi)
2516           (browse-url (format "http://dx.doi.org/%s" doi)))
2517         (throw 'done nil)))
2518     (message "No url or doi found"))))
2519 #+END_SRC
2520
2521 ** citeulike
2522    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.
2523
2524 *** function to upload bibtex to citeulike
2525
2526 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2527 (defun org-ref-upload-bibtex-entry-to-citeulike ()
2528   "with point in  a bibtex entry get bibtex string and submit to citeulike.
2529
2530 Relies on the python script /upload_bibtex_citeulike.py being in the user directory."
2531   (interactive)
2532   (message "uploading to citeulike")
2533   (save-restriction
2534     (bibtex-narrow-to-entry)
2535     (let ((startpos (point-min))
2536           (endpos (point-max))
2537           (bibtex-string (buffer-string))
2538           (script (concat "python " starter-kit-dir "/upload_bibtex_citeulike.py&")))
2539       (with-temp-buffer (insert bibtex-string)
2540                         (shell-command-on-region (point-min) (point-max) script t nil nil t)))))
2541 #+END_SRC
2542
2543 *** The upload script
2544 Here is the python script for uploading.
2545
2546 *************** TODO document how to get the cookies
2547 *************** END
2548
2549
2550 #+BEGIN_SRC python :tangle upload_bibtex_citeulike.py
2551 #!python
2552 import pickle, requests, sys
2553
2554 # reload cookies
2555 with open('c:/Users/jkitchin/Dropbox/blogofile-jkitchin.github.com/_blog/cookies.pckl', 'rb') as f:
2556     cookies = pickle.load(f)
2557
2558 url = 'http://www.citeulike.org/profile/jkitchin/import_do'
2559
2560 bibtex = sys.stdin.read()
2561
2562 data = {'pasted':bibtex,
2563         'to_read':2,
2564         'tag_parsing':'simple',
2565         'strip_brackets':'no',
2566         'update_id':'bib-key',
2567         'btn_bibtex':'Import BibTeX file ...'}
2568
2569 headers = {'content-type': 'multipart/form-data',
2570            'User-Agent':'jkitchin/johnrkitchin@gmail.com bibtexupload'}
2571
2572 r = requests.post(url, headers=headers, data=data, cookies=cookies, files={})
2573 print r
2574 #+END_SRC
2575
2576 ** Build a pdf from a bibtex file
2577    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.
2578
2579 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2580 (defun org-ref-build-full-bibliography ()
2581   "build pdf of all bibtex entries, and open it."
2582   (interactive)
2583   (let* ((bibfile (file-name-nondirectory (buffer-file-name)))
2584         (bib-base (file-name-sans-extension bibfile))
2585         (texfile (concat bib-base ".tex"))
2586         (pdffile (concat bib-base ".pdf")))
2587     (find-file texfile)
2588     (erase-buffer)
2589     (insert (format "\\documentclass[12pt]{article}
2590 \\usepackage[version=3]{mhchem}
2591 \\usepackage{url}
2592 \\usepackage[numbers]{natbib}
2593 \\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue, pdfstartview=FitH]{hyperref}
2594 \\usepackage{doi}
2595 \\begin{document}
2596 \\nocite{*}
2597 \\bibliographystyle{unsrtnat}
2598 \\bibliography{%s}
2599 \\end{document}" bib-base))
2600     (save-buffer)
2601     (shell-command (concat "pdflatex " bib-base))
2602     (shell-command (concat "bibtex " bib-base))
2603     (shell-command (concat "pdflatex " bib-base))
2604     (shell-command (concat "pdflatex " bib-base))
2605     (kill-buffer texfile)
2606     (org-open-file pdffile)
2607     ))
2608 #+END_SRC
2609
2610 ** Extract bibtex entries cited in an org-file
2611 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.
2612
2613 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
2614 (defun org-ref-extract-bibtex-entries ()
2615   "extract the bibtex entries referred to by cite links in the current buffer into a src block at the bottom of the current buffer.
2616
2617 If no bibliography is in the buffer the `reftex-default-bibliography' is used."
2618   (interactive)
2619   (let* ((temporary-file-directory (file-name-directory (buffer-file-name)))
2620          (tempname (make-temp-file "extract-bib"))
2621          (contents (buffer-string))
2622          (cb (current-buffer))
2623          basename texfile bibfile results)
2624
2625     ;; open tempfile and insert org-buffer contents
2626     (find-file tempname)
2627     (insert contents)
2628     (setq basename (file-name-sans-extension
2629                     (file-name-nondirectory buffer-file-name))
2630           texfile (concat tempname ".tex")
2631           bibfile (concat tempname ".bib"))
2632
2633     ;; see if we have a bibliography, and insert the default one if not.
2634     (save-excursion
2635       (goto-char (point-min))
2636       (unless (re-search-forward "^bibliography:" (point-max) 'end)
2637         (insert (format "\nbibliography:%s"
2638                         (mapconcat 'identity reftex-default-bibliography ",")))))
2639     (save-buffer)
2640
2641     ;; get a latex file and extract the references
2642     (org-latex-export-to-latex)
2643     (find-file texfile)
2644     (reftex-parse-all)
2645     (reftex-create-bibtex-file bibfile)
2646     (save-buffer)
2647     ;; save results of the references
2648     (setq results (buffer-string))
2649
2650     ;; kill buffers. these are named by basename, not full path
2651     (kill-buffer (concat basename ".bib"))
2652     (kill-buffer (concat basename ".tex"))
2653     (kill-buffer basename)
2654
2655     (delete-file bibfile)
2656     (delete-file texfile)
2657     (delete-file tempname)
2658
2659     ;; Now back to the original org buffer and insert the results
2660     (switch-to-buffer cb)
2661     (when (not (string= "" results))
2662       (save-excursion
2663         (goto-char (point-max))
2664         (insert "\n\n")
2665         (org-insert-heading)
2666         (insert (format " Bibtex entries
2667
2668 ,#+BEGIN_SRC text :tangle %s
2669 %s
2670 ,#+END_SRC" (concat (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) ".bib") results))))))
2671 #+END_SRC
2672
2673 ** Find bad cite links
2674    :PROPERTIES:
2675    :ID:       8515E800-EDA0-4B2A-85FD-55B6FF849203
2676    :END:
2677 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.
2678
2679 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
2680 (require 'cl)
2681
2682 (defun index (substring list)
2683   "return the index of string in a list of strings"
2684   (let ((i 0)
2685         (found nil))
2686     (dolist (arg list i)
2687       (if (string-match (concat "^" substring "$") arg)
2688           (progn
2689             (setq found t)
2690             (return i)))
2691       (setq i (+ i 1)))
2692     ;; return counter if found, otherwise return nil
2693     (if found i nil)))
2694
2695
2696 (defun org-ref-find-bad-citations ()
2697   "Create a list of citation keys in an org-file that do not have a bibtex entry in the known bibtex files.
2698
2699 Makes a new buffer with clickable links."
2700   (interactive)
2701   ;; generate the list of bibtex-keys and cited keys
2702   (let* ((bibtex-files (org-ref-find-bibliography))
2703          (bibtex-file-path (mapconcat (lambda (x) (file-name-directory (file-truename x))) bibtex-files ":"))
2704          (bibtex-keys (mapcar (lambda (x) (car x)) (bibtex-global-key-alist)))
2705          (bad-citations '()))
2706
2707     (org-element-map (org-element-parse-buffer) 'link
2708       (lambda (link)
2709         (let ((plist (nth 1 link)))
2710           (when (-contains? org-ref-cite-types (plist-get plist :type))
2711             (dolist (key (org-ref-split-and-strip-string (plist-get plist :path)))
2712               (when (not (index key bibtex-keys))
2713                 (message-box "%s" link)
2714                 (setq
2715                  bad-citations
2716                  (append
2717                   bad-citations
2718                   `(,(format "%s [[elisp:(progn (switch-to-buffer-other-frame \"%s\")(goto-char %s))][not found here]]\n"
2719                              key
2720                              (buffer-name)
2721                              (plist-get plist :begin)))))
2722                 )))))
2723       ;; set with-affilates to t to get citations in a caption
2724       nil nil nil t)
2725
2726     (if bad-citations
2727       (progn
2728         (switch-to-buffer-other-window "*Missing citations*")
2729         (org-mode)
2730         (erase-buffer)
2731         (insert "* List of bad cite links\n")
2732         (insert (mapconcat 'identity bad-citations ""))
2733                                         ;(setq buffer-read-only t)
2734         (use-local-map (copy-keymap org-mode-map))
2735         (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))
2736
2737       (when (get-buffer "*Missing citations*")
2738           (kill-buffer "*Missing citations*"))
2739       (message "No bad cite links found"))))
2740 #+END_SRC
2741
2742 ** helm interface to org-ref
2743 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.
2744
2745 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.
2746
2747 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2748 (defun org-ref-bad-cite-candidates ()
2749   "Returns a list of conses (key . marker) where key does not exist in the known bibliography files, and marker points to the key."
2750   (let* ((cp (point))                   ; save to return to later
2751          (bibtex-files (org-ref-find-bibliography))
2752          (bibtex-file-path (mapconcat
2753                             (lambda (x)
2754                               (file-name-directory (file-truename x)))
2755                             bibtex-files ":"))
2756          (bibtex-keys (mapcar (lambda (x) (car x))
2757                               (bibtex-global-key-alist)))
2758          (bad-citations '()))
2759
2760     (org-element-map (org-element-parse-buffer) 'link
2761       (lambda (link)
2762         (let ((plist (nth 1 link)))
2763           (when (-contains? org-ref-cite-types (plist-get plist :type))
2764             (dolist (key (org-ref-split-and-strip-string (plist-get plist :path)) )
2765               (when (not (index key bibtex-keys))
2766                 (goto-char (plist-get plist :begin))
2767                 (re-search-forward key)
2768                 (push (cons key (point-marker)) bad-citations)))
2769             )))
2770       ;; add with-affiliates to get cites in caption
2771       nil nil nil t)
2772     (goto-char cp)
2773     bad-citations))
2774
2775
2776 (defun org-ref-bad-ref-candidates ()
2777   "Returns a list of conses (ref . marker) where ref is a ref link that does not point to anything (i.e. a label)."
2778   ;; first get a list of legitimate labels
2779   (let ((cp (point))
2780         (labels (org-ref-get-labels))
2781         (bad-refs '()))
2782     ;; now loop over ref links
2783     (goto-char (point-min))
2784     (org-element-map (org-element-parse-buffer) 'link
2785       (lambda (link)
2786         (let ((plist (nth 1 link)))
2787           (when (or  (equal (plist-get plist ':type) "ref")
2788                      (equal (plist-get plist ':type) "eqref")
2789                      (equal (plist-get plist ':type) "pageref")
2790                      (equal (plist-get plist ':type) "nameref"))
2791             (unless (-contains? labels (plist-get plist :path))
2792               (goto-char (plist-get plist :begin))
2793               (add-to-list
2794                'bad-refs
2795                (cons (plist-get plist :path)
2796                      (point-marker))))))))
2797     (goto-char cp)
2798     bad-refs))
2799
2800
2801 (defun org-ref-bad-label-candidates ()
2802   "Return a list of labels where label is multiply defined."
2803   (let ((labels (org-ref-get-labels))
2804         (multiple-labels '()))
2805     (when (not (= (length labels)
2806                   (length (-uniq labels))))
2807       (dolist (label labels)
2808         (when (> (-count (lambda (a)
2809                            (equal a label))
2810                          labels) 1)
2811           ;; this is a multiply defined label.
2812           (let ((cp (point)))
2813             (goto-char (point-min))
2814             (while (re-search-forward
2815                     (format  "[^#+]label:%s\\s-" label) nil t)
2816               (push (cons label (point-marker)) multiple-labels))
2817
2818             (goto-char (point-min))
2819             (while (re-search-forward
2820                     (format  "\\label{%s}\\s-?" label) nil t)
2821               (push (cons label (point-marker)) multiple-labels))
2822
2823             (goto-char (point-min))
2824             (while (re-search-forward
2825                     (format  "^#\\+label:\\s-*%s" label) nil t)
2826               (push (cons label (point-marker)) multiple-labels))
2827
2828             (goto-char (point-min))
2829             (while (re-search-forward
2830                     (format   "^#\\+tblname:\\s-*%s" label) nil t)
2831               (push (cons label (point-marker)) multiple-labels))
2832             (goto-char cp)))))
2833       multiple-labels))
2834 #+END_SRC
2835
2836 #+RESULTS:
2837 : org-ref-bad-label-candidates
2838
2839 Now, we have a functions for candidates, we can make helm sources for each one, and then run a helm command to view them.
2840
2841 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2842 (defun org-ref ()
2843   "Opens a helm interface to actions for org-ref.
2844 Shows bad citations, ref links and labels"
2845   (interactive)
2846   (let ((cb (current-buffer))
2847         (bad-citations (org-ref-bad-cite-candidates))
2848         (bad-refs (org-ref-bad-ref-candidates))
2849         (bad-labels (org-ref-bad-label-candidates)))
2850
2851     (helm :sources `(((name . "Bad citations")
2852                        (candidates . ,bad-citations)
2853                        (action . (lambda (marker)
2854                                    (switch-to-buffer (marker-buffer marker))
2855                                    (goto-char marker))))
2856                      ;;
2857                      ((name . "Bad Labels")
2858                       (candidates . ,bad-labels)
2859                       (action . (lambda (marker)
2860                                    (switch-to-buffer (marker-buffer marker))
2861                                    (goto-char marker))))
2862                      ;;
2863                      ((name . "Bad ref links")
2864                       (candidates . ,bad-refs)
2865                       (action . (lambda (marker)
2866                                           (switch-to-buffer (marker-buffer marker))
2867                                           (goto-char marker))))
2868                      ;;
2869                      ((name . "Utilities")
2870                       (candidates . (("Check buffer again" . org-ref)
2871                                      ("Insert citation" . helm-bibtex)
2872                                      ("Insert label link" . org-ref-helm-insert-label-link)
2873                                      ("Insert ref link" . org-ref-helm-insert-ref-link)
2874                                      ("List of figures" . org-ref-list-of-figures)
2875                                      ("List of tables" . org-ref-list-of-tables)
2876                                      ("Table of contents" . nil)
2877                                      ))
2878                       (action . (lambda (x)
2879                                   (switch-to-buffer ,cb)
2880                                   (funcall x))))
2881                      ;;
2882                      ((name . "Export functions")
2883                       (candidates . (("Extract cited entries" . org-ref-extract-bibtex-entries)
2884                                      ("Export to html and open" . (lambda () (org-open-file (org-html-export-to-html))))
2885                                      ("Export to pdf and open" . (lambda ()
2886                                                                    (org-open-file (org-latex-export-to-pdf))))
2887                                      ("Export to manuscript pdf and open" . ox-manuscript-export-and-build-and-open)
2888                                      ("Export submission manuscript pdf and open" . ox-manuscript-build-submission-manuscript-and-open)
2889
2890                                      ))
2891                       (action . (lambda (x)
2892                                   (switch-to-buffer ,cb)
2893                                   (funcall x))))
2894                       ))))
2895 #+END_SRC
2896
2897
2898 ** Finding non-ascii characters
2899 I like my bibtex files to be 100% ascii. This function finds the non-ascii characters so you can replace them.
2900
2901 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2902 (defun org-ref-find-non-ascii-characters ()
2903   "finds non-ascii characters in the buffer. Useful for cleaning up bibtex files"
2904   (interactive)
2905   (occur "[^[:ascii:]]"))
2906 #+END_SRC
2907
2908 ** Resort a bibtex entry
2909 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.
2910
2911 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2912 (defun org-ref-sort-bibtex-entry ()
2913   "sort fields of entry in standard order and downcase them"
2914   (interactive)
2915   (bibtex-beginning-of-entry)
2916   (let* ((master '("author" "title" "journal" "volume" "number" "pages" "year" "doi" "url"))
2917          (entry (bibtex-parse-entry))
2918          (entry-fields)
2919          (other-fields)
2920          (type (cdr (assoc "=type=" entry)))
2921          (key (cdr (assoc "=key=" entry))))
2922
2923     ;; these are the fields we want to order that are in this entry
2924     (setq entry-fields (mapcar (lambda (x) (car x)) entry))
2925     ;; we do not want to reenter these fields
2926     (setq entry-fields (remove "=key=" entry-fields))
2927     (setq entry-fields (remove "=type=" entry-fields))
2928
2929     ;;these are the other fields in the entry
2930     (setq other-fields (remove-if-not (lambda(x) (not (member x master))) entry-fields))
2931
2932     (cond
2933      ;; right now we only resort articles
2934      ((string= (downcase type) "article")
2935       (bibtex-kill-entry)
2936       (insert
2937        (concat "@article{" key ",\n"
2938                (mapconcat
2939                 (lambda (field)
2940                   (when (member field entry-fields)
2941                     (format "%s = %s," (downcase field) (cdr (assoc field entry))))) master "\n")
2942                (mapconcat
2943                 (lambda (field)
2944                   (format "%s = %s," (downcase field) (cdr (assoc field entry)))) other-fields "\n")
2945                "\n}\n\n"))
2946       (bibtex-find-entry key)
2947       (bibtex-fill-entry)
2948       (bibtex-clean-entry)
2949        ))))
2950 #+END_SRC
2951
2952 ** Clean a bibtex entry
2953    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.
2954 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.
2955 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
2956 (defun org-ref-clean-bibtex-entry(&optional keep-key)
2957   "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"
2958   (interactive "P")
2959   (bibtex-beginning-of-entry)
2960 (end-of-line)
2961   ;; some entries do not have a key or comma in first line. We check and add it, if needed.
2962   (unless (string-match ",$" (thing-at-point 'line))
2963     (end-of-line)
2964     (insert ","))
2965
2966   ;; check for empty pages, and put eid or article id in its place
2967   (let ((entry (bibtex-parse-entry))
2968         (pages (bibtex-autokey-get-field "pages"))
2969         (year (bibtex-autokey-get-field "year"))
2970         (doi  (bibtex-autokey-get-field "doi"))
2971         ;; The Journal of Chemical Physics uses eid
2972         (eid (bibtex-autokey-get-field "eid")))
2973
2974     ;; replace http://dx.doi.org/ in doi. some journals put that in,
2975     ;; but we only want the doi.
2976     (when (string-match "^http://dx.doi.org/" doi)
2977       (bibtex-beginning-of-entry)
2978       (goto-char (car (cdr (bibtex-search-forward-field "doi" t))))
2979       (bibtex-kill-field)
2980       (bibtex-make-field "doi")
2981       (backward-char)
2982       (insert (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))
2983
2984     ;; asap articles often set year to 0, which messes up key
2985     ;; generation. fix that.
2986     (when (string= "0" year)
2987       (bibtex-beginning-of-entry)
2988       (goto-char (car (cdr (bibtex-search-forward-field "year" t))))
2989       (bibtex-kill-field)
2990       (bibtex-make-field "year")
2991       (backward-char)
2992       (insert (read-string "Enter year: ")))
2993
2994     ;; fix pages if they are empty if there is an eid to put there.
2995     (when (string= "-" pages)
2996       (when eid
2997         (bibtex-beginning-of-entry)
2998         ;; this seems like a clunky way to set the pages field.But I
2999         ;; cannot find a better way.
3000         (goto-char (car (cdr (bibtex-search-forward-field "pages" t))))
3001         (bibtex-kill-field)
3002         (bibtex-make-field "pages")
3003         (backward-char)
3004         (insert eid)))
3005
3006     ;; replace naked & with \&
3007     (save-restriction
3008       (bibtex-narrow-to-entry)
3009       (bibtex-beginning-of-entry)
3010       (message "checking &")
3011       (replace-regexp " & " " \\\\& ")
3012       (widen))
3013
3014     ;; generate a key, and if it duplicates an existing key, edit it.
3015     (unless keep-key
3016       (let ((key (bibtex-generate-autokey)))
3017
3018         ;; first we delete the existing key
3019         (bibtex-beginning-of-entry)
3020         (re-search-forward bibtex-entry-maybe-empty-head)
3021         (if (match-beginning bibtex-key-in-head)
3022             (delete-region (match-beginning bibtex-key-in-head)
3023                            (match-end bibtex-key-in-head)))
3024         ;; check if the key is in the buffer
3025         (when (save-excursion
3026                 (bibtex-search-entry key))
3027           (save-excursion
3028             (bibtex-search-entry key)
3029             (bibtex-copy-entry-as-kill)
3030             (switch-to-buffer-other-window "*duplicate entry*")
3031             (bibtex-yank))
3032           (setq key (bibtex-read-key "Duplicate Key found, edit: " key)))
3033
3034         (insert key)
3035         (kill-new key))) ;; save key for pasting
3036
3037     ;; run hooks. each of these operates on the entry with no arguments.
3038     ;; this did not work like  i thought, it gives a symbolp error.
3039     ;; (run-hooks org-ref-clean-bibtex-entry-hook)
3040     (mapcar (lambda (x)
3041               (save-restriction
3042                 (save-excursion
3043                   (funcall x))))
3044             org-ref-clean-bibtex-entry-hook)
3045
3046     ;; sort fields within entry
3047     (org-ref-sort-bibtex-entry)
3048     ;; check for non-ascii characters
3049     (occur "[^[:ascii:]]")
3050     ))
3051 #+END_SRC
3052
3053 #+RESULTS:
3054 : org-ref-clean-bibtex-entry
3055
3056 ** Sort the entries in a citation link by year
3057 I prefer citations in chronological order within a grouping. These functions sort the link under the cursor by year.
3058
3059 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3060 (defun org-ref-get-citation-year (key)
3061   "get the year of an entry with key. Returns year as a string."
3062   (interactive)
3063   (let* ((results (org-ref-get-bibtex-key-and-file key))
3064          (bibfile (cdr results)))
3065     (with-temp-buffer
3066       (insert-file-contents bibfile)
3067       (bibtex-search-entry key nil 0)
3068       (prog1 (reftex-get-bib-field "year" (bibtex-parse-entry t))
3069         ))))
3070
3071 (defun org-ref-sort-citation-link ()
3072  "replace link at point with sorted link by year"
3073  (interactive)
3074  (let* ((object (org-element-context))
3075         (type (org-element-property :type object))
3076         (begin (org-element-property :begin object))
3077         (end (org-element-property :end object))
3078         (link-string (org-element-property :path object))
3079         keys years data)
3080   (setq keys (org-ref-split-and-strip-string link-string))
3081   (setq years (mapcar 'org-ref-get-citation-year keys))
3082   (setq data (mapcar* (lambda (a b) `(,a . ,b)) years keys))
3083   (setq data (cl-sort data (lambda (x y) (< (string-to-int (car x)) (string-to-int (car y))))))
3084   ;; now get the keys separated by commas
3085   (setq keys (mapconcat (lambda (x) (cdr x)) data ","))
3086   ;; and replace the link with the sorted keys
3087   (cl--set-buffer-substring begin end (concat type ":" keys))))
3088 #+END_SRC
3089
3090 ** Sort entries in citation links with shift-arrow keys
3091 Sometimes it may be helpful to manually change the order of citations. These functions define shift-arrow functions.
3092 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3093 (defun org-ref-swap-keys (i j keys)
3094  "swap the keys in a list with index i and j"
3095  (let ((tempi (nth i keys)))
3096    (setf (nth i keys) (nth j keys))
3097    (setf (nth j keys) tempi))
3098   keys)
3099
3100 (defun org-ref-swap-citation-link (direction)
3101  "move citation at point in direction +1 is to the right, -1 to the left"
3102  (interactive)
3103  (let* ((object (org-element-context))
3104         (type (org-element-property :type object))
3105         (begin (org-element-property :begin object))
3106         (end (org-element-property :end object))
3107         (link-string (org-element-property :path object))
3108         key keys i)
3109    ;;   We only want this to work on citation links
3110    (when (-contains? org-ref-cite-types type)
3111         (setq key (org-ref-get-bibtex-key-under-cursor))
3112         (setq keys (org-ref-split-and-strip-string link-string))
3113         (setq i (index key keys))  ;; defined in org-ref
3114         (if (> direction 0) ;; shift right
3115             (org-ref-swap-keys i (+ i 1) keys)
3116           (org-ref-swap-keys i (- i 1) keys))
3117         (setq keys (mapconcat 'identity keys ","))
3118         ;; and replace the link with the sorted keys
3119         (cl--set-buffer-substring begin end (concat type ":" keys " "))
3120         ;; now go forward to key so we can move with the key
3121         (re-search-forward key)
3122         (goto-char (match-beginning 0)))))
3123
3124 ;; add hooks to make it work
3125 (add-hook 'org-shiftright-hook (lambda () (org-ref-swap-citation-link 1)))
3126 (add-hook 'org-shiftleft-hook (lambda () (org-ref-swap-citation-link -1)))
3127 #+END_SRC
3128
3129 ** Lightweight messages about links
3130 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.
3131
3132 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3133 (defun org-ref-get-label-context (label)
3134   "Return a string of context around a label."
3135   (save-excursion
3136     (catch 'result
3137       (goto-char (point-min))
3138       (when (re-search-forward
3139              (format "label:%s\\b" label) nil t)
3140         (throw 'result (buffer-substring
3141                         (progn
3142                           (previous-line)
3143                           (beginning-of-line)
3144                           (point))
3145                         (progn
3146                           (forward-line 4)
3147                           (point)))))
3148
3149       (goto-char (point-min))
3150       (when (re-search-forward
3151              (format "\\label{%s}" label) nil t)
3152         (throw 'result (buffer-substring
3153                         (progn
3154                           (previous-line)
3155                           (beginning-of-line)
3156                           (point))
3157                         (progn
3158                           (forward-line 4)
3159                           (point)))))
3160
3161       (goto-char (point-min))
3162       (when (re-search-forward
3163              (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t)
3164         (throw 'result (buffer-substring
3165                         (progn
3166                           (previous-line)
3167                           (beginning-of-line)
3168                           (point))
3169                         (progn
3170                           (forward-line 4)
3171                           (point)))))
3172
3173       (goto-char (point-min))
3174       (when (re-search-forward
3175              (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t)
3176         (throw 'result (buffer-substring
3177                         (progn
3178                           (previous-line)
3179                           (beginning-of-line)
3180                           (point))
3181                         (progn
3182                           (forward-line 4)
3183                           (point)))))
3184       (throw 'result "!!! NO CONTEXT FOUND !!!"))))
3185
3186
3187 (defun org-ref-link-message ()
3188   "Print a minibuffer message about the link that point is on."
3189   (interactive)
3190   (when (eq major-mode 'org-mode)
3191     (let* ((object (org-element-context))
3192            (type (org-element-property :type object)))
3193       (save-excursion
3194         (cond
3195          ;; cite links
3196          ((-contains? org-ref-cite-types type)
3197           (message (org-ref-get-citation-string-at-point)))
3198
3199          ;; message some context about the label we are referring to
3200          ((string= type "ref")
3201           (message "%scount: %s"
3202                    (org-ref-get-label-context
3203                     (org-element-property :path object))
3204                    (org-ref-count-labels
3205                         (org-element-property :path object))))
3206
3207          ((string= type "eqref")
3208           (message "%scount: %s"
3209                    (org-ref-get-label-context
3210                     (org-element-property :path object))
3211                    (org-ref-count-labels
3212                         (org-element-property :path object))))
3213
3214          ;; message the count
3215          ((string= type "label")
3216           (let ((count (org-ref-count-labels
3217                         (org-element-property :path object))))
3218             ;; get plurality on occurrence correct
3219             (message (concat
3220                       (number-to-string count)
3221                       " occurence"
3222                       (when (or (= count 0)
3223                                 (> count 1))
3224                         "s")))))
3225
3226          ((string= type "custom-id")
3227           (save-excursion
3228             (org-open-link-from-string
3229              (format "[[#%s]]" (org-element-property :path object)))
3230             (message "%s" (org-get-heading))))
3231
3232          ;; check if the bibliography files exist.
3233          ((string= type "bibliography")
3234           (let* ((bibfile)
3235                  ;; object is the link you clicked on
3236                  (object (org-element-context))
3237                  (link-string (org-element-property :path object))
3238                  (link-string-beginning)
3239                  (link-string-end))
3240             (save-excursion
3241               (goto-char (org-element-property :begin object))
3242               (search-forward link-string nil nil 1)
3243               (setq link-string-beginning (match-beginning 0))
3244               (setq link-string-end (match-end 0)))
3245
3246              ;; make sure we are in link and not before the :
3247             (when (> link-string-beginning (point))
3248               (goto-char link-string-beginning))
3249
3250             ;; now if we have comma separated bibliographies
3251             ;; we find the one clicked on. we want to
3252             ;; search forward to next comma from point
3253             (save-excursion
3254               (if (search-forward "," link-string-end 1 1)
3255                   (setq key-end (- (match-end 0) 1)) ; we found a match
3256                 (setq key-end (point)))) ; no comma found so take the point
3257
3258             ;; and backward to previous comma from point
3259             (save-excursion
3260               (if (search-backward "," link-string-beginning 1 1)
3261                   (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
3262                 (setq key-beginning (point)))) ; no match found
3263             ;; save the key we clicked on.
3264             (setq bibfile
3265                   (org-ref-strip-string
3266                    (buffer-substring key-beginning key-end)))
3267             (if (file-exists-p bibfile)
3268                 (message "%s exists." bibfile)
3269               (message "!!! %s NOT FOUND !!!" bibfile))))
3270          )))))
3271 #+END_SRC
3272
3273 * Aliases
3274 I like convenience. Here are some aliases for faster typing.
3275
3276 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3277 (defalias 'oro 'org-ref-open-citation-at-point)
3278 (defalias 'orc 'org-ref-citation-at-point)
3279 (defalias 'orp 'org-ref-open-pdf-at-point)
3280 (defalias 'oru 'org-ref-open-url-at-point)
3281 (defalias 'orn 'org-ref-open-notes-at-point)
3282 (defalias 'ornr 'org-ref-open-notes-from-reftex)
3283
3284 (defalias 'orib 'org-ref-insert-bibliography-link)
3285 (defalias 'oric 'org-ref-insert-cite-link)
3286 (defalias 'orir 'org-ref-insert-ref-link)
3287 (defalias 'orsl 'org-ref-store-bibtex-entry-link)
3288
3289 (defalias 'orcb 'org-ref-clean-bibtex-entry)
3290 #+END_SRC
3291 * Helm interface
3292 [[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.
3293
3294 1. Make the default action to insert selected keys.
3295 2. Make open entry second action
3296 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3297 (setq helm-source-bibtex
3298       '((name                                      . "BibTeX entries")
3299         (init                                      . helm-bibtex-init)
3300         (candidates                                . helm-bibtex-candidates)
3301         (filtered-candidate-transformer            . helm-bibtex-candidates-formatter)
3302         (action . (("Insert citation"              . helm-bibtex-insert-citation)
3303                    ("Show entry"                   . helm-bibtex-show-entry)
3304                    ("Open PDF file (if present)"   . helm-bibtex-open-pdf)
3305                    ("Open URL or DOI in browser"   . helm-bibtex-open-url-or-doi)
3306                    ("Insert reference"             . helm-bibtex-insert-reference)
3307                    ("Insert BibTeX key"            . helm-bibtex-insert-key)
3308                    ("Insert BibTeX entry"          . helm-bibtex-insert-bibtex)
3309                    ("Attach PDF to email"          . helm-bibtex-add-PDF-attachment)
3310                    ("Edit notes"                   . helm-bibtex-edit-notes)
3311                    ))))
3312 #+END_SRC
3313
3314 Now, let us define a function that inserts the cite links:
3315 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3316 (defun helm-bibtex-format-org-ref (keys)
3317   "Insert selected KEYS as cite link. Append KEYS if you are on a link.
3318 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.
3319
3320 In the helm-bibtex buffer, C-u will give you a helm menu to select a new link type for the selected entries.
3321
3322 C-u C-u will change the key at point to the selected keys.
3323 "
3324   (let* ((object (org-element-context))
3325          (last-char (save-excursion
3326                       (goto-char (org-element-property :end object))
3327                       (backward-char)
3328                       (if (looking-at " ")
3329                           " "
3330                         ""))))
3331     (cond
3332      ;; case where we are in a link
3333      ((and (equal (org-element-type object) 'link)
3334            (-contains?
3335             org-ref-cite-types
3336             (org-element-property :type object)))
3337       (cond
3338        ;; no prefix. append keys
3339        ((equal helm-current-prefix-arg nil)
3340         (goto-char (org-element-property :end object))
3341         (while (looking-back " ") (backward-char))
3342         (insert (concat "," (mapconcat 'identity keys ","))))
3343        ;; double prefix, replace key at point
3344        ((equal helm-current-prefix-arg '(16))
3345         (setf (buffer-substring
3346                (org-element-property :begin object)
3347                (org-element-property :end object))
3348               (concat
3349                (replace-regexp-in-string
3350                 (car (org-ref-get-bibtex-key-and-file)) ; key
3351                 (mapconcat 'identity keys ",")          ; new keys
3352                 (org-element-property :raw-link object))
3353                ;; replace space at end to avoid collapsing into next word.
3354                last-char))
3355         ;; and we want to go to the end of the new link
3356         (goto-char
3357          (org-element-property :end (org-element-context))))
3358        (t
3359         (message "Not found"))))
3360
3361      ;; We are next to a link, and we want to append
3362      ;; next to a link means one character back is on a link.
3363      ((save-excursion
3364         (backward-char)
3365         (and (equal (org-element-type (org-element-context)) 'link)
3366              (-contains?
3367               org-ref-cite-types
3368               (org-element-property :type (org-element-context)))))
3369       (while (looking-back " ") (backward-char))
3370       (insert (concat "," (mapconcat 'identity keys ","))))
3371
3372      ;; insert fresh link
3373      (t
3374       ;;(message-box "fresh link")
3375       (insert
3376        (concat (if (equal helm-current-prefix-arg '(4))
3377                    (helm :sources `((name . "link types")
3378                                     (candidates . ,org-ref-cite-types)
3379                                     (action . (lambda (x) x))))
3380                org-ref-default-citation-link)
3381                ":"
3382                (s-join "," keys))))))
3383   ;; return empty string for helm
3384   "")
3385
3386 (setq helm-bibtex-format-citation-functions
3387       '((org-mode . helm-bibtex-format-org-ref)))
3388
3389 (defun org-ref-helm-insert-cite-link (arg)
3390   "org-ref function to use helm-bibtex to insert a citation link.
3391 With one prefix arg, insert a ref link.
3392 With two prefix args, insert a label link."
3393   (interactive "P")
3394   (cond
3395    ((equal arg nil)
3396      (let ((helm-bibtex-bibliography (org-ref-find-bibliography)))
3397        (helm-bibtex)))
3398    ((equal arg '(4))
3399     (org-ref-helm-insert-ref-link))
3400    ((equal arg '(16))
3401     (org-ref-helm-insert-label-link))))
3402
3403 (require 'helm-bibtex)
3404
3405 ;; add our own fallback entries where we want them. These appear in reverse order of adding in the menu
3406 (setq helm-bibtex-fallback-options
3407       (-insert-at 1 '("Crossref" . "http://search.crossref.org/?q=%s") helm-bibtex-fallback-options))
3408
3409 (setq helm-bibtex-fallback-options
3410       (-insert-at
3411        1
3412        '("Scopus" . "http://www.scopus.com/scopus/search/submit/xadvanced.url?searchfield=TITLE-ABS-KEY(%s)")
3413        helm-bibtex-fallback-options))
3414
3415 (setq helm-bibtex-fallback-options
3416       (-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))
3417 #+END_SRC
3418
3419 ** A helm click menu
3420 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.
3421 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3422 (defun org-ref-get-citation-string-at-point ()
3423   "Get a string of a formatted citation"
3424   (interactive)
3425   (let* ((results (org-ref-get-bibtex-key-and-file))
3426          (key (car results))
3427          (bibfile (cdr results)))
3428     (if bibfile
3429         (save-excursion
3430           (with-temp-buffer
3431             (insert-file-contents bibfile)
3432             (bibtex-search-entry key)
3433             (org-ref-bib-citation)))
3434       "!!! No entry found !!!" )))
3435
3436 (defun org-ref-cite-candidates ()
3437   "Generate the list of possible candidates for click actions on a cite link.
3438 Checks for pdf and doi, and add appropriate functions."
3439   (interactive)
3440   (let* ((results (org-ref-get-bibtex-key-and-file))
3441          (key (car results))
3442          (pdf-file (format (concat org-ref-pdf-directory "%s.pdf") key))
3443          (bibfile (cdr results))
3444          (url (save-excursion
3445                 (with-temp-buffer
3446                   (insert-file-contents bibfile)
3447                   (bibtex-search-entry key)
3448                   (bibtex-autokey-get-field "url"))))
3449          (doi (save-excursion
3450                 (with-temp-buffer
3451                   (insert-file-contents bibfile)
3452                   (bibtex-search-entry key)
3453                   ;; I like this better than bibtex-url which does not always find
3454                   ;; the urls
3455                   (bibtex-autokey-get-field "doi"))))
3456          (candidates `(("Quit" . org-ref-citation-at-point)
3457                        ("Open bibtex entry" . org-ref-open-citation-at-point))))
3458     ;; for some reason, when there is no doi or url, they are returned as "". I
3459     ;; prefer nil so we correct this here.
3460     (when (string= doi "") (setq doi nil))
3461     (when (string= url "") (setq url nil))
3462
3463     ;; Conditional pdf functions
3464     (if (file-exists-p pdf-file)
3465         (add-to-list
3466          'candidates
3467          '("Open pdf" . org-ref-open-pdf-at-point)
3468          t)
3469       (add-to-list
3470        'candidates
3471        '("Try to get pdf" . (lambda ()
3472                               (save-window-excursion
3473                                 (org-ref-open-citation-at-point)
3474                                 (bibtex-beginning-of-entry)
3475                                 (doi-utils-get-bibtex-entry-pdf))))
3476        t))
3477
3478
3479     (add-to-list
3480      'candidates
3481      '("Open notes" . org-ref-open-notes-at-point)
3482      t)
3483
3484     ;; conditional url and doi functions
3485     (when (or url doi)
3486       (add-to-list
3487        'candidates
3488        '("Open in browser" . org-ref-open-url-at-point)
3489        t))
3490
3491     (when doi
3492       (mapc (lambda (x)
3493               (add-to-list 'candidates x t))
3494             `(("WOS" . org-ref-wos-at-point)
3495               ("Related articles in WOS" . org-ref-wos-related-at-point)
3496               ("Citing articles in WOS" . org-ref-wos-citing-at-point)
3497               ("Google Scholar" . org-ref-google-scholar-at-point)
3498               ("Pubmed" . org-ref-pubmed-at-point)
3499               ("Crossref" . org-ref-crossref-at-point)
3500               )))
3501
3502     (add-to-list
3503      'candidates
3504      '("Copy formatted citation to clipboard" . org-ref-copy-entry-as-summary)
3505      t)
3506
3507     (add-to-list
3508      'candidates
3509      '("Copy key to clipboard" . (lambda ()
3510                                   (kill-new
3511                                    (car (org-ref-get-bibtex-key-and-file)))))
3512      t)
3513
3514     (add-to-list
3515      'candidates
3516      '("Copy bibtex entry to file" . org-ref-copy-entry-at-point-to-file)
3517      t)
3518
3519     (add-to-list
3520      'candidates
3521      '("Email bibtex entry and pdf" . (lambda ()
3522                   (save-excursion
3523                     (org-ref-open-citation-at-point)
3524                     (email-bibtex-entry))))
3525      t)
3526   ;; finally return a numbered list of the candidates
3527   (loop for i from 0
3528         for cell in candidates
3529         collect (cons (format "%2s. %s" i (car cell))
3530                       (cdr cell)))))
3531
3532
3533 (defvar org-ref-helm-user-candidates '()
3534   "List of user-defined candidates to act when clicking on a cite link.
3535 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.
3536 ")
3537
3538 ;; example of adding your own function
3539 (add-to-list
3540  'org-ref-helm-user-candidates
3541  '("Example" . (lambda () (message-box "You did it!")))
3542  t)
3543
3544 (defun org-ref-cite-click-helm (key)
3545   "subtle points.
3546 1. get name and candidates before entering helm because we need the org-buffer.
3547 2. switch back to the org buffer before evaluating the action. most of them need the point and buffer."
3548   (interactive)
3549   (let ((name (org-ref-get-citation-string-at-point))
3550         (candidates (org-ref-cite-candidates))
3551         (cb (current-buffer)))
3552
3553     (helm :sources `(((name . ,name)
3554                       (candidates . ,candidates)
3555                       (action . (lambda (f)
3556                                   (switch-to-buffer cb)
3557                                   (funcall f))))
3558                      ((name . "User functions")
3559                       (candidates . ,org-ref-helm-user-candidates)
3560                       (action . (lambda (f)
3561                                   (switch-to-buffer cb)
3562                                   (funcall f))))
3563                      ))))
3564 #+END_SRC
3565
3566 #+RESULTS:
3567 : org-ref-cite-click-helm
3568
3569 * End of code
3570 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
3571 (provide 'org-ref)
3572 #+END_SRC
3573
3574 * Build                                                            :noexport:
3575 This code will tangle the elisp code out to org-ref.el and load it.
3576
3577 [[elisp:(progn (org-babel-tangle) (load-file "org-ref.el"))]]
3578
3579 Alternatively you may use:
3580
3581 [[elisp:(org-babel-load-file "org-ref.org")]]