Skip to content

Commit

Permalink
Vertico Prescient: Change how candidates are remembered. (#156)
Browse files Browse the repository at this point in the history
- Fix #155, remembering candidates when entering a new directory
  with `vertico-directory-enter`.
- Remember candidates on minibuffer exit as well as candidate
  insertion.

- Add Compat (https://github.com/emacs-compat/compat) as a dependency.
  It is already a dependency of Vertico.
- Add stub file `stub/compat.el`.
- Remove `vertico-prescient--remember`.
- Add `vertico-prescient--remember-minibuffer-contents`.  If
  completing a file name, only remember the last component of
  the file path, since that is the actual candidate.  If the candidate
  is a directory, include the trailing directory separator.
- Add `vertico-prescient--insertion-commands` and
  `vertico-prescient--remember-inserted-candidate` for remembering
  in `post-command-hook`.
- Add `vertico-prescient--remember-exited-candidate` and
  `vertico-prescient--exit-commands` for remembering in
  `minibuffer-exit-hook`.
- Hook `vertico-prescient--setup-remembrance` into
  `minibuffer-setup-hook`.
  • Loading branch information
okamsn committed Jan 4, 2024
1 parent 0e17905 commit 864b352
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 12 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ The format is based on [Keep a Changelog].
`completion-lazy-hilit` and `completion-lazy-hilit-fn`, new in Emacs
30 and already supported by some completion UIs ([#152], [#153]).

### Bugs fixed
* Change how candidates are remembered for Vertico to work with
`vertico-directory-enter` and to remember the minibuffer contents
when exiting the minibuffer.

[#152]: https://github.com/radian-software/prescient.el/issues/152
[#153]: https://github.com/radian-software/prescient.el/pull/153
[#156]: https://github.com/radian-software/prescient.el/pull/156

## 6.2 (released 2023-11-23)
### Features
Expand Down
7 changes: 7 additions & 0 deletions stub/compat.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
;; This file contains stub definitions from compat.el which allows
;; files to be byte-compiled in the absence of compat.el.

(unless (fboundp 'file-name-split)
(defun file-name-split (_FILENAME)))

(provide 'compat)
94 changes: 82 additions & 12 deletions vertico-prescient.el
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
;; Homepage: https://github.com/radian-software/prescient.el
;; Keywords: extensions
;; Created: 23 Sep 2022
;; Package-Requires: ((emacs "27.1") (prescient "6.1.0") (vertico "0.28"))
;; Package-Requires: ((emacs "27.1") (prescient "6.1.0") (vertico "0.28") (compat "29.1"))
;; SPDX-License-Identifier: MIT
;; Version: 6.2.0

Expand All @@ -24,10 +24,13 @@
;;;; Libraries and Declarations

(eval-when-compile (require 'cl-lib))
(require 'compat)
(require 'prescient)
(require 'subr-x)
(require 'vertico)

(defvar vertico-mode)

;;;; Customization

(defgroup vertico-prescient nil
Expand Down Expand Up @@ -92,13 +95,6 @@ by `vertico-prescient-mode'."
(defvar vertico-prescient--old-toggle-binding nil
"Previous binding of `M-s' in `vertico-map'.")

(defun vertico-prescient--remember ()
"Advice for remembering candidates in Vertico."
(when (>= vertico--index 0)
(prescient-remember
(substring-no-properties
(nth vertico--index vertico--candidates)))))

(defvar-local vertico-prescient--local-settings nil
"Whether this buffer has local settings due to `vertico-prescient-mode'.")

Expand All @@ -120,6 +116,77 @@ by `vertico-prescient-mode'."
(prescient--completion-kill-local-vars)
(setq vertico-prescient--local-settings nil))

(defun vertico-prescient--remember-minibuffer-contents ()
"Remember the minibuffer contents as a candidate.
If we are not completing a file name (according to
`minibuffer-completing-file-name'), then we remember the
minibuffer contents. When completing file names, we remember the
last component of the completed file name path, including a
trailing directory separator as needed."
(let ((txt (minibuffer-contents-no-properties)))
(unless (string-empty-p txt)
(prescient-remember (if minibuffer-completing-file-name
(if (directory-name-p txt)
(thread-first txt
file-name-split
(last 2)
car
file-name-as-directory)
(thread-first txt
file-name-split
last
car))
txt)))))

(defvar vertico-prescient--insertion-commands
'(vertico-insert
vertico-quick-insert
vertico-directory-enter)
"Commands that trigger `prescient-remember' after running.")

(defun vertico-prescient--remember-inserted-candidate ()
"Remember the minibuffer contents as a candidate after insertion commands.
Such commands are listed in `vertico-prescient--insertion-commands'."
(when (and (memq this-command vertico-prescient--insertion-commands)
;; Pro-actively try to avoid running the remembrance
;; function twice for commands that can insert and exit.
;; This might not be needed?
(let ((buf (current-buffer)))
;; In Emacs 28+, we would use the new second argument
;; to `minibufferp' check if the buffer is the active
;; minibuffer, but we want to support Emacs 27.
(and (> 0 (minibuffer-depth))
(minibufferp buf)
(eq (active-minibuffer-window)
(get-buffer-window buf)))))
(vertico-prescient--remember-minibuffer-contents)))

(defvar vertico-prescient--exit-commands
'(vertico-exit
vertico-quick-exit
exit-minibuffer
vertico-directory-enter)
"Commands that trigger `prescient-remember' when exiting the minibuffer.")

(defun vertico-prescient--remember-exited-candidate ()
"Remember the minibuffer contents as a candidate after exiting commands.
Such commands are listed in `vertico-prescient--exit-commands'."
(when (memq this-command vertico-prescient--exit-commands)
(vertico-prescient--remember-minibuffer-contents)))

(defun vertico-prescient--setup-remembrance ()
"Set up the remembering functions in the relevant hooks."
(when vertico-mode
(add-hook 'post-command-hook
#'vertico-prescient--remember-inserted-candidate
nil t)
(add-hook 'minibuffer-exit-hook
#'vertico-prescient--remember-exited-candidate
nil t)))

;;;###autoload
(define-minor-mode vertico-prescient-mode
"Minor mode to use prescient.el in Vertico menus.
Expand All @@ -139,7 +206,8 @@ This mode will:
to `completion-category-overrides'
- set `completion-category-defaults' to nil
- advise `vertico-insert' to remember candidates"
- insert code for remembering candidates into `minibuffer-exit-hook'
and `post-command-hook'."
:global t
:group 'prescient
(if vertico-prescient-mode
Expand Down Expand Up @@ -178,7 +246,8 @@ This mode will:
;; While sorting might not be enabled in Vertico, it might
;; still be enabled in another UI, such as Company or Corfu.
;; Therefore, we still want to remember candidates.
(advice-add 'vertico-insert :before #'vertico-prescient--remember))
(add-hook 'minibuffer-setup-hook
#'vertico-prescient--setup-remembrance))

;; Turn off mode.

Expand All @@ -193,7 +262,7 @@ This mode will:
(when (equal (lookup-key vertico-map (kbd "M-s"))
prescient-toggle-map)
(define-key vertico-map (kbd "M-s")
vertico-prescient--old-toggle-binding))
vertico-prescient--old-toggle-binding))
(remove-hook 'prescient--toggle-refresh-functions
#'vertico-prescient--toggle-refresh)

Expand All @@ -206,7 +275,8 @@ This mode will:
(vertico-prescient--undo-completion-settings))))

;; Undo remembrance settings.
(advice-remove 'vertico-insert #'vertico-prescient--remember)))
(remove-hook 'minibuffer-setup-hook
#'vertico-prescient--setup-remembrance)))

(provide 'vertico-prescient)
;;; vertico-prescient.el ends here
Expand Down

0 comments on commit 864b352

Please sign in to comment.