Skip to content

Commit

Permalink
Merge pull request #388 from franburstall/ivy-mark-cands
Browse files Browse the repository at this point in the history
Ivy mark cands
  • Loading branch information
tmalsburg authored Sep 8, 2021
2 parents 12079bb + 6414bc2 commit b856620
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 32 deletions.
29 changes: 21 additions & 8 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Ivy-bibtex: [[http://melpa.org/#/ivy-bibtex][http://melpa.org/packages/ivy-bibte
Helm-bibtex and ivy-bibtex allow you to search and manage your BibTeX bibliography. They both share the same generic backend, bibtex-completion, but one uses the Helm completion framework and the other Ivy as a front-end.

* News
- 2021-08-25: It is now possible to mark and act on multiple entries in ~ivy-bitex~. See [[#apply-actions-to-multiple-entries][here]].
- 2021-07-25: ~helm-bibtex-with-local-bibliography~ and ~ivy-bibtex-with-local-bibliography~ now also use locally and globally defined bibliographies in org files. These are bibliographies specified using the new ~#+BIBLIOGRAPHY:~ key word and those in the variable ~org-cite-global-bibliography~.
- 2021-07-18: Added a citation function for Org’s new citation system: ~bibtex-completion-format-citation-org-cite~ (for use in configuration variable ~bibtex-completion-format-citation-functions~)
- 2021-04-12: Added a section below explaining how the bibliography can be automatically reloaded when PDFs and notes are added. See [[https://github.com/tmalsburg/helm-bibtex#refresh-bibliography-when-new-pdfs-and-notes-are-added][here]].
Expand Down Expand Up @@ -406,27 +407,35 @@ If the last, numerical argument in ~helm-add-action-to-source~ is omitted, the n
(helm-add-action-to-source "Insert BibTeX key" 'bibtex-completion-insert-key helm-source-bibtex 0)
#+END_SRC

*Ivy-bibtex*: The default action and the additional available actions are set separately. The default action is controlled by the variable ~ivy-bibtex-default-action~. For example, the following code changes the default action to "insert BibTeX key":
*Ivy-bibtex*: The default action and the additional available actions are set separately. The default action is controlled by the variables ~ivy-bibtex-default-action~ and ~ivy-bibtex-default-multi-action~, with the latter intended for lists of marked entries (see [[#apply-actions-to-multiple-entries][Apply actions to multiple entries]]). For example, the following code changes the default action to "insert BibTeX key":

#+BEGIN_SRC emacs-lisp
(setq ivy-bibtex-default-action 'ivy-bibtex-insert-key)
#+END_SRC

In the same way, the following code sets the default action for lists of marked entries to "insert BibTeX key" which will insert a nice comma-separated list of keys:

#+begin_src emacs-lisp
(setq ivy-bibtex-default-multi-action 'ivy-bibtex-insert-key)
#+end_src

The additional actions are set by passing the desired action list to the command ~ivy-set-actions~. For instance, the following codes keeps only two available actions in addition to the default one:

#+BEGIN_SRC emacs-lisp
(ivy-set-actions
'ivy-bibtex
'(("p" ivy-bibtex-open-any "Open PDF, URL, or DOI")
("e" ivy-bibtex-edit-notes "Edit notes")))
'(("p" ivy-bibtex-open-any "Open PDF, URL, or DOI" ivy-bibtex-open-any)
("e" ivy-bibtex-edit-notes "Edit notes" ivy-bibtex-edit-notes)))
#+END_SRC

The letters ~p~ and ~e~ are the key bindings for the two actions in the action menu. The key binding ~o~ is reserved for the default action. If you only want to add new actions at the end of the action list, you can alternatively use the command ~ivy-add-actions~. For instance, the following adds a new action ~helm-bibtex-open-annotated-pdf~ (see [[#annotated][above]]) at the end of the action list:
The letters ~p~ and ~e~ are the key bindings for the two actions in the action menu. The key binding ~o~ is reserved for the default action. The second appearance of the action in this code alerts ~ivy~ that the action can handle lists of marked entries. It can safely be omitted if the right thing to do is simply apply the action to each entry in turn.

If you only want to add new actions at the end of the action list, you can alternatively use the command ~ivy-add-actions~. For instance, the following adds a new action ~ivy-bibtex-open-annotated-pdf~ (see [[#annotated][above]]) at the end of the action list:

#+BEGIN_SRC emacs-lisp
(ivy-add-actions
'ivy-bibtex
'(("P" ivy-bibtex-open-annotated-pdf "Open annotated PDF (if present)")))
'(("P" ivy-bibtex-open-annotated-pdf "Open annotated PDF (if present)" ivy-bibtex-open-annotated-pdf)))
#+END_SRC

** Create new actions
Expand Down Expand Up @@ -591,16 +600,20 @@ The available actions are:
*Ivy-bibtex*: Select an entry and press ~<return>~ to execute the default action. Alternatively, press ~M-o~ to see a list of all available actions, execute one of them and exit ivy-bibtex.

** Apply actions to multiple entries
:PROPERTIES:
:CUSTOM_ID: apply-actions-to-multiple-entries
:END:


*Helm-bibtex*: Start helm-bibtex, enter the search expression, move the cursor to the matching entry and enter ~C-<space>~ (control + space bar) to mark this entry, optionally change your search expression, mark more entries, finally press ~<return>~ or ~<tab>~ to execute an action for all selected entries at once and exit helm-bibtex.

*Ivy-bibtex*: Start ivy-bibtex, enter the search expression, move the cursor to the matching entry and press ~M-<return>~ instead of ~<return>~ or ~C-M-o~ instead of ~M-o~ to execute an action for this entry without exiting ivy-bibtex, optionally change your search expression, move the cursor the new matching entry and press ~M-<return>~ or ~C-M-o~ to execute the same (not necessarily the default) or another action for this new entry, and so on, finally press ~<return>~ or ~C-o~ to execute the same or another action and exit ivy-bibtex.
*Ivy-bibtex*: Start ivy-bibtex, enter the search expression, move the cursor to the matching entry and enter ~C-<space>~ (control + space bar) to mark this entry, optionally change your search expression, mark more entries, finally press ~<return>~ to execute the default action on all the selected entries or ~M-o~ to choose another action. Press ~S-<space>~ (shift + space bar) to un-mark a marked entry.

** A colleague asks for copies of your new papers

*Helm-bibtex*: Start an email to your colleague (~C-x m~) and execute ~helm-bibtex~. Search for your new publications and mark them with ~C-<space>~, then press ~<f7>~ to execute the action “Attach PDF to email”. Then ~M-x helm-resume~ (the publications are still marked) and press ~<f6>~ to execute the action “Insert BibTeX entry”. Optionally insert more human readable references using ~M-x helm-resume~ and ~<f4>~ to execute the action “Insert reference”. Send email (~C-c C-c~). Done. This takes less than 10 seconds.

*Ivy-bibtex*: Start an email to your colleague (~C-x m~) and execute ~ivy-bibtex~. Search for your new publications and select the first one, then press ~C-M-o a~ to execute the action “Attach PDF to email”. Then press ~C-M-o b~ to execute the action “Insert BibTeX entry”. Optionally insert a more human readable reference using ~C-M-o r~ to execute the action “Insert reference”. Then select your next publication and again ~C-M-o a~, ~C-M-o b~ and, optionally, ~C-M-o r~. And so on. Send email (~C-c C-c~). Done.
*Ivy-bibtex*: Start an email to your colleague (~C-x m~) and execute ~ivy-bibtex~. Search for your new publications and and mark them with ~C-<space>~, then press ~C-M-o a~ to execute the action “Attach PDF to email” while keeping ivy open. Then press ~M-o b~ to execute the action “Insert BibTeX entry” or insert more human readable references using ~M-o r~ to execute the action “Insert reference”. Send email (~C-c C-c~). Done. This takes less than 10 seconds.

Of course, this assumes that you’re sending email from Emacs, e.g. via [[http://www.djcbsoftware.nl/code/mu/mu4e.html][Mu4e]].

Expand Down Expand Up @@ -646,7 +659,7 @@ Bibtex-completion caches the bibliography to prevent a costly reread when a new

*Helm-bibtex*: Start helm-bibtex and enter search terms. Then select “CrossRef” in the section titled “Fallback options”. (You can use the left and right arrow keys to switch between sections.)

*Ivy-bibtex*: Start ivy-bibtex and enter search terms. Then press ~M-o f~ to see the list of fallback options and and select "CrossRef".
*Ivy-bibtex*: Start ivy-bibtex and enter search terms. Then press ~M-o f~ to see the list of fallback options and select "CrossRef".

This will use [[https://github.com/cpitclaudel/biblio.el][biblio.el]] to search the CrossRef database. In the results list, place the cursor on the entry of interest and hit ~c~ to copy the BibTeX for that entry or ~i~ to insert it at point. Press ~q~ to close the buffer with the search results. See the [[https://github.com/cpitclaudel/biblio.el/blob/master/README.md][documentation of biblio.el]] for details.

Expand Down
71 changes: 47 additions & 24 deletions ivy-bibtex.el
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
;; Maintainer: Titus von der Malsburg <[email protected]>
;; URL: https://github.com/tmalsburg/helm-bibtex
;; Version: 1.0.1
;; Package-Requires: ((bibtex-completion "1.0.0") (swiper "0.7.0") (cl-lib "0.5"))
;; Package-Requires: ((bibtex-completion "1.0.0") (ivy "0.13.0") (cl-lib "0.5"))

;; 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
Expand Down Expand Up @@ -86,19 +86,42 @@
"The default action for the `ivy-bibtex` command."
:group 'bibtex-completion
:type 'function)

(defvar ivy-bibtex-default-multi-action 'ivy-bibtex-open-any
"The default multi-action for the `ivy-bibtex` command.")

(defvar ivy-bibtex-use-extra-keymap t
"Non-nil if `ivy-bibtex' has keys for marking candidates.")

(defvar ivy-bibtex-extra-keymap
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-SPC") 'ivy-mark)
(define-key map (kbd "S-SPC") 'ivy-unmark)
map)
"Optional extra keymap for `ivy-bibtex'.")

(defun ivy-bibtex-display-transformer (candidate)
"Prepare bib entry CANDIDATE for display."
(let* ((width (1- (frame-width)))
(idx (get-text-property 0 'idx candidate))
(entry (cdr (nth idx (ivy-state-collection ivy-last)))))
(bibtex-completion-format-entry entry width)))
(let* ((width (- (frame-width) 2))
(idx (get-text-property 1 'idx candidate))
(entry (cdr (nth idx (ivy-state-collection ivy-last)))))
(s-concat (if (s-starts-with-p ivy-mark-prefix candidate) ivy-mark-prefix " ")
(bibtex-completion-format-entry entry width))))

(defmacro ivy-bibtex-ivify-action (action name)
"Wraps the function ACTION in another function named NAME which extracts the key from the candidate selected in ivy and passes it to ACTION."
`(defun ,name (candidate)
(let ((key (cdr (assoc "=key=" (cdr candidate)))))
(,action (list key)))))
"Wraps the function ACTION in two other functions named NAME and NAME-multi.
The first extracts the key from the candidate selected in ivy and
passes it to ACTION.
The second extracts the list of keys in mark candidates selected
in ivy and passes it to ACTION."
`(defun ,name (candidates)
,(format "Ivy wrapper for `%s' applied to one or more CANDIDATES." action)
(let ((keys (if (consp (car candidates))
(--map (cdr (assoc "=key=" (cdr it))) candidates)
(list (cdr (assoc "=key=" (cdr candidates)))))))
(,action keys))))

(ivy-bibtex-ivify-action bibtex-completion-open-any ivy-bibtex-open-any)
(ivy-bibtex-ivify-action bibtex-completion-open-pdf ivy-bibtex-open-pdf)
Expand All @@ -122,7 +145,7 @@ This is meant to be used as an action in `ivy-read`, with
:action (lambda (candidate) (bibtex-completion-fallback-action (cdr candidate) search-expression))))

(defvar ivy-bibtex-history nil
"Search history for `ivy-bibtex'")
"Search history for `ivy-bibtex'.")

;;;###autoload
(defun ivy-bibtex (&optional arg local-bib)
Expand Down Expand Up @@ -150,7 +173,9 @@ from the local bibliography. This is set internally by
:preselect preselect
:caller 'ivy-bibtex
:history 'ivy-bibtex-history
:action ivy-bibtex-default-action)))
:action ivy-bibtex-default-action
:multi-action ivy-bibtex-default-multi-action
:keymap (when ivy-bibtex-use-extra-keymap ivy-bibtex-extra-keymap))))

;;;###autoload
(defun ivy-bibtex-with-local-bibliography (&optional arg)
Expand All @@ -174,9 +199,7 @@ reread."
(cl-letf* ((candidates (bibtex-completion-candidates))
((symbol-function 'bibtex-completion-candidates)
(lambda ()
(seq-filter
(lambda (candidate) (assoc "=has-note=" candidate))
candidates))))
(--filter (assoc "=has-note=" it) candidates))))
(ivy-bibtex arg)))

(ivy-set-display-transformer
Expand All @@ -185,16 +208,16 @@ reread."

(ivy-set-actions
'ivy-bibtex
'(("p" ivy-bibtex-open-pdf "Open PDF file (if present)")
("u" ivy-bibtex-open-url-or-doi "Open URL or DOI in browser")
("c" ivy-bibtex-insert-citation "Insert citation")
("r" ivy-bibtex-insert-reference "Insert reference")
("k" ivy-bibtex-insert-key "Insert BibTeX key")
("b" ivy-bibtex-insert-bibtex "Insert BibTeX entry")
("a" ivy-bibtex-add-PDF-attachment "Attach PDF to email")
("e" ivy-bibtex-edit-notes "Edit notes")
("s" ivy-bibtex-show-entry "Show entry")
("l" ivy-bibtex-add-pdf-to-library "Add PDF to library")
'(("p" ivy-bibtex-open-pdf "Open PDF file (if present)" ivy-bibtex-open-pdf)
("u" ivy-bibtex-open-url-or-doi "Open URL or DOI in browser" ivy-bibtex-open-url-or-doi)
("c" ivy-bibtex-insert-citation "Insert citation" ivy-bibtex-insert-citation)
("r" ivy-bibtex-insert-reference "Insert reference" ivy-bibtex-insert-reference)
("k" ivy-bibtex-insert-key "Insert BibTeX key" ivy-bibtex-insert-key)
("b" ivy-bibtex-insert-bibtex "Insert BibTeX entry" ivy-bibtex-insert-bibtex)
("a" ivy-bibtex-add-PDF-attachment "Attach PDF to email" ivy-bibtex-add-PDF-attachment)
("e" ivy-bibtex-edit-notes "Edit notes" ivy-bibtex-edit-notes)
("s" ivy-bibtex-show-entry "Show entry" ivy-bibtex-show-entry)
("l" ivy-bibtex-add-pdf-to-library "Add PDF to library" ivy-bibtex-add-pdf-to-library)
("f" (lambda (_candidate) (ivy-bibtex-fallback ivy-text)) "Fallback options")))

(provide 'ivy-bibtex)
Expand Down

0 comments on commit b856620

Please sign in to comment.