From 4813891638fa3c93e2b15125964ac52f1582e5d4 Mon Sep 17 00:00:00 2001 From: Bruce D'Arcus Date: Fri, 19 Feb 2021 08:35:22 -0500 Subject: [PATCH 1/7] Make action-functions interactive commands Makes core action-functions interactive by adding a new `bibtex-completion--read` function, with configurable completion systems. The default uses `completing-read`. --- bibtex-completion.el | 47 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/bibtex-completion.el b/bibtex-completion.el index e3d437d..e8af98b 100644 --- a/bibtex-completion.el +++ b/bibtex-completion.el @@ -56,9 +56,24 @@ (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 + "Keymap for bibtex-completion commands" + (let ((map (make-sparse-keymap))) + (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)) + (defcustom bibtex-completion-bibliography nil "The BibTeX file or list of BibTeX files. Org-bibtex users can also specify org mode bibliography files, in @@ -478,6 +493,26 @@ 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 (cdr (assoc (bibtex-completion--completing-read) (bibtex-completion--get-candidates))))) + +(defun bibtex-completion--completing-read () + "Read bibtex-completion entries for completion using completing-read." + (bibtex-completion-init) + (completing-read + "BibTeX entries: " + (bibtex-completion--get-candidates))) + +(defun bibtex-completion--get-candidates () + "Return all keys from bibtex-completion-candidates." + (mapcar + (lambda (cand) + (cons (bibtex-completion-format-entry cand (1- (frame-width))) + (cdr (assoc "=key=" cand)))) + (bibtex-completion-candidates))) + (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, @@ -910,6 +945,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 @@ -928,6 +964,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)) @@ -1087,6 +1124,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)))) @@ -1096,6 +1134,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) @@ -1293,11 +1332,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) @@ -1320,6 +1361,7 @@ Self-contained means that cross-referenced entries are merged." (defun bibtex-completion-add-PDF-attachment (keys) "Attach the PDFs of the entries with the given KEYS where available." + (interactive (list (bibtex-completion--read))) (dolist (key keys) (let ((pdf (bibtex-completion-find-pdf key bibtex-completion-find-additional-pdfs))) (if pdf @@ -1442,10 +1484,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)) @@ -1475,6 +1519,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)))) From e5e4114691fec0dcca41d4577b7f16d44968049c Mon Sep 17 00:00:00 2001 From: Bruce D'Arcus Date: Thu, 25 Feb 2021 18:09:18 -0500 Subject: [PATCH 2/7] Add completion category --- bibtex-completion.el | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bibtex-completion.el b/bibtex-completion.el index e8af98b..cedd7f5 100644 --- a/bibtex-completion.el +++ b/bibtex-completion.el @@ -503,7 +503,11 @@ for string replacement." (bibtex-completion-init) (completing-read "BibTeX entries: " - (bibtex-completion--get-candidates))) + (lambda (string pred action) + (if (eq action 'metadata) + '(metadata + (category . bibtex)) + (complete-with-action action (bibtex-completion--get-candidates) string pred))))) (defun bibtex-completion--get-candidates () "Return all keys from bibtex-completion-candidates." From 8516cfa10f37d9ce45f1f568f391ad867015de34 Mon Sep 17 00:00:00 2001 From: Bruce D'Arcus Date: Sat, 27 Feb 2021 06:30:45 -0500 Subject: [PATCH 3/7] Revise bibtex-completion--get-candidates Change to cl-loop, and propertize candidates string to use bibtex-completion-candidates, but to display using bibtex-completion-format-entry. --- bibtex-completion.el | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/bibtex-completion.el b/bibtex-completion.el index 5d3b9ea..c33a076 100644 --- a/bibtex-completion.el +++ b/bibtex-completion.el @@ -503,19 +503,23 @@ for string replacement." (bibtex-completion-init) (completing-read "BibTeX entries: " - (lambda (string pred action) + (lambda (string predicate action) (if (eq action 'metadata) '(metadata + ;; (annotation-function . bibtex-completion--annotation) (category . bibtex)) - (complete-with-action action (bibtex-completion--get-candidates) string pred))))) + (complete-with-action action (bibtex-completion--get-candidates) string predicate))))) (defun bibtex-completion--get-candidates () "Return all keys from bibtex-completion-candidates." - (mapcar - (lambda (cand) - (cons (bibtex-completion-format-entry cand (1- (frame-width))) - (cdr (assoc "=key=" cand)))) - (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. From 629ba5458d335df16c77e3401dd7051d36c51699 Mon Sep 17 00:00:00 2001 From: Bruce D'Arcus Date: Sun, 28 Feb 2021 06:00:43 -0500 Subject: [PATCH 4/7] function enhancements --- bibtex-completion.el | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/bibtex-completion.el b/bibtex-completion.el index c33a076..91cda1e 100644 --- a/bibtex-completion.el +++ b/bibtex-completion.el @@ -60,8 +60,8 @@ :group 'completion) (defvar bibtex-completion-map - "Keymap for bibtex-completion commands" (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) @@ -363,6 +363,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.") @@ -379,7 +383,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 @@ -496,19 +499,22 @@ for string replacement." (defun bibtex-completion--read () "Select BibTeX entries in completion system." ;; define a completion function that defaults to completing-read, but can be overridden - (list (cdr (assoc (bibtex-completion--completing-read) (bibtex-completion--get-candidates))))) + (list (bibtex-completion-read-backend))) (defun bibtex-completion--completing-read () "Read bibtex-completion entries for completion using completing-read." (bibtex-completion-init) - (completing-read - "BibTeX entries: " - (lambda (string predicate action) - (if (eq action 'metadata) - '(metadata - ;; (annotation-function . bibtex-completion--annotation) - (category . bibtex)) - (complete-with-action action (bibtex-completion--get-candidates) string predicate))))) + (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." @@ -992,6 +998,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) From 322b364c5ccf9e83287c5a90882c955698436a57 Mon Sep 17 00:00:00 2001 From: Bruce D'Arcus Date: Mon, 1 Mar 2021 17:25:22 -0500 Subject: [PATCH 5/7] Add docstring to keymap --- bibtex-completion.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bibtex-completion.el b/bibtex-completion.el index 91cda1e..f501000 100644 --- a/bibtex-completion.el +++ b/bibtex-completion.el @@ -72,7 +72,9 @@ (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)) + map) + "Keymap for bibtex-completion commands" + ) (defcustom bibtex-completion-bibliography nil "The BibTeX file or list of BibTeX files. From a888ea50b78b3c789d94d0e04412be9c81657e47 Mon Sep 17 00:00:00 2001 From: Bruce D'Arcus Date: Thu, 4 Mar 2021 07:57:09 -0500 Subject: [PATCH 6/7] Introduce a downcased command The only command not all lowercase was `bibtex-completion-add-PDF-attachment`. This adds a new downcased interactive function that simply references that. Also, updates the keybinding. --- bibtex-completion.el | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bibtex-completion.el b/bibtex-completion.el index f501000..224d578 100644 --- a/bibtex-completion.el +++ b/bibtex-completion.el @@ -68,7 +68,7 @@ (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 "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) @@ -1379,9 +1379,15 @@ Self-contained means that cross-referenced entries are merged." concat (format " %s = {%s},\n" name value))))) -(defun bibtex-completion-add-PDF-attachment (keys) +(defun bibtex-completion-add-pdf-attachment () + ; 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) (let ((pdf (bibtex-completion-find-pdf key bibtex-completion-find-additional-pdfs))) (if pdf From 53363db41ee50a1ac6ac983452362a5528234ac5 Mon Sep 17 00:00:00 2001 From: Bruce D'Arcus Date: Thu, 4 Mar 2021 21:01:39 -0500 Subject: [PATCH 7/7] Add missing parameter --- bibtex-completion.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bibtex-completion.el b/bibtex-completion.el index 224d578..294ed54 100644 --- a/bibtex-completion.el +++ b/bibtex-completion.el @@ -1379,7 +1379,7 @@ Self-contained means that cross-referenced entries are merged." concat (format " %s = {%s},\n" name value))))) -(defun bibtex-completion-add-pdf-attachment () +(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."