[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/dired-preview 076a5fcc0f 1/3: dired-preview: Add suppor
From: |
ELPA Syncer |
Subject: |
[elpa] externals/dired-preview 076a5fcc0f 1/3: dired-preview: Add support for large file preview |
Date: |
Thu, 5 Oct 2023 03:57:58 -0400 (EDT) |
branch: externals/dired-preview
commit 076a5fcc0fa2e85277943f7966c82c9cac1d4b41
Author: Karthik Chikmagalur <karthikchikmagalur@gmail.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>
dired-preview: Add support for large file preview
* dired-preview.el (dired-preview--kill-large-buffers,
dired-preview--preview-p, dired-preview--add-to-previews,
dired-preview--chunk-size, dired-preview--find-large-file,
dired-preview--add-truncation-message,
dired-preview--large-files-alist, dired-preview--dispatch-file,
dired-preview--display-buffer): Preview files larger than
`dired-preview-max-size' by reading in only a leading chunk of
data. The size of this chunk is specified by
`dired-preview--chunk-size'.
The function `dired-preview--dispatch-file' is used to determine
how a file should be previewed. Currently it distinguishes
between large files and not-large files, but this will be expanded
in the future to handle media previews, etc.
The function `dired-preview--find-large-file' is responsible for
setting up the preview. The corresponding buffer is in
fundamental mode, set to read-only mode with undo disabled. The
function `dired-preview--add-truncation-message' inserts a message
at the end of the previewed chunk.
In this process,
- the large file cannot be marked as being visited,
- `delayed-mode-hooks' is nil, and
- the buffer is modified,
thus we cannot use the criteria used for regular previews to find
buffers showing previews of large files. We instead maintain a
separate list, `dired-preview--large-files-alist', to track them.
---
dired-preview.el | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 70 insertions(+), 4 deletions(-)
diff --git a/dired-preview.el b/dired-preview.el
index 8beb5d0644..0d33126131 100644
--- a/dired-preview.el
+++ b/dired-preview.el
@@ -59,6 +59,8 @@
(require 'dired)
(require 'seq)
+(eval-when-compile
+ (require 'subr-x))
(defgroup dired-preview nil
"Automatically preview file at point in Dired."
@@ -94,9 +96,17 @@ details."
:group 'dired-preview
:type 'number)
+(defcustom dired-preview-chunk-size 10240
+ "Size in bytes to read from large files."
+ :group 'dired-preview
+ :type 'integer)
+
(defvar dired-preview--buffers nil
"List with buffers of previewed files.")
+(defvar dired-preview--large-files-alist nil
+ "Alist mapping previewed large files to buffer names.")
+
(defun dired-preview--get-buffers ()
"Return buffers that show previews."
(seq-filter #'buffer-live-p dired-preview--buffers))
@@ -139,6 +149,15 @@ until it drops below this number.")
buffers))
(setq dired-preview--buffers (delq nil (nreverse buffers)))))
+(defun dired-preview--kill-large-buffers ()
+ "Kill buffers previewing large files."
+ (mapc (lambda (pair)
+ (let ((buffer (cdr pair)))
+ (and (bufferp buffer)
+ (kill-buffer buffer))))
+ dired-preview--large-files-alist)
+ (setq dired-preview--large-files-alist nil))
+
(defun dired-preview--get-windows ()
"Return windows that show previews."
(seq-filter #'dired-preview--window-parameter-p (window-list)))
@@ -186,6 +205,53 @@ See user option `dired-preview-ignored-extensions-regexp'."
(kill-local-variable 'delayed-mode-hooks)
(remove-hook 'post-command-hook #'dired-preview--run-mode-hooks :local))))
+(defun dired-preview--dispatch-file (file)
+ "Decide how to preview FILE.
+
+Return the preview buffer."
+ (cond
+ ((dired-preview--file-large-p file)
+ (dired-preview--find-large-file file))
+ (t
+ (dired-preview--find-file-no-select file))))
+
+(defun dired-preview--find-large-file (file)
+ "Read part of FILE with appropriate settings.
+
+The size of the leading chunk is specified by
+`dired-preview-chunk-size'."
+ (let ((inhibit-message t)
+ (enable-dir-local-variables nil)
+ (enable-local-variables :safe)
+ (non-essential t)
+ (delay-mode-hooks t))
+ (if-let* ((buffer (or (get-file-buffer file)
+ (find-buffer-visiting file)
+ (alist-get file dired-preview--large-files-alist
+ nil nil #'equal))))
+ buffer ; Buffer is already being visited, we can reuse it
+ (with-current-buffer (create-file-buffer file)
+ ;; We create a buffer with a partial preview
+ (buffer-disable-undo)
+ (insert-file-contents file nil 1 dired-preview-chunk-size 'replace)
+ (when (and (eq buffer-file-coding-system 'no-conversion)
+ dired-preview-binary-as-hexl)
+ (hexl-mode))
+ (dired-preview--add-truncation-message)
+ (read-only-mode t)
+ ;; Because this buffer is not marked as visiting FILE, we need to keep
+ ;; track of it ourselves.
+ (setf (alist-get file dired-preview--large-files-alist
+ nil nil 'equal)
+ (current-buffer))))))
+
+(defun dired-preview--add-truncation-message ()
+ "Add a message indicating that the previewed file is truncated."
+ (let ((end-ov (make-overlay (1- (point-max)) (point-max))))
+ (overlay-put
+ end-ov 'display
+ (propertize "\n--PREVIEW TRUNCATED--" 'face 'shadow))))
+
(defun dired-preview--find-file-no-select (file)
"Call `find-file-noselect' on FILE with appropriate settings."
;; NOTE: I learnt about `non-essential' and `delay-mode-hooks' from
@@ -205,7 +271,7 @@ Always return FILE buffer."
(let ((buffer (find-buffer-visiting file)))
(if (buffer-live-p buffer)
buffer
- (setq buffer (dired-preview--find-file-no-select file)))
+ (setq buffer (dired-preview--dispatch-file file)))
(with-current-buffer buffer
(add-hook 'post-command-hook #'dired-preview--run-mode-hooks nil :local))
(add-to-list 'dired-preview--buffers buffer)
@@ -263,7 +329,8 @@ aforementioned user option."
"Kill preview buffers and delete their windows."
(dired-preview--cancel-timer)
(dired-preview--delete-windows)
- (dired-preview--kill-buffers))
+ (dired-preview--kill-buffers)
+ (dired-preview--kill-large-buffers))
(defun dired-preview--close-previews-outside-dired ()
"Call `dired-preview--close-previews' if BUFFER is not in Dired mode."
@@ -293,8 +360,7 @@ Only do it with the current major mode is Dired."
(and (file-regular-p file)
(not (file-directory-p file))
(not (dired-preview--file-displayed-p file))
- (not (dired-preview--file-ignored-p file))
- (not (dired-preview--file-large-p file))))
+ (not (dired-preview--file-ignored-p file))))
(defun dired-preview-start (file)
"Preview instantly when invoke dired"