Subject: bug#67161: closed (Re: bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length')

From: [email-masked] (GNU bug Tracking System)
Date: Sat, 25 Nov 2023 10:53:02 +0000

Your bug report

#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length'

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
67161: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=67161
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length'
From: Eli Zaretskii <[email-masked]>
To: Liu Hui <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked]
Date: Sat, 25 Nov 2023 12:52:34 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

> From: Liu Hui <[email-masked]>
> Date: Wed, 22 Nov 2023 13:41:18 +0800
> Cc: [email-masked], [email-masked], [email-masked]
> 
> > Therefore, I would like to change
> >
> >   (put-text-property ell-beg (point) 'invisible 'dired-filename-hide)
> >
> > to
> >
> >   (let ((ov (make-overlay ell-beg (point))))
> >     (overlay-put ov 'invisible 'dired-filename-hide)
> >     (overlay-put ov 'isearch-open-invisible t)
> >     (overlay-put ov 'evaporate t))
> >
> > in the attached patch, then text in hidden part can be matched
> > regardless of search-invisible being open or t. It also has a bonus
> > that hidden text can be revealed during isearch.
> 
> Since there is no objection to using overlay, I have updated the patch
> accordingly with additional explanation. Thanks.

Thanks, installed on the master branch, and closing the bug.

Please in the future always mention the bug number as part of the
commit log message, when the bug number is known.

Subject: 30.0.50; [PATCH] Add option `dired-filename-display-length'
From: Liu Hui <[email-masked]>
To: [email-masked]
Date: Tue, 14 Nov 2023 17:52:58 +0800
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi,

The attached patch implements the feature of controlling the display
length of filename in dired buffers.

When setting this option to `window', the long filename is shortened
by hiding the middle part to ensure that the whole line needs not to
be wrapped. The option can also be set to an integer, meaning the
maximum display length of filename. For users who turn on line
truncation, this feature can display the end part including the file
extension, which I think is convenient.

Best,

--
Liu Hui
From 43a72585ff11b342cb48f454b4466ef5ed4b6f9b Mon Sep 17 00:00:00 2001
From: Liu Hui <[email-masked]>
Date: Tue, 14 Nov 2023 16:14:12 +0800
Subject: [PATCH] Add option `dired-filename-display-length'

* lisp/dired.el (dired-filename-display-length):
(dired-filename-hiding-ellipsis): New options.
(dired-insert-set-properties): Set invisibility spec for long
filenames.
(dired--get-filename-display-length)
(dired-filename-update-invisibility-spec): New functions.
(dired-mode): Add filename invisibility spec.
* lisp/wdired.el (wdired-change-to-wdired-mode)
(wdired-change-to-dired-mode): Update filename invisibility spec.
---
 lisp/dired.el  | 124 +++++++++++++++++++++++++++++++++----------------
 lisp/wdired.el |   2 +
 2 files changed, 85 insertions(+), 41 deletions(-)

diff --git a/lisp/dired.el b/lisp/dired.el
index 8919d2c223f..b650f15e28f 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -517,6 +517,21 @@ dired-hide-details-preserved-columns
   :type '(repeat integer)
   :version "30.1")
 
+(defcustom dired-filename-display-length nil
+  "If non-nil, hide middle part of long filenames in Dired buffers.
+If the value is the symbol `window', then filenames are shortened
+to not exceed the right edge of current window.  Otherwise, it
+should be an integer representing the maximum filename length."
+  :type '(choice (integer :tag "Full" nil)
+                 (const   :tag "Window" window)
+                 (integer :tag "Integer"))
+  :version "30.1")
+
+(defcustom dired-filename-hiding-ellipsis "…"
+  "String to indicate filename hiding."
+  :type 'string
+  :version "30.1")
+
 
 ;;; Internal variables
 
@@ -1903,48 +1918,62 @@ dired-insert-set-properties
   "Add various text properties to the lines in the region, from BEG to END."
   (save-excursion
     (goto-char beg)
-    (while (< (point) end)
-      (ignore-errors
-	(if (not (dired-move-to-filename))
-	    (unless (or (looking-at-p "^$")
-			(looking-at-p dired-subdir-regexp))
-	      (put-text-property (line-beginning-position)
-				 (1+ (line-end-position))
-				 'invisible 'dired-hide-details-information))
-	  (save-excursion
-            (let ((end (1- (point)))
-                  (opoint (goto-char (1+ (pos-bol))))
-                  (i 0))
-              (put-text-property opoint end 'invisible 'dired-hide-details-detail)
-              (while (re-search-forward "[^ ]+" end t)
-                (when (member (cl-incf i) dired-hide-details-preserved-columns)
-                  (put-text-property opoint (point) 'invisible nil))
-                (setq opoint (point)))))
-          (let ((beg (point)) (end (save-excursion
-	                             (dired-move-to-end-of-filename)
-	                             (1- (point)))))
-            (if dired-click-to-select-mode
-                (put-text-property beg end 'keymap
-                                   dired-click-to-select-map)
-              (when (and dired-mouse-drag-files (fboundp 'x-begin-drag))
-                (put-text-property beg end 'keymap
-                                   dired-mouse-drag-files-map)))
-	    (add-text-properties
-	     beg (1+ end)
-	     `(mouse-face
-	       highlight
-	       dired-filename t
-	       help-echo ,(if dired-click-to-select-mode
-                              "mouse-2: mark or unmark this file"
-                            (if (and dired-mouse-drag-files
-                                     (fboundp 'x-begin-drag))
-                                "down-mouse-1: drag this file to another program
+    (let ((ell-len (string-width dired-filename-hiding-ellipsis))
+          maxlen filename-col)
+      (while (< (point) end)
+        (ignore-errors
+	  (if (not (dired-move-to-filename))
+	      (unless (or (looking-at-p "^$")
+			  (looking-at-p dired-subdir-regexp))
+	        (put-text-property (line-beginning-position)
+				   (1+ (line-end-position))
+				   'invisible 'dired-hide-details-information))
+	    (save-excursion
+              (let ((end (1- (point)))
+                    (opoint (goto-char (1+ (pos-bol))))
+                    (i 0))
+                (put-text-property opoint end 'invisible 'dired-hide-details-detail)
+                (while (re-search-forward "[^ ]+" end t)
+                  (when (member (cl-incf i) dired-hide-details-preserved-columns)
+                    (put-text-property opoint (point) 'invisible nil))
+                  (setq opoint (point)))))
+            (let ((beg (point)) (end (save-excursion
+	                               (dired-move-to-end-of-filename)
+	                               (1- (point)))))
+              (if dired-click-to-select-mode
+                  (put-text-property beg end 'keymap
+                                     dired-click-to-select-map)
+                (when (and dired-mouse-drag-files (fboundp 'x-begin-drag))
+                  (put-text-property beg end 'keymap
+                                     dired-mouse-drag-files-map)))
+              (when dired-filename-display-length
+                (let ((len (string-width (buffer-substring beg (1+ end))))
+                      ell-beg)
+                  (or maxlen (setq maxlen (dired--get-filename-display-length)))
+                  (when (and (integerp maxlen) (> len maxlen (+ ell-len 2)))
+                    (or filename-col (setq filename-col (current-column)))
+                    (move-to-column (+ filename-col (/ maxlen 2)))
+                    (setq ell-beg (point))
+                    (move-to-column (+ filename-col (/ maxlen 2)
+                                       (- len maxlen) ell-len))
+                    (put-text-property
+                     ell-beg (point) 'invisible 'dired-filename-hide))))
+	      (add-text-properties
+	       beg (1+ end)
+	       `(mouse-face
+	         highlight
+	         dired-filename t
+	         help-echo ,(if dired-click-to-select-mode
+                                "mouse-2: mark or unmark this file"
+                              (if (and dired-mouse-drag-files
+                                       (fboundp 'x-begin-drag))
+                                  "down-mouse-1: drag this file to another program
 mouse-2: visit this file in other window"
-                              "mouse-2: visit this file in other window"))))
-	    (when (< (+ end 5) (line-end-position))
-	      (put-text-property (+ end 5) (line-end-position)
-			         'invisible 'dired-hide-details-link)))))
-      (forward-line 1))))
+                                "mouse-2: visit this file in other window"))))
+	      (when (< (+ end 5) (line-end-position))
+	        (put-text-property (+ end 5) (line-end-position)
+			           'invisible 'dired-hide-details-link)))))
+        (forward-line 1)))))
 
 (defun dired--make-directory-clickable ()
   (save-excursion
@@ -1976,6 +2005,12 @@ dired--make-directory-clickable
                           "RET" click))))
           (setq segment-start (point)))))))
 
