branch: elpa/dirvish
commit 2d63995d3296c259cef90830cf0433602429ecec
Author: Alex Lu <[email protected]>
Commit: Alex Lu <[email protected]>
feat: add `dirvish-peek-key` user option (closes #191)
---
dirvish.el | 9 ++++++---
docs/CUSTOMIZING.org | 28 +++++++++++++--------------
docs/EXTENSIONS.org | 18 ++++++++++++-----
extensions/dirvish-peek.el | 48 +++++++++++++++++++++++++++++++++++++++++++---
extensions/dirvish-side.el | 2 +-
5 files changed, 78 insertions(+), 27 deletions(-)
diff --git a/dirvish.el b/dirvish.el
index 641c8b58b4..de9e96e841 100644
--- a/dirvish.el
+++ b/dirvish.el
@@ -6,7 +6,7 @@
;; Keywords: files, convenience
;; Homepage: https://github.com/alexluigit/dirvish
;; SPDX-License-Identifier: GPL-3.0-or-later
-;; Package-Requires: ((emacs "28.1"))
+;; Package-Requires: ((emacs "28.1") (compat "30"))
;; This file is not part of GNU Emacs.
@@ -22,7 +22,7 @@
;;; Code:
(require 'dired)
-(require 'cl-lib)
+(require 'compat)
;;;; User Options
@@ -336,7 +336,10 @@ Set the PROP with BODY if given."
`val)))
(defun dirvish-run-with-delay (action fun &optional debounce throttle record)
- "DV ACTION FUN DEBOUNCE THROTTLE RECORD."
+ "Run function FUN accroding to ACTION with delay.
+DEBOUNCE defaults to `dirvish-input-debounce'.
+THROTTLE defaults to `dirvish-input-throttle'.
+RECORD defaults to `dirvish--delay-timer'."
(declare (indent defun))
(setq record (or record dirvish--delay-timer)
debounce (or debounce dirvish-input-debounce)
diff --git a/docs/CUSTOMIZING.org b/docs/CUSTOMIZING.org
index 7baae28b57..8635f059d2 100644
--- a/docs/CUSTOMIZING.org
+++ b/docs/CUSTOMIZING.org
@@ -494,26 +494,24 @@ you don't have to require them explicitly if you
installed dirvish from MELPA or
'(vc-state nerd-icons collapse file-size))
:bind ; Bind `dirvish-fd|dirvish-side|dirvish-dwim' as you see fit
(("C-c f" . dirvish)
- :map dirvish-mode-map ; Dirvish inherits `dired-mode-map'
- ;; (";" . dired-up-directory) ; So you can adjust dired bindings here
- ("?" . dirvish-dispatch) ; contains most of sub-menus in dirvish
extensions
- ("f" . dirvish-history-go-forward)
- ("b" . dirvish-history-go-backward)
+ :map dirvish-mode-map ; Dirvish inherits `dired-mode-map'
+ (";" . dired-up-directory) ; So you can adjust `dired' bindings
here
+ ("?" . dirvish-dispatch) ; [?] a helpful cheatsheet
+ ("a" . dirvish-setup-menu) ; [a]ttributes settings: press `a' +
`t' toggles mtime, etc.
+ ("f" . dirvish-file-info-menu) ; [f]ile info
+ ("o" . dirvish-quick-access) ; [o]pen `dirvish-quick-access-entries'
+ ("s" . dirvish-quicksort) ; [s]ort flie list
+ ("r" . dirvish-history-jump) ; [r]ecent visited
+ ("l" . dirvish-ls-switches-menu) ; [l]s command flags
+ ("*" . dirvish-mark-menu)
("y" . dirvish-yank-menu)
("N" . dirvish-narrow)
("^" . dirvish-history-last)
- ("s" . dirvish-setup-menu) ; `sf' toggles fullframe, `st' toggles
mtime, etc.
- ("h" . dirvish-history-jump) ; remapped `describe-mode'
- ("r" . dirvish-quicksort) ; remapped `dired-sort-toggle-or-edit'
- ("v" . dirvish-vc-menu) ; remapped `dired-view-file'
("TAB" . dirvish-subtree-toggle)
- ("M-a" . dirvish-quick-access)
- ("M-f" . dirvish-file-info-menu)
- ("M-l" . dirvish-ls-switches-menu)
- ("M-m" . dirvish-mark-menu)
+ ("M-f" . dirvish-history-go-forward)
+ ("M-b" . dirvish-history-go-backward)
("M-t" . dirvish-layout-toggle)
- ("M-e" . dirvish-emerge-menu)
- ("M-j" . dirvish-fd-jump)))
+ ("M-e" . dirvish-emerge-menu)))
#+end_src
** Mouse settings
diff --git a/docs/EXTENSIONS.org b/docs/EXTENSIONS.org
index e8ab56331a..b8557144bb 100644
--- a/docs/EXTENSIONS.org
+++ b/docs/EXTENSIONS.org
@@ -117,16 +117,24 @@ a directory, add ~dirvish-emerge-mode~ to
~dirvish-setup-hook~.
This extension introduces =dirvish-peek-mode=, a minor mode that enables file
previews within the minibuffer as you narrow down candidates. By leveraging
=dirvish.el= for its core functionality, it delivers a seamless and consistent
-preview experience.
+preview experience. It currently supports =vertico=, =ivy= and =icomplete=.
https://user-images.githubusercontent.com/16313743/158052790-22e6cf49-e18e-435c-908e-f5d91ba316a6.mp4
*Figure 1.* A demo of ~find-library~ and ~find-file~ commands after
~dirvish-peek-mode~ enabled.
-The ~dirvish-peek-display-alist~ option allows you to control the window
placement
-of the peek window.
-
-~dirvish-peek-mode~ currently supports =vertico=, =selectrum=, =ivy= and
=icomplete[-vertical]=.
+=dirvish-peek-mode= enables previews by default. You can disable them by
adjusting
+the =dirvish-peek-key= variable (adopted from ~consult-preview-key~).
Furthermore
+it is possible to specify keybindings which trigger the preview manually. The
+default setting of =dirvish-peek-key= is =any= which means that
=dirvish-peek-mode=
+triggers the preview /immediately/ on any key press when the selected candidate
+changes. The following settings are possible:
+
+- Automatic and immediate ='any=
+- Automatic and delayed =(list :debounce 0.5 'any)=
+- Manual and immediate ="M-."=
+- Manual and delayed =(list :debounce 0.5 "M-.")=
+- Disabled =nil=
* Version-control (*git*) integration (dirvish-vc.el)
diff --git a/extensions/dirvish-peek.el b/extensions/dirvish-peek.el
index e978b1dbe3..617b5cde6a 100644
--- a/extensions/dirvish-peek.el
+++ b/extensions/dirvish-peek.el
@@ -41,6 +41,18 @@ Notice that the `dirvish-preview-dispatchers' option is
respected across
all categories."
:group 'dirvish :type '(repeat :tag "each item can be 'file 'project-file
'library" symbol))
+;; Credit: copied from `consult-preview-key'
+(defcustom dirvish-peek-key 'any
+ "Preview trigger keys, can be nil, `any', a single key or a list of keys.
+Debouncing can be specified via the `:debounce' attribute. The
+individual keys must be strings accepted by `key-valid-p'."
+ :group 'dirvish
+ :type '(choice (const :tag "Any key" any)
+ (list :tag "Debounced" (const :debounce) (float :tag
"Seconds" 0.1) (const any))
+ (const :tag "No preview" nil)
+ (key :tag "Key")
+ (repeat :tag "List of keys" key)))
+
(defun dirvish-peek--prepare-cand-fetcher ()
"Set candidate fetcher according to current completion framework."
(dirvish-prop :peek-fetcher
@@ -50,6 +62,25 @@ all categories."
((bound-and-true-p icomplete-mode)
(lambda () (car completion-all-sorted-completions))))))
+;; Credit: copied from `consult--preview-key-normalize'
+(defun dirvish-peek--normalize-keys (peek-key)
+ "Normalize PEEK-KEY, return alist of keys and debounce times."
+ (let ((keys) (debounce 0))
+ (setq peek-key (ensure-list peek-key))
+ (while peek-key
+ (if (eq (car peek-key) :debounce)
+ (setq debounce (cadr peek-key)
+ peek-key (cddr peek-key))
+ (let ((key (car peek-key)))
+ (cond
+ ((eq key 'any))
+ ((not (key-valid-p key))
+ (error "%S is not a valid key definition; see `key-valid-p'" key))
+ (t (setq key (key-parse key))))
+ (push (cons key debounce) keys))
+ (pop peek-key)))
+ keys))
+
(dirvish-define-preview peek-exception (file)
"Handle exceptions when peek files."
(cond ((string-prefix-p "LIB_EXCEPTION:::" file)
@@ -74,7 +105,14 @@ one of categories in `dirvish-peek-categories'."
(dv (dirvish--get-session 'curr-layout 'any))
(win (and dv (dv-preview-window dv))) new-dv)
(dirvish-prop :peek-category p-category)
- (when p-category
+ (when (and p-category dirvish-peek-key)
+ (let ((old-map (current-local-map))
+ (map (make-sparse-keymap))
+ (keys (dirvish-peek--normalize-keys dirvish-peek-key)))
+ (pcase-dolist (`(,k . ,_) keys)
+ (unless (or (eq k 'any) (lookup-key old-map k))
+ (define-key map k #'ignore)))
+ (use-local-map (make-composed-keymap map old-map)))
(dirvish-peek--prepare-cand-fetcher)
(add-hook 'post-command-hook #'dirvish-peek-update-h 90 t)
(add-hook 'minibuffer-exit-hook #'dirvish-peek-exit-h nil t)
@@ -89,11 +127,15 @@ one of categories in `dirvish-peek-categories'."
do (dirvish-prop k (and (functionp v) (funcall v))))
(dirvish-prop :dv (dv-id new-dv))
(dirvish-prop :preview-dps
- (append '(dirvish-peek-exception-dp) (dv-preview-dispatchers
new-dv))))))
+ (append '(dirvish-peek-exception-dp)
+ (dv-preview-dispatchers new-dv))))))
(defun dirvish-peek-update-h ()
"Hook for `post-command-hook' to update peek window."
(when-let* ((category (dirvish-prop :peek-category))
+ (key (this-single-command-keys))
+ (peek-keys (dirvish-peek--normalize-keys dirvish-peek-key))
+ (peek-key (or (assq 'any peek-keys) (assoc key peek-keys)))
(cand-fetcher (dirvish-prop :peek-fetcher))
(cand (funcall cand-fetcher))
(dv (dirvish-curr)))
@@ -112,7 +154,7 @@ one of categories in `dirvish-peek-categories'."
(error-message-string err)))))))
(dirvish-prop :index cand)
(dirvish-run-with-delay cand
- (lambda (action) (dirvish--preview-update dv action)))))
+ (lambda (action) (dirvish--preview-update dv action)) (cdr peek-key))))
(defun dirvish-peek-exit-h ()
"Hook for `minibuffer-exit-hook' to destroy peek session."
diff --git a/extensions/dirvish-side.el b/extensions/dirvish-side.el
index 0b6e65c33d..87c5eb29f8 100644
--- a/extensions/dirvish-side.el
+++ b/extensions/dirvish-side.el
@@ -171,7 +171,7 @@ after switching to a new project."
- If the current window is a side session window, hide it.
- If a side session is visible, select it.
- If a side session exists but is not visible, show it.
-- If there is no side session exists,create a new one with PATH.
+- If there is no side session exists, create a new one with PATH.
If called with \\[universal-arguments], prompt for PATH,
otherwise it defaults to `project-current'."