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

Make bibtex-completion (more) interactive #361

Closed
Closed
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
72 changes: 70 additions & 2 deletions bibtex-completion.el
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,26 @@
(declare-function org-element-property "org-element")

(defgroup bibtex-completion nil
"Helm plugin for searching entries in a BibTeX bibliography."
"Provides searching of entries in a BibTeX bibliography, and running actions on them."
:group 'completion)

(defvar bibtex-completion-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "o") 'bibtex-completion-open-any)
(define-key map (kbd "p") 'bibtex-completion-open-pdf)
(define-key map (kbd "u") 'bibtex-completion-open-url-or-doi)
(define-key map (kbd "c") 'bibtex-completion-insert-citation)
(define-key map (kbd "r") 'bibtex-completion-insert-reference)
(define-key map (kbd "k") 'bibtex-completion-insert-key)
(define-key map (kbd "b") 'bibtex-completion-insert-bibtex)
(define-key map (kbd "a") 'bibtex-completion-add-pdf-attachment)
(define-key map (kbd "e") 'bibtex-completion-edit-notes)
(define-key map (kbd "s") 'bibtex-completion-show-entry)
(define-key map (kbd "l") 'bibtex-completion-add-pdf-to-library)
map)
"Keymap for bibtex-completion commands"
)

(defcustom bibtex-completion-bibliography nil
"The BibTeX file or list of BibTeX files.
Org-bibtex users can also specify org mode bibliography files, in
Expand Down Expand Up @@ -348,6 +365,10 @@ Only entries of these types are checked in order to resolve
cross-references. The default list is usually sufficient; adding
more types can slow down resolution for large biblioraphies.")

;; one can reset the backend function using fset; maybe there's a
;; more elegant way to do this?
(fset 'bibtex-completion-read-backend `bibtex-completion--completing-read)

(defvar bibtex-completion-display-formats-internal nil
"Stores `bibtex-completion-display-formats' together with the \"used width\" of each format string.
This is set internally.")
Expand All @@ -364,7 +385,6 @@ bibliography file is reparsed.")
(defvar bibtex-completion-string-hash-table nil
"A hash table used for string replacements.")


(defun bibtex-completion-normalize-bibliography (&optional type)
"Return a list of bibliography file(s) in `bibtex-completion-bibliography'.
If there are org mode bibliography-files, their corresponding
Expand Down Expand Up @@ -478,6 +498,37 @@ for string replacement."
(defvar bibtex-completion-cached-notes-keys nil
"A cache storing notes keys obtained when the bibliography was last parsed.")

(defun bibtex-completion--read ()
"Select BibTeX entries in completion system."
;; define a completion function that defaults to completing-read, but can be overridden
(list (bibtex-completion-read-backend)))

(defun bibtex-completion--completing-read ()
"Read bibtex-completion entries for completion using completing-read."
(bibtex-completion-init)
(when-let ((candidates (bibtex-completion--get-candidates))
(chosen
(completing-read
"BibTeX entries: "
(lambda (string predicate action)
(if (eq action 'metadata)
'(metadata
;; (annotation-function . bibtex-completion--annotation)
(category . bibtex))
(complete-with-action action candidates string predicate))))))
(cdr (assoc chosen candidates))))

(defun bibtex-completion--get-candidates ()
"Return all keys from bibtex-completion-candidates."
(cl-loop
for candidate in (bibtex-completion-candidates)
collect
(cons
;; Here use one string for display, and the other for search.
(propertize
(car candidate) 'display (bibtex-completion-format-entry candidate (1- (frame-width))))
(cdr (assoc "=key=" candidate)))))

(defun bibtex-completion-candidates ()
"Read the BibTeX files and return a list of conses, one for each entry.
The first element of these conses is a string containing authors,
Expand Down Expand Up @@ -910,6 +961,7 @@ governed by the variable `bibtex-completion-display-formats'."
If multiple PDFs are found for an entry, ask for the one to open
using `completion-read'. If FALLBACK-ACTION is non-nil, it is
called in case no PDF is found."
(interactive (list (bibtex-completion--read)))
(dolist (key keys)
(let ((pdf (bibtex-completion-find-pdf key bibtex-completion-find-additional-pdfs)))
(cond
Expand All @@ -928,6 +980,7 @@ called in case no PDF is found."

(defun bibtex-completion-open-url-or-doi (keys)
"Open the URL or DOI associated with entries in KEYS in a browser."
(interactive (list (bibtex-completion--read)))
(dolist (key keys)
(let* ((entry (bibtex-completion-get-entry key))
(url (bibtex-completion-get-value "url" entry))
Expand All @@ -947,6 +1000,7 @@ called in case no PDF is found."
If multiple PDFs are found for an entry, ask for the one to open
using `completion-read'. If no PDF is found, try to open a URL
or DOI in the browser instead."
(interactive (list (bibtex-completion--read)))
(bibtex-completion-open-pdf keys 'bibtex-completion-open-url-or-doi))

(defun bibtex-completion-format-citation-default (keys)
Expand Down Expand Up @@ -1087,6 +1141,7 @@ The format depends on
(let ((format-function
(cdr (or (assoc major-mode bibtex-completion-format-citation-functions)
(assoc 'default bibtex-completion-format-citation-functions)))))
(interactive (list (bibtex-completion--read)))
(insert
(funcall format-function keys))))

Expand All @@ -1096,6 +1151,7 @@ The format depends on
(s-word-wrap fill-column
(concat "\n- " (bibtex-completion-apa-format-reference it)))
keys)))
(interactive (list (bibtex-completion--read)))
(insert "\n" (s-join "\n" refs) "\n")))

(defun bibtex-completion-apa-format-reference (key)
Expand Down Expand Up @@ -1296,11 +1352,13 @@ Surrounding curly braces are stripped."

(defun bibtex-completion-insert-key (keys)
"Insert BibTeX KEYS at point."
(interactive (list (bibtex-completion--read)))
(insert
(funcall 'bibtex-completion-format-citation-default keys)))

(defun bibtex-completion-insert-bibtex (keys)
"Insert BibTeX entries for entries in KEYS at point."
(interactive (list (bibtex-completion--read)))
(insert (s-join "\n" (--map (bibtex-completion-make-bibtex it) keys))))

(defun bibtex-completion-make-bibtex (key)
Expand All @@ -1321,6 +1379,13 @@ Self-contained means that cross-referenced entries are merged."
concat
(format " %s = {%s},\n" name value)))))

(defun bibtex-completion-add-pdf-attachment (keys)
; this is basically a lowercase command alias for the function
; ideally, that name should be deprecated in favor of this one
"Attach the PDFs of the entries with the given KEYS where available."
(interactive (list (bibtex-completion--read)))
(bibtex-completion-add-PDF-attachment))

(defun bibtex-completion-add-PDF-attachment (keys)
"Attach the PDFs of the entries with the given KEYS where available."
(dolist (key keys)
Expand Down Expand Up @@ -1445,10 +1510,12 @@ Creates new notes where none exist yet."

(defun bibtex-completion-edit-notes (keys)
"Open the notes associated with KEYS using `bibtex-completion-edit-notes-function'."
(interactive (list (bibtex-completion--read)))
(funcall bibtex-completion-edit-notes-function keys))

(defun bibtex-completion-show-entry (keys)
"Show the first entry in KEYS in the relevant BibTeX file."
(interactive (list (bibtex-completion--read)))
(catch 'break
(dolist (bib-file (bibtex-completion-normalize-bibliography 'main))
(let ((key (car keys))
Expand Down Expand Up @@ -1478,6 +1545,7 @@ Creates new notes where none exist yet."
"Add a PDF to the library for the first entry in KEYS.
The PDF can be added either from an open buffer, a file, or a
URL."
(interactive (list (bibtex-completion--read)))
(let* ((key (car keys))
(source (char-to-string
(read-char-choice "Add pdf from [b]uffer, [f]ile, or [u]rl? " '(?b ?f ?u))))
Expand Down