Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display local and global bibliographies simultaneously #272

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ericdanan
Copy link
Contributor

This makes the helm-bibtex and ivy-bibtex commands show both local and global bibliography entries simultaneously. Commands helm-bibtex-with-global-bibliography, helm-bibtex-with-local-bibliography, and similarly for ivy-bibtex, show only the global or local entries, respectively. If a file is both in the local and global bibliographies, it is considered a global bibliography file only.

In helm-bibtex, the local and global entries are shown in separate sources. In ivy-bibtex, a different face is used for local entries (since ivy does not display sources separately). This face is customizable through the variable ivy-bibtex-local-bibliography-face.

Also, a new variable bibtex-completion-reverse-order allows to customize whether the order of files and/or entries are reversed in the list of candidates (the default behavior is unchanged: entries are
reversed but not files). Finally, ivy-bibtex accepts an additional argument input as is already the case for helm-bibtex.

The commit message explains in more details how this is implemented.

Some action functions related to pdf or notes files may need some more work. Imagine for instance that a user edits notes for a local entry that is not in the global bibliography. Currently that would create a notes files for this entry, which perhaps not desirable. Several options to prevent this:

  • Disable this action for local entries
  • Only create / open the notes file if there is a global entry with the same key
  • Be more cautious and only create / open the file if the global entry also has the same title

Similarly for bibtex-completion-add-pdf-to-library. Perhaps as well bibtex-completion-open-pdf and bibtex-completion-add-PDF-attachment. Please let me know what you think, If you'd like to completely disable the notes/pdf related actions for local entries, a possibility would be to not look for pdf and notes at all when these files are parsed.

Also the readme would need to be updated.

This makes the helm-bibtex and ivy-bibtex commands show both local and
global bibliography entries simultaneously. Commands
helm-bibtex-with-global-bibliography,
helm-bibtex-with-local-bibliography, and similarly for ivy-bibtex,
show only the global or local entries, respectively. If a file is both
in the local and global bibliographies, it is considered a global
bibliography file only.

In helm-bibtex, the local and global entries are shown in separate
sources. In ivy-bibtex, a different face is used for local
entries (since ivy does not display sources separately). This face is
customizable through the variable ivy-bibtex-local-bibliography-face.

Also, a new variable bibtex-completion-reverse-order allows to
customize whether the order of files and/or entries are reversed in
the list of candidates (the default behavior is unchanged: entries are
reversed but not files). Finally, ivy-bibtex accepts an additional
argument input as is already the case for helm-bibtex.

The simultaneous display of local and global entries is implemented as
follows. The optional argument local-bib of helm-bibtex and ivy-bibtex
is now more generallly named scope and be either 'global or 'local to
show only the global or local entries, respectively, or nil to show
both.

This scope argument is first passed to the function
bibtex-completion-init, which initializes the newly introduced variable
bibtex-completion-bibliography-internal accordingly: it is a cons
whose car and cdr are the the global and local bibliiography
bibliographies currently in use. If scope is nil, the car of this cons
is the value of bibtex-completion-bibliography and its cdr is the list
returned by bibtex-completion-find-local-bibliography from which the
files in bibtex-completion-bibliography are removed. If scope is
'global or 'local then the cdr or car of this cons is nil,
respectively.

Then bibtex-completion-candidates parses the
bibliography as needed and now returns a cons of two lists of entries,
one corresponding to the car and one to the cdr of
bibtex-completion-bibliography-internal. These two lists are used as
candidates list in the global and local sources that helm-bibtex now
has. Then when the selected candidates or the set of marked candidates
is passed to an action function by helm-bibtex, a property scope is
added to the key strings, with value 'global or 'global depending on
the source. This is done by modifying the macro
helm-bibtex-helmify-action.

For ivy-bibtex we need to append the two lists of candidates, but the
number of local candidates is first recorded. This allows to determine
if a given candidate is local or global. The function
ivy-bibtex-display-transformer uses this to fontify the local
candidates, and the macro ivy-bibtex-ivify-action is also modified to
propertize the key string passed to the action functions with the
scope property (ivy does not support marking several candidates).

