branch: elpa/dirvish commit 5ec7c66a4e8389be8712abd7b8e83d8b43f9a09d Author: Alex Lu <hellosimon1...@hotmail.com> Commit: Alex Lu <hellosimon1...@hotmail.com>
feat: add `dirvish-special-preview-mode` and `dirvish-misc-mode` Closes #184 Closes #195 --- dirvish-widgets.el | 5 +- dirvish.el | 78 +++++++++++++------------- docs/CUSTOMIZING.org | 155 +++++++++++++++++++++++++++++++-------------------- 3 files changed, 135 insertions(+), 103 deletions(-) diff --git a/dirvish-widgets.el b/dirvish-widgets.el index 168845bcfc..464365e2d6 100644 --- a/dirvish-widgets.el +++ b/dirvish-widgets.el @@ -727,9 +727,8 @@ Require: `zipinfo' (executable) Require: `tar' (executable)" :require (dirvish-zipinfo-program dirvish-tar-program) (cond ((equal ext "zip") `(shell . (,dirvish-zipinfo-program ,file))) - ;; Emacs source code files - ((string-suffix-p ".el.gz" file) - (dirvish--find-file-temporarily file)) + ;; Emacs source code files, let `fallback' handles it + ((string-suffix-p ".el.gz" file)) ((member ext '("tar" "zst" "bz2" "bz" "gz" "xz" "tgz")) `(shell . (,dirvish-tar-program "-tvf" ,file))))) diff --git a/dirvish.el b/dirvish.el index 1b6d9156e3..3ce350b143 100644 --- a/dirvish.el +++ b/dirvish.el @@ -258,25 +258,19 @@ input for `dirvish-redisplay-debounce' seconds." (cl-defgeneric dirvish-build-cache () "Build cache for current directory." nil) (defcustom dirvish-after-revert-hook '(dirvish-clean-cache) - "Executed after `revert-buffer'." + "Functions called after running `revert-buffer' command." :group 'dirvish :type 'hook) (defcustom dirvish-setup-hook '(dirvish-build-cache) - "Executed after the Dired buffer is showed up." + "Functions called when directory data for the root buffer is ready." :group 'dirvish :type 'hook) (defcustom dirvish-find-entry-hook '(dirvish-insert-entry-h) - "Executed after finding a entry." + "Functions called before a Dired buffer is displayed." :group 'dirvish :type 'hook) (defcustom dirvish-preview-setup-hook nil - "Functions called after a preview buffer gets placed in the preview window. -The value should be a list of functions take no argument, and they are -called with the preview window temporarily selected." - :group 'dirvish :type 'hook) - -(defcustom dirvish-util-buffer-init-hook nil - "Functions called in the mode-line / header-line buffer upon initialization." + "Functions called in the file preview buffer." :group 'dirvish :type 'hook) ;;;; Internal variables @@ -838,6 +832,7 @@ buffer, it defaults to filename under the cursor when it is nil." (with-current-buffer (dirvish--util-buffer "temp") (let ((text (gethash file (dv-preview-hash dv))) info) (with-silent-modifications + (setq buffer-read-only t) (if text (insert text) (insert-file-contents file nil 0 dirvish-preview-large-file-threshold) @@ -859,6 +854,7 @@ buffer, it defaults to filename under the cursor when it is nil." (error (setq info (error-message-string err)))) (set-frame-parameter nil 'dv-preview-last (current-buffer)) (if info (prog1 `(info . ,info) (dirvish--kill-buffer (current-buffer))) + (run-hooks 'dirvish-preview-setup-hook) (unless text (puthash file (buffer-string) (dv-preview-hash dv))) `(buffer . ,(current-buffer)))))) @@ -937,18 +933,12 @@ When PROC finishes, fill preview buffer with process result." (str (with-current-buffer (process-buffer proc) (buffer-string)))) (if (eq cmd-type 'shell) (with-current-buffer (dirvish--util-buffer 'shell dv nil t) - (fundamental-mode) (setq mode-line-format nil header-line-format nil) (let (buffer-read-only) (erase-buffer) (remove-overlays) (insert str)) - (add-hook 'window-scroll-functions #'dirvish-apply-ansicolor-h nil t) (dirvish-apply-ansicolor-h nil (point-min))) (with-current-buffer (dirvish--util-buffer 'dired dv nil t) - (dirvish-directory-view-mode) - (setq mode-line-format nil header-line-format nil) (font-lock-mode 1) (let (buffer-read-only) (erase-buffer) (remove-overlays) (insert str)) (setq-local dired-subdir-alist - (list (cons (car (dv-index dv)) (point-min-marker))) - font-lock-defaults - '(dired-font-lock-keywords t nil nil beginning-of-line)))) + (list (cons (car (dv-index dv)) (point-min-marker)))))) (kill-buffer (process-buffer proc)))) (defun dirvish--run-shell-for-preview (dv recipe) @@ -981,10 +971,8 @@ When PROC finishes, fill preview buffer with process result." (buf (cl-loop for fn in fns for rcp = (funcall fn index ext window dv) thereis (and rcp (dirvish-preview-dispatch rcp dv))))) - (with-current-buffer buf (setq buffer-read-only t)) (setq-local other-window-scroll-buffer buf) (set-window-buffer window buf) - (with-selected-window window (run-hooks 'dirvish-preview-setup-hook)) (unless (memq buf orig-bufs) (push buf (dv-preview-buffers dv))))) ;;;; Attributes @@ -1237,13 +1225,8 @@ LEVEL is the depth of current window." (dirvish-prop :dv (dv-id dv)) (dirvish-prop :remote (file-remote-p dir)) (puthash dir str (dv-parent-hash dv)) - (erase-buffer) - (setq mode-line-format nil header-line-format nil) - (save-excursion (insert str)) - (setq-local dired-subdir-alist (list (cons dir (point-min-marker))) - font-lock-defaults - '(dired-font-lock-keywords t nil nil beginning-of-line)) - (font-lock-mode 1) + (let (buffer-read-only) (erase-buffer) (save-excursion (insert str))) + (setq-local dired-subdir-alist (list (cons dir (point-min-marker)))) (dired-goto-file-1 (file-name-nondirectory index) index (point-max)) (dirvish--maybe-toggle-cursor '(box . 0)) ; always hide cursor in parents (dirvish-prop :attrs (dirvish--attrs-expand icon)) @@ -1278,19 +1261,16 @@ LEVEL is the depth of current window." (defun dirvish--init-util-buffers (dv) "Initialize util buffers for DV." (with-current-buffer (dirvish--util-buffer 'preview dv nil t) - (fundamental-mode) (setq mode-line-format nil header-line-format nil)) + (dirvish-special-preview-mode)) + (with-current-buffer (dirvish--util-buffer 'shell dv nil t) + (dirvish-special-preview-mode) + (add-hook 'window-scroll-functions #'dirvish-apply-ansicolor-h nil t)) + (with-current-buffer (dirvish--util-buffer 'dired dv nil t) + (dirvish-directory-view-mode)) (with-current-buffer (dirvish--util-buffer 'header dv) - (dirvish-prop :dv (dv-id dv)) - (setq-local face-remapping-alist '((header-line-inactive header-line))) - (setq cursor-type nil window-size-fixed 'height - mode-line-format nil header-line-format nil) - (run-hooks 'dirvish-util-buffer-init-hook)) + (dirvish-misc-mode) (dirvish-prop :dv (dv-id dv))) (with-current-buffer (dirvish--util-buffer 'footer dv) - (dirvish-prop :dv (dv-id dv)) - (setq-local face-remapping-alist '((mode-line-inactive mode-line))) - (setq cursor-type nil window-size-fixed 'height - mode-line-format nil header-line-format nil) - (run-hooks 'dirvish-util-buffer-init-hook))) + (dirvish-misc-mode) (dirvish-prop :dv (dv-id dv)))) (defun dirvish--dir-data-async (dir buffer &optional inhibit-setup) "Asynchronously fetch metadata for DIR, stored locally in BUFFER. @@ -1406,9 +1386,27 @@ INHIBIT-SETUP is non-nil." dirvish-default-layout)) (dirvish-find-entry-a dir))))) -(define-derived-mode dirvish-directory-view-mode - fundamental-mode "Dirvish-directory-view" - "Major mode for dirvish parent buffers." +;;;; Major modes + +(define-derived-mode dirvish-directory-view-mode special-mode + "Major mode for parent directory and directory preview buffer." + (setq mode-line-format nil header-line-format nil + font-lock-defaults + '(dired-font-lock-keywords t nil nil beginning-of-line)) + (font-lock-mode 1) + :group 'dirvish :interactive nil) + +(define-derived-mode dirvish-special-preview-mode special-mode + "Major mode for info, shell command output and non-text file preview buffer." + (setq mode-line-format nil header-line-format nil) + :group 'dirvish :interactive nil) + +(define-derived-mode dirvish-misc-mode special-mode + "Major mode for mode/header-line and other special buffers." + (setq face-remapping-alist '((header-line-inactive header-line) + (mode-line-inactive mode-line)) + cursor-type nil window-size-fixed 'height + mode-line-format nil header-line-format nil) :group 'dirvish :interactive nil) ;;;; Commands diff --git a/docs/CUSTOMIZING.org b/docs/CUSTOMIZING.org index fa0b1d5151..efff09b117 100644 --- a/docs/CUSTOMIZING.org +++ b/docs/CUSTOMIZING.org @@ -82,16 +82,6 @@ leaving the last index buffer open, set ~dirvish-reuse-session~ to =nil=. See: [[https://github.com/alexluigit/dirvish/discussions/102#discussioncomment-3205349][the rationale behind buffer management in Dirvish]] -** Multiple window layouts - -A session with a /layout/ means it has a companion preview window and possibly -one or more parent windows. The session layout can be toggled, namely turn -on/off the preview and parent windows, using ~dirvish-layout-toggle~. - -You can define multiple layouts in ~dirvish-layout-recipes~ and cycle them through -~dirvish-layout-switch~, by doing so you can have various pane-ratio for different -tasks. For example, 1:3 for image preview, 1:3:5 for general file preview, etc. - ** Hooks Apart from the hooks provided by Dired, Dirvish got some additions. @@ -99,15 +89,11 @@ Apart from the hooks provided by Dired, Dirvish got some additions. * ~dirvish-setup-hook~: Functions called when directory data for the root buffer is ready. - * ~dirvish-after-revert-hook~: Functions called after =revert-buffer= command. + * ~dirvish-after-revert-hook~: Functions called after running =revert-buffer= command. * ~dirvish-find-entry-hook~: Functions called before a Dired buffer is displayed. - * ~dirvish-preview-setup-hook~: Functions called after a preview buffer gets - placed in the preview window. - - * ~dirvish-util-buffer-init-hook~: Functions called in the mode/header-line buffer - upon initialization. + * ~dirvish-preview-setup-hook~: Functions called in the regular preview buffer. ** =find-dired= integration @@ -141,17 +127,33 @@ To achieve this, the only thing you need to do is put these symbols into ~dirvish-attributes~ like this (order doesn't matter): #+begin_src emacs-lisp - ;; Don't worry, Dirvish is still performant even if you enable all these attributes - (setq dirvish-attributes - '(vc-state subtree-state all-the-icons collapse git-msg file-time file-size)) +;; Don't worry, Dirvish is still performant even if you enable all these attributes +(setq dirvish-attributes + '(vc-state subtree-state all-the-icons collapse git-msg file-time file-size)) #+end_src +* Multile layout recipies + +In Dirvish, a Dirvish window with an associated layout includes a preview window +and, optionally, one or more parent windows. You can toggle the visibility of +the session layout (preview and parent windows) using ~dirvish-layout-toggle~. + +You can define multiple layouts in ~dirvish-layout-recipes~ and cycle through them +with ~dirvish-layout-switch~. This allows you to have different pane ratios for +various tasks. For example, use a 1:3 ratio for image previews or a 1:3:5 ratio +for general file previews. + * Mode line | Header line -Dirvish uses mode line and header line to display additional information for the -current directory or session. The mode line only span the directory panes by -default, to make them span all panes, just set ~dirvish-use-mode-line~ to ~global~. -Setting the same option to /nil/ hides the mode line in dirvish buffers. +Dirvish displays information about the current directory or session in the mode +line and header line. These features are enabled by default and include +sensible default configurations. + +** Changing its placement, height and format + +The mode line only span the directory panes by default, to make them span all +panes, just set ~dirvish-use-mode-line~ to ~global~. Setting the same option to /nil/ +hides the mode line in dirvish buffers. To configure the content in the mode line, put the segments you wanted into ~dirvish-mode-line-format~. There is also ~dirvish-mode-line-height~ for you to set @@ -163,27 +165,34 @@ The header line can be customized in the same way with ~dirvish-use-header-line~ The ~dired-switches-in-mode-line~ option is ignored in Dirvish. #+begin_src emacs-lisp - ;; Placement - ;; (setq dirvish-use-header-line nil) ; hide header line (show the classic dired header) - ;; (setq dirvish-use-mode-line nil) ; hide mode line - (setq dirvish-use-header-line 'global) ; make header line span all panes - - ;; Height - ;;; '(25 . 35) means - ;;; - height in single window sessions is 25 - ;;; - height in full-frame sessions is 35 - (setq dirvish-header-line-height '(25 . 35)) - (setq dirvish-mode-line-height 25) ; shorthand for '(25 . 25) - - ;; Segments - ;;; 1. the order of segments *matters* here - ;;; 2. it's ok to place raw string inside - (setq dirvish-header-line-format - '(:left (path) :right (free-space)) - dirvish-mode-line-format - '(:left (sort file-time " " file-size symlink) :right (omit yank index))) +;; Placement +;; (setq dirvish-use-header-line nil) ; hide header line (show the classic dired header) +;; (setq dirvish-use-mode-line nil) ; hide mode line +(setq dirvish-use-header-line 'global) ; make header line span all panes + +;; Height +;;; '(25 . 35) means +;;; - height in single window sessions is 25 +;;; - height in full-frame sessions is 35 +(setq dirvish-header-line-height '(25 . 35)) +(setq dirvish-mode-line-height 25) ; shorthand for '(25 . 25) + +;; Segments +;;; 1. the order of segments *matters* here +;;; 2. it's ok to place raw strings in it as separators +(setq dirvish-header-line-format + '(:left (path) :right (free-space)) + dirvish-mode-line-format + '(:left (sort file-time " " file-size symlink) :right (omit yank index))) #+end_src +** Special buffers for displaying mode-line and header-line + +When Dirvish uses a layout that occupies the entire frame, the mode-line and +header-line are displayed in separate buffers and their corresponding +windows. These buffers are initialized with ~dirvish-misc-mode~. To customize the +settings of these buffers, append your configuration to ~dirvish-misc-mode-hook~. + * File preview Dirvish uses different strategies towards various filetypes. You may want to @@ -221,10 +230,6 @@ want to display preview for epub files via packages like =nov=, just remove the (setq dirvish-preview-dispatchers (remove 'epub dirvish-preview-dispatchers)) #+end_src -The =dirvish-preview-dired-sync-omit= option allows ~dired~ preview buffers to sync -your =dired-omit-mode= and its settings from the root window, it is turned off by -default. - Some of preview dispatchers, such as ~image~, generate cache images to improve the preview experience. Every time you enter a directory, Dirvish scans the the content of that directory and computes the fileset of the directory that @@ -232,14 +237,52 @@ requires cache image generation, the corresponding caches are generated later when Emacs is idle. You can tweak the behavior of auto caching or turn off this feature completely -by customizing the ~dirvish-media-auto-cache-threshold~ option. +by customizing the ~dirvish-media-auto-cache-threshold~ option. If you don't want +the media properties displayed in the preview buffer, you can turn off +~dirvish-show-media-properties~. -If you don't want the media properties displayed in the preview buffer, you can -turn off ~dirvish-show-media-properties~. +The ~dirvish-preview-dired-sync-omit~ option allows ~dired~ preview buffers to sync +your =dired-omit-mode= and its settings from the root window, it is turned off by +default. -Here are several examples to extend the preview capabilities of Dirvish. +Dirvish also offers these user options to customize its preview behavior. Refer +to the docstrings of these options for detailed information. -** Preview PDF files with generated thumbnail + * ~dirvish-preview-buffers-max-count~ + * ~dirvish-preview-disabled-exts~ + * ~dirvish-preview-environment~ + * ~dirvish-preview-large-file-threshold~ + +** Customizations for preview buffers + +There are several types of buffer can be placed in the preview window in Dirvish. + +*** Directory files listing + +The ~dired~ preview dispatcher creates buffers in ~dirvish-directory-view-mode~. +This mode is also used for the parent directory listing buffers. Consequently, +a single hook can configure both the parent buffer and the dired preview buffer. + +#+begin_src emacs-lisp +(add-hook 'dirvish-directory-view-mode-hook #'diredfl-mode) +#+end_src + +*** Regular files with certain major mode + +When a regular file with certain major mode is being previewed, you can change +its settings by the ~dirvish-preview-setup-hook~. + +*** Special preview buffer + +A ~dirvish-special-preview-mode~ buffer is displayed in the preview window for all +the rest filetypes. This includes cases for shell command output, error/warning +info display, image and metadata and etc. + +** Other use cases + +Here are several examples on how to extend the preview capabilities of Dirvish. + +*** Preview PDF files with generated thumbnail The default ~pdf~ preview method uses =pdf-tools= to open the document, which works fine for most of the pdf documents, but it feels sluggish for some documents @@ -257,7 +300,7 @@ Note: this dispatcher requires the =pdftoppm= executable. (cl-substitute 'pdf-preface 'pdf dirvish-preview-dispatchers)) #+end_src -** Preview directory using ~eza~ command +*** Preview directory using ~eza~ command Let's assume you don't like the default directory preview results provided by Dired, you can create a directory previewer that utilizes the ~eza~ command: @@ -285,14 +328,6 @@ doesn't have good integration with the =ansi-color= package. [[https://user-images.githubusercontent.com/16313743/158852998-ebf4f1f7-7e12-450d-bb34-ce04ac22309c.png][https://user-images.githubusercontent.com/16313743/158852998-ebf4f1f7-7e12-450d-bb34-ce04ac22309c.png]] -** User options - - * ~dirvish-preview-buffers-max-count~ - * ~dirvish-preview-disabled-exts~ - * ~dirvish-preview-environment~ - * ~dirvish-preview-dired-sync-omit~ - * ~dirvish-large-file-truncate-threshold~ - * Sample config ** Dirvish