* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' @ 2023-11-14 9:52 Liu Hui 2023-11-14 13:26 ` Eli Zaretskii 2023-11-15 15:54 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 37+ messages in thread From: Liu Hui @ 2023-11-14 9:52 UTC (permalink / raw) To: 67161 [-- Attachment #1: Type: text/plain, Size: 508 bytes --] 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 [-- Attachment #2: 0001-Add-option-dired-filename-display-length.patch --] [-- Type: text/x-patch, Size: 8964 bytes --] From 43a72585ff11b342cb48f454b4466ef5ed4b6f9b Mon Sep 17 00:00:00 2001 From: Liu Hui <liuhui1610@gmail.com> 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") + \f ;;; 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)))) + \f ;;; 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 \f ;;; 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 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-14 9:52 bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' Liu Hui @ 2023-11-14 13:26 ` Eli Zaretskii 2023-11-15 10:04 ` Liu Hui 2023-11-15 15:54 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-14 13:26 UTC (permalink / raw) To: Liu Hui; +Cc: 67161 > From: Liu Hui <liuhui1610@gmail.com> > Date: Tue, 14 Nov 2023 17:52:58 +0800 > > 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. Thanks. > +(defcustom dired-filename-hiding-ellipsis "…" We shouldn't use non-ASCII characters by default, without checking they can be displayed. > + (let ((ell-len (string-width dired-filename-hiding-ellipsis)) > + maxlen filename-col) > + (while (< (point) end) > + (ignore-errors > + (if (not (dired-move-to-filename)) Did you consider using truncate-string-to-width here? ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-14 13:26 ` Eli Zaretskii @ 2023-11-15 10:04 ` Liu Hui 2023-11-15 12:32 ` Eli Zaretskii 2023-11-15 18:06 ` Drew Adams 0 siblings, 2 replies; 37+ messages in thread From: Liu Hui @ 2023-11-15 10:04 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 67161 Eli Zaretskii <eliz@gnu.org> 于2023年11月14日周二 21:26写道: > > +(defcustom dired-filename-hiding-ellipsis "…" > > We shouldn't use non-ASCII characters by default, without checking > they can be displayed. Thanks for pointing this out. I think it can be changed to "...". > > + (let ((ell-len (string-width dired-filename-hiding-ellipsis)) > > + maxlen filename-col) > > + (while (< (point) end) > > + (ignore-errors > > + (if (not (dired-move-to-filename)) > > Did you consider using truncate-string-to-width here? I'm not sure what you mean. Using truncate-string-to-width to shorten string or using truncate-string-ellipsis to obtain the ellipsis? The problem of truncate-string-to-width is that it produces a new string. I want to avoid modifying the buffer text since it would break other dired functionalities. Therefore this patch only changes the display instead of the underlying text. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-15 10:04 ` Liu Hui @ 2023-11-15 12:32 ` Eli Zaretskii 2023-11-16 10:07 ` Liu Hui 2023-11-15 18:06 ` Drew Adams 1 sibling, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-15 12:32 UTC (permalink / raw) To: Liu Hui, Stefan Kangas, Stefan Monnier; +Cc: 67161 > From: Liu Hui <liuhui1610@gmail.com> > Date: Wed, 15 Nov 2023 18:04:13 +0800 > Cc: 67161@debbugs.gnu.org > > Eli Zaretskii <eliz@gnu.org> 于2023年11月14日周二 21:26写道: > > > > +(defcustom dired-filename-hiding-ellipsis "…" > > > > We shouldn't use non-ASCII characters by default, without checking > > they can be displayed. > > Thanks for pointing this out. I think it can be changed to "...". I actually wonder why we need it as a defcustom. If you use truncate-string-ellipsis, you will get both a customizable setting and the correct string for the terminal at hand. Why do we need an extra option? > > > + (let ((ell-len (string-width dired-filename-hiding-ellipsis)) > > > + maxlen filename-col) > > > + (while (< (point) end) > > > + (ignore-errors > > > + (if (not (dired-move-to-filename)) > > > > Did you consider using truncate-string-to-width here? > > I'm not sure what you mean. Using truncate-string-to-width to shorten > string or using truncate-string-ellipsis to obtain the ellipsis? The > problem of truncate-string-to-width is that it produces a new string. > I want to avoid modifying the buffer text since it would break other > dired functionalities. Therefore this patch only changes the display > instead of the underlying text. So you consider using the 'invisible' property a good feature? I actually don't like using it for such purposes, as it gets in the way. But maybe as an opt-in behavior that could be OK? Stefan & Stefan, WDYT? Btw, using string-width might not be the best possibility here. I would recommend string-pixel-width instead (with subsequent division by what default-char-width returns), as that will produce a better approximation, especially on GUI frames. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-15 12:32 ` Eli Zaretskii @ 2023-11-16 10:07 ` Liu Hui 2023-11-16 12:11 ` Eli Zaretskii 0 siblings, 1 reply; 37+ messages in thread From: Liu Hui @ 2023-11-16 10:07 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 67161, Stefan Kangas, Stefan Monnier [-- Attachment #1: Type: text/plain, Size: 1391 bytes --] Eli Zaretskii <eliz@gnu.org> 于2023年11月15日周三 20:32写道: > I actually wonder why we need it as a defcustom. If you use > truncate-string-ellipsis, you will get both a customizable setting and > the correct string for the terminal at hand. Why do we need an extra > option? As Stefan promptly pointed out, the ellipsis defcustom is actually useless because the display of ellipsis is determined by the display table. So I have deleted it in the attached patch. > So you consider using the 'invisible' property a good feature? I > actually don't like using it for such purposes, as it gets in the way. I don't know the drawback of the 'invisible' property. This patch is inspired by dired-hide-details-mode, which uses the property to hide file information. > Btw, using string-width might not be the best possibility here. I > would recommend string-pixel-width instead (with subsequent division > by what default-char-width returns), as that will produce a better > approximation, especially on GUI frames. I agree using pixel width is more accurate, though the approximation based on character width is good enough in most cases. In fact, in addition to string-width, move-to-column also needs to be replaced by a function that moves the point to the character at a specific pixel position. It seems there isn't such a built-in function. [-- Attachment #2: 0001-Add-option-dired-filename-display-length.patch --] [-- Type: text/x-patch, Size: 9908 bytes --] From 991ea588df6799331a7feea9e83493ef0d724096 Mon Sep 17 00:00:00 2001 From: Liu Hui <liuhui1610@gmail.com> Date: Tue, 14 Nov 2023 16:14:12 +0800 Subject: [PATCH] Add option `dired-filename-display-length' * lisp/dired.el (dired-filename-display-length): New option. (dired-insert-set-properties): Set invisibility spec for long filenames. (dired--get-ellipsis-length) (dired--get-filename-display-length) (dired-filename-update-invisibility-spec): New functions. (dired-mode): Add filename invisibility spec. (dired-make-directory-clickable): (dired-kill-when-opening-new-dired-buffer): (dired-hide-details-preserved-columns): Add missing group. * lisp/wdired.el (wdired-change-to-wdired-mode) (wdired-change-to-dired-mode): Update filename invisibility spec. --- lisp/dired.el | 130 +++++++++++++++++++++++++++++++++---------------- lisp/wdired.el | 2 + 2 files changed, 91 insertions(+), 41 deletions(-) diff --git a/lisp/dired.el b/lisp/dired.el index 8919d2c223f..aad77a3dfc0 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -350,6 +350,7 @@ dired-after-readin-hook (defcustom dired-make-directory-clickable t "When non-nil, make the directory at the start of the dired buffer clickable." :version "29.1" + :group 'dired :type 'boolean) (defcustom dired-initial-position-hook nil @@ -429,6 +430,7 @@ dired-mark-region (defcustom dired-kill-when-opening-new-dired-buffer nil "If non-nil, kill the current buffer when selecting a new directory." :type 'boolean + :group 'dired :version "28.1") (defcustom dired-guess-shell-case-fold-search t @@ -515,6 +517,18 @@ dired-movement-style (defcustom dired-hide-details-preserved-columns nil "List of columns which are not hidden in `dired-hide-details-mode'." :type '(repeat integer) + :group 'dired + :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 (const :tag "Full" nil) + (const :tag "Window" window) + (integer :tag "Integer")) + :group 'dired :version "30.1") \f @@ -1903,48 +1917,61 @@ 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 (dired--get-ellipsis-length)) 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 +2003,20 @@ dired--make-directory-clickable "RET" click)))) (setq segment-start (point))))))) +(defun dired--get-ellipsis-length () + "Return length of ellipsis." + (let* ((dt (or (window-display-table) + buffer-display-table + standard-display-table)) + (glyphs (and dt (display-table-slot dt 'selective-display)))) + (if glyphs (length glyphs) (eval-when-compile (length "..."))))) + +(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) 1 (current-column)))) + \f ;;; Reverting a dired buffer @@ -2617,6 +2658,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 +3148,12 @@ dired-hide-details-update-invisibility-spec \f ;;; 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 . t))) + (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 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-16 10:07 ` Liu Hui @ 2023-11-16 12:11 ` Eli Zaretskii 2023-11-18 9:23 ` Liu Hui 0 siblings, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-16 12:11 UTC (permalink / raw) To: Liu Hui; +Cc: 67161, stefankangas, monnier > From: Liu Hui <liuhui1610@gmail.com> > Date: Thu, 16 Nov 2023 18:07:04 +0800 > Cc: Stefan Kangas <stefankangas@gmail.com>, Stefan Monnier <monnier@iro.umontreal.ca>, > 67161@debbugs.gnu.org > > From 991ea588df6799331a7feea9e83493ef0d724096 Mon Sep 17 00:00:00 2001 > From: Liu Hui <liuhui1610@gmail.com> > Date: Tue, 14 Nov 2023 16:14:12 +0800 > Subject: [PATCH] Add option `dired-filename-display-length' > > * lisp/dired.el (dired-filename-display-length): New option. > (dired-insert-set-properties): Set invisibility spec for long > filenames. > (dired--get-ellipsis-length) > (dired--get-filename-display-length) > (dired-filename-update-invisibility-spec): New functions. > (dired-mode): Add filename invisibility spec. > (dired-make-directory-clickable): > (dired-kill-when-opening-new-dired-buffer): > (dired-hide-details-preserved-columns): Add missing group. > * lisp/wdired.el (wdired-change-to-wdired-mode) > (wdired-change-to-dired-mode): Update filename invisibility spec. These changes need a NEWS entry to describe the new option and its effect in short. > diff --git a/lisp/dired.el b/lisp/dired.el > index 8919d2c223f..aad77a3dfc0 100644 > --- a/lisp/dired.el > +++ b/lisp/dired.el > @@ -350,6 +350,7 @@ dired-after-readin-hook > (defcustom dired-make-directory-clickable t > "When non-nil, make the directory at the start of the dired buffer clickable." > :version "29.1" > + :group 'dired > :type 'boolean) > > (defcustom dired-initial-position-hook nil > @@ -429,6 +430,7 @@ dired-mark-region > (defcustom dired-kill-when-opening-new-dired-buffer nil > "If non-nil, kill the current buffer when selecting a new directory." > :type 'boolean > + :group 'dired > :version "28.1") > > (defcustom dired-guess-shell-case-fold-search t > @@ -515,6 +517,18 @@ dired-movement-style > (defcustom dired-hide-details-preserved-columns nil > "List of columns which are not hidden in `dired-hide-details-mode'." > :type '(repeat integer) > + :group 'dired > + :version "30.1") Why do we need an explicit :group tag here? Options whose group is not 'dired' indeed need it, but those whose group is 'dired' get it implicitly, AFAIU. > +(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." This should tell more about the effect: that portions of longer file names are hidden by using the 'invisible' property and that the ellipsis is displayed in their stead. > +(defun dired--get-ellipsis-length () > + "Return length of ellipsis." > + (let* ((dt (or (window-display-table) > + buffer-display-table > + standard-display-table)) > + (glyphs (and dt (display-table-slot dt 'selective-display)))) > + (if glyphs (length glyphs) (eval-when-compile (length "..."))))) Why do you use 'length' here and not 'string-width' or similar? You seem to assume that each character takes just one column on display? > +(defun dired--get-filename-display-length () > + "Return maximum display length of filename." This doc string is inaccurate. The function actually returns the number of columns available for displaying the file names in a Dired buffer, and it should be called with point at the first character of the file name. > +(defun dired-filename-update-invisibility-spec () This function should have a doc string. > 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) Please add comments in these two places explaining why you call dired-filename-update-invisibility-spec here, so that the reader won't need to look at that function to understand the reason. Thanks. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-16 12:11 ` Eli Zaretskii @ 2023-11-18 9:23 ` Liu Hui 2023-11-18 10:55 ` Eli Zaretskii 0 siblings, 1 reply; 37+ messages in thread From: Liu Hui @ 2023-11-18 9:23 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 67161, stefankangas, monnier [-- Attachment #1: Type: text/plain, Size: 5611 bytes --] Eli Zaretskii <eliz@gnu.org> 于2023年11月16日周四 20:11写道: > > > From: Liu Hui <liuhui1610@gmail.com> > > Date: Thu, 16 Nov 2023 18:07:04 +0800 > > Cc: Stefan Kangas <stefankangas@gmail.com>, Stefan Monnier <monnier@iro.umontreal.ca>, > > 67161@debbugs.gnu.org > > > > From 991ea588df6799331a7feea9e83493ef0d724096 Mon Sep 17 00:00:00 2001 > > From: Liu Hui <liuhui1610@gmail.com> > > Date: Tue, 14 Nov 2023 16:14:12 +0800 > > Subject: [PATCH] Add option `dired-filename-display-length' > > > > * lisp/dired.el (dired-filename-display-length): New option. > > (dired-insert-set-properties): Set invisibility spec for long > > filenames. > > (dired--get-ellipsis-length) > > (dired--get-filename-display-length) > > (dired-filename-update-invisibility-spec): New functions. > > (dired-mode): Add filename invisibility spec. > > (dired-make-directory-clickable): > > (dired-kill-when-opening-new-dired-buffer): > > (dired-hide-details-preserved-columns): Add missing group. > > * lisp/wdired.el (wdired-change-to-wdired-mode) > > (wdired-change-to-dired-mode): Update filename invisibility spec. > > These changes need a NEWS entry to describe the new option and its > effect in short. Added. > > diff --git a/lisp/dired.el b/lisp/dired.el > > index 8919d2c223f..aad77a3dfc0 100644 > > --- a/lisp/dired.el > > +++ b/lisp/dired.el > > @@ -350,6 +350,7 @@ dired-after-readin-hook > > (defcustom dired-make-directory-clickable t > > "When non-nil, make the directory at the start of the dired buffer clickable." > > :version "29.1" > > + :group 'dired > > :type 'boolean) > > > > (defcustom dired-initial-position-hook nil > > @@ -429,6 +430,7 @@ dired-mark-region > > (defcustom dired-kill-when-opening-new-dired-buffer nil > > "If non-nil, kill the current buffer when selecting a new directory." > > :type 'boolean > > + :group 'dired > > :version "28.1") > > > > (defcustom dired-guess-shell-case-fold-search t > > @@ -515,6 +517,18 @@ dired-movement-style > > (defcustom dired-hide-details-preserved-columns nil > > "List of columns which are not hidden in `dired-hide-details-mode'." > > :type '(repeat integer) > > + :group 'dired > > + :version "30.1") > > Why do we need an explicit :group tag here? Options whose group is > not 'dired' indeed need it, but those whose group is 'dired' get it > implicitly, AFAIU. I find these options are implicitly assigned to the dired-guess group rather than dired group, since dired-guess is the last group. > > +(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." > > This should tell more about the effect: that portions of longer file > names are hidden by using the 'invisible' property and that the > ellipsis is displayed in their stead. Done. > > +(defun dired--get-ellipsis-length () > > + "Return length of ellipsis." > > + (let* ((dt (or (window-display-table) > > + buffer-display-table > > + standard-display-table)) > > + (glyphs (and dt (display-table-slot dt 'selective-display)))) > > + (if glyphs (length glyphs) (eval-when-compile (length "..."))))) > > Why do you use 'length' here and not 'string-width' or similar? You > seem to assume that each character takes just one column on display? Fixed. > > +(defun dired--get-filename-display-length () > > + "Return maximum display length of filename." > > This doc string is inaccurate. The function actually returns the > number of columns available for displaying the file names in a Dired > buffer, and it should be called with point at the first character of > the file name. Why is it inaccurate? When `dired-filename-display-length' is window, the function does return the number of columns available, and it is used as the maximum display length. Moreover, it could be an integer, which also means the maximum display length. > > +(defun dired-filename-update-invisibility-spec () > > This function should have a doc string. Added. > > 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) > > Please add comments in these two places explaining why you call > dired-filename-update-invisibility-spec here, so that the reader won't > need to look at that function to understand the reason. Added. > Thanks. BTW, I just find isearch doesn't handle hidden filenames based on 'invisible' text property, which needs to be fixed. So maybe an overlay-based approach is better? though I don't know if there is any possible problem with using overlays for this feature. WDYT? [-- Attachment #2: 0001-Add-option-dired-filename-display-length.patch --] [-- Type: text/x-patch, Size: 11189 bytes --] From 9f42d75566e980c326783e4f55c161a67cdf5ae6 Mon Sep 17 00:00:00 2001 From: Liu Hui <liuhui1610@gmail.com> Date: Tue, 14 Nov 2023 16:14:12 +0800 Subject: [PATCH] Add option `dired-filename-display-length' * lisp/dired.el (dired-filename-display-length): New option. (dired-insert-set-properties): Set invisibility spec for long filenames. (dired--get-ellipsis-length) (dired--get-filename-display-length) (dired-filename-update-invisibility-spec): New functions. (dired-mode): Add filename invisibility spec. (dired-make-directory-clickable): (dired-kill-when-opening-new-dired-buffer): (dired-hide-details-preserved-columns): Add missing group. * lisp/wdired.el (wdired-change-to-wdired-mode) (wdired-change-to-dired-mode): Update filename invisibility spec. * etc/NEWS: Announce the change. --- etc/NEWS | 7 +++ lisp/dired.el | 138 ++++++++++++++++++++++++++++++++++--------------- lisp/wdired.el | 6 +++ 3 files changed, 110 insertions(+), 41 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 23f4a8b5311..e9a84cb9183 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -472,6 +472,13 @@ empty lines. It also controls how to move point when encountering a boundary (e.g., if every line is visible, invoking 'dired-next-line' at the last line will move to the first line). The default is nil. +*** New user option 'dired-filename-display-length'. +It is an integer representing the maximum display length of filenames. +The middle part of filename whose length exceeds the restriction is +hidden and a ellipsis is displayed instead. A value of 'window' means +using the right edge of window as the display restriction. The +default is nil. + ** Ediff --- diff --git a/lisp/dired.el b/lisp/dired.el index 8919d2c223f..7eeab86d851 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -350,6 +350,7 @@ dired-after-readin-hook (defcustom dired-make-directory-clickable t "When non-nil, make the directory at the start of the dired buffer clickable." :version "29.1" + :group 'dired :type 'boolean) (defcustom dired-initial-position-hook nil @@ -429,6 +430,7 @@ dired-mark-region (defcustom dired-kill-when-opening-new-dired-buffer nil "If non-nil, kill the current buffer when selecting a new directory." :type 'boolean + :group 'dired :version "28.1") (defcustom dired-guess-shell-case-fold-search t @@ -515,6 +517,22 @@ dired-movement-style (defcustom dired-hide-details-preserved-columns nil "List of columns which are not hidden in `dired-hide-details-mode'." :type '(repeat integer) + :group 'dired + :version "30.1") + +(defcustom dired-filename-display-length nil + "If non-nil, restrict the display length of filenames. +If the value is the symbol `window', the right edge of current +window is used as the restriction. Otherwise, it should be an +integer representing the maximum filename length. + +The middle part of filename whose length exceeds the restriction +is hidden by using the `invisible' property and a ellipsis is +displayed instead." + :type '(choice (const :tag "No restriction" nil) + (const :tag "Window" window) + (integer :tag "Integer")) + :group 'dired :version "30.1") \f @@ -1903,48 +1921,61 @@ 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 (dired--get-ellipsis-length)) 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 +2007,21 @@ dired--make-directory-clickable "RET" click)))) (setq segment-start (point))))))) +(defun dired--get-ellipsis-length () + "Return length of ellipsis." + (let* ((dt (or (window-display-table) + buffer-display-table + standard-display-table)) + (glyphs (and dt (display-table-slot dt 'selective-display)))) + (string-width (if glyphs (concat glyphs) "...")))) + +(defun dired--get-filename-display-length () + "Return maximum display length of filename. +It is called at the first character of the file name." + (if (integerp dired-filename-display-length) + dired-filename-display-length + (- (window-max-chars-per-line) 1 (current-column)))) + \f ;;; Reverting a dired buffer @@ -2617,6 +2663,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 +3153,15 @@ dired-hide-details-update-invisibility-spec \f ;;; Functions to hide/unhide text +(defun dired-filename-update-invisibility-spec () + "Update `buffer-invisibility-spec' for filenames. +Specifically, the filename invisibility spec is added in Dired +buffers and removed in WDired buffers." + (funcall (if (derived-mode-p 'dired-mode) + 'add-to-invisibility-spec + 'remove-from-invisibility-spec) + '(dired-filename-hide . t))) + (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..b996be9baa9 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -261,6 +261,9 @@ wdired-change-to-wdired-mode (add-function :override (local 'revert-buffer-function) #'wdired-revert) (set-buffer-modified-p nil) (setq buffer-undo-list nil) + ;; remove filename invisibility spec to ensure filenames are visible + ;; for editing + (dired-filename-update-invisibility-spec) (run-mode-hooks 'wdired-mode-hook) (message "%s" (substitute-command-keys "Press \\[wdired-finish-edit] when finished \ @@ -456,6 +459,9 @@ wdired-change-to-dired-mode (dired-sort-set-mode-line) (dired-advertise) (dired-hide-details-update-invisibility-spec) + ;; re-add filename invisibility spec that is removed in + ;; `wdired-change-to-wdired-mode' + (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 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-18 9:23 ` Liu Hui @ 2023-11-18 10:55 ` Eli Zaretskii 2023-11-18 16:12 ` Drew Adams 2023-11-20 4:34 ` Liu Hui 0 siblings, 2 replies; 37+ messages in thread From: Eli Zaretskii @ 2023-11-18 10:55 UTC (permalink / raw) To: Liu Hui; +Cc: 67161, stefankangas, monnier > From: Liu Hui <liuhui1610@gmail.com> > Date: Sat, 18 Nov 2023 17:23:26 +0800 > Cc: stefankangas@gmail.com, monnier@iro.umontreal.ca, 67161@debbugs.gnu.org > > > > +(defun dired--get-filename-display-length () > > > + "Return maximum display length of filename." > > > > This doc string is inaccurate. The function actually returns the > > number of columns available for displaying the file names in a Dired > > buffer, and it should be called with point at the first character of > > the file name. > > Why is it inaccurate? When `dired-filename-display-length' is window, > the function does return the number of columns available, and it is > used as the maximum display length. Moreover, it could be an integer, > which also means the maximum display length. If there are two different modes of using this function, the doc string could describe them both. Currently, it only describes the use case where dired-filename-display-length is an integer, in which case it is a simple accessor. The other use case is more subtle, and the doc string is completely silent about that, in particular it doesn't mention that point should be at the first character of the file name in that case. > BTW, I just find isearch doesn't handle hidden filenames based on > 'invisible' text property, which needs to be fixed. So maybe an > overlay-based approach is better? though I don't know if there is any > possible problem with using overlays for this feature. WDYT? Doesn't "M-x i" during isearch handle this? > --- a/lisp/wdired.el > +++ b/lisp/wdired.el > @@ -261,6 +261,9 @@ wdired-change-to-wdired-mode > (add-function :override (local 'revert-buffer-function) #'wdired-revert) > (set-buffer-modified-p nil) > (setq buffer-undo-list nil) > + ;; remove filename invisibility spec to ensure filenames are visible > + ;; for editing Comments should be complete sentences: begin with a capital letter and end with a period. Also, please mention here the new defcustom you add to Dired, so that the comment could better explain itself. Thanks. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-18 10:55 ` Eli Zaretskii @ 2023-11-18 16:12 ` Drew Adams 2023-11-20 4:34 ` Liu Hui 1 sibling, 0 replies; 37+ messages in thread From: Drew Adams @ 2023-11-18 16:12 UTC (permalink / raw) To: Eli Zaretskii, Liu Hui Cc: 67161@debbugs.gnu.org, stefankangas@gmail.com, monnier@iro.umontreal.ca > Doesn't "M-x i" during isearch handle this? Typo, I think. `M-s i'. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-18 10:55 ` Eli Zaretskii 2023-11-18 16:12 ` Drew Adams @ 2023-11-20 4:34 ` Liu Hui 2023-11-20 12:10 ` Eli Zaretskii ` (2 more replies) 1 sibling, 3 replies; 37+ messages in thread From: Liu Hui @ 2023-11-20 4:34 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 67161, stefankangas, monnier [-- Attachment #1: Type: text/plain, Size: 2539 bytes --] Eli Zaretskii <eliz@gnu.org> 于2023年11月18日周六 18:55写道: > If there are two different modes of using this function, the doc > string could describe them both. Currently, it only describes the use > case where dired-filename-display-length is an integer, in which case > it is a simple accessor. The other use case is more subtle, and the > doc string is completely silent about that, in particular it doesn't > mention that point should be at the first character of the file name > in that case. Thanks for the explanation. I have updated the doc string as suggested. > > BTW, I just find isearch doesn't handle hidden filenames based on > > 'invisible' text property, which needs to be fixed. So maybe an > > overlay-based approach is better? though I don't know if there is any > > possible problem with using overlays for this feature. WDYT? > > Doesn't "M-x i" during isearch handle this? No. I want to search text in hidden part rather than only in the visible part, which is necessary for users to find relevant files even if they are partly hidden. Here is an example illustrating the problem: 1. emacs -Q 2. type M-: (insert "visible " (propertize "hidden" 'invisible t)) 3. C-s hidden isearch fails to match the invisible text by default, unless search-invisible is changed to t. However, the default value of search-invisible is open and it cannot be changed to t during isearch by M-s i. 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. > > --- a/lisp/wdired.el > > +++ b/lisp/wdired.el > > @@ -261,6 +261,9 @@ wdired-change-to-wdired-mode > > (add-function :override (local 'revert-buffer-function) #'wdired-revert) > > (set-buffer-modified-p nil) > > (setq buffer-undo-list nil) > > + ;; remove filename invisibility spec to ensure filenames are visible > > + ;; for editing > > Comments should be complete sentences: begin with a capital letter and > end with a period. Also, please mention here the new defcustom you > add to Dired, so that the comment could better explain itself. > > Thanks. Fixed. [-- Attachment #2: 0001-Add-option-dired-filename-display-length.patch --] [-- Type: text/x-patch, Size: 11471 bytes --] From 17a02e8af4502c84054fd7bac9d69f004d09d6a4 Mon Sep 17 00:00:00 2001 From: Liu Hui <liuhui1610@gmail.com> Date: Mon, 20 Nov 2023 12:09:15 +0800 Subject: [PATCH] Add option `dired-filename-display-length' * lisp/dired.el (dired-filename-display-length): New option. (dired-insert-set-properties): Set invisibility spec for long filenames. (dired--get-ellipsis-length) (dired--get-filename-display-length) (dired-filename-update-invisibility-spec): New functions. (dired-mode): Add filename invisibility spec. (dired-make-directory-clickable): (dired-kill-when-opening-new-dired-buffer): (dired-hide-details-preserved-columns): Add missing group. * lisp/wdired.el (wdired-change-to-wdired-mode) (wdired-change-to-dired-mode): Update filename invisibility spec. * etc/NEWS: Announce the change. --- etc/NEWS | 7 +++ lisp/dired.el | 141 +++++++++++++++++++++++++++++++++++-------------- lisp/wdired.el | 7 +++ 3 files changed, 114 insertions(+), 41 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 23f4a8b5311..ad9bda54b5e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -472,6 +472,13 @@ empty lines. It also controls how to move point when encountering a boundary (e.g., if every line is visible, invoking 'dired-next-line' at the last line will move to the first line). The default is nil. +*** New user option 'dired-filename-display-length'. +It is an integer representing the maximum display length of filenames. +The middle part of filename whose length exceeds the restriction is +hidden and an ellipsis is displayed instead. A value of 'window' +means using the right edge of window as the display restriction. The +default is nil. + ** Ediff --- diff --git a/lisp/dired.el b/lisp/dired.el index 8919d2c223f..e1893b1e8f1 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -350,6 +350,7 @@ dired-after-readin-hook (defcustom dired-make-directory-clickable t "When non-nil, make the directory at the start of the dired buffer clickable." :version "29.1" + :group 'dired :type 'boolean) (defcustom dired-initial-position-hook nil @@ -429,6 +430,7 @@ dired-mark-region (defcustom dired-kill-when-opening-new-dired-buffer nil "If non-nil, kill the current buffer when selecting a new directory." :type 'boolean + :group 'dired :version "28.1") (defcustom dired-guess-shell-case-fold-search t @@ -515,6 +517,22 @@ dired-movement-style (defcustom dired-hide-details-preserved-columns nil "List of columns which are not hidden in `dired-hide-details-mode'." :type '(repeat integer) + :group 'dired + :version "30.1") + +(defcustom dired-filename-display-length nil + "If non-nil, restrict the display length of filenames. +If the value is the symbol `window', the right edge of current +window is used as the restriction. Otherwise, it should be an +integer representing the maximum filename length. + +The middle part of filename whose length exceeds the restriction +is hidden by using the `invisible' property and an ellipsis is +displayed instead." + :type '(choice (const :tag "No restriction" nil) + (const :tag "Window" window) + (integer :tag "Integer")) + :group 'dired :version "30.1") \f @@ -1903,48 +1921,61 @@ 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 (dired--get-ellipsis-length)) 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 +2007,24 @@ dired--make-directory-clickable "RET" click)))) (setq segment-start (point))))))) +(defun dired--get-ellipsis-length () + "Return length of ellipsis." + (let* ((dt (or (window-display-table) + buffer-display-table + standard-display-table)) + (glyphs (and dt (display-table-slot dt 'selective-display)))) + (string-width (if glyphs (concat glyphs) "...")))) + +(defun dired--get-filename-display-length () + "Return maximum display length of filename. +When `dired-filename-display-length' is not an integer, the +function actually returns the number of columns available for +displaying the file names, and should be called with point at the +first character of the file name." + (if (integerp dired-filename-display-length) + dired-filename-display-length + (- (window-max-chars-per-line) 1 (current-column)))) + \f ;;; Reverting a dired buffer @@ -2617,6 +2666,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 +3156,15 @@ dired-hide-details-update-invisibility-spec \f ;;; Functions to hide/unhide text +(defun dired-filename-update-invisibility-spec () + "Update `buffer-invisibility-spec' for filenames. +Specifically, the filename invisibility spec is added in Dired +buffers and removed in WDired buffers." + (funcall (if (derived-mode-p 'dired-mode) + 'add-to-invisibility-spec + 'remove-from-invisibility-spec) + '(dired-filename-hide . t))) + (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..b5b01f0d089 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -261,6 +261,10 @@ wdired-change-to-wdired-mode (add-function :override (local 'revert-buffer-function) #'wdired-revert) (set-buffer-modified-p nil) (setq buffer-undo-list nil) + ;; Non-nil `dired-filename-display-length' may cause filenames to be + ;; hidden partly, so we remove filename invisibility spec + ;; temporarily to ensure filenames are visible for editing. + (dired-filename-update-invisibility-spec) (run-mode-hooks 'wdired-mode-hook) (message "%s" (substitute-command-keys "Press \\[wdired-finish-edit] when finished \ @@ -456,6 +460,9 @@ wdired-change-to-dired-mode (dired-sort-set-mode-line) (dired-advertise) (dired-hide-details-update-invisibility-spec) + ;; Restore filename invisibility spec that is removed in + ;; `wdired-change-to-wdired-mode'. + (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 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 4:34 ` Liu Hui @ 2023-11-20 12:10 ` Eli Zaretskii 2023-11-20 17:54 ` Juri Linkov 2023-11-20 18:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-20 17:20 ` Drew Adams 2023-11-22 5:41 ` Liu Hui 2 siblings, 2 replies; 37+ messages in thread From: Eli Zaretskii @ 2023-11-20 12:10 UTC (permalink / raw) To: Liu Hui, Juri Linkov; +Cc: 67161, stefankangas, monnier > From: Liu Hui <liuhui1610@gmail.com> > Date: Mon, 20 Nov 2023 12:34:13 +0800 > Cc: stefankangas@gmail.com, monnier@iro.umontreal.ca, 67161@debbugs.gnu.org > > > > BTW, I just find isearch doesn't handle hidden filenames based on > > > 'invisible' text property, which needs to be fixed. So maybe an > > > overlay-based approach is better? though I don't know if there is any > > > possible problem with using overlays for this feature. WDYT? > > > > Doesn't "M-s i" during isearch handle this? > > No. I want to search text in hidden part rather than only in the > visible part, which is necessary for users to find relevant files even > if they are partly hidden. > > Here is an example illustrating the problem: > 1. emacs -Q > 2. type M-: (insert "visible " (propertize "hidden" 'invisible t)) > 3. C-s hidden > > isearch fails to match the invisible text by default, unless > search-invisible is changed to t. However, the default value of > search-invisible is open and it cannot be changed to t during isearch > by M-s i. > > 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. Juri, this seems to be a usability bug? Why does Isearch only look into invisible overlay properties, but not text properties? IOW, why doesn't "M-s i" set the value of isearch-invisible to t, not 'open'? Or maybe 'open' should also search inside text properties, not just overlays? In any case, the differences between properties and overlays is unusual and IMO a misfeature. Can this be fixed? ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 12:10 ` Eli Zaretskii @ 2023-11-20 17:54 ` Juri Linkov 2023-11-20 18:42 ` Eli Zaretskii 2023-11-20 18:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 37+ messages in thread From: Juri Linkov @ 2023-11-20 17:54 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Liu Hui, 67161, stefankangas, monnier >> 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)) > > Juri, this seems to be a usability bug? Why does Isearch only look > into invisible overlay properties, but not text properties? IOW, why > doesn't "M-s i" set the value of isearch-invisible to t, not 'open'? > Or maybe 'open' should also search inside text properties, not just > overlays? In any case, the differences between properties and > overlays is unusual and IMO a misfeature. Can this be fixed? I recall Ihor implemented the revealing of invisible text properties for Org-mode when overlays were very slow. But now overlays are optimized, so Liu is absolutely right that better to use overlays. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 17:54 ` Juri Linkov @ 2023-11-20 18:42 ` Eli Zaretskii 0 siblings, 0 replies; 37+ messages in thread From: Eli Zaretskii @ 2023-11-20 18:42 UTC (permalink / raw) To: Juri Linkov; +Cc: liuhui1610, 67161, stefankangas, monnier > From: Juri Linkov <juri@linkov.net> > Cc: Liu Hui <liuhui1610@gmail.com>, stefankangas@gmail.com, > monnier@iro.umontreal.ca, 67161@debbugs.gnu.org > Date: Mon, 20 Nov 2023 19:54:27 +0200 > > >> 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)) > > > > Juri, this seems to be a usability bug? Why does Isearch only look > > into invisible overlay properties, but not text properties? IOW, why > > doesn't "M-s i" set the value of isearch-invisible to t, not 'open'? > > Or maybe 'open' should also search inside text properties, not just > > overlays? In any case, the differences between properties and > > overlays is unusual and IMO a misfeature. Can this be fixed? > > I recall Ihor implemented the revealing of invisible text properties > for Org-mode when overlays were very slow. But now overlays are > optimized, so Liu is absolutely right that better to use overlays. That might be so, but I was asking about Isearch being able to find matches inside invisible text, not about the Dired feature. Why cannot a user tell Isearch to find text that is invisible due to text properties? ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 12:10 ` Eli Zaretskii 2023-11-20 17:54 ` Juri Linkov @ 2023-11-20 18:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-20 19:17 ` Eli Zaretskii 2023-11-21 7:52 ` Juri Linkov 1 sibling, 2 replies; 37+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-20 18:55 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Liu Hui, 67161, stefankangas, Juri Linkov >> 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. Yes, using an overlay sounds like a better choice here, thanks. > Juri, this seems to be a usability bug? Why does Isearch only look > into invisible overlay properties, but not text properties? IOW, why > doesn't "M-s i" set the value of isearch-invisible to t, not 'open'? I think the idea is that matching invisible text is somewhat inconvenient, so it's better to temporarily reveal/open that text. But I think it points to an bug in Isearch: when `isearch-invisible` is `open` we should match text inside invisible text, regardless if we can reveal/open that invisible text or not. IOW `open` should find the same matches as `t`, the only difference being that it additionally (tries to) reveal/open the text. > In any case, the differences between properties and > overlays is unusual and IMO a misfeature. Can this be fixed? Indeed, it would be good to implement some way to reveal/open invisible text made invisible via text-properties rather than overlays. That also applies to `reveal-mode`, of course. Stefan ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 18:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-20 19:17 ` Eli Zaretskii 2023-11-21 7:52 ` Juri Linkov 1 sibling, 0 replies; 37+ messages in thread From: Eli Zaretskii @ 2023-11-20 19:17 UTC (permalink / raw) To: Stefan Monnier; +Cc: liuhui1610, 67161, stefankangas, juri > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: Liu Hui <liuhui1610@gmail.com>, Juri Linkov <juri@linkov.net>, > stefankangas@gmail.com, 67161@debbugs.gnu.org > Date: Mon, 20 Nov 2023 13:55:58 -0500 > > > Juri, this seems to be a usability bug? Why does Isearch only look > > into invisible overlay properties, but not text properties? IOW, why > > doesn't "M-s i" set the value of isearch-invisible to t, not 'open'? > > I think the idea is that matching invisible text is somewhat > inconvenient, so it's better to temporarily reveal/open that text. > But I think it points to an bug in Isearch: when `isearch-invisible` is > `open` we should match text inside invisible text, regardless if we can > reveal/open that invisible text or not. IOW `open` should find the > same matches as `t`, the only difference being that it additionally > (tries to) reveal/open the text. Agreed. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 18:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-20 19:17 ` Eli Zaretskii @ 2023-11-21 7:52 ` Juri Linkov 2023-11-21 11:55 ` Eli Zaretskii 1 sibling, 1 reply; 37+ messages in thread From: Juri Linkov @ 2023-11-21 7:52 UTC (permalink / raw) To: Stefan Monnier; +Cc: Liu Hui, Eli Zaretskii, 67161, stefankangas >>> 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. > > Yes, using an overlay sounds like a better choice here, thanks. > >> Juri, this seems to be a usability bug? Why does Isearch only look >> into invisible overlay properties, but not text properties? IOW, why >> doesn't "M-s i" set the value of isearch-invisible to t, not 'open'? > > I think the idea is that matching invisible text is somewhat > inconvenient, so it's better to temporarily reveal/open that text. > But I think it points to an bug in Isearch: when `isearch-invisible` is > `open` we should match text inside invisible text, regardless if we can > reveal/open that invisible text or not. IOW `open` should find the > same matches as `t`, the only difference being that it additionally > (tries to) reveal/open the text. This could be a new value like `open-or-match` with a trivial change: @@ -3899,6 +3899,9 @@ isearch-filter-visible of what `isearch-range-invisible' says." (and (not (text-property-not-all beg end 'inhibit-isearch nil)) (or (eq search-invisible t) + (when (eq search-invisible 'open-or-match) + (isearch-range-invisible beg end) + t) (not (isearch-range-invisible beg end))))) But I doubt that it could be enabled by default because in many cases it's too confusing for users to stop at a match that is not visible. OTOH, there was a request about informing the user about hidden matches. So now the Isearch prompt shows the number of invisible matches. Having this information the user can reveal in some way and visually inspect these matches. >> In any case, the differences between properties and >> overlays is unusual and IMO a misfeature. Can this be fixed? > > Indeed, it would be good to implement some way to reveal/open invisible > text made invisible via text-properties rather than overlays. > That also applies to `reveal-mode`, of course. Would be nice to have such useful feature. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-21 7:52 ` Juri Linkov @ 2023-11-21 11:55 ` Eli Zaretskii 2023-11-21 17:12 ` Juri Linkov 0 siblings, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-21 11:55 UTC (permalink / raw) To: Juri Linkov; +Cc: liuhui1610, 67161, monnier, stefankangas > From: Juri Linkov <juri@linkov.net> > Cc: Eli Zaretskii <eliz@gnu.org>, Liu Hui <liuhui1610@gmail.com>, > stefankangas@gmail.com, 67161@debbugs.gnu.org > Date: Tue, 21 Nov 2023 09:52:02 +0200 > > > I think the idea is that matching invisible text is somewhat > > inconvenient, so it's better to temporarily reveal/open that text. > > But I think it points to an bug in Isearch: when `isearch-invisible` is > > `open` we should match text inside invisible text, regardless if we can > > reveal/open that invisible text or not. IOW `open` should find the > > same matches as `t`, the only difference being that it additionally > > (tries to) reveal/open the text. > > This could be a new value like `open-or-match` with a trivial change: > > @@ -3899,6 +3899,9 @@ isearch-filter-visible > of what `isearch-range-invisible' says." > (and (not (text-property-not-all beg end 'inhibit-isearch nil)) > (or (eq search-invisible t) > + (when (eq search-invisible 'open-or-match) > + (isearch-range-invisible beg end) > + t) > (not (isearch-range-invisible beg end))))) > > But I doubt that it could be enabled by default because in many cases > it's too confusing for users to stop at a match that is not visible. Isn't it possible to unhide the invisible text by temporarily manipulating buffer-invisibility-spec? ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-21 11:55 ` Eli Zaretskii @ 2023-11-21 17:12 ` Juri Linkov 0 siblings, 0 replies; 37+ messages in thread From: Juri Linkov @ 2023-11-21 17:12 UTC (permalink / raw) To: Eli Zaretskii; +Cc: liuhui1610, 67161, monnier, stefankangas >> > I think the idea is that matching invisible text is somewhat >> > inconvenient, so it's better to temporarily reveal/open that text. >> > But I think it points to an bug in Isearch: when `isearch-invisible` is >> > `open` we should match text inside invisible text, regardless if we can >> > reveal/open that invisible text or not. IOW `open` should find the >> > same matches as `t`, the only difference being that it additionally >> > (tries to) reveal/open the text. >> >> This could be a new value like `open-or-match` with a trivial change: >> >> @@ -3899,6 +3899,9 @@ isearch-filter-visible >> of what `isearch-range-invisible' says." >> (and (not (text-property-not-all beg end 'inhibit-isearch nil)) >> (or (eq search-invisible t) >> + (when (eq search-invisible 'open-or-match) >> + (isearch-range-invisible beg end) >> + t) >> (not (isearch-range-invisible beg end))))) >> >> But I doubt that it could be enabled by default because in many cases >> it's too confusing for users to stop at a match that is not visible. > > Isn't it possible to unhide the invisible text by temporarily > manipulating buffer-invisibility-spec? Do you mean unhiding text properties? ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 4:34 ` Liu Hui 2023-11-20 12:10 ` Eli Zaretskii @ 2023-11-20 17:20 ` Drew Adams 2023-11-22 5:41 ` Liu Hui 2 siblings, 0 replies; 37+ messages in thread From: Drew Adams @ 2023-11-20 17:20 UTC (permalink / raw) To: Liu Hui, Eli Zaretskii Cc: 67161@debbugs.gnu.org, stefankangas@gmail.com, monnier@iro.umontreal.ca > 1. emacs -Q > 2. type M-: (insert "visible " (propertize "hidden" 'invisible t)) > 3. C-s hidden Just set or bind `isearch-filter-predicate' to `isearch-range-invisible', to search only invisible text. `C-h f isearch-range-invisible': isearch-range-invisible is a compiled Lisp function in ‘isearch.el’. (isearch-range-invisible BEG END) Return t if all the text from BEG to END is invisible. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-20 4:34 ` Liu Hui 2023-11-20 12:10 ` Eli Zaretskii 2023-11-20 17:20 ` Drew Adams @ 2023-11-22 5:41 ` Liu Hui 2023-11-25 10:52 ` Eli Zaretskii 2 siblings, 1 reply; 37+ messages in thread From: Liu Hui @ 2023-11-22 5:41 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 67161, stefankangas, monnier [-- Attachment #1: Type: text/plain, Size: 616 bytes --] > 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. [-- Attachment #2: 0001-Add-option-dired-filename-display-length.patch --] [-- Type: text/x-patch, Size: 12143 bytes --] From f2fcbc4756e3beb270a89fe5db5d64e467cb6d1d Mon Sep 17 00:00:00 2001 From: Liu Hui <liuhui1610@gmail.com> Date: Mon, 20 Nov 2023 12:09:15 +0800 Subject: [PATCH] Add option `dired-filename-display-length' * lisp/dired.el (dired-filename-display-length): New option. (dired-insert-set-properties): Set invisible property for long filenames. (dired--get-ellipsis-length) (dired--get-filename-display-length) (dired-filename-update-invisibility-spec): New functions. (dired-mode): Add filename invisibility spec. (dired-make-directory-clickable): (dired-kill-when-opening-new-dired-buffer): (dired-hide-details-preserved-columns): Add missing group. * lisp/wdired.el (wdired-change-to-wdired-mode) (wdired-change-to-dired-mode): Update filename invisibility spec. * etc/NEWS: Announce the change. --- etc/NEWS | 7 +++ lisp/dired.el | 151 +++++++++++++++++++++++++++++++++++-------------- lisp/wdired.el | 7 +++ 3 files changed, 123 insertions(+), 42 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index e14d15a7487..b4a3014debd 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -487,6 +487,13 @@ empty lines. It also controls how to move point when encountering a boundary (e.g., if every line is visible, invoking 'dired-next-line' at the last line will move to the first line). The default is nil. +*** New user option 'dired-filename-display-length'. +It is an integer representing the maximum display length of filenames. +The middle part of filename whose length exceeds the restriction is +hidden and an ellipsis is displayed instead. A value of 'window' +means using the right edge of window as the display restriction. The +default is nil. + ** Ediff --- diff --git a/lisp/dired.el b/lisp/dired.el index 583cb2475e2..8812721bb3a 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -350,6 +350,7 @@ dired-after-readin-hook (defcustom dired-make-directory-clickable t "When non-nil, make the directory at the start of the dired buffer clickable." :version "29.1" + :group 'dired :type 'boolean) (defcustom dired-initial-position-hook nil @@ -429,6 +430,7 @@ dired-mark-region (defcustom dired-kill-when-opening-new-dired-buffer nil "If non-nil, kill the current buffer when selecting a new directory." :type 'boolean + :group 'dired :version "28.1") (defcustom dired-guess-shell-case-fold-search t @@ -515,6 +517,22 @@ dired-movement-style (defcustom dired-hide-details-preserved-columns nil "List of columns which are not hidden in `dired-hide-details-mode'." :type '(repeat integer) + :group 'dired + :version "30.1") + +(defcustom dired-filename-display-length nil + "If non-nil, restrict the display length of filenames. +If the value is the symbol `window', the right edge of current +window is used as the restriction. Otherwise, it should be an +integer representing the maximum filename length. + +The middle part of filename whose length exceeds the restriction +is hidden by using the `invisible' property and an ellipsis is +displayed instead." + :type '(choice (const :tag "No restriction" nil) + (const :tag "Window" window) + (integer :tag "Integer")) + :group 'dired :version "30.1") \f @@ -1900,51 +1918,72 @@ dired-click-to-select-mode (defvar dired-click-to-select-map) (defun dired-insert-set-properties (beg end) - "Add various text properties to the lines in the region, from BEG to END." + "Add various text properties to the lines in the region, from BEG to END. +Overlays could be added when some user options are enabled, e.g., +`dired-filename-display-length'." + (remove-overlays beg end 'invisible 'dired-filename-hide) (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 (dired--get-ellipsis-length)) 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)) + ;; Here we use overlays because isearch by default + ;; doesn't support finding matches in hidden text + ;; made invisible via text properties. + (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))))) + (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 +2015,24 @@ dired--make-directory-clickable "RET" click)))) (setq segment-start (point))))))) +(defun dired--get-ellipsis-length () + "Return length of ellipsis." + (let* ((dt (or (window-display-table) + buffer-display-table + standard-display-table)) + (glyphs (and dt (display-table-slot dt 'selective-display)))) + (string-width (if glyphs (concat glyphs) "...")))) + +(defun dired--get-filename-display-length () + "Return maximum display length of filename. +When `dired-filename-display-length' is not an integer, the +function actually returns the number of columns available for +displaying the file names, and should be called with point at the +first character of the file name." + (if (integerp dired-filename-display-length) + dired-filename-display-length + (- (window-max-chars-per-line) 1 (current-column)))) + \f ;;; Reverting a dired buffer @@ -2617,6 +2674,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 +3164,15 @@ dired-hide-details-update-invisibility-spec \f ;;; Functions to hide/unhide text +(defun dired-filename-update-invisibility-spec () + "Update `buffer-invisibility-spec' for filenames. +Specifically, the filename invisibility spec is added in Dired +buffers and removed in WDired buffers." + (funcall (if (derived-mode-p 'dired-mode) + 'add-to-invisibility-spec + 'remove-from-invisibility-spec) + '(dired-filename-hide . t))) + (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..b5b01f0d089 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -261,6 +261,10 @@ wdired-change-to-wdired-mode (add-function :override (local 'revert-buffer-function) #'wdired-revert) (set-buffer-modified-p nil) (setq buffer-undo-list nil) + ;; Non-nil `dired-filename-display-length' may cause filenames to be + ;; hidden partly, so we remove filename invisibility spec + ;; temporarily to ensure filenames are visible for editing. + (dired-filename-update-invisibility-spec) (run-mode-hooks 'wdired-mode-hook) (message "%s" (substitute-command-keys "Press \\[wdired-finish-edit] when finished \ @@ -456,6 +460,9 @@ wdired-change-to-dired-mode (dired-sort-set-mode-line) (dired-advertise) (dired-hide-details-update-invisibility-spec) + ;; Restore filename invisibility spec that is removed in + ;; `wdired-change-to-wdired-mode'. + (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 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-22 5:41 ` Liu Hui @ 2023-11-25 10:52 ` Eli Zaretskii 2023-11-25 17:51 ` Juri Linkov 0 siblings, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-25 10:52 UTC (permalink / raw) To: Liu Hui; +Cc: 67161-done, stefankangas, monnier > From: Liu Hui <liuhui1610@gmail.com> > Date: Wed, 22 Nov 2023 13:41:18 +0800 > Cc: stefankangas@gmail.com, monnier@iro.umontreal.ca, 67161@debbugs.gnu.org > > > 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. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-25 10:52 ` Eli Zaretskii @ 2023-11-25 17:51 ` Juri Linkov 2023-11-25 20:02 ` Eli Zaretskii 0 siblings, 1 reply; 37+ messages in thread From: Juri Linkov @ 2023-11-25 17:51 UTC (permalink / raw) To: 67161; +Cc: liuhui1610, eliz > Thanks, installed on the master branch, and closing the bug. There is a problem with this specific configuration when ellipsis is a vector: (progn (or standard-display-table (setq standard-display-table (make-display-table))) (let* ((face (lsh (face-id 'escape-glyph) 22)) (dots (+ face ?…))) (set-char-table-extra-slot standard-display-table 4 (vector dots)))) that fails with Debugger entered--Lisp error: (wrong-type-argument characterp 88088614) concat([88088614]) (if glyphs (concat glyphs) "...") (string-width (if glyphs (concat glyphs) "...")) dired--get-ellipsis-length() ... ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-25 17:51 ` Juri Linkov @ 2023-11-25 20:02 ` Eli Zaretskii 2023-11-26 2:56 ` Liu Hui 0 siblings, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-25 20:02 UTC (permalink / raw) To: Juri Linkov; +Cc: liuhui1610, 67161 > From: Juri Linkov <juri@linkov.net> > Cc: eliz@gnu.org, liuhui1610@gmail.com > Date: Sat, 25 Nov 2023 19:51:55 +0200 > > > Thanks, installed on the master branch, and closing the bug. > > There is a problem with this specific configuration > when ellipsis is a vector: > > (progn > (or standard-display-table (setq standard-display-table (make-display-table))) > (let* ((face (lsh (face-id 'escape-glyph) 22)) > (dots (+ face ?…))) > (set-char-table-extra-slot standard-display-table 4 (vector dots)))) > > that fails with > > Debugger entered--Lisp error: (wrong-type-argument characterp 88088614) > concat([88088614]) > (if glyphs (concat glyphs) "...") > (string-width (if glyphs (concat glyphs) "...")) > dired--get-ellipsis-length() > ... > Does the below fix the problem, and is the Dired display after the change correct when file names are truncated? diff --git a/lisp/dired.el b/lisp/dired.el index 23a6fc0..096d6a8 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -2021,8 +2021,12 @@ dired--get-ellipsis-length (let* ((dt (or (window-display-table) buffer-display-table standard-display-table)) - (glyphs (and dt (display-table-slot dt 'selective-display)))) - (string-width (if glyphs (concat glyphs) "...")))) + (glyphs (and dt (display-table-slot dt 'selective-display))) + (vlen (length glyphs)) + (char-glyphs (make-vector vlen nil))) + (dotimes (i vlen) + (aset char-glyphs i (glyph-char (aref glyphs i)))) + (string-width (if glyphs (concat char-glyphs) "...")))) (defun dired--get-filename-display-length () "Return maximum display length of filename. ^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-25 20:02 ` Eli Zaretskii @ 2023-11-26 2:56 ` Liu Hui 2023-11-26 5:59 ` Eli Zaretskii 2023-11-27 7:19 ` Juri Linkov 0 siblings, 2 replies; 37+ messages in thread From: Liu Hui @ 2023-11-26 2:56 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 67161, Juri Linkov Eli Zaretskii <eliz@gnu.org> 于2023年11月26日周日 04:02写道: > Does the below fix the problem, and is the Dired display after the > change correct when file names are truncated? > > diff --git a/lisp/dired.el b/lisp/dired.el > index 23a6fc0..096d6a8 100644 > --- a/lisp/dired.el > +++ b/lisp/dired.el > @@ -2021,8 +2021,12 @@ dired--get-ellipsis-length > (let* ((dt (or (window-display-table) > buffer-display-table > standard-display-table)) > - (glyphs (and dt (display-table-slot dt 'selective-display)))) > - (string-width (if glyphs (concat glyphs) "...")))) > + (glyphs (and dt (display-table-slot dt 'selective-display))) > + (vlen (length glyphs)) > + (char-glyphs (make-vector vlen nil))) > + (dotimes (i vlen) > + (aset char-glyphs i (glyph-char (aref glyphs i)))) > + (string-width (if glyphs (concat char-glyphs) "...")))) > > (defun dired--get-filename-display-length () > "Return maximum display length of filename. Thanks Eli! I wasn't aware of the face of glyph and I confirm the dired display is correct with your fix. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 2:56 ` Liu Hui @ 2023-11-26 5:59 ` Eli Zaretskii 2023-11-26 10:49 ` Eli Zaretskii 2023-11-26 14:03 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-27 7:19 ` Juri Linkov 1 sibling, 2 replies; 37+ messages in thread From: Eli Zaretskii @ 2023-11-26 5:59 UTC (permalink / raw) To: Liu Hui, Stefan Monnier; +Cc: 67161, juri > From: Liu Hui <liuhui1610@gmail.com> > Date: Sun, 26 Nov 2023 10:56:52 +0800 > Cc: Juri Linkov <juri@linkov.net>, 67161@debbugs.gnu.org > > Eli Zaretskii <eliz@gnu.org> 于2023年11月26日周日 04:02写道: > > > Does the below fix the problem, and is the Dired display after the > > change correct when file names are truncated? > > > > diff --git a/lisp/dired.el b/lisp/dired.el > > index 23a6fc0..096d6a8 100644 > > --- a/lisp/dired.el > > +++ b/lisp/dired.el > > @@ -2021,8 +2021,12 @@ dired--get-ellipsis-length > > (let* ((dt (or (window-display-table) > > buffer-display-table > > standard-display-table)) > > - (glyphs (and dt (display-table-slot dt 'selective-display)))) > > - (string-width (if glyphs (concat glyphs) "...")))) > > + (glyphs (and dt (display-table-slot dt 'selective-display))) > > + (vlen (length glyphs)) > > + (char-glyphs (make-vector vlen nil))) > > + (dotimes (i vlen) > > + (aset char-glyphs i (glyph-char (aref glyphs i)))) > > + (string-width (if glyphs (concat char-glyphs) "...")))) > > > > (defun dired--get-filename-display-length () > > "Return maximum display length of filename. > > Thanks Eli! I wasn't aware of the face of glyph and I confirm the > dired display is correct with your fix. Thanks for testing. However, I'm beginning to think that this is a subtle misfeature in 'concat': it should support vector of glyphs with faces, and should preserve the face information (my patch simply discards faces, which could perhaps affect string-width result). So I think we should perhaps extend 'concat' to support vectors of glyphs with faces. Stefan, WDYT? ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 5:59 ` Eli Zaretskii @ 2023-11-26 10:49 ` Eli Zaretskii 2023-11-26 14:03 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 0 replies; 37+ messages in thread From: Eli Zaretskii @ 2023-11-26 10:49 UTC (permalink / raw) To: juri; +Cc: liuhui1610, 67161, monnier > Cc: 67161@debbugs.gnu.org, juri@linkov.net > Date: Sun, 26 Nov 2023 07:59:29 +0200 > From: Eli Zaretskii <eliz@gnu.org> > > > From: Liu Hui <liuhui1610@gmail.com> > > Date: Sun, 26 Nov 2023 10:56:52 +0800 > > Cc: Juri Linkov <juri@linkov.net>, 67161@debbugs.gnu.org > > > > Thanks Eli! I wasn't aware of the face of glyph and I confirm the > > dired display is correct with your fix. > > Thanks for testing. > > However, I'm beginning to think that this is a subtle misfeature in > 'concat': it should support vector of glyphs with faces, and should > preserve the face information (my patch simply discards faces, which > could perhaps affect string-width result). > > So I think we should perhaps extend 'concat' to support vectors of > glyphs with faces. Stefan, WDYT? For now, I installed my fix, so that at least the code will work with Juri's customizations. If and when 'concat' supports glyphs with faces in display-tables, we could revert the change in dired.el ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 5:59 ` Eli Zaretskii 2023-11-26 10:49 ` Eli Zaretskii @ 2023-11-26 14:03 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-26 14:53 ` Eli Zaretskii 1 sibling, 1 reply; 37+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-26 14:03 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Liu Hui, 67161, juri > However, I'm beginning to think that this is a subtle misfeature in > 'concat': it should support vector of glyphs with faces, and should > preserve the face information (my patch simply discards faces, which > could perhaps affect string-width result). Hmm... It's hard for me to judge because I don't really understand why we have "vectors of glyphs". If vectors of glyphs can express things we can't express in a string, then the question is what should `concat` do in that case, and if we can then ... why do we even have vectors of glyphs? Stefan ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 14:03 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-26 14:53 ` Eli Zaretskii 2023-11-26 17:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-26 14:53 UTC (permalink / raw) To: Stefan Monnier; +Cc: liuhui1610, 67161, juri > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: Liu Hui <liuhui1610@gmail.com>, juri@linkov.net, 67161@debbugs.gnu.org > Date: Sun, 26 Nov 2023 09:03:39 -0500 > > > However, I'm beginning to think that this is a subtle misfeature in > > 'concat': it should support vector of glyphs with faces, and should > > preserve the face information (my patch simply discards faces, which > > could perhaps affect string-width result). > > Hmm... It's hard for me to judge because I don't really understand why > we have "vectors of glyphs". They are stored in display-tables. > If vectors of glyphs can express things we can't express in a > string, then the question is what should `concat` do in that case, > and if we can then ... why do we even have vectors of glyphs? See above. I don't know why display-tables store vectors and not strings, but it was like that forever. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 14:53 ` Eli Zaretskii @ 2023-11-26 17:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-26 17:58 ` Eli Zaretskii 0 siblings, 1 reply; 37+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-26 17:08 UTC (permalink / raw) To: Eli Zaretskii; +Cc: liuhui1610, 67161, juri >> > However, I'm beginning to think that this is a subtle misfeature in >> > 'concat': it should support vector of glyphs with faces, and should >> > preserve the face information (my patch simply discards faces, which >> > could perhaps affect string-width result). >> Hmm... It's hard for me to judge because I don't really understand why >> we have "vectors of glyphs". > They are stored in display-tables. Yes, I know do that much :-) >> If vectors of glyphs can express things we can't express in a >> string, then the question is what should `concat` do in that case, >> and if we can then ... why do we even have vectors of glyphs? > See above. I don't know why display-tables store vectors and not > strings, but it was like that forever. If everything we can do with vectors of glyphs can be done with strings (i.e. vectors of glyphs are basically accidents of history), then it seems it would make sense to auto-convert a vector of glyph to a string *and* to phase out the use of vectors of glyphs. Stefan ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 17:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-26 17:58 ` Eli Zaretskii 2023-11-26 18:06 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 37+ messages in thread From: Eli Zaretskii @ 2023-11-26 17:58 UTC (permalink / raw) To: Stefan Monnier; +Cc: liuhui1610, 67161, juri > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: liuhui1610@gmail.com, juri@linkov.net, 67161@debbugs.gnu.org > Date: Sun, 26 Nov 2023 12:08:04 -0500 > > >> If vectors of glyphs can express things we can't express in a > >> string, then the question is what should `concat` do in that case, > >> and if we can then ... why do we even have vectors of glyphs? > > See above. I don't know why display-tables store vectors and not > > strings, but it was like that forever. > > If everything we can do with vectors of glyphs can be done with strings > (i.e. vectors of glyphs are basically accidents of history), then it > seems it would make sense to auto-convert a vector of glyph to a string > *and* to phase out the use of vectors of glyphs. Yes, but who will have the energy and motivation to go over all the places that use the display-tables (both in Lisp and in C), and convert all of them to use strings with faces instead vectors of glyphs? To say nothing of the related documentation? And then we will probably discover that some subtle aspect of this is the real reason why we use vectors of glyphs... ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 17:58 ` Eli Zaretskii @ 2023-11-26 18:06 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 0 replies; 37+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-26 18:06 UTC (permalink / raw) To: Eli Zaretskii; +Cc: liuhui1610, 67161, juri > Yes, but who will have the energy and motivation to go over all the > places that use the display-tables (both in Lisp and in C), and > convert all of them to use strings with faces instead vectors of > glyphs? To say nothing of the related documentation? And then we > will probably discover that some subtle aspect of this is the real > reason why we use vectors of glyphs... Sounds exciting! Stefan ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-26 2:56 ` Liu Hui 2023-11-26 5:59 ` Eli Zaretskii @ 2023-11-27 7:19 ` Juri Linkov 2023-11-27 8:32 ` Liu Hui 1 sibling, 1 reply; 37+ messages in thread From: Juri Linkov @ 2023-11-27 7:19 UTC (permalink / raw) To: Liu Hui; +Cc: Eli Zaretskii, 67161 >> Does the below fix the problem, and is the Dired display after the >> change correct when file names are truncated? > > Thanks Eli! I wasn't aware of the face of glyph and I confirm the > dired display is correct with your fix. Now that it works I was able to find a different problem: Debugger entered--Lisp error: (void-function t) t(#<overlay from 960 to 1016 in tmp/>) isearch-open-necessary-overlays(#<overlay from 960 to 1016 in tmp/>) isearch-clean-overlays() isearch-exit() funcall-interactively(isearch-exit) command-execute(isearch-exit) because 'isearch-open-invisible' should be a function. I wonder what would be a suitable function. After searching for other uses I found a good example in lisp/org/org-fold-core.el: (overlay-put o 'isearch-open-invisible #'delete-overlay) that works nicely leaving the overlay open after exiting isearch in dired. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-27 7:19 ` Juri Linkov @ 2023-11-27 8:32 ` Liu Hui 2023-11-27 17:16 ` Juri Linkov 0 siblings, 1 reply; 37+ messages in thread From: Liu Hui @ 2023-11-27 8:32 UTC (permalink / raw) To: Juri Linkov; +Cc: Eli Zaretskii, 67161 Juri Linkov <juri@linkov.net> 于2023年11月27日周一 15:31写道: > Now that it works I was able to find a different problem: > > Debugger entered--Lisp error: (void-function t) > t(#<overlay from 960 to 1016 in tmp/>) > isearch-open-necessary-overlays(#<overlay from 960 to 1016 in tmp/>) > isearch-clean-overlays() > isearch-exit() > funcall-interactively(isearch-exit) > command-execute(isearch-exit) > > because 'isearch-open-invisible' should be a function. > I wonder what would be a suitable function. > After searching for other uses I found a good example > in lisp/org/org-fold-core.el: > > (overlay-put o 'isearch-open-invisible #'delete-overlay) > > that works nicely leaving the overlay open after exiting isearch in dired. Sorry for the mistake! I can reproduce the problem and the fix works well. Thank you, Juri! ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-27 8:32 ` Liu Hui @ 2023-11-27 17:16 ` Juri Linkov 0 siblings, 0 replies; 37+ messages in thread From: Juri Linkov @ 2023-11-27 17:16 UTC (permalink / raw) To: Liu Hui; +Cc: Eli Zaretskii, 67161 >> Now that it works I was able to find a different problem: >> >> Debugger entered--Lisp error: (void-function t) >> t(#<overlay from 960 to 1016 in tmp/>) >> isearch-open-necessary-overlays(#<overlay from 960 to 1016 in tmp/>) >> isearch-clean-overlays() >> isearch-exit() >> funcall-interactively(isearch-exit) >> command-execute(isearch-exit) >> >> because 'isearch-open-invisible' should be a function. >> I wonder what would be a suitable function. >> After searching for other uses I found a good example >> in lisp/org/org-fold-core.el: >> >> (overlay-put o 'isearch-open-invisible #'delete-overlay) >> >> that works nicely leaving the overlay open after exiting isearch in dired. > > Sorry for the mistake! I can reproduce the problem and the fix works > well. Thank you, Juri! Thanks for confirming. Now pushed and everything works nicely. ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-15 10:04 ` Liu Hui 2023-11-15 12:32 ` Eli Zaretskii @ 2023-11-15 18:06 ` Drew Adams 1 sibling, 0 replies; 37+ messages in thread From: Drew Adams @ 2023-11-15 18:06 UTC (permalink / raw) To: Liu Hui, Eli Zaretskii; +Cc: 67161@debbugs.gnu.org > > We shouldn't use non-ASCII characters by default, without checking > > they can be displayed. > > Thanks for pointing this out. I think it can be changed to "...". +1. Would someone please do likewise for `dired-sort-set-mode-line'? My version (in Dired+) uses "...", not an ellipsis char. FWIW, IMO an ellipsis char is _bad_ when the font used is fixed width. It's not very legible, in particular. ___ FWIW2: The other difference my version has is that it respects a user option: ___ diredp-switches-in-mode-line is a variable defined in `dired+.el'. Its value is nil How to indicate `dired-actual-switches' in mode-line. Possible values: * `nil': Indicate name-or-date sort order, if possible. Else show full switches. * `as-is': Show full switches. * Integer: Show only the first N chars of full switches. * Function: Pass `dired-actual-switches' as arg and show result. ___ If vanilla Emacs did likewise or something similar then I wouldn't need my version of `dired-sort-set-mode-line' (for new Emacs versions, at least). ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-14 9:52 bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' Liu Hui 2023-11-14 13:26 ` Eli Zaretskii @ 2023-11-15 15:54 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-16 3:44 ` Liu Hui 1 sibling, 1 reply; 37+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-15 15:54 UTC (permalink / raw) To: Liu Hui; +Cc: 67161 > +(defcustom dired-filename-hiding-ellipsis "…" [...] > +(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))) AFAIK this does not do what the code suggests: the ELLIPSIS part of the element passed to `add-to-invisibility-spec` is treated as a boolean. How the ellipses are displayed is controlled by the `selective-display` extra slot of the display table. I think it's good that you use `invisible`, tho, specifically since it then uses whichever ellipsis the user has chosen via the display-table. The downside is that most users don't know how to change it and there's no convenient facility to access it. You probably need something like (defun length-of-standard-ellipsis () (let ((glyphs (and standard-display-table (display-table-slot standard-display-table 'selective-display)))) (if glyphs (length glyphs) (eval-when-compile (length "..."))))) -- Stefan ^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' 2023-11-15 15:54 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-16 3:44 ` Liu Hui 0 siblings, 0 replies; 37+ messages in thread From: Liu Hui @ 2023-11-16 3:44 UTC (permalink / raw) To: Stefan Monnier; +Cc: 67161 Stefan Monnier <monnier@iro.umontreal.ca> 于2023年11月15日周三 23:57写道: > I think it's good that you use `invisible`, tho, specifically since it > then uses whichever ellipsis the user has chosen via the display-table. > The downside is that most users don't know how to change it and there's > no convenient facility to access it. You probably need something like > > (defun length-of-standard-ellipsis () > (let ((glyphs > (and standard-display-table > (display-table-slot standard-display-table > 'selective-display)))) > (if glyphs (length glyphs) (eval-when-compile (length "..."))))) Thanks very much for pointing out the problem! Your suggestion is valuable, and I will update the patch later. ^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2023-11-27 17:16 UTC | newest] Thread overview: 37+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-11-14 9:52 bug#67161: 30.0.50; [PATCH] Add option `dired-filename-display-length' Liu Hui 2023-11-14 13:26 ` Eli Zaretskii 2023-11-15 10:04 ` Liu Hui 2023-11-15 12:32 ` Eli Zaretskii 2023-11-16 10:07 ` Liu Hui 2023-11-16 12:11 ` Eli Zaretskii 2023-11-18 9:23 ` Liu Hui 2023-11-18 10:55 ` Eli Zaretskii 2023-11-18 16:12 ` Drew Adams 2023-11-20 4:34 ` Liu Hui 2023-11-20 12:10 ` Eli Zaretskii 2023-11-20 17:54 ` Juri Linkov 2023-11-20 18:42 ` Eli Zaretskii 2023-11-20 18:55 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-20 19:17 ` Eli Zaretskii 2023-11-21 7:52 ` Juri Linkov 2023-11-21 11:55 ` Eli Zaretskii 2023-11-21 17:12 ` Juri Linkov 2023-11-20 17:20 ` Drew Adams 2023-11-22 5:41 ` Liu Hui 2023-11-25 10:52 ` Eli Zaretskii 2023-11-25 17:51 ` Juri Linkov 2023-11-25 20:02 ` Eli Zaretskii 2023-11-26 2:56 ` Liu Hui 2023-11-26 5:59 ` Eli Zaretskii 2023-11-26 10:49 ` Eli Zaretskii 2023-11-26 14:03 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-26 14:53 ` Eli Zaretskii 2023-11-26 17:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-26 17:58 ` Eli Zaretskii 2023-11-26 18:06 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-27 7:19 ` Juri Linkov 2023-11-27 8:32 ` Liu Hui 2023-11-27 17:16 ` Juri Linkov 2023-11-15 18:06 ` Drew Adams 2023-11-15 15:54 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-11-16 3:44 ` Liu Hui
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).