emacs-elpa-diffs
[Top][All Lists]
Advanced

[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"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]