;;; org-ref-reftex.el --- org-ref completion setup with reftex -*- lexical-binding: t; -*- ;; Copyright (C) 2016 John Kitchin ;; Author: John Kitchin ;; Keywords: ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: This is a bare-bones completion engine using only org-mode and ;;; vanilla Emacs functions. It is not being further developed. ;; ;;; Code: (require 'reftex) (require 'reftex-cite) (require 'org-ref-utils) (declare-function 'org-ref-find-bibliography "org-ref-core.el") (declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el") (declare-function 'org-ref-bib-citation "org-ref-core.el") (defvar org-ref-cite-types) (defvar org-ref-open-notes-function) (defvar org-ref-get-pdf-filename-function) (defvar org-ref-open-pdf-function) ;;;###autoload (defun org-ref-reftex-completion () "Use reftex and org-mode for completion." (interactive) ;; Define core functions for org-ref (setq org-ref-insert-link-function 'org-ref-insert-cite-link org-ref-insert-cite-function 'org-ref-insert-cite-link org-ref-insert-label-function 'org-insert-link org-ref-insert-ref-function 'org-insert-link org-ref-cite-onclick-function 'org-ref-cite-onclick-minibuffer-menu) (message "reftex completion in org-ref loaded.")) (org-ref-reftex-completion) (define-key org-mode-map (kbd org-ref-insert-cite-key) org-ref-insert-link-function) ;; Messages in the minbuffer conflict with the minibuffer menu. So we turn them ;; off. (setq org-ref-show-citation-on-enter nil) ;;* org-mode / reftex setup (defun org-mode-reftex-setup () "Setup `org-mode' and reftex for `org-ref'." (and (buffer-file-name) (file-exists-p (buffer-file-name)) (global-auto-revert-mode t)) (make-local-variable 'reftex-cite-format) (setq reftex-cite-format 'org)) (add-hook 'org-mode-hook 'org-mode-reftex-setup) (eval-after-load 'reftex-vars '(progn (add-to-list 'reftex-cite-format-builtin '(org "Org-mode citation" ((?\C-m . "cite:%l") ; default (?d . ",%l") ; for appending (?a . "autocite:%l") (?t . "citet:%l") (?T . "citet*:%l") (?p . "citep:%l") (?P . "citep*:%l") (?h . "citeauthor:%l") (?H . "citeauthor*:%l") (?y . "citeyear:%l") (?x . "citetext:%l") (?n . "nocite:%l")))))) (defun org-ref-insert-cite-link (alternative-cite) "Insert a default citation link using reftex. If you are on a link, it appends to the end of the link, otherwise, a new link is inserted. Use a prefix arg (ALTERNATIVE-CITE) to get a menu of citation types." (interactive "P") (org-ref-find-bibliography) (let* ((object (org-element-context)) (link-string-end (org-element-property :end object))) (if (not alternative-cite) (cond ;; case where we are in a link ((and (equal (org-element-type object) 'link) (-contains? org-ref-cite-types (org-element-property :type object))) (goto-char link-string-end) ;; sometimes there are spaces at the end of the link ;; this code moves point pack until no spaces are there (skip-chars-backward " ") (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ",")))) ;; We are next to a link, and we want to append ((save-excursion (backward-char) (and (equal (org-element-type (org-element-context)) 'link) (-contains? org-ref-cite-types (org-element-property :type (org-element-context))))) (skip-chars-backward " ") (insert (concat "," (mapconcat 'identity (reftex-citation t ?a) ",")))) ;; insert fresh link (t (insert (concat org-ref-default-citation-link ":" (mapconcat 'identity (reftex-citation t) ","))))) ;; you pressed a C-u so we run this code (reftex-citation)))) ;;;###autoload (defun org-ref-open-notes-from-reftex () "Call reftex, and open notes for selected entry." (interactive) ;; now look for entry in the notes file (if org-ref-bibliography-notes (find-file-other-window org-ref-bibliography-notes) (error "org-ref-bibliography-notes is not set to anything")) (org-open-link-from-string (format "[[#%s]]" (car (reftex-citation t)))) (funcall org-ref-open-notes-function)) (defalias 'ornr 'org-ref-open-notes-from-reftex) ;;*** Minibuffer menu ;;;###autoload (defun org-ref-cite-onclick-minibuffer-menu (&optional _link-string) "Action when a cite link is clicked on. Provides a menu of context sensitive actions. If the bibtex entry has a pdf, you get an option to open it. If there is a doi, you get a lot of options. LINK-STRING is used by the link function." (interactive) (let* ((results (org-ref-get-bibtex-key-and-file)) (key (car results)) (pdf-file (funcall org-ref-get-pdf-filename-function key)) (bibfile (cdr results)) (url (save-excursion (with-temp-buffer (insert-file-contents bibfile) (bibtex-set-dialect (parsebib-find-bibtex-dialect) t) (bibtex-search-entry key) (bibtex-autokey-get-field "url")))) (doi (save-excursion (with-temp-buffer (insert-file-contents bibfile) (bibtex-set-dialect (parsebib-find-bibtex-dialect) t) (bibtex-search-entry key) ;; I like this better than bibtex-url which does not always find ;; the urls (bibtex-autokey-get-field "doi"))))) (when (string= "" doi) (setq doi nil)) (when (string= "" url) (setq url nil)) (setq org-ref-cite-menu-funcs '()) ;; open action (when bibfile (add-to-list 'org-ref-cite-menu-funcs '("o" "pen" org-ref-open-citation-at-point))) ;; pdf (when (file-exists-p pdf-file) (add-to-list 'org-ref-cite-menu-funcs `("p" "df" ,org-ref-open-pdf-function) t)) ;; notes (add-to-list 'org-ref-cite-menu-funcs '("n" "otes" org-ref-open-notes-at-point) t) ;; url (when (or url doi) (add-to-list 'org-ref-cite-menu-funcs '("u" "rl" org-ref-open-url-at-point) t)) ;; doi funcs (when doi (add-to-list 'org-ref-cite-menu-funcs '("w" "os" org-ref-wos-at-point) t) (add-to-list 'org-ref-cite-menu-funcs '("c" "iting" org-ref-wos-citing-at-point) t) (add-to-list 'org-ref-cite-menu-funcs '("r" "elated" org-ref-wos-related-at-point) t) (add-to-list 'org-ref-cite-menu-funcs '("g" "oogle scholar" org-ref-google-scholar-at-point) t) (add-to-list 'org-ref-cite-menu-funcs '("P" "ubmed" org-ref-pubmed-at-point) t)) ;; add user functions (dolist (tup org-ref-user-cite-menu-funcs) (add-to-list 'org-ref-cite-menu-funcs tup t)) ;; finally quit (add-to-list 'org-ref-cite-menu-funcs '("q" "uit" (lambda ())) t) ;; now we make a menu ;; construct menu string as a message (message (concat (let* ((results (org-ref-get-bibtex-key-and-file)) (key (car results)) (bibfile (cdr results))) (save-excursion (with-temp-buffer (insert-file-contents bibfile) (bibtex-set-dialect (parsebib-find-bibtex-dialect) t) (bibtex-search-entry key) (org-ref-bib-citation)))) "\n" (mapconcat (lambda (tup) (concat "[" (elt tup 0) "]" (elt tup 1) " ")) org-ref-cite-menu-funcs ""))) ;; get the input (let* ((input (read-char-exclusive)) (choice (assoc (char-to-string input) org-ref-cite-menu-funcs))) ;; now run the function (2nd element in choice) (when choice (funcall (elt choice 2)))))) (provide 'org-ref-reftex) ;;; org-ref-reftex.el ends here