]> git.donarmstrong.com Git - org-ref.git/blobdiff - org-ref.org
add function to give message when on a cite link.
[org-ref.git] / org-ref.org
index 334be1382acf102f949ce2d405b5c122e0268c25..0908cd4aeed87971cda7770d3a37ca6eafaebbe5 100644 (file)
@@ -38,11 +38,11 @@ This document is an experiment at creating a literate program to provide similar
 
 ;;; Commentary:
 ;;
-;; Lisp code to setup bibliography cite, ref and label org-mode links.
-;; also sets up reftex for org-mode. The links are clickable and do
-;; things that are useful. You should really read org-ref.org for details.
+;; Lisp code to setup bibliography cite, ref and label org-mode links.  also
+;; sets up reftex and helm for org-mode citations. The links are clickable and
+;; do things that are useful. You should really read org-ref.org for details.
 ;;
-;; Package-Requires: ((dash))
+;; Package-Requires: ((dash) (helm) (helm-bibtex))
 #+END_SRC
 
 ** requires
@@ -51,6 +51,8 @@ The only external require is reftex-cite
 #+BEGIN_SRC emacs-lisp  :tangle org-ref.el
 (require 'reftex-cite)
 (require 'dash)
+(require 'helm)
+(require 'helm-bibtex
 #+END_SRC
 
 ** Custom variables
@@ -113,13 +115,36 @@ There are some variables needed later to tell this library where you store your
     ;;(org-tree-to-indirect-buffer)
     (outline-previous-visible-heading 1)
     (recenter-top-bottom 0))
-  "User-defined way to open a notes entry. This is excecuted after the entry is found, with the cursor at the beginning of the headline. The default setting fully expands the notes, and moves the headline to the top of the buffer")
+  "User-defined way to open a notes entry. This is excecuted after the entry is found, with the cursor at the beginning of the headline. The default setting fully expands the notes, and moves the headline to the top of the buffer"
+:type 'function
+:group 'org-ref)
 
 
 (defcustom org-ref-open-pdf-function
    'org-ref-open-pdf-at-point
 "User-defined function to open a pdf from a link. The function must get the key at point, and derive a path to the pdf file, then open it. The default function is `org-ref-open-pdf-at-point'."
-  :type 'function)
+  :type 'function
+  :group 'org-ref)
+
+
+(defcustom org-ref-insert-cite-function
+  'helm-bibtex
+  "Function to call to insert citation links. The default is `helm-bibtex'. org-ref modifies helm-bibtex a little bit to give org-mode citations, and to reorder default actions. You may use `org-ref-insert-cite-link' if you like the reftex interface."
+ :type 'function
+ :group 'org-ref)
+
+
+(defcustom org-ref-cite-onclick-function
+  'org-ref-cite-click-helm
+  "Function that runs when you click on a cite link. The function must take no arguments. You may also use `org-ref-cite-onclick-minibuffer-menu' if you do not like helm."
+ :type 'function
+ :group 'org-ref)
+
+(defcustom org-ref-show-citation-on-enter t
+  "If non-nil add a hook function to show the citation summary in
+  the minibuffer just by putting the cursor in a link"
+ :group 'org-ref)
+
 #+END_SRC
 
 This next variable determines the citation types that are available in org-ref. Links for each one are automatically generated, and completion functions are automatically generated. Users may add to this list in their own init files.
@@ -197,7 +222,7 @@ We setup reftex here. We use a custom insert cite link function defined here: [[
         )
     (make-local-variable 'reftex-cite-format)
     (setq reftex-cite-format 'org)
-    (define-key org-mode-map (kbd org-ref-insert-cite-key) 'org-ref-insert-cite-link))
+    (define-key org-mode-map (kbd org-ref-insert-cite-key) org-ref-insert-cite-function))
 
 (add-hook 'org-mode-hook 'org-mode-reftex-setup)
 
@@ -1465,12 +1490,13 @@ Prompt for NEW-FILE includes bib files in org-ref-default-bibliography, and bib
   (interactive)
   (let* ((results (org-ref-get-bibtex-key-and-file))
         (key (car results))
-        (bibfile (cdr results)))
+        (bibfile (cdr results))
+         doi)
     (save-excursion
       (with-temp-buffer
         (insert-file-contents bibfile)
         (bibtex-search-entry key)
-       (bibtex-autokey-get-field "doi")
+       (setq doi (bibtex-autokey-get-field "doi"))
        ;; in case doi is a url, remove the url part.
        (replace-regexp-in-string "^http://dx.doi.org/" "" doi)))))
 
@@ -1727,7 +1753,7 @@ and the completion function."
   (eval-expression
    `(org-add-link-type
      ,type
-     'org-ref-cite-onclick-minibuffer-menu
+     org-ref-cite-onclick-function
      (quote ,(intern (format "org-ref-format-%s" type)))))
 
   ;; create the completion function
@@ -1793,6 +1819,8 @@ inserted. Use a prefix arg to get a menu of citation types."
       (reftex-citation)))
   )
 #+END_SRC
+cite:zhou-2004-first-lda-u,paier-2006-errat,boes-2015-estim-bulk
+
 
 #+RESULTS:
 : org-ref-insert-cite-link
@@ -2110,7 +2138,8 @@ And at the end of the document put \makeglossaries.
 
 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
 (defun org-ref-bib-citation ()
-  "from a bibtex entry, create and return a simple citation string."
+  "From a bibtex entry, create and return a simple citation string.
+This assumes you are in an article."
 
   (bibtex-beginning-of-entry)
   (let* ((cb (current-buffer))
@@ -2749,6 +2778,214 @@ I like convenience. Here are some aliases for faster typing.
 
 (defalias 'orcb 'org-ref-clean-bibtex-entry)
 #+END_SRC
+* Helm interface
+[[https://github.com/tmalsburg/helm-bibtex][helm-bibtex]] is a very cool interface to bibtex files. Out of the box though, it is not super convenient for org-ref. Here, we modify it to make it fit our workflow and extend it where needed.
+
+1. Make the default action to insert selected keys.
+2. Make open entry second action
+#+BEGIN_SRC emacs-lisp :tangle org-ref.el
+(setq helm-source-bibtex
+      '((name                                      . "BibTeX entries")
+       (init                                      . helm-bibtex-init)
+       (candidates                                . helm-bibtex-candidates)
+       (filtered-candidate-transformer            . helm-bibtex-candidates-formatter)
+       (action . (("Insert citation"              . helm-bibtex-insert-citation)
+                  ("Show entry"                   . helm-bibtex-show-entry)
+                  ("Open PDF file (if present)"   . helm-bibtex-open-pdf)
+                  ("Open URL or DOI in browser"   . helm-bibtex-open-url-or-doi)
+                  ("Insert reference"             . helm-bibtex-insert-reference)
+                  ("Insert BibTeX key"            . helm-bibtex-insert-key)
+                  ("Insert BibTeX entry"          . helm-bibtex-insert-bibtex)
+                  ("Attach PDF to email"          . helm-bibtex-add-PDF-attachment)
+                  ("Edit notes"                   . helm-bibtex-edit-notes)
+                  ))))
+#+END_SRC
+
+Now, let us define a function that inserts the cite links:
+#+BEGIN_SRC emacs-lisp :tangle org-ref.el
+(defun helm-bibtex-format-org-ref (keys)
+  "insert selected KEYS as cite link. Append KEYS if you are on a link."
+  (let* ((object (org-element-context)))
+    (cond
+     ;; case where we are in a link
+     ((and (equal (org-element-type object) 'link)
+          (-contains? org-ref-cite-types (org-element-property :type object)))
+      (goto-char link-string-end)
+      ;; sometimes there are spaces at the end of the link
+      ;; this code moves point pack until no spaces are there
+      (while (looking-back " ") (backward-char))
+      (insert (concat "," (mapconcat 'identity keys ","))))
+
+     ;; We are next to a link, and we want to append
+     ((save-excursion
+       (backward-char)
+       (and (equal (org-element-type (org-element-context)) 'link)
+            (-contains? org-ref-cite-types (org-element-property :type (org-element-context)))))
+      (while (looking-back " ") (backward-char))
+      (insert (concat "," (mapconcat 'identity keys ","))))
+
+     ;; insert fresh link
+     (t
+      (insert
+       (concat org-ref-default-citation-link
+              ":"
+              (s-join keys ",")))))))
+
+(setq helm-bibtex-format-citation-functions
+      '((org-mode . helm-bibtex-format-org-ref)))
+
+(require 'helm-bibtex)
+#+END_SRC
+
+** A helm click menu
+
+#+BEGIN_SRC emacs-lisp :tangle org-ref.el
+(defun org-ref-get-citation-string-at-point ()
+  (interactive)
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+        (bibfile (cdr results)))
+    (save-excursion
+      (with-temp-buffer
+       (insert-file-contents bibfile)
+       (bibtex-search-entry key)
+       (org-ref-bib-citation)))))
+
+(defun org-ref-cite-candidates ()
+  "Generate the list of possible candidates.
+Check for pdf and doi, and add appropriate functions."
+  (interactive)
+  (let* ((results (org-ref-get-bibtex-key-and-file))
+        (key (car results))
+         (pdf-file (format (concat org-ref-pdf-directory "%s.pdf") key))
+         (bibfile (cdr results))
+        (url (save-excursion
+               (with-temp-buffer
+                 (insert-file-contents bibfile)
+                 (bibtex-search-entry key)
+                 (bibtex-autokey-get-field "url"))))
+        (doi (save-excursion
+               (with-temp-buffer
+                 (insert-file-contents bibfile)
+                 (bibtex-search-entry key)
+                 ;; I like this better than bibtex-url which does not always find
+                 ;; the urls
+                 (bibtex-autokey-get-field "doi"))))
+        (candidates `(                 ;;the first candidate is a brief summary
+                      ("Quit" . org-ref-citation-at-point)
+                      ("Open bibtex entry" . org-ref-open-citation-at-point))))
+
+
+    (when (file-exists-p pdf-file)
+      (add-to-list
+       'candidates
+       '("Open pdf" . org-ref-open-pdf-at-point)
+       t
+       ))
+
+    (add-to-list
+     'candidates
+     '("Open notes" . org-ref-open-notes-at-point)
+     t)
+
+    (when (or url doi)
+      (add-to-list
+       'candidates
+       '("Open in browser" . org-ref-open-url-at-point)
+       t))
+
+    (when doi
+      (mapc (lambda (x)
+             (add-to-list 'candidates x t))
+           `(("WOS" . org-ref-wos-at-point)
+             ("Related articles in WOS" . org-ref-wos-related-at-point)
+             ("Citing articles in WOS" . org-ref-wos-citing-at-point)
+             ("Google Scholar" . org-ref-google-scholar-at-point)
+             ("Pubmed" . org-ref-pubmed-at-point)
+             ("Crossref" . org-ref-crossref-at-point)
+             )))
+
+    (add-to-list
+     'candidates
+     '("Copy formatted citation to clipboard" . org-ref-copy-entry-as-summary)
+     t)
+
+    (add-to-list
+     'candidates
+     '("Copy key to clipboard" . (lambda ()
+                                 (kill-new
+                                  (car (org-ref-get-bibtex-key-and-file)))))
+     t)
+
+    (add-to-list
+     'candidates
+     '("Copy bibtex entry to file" . org-ref-copy-entry-at-point-to-file)
+     t)
+
+    (add-to-list
+     'candidates
+     '("Email bibtex entry and pdf" . (lambda ()
+                 (save-excursion
+                   (org-ref-open-citation-at-point)
+                   (email-bibtex-entry))))
+     t)
+  ;; finally return a numbered list of the candidates
+  (loop for i from 0
+       for cell in candidates
+       collect (cons (format "%2s. %s" i (car cell))
+                     (cdr cell)))))
+
+
+(defvar org-ref-helm-user-candidates '()
+  "List of user-defined candidates to act when clicking on a cite link.
+This is a list of cons cells '((\"description\" . action)). The action function should not take an argument, and should assume point is on the cite key of interest.
+")
+
+;; example of adding your own function
+(add-to-list
+ 'org-ref-helm-user-candidates
+ '("Example" . (lambda () (message-box "You did it!")))
+ t)
+
+(defun org-ref-cite-click-helm (key)
+  "subtle points.
+1. get name and candidates before entering helm because we need the org-buffer.
+2. switch back to the org buffer before evaluating the action. most of them need the point and buffer."
+  (interactive)
+  (let ((name (org-ref-get-citation-string-at-point))
+       (candidates (org-ref-cite-candidates))
+       (cb (current-buffer)))
+
+    (helm :sources `(((name . ,name)
+                     (candidates . ,candidates)
+                     (action . (lambda (f)
+                                 (switch-to-buffer cb)
+                                 (funcall f))))
+                    ((name . "User functions")
+                     (candidates . ,org-ref-helm-user-candidates)
+                     (action . (lambda (f)
+                                 (switch-to-buffer cb)
+                                 (funcall f))))
+                    ))))
+#+END_SRC
+
+#+RESULTS:
+: org-ref-cite-click-helm
+
+To get a lighter weight message about the cite link, we define a function that gives us the minibuffer message, without the menu. We add it to a hook that updates after every command, including cursor movements.
+
+#+BEGIN_SRC emacs-lisp :tangle org-ref.el
+(defun org-ref-cite-link-p () (interactive)
+       (let* ((object (org-element-context))
+             (type (org-element-property :type object)))
+        ;;   We only want this to work on citation links
+        (when (-contains? org-ref-cite-types type)
+          (message (org-ref-get-citation-string-at-point)))))
+
+(when org-ref-show-citation-on-enter
+ (add-hook 'post-command-hook 'org-ref-cite-link-p))
+#+END_SRC
+
 * End of code
 #+BEGIN_SRC emacs-lisp :tangle org-ref.el
 (provide 'org-ref)