|
|
- ;;; org-ref-helm-cite.el --- Helm interface to insert citations from bibtex files for org-ref -*- lexical-binding: t; -*-
-
- ;; Copyright (C) 2016 John Kitchin
-
- ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
- ;; Keywords:
-
- ;; This program is free software; you can redistribute it and/or modify
- ;; it under the terms of the GNU General Public License as published by
- ;; the Free Software Foundation, either version 3 of the License, or
- ;; (at your option) any later version.
-
- ;; This program is distributed in the hope that it will be useful,
- ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;; GNU General Public License for more details.
-
- ;; You should have received a copy of the GNU General Public License
- ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- ;;; Commentary: This is a competitor of `helm-bibtex'.
- ;; The main difference is the format of the candidates, which are full citations
- ;; in this package, and multiline. This package also makes the candidates
- ;; sortable in different ways, and provides different, context specific actions
- ;; depending on what buffer you call `org-ref-helm-cite' from, and depending
- ;; on the properties of the selected candidate.
- ;;
- ;; Another significant feature is persistent caching of bibtex files to make
- ;; startup fast.
-
- ;;
-
- (declare-function 'org-ref-find-bibliography "org-ref-core.el")
- (declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
-
- (defvar org-ref-pdf-directory)
- (defvar org-ref-notes-directory)
- (defvar org-ref-cite-types)
- (defvar org-ref-default-citation-link)
- (defvar org-ref-insert-link-function)
- (defvar org-ref-insert-cite-function)
- (defvar org-ref-insert-label-function)
- (defvar org-ref-insert-ref-function)
- (defvar org-ref-cite-onclick-function)
- (defvar org-ref-insert-cite-key)
-
-
- ;;; Code:
- (require 'org-ref-helm)
- (require 'org-ref-bibtex)
-
-
- (defun org-ref-helm-cite-completion ()
- "Use helm and org-ref for completion."
- (interactive)
- (setq org-ref-insert-link-function 'org-ref-insert-link
- org-ref-insert-cite-function 'org-ref-helm-cite
- org-ref-insert-label-function 'org-ref-helm-insert-label-link
- org-ref-insert-ref-function 'org-ref-helm-insert-ref-link
- org-ref-cite-onclick-function 'org-ref-helm-cite-click))
-
- (org-ref-helm-cite-completion)
-
- (define-key org-mode-map
- (kbd org-ref-insert-cite-key)
- org-ref-insert-link-function)
-
- ;;* Variables
- (defvar org-ref-helm-cite-from nil
- "Variable to store the mode `org-ref-helm-cite' was called
- from. This is used to provide some context specific actions.")
-
-
- (defvar org-ref-helm-cite-help-message
- "* Org-ref helm bibtex.
- M-<down> allows you to sort the entries by year or first author
- last name.")
-
-
- (defvar org-ref-helm-cite-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-<down>") 'org-ref-helm-cite-sort)
- map))
-
-
- (defvar orhc-sort-fn nil
- "Function for sorting the helm entries.")
-
- ;;* Helm functions
-
- (defun orhc-helm-cite-sort-alphabetical-a (c1 c2)
- "Sort entries by first author last name from a to z."
- (let* ((a1 (cdr c1))
- (au1 (cdr (assoc "author" a1)))
- (a2 (cdr c2))
- (au2 (cdr (assoc "author" a2)))
- fa1 fa2)
- (if (or (not (stringp au1))
- (not (stringp au2)))
- nil
- ;; we need to parse names
- (setq fa1 (car (s-split " and " au1))
- fa2 (car (s-split " and " au2)))
-
- (if (string-match "," fa1)
- ;; last, first
- (setq fa1 (car (s-split "," fa1)))
- ;; first last, ignore von names and jr
- (setq fa1 (car (last (s-split " " fa1)))))
-
- (if (string-match "," fa2)
- ;; last, first
- (setq fa2 (car (s-split "," fa2)))
- ;; first last, ignore von names, and jr
- (setq fa2 (car (last (s-split " " fa2)))))
- (string< fa1 fa2))))
-
-
- (defun orhc-helm-cite-sort-alphabetical-z (c1 c2)
- "Sort entries by first author last name from z to a."
- (let* ((a1 (cdr c1))
- (au1 (cdr (assoc "author" a1)))
- (a2 (cdr c2))
- (au2 (cdr (assoc "author" a2)))
- fa1 fa2)
- (if (or (not (stringp au1))
- (not (stringp au2)))
- nil
- ;; we need to parse names to get lastname
- (setq fa1 (car (s-split " and " au1))
- fa2 (car (s-split " and " au2)))
-
- (if (string-match "," fa1)
- ;; last, first
- (setq fa1 (car (s-split "," fa1)))
- ;; first last, ignore von names and jr
- (setq fa1 (car (last (s-split " " fa1)))))
-
- (if (string-match "," fa2)
- ;; last, first
- (setq fa2 (car (s-split "," fa2)))
- ;; first last, ignore von names, and jr
- (setq fa2 (car (last (s-split " " fa2)))))
- (string< fa2 fa1))))
-
-
- (defun org-ref-helm-cite-sort ()
- "Sort interface for `org-ref-helm-cite'."
- (interactive)
- (let ((action (read-char "year↓ (y) year↑ (Y)
- 1st author↓ (a) 1st author↑ (z)
- key↓ (k) key↑ (K): ")))
- (cond
- ;; sort on year
- ((eq action ?y)
- (setq orhc-sort-fn
- (lambda (c1 c2)
- (let* ((a1 (cdr c1))
- (y1 (cdr (assoc "year" a1)))
- (a2 (cdr c2))
- (y2 (cdr (assoc "year" a2))))
- (if (or (null y1) (null y2))
- nil
- (> (string-to-number y1) (string-to-number y2)))))))
- ((eq action ?Y)
- (setq orhc-sort-fn
- (lambda (c1 c2)
- (let* ((a1 (cdr c1))
- (y1 (cdr (assoc "year" a1)))
- (a2 (cdr c2))
- (y2 (cdr (assoc "year" a2))))
- (if (or (null y1) (null y2))
- nil
- (< (string-to-number y1) (string-to-number y2)))))))
- ;; sort on key
- ((eq action ?k)
- (setq orhc-sort-fn
- (lambda (c1 c2)
- (let* ((a1 (cdr c1))
- (k1 (cdr (assoc "=key=" a1)))
- (a2 (cdr c2))
- (k2 (cdr (assoc "=key=" a2))))
- (string< k2 k1)))))
- ((eq action ?K)
- (setq orhc-sort-fn
- (lambda (c1 c2)
- (let* ((a1 (cdr c1))
- (k1 (cdr (assoc "=key=" a1)))
- (a2 (cdr c2))
- (k2 (cdr (assoc "=key=" a2))))
- (string< k1 k2)))))
- ;; sort on first author last name
- ((eq action ?a)
- (setq orhc-sort-fn #'orhc-helm-cite-sort-alphabetical-a))
- ((eq action ?z)
- (setq orhc-sort-fn #'orhc-helm-cite-sort-alphabetical-z))
- (t (setq orhc-sort-fn nil)))
- (helm-update)
- (setq orhc-sort-fn nil)))
-
-
- (defun org-ref-helm-candidate-transformer (candidates _source)
- "Transform CANDIDATES, sorting if needed.
- SOURCE is ignored, but required."
- (if orhc-sort-fn
- (-sort orhc-sort-fn candidates)
- candidates))
-
-
- (defun org-ref-helm-cite-action-transformer (actions candidate)
- "Compute ACTIONS for CANDIDATE."
- ;; Check for pdf and add open or get action.
- (setq actions (append
- actions
- '(("insert citation(s)" . org-ref-helm-cite-insert-citation)
- ("show entry" . org-ref-helm-cite-open-entry))))
-
- (let ((pdf (expand-file-name
- (concat (cdr (assoc "=key=" candidate)) ".pdf")
- org-ref-pdf-directory)))
- (if (file-exists-p pdf)
- (setq actions (append actions
- (list
- (cons
- (format "Open %s" pdf)
- (lambda (_candidate)
- (org-open-file pdf))))))
- (when (assoc "doi" candidate)
- (setq actions
- (append actions
- (list
- (cons
- (format "Get PDF")
- (lambda (candidate)
- (save-window-excursion
- (find-file (cdr (assoc "file" candidate)))
- (goto-char (cdr (assoc "position" candidate)))
- (doi-utils-get-bibtex-entry-pdf))))))))))
-
- ;; check for url/doi
- (when (assoc "url" candidate)
- (setq actions (append actions
- (list
- (cons (format "Open %s"
- (cdr (assoc "url" candidate)))
- (lambda (x)
- (browse-url (cdr (assoc "url" x)))))))))
-
- (when (assoc "doi" candidate)
- (setq actions (append actions
- (list
- (cons
- (format "Open doi (%s)"
- (cdr (assoc "doi" candidate)))
- (lambda (x)
- (browse-url
- (format "http://dx.doi.org/%s"
- (cdr (assoc "doi" x))))))))))
-
- ;; Notes, open or create.
- (let ((note-file (expand-file-name
- (concat (cdr (assoc "=key=" candidate)) ".org")
- org-ref-notes-directory)))
- (if (file-exists-p note-file)
- (setq actions (append actions (list (cons "Open notes"
- (lambda (_x)
- (find-file note-file))))))
- (setq actions (append actions (list (cons "Create notes"
- (lambda (_x)
- (find-file note-file))))))))
-
- (setq actions (append
- actions
- '(("Add keywords" . org-ref-helm-cite-set-keywords)
- ("copy to clipboard" . org-ref-helm-cite-copy-entries)
- ("email" . org-ref-helm-cite-email-entries)
- ("Insert formatted entries" . (lambda (_)
- (insert
- (mapconcat 'identity
- (cl-loop for key in (helm-marked-candidates)
- collect (org-ref-format-entry key))
- "\n\n"))))
- ("Copy formatted entry" . (lambda (_)
- (kill-new
- (mapconcat 'identity
- (cl-loop for key in (helm-marked-candidates)
- collect (org-ref-format-entry key))
- "\n\n")))))))
-
- ;; this is where we could add WOK/scopus functions
- actions)
-
-
- (defun org-ref-helm-cite-insert-citation (_candidate)
- "Insert selected CANDIDATE as cite link.
- This is an action for helm, and it actually works on
- `helm-marked-candidates'. Append KEYS if you are on a link.
-
- In the `org-ref-helm-cite' buffer, \\[universal-argument] will give you
- a helm menu to select a new link type for the selected entries.
-
- A double \\[universal-argument] \\[universal-argument] will
- change the key at point to the selected keys."
- (let* ((keys (cl-loop for entry in (helm-marked-candidates)
- collect (cdr (assoc "=key=" entry))))
- (object (org-element-context))
- (last-char (save-excursion
- (when (org-element-property :end object)
- (goto-char (org-element-property :end object))
- (unless (bobp)
- (backward-char))
- (if (looking-at " ")
- " "
- "")))))
- (cond
- ;; case where we are in a link
- ((and (equal (org-element-type object) 'link)
- (-contains?
- org-ref-cite-types
- (org-element-property :type object)))
- (cond
- ;; no prefix. insert or append keys
- ((equal helm-current-prefix-arg nil)
- (cond
- ;; point after :
- ((looking-back ":" (- (point) 2))
- (insert (concat (mapconcat 'identity keys ",") ",")))
- ;; point on :
- ((looking-at ":")
- (forward-char)
- (insert (concat (mapconcat 'identity keys ",") ",")))
- ;; point on the cite type
- ((-contains? org-ref-cite-types (thing-at-point 'word))
- (re-search-forward ":")
- (insert (concat (mapconcat 'identity keys ",") ",")))
- ;; after ,
- ((looking-back "," (- (point) 2))
- (insert (concat (mapconcat 'identity keys ",") ",")))
- ;; on comma
- ((looking-at ",")
- (forward-char)
- (insert (concat (mapconcat 'identity keys ",") ",")))
- ;; somewhere in the middle or end
- (t
- ;; goto next comma or end
- (re-search-forward
- ","
- (org-element-property :end object) t)
- (skip-chars-backward " ")
- (insert (mapconcat 'identity keys ","))
- (unless (looking-at ",") (insert ",")))))
- ;; double prefix, replace key at point
- ((equal helm-current-prefix-arg '(16))
- (setf (buffer-substring
- (org-element-property :begin object)
- (org-element-property :end object))
- (concat
- (replace-regexp-in-string
- (car (org-ref-get-bibtex-key-and-file)) ; key
- (mapconcat 'identity keys ",") ; new keys
- (org-element-property :raw-link object))
- ;; replace space at end to avoid collapsing into next word.
- last-char))
- ;; and we want to go to the end of the new link
- (goto-char
- (org-element-property :end (org-element-context))))
- (t
- (message "Not found"))))
-
- ;; We are next to a link, and we want to append
- ;; next to a link means one character back is on a link.
- ((save-excursion
- (unless (bobp) (backward-char))
- (and (equal (org-element-type (org-element-context)) 'link)
- (-contains?
- org-ref-cite-types
- (org-element-property :type (org-element-context)))))
- (skip-chars-backward " ")
- (insert (concat "," (mapconcat 'identity keys ","))))
-
- ;; insert fresh link
- (t
- ;;(message-box "fresh link")
- (insert
- (concat (if (equal helm-current-prefix-arg '(4))
- (helm :sources `((name . "link types")
- (candidates . ,org-ref-cite-types)
- (action . (lambda (x) x))))
- org-ref-default-citation-link)
- ":"
- (s-join "," keys)))))))
-
-
- (defun org-ref-helm-cite-init ()
- "Initializes the source, setting bibtex files from the
- originating buffer, and mode of originating buffer."
- (org-ref-save-all-bibtex-buffers)
- (setq org-ref-bibtex-files (org-ref-find-bibliography))
- ;; save major-mode we came from so we can do context specific things.
- (setq org-ref-helm-cite-from major-mode)
- (message "initialized."))
-
-
- (defun org-ref-helm-cite-open-entry (entry)
- "Open the selected bibtex entry in its file."
- (find-file (cdr (assoc "bibfile" entry)))
- (goto-char (cdr (assoc "position" entry)))
- (bibtex-beginning-of-entry))
-
-
- (defun org-ref-helm-cite-copy-entries (_candidate)
- "Copy selected bibtex entries to the clipboard."
- (with-temp-buffer
- (cl-loop for entry in (helm-marked-candidates)
- do
- (save-window-excursion
- (org-ref-helm-cite-open-entry entry)
- (bibtex-copy-entry-as-kill))
- (bibtex-yank)
- (insert "\n"))
- (kill-region (point-min) (point-max))))
-
-
- (defun org-ref-helm-cite-email-entries (_candidate)
- "Insert selected entries and attach pdf files to an email.
- Create email unless called from an email."
- (unless (or (eq org-ref-helm-cite-from 'message-mode)
- (eq org-ref-helm-cite-from 'mu4e-compose-mode))
- (compose-mail))
- (cl-loop for entry in (helm-marked-candidates)
- do
- (save-window-excursion
- (org-ref-helm-cite-open-entry entry)
- (bibtex-copy-entry-as-kill))
- (message-goto-body)
- (insert (pop bibtex-entry-kill-ring))
- (insert "\n")
- if (file-exists-p (expand-file-name
- (concat (cdr (assoc "=key=" entry)) ".pdf")
- org-ref-pdf-directory))
- do
- (mml-attach-file (expand-file-name
- (concat (cdr (assoc "=key=" entry)) ".pdf")
- org-ref-pdf-directory)))
- (message-goto-to))
-
- (defun org-ref-helm-cite-set-keywords (_candidate)
- "Prompt for keywords, and put them on the selected entries."
- (let ((keywords (read-string "Keyword(s) comma-separated: " ))
- entry-keywords)
- (cl-loop for entry in (helm-marked-candidates)
- do
- (save-window-excursion
- (org-ref-helm-cite-open-entry entry)
- (setq entry-keywords (bibtex-autokey-get-field "keywords"))
- (bibtex-set-field
- "keywords"
- (if (> (length entry-keywords) 0)
- (concat entry-keywords ", " keywords)
- keywords))))))
-
- ;;** Helm sources
- (defvar orhc-multiline t
- "Make helm-source multiline if non-nil.
- This adds a small separator between the candidates which is a
- little more readable.")
-
- (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.")
-
- (defvar org-ref-helm-cite-source
- (helm-build-sync-source "org-ref Bibtex"
- :init #'org-ref-helm-cite-init
- :candidates #'orhc-bibtex-candidates
- :keymap 'org-ref-helm-cite-map
- :multiline orhc-multiline
- :help-message 'org-ref-helm-cite-help-message
- :filtered-candidate-transformer 'org-ref-helm-candidate-transformer
- :action-transformer 'org-ref-helm-cite-action-transformer
- :action '()))
-
- ;; Fallback sources
- ;; The candidates here are functions that work on `helm-pattern'.
- (defvar org-ref-helm-cite-fallback-source
- nil
- "Helm fallback source.")
-
-
- (setq org-ref-helm-cite-fallback-source
- (helm-build-sync-source "org-ref bibtex Fallbacks"
- :candidates '(("Google" . (lambda ()
- (browse-url
- (format "http://www.google.com/search?q=%s"
- (url-hexify-string helm-pattern)))))
- ("Google Scholar" . (lambda ()
- (browse-url
- (format "http://scholar.google.com/scholar?q=%s"
- (url-hexify-string helm-pattern)))))
- ("Crossref" . (lambda ()
- (browse-url
- (format
- "http://search.crossref.org/?q=%s"
- (url-hexify-string helm-pattern)))))
- ("Pubmed" . (lambda ()
- (browse-url
- (format
- "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s"
- (url-hexify-string helm-pattern)))))
- ("Arxiv" . (lambda ()
- (browse-url
- (format
- "http://arxiv.org/find/all/1/all:+AND+%s/0/1/0/all/0/1"
- (url-hexify-string helm-pattern)))))
- ("WebOfKnowledge" . (lambda ()
- (browse-url
- (format
- "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
- (url-hexify-string helm-pattern)))))
- ("Scopus" . (lambda ()
- (browse-url
- (format
- "http://www.scopus.com//search/submit/basic.url?field1=TITLE-ABS-KEY&searchterm1=%s"
- (url-hexify-string helm-pattern)))))
- )
- ;; This keeps all the fallback candidates available, by tricking it into
- ;; thinking every candidate is a match.
- :match (lambda (_candidate) t)
- :action (lambda (candidate) (funcall candidate))))
-
-
- (defun org-ref-helm-cite ()
- "Helm interface to bibtex files for `org-ref'."
- (interactive)
- (helm :sources '(org-ref-helm-cite-source
- org-ref-helm-cite-fallback-source)))
-
-
- (defalias 'orhc 'org-ref-helm-cite)
-
- ;; ** Onclick function
- ;; These are adapted from org-ref-helm-bibtex, and the dependencies on helm-bibtex removed.
-
- (defun org-ref-helm-cite-candidates ()
- "Generate the list of possible candidates for click actions on a cite link.
- Checks for pdf and doi, and add appropriate functions."
- (let* ((results (org-ref-get-bibtex-key-and-file))
- (key (car results))
- (bibfile (cdr results))
- (pdf-file (funcall org-ref-get-pdf-filename-function key))
- (url (save-excursion
- (with-temp-buffer
- (insert-file-contents bibfile)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key)
- (bibtex-autokey-get-field "url"))))
- (doi (save-excursion
- (with-temp-buffer
- (insert-file-contents bibfile)
- (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
- (bibtex-search-entry key)
- ;; I like this better than bibtex-url which does not always find
- ;; the urls
- (bibtex-autokey-get-field "doi"))))
- (candidates `(("Quit" . org-ref-citation-at-point)
- ("Open bibtex entry" . org-ref-open-citation-at-point))))
- ;; for some reason, when there is no doi or url, they are returned as "". I
- ;; prefer nil so we correct this here.
- (when (string= doi "") (setq doi nil))
- (when (string= url "") (setq url nil))
-
- ;; Conditional pdf functions
- ;; try with org-ref first
- (cond ((file-exists-p pdf-file)
- (cl-pushnew
- '("Open pdf" . (lambda ()
- (funcall org-ref-open-pdf-function)))
- candidates))
-
- ;; try with doi
- (t
- (cl-pushnew
- '("Try to get pdf" . (lambda ()
- (save-window-excursion
- (org-ref-open-citation-at-point)
- (bibtex-beginning-of-entry)
- (doi-utils-get-bibtex-entry-pdf))))
- candidates)))
-
- (cl-pushnew
- '("Add/Open notes" . org-ref-open-notes-at-point)
- candidates)
-
- ;; conditional url and doi functions
- (when (or url doi)
- (cl-pushnew
- '("Open in browser" . org-ref-open-url-at-point)
- candidates))
-
- (when doi
- (mapc (lambda (x)
- (cl-pushnew x candidates))
- `(("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))))
-
- (cl-pushnew
- '("Insert new citation" . (lambda ()
- (org-ref-helm-insert-cite-link nil)))
- candidates)
-
- (cl-pushnew
- '("Delete key at point" . org-ref-delete-key-at-point)
- candidates)
-
- ;; This is kind of clunky. We store the key at point. Add the new ref. Get
- ;; it off the end, and put it in the original position.
- (cl-pushnew
- '("Replace key at point" . org-ref-replace-key-at-point)
- candidates)
-
- (cl-pushnew
- '("Delete citation at point" . org-ref-delete-cite-at-point)
- candidates)
-
- (cl-pushnew
- '("Sort keys by year" . org-ref-sort-citation-link)
- candidates)
-
- (cl-pushnew
- '("Copy formatted citation to clipboard" . org-ref-copy-entry-as-summary)
- candidates)
-
- (cl-pushnew
- '("Copy key to clipboard" . (lambda ()
- (kill-new
- (car (org-ref-get-bibtex-key-and-file)))))
- candidates)
-
- (cl-pushnew
- '("Copy bibtex entry to file" . org-ref-copy-entry-at-point-to-file)
- candidates)
-
- (cl-pushnew
- '("Email bibtex entry and pdf" . (lambda ()
- (save-excursion
- (org-ref-open-citation-at-point)
- (org-ref-email-bibtex-entry))))
- candidates)
-
- ;; add Scopus functions. These work by looking up a DOI to get a Scopus
- ;; EID. This may only work for Scopus articles. Not all DOIs are recognized
- ;; in the Scopus API. We only load these if you have defined a
- ;; `*scopus-api-key*', which is required to do the API queries. See
- ;; `scopus'. These functions are appended to the candidate list.
- (when (and (boundp '*scopus-api-key*) *scopus-api-key*)
- (cl-pushnew
- '("Open in Scopus" . (lambda ()
- (let ((eid (scopus-doi-to-eid (org-ref-get-doi-at-point))))
- (if eid
- (scopus-open-eid eid)
- (message "No EID found.")))))
- candidates)
-
- (cl-pushnew
- '("Scopus citing articles" . (lambda ()
- (let ((url (scopus-citing-url
- (org-ref-get-doi-at-point))))
- (if url
- (browse-url url)
- (message "No url found.")))))
- candidates)
-
- (cl-pushnew
- '("Scopus related by authors" . (lambda ()
- (let ((url (scopus-related-by-author-url
- (org-ref-get-doi-at-point))))
- (if url
- (browse-url url)
- (message "No url found.")))))
- candidates)
-
- (cl-pushnew
- '("Scopus related by references" . (lambda ()
- (let ((url (scopus-related-by-references-url
- (org-ref-get-doi-at-point))))
- (if url
- (browse-url url)
- (message "No url found.")))))
- candidates)
-
- (cl-pushnew
- '("Scopus related by keywords" . (lambda ()
- (let ((url (scopus-related-by-keyword-url
- (org-ref-get-doi-at-point))))
- (if url
- (browse-url url)
- (message "No url found.")))))
- candidates))
-
- ;; finally return a numbered list of the candidates
- (cl-loop for i from 0
- for cell in (reverse candidates)
- collect (cons (format "%2s. %s" i (car cell))
- (cdr cell)))))
-
- (defun org-ref-helm-cite-click (_key)
- "Open helm for actions on a cite link.
- subtle points.
-
- 1. get name and candidates before entering helm because we need
- the org-buffer.
-
- 2. switch back to the org buffer before evaluating the
- action. most of them need the point and buffer.
-
- KEY is returned for the selected item(s) in helm."
- (interactive)
- (let ((name (org-ref-format-entry (org-ref-get-bibtex-key-under-cursor)))
- (candidates (org-ref-helm-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))))))))
-
-
- ;;* Formatted citations
-
- (defun orhc-formatted-citations (_candidate)
- "Return string containing formatted citations for entries in
- `helm-marked-candidates'."
- (load-library
- (completing-read "Style: " '("unsrt" "author-year") nil nil "unsrt"))
-
- (with-temp-buffer
- (cl-loop for i from 1 to (length (helm-marked-candidates))
- for entry in (helm-marked-candidates)
- do
- (insert (format "%s. %s\n\n" i (orhc-formatted-citation entry))))
-
- (buffer-string)))
-
-
- (defun orhc-insert-formatted-citations (candidate)
- "Insert formatted citations at point for selected entries."
- (insert (orhc-formatted-citations candidate)))
-
-
- (defun orhc-copy-formatted-citations (candidate)
- "Copy formatted citations to clipboard for selected entries."
- (with-temp-buffer
- (orhc-insert-formatted-citations candidate)
- (kill-ring-save (point-min) (point-max))))
-
- (provide 'org-ref-helm-cite)
- ;;; org-ref-helm-cite.el ends here
|