branch: elpa/dirvish commit b5b7926f6c1750a21cd8407eb213c9a8bd94b3ac Author: Alex Lu <hellosimon1...@hotmail.com> Commit: Alex Lu <hellosimon1...@hotmail.com>
refactor(side): simplify file opening With this change, opening a file from the side window offers these options: - `dired-find-file`: Opens the file in the most recently used window. - `dired-find-alternate-file`: Opens the file and closes the side window. - `dired-find-file-other-window`: Opens the file in a new split window. Users who preferred the removed `dirvish-side-auto-close` option can replicate this behavior by customizing `dirvish-side-open-file-action`. This approach simplifies configuration and leverages existing window splitting preferences, such as `split-width-threshold`. --- dirvish.el | 32 +++++++++++++------------ docs/CUSTOMIZING.org | 14 +++++++---- docs/EXTENSIONS.org | 2 +- extensions/dirvish-side.el | 58 +++++++++++++++++++++------------------------- 4 files changed, 54 insertions(+), 52 deletions(-) diff --git a/dirvish.el b/dirvish.el index e32f2a2241..950fe781f7 100644 --- a/dirvish.el +++ b/dirvish.el @@ -335,9 +335,9 @@ seconds. DEBOUNCE defaults to `dirvish-redisplay-debounce'." (defmacro dirvish-save-dedication (&rest body) "Run BODY after undedicating window, restore dedication afterwards." (declare (debug (&rest form))) - `(let ((dedicated (window-dedicated-p))) - (set-window-dedicated-p nil nil) - (prog1 ,@body (set-window-dedicated-p nil dedicated)))) + `(let* ((w (selected-window)) (ded (window-dedicated-p w))) + (set-window-dedicated-p w nil) + (prog1 ,@body (and (window-live-p w) (set-window-dedicated-p w ded))))) (defsubst dirvish-curr () "Return Dirvish session attached to current buffer, if there is any." @@ -429,7 +429,7 @@ Set process's SENTINEL and PUTS accordingly." (size-fixed () :documentation "passes to `window-size-fixed' for ROOT-WINDOW.") (root-conf #'ignore :documentation "is a function to apply extra configs for INDEX buffer.") (root-window-fn () :documentation "is a function used to create the ROOT-WINDOW for DV.") - (open-file-fn #'ignore :documentation "is a function called before opening a file.") + (open-file #'dirvish-open-file :documentation "is a function to handle file opening.") (curr-layout () :documentation "is the working layout recipe of DV.") (ff-layout dirvish-default-layout :documentation "is a full-frame layout recipe.") (ls-switches dired-listing-switches :documentation "is the directory listing switches.") @@ -488,11 +488,12 @@ FROM-QUIT is used to signify the calling command." (let* ((idx (dv-index dv)) (ff (dv-curr-layout dv)) (wcon (dv-winconf dv)) (server-buf? (lambda (root) (with-current-buffer (cdr root) (bound-and-true-p server-buffer-clients)))) - keep roots kill-buffer-hook) + (keep (list idx)) roots kill-buffer-hook) (cl-loop with killer = (lambda (r) (unless (member r keep) (kill-buffer (cdr r)))) for root in (setq roots (dv-roots dv)) if (or (get-buffer-window (cdr root)) (funcall server-buf? root)) - do (push root keep) finally do (mapc killer roots)) + do (cl-pushnew root keep :test #'equal) + finally do (mapc killer roots)) (when (and ff wcon) (set-window-configuration wcon)) (set-window-fringes nil (frame-parameter nil 'left-fringe) (frame-parameter nil 'left-fringe)) @@ -550,6 +551,14 @@ FROM-QUIT is used to signify the calling command." (dv-preview-dispatchers dv) (dirvish--preview-dps-validate) (dv-attributes dv) (dirvish--attrs-expand attrs)))) +(defun dirvish-open-file (dv find-fn file) + "Open FILE using FIND-FN for default DV sessions." + (let ((cur (current-buffer)) fbuf) + (unwind-protect (funcall find-fn file) + (unless (eq (setq fbuf (current-buffer)) cur) + (dirvish--clear-session dv) + (dirvish-save-dedication (switch-to-buffer fbuf)))))) + (cl-defun dirvish--find-entry (find-fn entry) "Find ENTRY using FIND-FN in current dirvish session. FIND-FN can be one of `find-file', `find-alternate-file', @@ -576,15 +585,8 @@ filename or a string with format of `dirvish-fd-bufname'." (cl-return-from dirvish--find-entry))) (cl-return-from dirvish--find-entry (dirvish--kill-buffer cur))) (if directory? (dirvish-save-dedication (funcall find-fn entry)) - (funcall (dv-open-file-fn dv)) - (dirvish--clear-session dv) - ;; if focusing a file window, do not kill previous buffer - (when (and (not (dirvish-curr)) (eq find-fn 'find-alternate-file)) - (setq find-fn 'find-file)) - (unwind-protect - (dirvish-save-dedication (funcall find-fn entry)) - ;; opening aborted, e.g. user answered `no' on big file alert prompt. - (when (eq (current-buffer) cur) (quit-window)))))) + (mapc #'dirvish--kill-buffer (dv-preview-buffers dv)) + (funcall (dv-open-file dv) dv find-fn entry)))) ;;;; Preview diff --git a/docs/CUSTOMIZING.org b/docs/CUSTOMIZING.org index 373c007b09..aced181da8 100644 --- a/docs/CUSTOMIZING.org +++ b/docs/CUSTOMIZING.org @@ -427,6 +427,14 @@ you don't have to require them explicitly if you installed dirvish from MELPA or =/path/to/dirvish/extensions/= is in your ~load-path~). #+begin_src emacs-lisp +(use-package dired + :config + (setq dired-listing-switches + "-l --almost-all --human-readable --group-directories-first --no-group") + ;; this command is useful when you want to close the window of `dirvish-side' + ;; automatically when opening a file + (put 'dired-find-alternate-file 'disabled nil)) + (use-package dirvish :ensure t :init @@ -448,14 +456,11 @@ you don't have to require them explicitly if you installed dirvish from MELPA or '(vc-state subtree-state nerd-icons collapse git-msg file-time file-size) dirvish-side-attributes '(vc-state nerd-icons collapse file-size)) - (setq dired-listing-switches - "-l --almost-all --human-readable --group-directories-first --no-group") :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' - ;; ("o" . dired-up-directory) ; So you can adjust dired bindings here + ;; (";" . dired-up-directory) ; So you can adjust dired bindings here ("?" . dirvish-dispatch) ; contains most of sub-menus in dirvish extensions - ("a" . dirvish-quick-access) ("f" . dirvish-history-go-forward) ("b" . dirvish-history-go-backward) ("y" . dirvish-yank-menu) @@ -466,6 +471,7 @@ you don't have to require them explicitly if you installed dirvish from MELPA or ("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) diff --git a/docs/EXTENSIONS.org b/docs/EXTENSIONS.org index 6543328068..e8ab56331a 100644 --- a/docs/EXTENSIONS.org +++ b/docs/EXTENSIONS.org @@ -182,7 +182,7 @@ as a sidebar in the frame. These customization options are available: + ~dirvish-side-display-alist~: Display actions for the side window. + ~dirvish-side-window-parameters~: Window parameters for the side window. + ~dirvish-side-width~: Width of the side window. -+ ~dirvish-side-open-file-window-function~: Set window of for opened files. ++ ~dirvish-side-open-file-action~: Action to perform before opening a file in a side window. + ~dirvish-side-auto-expand~: Whether to auto expand parent directories of current file. When ~dirvish-side-follow-mode~ is enabled, the visible side session will select diff --git a/extensions/dirvish-side.el b/extensions/dirvish-side.el index 242b432e30..a3ecb2d74e 100644 --- a/extensions/dirvish-side.el +++ b/extensions/dirvish-side.el @@ -43,45 +43,21 @@ See `dirvish-mode-line-format' for details." See `dirvish-attributes' for details." :group 'dirvish :type '(repeat (symbol :tag "Dirvish attribute"))) -(defcustom dirvish-side-open-file-action 'mru - "The action of how to open a file in side window. -The value can be one of: - -- \\='mru - open the file in the most-recent-used window. -- \\='split - open the file below the mru window. -- \\='vsplit - open the file in a vertical split window. -- a function that returns a target window for the file buffer, - such as `ace-select-window'." +(defcustom dirvish-side-open-file-action nil + "Action to perform before opening a file in a side window. +The value is a function called before switching to the file buffer. The +most recent used window is select if it is nil." :group 'dirvish - :type '(choice (const :tag "open the file in the most-recent-used window" mru) - (const :tag "open the file below the mru window" split) - (const :tag "open the file in a vertical split window" vsplit) + :type '(choice (const :tag "open the file in the most-recent-used window" nil) (function :tag "custom function"))) -(defcustom dirvish-side-auto-close nil - "Whether to auto close the side session after opening a file." - :group 'dirvish :type 'boolean) - (defcustom dirvish-side-auto-expand t "Whether to auto expand parent directories of current file. If non-nil, expand all the parent directories of current buffer's filename until the project root when opening a side session." :group 'dirvish :type 'boolean) -(defun dirvish-side-open-file-fn () - "Called before opening a file in side sessions." - (when (dv-curr-layout (dirvish-curr)) (dirvish-layout-toggle)) - (when dirvish-side-auto-close (quit-window)) - (let* ((mru (get-mru-window nil nil t))) - (select-window (cond ((functionp dirvish-side-open-file-action) - (funcall dirvish-side-open-file-action)) - ((eq dirvish-side-open-file-action 'mru) mru) - ((eq dirvish-side-open-file-action 'split) - (with-selected-window mru (split-window-below))) - ((eq dirvish-side-open-file-action 'vsplit) - (with-selected-window mru (split-window-right))))))) - -(defun dirvish-side-root-conf-fn (buffer) +(defun dirvish-side-root-conf (buffer) "Setup BUFFER for side session." (let ((name (buffer-name buffer))) (unless (string-prefix-p " *SIDE :: " name) @@ -108,6 +84,24 @@ filename until the project root when opening a side session." (enlarge-window-horizontally (- w (window-width))))))) (select-window win))) +(defun dirvish-side-open-file (dv find-fn file) + "Open FILE using FIND-FN for default DV sessions." + (let ((idx (current-buffer)) fbuf) + (unwind-protect (if (eq find-fn 'find-file-other-window) + (funcall find-fn file) ; a new window is split + (dirvish-save-dedication (funcall find-fn file))) + (cond ((eq (setq fbuf (current-buffer)) idx) nil) + ((eq find-fn 'find-file-other-window) (dirvish--clear-session dv)) + (t (dirvish--clear-session dv) + (setf (dv-curr-layout dv) nil) + (if (buffer-live-p idx) ; `find-alternate-file' kills idx + (dirvish-save-dedication (switch-to-buffer idx)) + (delete-window)) + (when (dirvish-curr) (other-window 1)) + (when (functionp dirvish-side-open-file-action) + (funcall dirvish-side-open-file-action)) + (dirvish-save-dedication (switch-to-buffer fbuf))))))) + (defun dirvish-side--session-visible-p () "Return the root window of visible side session." (cl-loop @@ -144,9 +138,9 @@ filename until the project root when opening a side session." :type 'side :size-fixed 'width :dedicated t - :root-conf #'dirvish-side-root-conf-fn + :root-conf #'dirvish-side-root-conf :root-window-fn #'dirvish-side-root-window-fn - :open-file-fn #'dirvish-side-open-file-fn))) + :open-file #'dirvish-side-open-file))) (r-win (dv-root-window dv))) (setq r-win (dirvish--create-root-window dv)) (with-selected-window r-win