+(defun dired--get-filename-display-length ()
+  "Return maximum display length of filename."
+  (if (integerp dired-filename-display-length)
+      dired-filename-display-length
+    (- (window-max-chars-per-line) 2 (current-column))))
+
 
 ;;; Reverting a dired buffer
 
@@ -2617,6 +2652,7 @@ dired-mode
 	mode-line-buffer-identification
 	(propertized-buffer-identification "%17b"))
   (add-to-invisibility-spec '(dired . t))
+  (dired-filename-update-invisibility-spec)
   ;; Ignore dired-hide-details-* value of invisible text property by default.
   (when (eq buffer-invisibility-spec t)
     (setq buffer-invisibility-spec (list t)))
@@ -3106,6 +3142,12 @@ dired-hide-details-update-invisibility-spec
 
 ;;; Functions to hide/unhide text
 
+(defun dired-filename-update-invisibility-spec ()
+  (funcall (if (derived-mode-p 'dired-mode)
+               'add-to-invisibility-spec
+             'remove-from-invisibility-spec)
+           `(dired-filename-hide . ,dired-filename-hiding-ellipsis)))
+
 (defun dired--find-hidden-pos (start end)
   (text-property-any start end 'invisible 'dired))
 
diff --git a/lisp/wdired.el b/lisp/wdired.el
index 079d93d6011..5d50a574290 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -261,6 +261,7 @@ wdired-change-to-wdired-mode
   (add-function :override (local 'revert-buffer-function) #'wdired-revert)
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
+  (dired-filename-update-invisibility-spec)
   (run-mode-hooks 'wdired-mode-hook)
   (message "%s" (substitute-command-keys
 		 "Press \\[wdired-finish-edit] when finished \
@@ -456,6 +457,7 @@ wdired-change-to-dired-mode
   (dired-sort-set-mode-line)
   (dired-advertise)
   (dired-hide-details-update-invisibility-spec)
+  (dired-filename-update-invisibility-spec)
   (remove-hook 'kill-buffer-hook #'wdired-check-kill-buffer t)
   (remove-hook 'before-change-functions #'wdired--before-change-fn t)
   (remove-hook 'after-change-functions #'wdired--restore-properties t)
-- 
2.25.1