Update packages/ Add org-ref
This commit is contained in:
732
elpa/org-ref-20180608.1130/org-ref-helm-bibtex.el
Normal file
732
elpa/org-ref-20180608.1130/org-ref-helm-bibtex.el
Normal file
@@ -0,0 +1,732 @@
|
||||
;;; org-ref-helm-bibtex.el --- Customization of helm-bibtex 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 file defines the completion engine for org-ref using `helm-bibtex'.
|
||||
|
||||
|
||||
(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-get-pdf-filename-function)
|
||||
(defvar org-ref-default-citation-link)
|
||||
(defvar org-ref-cite-types)
|
||||
(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 'helm-config)
|
||||
(require 'helm)
|
||||
(require 'helm-bibtex)
|
||||
(require 'helm-utils)
|
||||
(require 'org-ref-helm)
|
||||
(require 'async)
|
||||
(require 'package)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ref-bibtex-completion-completion ()
|
||||
"Use helm and ‘helm-bibtex’ for completion."
|
||||
(interactive)
|
||||
;; Define core functions for org-ref
|
||||
(setq org-ref-insert-link-function 'org-ref-helm-insert-cite-link
|
||||
org-ref-insert-cite-function 'org-ref-helm-insert-cite-link
|
||||
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-cite-click-helm))
|
||||
|
||||
(org-ref-bibtex-completion-completion)
|
||||
(define-key org-mode-map
|
||||
(kbd org-ref-insert-cite-key)
|
||||
org-ref-insert-link-function)
|
||||
|
||||
(defcustom org-ref-bibtex-completion-actions
|
||||
'(("Insert citation" . helm-bibtex-insert-citation)
|
||||
("Open PDF, URL or DOI" . helm-bibtex-open-any)
|
||||
("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)
|
||||
("Insert formatted citation(s)" . (lambda (_)
|
||||
(insert
|
||||
(mapconcat 'identity
|
||||
(cl-loop for key in (helm-marked-candidates)
|
||||
collect (org-ref-format-entry key))
|
||||
"\n\n"))))
|
||||
("Attach PDF to email" . helm-bibtex-add-PDF-attachment)
|
||||
("Edit notes" . helm-bibtex-edit-notes)
|
||||
("Show entry" . helm-bibtex-show-entry)
|
||||
("Add keywords to entries" . org-ref-helm-tag-entries)
|
||||
("Copy entry to clipboard" . bibtex-completion-copy-candidate)
|
||||
("Add PDF to library" . helm-bibtex-add-pdf-to-library))
|
||||
"Cons cells of string and function to set the actions of `helm-bibtex' to.
|
||||
The car of cons cell is the string describing the function.
|
||||
The cdr of the the cons cell is the function to use."
|
||||
:type '(alist :key-type (string) :value-type (function))
|
||||
:group 'org-ref)
|
||||
|
||||
|
||||
(cl-loop for i from 0 to (length org-ref-bibtex-completion-actions)
|
||||
for ccell in org-ref-bibtex-completion-actions
|
||||
do
|
||||
(helm-delete-action-from-source (car ccell) helm-source-bibtex)
|
||||
(helm-add-action-to-source
|
||||
(car ccell)
|
||||
(cdr ccell)
|
||||
helm-source-bibtex))
|
||||
|
||||
|
||||
(defcustom org-ref-bibtex-completion-format-org
|
||||
'org-ref-bibtex-completion-format-org
|
||||
"Function for how `helm-bibtex' inserts citations."
|
||||
:type 'function
|
||||
:group 'org-ref)
|
||||
|
||||
|
||||
(setf (cdr (assoc 'org-mode bibtex-completion-format-citation-functions))
|
||||
org-ref-bibtex-completion-format-org)
|
||||
|
||||
|
||||
(setq org-ref-insert-cite-function 'org-ref-helm-insert-cite-link
|
||||
org-ref-cite-onclick-function 'org-ref-cite-click-helm)
|
||||
|
||||
|
||||
;;* Helm bibtex setup.
|
||||
(setq bibtex-completion-additional-search-fields '(keywords))
|
||||
|
||||
(setq bibtex-completion-display-formats
|
||||
'((t . "${author:36} ${title:*} ${year:4} ${=has-pdf=:1}${=has-note=:1} ${=type=:7} ${keywords:31}")))
|
||||
|
||||
(defun bibtex-completion-copy-candidate (_candidate)
|
||||
"Copy the selected bibtex entries to the clipboard.
|
||||
Used as a new action in `helm-bibtex'.
|
||||
CANDIDATE is ignored."
|
||||
(with-temp-buffer
|
||||
(mapc #'insert-file-contents
|
||||
(-flatten (list bibtex-completion-bibliography)))
|
||||
|
||||
(let ((entries '()))
|
||||
(cl-loop for bibtex-key in (helm-marked-candidates)
|
||||
do
|
||||
(goto-char (point-min))
|
||||
(re-search-forward (concat "^@\\(" parsebib--bibtex-identifier
|
||||
"\\)[[:space:]]*[\(\{][[:space:]]*"
|
||||
(regexp-quote bibtex-key)
|
||||
"[[:space:]]*,"))
|
||||
(bibtex-mark-entry)
|
||||
(cl-pushnew (buffer-substring (point) (mark)) entries))
|
||||
|
||||
(with-temp-buffer
|
||||
(dolist (entry entries)
|
||||
(insert (format "%s\n\n" entry)))
|
||||
(kill-new (buffer-string))))))
|
||||
|
||||
|
||||
|
||||
(defun org-ref-helm-tag-entries (_candidates)
|
||||
"Set tags on selected bibtex entries from `helm-bibtex'.
|
||||
User is prompted for tags. This function is called from `helm-bibtex'.
|
||||
Argument CANDIDATES helm candidates."
|
||||
(message "")
|
||||
(let* ((keys (helm-marked-candidates))
|
||||
(entry (bibtex-completion-get-entry (car keys)))
|
||||
(field (cdr (assoc-string "keywords" entry)))
|
||||
(value (when field (replace-regexp-in-string "^{\\|}$" "" field)))
|
||||
(keywords (read-string "Keywords (comma separated): "
|
||||
(when (and value (not (equal "" value)))
|
||||
(concat value ", ")))))
|
||||
(cl-loop for key in keys
|
||||
do
|
||||
(save-window-excursion
|
||||
(bibtex-completion-show-entry (list key))
|
||||
;; delete keyword field if empty
|
||||
(if (equal "" keywords)
|
||||
(save-restriction
|
||||
(bibtex-narrow-to-entry)
|
||||
(goto-char (car (cdr (bibtex-search-forward-field "keywords" t))))
|
||||
(bibtex-kill-field))
|
||||
(bibtex-set-field
|
||||
"keywords"
|
||||
(concat
|
||||
(if (listp keywords)
|
||||
(if (string-match value keywords)
|
||||
(and (replace-match "")
|
||||
(mapconcat 'identity keywords ", "))
|
||||
(mapconcat 'identity keywords ", "))
|
||||
;; remove trailing comma
|
||||
(replace-regexp-in-string ", $" "" keywords)))))
|
||||
(save-buffer)))))
|
||||
|
||||
|
||||
(defun org-ref-bibtex-completion-format-org (keys)
|
||||
"Insert selected KEYS as cite link.
|
||||
Append KEYS if you are on a link.
|
||||
|
||||
Technically, this function should return a string that is
|
||||
inserted by helm. This function does the insertion and gives helm
|
||||
an empty string to insert. This lets us handle appending to a
|
||||
link properly.
|
||||
|
||||
In the `helm-bibtex' buffer, \\[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* ((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) 'mv)
|
||||
(skip-chars-backward " ")
|
||||
(skip-chars-backward "]")
|
||||
(unless (looking-at ",") (insert ","))
|
||||
(insert (mapconcat 'identity keys ",")))))
|
||||
;; double prefix, replace key at point
|
||||
((equal helm-current-prefix-arg '(16))
|
||||
(setf (buffer-substring
|
||||
(org-element-property :begin object)
|
||||
(org-element-property :end object))
|
||||
(concat
|
||||
(replace-regexp-in-string
|
||||
(car (org-ref-get-bibtex-key-and-file)) ; key
|
||||
(mapconcat 'identity keys ",") ; new keys
|
||||
(org-element-property :raw-link object))
|
||||
;; replace space at end to avoid collapsing into next word.
|
||||
last-char))
|
||||
;; and we want to go to the end of the new link
|
||||
(goto-char
|
||||
(org-element-property :end (org-element-context))))
|
||||
(t
|
||||
(message "Not found"))))
|
||||
|
||||
;; We are next to a link, and we want to append
|
||||
;; next to a link means one character back is on a link.
|
||||
((save-excursion
|
||||
(unless (bobp) (backward-char))
|
||||
(and (equal (org-element-type (org-element-context)) 'link)
|
||||
(-contains?
|
||||
org-ref-cite-types
|
||||
(org-element-property :type (org-element-context)))))
|
||||
(skip-chars-backward " ")
|
||||
(insert (concat "," (mapconcat 'identity keys ","))))
|
||||
|
||||
;; insert fresh link
|
||||
(t
|
||||
(insert
|
||||
(concat
|
||||
(when org-ref-prefer-bracket-links "[[")
|
||||
(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)
|
||||
(when org-ref-prefer-bracket-links "]]"))))))
|
||||
;; return empty string for helm
|
||||
"")
|
||||
|
||||
|
||||
(defun org-ref-format-citation (keys)
|
||||
"Formatter for org-ref citation commands.
|
||||
Prompt for the command and additional arguments if the commands can
|
||||
take any. If point is inside a citation link, append KEYS. Otherwise
|
||||
prompt for pre/post text. Prompts can also be switched off by setting
|
||||
the variable `bibtex-completion-cite-prompt-for-optional-arguments' to
|
||||
nil. To enable this formatter, add it to
|
||||
`bibtex-completion-format-citation-functions'. For example:
|
||||
|
||||
\(setf (cdr (assoc 'org-mode bibtex-completion-format-citation-functions)) 'org-ref-format-citation)
|
||||
|
||||
Note also that pre text is preceded by a double colon, for example:
|
||||
|
||||
\[[cite:key][See::Chapter 1]], which exports to:
|
||||
|
||||
\\cite[See][Chapter 1]{key}."
|
||||
;; Check if point is inside a cite link
|
||||
(let ((link (org-element-context))
|
||||
end path)
|
||||
(if (-contains? org-ref-cite-types (org-element-property :type link))
|
||||
(progn
|
||||
(setq end (org-element-property :end link)
|
||||
path (org-element-property :path link))
|
||||
(goto-char end)
|
||||
(skip-chars-backward " ")
|
||||
;; Check if link has pre/post text
|
||||
(if (looking-back "\]" (line-beginning-position))
|
||||
(progn
|
||||
(re-search-backward path nil t)
|
||||
(re-search-forward "\]" nil t)
|
||||
(backward-char 1)
|
||||
(format ",%s" (s-join "," keys))))
|
||||
(format ",%s" (s-join "," keys)))
|
||||
(let* ((initial (when bibtex-completion-cite-default-as-initial-input bibtex-completion-cite-default-command))
|
||||
(default
|
||||
(unless bibtex-completion-cite-default-as-initial-input bibtex-completion-cite-default-command))
|
||||
(default-info
|
||||
(if default (format " (default \"%s\")" default) ""))
|
||||
(cite-command
|
||||
(completing-read (format "Cite command%s: " default-info)
|
||||
bibtex-completion-cite-commands nil nil initial
|
||||
'bibtex-completion-cite-command-history default nil)))
|
||||
(if (member cite-command '("nocite" "supercite")) ; These don't want arguments.
|
||||
(format "%s:%s" cite-command (s-join "," keys))
|
||||
(let ((text (if bibtex-completion-cite-prompt-for-optional-arguments
|
||||
(read-from-minibuffer "Pre/post text: ")
|
||||
"")))
|
||||
(if (string= "" text)
|
||||
(format "%s:%s" cite-command (s-join "," keys))
|
||||
(format "[[%s:%s][%s]]" cite-command (s-join "," keys) text))))))))
|
||||
|
||||
|
||||
(defvar bibtex-completion-cached-candidates)
|
||||
(defvar bibtex-completion-bibliography-hash)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ref-helm-load-completions-async ()
|
||||
"Load the bibtex files into helm sources asynchronously.
|
||||
For large bibtext files, the intial call to ‘org-ref-helm-insert-cite-link’
|
||||
can take a long time to load the completion sources. This function loads
|
||||
the completion sources in the background so the initial call to ‘org-ref-helm-insert-cite-link’ is much faster."
|
||||
(interactive)
|
||||
(async-start
|
||||
`(lambda (&optional formatter)
|
||||
(require 'package)
|
||||
(package-initialize)
|
||||
(require 'helm-bibtex)
|
||||
,(async-inject-variables "bibtex-compl.*")
|
||||
|
||||
(with-temp-buffer
|
||||
(mapc #'insert-file-contents
|
||||
(-flatten (list bibtex-completion-bibliography)))
|
||||
;; Check hash of bibliography and reparse if necessary:
|
||||
(let ((bibliography-hash (secure-hash 'sha256 (current-buffer))))
|
||||
(unless (and bibtex-completion-cached-candidates
|
||||
(string= bibtex-completion-bibliography-hash bibliography-hash))
|
||||
(message "Loading bibliography ...")
|
||||
(let* ((entries (bibtex-completion-parse-bibliography))
|
||||
(entries (bibtex-completion-resolve-crossrefs entries))
|
||||
(entries (bibtex-completion-prepare-entries entries))
|
||||
(entries (nreverse entries))
|
||||
(entries
|
||||
(--map (cons (bibtex-completion-clean-string
|
||||
(s-join " " (-map #'cdr it))) it)
|
||||
entries)))
|
||||
(setq bibtex-completion-cached-candidates
|
||||
(if (functionp formatter)
|
||||
(funcall formatter entries)
|
||||
entries)))
|
||||
(setq bibtex-completion-bibliography-hash bibliography-hash))
|
||||
(cons bibliography-hash bibtex-completion-cached-candidates))))
|
||||
(lambda (result)
|
||||
(setq bibtex-completion-cached-candidates (cdr result))
|
||||
(setq bibtex-completion-bibliography-hash (car result))
|
||||
(message "Finished loading org-ref completions"))))
|
||||
|
||||
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ref-helm-insert-cite-link (&optional arg)
|
||||
"Insert a citation link with `helm-bibtex'.
|
||||
With one prefix ARG, insert a ref link.
|
||||
With two prefix ARGs, insert a label link."
|
||||
(interactive "P")
|
||||
;; save all bibtex buffers so we get the most up-to-date selection. I find
|
||||
;; that I often edit a bibliography and forget to save it, so the newest entry
|
||||
;; does not show in helm-bibtex.
|
||||
(org-ref-save-all-bibtex-buffers)
|
||||
(cond
|
||||
((equal arg nil)
|
||||
(let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
|
||||
(helm-bibtex)))
|
||||
((equal arg '(4))
|
||||
(org-ref-helm-insert-ref-link))
|
||||
((equal arg '(16))
|
||||
(org-ref-helm-insert-label-link))))
|
||||
|
||||
|
||||
;; add our own fallback entries where we want them. These appear in reverse
|
||||
;; order of adding in the menu
|
||||
(setq bibtex-completion-fallback-options
|
||||
(-insert-at 1 '("Crossref" . "http://search.crossref.org/?q=%s") bibtex-completion-fallback-options))
|
||||
|
||||
|
||||
(setq bibtex-completion-fallback-options
|
||||
(-insert-at
|
||||
1
|
||||
'("Scopus" . "http://www.scopus.com/scopus/search/submit/xadvanced.url?searchfield=TITLE-ABS-KEY(%s)")
|
||||
bibtex-completion-fallback-options))
|
||||
|
||||
|
||||
(setq bibtex-completion-fallback-options
|
||||
(-insert-at 1 '("WOS" . "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary") bibtex-completion-fallback-options))
|
||||
|
||||
(defun org-ref-cite-candidates ()
|
||||
"Generate the list of possible candidates for click actions on a cite link.
|
||||
Checks for pdf and doi, and add appropriate functions."
|
||||
(let* ((results (org-ref-get-bibtex-key-and-file))
|
||||
(key (car results))
|
||||
(bibfile (cdr results))
|
||||
(bibtex-completion-bibliography (list bibfile))
|
||||
(entry (bibtex-completion-get-entry key))
|
||||
(pdf-file (funcall org-ref-get-pdf-filename-function key))
|
||||
(pdf-bibtex-completion (car (bibtex-completion-find-pdf key)))
|
||||
(notes-p (cdr (assoc "=has-note=" entry)))
|
||||
(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 bibtex-completion
|
||||
(pdf-bibtex-completion
|
||||
(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)))
|
||||
|
||||
(if notes-p
|
||||
(cl-pushnew
|
||||
'("Open notes" . org-ref-open-notes-at-point)
|
||||
candidates)
|
||||
(cl-pushnew
|
||||
'("Add 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)
|
||||
|
||||
(when bibtex-completion-cite-prompt-for-optional-arguments
|
||||
(cl-pushnew
|
||||
'("Update pre/post text" . org-ref-update-pre-post-text)
|
||||
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)))))
|
||||
|
||||
|
||||
(defvar org-ref-helm-user-candidates '()
|
||||
"List of user-defined candidates to act when clicking on a cite link.
|
||||
This is a list of cons cells '((\"description\" . action)). The
|
||||
action function should not take an argument, and should assume
|
||||
point is on the cite key of interest.")
|
||||
|
||||
;; example of adding your own function
|
||||
(add-to-list
|
||||
'org-ref-helm-user-candidates
|
||||
'("Open pdf in emacs" . (lambda ()
|
||||
(find-file
|
||||
(concat
|
||||
(file-name-as-directory org-ref-pdf-directory)
|
||||
(car (org-ref-get-bibtex-key-and-file))
|
||||
".pdf"))))
|
||||
t)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ref-cite-click-helm (_key)
|
||||
"Open helm for actions on a cite link.
|
||||
subtle points.
|
||||
|
||||
1. get name and candidates before entering helm because we need
|
||||
the org-buffer.
|
||||
|
||||
2. switch back to the org buffer before evaluating the
|
||||
action. most of them need the point and buffer.
|
||||
|
||||
KEY is returned for the selected item(s) in helm."
|
||||
(interactive)
|
||||
(let ((name (org-ref-format-entry (org-ref-get-bibtex-key-under-cursor)))
|
||||
(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))))))))
|
||||
|
||||
|
||||
;; browse labels
|
||||
|
||||
(defun org-ref-browser-label-source ()
|
||||
(let ((labels (org-ref-get-labels)))
|
||||
(helm-build-sync-source "Browse labels"
|
||||
:follow 1
|
||||
:candidates labels
|
||||
:action '(("Browse labels" . (lambda (label)
|
||||
(with-selected-window (selected-window)
|
||||
(org-open-link-from-string
|
||||
(format "ref:%s" label)))))))))
|
||||
|
||||
;; browse citation links
|
||||
|
||||
(defun org-ref-browser-transformer (candidates)
|
||||
"Add counter to candidates."
|
||||
(let ((counter 0))
|
||||
(cl-loop for i in candidates
|
||||
collect (format "%s %s" (cl-incf counter) i))))
|
||||
|
||||
(defun org-ref-browser-display (candidate)
|
||||
"Strip counter from candidates."
|
||||
(replace-regexp-in-string "^[0-9]+? " "" candidate))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ref-browser (&optional arg)
|
||||
"Quickly browse label links in helm.
|
||||
With a prefix ARG, browse citation links."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(let ((keys nil)
|
||||
(alist nil))
|
||||
(widen)
|
||||
(outline-show-all)
|
||||
(org-element-map (org-element-parse-buffer) 'link
|
||||
(lambda (link)
|
||||
(let ((plist (nth 1 link)))
|
||||
(when (-contains? org-ref-cite-types (plist-get plist ':type))
|
||||
(let ((start (org-element-property :begin link)))
|
||||
(dolist (key
|
||||
(org-ref-split-and-strip-string (plist-get plist ':path)))
|
||||
(setq keys (append keys (list key)))
|
||||
(setq alist (append alist (list (cons key start))))))))))
|
||||
(let ((counter 0)
|
||||
count-key-pos)
|
||||
;; the idea here is to create an alist with ("counter key" .
|
||||
;; position) to produce unique candidates
|
||||
(setq count-key-pos (mapcar (lambda (x)
|
||||
(cons
|
||||
(format "%s %s" (cl-incf counter) (car x)) (cdr x)))
|
||||
alist))
|
||||
;; push mark to restore position with C-u C-SPC
|
||||
(push-mark (point))
|
||||
;; move point to the first citation link in the buffer
|
||||
(goto-char (cdr (assoc (caar alist) alist)))
|
||||
(helm :sources
|
||||
(helm-build-sync-source "Browse citation links"
|
||||
:follow 1
|
||||
:candidates keys
|
||||
:candidate-transformer 'org-ref-browser-transformer
|
||||
:real-to-display 'org-ref-browser-display
|
||||
:persistent-action (lambda (candidate)
|
||||
(helm-goto-char
|
||||
(cdr (assoc candidate count-key-pos))))
|
||||
:action `(("Open menu" . ,(lambda (candidate)
|
||||
(helm-goto-char
|
||||
(cdr (assoc candidate count-key-pos)))
|
||||
(org-open-at-point)))))
|
||||
:candidate-number-limit 10000
|
||||
:buffer "*helm browser*")))
|
||||
(helm :sources (org-ref-browser-label-source)
|
||||
:buffer "*helm labels*")))
|
||||
|
||||
|
||||
|
||||
(provide 'org-ref-helm-bibtex)
|
||||
;;; org-ref-helm-bibtex.el ends here
|
||||
Reference in New Issue
Block a user