Package: emacs;
Reported by: Spencer Baugh <sbaugh <at> janestreet.com>
Date: Fri, 22 Aug 2025 21:21:01 UTC
Severity: normal
Tags: patch
Fixed in version 31.0.50
Done: Juri Linkov <juri <at> linkov.net>
View this message in rfc822 format
From: Spencer Baugh <sbaugh <at> janestreet.com> To: Juri Linkov <juri <at> linkov.net> Cc: Eli Zaretskii <eliz <at> gnu.org>, 79293 <at> debbugs.gnu.org Subject: bug#79293: [PATCH] Pass dired default filenames via defaults argument Date: Wed, 27 Aug 2025 16:26:17 -0400
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes: >> Also, attached is an updated version of the patch which reflects the >> fact that the "default" variable actually was unused before, only >> "defaults" was used. >> [...] >> - (default (and dired-one-file >> - (not dired-dwim-target) ; Bug#25609 > > Removing these lines breaks dired-tests added > in the same commit 841e3e377c97 for Bug#25609 above. Ah, sorry, I guess I forgot to run dired-tests. But this is great news, this means this code is covered by at least one test. The real issue in bug#25609 is that the minibuffer default didn't have the correct value when dired-dwim-target is non-nil. From my analysis of the code, the default should always be the same as the initial input in the minibuffer (TARGET-DIR), but that wasn't happening with non-nil dired-dwim-target. With my change, this is fixed easily enough by just making sure TARGET-DIR is the first element of the defaults list. This doesn't change observable behavior because read-file-name explicitly handles the case where the initial input matches the first default: ;; When the first default in `minibuffer-default' ;; duplicates initial input `insdef', ;; reset `minibuffer-default' to nil. (when (equal (or (car-safe insdef) insdef) (or (car-safe minibuffer-default) minibuffer-default)) (setq minibuffer-default (cdr-safe minibuffer-default))) This also fixes bug#25609, with even less code, and dired-tests and dired-aux-tests both once again all pass. This version of the patch also extends the change to dired-compare-directories, so it gets the abbreviate-file-name benefits too.
[0001-Pass-dired-default-filenames-via-defaults-argument.patch (text/x-patch, inline)]
From 388b1855afd2252431c8b44e6674362c6219c18d Mon Sep 17 00:00:00 2001 From: Spencer Baugh <sbaugh <at> janestreet.com> Date: Fri, 22 Aug 2025 17:19:09 -0400 Subject: [PATCH] Pass dired default filenames via defaults argument Rather than using minibuffer-with-setup-hook, just pass the list of default file names as a regular argument to read-file-name. This allows read-file-name to run abbreviate-file-name on the defaults as it normally does, instead of the defaults appearing in expanded form. dired-dwim-target-defaults changes slightly to return the correct default at the start of the list. * lisp/dired-aux.el (dired-do-create-files) (dired-compare-directories): Pass default file names as an argument. (bug#79293) (dired-dwim-target-defaults): Return the correct default at the start of the list. --- lisp/dired-aux.el | 51 +++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 049d200f590..e28106d9865 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -330,14 +330,13 @@ dired-compare-directories (interactive (list (let* ((target-dir (dired-dwim-target-directory)) - (defaults (dired-dwim-target-defaults nil target-dir))) + (defaults (dired-dwim-target-defaults nil target-dir))) (minibuffer-with-setup-hook (lambda () - (setq-local minibuffer-default-add-function nil) - (setq minibuffer-default defaults)) + (setq-local minibuffer-default-add-function nil)) (read-directory-name (format "Compare %s with: " (dired-current-directory)) - target-dir target-dir t))) + target-dir defaults t))) (read-from-minibuffer "Mark if (lisp expr or RET): " nil nil t nil "nil")) dired-mode) (let* ((dir1 (dired-current-directory)) @@ -2668,17 +2667,12 @@ dired-do-create-files (dired-one-file ; fluid variable inside dired-create-files (and (consp fn-list) (null (cdr fn-list)) (car fn-list))) (target-dir (dired-dwim-target-directory)) - (default (and dired-one-file - (not dired-dwim-target) ; Bug#25609 - (expand-file-name (file-name-nondirectory - (car fn-list)) - target-dir))) (defaults (dired-dwim-target-defaults fn-list target-dir)) (target (expand-file-name ; fluid variable inside dired-create-files (minibuffer-with-setup-hook (lambda () - (setq-local minibuffer-default-add-function nil) - (setq minibuffer-default defaults)) + ;; Don't run `read-file-name--defaults' + (setq-local minibuffer-default-add-function nil)) (dired-mark-read-file-name (format "%s %%s %s: " (if dired-one-file op1 operation) @@ -2688,7 +2682,7 @@ dired-do-create-files ;; other operations copy (etc) to the ;; prompted file name. "from" "to")) - target-dir op-symbol arg rfn-list default)))) + target-dir op-symbol arg rfn-list defaults)))) (into-dir (progn (when @@ -2813,28 +2807,26 @@ dired-dwim-target-directory this-dir))) (defun dired-dwim-target-defaults (fn-list target-dir) - ;; Return a list of default values for file-reading functions in Dired. - ;; This list may contain directories from Dired buffers in other windows. - ;; `fn-list' is a list of file names used to build a list of defaults. - ;; When nil or more than one element, a list of defaults will - ;; contain only directory names. `target-dir' is a directory name - ;; to exclude from the returned list, for the case when this - ;; directory name is already presented in initial input. - ;; For Dired operations that support `dired-dwim-target', - ;; the argument `target-dir' should have the value returned - ;; from `dired-dwim-target-directory'. + "Return a list of default values for file-reading functions in Dired. + +This list may contain directories from Dired buffers in other windows. +FN-LIST is a list of file names used to build a list of defaults. +When nil or more than one element, a list of defaults will +contain only directory names. + +TARGET-DIR should be the initial input in the minibuffer for the +file-reading function. For Dired operations that support +`dired-dwim-target', TARGET-DIR should have the value returned from +`dired-dwim-target-directory'." (let ((dired-one-file (and (consp fn-list) (null (cdr fn-list)) (car fn-list))) (current-dir (and (eq major-mode 'dired-mode) (dired-current-directory))) ;; Get a list of directories of visible buffers in dired-mode. (dired-dirs (dired-dwim-target-directories))) - ;; Force the current dir to be the first in the list. + ;; Force TARGET-DIR then CURRENT-DIR to be first in the list. (setq dired-dirs - (delete-dups (delq nil (cons current-dir dired-dirs)))) - ;; Remove the target dir (if specified) or the current dir from - ;; default values, because it should be already in initial input. - (setq dired-dirs (delete (or target-dir current-dir) dired-dirs)) + (delete-dups (delq nil (cons target-dir (cons current-dir dired-dirs))))) ;; Return a list of default values. (if dired-one-file ;; For one file operation, provide a list that contains @@ -2847,10 +2839,7 @@ dired-dwim-target-defaults (mapcar (lambda (dir) (expand-file-name (file-name-nondirectory (car fn-list)) dir)) - (reverse dired-dirs)) - (list (expand-file-name - (file-name-nondirectory (car fn-list)) - (or target-dir current-dir)))) + (reverse dired-dirs))) ;; For multi-file operation, return only a list of other directories. dired-dirs))) -- 2.43.7
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.