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

support local bibs #208

Merged
merged 4 commits into from
Aug 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 8 additions & 43 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -222,61 +222,26 @@ You then have two ways to access these strings from the completion prompt:
=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=.

** Pre-filtering entries
:PROPERTIES:
:CUSTOM_ID: prefiltering-entries
:END:

By default, =bibtex-actions= will, assuming you are using =orderless= or =prescient= to filter candidates, pre-filter entries for the following commands.

1. =bibtex-actions-open=: pre-narrows the list to those which have associated pdf or links
2. =bibtex-actions-open-link=: pre-narrows the list to those which have associated links
3. =bibtex-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=:

#+begin_src elisp
(setq bibtex-actions-initial-inputs
'((pdf . nil)
(note . nil)
(link . "has:link")
(source . "has:link\\|has:pdf"))
#+end_src

** Refreshing the library display
:PROPERTIES:
:CUSTOM_ID: refreshing-the-library-display
:END:

Bibtex-actions uses a cache to speed up library display.
=Bibtex-actions= 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 =bibtex-actions-refresh= command will reload the cache, and you can call this manually.
The =bibtex-actions-refresh= command will reload the caches, 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:

#+BEGIN_SRC emacs-lisp
;; 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)
#+END_SRC

You can also extend this to do the same thing for your PDF files, or notes:
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:

#+BEGIN_SRC emacs-lisp
(file-notify-add-watch
bibtex-completion-library-path '(change) 'bibtex-actions-refresh)
(defun gen-bib-cache-idle ()
Copy link
Contributor

@aikrahguzar aikrahguzar Aug 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hook won't help with stale cache, I include it so that the cache is generated when a new buffer is opened making the ui seem more responsive.

For stale cache filenotifyis the solution though it won't work with local cache as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For stale cache filenotifyis the solution though it won't work with local cache as is.

As in, they conflict, or (as I assume) they are complementary? If the latter, I'll add it back and adjust the language.

Copy link
Contributor

@aikrahguzar aikrahguzar Aug 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are complemtary. I think another hook will be needed that adds a watch on the files returned by bibtex-completion-find-local-bibliography to make it work with local cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just use "suggested changes" to suggest the specific line changes then? Just click the left most icon on the toolbar.

Allows me to just click to accept, and then you get credit in the git history.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I adjusted the language, I will have to look into filenotify a bit to write and test the hook for cache update.

"Generate bib item caches with idle timer"
(run-with-idle-timer 0.5 nil #'bibtex-actions-refresh))

(file-notify-add-watch
bibtex-completion-note-path '(change) 'bibtex-actions-refresh)
(add-hook 'LaTeX-mode-hook #'gen-bib-cache-idle)
(add-hook 'org-mode-hook #'gen-bib-cache-idle)
#+END_SRC

For additional configuration options on this, see [[https://github.com/bdarcus/bibtex-actions/wiki/Configuration#automating-path-watches][the wiki]].
Expand Down
47 changes: 39 additions & 8 deletions bibtex-actions.el
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,26 @@ offering the selection candidates"
collect (cdr (or (assoc choice candidates)
(rassoc choice candidates))))))

(defun bibtex-actions--format-candidates ()
"Transform candidates from 'bibtex-completion-candidates'.
(defun bibtex-actions--normalize-paths (file-paths)
"Return a list of FILE-PATHS normalized with truename."
(if (stringp file-paths)
;; If path is a string, return as a list.
(list (file-truename file-paths))
(delete-dups (mapcar (lambda (p) (file-truename p)) file-paths))))

(defun bibtex-actions--local-files-to-cache ()
"The local bibliographic files not included in the global bibliography."
;; We cache these locally to the buffer.
(let* ((local-bib-files
(bibtex-actions--normalize-paths
(bibtex-completion-find-local-bibliography)))
(global-bib-files
(bibtex-actions--normalize-paths
bibtex-completion-bibliography)))
(seq-difference local-bib-files global-bib-files)))
bdarcus marked this conversation as resolved.
Show resolved Hide resolved

(defun bibtex-actions--format-candidates (&optional context)
"Format candidates, with optional hidden CONTEXT metadata.
This both propertizes the candidates for display, and grabs the
key associated with each one."
(let* ((main-template
Expand Down Expand Up @@ -240,7 +258,7 @@ key associated with each one."
;; We display this content already using symbols; here we add back
;; text to allow it to be searched, and citekey to ensure uniqueness
;; of the candidate.
(candidate-hidden (s-join " " (list pdf note link citekey))))
(candidate-hidden (s-join " " (list pdf note link context citekey))))
(cons
;; If we don't trim the trailing whitespace, 'completing-read-multiple' will
;; get confused when there are multiple selected candidates.
Expand Down Expand Up @@ -275,17 +293,24 @@ key associated with each one."
(s-join bibtex-actions-symbol-separator
(list pdf note link))" ") suffix))))

(defvar bibtex-actions--candidates-cache nil
"Store the candidates list.")
(defvar bibtex-actions--candidates-cache 'uninitialized
"Store the global candidates list.")

(defvar-local bibtex-actions--local-candidates-cache 'uninitialized
;; We use defvar-local so can maintain per-buffer candidate caches.
"Store the local (per-buffer) candidates list.")

(defun bibtex-actions--get-candidates (&optional force-rebuild-cache)
"Get the cached candidates.
If the cache is nil, this will load the cache.
If FORCE-REBUILD-CACHE is t, force reloading the cache."
(when (or force-rebuild-cache
(not bibtex-actions--candidates-cache))
(eq 'uninitialized bibtex-actions--candidates-cache)
(eq 'uninitialized bibtex-actions--local-candidates-cache))
(bibtex-actions-refresh force-rebuild-cache))
bibtex-actions--candidates-cache)
(seq-concatenate 'list
bibtex-actions--local-candidates-cache
bibtex-actions--candidates-cache))

;;;###autoload
(defun bibtex-actions-refresh (&optional force-rebuild-cache)
Expand All @@ -295,8 +320,14 @@ is non-nil, also run the `bibtex-actions-before-refresh-hook' hook."
(interactive "P")
(when force-rebuild-cache
(run-hooks 'bibtex-actions-force-refresh-hook))
;; t in the result indicates that cache was computed but came out nil nil
;; itself is used to indicate a cache that hasn't been computed this is to
;; work around the fact that we can't differentiate between empty list and nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is outdated now. I forgot to remove it earlier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops; I merged it.

You can remove it when you do the related PR :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was quick. I hope these late changes don't introduce any errors. They are pretty trivial but still fingers crossed.

(setq bibtex-actions--candidates-cache
(bibtex-actions--format-candidates)))
(bibtex-actions--format-candidates))
(let ((bibtex-completion-bibliography (bibtex-actions--local-files-to-cache)))
(setq bibtex-actions--local-candidates-cache

This comment was marked as resolved.

(bibtex-actions--format-candidates "is:local"))))

;;;###autoload
(defun bibtex-actions-insert-preset ()
Expand Down