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

Add previous inputs to the list of defaults during multiple selection #717

Merged
merged 5 commits into from
Jan 1, 2023
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
10 changes: 10 additions & 0 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ 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

If you want to select multiple candidates using the same search term =M-n= also recalls the previous input, so you can use =TAB= to select one candidate then press =M-n= to quickly insert the previous search term again (see notes below for some caveats).

=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=.

Expand All @@ -238,6 +240,14 @@ The ~citar-notes-sources~ variable configures note backends, and ~citar-notes-so
A backend primarily specifies functions to update the Citar display, to create the completion candidates, and to open existing and new notes.
See the ~citar-notes-sources~ docstring for details, and the =citar-register-notes-source= and =citar-remove-notes-source= convenience functions.

Using =M-n= to recall the previous input only works when selecting multiple candidates during a single =citar-command=. If you use =vertico=, =vertico-repeat= provides similar functionality for rerunning the commands with the last input.

By default =Emacs= leaves the point at the beginning of input if you press =M-n= with minibuffer empty. If you want to change this behavior and instead leave the point at the end of input use,

#+BEGIN_SRC emacs-lisp
(advice-add 'goto-history-element :after (defun my-end-of-buffer (&rest _) (goto-char (point-max))))
#+END_SRC

** 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=.
Expand Down
40 changes: 26 additions & 14 deletions citar.el
Original file line number Diff line number Diff line change
Expand Up @@ -584,10 +584,17 @@ to filter them."
SEL is the key which should be used for selection. EXIT is the key which
is used for exiting the minibuffer during completing read.")

(defvar citar--multiple-last-input nil
"Variable used to track the input so that it can be restored subsequently.")

(defun citar--multiple-exit ()
"Exit with the currently selected candidates."
(interactive)
(setq unread-command-events (listify-key-sequence (kbd (car citar--multiple-setup)))))
(funcall-interactively (key-binding (kbd (car citar--multiple-setup)))))

(defun citar--multiple-record-input ()
"Record the current minibuffer input."
(setq citar--multiple-last-input (minibuffer-contents-no-properties)))

(defun citar--setup-multiple-keymap ()
"Make a keymap suitable for `citar--select-multiple'."
Expand All @@ -596,29 +603,34 @@ is used for exiting the minibuffer during completing read.")
(kbdexit (kbd (cdr citar--multiple-setup))))
(define-key keymap kbdselect (lookup-key keymap kbdexit))
(define-key keymap kbdexit #'citar--multiple-exit)
(use-local-map keymap)))
(use-local-map keymap))
(add-hook 'post-command-hook #'citar--multiple-record-input nil t))

(defun citar--select-multiple (prompt candidates &optional filter history def)
"Select multiple CANDIDATES with PROMPT.
HISTORY is the `completing-read' history argument."
;; Because completing-read-multiple just does not work for long candidate
;; strings, and IMO is a poor UI.
(let* ((selected-hash (make-hash-table :test 'equal)))
(while (let ((initial-history (symbol-value history))
(item (minibuffer-with-setup-hook #'citar--setup-multiple-keymap
(completing-read
(format "%s (%s/%s): " prompt
(hash-table-count selected-hash)
(hash-table-count candidates))
(citar--multiple-completion-table selected-hash candidates filter)
nil t nil history `("" . ,def)))))
(unless (string-empty-p item)
(let* ((selected-hash (make-hash-table :test 'equal))
(command this-command))
(push (setq citar--multiple-last-input "") def)
(while (let* ((initial-history (symbol-value history))
(item (minibuffer-with-setup-hook #'citar--setup-multiple-keymap
(completing-read
(format "%s (%s/%s): " prompt
(hash-table-count selected-hash)
(hash-table-count candidates))
(citar--multiple-completion-table selected-hash candidates filter)
nil t nil history def))))
(push citar--multiple-last-input def)
(unless (string-blank-p citar--multiple-last-input)
(if (not (gethash item selected-hash))
(puthash item t selected-hash)
(remhash item selected-hash)
(set history initial-history)))
(not (or (eq last-command #'citar--multiple-exit)
(string-empty-p item)))))
(not (or (eq this-command #'citar--multiple-exit)
(string-blank-p citar--multiple-last-input))))
(setq this-command command))
(hash-table-keys selected-hash)))

(cl-defun citar--get-resource-candidates (citekeys &key files links notes create-notes)
Expand Down