|
;;; org-ref-ivy-cite.el --- Use ivy for completion in 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:
|
|
|
|
;;
|
|
|
|
(declare-function 'org-ref-insert-key-at-point "org-ref-core.el")
|
|
(declare-function 'org-ref-find-bibliography "org-ref-core.el")
|
|
(declare-function 'org-ref-get-labels "org-ref-core.el")
|
|
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
|
|
|
|
|
|
;;; Code:
|
|
(require 'ivy)
|
|
(require 'org-ref-bibtex)
|
|
(require 'org-ref-citeproc)
|
|
(require 'bibtex-completion)
|
|
|
|
;; This lets you customize how the completion for ivy is displayed. The default
|
|
;; is in the minibuffer. You may like to see something more like a popup though.
|
|
(defcustom org-ref-ivy-display-function nil
|
|
"ivy function to display completion with.
|
|
Set to `ivy-display-function-overlay' to get popups at point."
|
|
:type 'function
|
|
:group 'org-ref)
|
|
|
|
(when org-ref-ivy-display-function
|
|
(add-to-list 'ivy-display-functions-alist
|
|
`(org-ref-ivy-insert-cite-link . ,org-ref-ivy-display-function))
|
|
(add-to-list 'ivy-display-functions-alist
|
|
`(org-ref-ivy-insert-label-link . ,org-ref-ivy-display-function))
|
|
(add-to-list 'ivy-display-functions-alist
|
|
`(org-ref-ivy-insert-ref-link . ,org-ref-ivy-display-function)))
|
|
|
|
|
|
(defvar org-ref-cite-types)
|
|
(defvar org-ref-show-citation-on-enter)
|
|
|
|
(defvar org-ref-ivy-cite-marked-candidates '()
|
|
"Holds entries marked in `org-ref-ivy-insert-cite-link'.")
|
|
|
|
;;;###autoload
|
|
(defun org-ref-ivy-cite-completion ()
|
|
"Use ivy for completion."
|
|
(interactive)
|
|
;; Define core functions for org-ref
|
|
(setq org-ref-insert-link-function 'org-ref-insert-link
|
|
org-ref-insert-cite-function 'org-ref-ivy-insert-cite-link
|
|
org-ref-insert-label-function 'org-ref-ivy-insert-label-link
|
|
org-ref-insert-ref-function 'org-ref-ivy-insert-ref-link
|
|
org-ref-cite-onclick-function (lambda (_) (org-ref-cite-hydra/body))))
|
|
|
|
(org-ref-ivy-cite-completion)
|
|
|
|
(define-key org-mode-map
|
|
(kbd org-ref-insert-cite-key)
|
|
org-ref-insert-link-function)
|
|
|
|
|
|
(defun or-looking-forward-cite ()
|
|
"Return if point is in the position before a citation."
|
|
(save-excursion
|
|
(forward-char)
|
|
(-contains? org-ref-cite-types
|
|
(org-element-property
|
|
:type
|
|
(org-element-context)))))
|
|
|
|
|
|
(defun or-looking-back-cite ()
|
|
"Return if point is in the position after a citation."
|
|
(save-excursion
|
|
(forward-char -1)
|
|
(-contains? org-ref-cite-types
|
|
(org-element-property
|
|
:type
|
|
(org-element-context)))))
|
|
|
|
|
|
(defun or-ivy-bibtex-insert-cite (entry)
|
|
"Insert a citation for ENTRY.
|
|
If `org-ref-ivy-cite-marked-candidates' is non-nil then they are added instead of ENTRY.
|
|
ENTRY is selected from `orhc-bibtex-candidates'."
|
|
(with-ivy-window
|
|
(if org-ref-ivy-cite-marked-candidates
|
|
(cl-loop for entry in org-ref-ivy-cite-marked-candidates
|
|
do
|
|
(if ivy-current-prefix-arg
|
|
(let ((org-ref-default-citation-link (ivy-read "Type: " org-ref-cite-types)))
|
|
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry)))))
|
|
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry))))))
|
|
(if ivy-current-prefix-arg
|
|
(let ((org-ref-default-citation-link (ivy-read "Type: " org-ref-cite-types)))
|
|
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry)))))
|
|
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry))))))))
|
|
|
|
|
|
(defun or-ivy-bibtex-open-pdf (entry)
|
|
"Open the pdf associated with ENTRY.
|
|
ENTRY is selected from `orhc-bibtex-candidates'."
|
|
(with-ivy-window
|
|
(let ((pdf (expand-file-name
|
|
(format "%s.pdf"
|
|
(cdr (assoc "=key=" entry)))
|
|
org-ref-pdf-directory)))
|
|
(if (file-exists-p pdf)
|
|
(org-open-file pdf)
|
|
(message "No pdf found for %s" (cdr (assoc "=key=" entry)))))))
|
|
|
|
|
|
(defun or-ivy-bibtex-open-notes (entry)
|
|
"Open the notes associated with ENTRY.
|
|
ENTRY is selected from `orhc-bibtex-candidates'."
|
|
(with-ivy-window
|
|
(org-ref-open-notes-at-point
|
|
(cdr (assoc "=key=" entry)))))
|
|
|
|
|
|
(defun or-ivy-bibtex-open-entry (entry)
|
|
"Open the bibtex file at ENTRY.
|
|
ENTRY is selected from `orhc-bibtex-candidates'."
|
|
(find-file (cdr (assoc "bibfile" entry)))
|
|
(goto-char (cdr (assoc "position" entry)))
|
|
(bibtex-beginning-of-entry))
|
|
|
|
|
|
(defun or-ivy-bibtex-copy-entry (entry)
|
|
"Copy selected bibtex ENTRY to the clipboard."
|
|
(with-temp-buffer
|
|
(save-window-excursion
|
|
(or-ivy-bibtex-open-entry entry)
|
|
(bibtex-copy-entry-as-kill))
|
|
(bibtex-yank)
|
|
(kill-region (point-min) (point-max))))
|
|
|
|
|
|
(defun or-ivy-bibtex-open-url (entry)
|
|
"Open the URL associated with ENTRY.
|
|
ENTRY is selected from `orhc-bibtex-candidates'."
|
|
(let ((url (cdr (assoc "url" entry))))
|
|
(if url
|
|
(browse-url url)
|
|
(message "No url found for %s" (cdr (assoc "=key=" entry))))))
|
|
|
|
|
|
(defun or-ivy-bibtex-open-doi (entry)
|
|
"Open the DOI associated with ENTRY.
|
|
ENTRY is selected from `orhc-bibtex-candidates'."
|
|
(let ((doi (cdr (assoc "doi" entry))))
|
|
(if doi
|
|
(browse-url (format "http://dx.doi.org/%s" doi))
|
|
(message "No doi found for %s" (cdr (assoc "=key=" entry))))))
|
|
|
|
|
|
(defun or-ivy-bibtex-set-keywords (entry)
|
|
"Prompt for keywords, and put them on the selected ENTRY."
|
|
(let ((keywords (read-string "Keyword(s) comma-separated: " ))
|
|
entry-keywords)
|
|
(save-window-excursion
|
|
(or-ivy-bibtex-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)))))
|
|
|
|
|
|
(defun or-ivy-bibtex-email-entry (entry)
|
|
"Insert selected ENTRY and attach pdf file to an email.
|
|
Create email unless called from an email."
|
|
(with-ivy-window
|
|
(let ((goto-to nil))
|
|
(unless (memq major-mode '(message-mode mu4e-compose-mode))
|
|
(setq goto-to t)
|
|
(compose-mail)
|
|
(message-goto-body))
|
|
(save-window-excursion
|
|
(or-ivy-bibtex-open-entry entry)
|
|
(bibtex-copy-entry-as-kill))
|
|
(insert (pop bibtex-entry-kill-ring))
|
|
(insert "\n")
|
|
(let ((pdf (expand-file-name
|
|
(format "%s.pdf"
|
|
(cdr (assoc "=key=" entry)))
|
|
org-ref-pdf-directory)))
|
|
(if (file-exists-p pdf)
|
|
(mml-attach-file pdf)))
|
|
(when goto-to
|
|
(message-goto-to)))))
|
|
|
|
|
|
(defun or-ivy-bibtex-formatted-citation (entry)
|
|
"Return string containing formatted citations for ENTRY.
|
|
This uses a citeproc library."
|
|
(let ((enable-recursive-minibuffers t))
|
|
(ivy-read "Style: " '("unsrt" "author-year")
|
|
:action 'load-library
|
|
:require-match t
|
|
:preselect "unsrt"
|
|
:caller 'or-ivy-formatted-citation)
|
|
(format "%s\n\n" (orhc-formatted-citation entry))))
|
|
|
|
|
|
(defun or-ivy-bibtex-insert-formatted-citation (entry)
|
|
"Insert formatted citations at point for selected entries."
|
|
(with-ivy-window
|
|
(insert (mapconcat
|
|
'identity
|
|
(cl-loop for entry in (or org-ref-ivy-cite-marked-candidates (list entry))
|
|
collect (org-ref-format-bibtex-entry entry))
|
|
"\n\n"))))
|
|
|
|
|
|
(defun or-ivy-bibtex-copy-formatted-citation (entry)
|
|
"Copy formatted citation to clipboard for ENTRY."
|
|
(kill-new (org-ref-format-entry entry)))
|
|
|
|
|
|
(defun or-ivy-bibtex-add-entry (_)
|
|
"Open a bibliography file and move point to the end, in order
|
|
to add a new bibtex entry. The arg is selected from
|
|
`orhc-bibtex-candidates' but ignored."
|
|
(ivy-read "bibtex file: " org-ref-bibtex-files
|
|
:require-match t
|
|
:action 'find-file
|
|
:caller 'or-ivy-bibtex-add-entry)
|
|
(widen)
|
|
(goto-char (point-max))
|
|
(unless (bolp)
|
|
(insert "\n")))
|
|
|
|
|
|
(defvar org-ref-ivy-cite-actions
|
|
'(("b" or-ivy-bibtex-open-entry "Open bibtex entry")
|
|
("B" or-ivy-bibtex-copy-entry "Copy bibtex entry")
|
|
("p" or-ivy-bibtex-open-pdf "Open pdf")
|
|
("n" or-ivy-bibtex-open-notes "Open notes")
|
|
("u" or-ivy-bibtex-open-url "Open url")
|
|
("d" or-ivy-bibtex-open-doi "Open doi")
|
|
("k" or-ivy-bibtex-set-keywords "Add keywords")
|
|
("e" or-ivy-bibtex-email-entry "Email entry")
|
|
("f" or-ivy-bibtex-insert-formatted-citation "Insert formatted citation")
|
|
("F" or-ivy-bibtex-copy-formatted-citation "Copy formatted citation")
|
|
("a" or-ivy-bibtex-add-entry "Add bibtex entry"))
|
|
"List of additional actions for `org-ref-ivy-insert-cite-link' (the default action being to insert a citation).")
|
|
|
|
(defvar org-ref-ivy-cite-re-builder 'ivy--regex-ignore-order
|
|
"Regex builder to use in `org-ref-ivy-insert-cite-link'. Can be set to nil to use Ivy's default).")
|
|
|
|
(defun org-ref-swap (i j lst)
|
|
"Swap index I and J in the list LST."
|
|
(let ((tempi (nth i lst)))
|
|
(setf (nth i lst) (nth j lst))
|
|
(setf (nth j lst) tempi))
|
|
lst)
|
|
|
|
(defun org-ref-ivy-current ()
|
|
(if (boundp 'ivy--current)
|
|
ivy--current
|
|
(ivy-state-current ivy-last)))
|
|
|
|
(defun org-ref-ivy-move-up ()
|
|
"Move ivy candidate up and update candidates."
|
|
(interactive)
|
|
(setf (ivy-state-collection ivy-last)
|
|
(org-ref-swap ivy--index (1- ivy--index) (ivy-state-collection ivy-last)))
|
|
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
|
|
(ivy--reset-state ivy-last))
|
|
|
|
(defun org-ref-ivy-move-down ()
|
|
"Move ivy candidate down."
|
|
(interactive)
|
|
(setf (ivy-state-collection ivy-last)
|
|
(org-ref-swap ivy--index (1+ ivy--index) (ivy-state-collection ivy-last)))
|
|
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
|
|
(ivy--reset-state ivy-last))
|
|
|
|
(defun org-ref-ivy-sort-year-ascending ()
|
|
"Sort entries by year in ascending order."
|
|
(interactive)
|
|
(setf (ivy-state-collection ivy-last)
|
|
(cl-sort (copy-sequence (ivy-state-collection ivy-last))
|
|
(lambda (a b)
|
|
(let ((y1 (string-to-number (or (cdr (assoc "year" a)) "0")))
|
|
(y2 (string-to-number (or (cdr (assoc "year" b)) "0"))))
|
|
(< y1 y2)))))
|
|
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
|
|
(ivy--reset-state ivy-last))
|
|
|
|
(defun org-ref-ivy-sort-year-descending ()
|
|
"sort entries by year in descending order."
|
|
(interactive)
|
|
(setf (ivy-state-collection ivy-last)
|
|
(cl-sort (copy-sequence (ivy-state-collection ivy-last))
|
|
(lambda (a b)
|
|
(let ((y1 (string-to-number (or (cdr (assoc "year" a)) "0")))
|
|
(y2 (string-to-number (or (cdr (assoc "year" b)) "0"))))
|
|
(> y1 y2)))))
|
|
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
|
|
(ivy--reset-state ivy-last))
|
|
|
|
;; * marking candidates
|
|
|
|
(defun org-ref-ivy-mark-candidate ()
|
|
"Add current candidate to `org-ref-ivy-cite-marked-candidates'.
|
|
If candidate is already in, remove it."
|
|
(interactive)
|
|
(let ((cand (or (assoc (org-ref-ivy-current) (ivy-state-collection ivy-last))
|
|
(org-ref-ivy-current))))
|
|
(if (-contains? org-ref-ivy-cite-marked-candidates cand)
|
|
;; remove it from the marked list
|
|
(setq org-ref-ivy-cite-marked-candidates
|
|
(-remove-item cand org-ref-ivy-cite-marked-candidates))
|
|
|
|
;; add to list
|
|
(setq org-ref-ivy-cite-marked-candidates
|
|
(append org-ref-ivy-cite-marked-candidates (list cand)))))
|
|
|
|
(ivy-next-line))
|
|
|
|
|
|
(defun org-ref-ivy-show-marked-candidates ()
|
|
"Show marked candidates."
|
|
(interactive)
|
|
(setf (ivy-state-collection ivy-last) org-ref-ivy-cite-marked-candidates)
|
|
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
|
|
(ivy--reset-state ivy-last))
|
|
|
|
|
|
(defun org-ref-ivy-show-all ()
|
|
"Show all the candidates."
|
|
(interactive)
|
|
(setf (ivy-state-collection ivy-last)
|
|
(orhc-bibtex-candidates))
|
|
(ivy--reset-state ivy-last))
|
|
|
|
;; * org-ref-cite keymap
|
|
|
|
(defvar org-ref-ivy-cite-keymap
|
|
(let ((map (make-sparse-keymap)))
|
|
(define-key map (kbd "C-<SPC>") 'org-ref-ivy-mark-candidate)
|
|
(define-key map (kbd "C-,") 'org-ref-ivy-show-marked-candidates)
|
|
(define-key map (kbd "C-.") 'org-ref-ivy-show-all)
|
|
(define-key map (kbd "C-<up>") 'org-ref-ivy-move-up)
|
|
(define-key map (kbd "C-<down>") 'org-ref-ivy-move-down)
|
|
(define-key map (kbd "C-y") 'org-ref-ivy-sort-year-ascending)
|
|
(define-key map (kbd "C-M-y") 'org-ref-ivy-sort-year-descending)
|
|
(define-key map (kbd "C-k") (lambda ()
|
|
(interactive)
|
|
(beginning-of-line)
|
|
(kill-visual-line)
|
|
(setf (ivy-state-collection ivy-last)
|
|
(orhc-bibtex-candidates))
|
|
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
|
|
(ivy--reset-state ivy-last)))
|
|
(define-key map (kbd "C-<return>")
|
|
(lambda ()
|
|
"Apply action and move to next/previous candidate."
|
|
(interactive)
|
|
(ivy-call)
|
|
(ivy-next-line)))
|
|
;; (define-key ivy-minibuffer-map (kbd "M-<return>")
|
|
;; (lambda ()
|
|
;; "Apply default action to all marked candidates."
|
|
;; (interactive)
|
|
;; (mapc (ivy--get-action ivy-last)
|
|
;; org-ref-ivy-cite-marked-candidates)
|
|
;; (ivy-exit-with-action (function (lambda (_) nil)))))
|
|
map)
|
|
"A key map for `org-ref-ivy-insert-cite-link'.")
|
|
|
|
|
|
(ivy-set-actions
|
|
'org-ref-ivy-insert-cite-link
|
|
org-ref-ivy-cite-actions)
|
|
|
|
|
|
(defun org-ref-ivy-insert-cite-link (&optional arg)
|
|
"ivy function for interacting with bibtex.
|
|
Uses `org-ref-find-bibliography' for bibtex sources, unless a
|
|
prefix ARG is used, which uses `org-ref-default-bibliography'."
|
|
(interactive "P")
|
|
(setq org-ref-bibtex-files (if arg
|
|
org-ref-default-bibliography
|
|
(org-ref-find-bibliography)))
|
|
(setq org-ref-ivy-cite-marked-candidates '())
|
|
|
|
(ivy-read "Open: " (orhc-bibtex-candidates)
|
|
:require-match t
|
|
:keymap org-ref-ivy-cite-keymap
|
|
:re-builder org-ref-ivy-cite-re-builder
|
|
:action 'or-ivy-bibtex-insert-cite
|
|
:caller 'org-ref-ivy-insert-cite-link))
|
|
|
|
|
|
(defun org-ref-ivy-cite-transformer (s)
|
|
"Make entry red if it is marked."
|
|
(let* ((fill-column (frame-width))
|
|
(fill-prefix " ")
|
|
(wrapped-s (with-temp-buffer
|
|
(insert s)
|
|
(fill-paragraph)
|
|
(buffer-string))))
|
|
(if (-contains?
|
|
(if (listp (car org-ref-ivy-cite-marked-candidates))
|
|
(mapcar 'car org-ref-ivy-cite-marked-candidates)
|
|
org-ref-ivy-cite-marked-candidates)
|
|
s)
|
|
(propertize wrapped-s 'face 'font-lock-warning-face)
|
|
(propertize wrapped-s 'face nil))))
|
|
|
|
(ivy-set-display-transformer
|
|
'org-ref-ivy-insert-cite-link
|
|
'org-ref-ivy-cite-transformer )
|
|
|
|
|
|
(defun org-ref-ivy-insert-label-link ()
|
|
"Insert a label with ivy."
|
|
(interactive)
|
|
(insert
|
|
(concat (if (not (looking-back "label:" 6)) "label:" "")
|
|
(ivy-read "label: " (org-ref-get-labels)
|
|
:caller 'org-ref-ivy-insert-label-link))))
|
|
|
|
|
|
(defun org-ref-ivy-insert-ref-link ()
|
|
"Insert a ref link with ivy.
|
|
Use a prefix arg to select the ref type."
|
|
(interactive)
|
|
(let ((label (ivy-read "label: " (org-ref-get-labels) :require-match t
|
|
:caller 'org-ref-ivy-insert-ref-link)))
|
|
(cond
|
|
;; from a colon insert
|
|
((looking-back ":" 1)
|
|
(insert label))
|
|
;; non-default
|
|
(ivy-current-prefix-arg
|
|
(insert
|
|
(ivy-read "type: " org-ref-ref-types)
|
|
":"
|
|
label))
|
|
;; default
|
|
(t
|
|
(insert
|
|
(or (when (looking-at "$") " ") "")
|
|
(concat org-ref-default-ref-type
|
|
":"
|
|
label))))))
|
|
|
|
|
|
(require 'hydra)
|
|
(setq hydra-is-helpful t)
|
|
|
|
(defhydra org-ref-cite-hydra (:color blue)
|
|
"
|
|
_p_: Open pdf _w_: WOS _g_: Google Scholar _K_: Copy citation to clipboard
|
|
_u_: Open url _r_: WOS related _P_: Pubmed _k_: Copy key to clipboard
|
|
_n_: Open notes _c_: WOS citing _C_: Crossref _f_: Copy formatted entry
|
|
_o_: Open entry _e_: Email entry ^ ^ _q_: quit
|
|
_i_: Insert cite _h_: change type
|
|
"
|
|
("o" org-ref-open-citation-at-point nil)
|
|
("p" org-ref-open-pdf-at-point nil)
|
|
("n" org-ref-open-notes-at-point nil)
|
|
("u" org-ref-open-url-at-point nil)
|
|
("w" org-ref-wos-at-point nil)
|
|
("r" org-ref-wos-related-at-point nil)
|
|
("c" org-ref-wos-citing-at-point nil)
|
|
("g" org-ref-google-scholar-at-point nil)
|
|
("P" org-ref-pubmed-at-point nil)
|
|
("C" org-ref-crossref-at-point nil)
|
|
("K" org-ref-copy-entry-as-summary nil)
|
|
("k" (progn
|
|
(kill-new
|
|
(car (org-ref-get-bibtex-key-and-file))))
|
|
nil)
|
|
("f" (kill-new
|
|
(org-ref-format-entry (org-ref-get-bibtex-key-under-cursor)))
|
|
nil)
|
|
|
|
("e" (kill-new (save-excursion
|
|
(org-ref-open-citation-at-point)
|
|
(org-ref-email-bibtex-entry)))
|
|
nil)
|
|
("i" (funcall org-ref-insert-cite-function))
|
|
("h" org-ref-change-cite-type)
|
|
("q" nil))
|
|
|
|
|
|
(defun org-ref-ivy-onclick-actions ()
|
|
"An alternate click function that uses ivy for action selection.
|
|
Each action is taken from `org-ref-ivy-cite-actions'. Each action
|
|
should act on a bibtex entry that matches the key in
|
|
`orhc-bibtex-candidates'. Set `org-ref-cite-onclick-function' to
|
|
this function to use it."
|
|
(interactive)
|
|
(ivy-read
|
|
"action: "
|
|
(cl-loop for i from 0
|
|
for (_ func s) in
|
|
org-ref-ivy-cite-actions
|
|
collect (cons (format "%2s. %s" i s) func))
|
|
:action (lambda (f)
|
|
(let* ((key (car (org-ref-get-bibtex-key-and-file)))
|
|
(entry (cdr (elt (orhc-bibtex-candidates)
|
|
(-elem-index
|
|
key
|
|
(cl-loop for entry in (orhc-bibtex-candidates)
|
|
collect (cdr (assoc "=key=" entry ))))))))
|
|
(funcall f entry)))))
|
|
|
|
|
|
;; * org-ref-ivy-set-keywords
|
|
(defvar org-ref-ivy-set-keywords-keymap
|
|
(let ((map (make-sparse-keymap)))
|
|
(define-key map (kbd "C-<SPC>") 'org-ref-ivy-mark-candidate)
|
|
(define-key map (kbd "C-,") 'org-ref-ivy-show-marked-candidates)
|
|
(define-key map (kbd "C-.") 'org-ref-ivy-show-all)
|
|
(define-key map (kbd "C-<up>") 'org-ref-ivy-move-up)
|
|
(define-key map (kbd "C-<down>") 'org-ref-ivy-move-down)
|
|
map)
|
|
"A key map for `org-ref-ivy-set-keywords'.")
|
|
|
|
(defun org-ref-ivy-set-keywords ()
|
|
"Add keywords to bibtex entries selected by org-ref-ivy."
|
|
(interactive)
|
|
(setq org-ref-ivy-cite-marked-candidates '())
|
|
(ivy-read "Keywords: " (org-ref-bibtex-keywords)
|
|
:keymap org-ref-ivy-set-keywords-keymap
|
|
:caller 'org-ref-ivy-set-keywords
|
|
:action (lambda (key)
|
|
(org-ref-set-bibtex-keywords
|
|
(mapconcat
|
|
'identity
|
|
(or org-ref-ivy-cite-marked-candidates (list key))
|
|
", ")))))
|
|
|
|
(ivy-set-display-transformer
|
|
'org-ref-ivy-set-keywords
|
|
'org-ref-ivy-cite-transformer)
|
|
|
|
(provide 'org-ref-ivy-cite)
|
|
;;; org-ref-ivy-cite.el ends here
|