This package turns bibtex-completion functions into completing-read-based Emacs commands. When used with selectrum, embark, and marginalia, it provides similar functionality to helm-bibtex and ivy-bibtex: quick filtering and selecting of bibliographic entries from the minibuffer, and the option to run different commands against them.
Here’s a screenshot with selectrum and embark.
And another with vertico:
Bibtex-actions is available for installation from MELPA.
To setup bibtex-actions using use-package
, you can simply do:
(use-package bibtex-actions
:bind (("C-c b" . bibtex-actions-insert-citation)
:map minibuffer-local-map
("M-b" . bibtex-actions-insert-preset))
:after embark
:config
;; Make the 'bibtex-actions' bindings available from `embark-act'.
(add-to-list 'embark-keymap-alist '(bibtex . bibtex-actions-map))
:custom
(bibtex-completion-bibliography '("~/bib/references.bib")))
Since most of the command logic resides in bibtex-completion, that is where to look for different configuration options.
The only thing, however, that you must configure is where to find your bib file(s).
(setq bibtex-completion-bibliography "~/bib/references.bib")
Bibtex-actions
uses the built-in completing-read-multiple
, and so any vertical completion system that supports that should work.
In particular, all of these work well:
- selectrum (the most full-featured)
- vertico (new, with a more minimal feature set)
- icomplete-vertical (for those that love icomplete, but want a vertical UI)
bibtex-actions
to work correctly, and as you may have come to expect in helm-bibtex
or ivy-bibtex
, you need to install and configure either prescient
or orderless
.
You can read more about this at the selectrum README, but here’s an example using orderless
with its style dispatchers.
In this case, that search string is searching for all items without either a PDF or note associated with them, and then includes a “the” initialism, and a flex search on “abc”.
The repository test
directory also includes a script you can use to run this and associated packages in the emacs -Q
sandbox.
To do that, simply run ./run.sh
from the test
directory.
By default, this will use selectrum as the completion system.
If you would like to try vertico instead, just do M-x vertico-mode
.
There are three sections of the browsing UI.
- The prefix, exploiting the affixation feature only available starting with Emacs 28, and holding the symbols to indicate the presence of PDFs or notes associated with the entries.
- The main display, which by default shows author, title, and date.
- The suffix, which by default shows citekey, reference type, and (if present) tags or keywords.
You can search against all of the above content.
For the prefix, you can filter for associated PDFs or notes using has:pdf
or has:note
respectively (and at least with my setup, even the :p
or :n
shorthand).
You can configure both of the last two just as you do with bibtex-completion.
(setq bibtex-actions-template '((t . " ${title:*}")))
(setq bibtex-actions-template-suffix '((t . " ${=key=:15}")))
Note: the asterisk signals to the formatter to use available space for the column. You should only use this on one field total, across the two templates, for the formatting to work correctly.
By default, this UI is plain text, but you can configure it to use icons instead.
Here’s how to configure it to use all-the-icons
:
(setq bibtex-actions-symbols
`((pdf . (,(all-the-icons-icon-for-file "foo.pdf" :face 'all-the-icons-dred) .
,(all-the-icons-icon-for-file "foo.pdf" :face 'bibtex-actions-icon-dim)))
(note . (,(all-the-icons-icon-for-file "foo.txt") .
,(all-the-icons-icon-for-file "foo.txt" :face 'bibtex-actions-icon-dim)))
(link .
(,(all-the-icons-faicon "external-link-square" :v-adjust 0.02 :face 'all-the-icons-dpurple) .
,(all-the-icons-faicon "external-link-square" :v-adjust 0.02 :face 'bibtex-actions-icon-dim)))))
;; Here we define a face to dim non 'active' icons, but preserve alignment
(defface bibtex-actions-icon-dim
'((((background dark)) :foreground "#282c34")
(((background light)) :foreground "#fafafa"))
"Face for obscuring/dimming icons"
:group 'all-the-icons-faces)
Bibtex-actions
has functionality similar to the predefined search functionality in helm-bibtex
and ivy-bibtex
, but with a different implementation.
Rather than create a new command with the search terms as argument, you just set the bibtex-actions-presets
variable, and add the strings you want to access:
(setq bibtex-actions-presets '("one search string" "another search string"))
You then have two ways to access these strings from the completion prompt:
- by using
M-n
from the prompt, which will cycle through the strings - by calling
bibtex-actions-insert-preset
with a keybinding, and then selecting the string
Bibtex-actions
also preserves the history of your selections (see caveat below about multiple candidate selection though), which are also accessible in your completion UI, but by using M-p
.
You can save this history across sessions by adding bibtex-actions-history
to savehist-additional-variables
.
By default, bibtex-actions
will, assuming you are using orderless
or prescient
to filter candidates, pre-filter entries for the following commands.
bibtex-actions-open
: pre-narrows the list to those which have associated pdf or linksbibtex-actions-open-link
: pre-narrows the list to those which have associated linksbibtex-actions-open-pdf
: -pre-narrows the list to those which have associated pdf(s)
That is, upon running the command, an initial-input
value will be inserted to narrow the results.
You can also delete that if you prefer to see the full list of candidates.
By default, pre-filtering of bibtex-actions-open-notes
is off, because the command by default will create a new note if none is available, and therefore it makes sense to have access to your full library.
But you can customize this to pre-filter if you prefer.
If you want to modify those values, or remove them entirely, you can set bibtex-actions-initial-inputs
like so; in this case turning off pre-filtering for bibtex-actions-open-pdf
:
(setq bibtex-actions-initial-inputs
'((pdf . nil)
(note . nil)
(link . "has:link")
(source . "has:link\\|has:pdf"))
Bibtex-actions uses a cache to speed up library display. This is great for performance, but means the data can become stale if you modify it.
The bibtex-actions-refresh
command will reload the cache, and you can call this manually.
You can also call any of the bibtex-actions
commands with a prefix argument: C-u M-x bibtex-actions-insert-key
.
Finally, another option is to add bibtex-completion
-style proactive loading externally by using filenotify
something like this:
;; Of course, you could also use `bibtex-completion-bibliography` here, but would need
;; to adapt this if you specify multiple files.
(file-notify-add-watch
"/path/to/file.bib" '(change) 'bibtex-actions-refresh)
You can also extend this to do the same thing for your PDF files, or notes:
(file-notify-add-watch
bibtex-completion-library-path '(change) 'bibtex-actions-refresh)
(file-notify-add-watch
bibtex-completion-note-path '(change) 'bibtex-actions-refresh)
For additional configuration options on this, see the wiki.
You have a few different ways to interact with these commands.
Simply do M-x
and select the command that you want, enter the terms to find the item you are looking for, and hit return.
This runs the default action: the command you invoked.
Here’s the view, using marginalia for annotations.
A note on multiple candidate selection:
These commands do allow you to select multiple items, with two caveats:
- For this to work correctly, you must use the ampersand (
&
) ascrm-separator
to separate the candidates. - We use long candidate strings, so if you use a completion system that requires you to
TAB
-complete, the experience is less-than-ideal.
If while browsing you instead would rather edit that record, and you have embark installed and configured, this is where embark-act
comes in.
Simply input the keybinding for embark-act
(in my case C-o
), and select the alternate action.
A final option, that can be useful: run embark-collect-snapshot
(S
) from embark-act
.
This will select the candidate subset, and open it in a separate buffer.
From there, you can run the same options discussed above using embark-act
(which is also bound to a
in the collect buffer).
So, for example, say you are working on a paper. You hold the complete super-set of items you are interested in citing at some point in that buffer. From there, you can run different actions on the candidates at will, rather than search individually for each item you want to cite.
This is inspired by helm-bibtex
and ivy-bibtex
, but is based on completing-read
.
In comparison:
- like
helm-bibtex
, but unlikeivy-bibtex
,bibtex-actions
has support for multi-selection of candidates helm-bibtex
andivy-bibtex
provide a single command, and the actions accessed from there;bibtex-actions
provides all of its actions as standard commands, available fromM-x
, without a single entry point.bibtex-actions
is based oncompleting-read-multiple
, with a single dependency, and works with different completion systems (though in practice is best supported inselectrum
) and supporting packages that arecompleting-read
compliant;helm-bibtex
andivy-bibtex
are based onhelm
andivy
respectively.
The ideas in this project were initially worked out in a conversation with Maxime Tréca and Daniel Mendler. Daniel, author of consult and marginalia, helped us understand the possibilities of the new suite of completing-read packages, while Maxime came up with an initial prototype.
This code takes those ideas and re-implements them to fill out the feature set, and also optimize the code clarity and performance.
Along the way, Clemens Radermacher and Omar Antolín helped with some of the intricacies of completing-read and elisp.
And, of course, thanks to Titus von der Malburg for creating and maintaining bibtex-completion
and helm-bibtex
and ivy-bibtex
.