Skip to content
forked from emacs-citar/citar

A package to quickly find and act on BibTeX, BibLaTeX and CSL JSON entries using default Emacs completion; especially Selectrum/Vertico with Consult and Embark.

License

Notifications You must be signed in to change notification settings

tmalsburg/citar

 
 

Repository files navigation

https://melpa.org/packages/citar-badge.svg

Citar

Features

Note: this package was formerly called “bibtex-actions.”

This package provides a completing-read front-end to browse and act on BibTeX, BibLaTeX, and CSL JSON bibliographic data, and LaTeX, markdown, and org-cite editing support.

When used with vertico (or 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.

With embark, it also makes available at-point actions in org-mode citations.

Here’s a screenshot with vertico, embark. and consult-completing-read-multiple.

images/vertico.png

Installation

citar is available for installation from MELPA.

In addition, the following packages are strongly recommended for the best experience.

  1. Vertico or Selectrum (completion interface)
  2. Orderless (completion style)
  3. Embark (contextual actions)
  4. Marginalia (annotations, and also candidate classification for Embark)
  5. Consult (enhanced interface for multiple candidate selection)

Configuration

Basic

This is the minimal configuration, and will work with any completing-read compliant vertical completion UI, like Vertico, Selectrum, or the built-in icomplete-vertical, with actions available via M-x commands.

(use-package citar
  :bind (("C-c b" . citar-insert-citation)
         :map minibuffer-local-map
         ("M-b" . citar-insert-preset))
  :custom
  (citar-bibliography '("~/bib/references.bib"))

Since most of the command logic resides in bibtex-completion, that is where to look for different configuration options.

Embark

Citar will automatically integrate with Embark if it is installed, offering contextual access to actions in the minibuffer and at-point. Some citation commands prompt for multiple citation keys, for which Consult offers an enhanced interface:

;; use consult-completing-read for enhanced interface
(advice-add #'completing-read-multiple :override #'consult-completing-read-multiple)

When using Embark, the Citar actions are generic, and work the same across org, markdown, and latex modes.

Org-Cite

images/org-cite-embark-point.png

If you use Org-Mode, this is the best option. Use the basic configuration above, and in addition, configure Org-Cite to use Citar:

;; Set bibliography paths so they are the same.
(defvar my/bibs '("~/bib/references.bib"))

(use-package citar-org
  :no-require
  :bind ; optional
  (:map org-mode-map
        ("C-c b" . #'org-cite-insert)) ; Also bound to C-c C-x C-@
  :custom
  (org-cite-global-bibliography my/bibs)
  (org-cite-insert-processor 'citar)
  (org-cite-follow-processor 'citar)
  (org-cite-activate-processor 'citar))

You can insert citations with the org-cite-insert command, which is bound to C-c C-x C-@ in Org-Mode buffers. The optional :bind command above also gives it the shorter C-c b binding.

If you prefer to have the Embark menu open with org-open-at-point, you should set this variable.

(setq citar-at-point-function 'embark-act)

You can invoke both embark-act and embark-dwim, however, independently of org-at-point, and in other modes such as latex-mode.

Rich UI

There are three sections of the browsing UI.

  1. 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.
  2. The main display, which by default shows author, title, and date.
  3. 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).

images/ui-segments.png

Templates

The citar-templates variable configures formatting for these sections, as well as the default note function. Here’s the defaults:

(setq citar-templates
      '((main . "${author editor:30}     ${date year issued:4}     ${title:48}")
        (suffix . "          ${=key= id:15}    ${=type=:12}    ${tags keywords:*}")
        (note . "#+title: Notes on ${author editor}, ${title}")))

Note:

  1. You may include multiple variables in a field; the formatter will print the first one it finds.
  2. If you plan to use CSL JSON at all, you can and should include CSL JSON variables names where appropriate as such options. The default main template dates field demonstrates this.
  3. The asterisk signals to the formatter to use available space for the column.
  4. The note template does not take widths, as formatting is inline there rather than columnar.

Icons

By default, this UI is plain text, but you can configure it to use icons instead.

images/rich-ui-icons.png

Here’s how to configure it to use all-the-icons:

(setq citar-symbols
  `((file . (,(all-the-icons-icon-for-file "foo.pdf" :face 'all-the-icons-dred) .
            ,(all-the-icons-icon-for-file "foo.pdf" :face 'citar-icon-dim)))
    (note . (,(all-the-icons-icon-for-file "foo.txt") .
            ,(all-the-icons-icon-for-file "foo.txt" :face 'citar-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 'citar-icon-dim)))))
;; Here we define a face to dim non 'active' icons, but preserve alignment
(defface citar-icon-dim
    '((((background dark)) :foreground "#282c34")
     (((background light)) :foreground "#fafafa"))
     "Face for obscuring/dimming icons"
     :group 'all-the-icons-faces)

Test Script

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.

History and predefined searches

citar 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 citar-presets variable, and add the strings you want to access:

(setq citar-presets '("one search string" "another search string"))

You then have two ways to access these strings from the completion prompt:

  1. by using M-n from the prompt, which will cycle through the strings
  2. by calling citar-insert-preset with a keybinding, and then selecting the string

citar 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 citar-history to savehist-additional-variables.

Refreshing the library display

citar uses two caches to speed up library display; one for the global bibliography, and another for local files specific to a buffer. This is great for performance, but means the data can become stale if you modify it.

The citar-refresh command will reload the caches, and you can call this manually. You can also call any of the citar commands with a prefix argument: C-u M-x citar-insert-key.

Although not default, citar also provides convenience functions for auto-refreshing cache when bib files change using filenotify. The simplest use of this functionality is

(citar-filenotify-setup '(LaTeX-mode-hook org-mode-hook))

This will add watches for the global bib files and in addition add a hook to LaTeX-mode-hook and org-mode-hook to add watches for local bibliographic files. By default this will invalidate the cache if a bib file changes. If the bib files change rarely, a more suitable option is to refresh the cache. This can be achieved by

(setq citar-filenotify-callback 'refresh-cache)

The behavior can be tweaked more thoroughly by setting citar-filenotify-callback to a function. See its documentation for details. Watches can be also placed on additional files. This is controlled by the variable citar-filenotify-files.

Another option to make the completion interface more seamless is to add a hook which generates the cache after a buffer is opened. This can be done when emacs has been idle (half a second in the example below) with something like this:

(defun gen-bib-cache-idle ()
  "Generate bib item caches with idle timer"
  (run-with-idle-timer 0.5 nil #'citar-refresh))

(add-hook 'LaTeX-mode-hook #'gen-bib-cache-idle)
(add-hook 'org-mode-hook #'gen-bib-cache-idle)

For additional configuration options on this, see the wiki.

Notes

This package provides a citar-file-open-note-function variable, and a simple default function. To replace the default with one from org-roam-bibtex, you can do:

(setq citar-file-open-note-function 'orb-citar-edit-note)

Note, however: if you use that function you need to ensure that the bibtex-completion-bibliography variable is correctly set to the same paths as citar-bibliography.

Beyond the note template, there is citar-file-note-org-include, which defines content to include in the document property drawer, primarily for us with org-roam. Current options are:

org-id
required for org-roam v2 to identify the note document
org-roam-ref
adds the citation key to identify it as a bibliographic note

To set both:

(setq citar-file-note-org-include '(org-id org-roam-ref))

Files, file association and file-field parsing

If you have citar-library-paths set, the relevant open commands will look in those directories for file names of CITEKEY.EXTENSION. They will also parse contents of a file-field. The citar-file-parser-functions variable governs which parsers to use, and there are two included parsers:

  1. The default citar-file-parser-default parser works for simple semi-colon-delimited lists of file paths, as in Zotero.
  2. The citar-file-parser-triplet works for Mendeley and Calibre, which represent files using a format like :/path/file.pdf:PDF.

If you have a mix of entries created with Zotero and Calibre, you can set it like so and it will parse both:

(setq citar-file-parser-functions
  '(citar-file-parser-default
    citar-file-parser-triplet))

The citar-file-extension variable governs which file extensions the open commands will recognize.

The citar-open-library-files command includes an optional file browser, which can be set with the citar-file-open-prompt boolean variable. When used with embark and consult, you will have a range of alternate actions available for the candidates.

images/file-browser-embark.png

Usage

You have a few different ways to use citar.

Org-cite

citar includes org-cite integration in oc-citar, which includes a processor with “insert,” “activate” and “follow” capabilities.

The “insert processor” uses citar-select-refs to browse your library to insert and edit citations and citation references using the org-cite-insert command. The command is context-aware, so depending on where point is in the buffer, will behave differently. For example, if point:

  • precedes the colon, you will be prompted to edit the style
  • is on an existing citation-reference, you will be prompted to replace it
  • follows or precedes a citation-reference, you will be prompted to add a new citation-reference

The “activate processor” runs the list of functions in oc-bibtex-activation-functions, which by default is the basic processor from oc-basic to provide fontification, and also a little function that adds a keymap for editing citations at point. That keymap includes the following bindings that provide additional citation and citation-reference editing options.

keybinding
C-doc-citar-delete-citation
C-koc-citar-kill-citation
S-<left>oc-citar-shift-reference-left
S-<right>oc-citar-shift-reference-right
C-poc-citar-update-pre-suffix
<mouse-1>citar-dwim
<mouse-3>embark-act

The “follow processor” provides at-point functionality accessible via the org-open-at-point command. By default, in org-mode with org-cite support, when point is on a citation or citation-reference, and you invoke org-open-at-point, it will run the default command, which is citar-open. Changing this value to embark-act with embark installed and configured will provide access to the standard citar commands at point.

Org-cite citations include optional “styles” and “variants” to locally modify the citation rendering. To edit these, just make sure point is on the citation prefix before running org-cite-insert, and you will get a list of available styles. That list is based on your configuration; if you have the oc-natbib and oc-csl processors configured, for example, the list will include the styles and variants available in those two processors. The variants included in the bundled processors include the following, with the shortcuts in parentheses:

  • bare (b): without surrounding punctuation
  • caps (c): force initial capitalization
  • full (f): ignore et al shortening for author names

Generally, you shouldn’t need these, but they can be useful in certain circumstances. If an export processor doesn’t support a specific variant for a specific style, it should just fallback to the base style. For example, if you specify text/f, and the export processor you use doesn’t support the f variant there, it should just output as if you specified text.

M-x

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.

images/m-x.png

A note on multiple candidate selection:

These commands do allow you to select multiple items, with two caveats:

  1. For this to work correctly, you must use the ampersand (&) as crm-separator to separate the candidates.
  2. We use long candidate strings, so if you use a completion system that requires you to TAB-complete, the experience is less-than-ideal.

Access an alternate action via embark-act

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.

Use embark-collect-snapshot

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.

Use citar-dwim

M-x citar-dwim will run the default action on citation keys found at point directly. If you have embark installed, you use can embark-dwim instead for the same behavior, and embark-act for additional actions at-point.

If no citation key is found, the minibuffer will open for selection. You can disable this behavior by setting citar-at-point-fallback to nil.

Comparisons

This is inspired by helm-bibtex and ivy-bibtex, but is based on completing-read. In comparison:

  • like helm-bibtex, but unlike ivy-bibtex, citar has support for multi-selection of candidates
  • helm-bibtex and ivy-bibtex provide a single command, and the actions accessed from there; citar provides all of its actions as standard commands, available from M-x, without a single entry point.
  • citar is based on completing-read-multiple, with a single dependency, and works with different completion systems (though in practice is best supported in selectrum) and supporting packages that are completing-read compliant; helm-bibtex and ivy-bibtex are based on helm and ivy respectively.

What about org-ref and org-ref-cite?

The future of the latter package at this point is unclear, though there is some cross-fertilization of ideas and code between this project and that.

The former is an integrated package that supports citations, cross-references, acronyms and glossaries, but notably does not support org-cite; citar will only ever support org-cite, and exclusively focus on citations.

Acknowledgements

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.

About

A package to quickly find and act on BibTeX, BibLaTeX and CSL JSON entries using default Emacs completion; especially Selectrum/Vertico with Consult and Embark.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Emacs Lisp 70.9%
  • TeX 28.9%
  • Shell 0.2%