Finally, the function bibtex-completion-get-entry1 is modified to read
the scope property of the key string and get the entry from the
corresponding bibliography. This is sufficient to make most action
functions able to distinguish between local and global bibliography
entries. The only exception is the function
bibtex-completion-show-entry, which is modified directly. Other
actions, such as bibtex-completion-insert-citation, simply ignore
the scope property since they don't need to make
this distinction.
@tmalsburg
Copy link
Owner

Hi Eric, thanks for this fantastic PR and sorry for the silence. My wife and I had a baby recently and it's become difficult to find time for side projects. This looks really interesting but before I comment on some of the technical details, could you please explain a bit which problem this PR is addressing? I realize that this may be obvious for users of both local and global bibliographies, but I'm using just one global bibliography for everything.

@ericdanan
Copy link
Contributor Author

I completely understand, congratulations!

The local bibliography is typically made of the bibtex file(s) associated with a latex document. My main use case is when I'm working with coauthors on an paper and each of us adds entries (possibly copied from their global bibliography) to the paper's local bibliography.

Currently I can call ivy-bibtex / ivy-bibtex-with-local-bibliography to open the global / local bibliography, but it would be more convenient to open both at once (you also made a comment in this sense). This is what this PR implements.

Please let me know if you need any further clarification.

@tmalsburg
Copy link
Owner

Thanks, I was just wondering which other future feature requests this might entail. For instance, I imagine that someone using local and global bibliographies might also want to have actions for moving entries from one to the other. E.g. add an entry to the shared (local) bibliography or import a co-author's entry to the global bibliography. One big question for me is whether we should go in this direction. So far helm/ivy-bibtex were just for reading bibliographies and not for modifying them. My own philosophy is that bibtex-files should be edited by hand. After all, Emacs is a terrific text editor and it already has multiple facilities for maintaining BibTeX files. But more importantly I think that helm and ivy have terrible UIs for implementing a full-blown bibliography manager. Everything would basically have to be an action and selecting the appropriate action becomes tedious as their number increases.

Anyway, coming back to the specific issue. I think showing entries from local and global bibliographies is a useful addition, which I might end up using as well. However, looking at your PR I realize that my data structures are woefully inadequate for this because they do not keep track of where an entry is coming from. If there is an entry with BibTeX key XYZ in both the local and the global bibliography, an action has no way of knowing which of the two it is supposed to act on. It's really starting to show that helm-bibtex started as a quick hack and that I didn't think ahead when I laid its foundations.

I haven't tried your code but I looks as if it would work flawlessly (within the limits you mention). So we could merge this as is I guess. I hesitate, though, because I worry that the code base is becoming harder and harder to understand for potential contributors and also for myself. Do you think that it would be worth rethinking the data structures such that they allow for a more complete and more elegant solution? For instance, would it make sense to introduce an internal identifier for entries that is composed of BibTeX key plus path of source file? This wouldn't magically solve all our problems (e.g. those related to notes) but it might put us in a better position for solving these issuesl. I would be interested to hear your thoughts on this.

@ericdanan
Copy link
Contributor Author

Re future feature requests, yes I guess an additional action for moving entries would be a natural one, but I agree with you I would better do this by hand. What I've done is simply add an action to copy the bibtex entry and I think having this could safely be added to the bibtex-completion code. Then having both the local and global bibliographies displayed simultaneously makes things convenient enough: I can apply this action without leaving the session and then choose a (local or global) bibliography from the fallback actions and paste the copied entry there.

Re data structure, I think I remember having asked once about the possibility to add the source file path as an additional field in the entry alist (or an alternative could be as you suggest to concatenate it with the entry key), and that your answer was that the amount of stored information would better be kept to a minimum so as not to increasing loading time for large bibliographies like crypto.bib. So in this PR I went for another strategy: wait until entry keys are passed to an action function and add the string property 'local or 'global to these keys only. So actions are able to distinguish between an local and a global entry with the same key, and there should be no impact on performance for large bibliographies (the commit message explains how all this is done but do let me know if it is not clear). My impression is that bibtex-completion generally tries to optimize performance for large bibliographies and that this can make the code more complicated than systematically caching a priori all the information that might be needed at some point, so the best approach should depend on your trade-off between performance and simplicity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants