GNU bug report logs -
#78658
30.1; [PATCH] Dired feature suggestion: dired-on-marked-files-in-all-buffers
Previous Next
To reply to this bug, email your comments to 78658 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sun, 01 Jun 2025 03:20:07 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Phil Sainty <psainty <at> orcon.net.nz>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Sun, 01 Jun 2025 03:20:07 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
A user in the matrix.org Emacs chat room was asking why they couldn't
open multiple directories in multiple dired buffers, mark various files
in each of those buffers, and then perform some action on ALL of those
marked files at once.
My first thought was that this would be chaotic due to the possibility
of dired buffers with marked files which the user wasn't aware of at
the time; but then I remembered that you can pass `dired' a file list
in order to create a new dired buffer with only those files, and I
thought *that* sounded like a nice feature which addressed the
requirement in a safe manner (as the user then gets to review the file
list in the new dired buffer before acting on them).
I've attached a patch with a first pass implementation.
Thoughts?
[0001-lisp-dired.el-dired-on-marked-files-in-all-buffers-N.patch (text/x-diff, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sun, 01 Jun 2025 06:11:02 GMT)
Full text and
rfc822 format available.
Message #8 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> Date: Sun, 01 Jun 2025 15:19:02 +1200
> From: Phil Sainty <psainty <at> orcon.net.nz>
>
> A user in the matrix.org Emacs chat room was asking why they couldn't
> open multiple directories in multiple dired buffers, mark various files
> in each of those buffers, and then perform some action on ALL of those
> marked files at once.
If those other directories are subdirectories of some common parent,
we already have 'i'.
> My first thought was that this would be chaotic due to the possibility
> of dired buffers with marked files which the user wasn't aware of at
> the time; but then I remembered that you can pass `dired' a file list
> in order to create a new dired buffer with only those files, and I
> thought *that* sounded like a nice feature which addressed the
> requirement in a safe manner (as the user then gets to review the file
> list in the new dired buffer before acting on them).
>
> I've attached a patch with a first pass implementation.
>
> Thoughts?
I guess we could add that, although it's a rare use case, and the
display is not very nice, since all the file names are absolute, and
thus long. Perhaps use abbreviate-file-name?
> +(defun dired-on-marked-files-in-all-buffers ()
> + "Invoke `dired' on the marked files in all dired buffers."
> + (interactive)
> + (if-let ((files (dired-get-marked-files-in-all-buffers)))
> + (dired (cons "/" files))
Why "/"? It sounds arbitrary. Also non-portable; use
(expand-file-name "/")
instead.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sun, 01 Jun 2025 07:05:03 GMT)
Full text and
rfc822 format available.
Message #11 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> A user in the matrix.org Emacs chat room was asking why they couldn't
> open multiple directories in multiple dired buffers, mark various files
> in each of those buffers, and then perform some action on ALL of those
> marked files at once.
>
> My first thought was that this would be chaotic due to the possibility
> of dired buffers with marked files which the user wasn't aware of at
> the time; but then I remembered that you can pass `dired' a file list
> in order to create a new dired buffer with only those files, and I
> thought *that* sounded like a nice feature which addressed the
> requirement in a safe manner (as the user then gets to review the file
> list in the new dired buffer before acting on them).
>
> I've attached a patch with a first pass implementation.
>
> Thoughts?
Ideally, it could find the common prefix, then set
default-directory to it and list only relative file names,
like in the output of e.g. 'find-dired-with-command'.
But it already is very useful, and much better
than the output of 'M-x locate'.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sun, 01 Jun 2025 16:54:03 GMT)
Full text and
rfc822 format available.
Message #14 received at 78658 <at> debbugs.gnu.org (full text, mbox):
>> I've attached a patch with a first pass implementation.
>>
>> Thoughts?
>
> Ideally, it could find the common prefix, then set
> default-directory to it and list only relative file names,
> like in the output of e.g. 'find-dired-with-command'.
>
> But it already is very useful, and much better
> than the output of 'M-x locate'.
I realized this feature has great potential. When restricted
to a project's subdirs it can serve as a project's workspace
where the user can select a set of relevant files to work on.
Currently the closest approximation is *vc-dir*. But it shows
only edited files by default. While it's possible to add
unedited files by 'i' ('vc-dir-show-fileentry'), it's not
as easy as marking files in Dired.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Mon, 02 Jun 2025 00:14:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > I've attached a patch with a first pass implementation.
It's a very good idea. I plan to add it to Dired+ (with
attribution), for use with older Emacs, even if it doesn't
get added to Emacs.
> Ideally, it could find the common prefix, then set
> default-directory to it and list only relative file names,
> like in the output of e.g. 'find-dired-with-command'.
Another good idea.
___
Here's the code I have for this now. If you add the feature
to Emacs then the Dired+ functions will just become aliases
for the vanilla Emacs functions (in releases where they exist).
(defun diredp-get-marked-files-in-all-buffers ()
"Return names of files and directories marked in any Dired buffers.
Like `dired-get-marked-files', but for all Dired buffers."
(diredp-delete-dups
(let ((dired-bufs (delq nil (mapcar (lambda (d.b)
(and (buffer-live-p (cdr d.b))
(cdr d.b)))
dired-buffers))))
(apply #'nconc
(mapcar (lambda (buf)
(with-current-buffer buf
(let ((files (dired-get-marked-files nil nil nil t)))
(setq files (and (cdr files) (if (eq (car files) t)
(cadr files)
files))))))
dired-bufs)))))
(defun diredp-marked-files-in-all-buffers ()
"Dired the files and directories marked in any Dired buffers.
Like `diredp-marked-files', but for all Dired buffers."
(interactive)
(let ((files (diredp-get-marked-files-in-all-buffers)))
(unless (directory-name-p common) (setq common (diredp-parent-dir common)))
(let ((default-directory (or common default-directory)))
(dired (cons "MARKED-ANYWHERE"
(if common
(mapcar (lambda (file) (file-relative-name file common))
files)
files)))))))
Differences from Phil's patch (besides the function names):
1. Use Juri's suggestion of using a common ancestor directory
and relative file names. IIRC, file systems can sometimes
have no common prefix - in which case use absolute names if
there's no common ancestor directory.
2. The Dired buffer is named `MARKED ANYWHERE', so as not to
interfere with (i.e., replace) another (e.g., normal)
listing of the same directory.
3. Use variable `dired-buffers', to check only Dired buffers
instead of all buffers.
4. Quick check of marked-files list (without `length').
___
FWIW -
Dired+ has long had commands that act on all marked files & dirs
in a Dired buffer, and all marked files & dirs in Dired buffers
for marked subdirs,... defined recursively.
IOW, instead of (as in Phil's feature) checking all Dired buffers
for markings, such functions check only the current Dired buffer,
Dired buffers for its marked subdirs, and so on recursively.
Applying `dired' to that collection of marked files & dirs is
only one possible action. In general, all of the usual actions
for marked files are provided (by separate commands).
Phil's feature is a good addition to such functionality.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Mon, 02 Jun 2025 16:24:02 GMT)
Full text and
rfc822 format available.
Message #20 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> (defun diredp-marked-files-in-all-buffers ()
> "Dired the files and directories marked in any Dired buffers.
> Like `diredp-marked-files', but for all Dired buffers."
> (interactive)
> (let ((files (diredp-get-marked-files-in-all-buffers)))
> (unless (directory-name-p common) (setq common (diredp-parent-dir
> common)))
> (let ((default-directory (or common default-directory)))
> (dired (cons "MARKED-ANYWHERE"
> (if common
> (mapcar (lambda (file) (file-relative-name file common))
> files)
> files)))))))
Typo - somehow I omitted some lines. Should have been this:
(defun diredp-marked-files-in-all-buffers ()
"Dired the files and directories marked in any Dired buffers.
Like `diredp-marked-files', but for all Dired buffers."
(interactive)
(let ((files (diredp-get-marked-files-in-all-buffers)))
(unless files (user-error "No marked files in any Dired buffer"))
(let ((common (try-completion "" files)))
(unless (directory-name-p common) (setq common (diredp-parent-dir common)))
(let ((default-directory (or common default-directory)))
(dired (cons "MARKED-ANYWHERE"
(if common
(mapcar (lambda (file) (file-relative-name file common))
files)
files)))))))
And it would be good to let users optionally name the resulting buffer:
(defun diredp-marked-files-in-all-buffers (&optional buffer-name)
"Dired the files and directories marked in any Dired buffers.
Like `diredp-marked-files', but for all Dired buffers.
With a prefix argument you're prompted for the name of the resulting
Dired buffer. Otherwise, the name is `MARKED-ANYWHERE'."
(interactive (list (if current-prefix-arg
(read-string "Resulting Dired buffer name: ")
"MARKED-ANYWHERE")))
(let ((files (diredp-get-marked-files-in-all-buffers)))
(unless files (user-error "No marked files in any Dired buffer"))
(let ((common (try-completion "" files)))
(unless (directory-name-p common) (setq common (diredp-parent-dir common)))
(let ((default-directory (or common default-directory)))
(dired (cons buffer-name
(if common
(mapcar (lambda (file) (file-relative-name file common))
files)
files)))))))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 11:39:03 GMT)
Full text and
rfc822 format available.
Message #23 received at 78658 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Hi Drew,
Thank you for:
> (let ((common (try-completion "" files)))
My brain had failed to make the connection between "completion"
and programmatically obtaining a common prefix from list of
strings. It makes perfect sense in hindsight, but I'd simply
never thought about completion in non-interactive terms, and was
surprised when I hadn't found a documented function for doing
this (but I wasn't looking under Completion at all).
Eli, I reckon this is worth either documenting somewhere under
(info "(elisp) Strings and Characters") or else creating a
slightly more string-centric wrapper, something like:
(defun string-common-prefix (strings)
"Return the largest common prefix from a list of STRINGS."
(let ((prefix (try-completion "" strings)))
(if (stringp prefix)
prefix
"")))
(And I now notice that the string shortdoc group *does*
include `try-completion' -- albeit without an example of
using "" for STRING, which I think would be a good addition.)
Regarding the buffer naming:
>> (dired (cons "MARKED-ANYWHERE"
It hadn't occurred to me that this could be something other
than a directory path. I definitely agree it would be ideal
not to conflict with other dired buffers, but I've seen some
some oddities from doing it that way. E.g. after creating
that buffer, I can't obtain it with:
(dired-find-buffer-nocreate "MARKED-ANYWHERE" 'dired-mode)
but rather I need to use:
(dired-find-buffer-nocreate "/path/to/MARKED-ANYWHERE" 'dired-mode)
for the file path it thinks is relevant, which then has some
possibility (albeit unlikely) of conflicting with a real path.
And also (for better or worse) the new command can create extra
MARKED-ANYWHERE buffers under different paths.
We could further reduce the chance of any conflict with an
actual file by choosing an even less-likely name; but perhaps
there's a cleaner solution.
The version I'm currently playing with is attached. I haven't
tested your version yet, but I've grabbed some of the changes
from the code you've shown.
I've split out a couple of extra functions which felt useful on
their own:
`file-name-directory-common-prefix'
"The nearest common ancestor directory for FILES."
`dired-get-explicitly-marked-files'
"Like `dired-get-marked-files' but always returns nil when
nothing is marked."
-Phil
[dired-on-marked-files-in-all-buffers.el (text/x-lisp, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 11:50:06 GMT)
Full text and
rfc822 format available.
Message #26 received at 78658 <at> debbugs.gnu.org (full text, mbox):
On 2025-06-01 18:10, Eli Zaretskii wrote:
>> + (dired (cons "/" files))
>
> Why "/"? It sounds arbitrary. Also non-portable; use
>
> (expand-file-name "/")
>
> instead.
Thanks Eli. I'm pretty fuzzy on the whole portability aspect of these
things, and have only GNU/Linux systems to test on, so I'm sure I'll
get things wrong. Hopefully they'll all be similarly straightforward
to resolve.
I'd used "/" at the time because the code was dealing only with the
absolute paths, so it wasn't arbitrary as such; but now that there's
additional code to figure out a common subdirectory (if any), there's
no need for a hard-coded value like that.
-Phil
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 12:25:04 GMT)
Full text and
rfc822 format available.
Message #29 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> Cc: 78658 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
> Date: Tue, 03 Jun 2025 23:37:57 +1200
> From: Phil Sainty <psainty <at> orcon.net.nz>
>
> Hi Drew,
>
> Thank you for:
>
> > (let ((common (try-completion "" files)))
>
> My brain had failed to make the connection between "completion"
> and programmatically obtaining a common prefix from list of
> strings. It makes perfect sense in hindsight, but I'd simply
> never thought about completion in non-interactive terms, and was
> surprised when I hadn't found a documented function for doing
> this (but I wasn't looking under Completion at all).
>
> Eli, I reckon this is worth either documenting somewhere under
> (info "(elisp) Strings and Characters") or else creating a
> slightly more string-centric wrapper, something like:
Feel free to suggest patches for the documentation, but please
remember that results of calling completion functions can depend on
the completion styles in effect, so if we want to advertise this as a
way of producing the largest common prefix, we should probably bind
completion-styles to something specific around this call.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 16:54:02 GMT)
Full text and
rfc822 format available.
Message #32 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> Dired+ has long had commands that act on all marked files & dirs
> in a Dired buffer, and all marked files & dirs in Dired buffers
> for marked subdirs,... defined recursively.
>
> IOW, instead of (as in Phil's feature) checking all Dired buffers
> for markings, such functions check only the current Dired buffer,
> Dired buffers for its marked subdirs, and so on recursively.
It would be too tedious to mark subdirs, so it should be sufficient
just to check all subdir Dired buffers. That would be useful for the
most common case of running this command from the project root dir
that will collect marked files from all project Dired buffers
and show the file names relative to the project root
where the command was run.
> Applying `dired' to that collection of marked files & dirs is
> only one possible action. In general, all of the usual actions
> for marked files are provided (by separate commands).
When all marked files are collected in one virtual Dired buffer,
then it's easy to perform all other possible actions from this buffer.
> And it would be good to let users optionally name the resulting buffer:
> (defun diredp-marked-files-in-all-buffers (&optional buffer-name)
> "Dired the files and directories marked in any Dired buffers.
> Like `diredp-marked-files', but for all Dired buffers.
> With a prefix argument you're prompted for the name of the resulting
> Dired buffer. Otherwise, the name is `MARKED-ANYWHERE'."
This is quite an ugly name, but the name pattern could be defined
by a new variable with a value like "*Dired Marked %s*" where %s
is replaced with the default directory.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 19:48:07 GMT)
Full text and
rfc822 format available.
Message #35 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> Thank you for: (let ((common (try-completion "" files)))
Thank you for your great idea, Phil.
> My brain had failed to make the connection between "completion"
> and programmatically obtaining a common prefix from list of
> strings. It makes perfect sense in hindsight, but I'd simply
> never thought about completion in non-interactive terms, and was
> surprised when I hadn't found a documented function for doing
> this (but I wasn't looking under Completion at all).
Understood. Same for everyone. I defined utility function
`diredp-common-ancestor-dir' for this (see below).
> Eli, I reckon this is worth either documenting somewhere under
> (info "(elisp) Strings and Characters") or else creating a
> slightly more string-centric wrapper, something like:
>
> (defun string-common-prefix (strings)
> "Return the largest common prefix from a list of STRINGS."
> (let ((prefix (try-completion "" strings)))
> (if (stringp prefix) prefix "")))
Dunno how useful that alone is, but maybe.
I'm using this now:
(defun diredp-common-ancestor-dir (files)
"Return the common ancestor directory of FILES, or nil if none."
(let ((common (try-completion "" files)))
(if (stringp common)
(unless (directory-name-p common) (setq common (diredp-parent-dir common)))
(when (eq t common) (setq common "")))
common))
And I've long used this helper a fair amount:
(defun diredp-parent-dir (file &optional relativep)
"Return the parent directory of FILE, or nil if none.
Optional arg RELATIVEP non-nil means return a relative name, that is,
just the parent component."
(let ((parent (file-name-directory (directory-file-name (expand-file-name file))))
relparent)
(when relativep (setq relparent (file-name-nondirectory (directory-file-name parent))))
(and (not (equal parent file)) (or relparent parent))))
> Regarding the buffer naming:
>
> >> (dired (cons "MARKED-ANYWHERE"
>
> It hadn't occurred to me that this could be something other
> than a directory path. I definitely agree it would be ideal
> not to conflict with other dired buffers, but I've seen some
> some oddities from doing it that way. E.g. after creating
> that buffer, I can't obtain it with:
>
> (dired-find-buffer-nocreate "MARKED-ANYWHERE" 'dired-mode)
> but rather I need to use:
> (dired-find-buffer-nocreate "/path/to/MARKED-ANYWHERE" 'dired-mode)
>
> for the file path it thinks is relevant, which then has some
> possibility (albeit unlikely) of conflicting with a real path.
I don't worry about that. When DIRNAME is a cons, its car is
just used as a buffer name. It shouldn't (and needn't) ever
be taken as a directory.
> And also (for better or worse) the new command can create extra
> MARKED-ANYWHERE buffers under different paths.
For better, IMO.
You'll get additional buffers, named `MARKED-ANYWHERE <abc>' etc.
With my code a user can anyway provide a different buffer name.
You can have multiple such Dired buffers, with different names,
for different sets of markings, for different purposes/contexts.
> We could further reduce the chance of any conflict with an
> actual file by choosing an even less-likely name; but perhaps
> there's a cleaner solution.
It's a buffer name. I don't see how conflicts with file names
are relevant.
> The version I'm currently playing with is attached. I haven't
> tested your version yet, but I've grabbed some of the changes
> from the code you've shown.
>
> I've split out a couple of extra functions which felt useful on
> their own:
>
> `file-name-directory-common-prefix'
> "The nearest common ancestor directory for FILES."
>
> `dired-get-explicitly-marked-files'
> "Like `dired-get-marked-files' but always returns nil when
> nothing is marked."
I too have a few utility functions, but not the same:
diredp-common-ancestor-dir (see above)
diredp-parent-dir (see above)
diredp-live-dired-buffers
diredp-explicit
This is what I'm using now:
(defun diredp-get-marked-files-in-all-buffers ()
"Return names of files and directories marked in any Dired buffers.
Like `dired-get-marked-files', but for all Dired buffers."
(delete-dups
(let ((dired-bufs (diredp-live-dired-buffers)))
(apply #'nconc
(mapcar (lambda (buf)
(with-current-buffer buf
(let ((files (dired-get-marked-files nil nil nil t)))
(setq files (and (cdr files) (if (eq (car files) t)
(list (cadr files))
files))))))
dired-bufs)))))
(defun diredp-live-dired-buffers ()
"Return a list of the live Dired buffers."
(delq nil (mapcar (lambda (d.b)(and (buffer-live-p (cdr d.b)) (cdr d.b)))
dired-buffers)))
(defun diredp-marked-in-any-buffers (&optional files buffer-name)
"Dired the files and directories marked in any Dired buffers.
Like `diredp-marked-files', but for all Dired buffers.
With a prefix argument you're prompted for the name of the resulting
Dired buffer. Otherwise, the name is `MARKED-ANYWHERE'.
This command is only for interactive use."
(interactive (let ((fils (diredp-get-marked-files-in-all-buffers)))
(unless files (user-error "No marked files in any Dired buffer"))
(list fils (if current-prefix-arg
(read-string "Resulting Dired buffer name: ")
"MARKED-ANYWHERE"))))
(diredp-explicit files buffer-name))
(defun diredp-explicit (files buffer-name &optional other-window-p)
"Dired FILES (a list of absolute file names) in buffer BUFFER-NAME.
The names are listed relative to their common-ancestor directory or,
if none, relative to the current value of `default-directory'.
Non-nil OTHER-WINDOW-P means use `dired-other-window', not `dired'."
(let ((common (diredp-common-ancestor-dir files)))
(let ((default-directory (or common default-directory)))
(funcall (if other-window-p #'dired-other-window #'dired)
(cons buffer-name (if common
(mapcar (lambda (file)
(file-relative-name file common))
files)
files))))))
(defun diredp-common-ancestor-dir (files)
"Return the common ancestor directory of FILES, or nil if none."
(let ((common (try-completion "" files)))
(if (stringp common)
(unless (directory-name-p common) (setq common (diredp-parent-dir common)))
(when (eq t common) (setq common "")))
common))
(defun diredp-parent-dir (file &optional relativep)
"Return the parent directory of FILE, or nil if none.
Optional arg RELATIVEP non-nil means return a relative name, that is,
just the parent component."
(let ((parent (file-name-directory (directory-file-name (expand-file-name file))))
relparent)
(when relativep
(setq relparent (file-name-nondirectory (directory-file-name parent))))
(and (not (equal parent file)) (or relparent parent))))
Dunno whether it's worth having something like your
`dired-get-explicitly-marked-files'. But IMO it's anyway
better not to use `length' - better to just test for the
`t' explicit-marked case:
(and (cdr files) ; Return nil for unmarked singleton
(if (eq (car files) t) ; Marked singleton - listify it.
(list (cadr files))
files)) ; Multiple files
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 19:50:09 GMT)
Full text and
rfc822 format available.
Message #38 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > Dired+ has long had commands that act on all marked files & dirs
> > in a Dired buffer, and all marked files & dirs in Dired buffers
> > for marked subdirs,... defined recursively.
> >
> > IOW, instead of (as in Phil's feature) checking all Dired buffers
> > for markings, such functions check only the current Dired buffer,
> > Dired buffers for its marked subdirs, and so on recursively.
>
> It would be too tedious to mark subdirs,
I don't agree. It's simple and practical.
You may be thinking of your use case (below), where you
apparently want (1) a Dired buffer for each descendant
directory, (2) a Dired buffer for the top-level dir,
and (3) a Dired buffer for each subdir marked in each
such buffer.
The general case is, well, more general: you want to do
something to or with some, not all, files and dirs in a
listing, so you mark them.
> so it should be sufficient
> just to check all subdir Dired buffers. That would be useful for the
> most common case of running this command from the project root dir
> that will collect marked files from all project Dired buffers
> and show the file names relative to the project root
> where the command was run.
I don't think that's "the most common case", and I don't
think there is a "most common case". It's generally useful
to do what I described.
In some ways it's similar to doing things in a single Dired
buffer with inserted descendant directories. In other ways
it's different. Both (inserted dirs and separate buffers)
are useful.
Inserting all subdirs is rare - there's no "most common case"
of inserting all subdirs. That use case isn't "sufficient".
And the same holds for when you use multiple Dired buffers
instead (or in addition!).
> > Applying `dired' to that collection of marked files & dirs is
> > only one possible action. In general, all of the usual actions
> > for marked files are provided (by separate commands).
>
> When all marked files are collected in one virtual Dired buffer,
> then it's easy to perform all other possible actions from this buffer.
That's the "insertion" approach, applied thoroughly. It's
long been available: just one big Dired buffer, containing
listings of all descendant directories. When was the last
time you actually used such a listing?
> > And it would be good to let users optionally name the resulting buffer:
> > (defun diredp-marked-files-in-all-buffers (&optional buffer-name)
> > "Dired the files and directories marked in any Dired buffers.
> > Like `diredp-marked-files', but for all Dired buffers.
> > With a prefix argument you're prompted for the name of the resulting
> > Dired buffer. Otherwise, the name is `MARKED-ANYWHERE'."
The name I'm using now is `diredp-marked-in-any-buffers'.
I dropped the "files" part, in keeping with other Dired+
command names.
(And because it's really file and/or dir names that are
marked. And actually it's _lines_ of a listing that are
marked -- not files, not files & dirs, not file & dir
names -- just lines.)
I have other `diredp-marked-*' commands. E.g., `diredp-marked'
opens Dired on the marked files and directories.
`diredp-marked-recursive' is similar, but it opens Dired on
marked files & dirs, plus those marked in Dired buffers for
any marked subdirs, etc., defined recursively.
There are lots of other commands that act on marked files &
dirs, defined recursively or not, in ways other than opening
Dired on them.
> This is quite an ugly name, but the name pattern could be defined
> by a new variable with a value like "*Dired Marked %s*" where %s
> is replaced with the default directory.
Whatever. `default-directory' is shown in the top-level
directory header line. And it's available via `C-h v'.
I don't see that putting it in the buffer name is useful.
More likely, a user will want a buffer name that's specific
to some given context or purpose: what the buffer is _for_ --
a given project, a particular kind of markings (e.g. file types,
dates), or whatever. The default directory isn't so important,
generally.
The default buffer name should be a simple placeholder that
says what the buffer is about in a _general_ way. In general,
this is about files & dirs gathered because they were marked
in some Dired buffers.
Note that it's about some set of markings that existed when
the new Dired buffer was created. Those markings need not
continue to exist. And yet the MARKED-ANYWHERE Dired buffer
can continue to exist. It can even be bookmarked (persisted)
and restored later.
And such a set of files & dirs need not even have a common
ancestor directory. A file system can be a forest, not a tree.
That's the case for MS Windows, for example: two drives don't
have any parent. The code works fine for such cases; entries
that don't have a common ancestor are listed with absolute names.
The Dired buffer created from marked files from different trees
(e.g. different Windows drives) has a `default-directory', yes,
but it isn't relevant to all of the listed files, in the same
way that it would be relevant in a "normal" Dired buffer.
E.g., here's a MARKED-ANYWHERE <toto> buffer:
c:/usr/toto:
d:/usr/toto/bbbbb/31 octobre 2022 Paris.zip
d:/usr/toto/bbbbb/aaaa-YYY
bbbbb/aaaa-YYY
The default directory is shown in the directory header line:
c:/usr/toto:. The 2nd and 3rd files listed have the same
name and the same parent-directory name, but they're on
different drives. The 3rd file is listed with a name relative
to the default directory. The 1st and 2nd files are listed
with absolute names. They have no relation to the default
directory or even to its drive; they're on the D drive, not
the C drive.
Dired buffers from a cons DIRNAME are somewhat strange critters.
They're essentially "snapshot" listings. In some cases it can
make sense when reverting them to reflect the current state of
the file system (e.g., removing entries for files that have
been deleted). I do that, for example, for a snapshot-listing
command `diredp-dired-recent-files'.
In other cases it makes little or sense to do that, and what
you want really is a snapshot listing of some former state.
Reverting the buffer just relists (replays) the recorded
file names, as is. This is the case we're talking about now,
MARKED-ANYWHERE buffers.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 19:56:08 GMT)
Full text and
rfc822 format available.
Message #41 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > > (let ((common (try-completion "" files)))
> >
> > My brain had failed to make the connection between "completion"
> > and programmatically obtaining a common prefix from list of
> > strings. It makes perfect sense in hindsight, but I'd simply
> > never thought about completion in non-interactive terms, and was
> > surprised when I hadn't found a documented function for doing
> > this (but I wasn't looking under Completion at all).
> >
> > Eli, I reckon this is worth either documenting somewhere under
> > (info "(elisp) Strings and Characters") or else creating a
> > slightly more string-centric wrapper, something like:
>
> Feel free to suggest patches for the documentation, but please
> remember that results of calling completion functions can depend on
> the completion styles in effect, so if we want to advertise this as a
> way of producing the largest common prefix, we should probably bind
> completion-styles to something specific around this call.
That may be a good point. In a way it's too bad that
`completion-styles' affects `try-completion'.
Or maybe I should say that it's too bad we don't have a
better primitive for this purpose than `try-completion'.
In a way, we're reusing something that wasn't really
designed for this use.
There's also `fill-common-string-prefix', but that
just takes two strings as arg. What's called for is
a function that takes a list of strings as arg (like
`try-completion' does).
In the code that I show in my reply today to Phil, I
too didn't bother to bind `completion-styles'. But
I agree that if we use `try-completion' in this way
then maybe we should do that.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 20:10:10 GMT)
Full text and
rfc822 format available.
Message #44 received at 78658 <at> debbugs.gnu.org (full text, mbox):
Drew Adams via "Bug reports for GNU Emacs, the Swiss army knife of text
editors" <bug-gnu-emacs <at> gnu.org> writes:
>> > > (let ((common (try-completion "" files)))
>> >
>> > My brain had failed to make the connection between "completion"
>> > and programmatically obtaining a common prefix from list of
>> > strings. It makes perfect sense in hindsight, but I'd simply
>> > never thought about completion in non-interactive terms, and was
>> > surprised when I hadn't found a documented function for doing
>> > this (but I wasn't looking under Completion at all).
>> >
>> > Eli, I reckon this is worth either documenting somewhere under
>> > (info "(elisp) Strings and Characters") or else creating a
>> > slightly more string-centric wrapper, something like:
>>
>> Feel free to suggest patches for the documentation, but please
>> remember that results of calling completion functions can depend on
>> the completion styles in effect, so if we want to advertise this as a
>> way of producing the largest common prefix, we should probably bind
>> completion-styles to something specific around this call.
>
> That may be a good point. In a way it's too bad that
> `completion-styles' affects `try-completion'.
Note that the `completion-styles' only affect
`completion-try-completion' and `completion-all-completions', but not
the primitive `try-completion', which always computes the common prefix.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 20:11:07 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 20:13:08 GMT)
Full text and
rfc822 format available.
Message #50 received at submit <at> debbugs.gnu.org (full text, mbox):
> >> Feel free to suggest patches for the documentation, but please
> >> remember that results of calling completion functions can depend on
> >> the completion styles in effect, so if we want to advertise this as a
> >> way of producing the largest common prefix, we should probably bind
> >> completion-styles to something specific around this call.
> >
> > That may be a good point. In a way it's too bad that
> > `completion-styles' affects `try-completion'.
>
> Note that the `completion-styles' only affect
> `completion-try-completion' and `completion-all-completions', but not
> the primitive `try-completion', which always computes the common prefix.
Thanks, I'd forgotten that.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Tue, 03 Jun 2025 20:13:12 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 06:16:02 GMT)
Full text and
rfc822 format available.
Message #56 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> You may be thinking of your use case (below), where you
> apparently want (1) a Dired buffer for each descendant
> directory, (2) a Dired buffer for the top-level dir,
> and (3) a Dired buffer for each subdir marked in each
> such buffer.
To avoid misunderstanding, here is the use case that I meant:
1. mark the file dired.el in the 'lisp' dir;
2. mark the file vc-dir.el in the 'lisp/vc' dir;
3. in the root dir invoke 'dired-on-marked-files'
and it shows the list of
lisp/dired.el
lisp/vc/vc-dir.el
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 08:37:04 GMT)
Full text and
rfc822 format available.
Message #59 received at 78658 <at> debbugs.gnu.org (full text, mbox):
On 2025-06-04 08:09, Daniel Mendler wrote:
> Note that the `completion-styles' only affect
> `completion-try-completion' and `completion-all-completions', but not
> the primitive `try-completion', which always computes the common
> prefix.
Thanks for confirming that.
There are a couple of edge-cases for `try-completion' which made me
think a new wrapper function for the "find the longest string prefix"
case would be a good thing, which are:
(try-completion "" '())
nil
(try-completion "" '(""))
t
Hence:
(defun string-common-prefix (strings)
"Return the largest common prefix from a list of STRINGS."
(let ((prefix (try-completion "" strings)))
(if (stringp prefix)
prefix
"")))
In both of the special cases, an empty string is what I'd want to get
from a function for finding the longest common prefix.
In the case of '("") that's because the empty string is the literal
correct result.
In the case of '() I think an empty string "" is the most useful
result for code expecting/requiring a string, avoiding any need to
test for a nil value. One might argue for returning nil here -- but
any code wanting that can test the list argument instead, as the only
way for (try-completion "" list) to return nil is if `list' is nil (or
if it's not a list of strings, which I'd consider invalid enough to be
ignored).
I think this would be a more-discoverable and better-behaved function
for simple "find the longest common prefix" needs.
-Phil
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 08:38:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 08:59:01 GMT)
Full text and
rfc822 format available.
Message #65 received at submit <at> debbugs.gnu.org (full text, mbox):
Phil Sainty <psainty <at> orcon.net.nz> writes:
> On 2025-06-04 08:09, Daniel Mendler wrote:
>> Note that the `completion-styles' only affect
>> `completion-try-completion' and `completion-all-completions', but not
>> the primitive `try-completion', which always computes the common prefix.
>
> Thanks for confirming that.
>
> There are a couple of edge-cases for `try-completion' which made me
> think a new wrapper function for the "find the longest string prefix"
> case would be a good thing, which are:
>
> (try-completion "" '())
> nil
>
> (try-completion "" '(""))
> t
>
> Hence:
>
> (defun string-common-prefix (strings)
> "Return the largest common prefix from a list of STRINGS."
> (let ((prefix (try-completion "" strings)))
> (if (stringp prefix)
> prefix
> "")))
Note that try-completion can also return `t' and in that case you want
to return the exact string, not the empty string. Also you may want to
bind some completion variables like `completion-regexp-list' and
`completion-ignore-case' to nil (or to an `ignore-case' argument), such
that they do not affect the result. These dynamic variables are not user
settings, but are usually let-bound inside completion style functions
like `completion--pcm-all-completions'. Please take a close look at the
documentation of `try-completion'. In any case, I agree that such a
wrapper would be good to have and easier to use.
Daniel
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 08:59:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 09:44:02 GMT)
Full text and
rfc822 format available.
Message #71 received at 78658 <at> debbugs.gnu.org (full text, mbox):
On 2025-06-04 20:57, Daniel Mendler wrote:
> Note that try-completion can also return `t' and in that case you
> want to return the exact string, not the empty string.
I believe I've accounted for that -- my function is passing the
empty string as the first argument to try-completion, and therefore
"the exact string" can only be the empty string (AFAICS).
> Also you may want to
> bind some completion variables like `completion-regexp-list' and
> `completion-ignore-case' to nil (or to an `ignore-case' argument), such
> that they do not affect the result. These dynamic variables are not
> user
> settings, but are usually let-bound inside completion style functions
> like `completion--pcm-all-completions'. Please take a close look at the
> documentation of `try-completion'. In any case, I agree that such a
> wrapper would be good to have and easier to use.
Thank you; I'll make those changes and check the docs to see if I can
spot anything else.
-Phil
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 09:45:03 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 17:20:03 GMT)
Full text and
rfc822 format available.
Message #77 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > > > Dired+ has long had commands that act on all marked files & dirs
> > > > in a Dired buffer, and all marked files & dirs in Dired buffers
> > > > for marked subdirs,... defined recursively.
> > > >
> > > > IOW, instead of (as in Phil's feature) checking all Dired buffers
> > > > for markings, such functions check only the current Dired buffer,
> > > > Dired buffers for its marked subdirs, and so on recursively.
> > >
> > > It would be too tedious to mark subdirs,
> >
> > I don't agree. It's simple and practical.
> >
> > You may be thinking of your use case (below), where you
> > apparently want (1) a Dired buffer for each descendant
> > directory, (2) a Dired buffer for the top-level dir,
> > and (3) a Dired buffer for each subdir marked in each
> > such buffer.
>
> To avoid misunderstanding, here is the use case that I meant:
>
> 1. mark the file dired.el in the 'lisp' dir;
> 2. mark the file vc-dir.el in the 'lisp/vc' dir;
> 3. in the root dir invoke 'dired-on-marked-files'
>
> and it shows the list of
>
> lisp/dired.el
> lisp/vc/vc-dir.el
Sounds like we're miscommunicating. You're now talking about
`dired-on-marked-files', by which I guess you mean Phil's
`dired-on-marked-files-in-all-buffers'. That doesn't require
any marking of subdirs.
But you didn't reply "It would be too tedious to mark subdirs",
to anything about `dired-on-marked-files-in-all-buffers'. You
replied that to my mention of the Dired+ feature of selectively
acting on marked files & dirs in Dired buffers for marked subdirs.
And you seemed to be saying that for that the most common case
is to want to act on all marked lines in all Dired buffers for
subdir listings (at all levels). IOW, no selectivity.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 17:52:02 GMT)
Full text and
rfc822 format available.
Message #80 received at 78658 <at> debbugs.gnu.org (full text, mbox):
>> To avoid misunderstanding, here is the use case that I meant:
>>
>> 1. mark the file dired.el in the 'lisp' dir;
>> 2. mark the file vc-dir.el in the 'lisp/vc' dir;
>> 3. in the root dir invoke 'dired-on-marked-files'
>>
>> and it shows the list of
>>
>> lisp/dired.el
>> lisp/vc/vc-dir.el
>
> Sounds like we're miscommunicating. You're now talking about
> `dired-on-marked-files', by which I guess you mean Phil's
> `dired-on-marked-files-in-all-buffers'. That doesn't require
> any marking of subdirs.
Yes, I removed the name suffix, but now realized a better name
for the above logic would be `dired-on-marked-files-in-subdirs'.
> But you didn't reply "It would be too tedious to mark subdirs",
> to anything about `dired-on-marked-files-in-all-buffers'. You
> replied that to my mention of the Dired+ feature of selectively
> acting on marked files & dirs in Dired buffers for marked subdirs.
>
> And you seemed to be saying that for that the most common case
> is to want to act on all marked lines in all Dired buffers for
> subdir listings (at all levels). IOW, no selectivity.
Maybe I misunderstood your description, but I thought that
with the above use case, to be able to include lisp/vc/vc-dir.el
to the composite Dired bufer, you require also marking
the subdir 'lisp', and then also marking the subdir 'vc',
that requires too much extra effort from the user.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 18:28:02 GMT)
Full text and
rfc822 format available.
Message #83 received at 78658 <at> debbugs.gnu.org (full text, mbox):
I wrote:
> (defun diredp-live-dired-buffers ()
> "Return a list of the live Dired buffers."
> (delq nil (mapcar (lambda (d.b)
> (and (buffer-live-p (cdr d.b)) (cdr d.b)))
> dired-buffers)))
I'm afraid I may have led you (and myself) astray, by suggesting to
use variable `dired-buffers' instead of testing all buffers.
(I see you adopted that in your latest code.)
It works fine, and it's much faster by not bothering with non-Dired
buffers. The problem is that it doesn't work with commands
`find-dired' and `find-lisp-find-dired*'. They produce legitimate
Dired buffers, and they work fine with the feature we're discussing,
but they're excluded from `dired-buffers'. They have this binding:
(let ((dired-buffers dired-buffers))...)
_Should_ they be excluded from `dired-buffers'? Maybe so, maybe not.
They support most Dired features, and their mode is `dired-mode', but
there are perhaps a few Dired features they don't support (dunno what,
offhand - they support WDired and everything else that occurs to me
offhand). (I wish their code included a comment as to _why_ they have
that binding.)
Anyway, if we do want to support such buffers (which we should) then
we unfortunately need to check all buffers, not just those in variable
`dired-buffers'.
So my function `diredp-live-dired-buffers' needs to change from this:
(defun diredp-live-dired-buffers ()
"Return a list of the live Dired buffers."
(delq nil (mapcar (lambda (d.b)
(and (buffer-live-p (cdr d.b)) (cdr d.b)))
dired-buffers)))
to this:
(defun diredp-live-dired-buffers ()
"Return a list of the live Dired buffers."
(delq nil (mapcar (lambda (buf)
(and (buffer-live-p buf)
(with-current-buffer buf
(and (derived-mode-p 'dired-mode) buf))))
(buffer-list))))
Or maybe make it more general, to handle either 100% Dired buffers
or (optionally) both those and the find-* Dired buffers:
(defun diredp-live-dired-buffers (&optional exclude-find-bufs-p)
"Return a list of the live Dired buffers.
Non-nil EXCLUDE-FIND-BUFS-P means exclude Dired buffers that aren't
listed in variable `dired-buffers'. Examples are the Dired buffers
from commands `find*-dired' and `find-lisp-find-dired*'."
(delq nil
(if exclude-find-bufs-p
(mapcar (lambda (d.b)
(and (buffer-live-p (cdr d.b)) (cdr d.b)))
dired-buffers)
(mapcar (lambda (buf)
(and (buffer-live-p buf)
(with-current-buffer buf
(and (derived-mode-p 'dired-mode) buf))))
(buffer-list)))))
There's no need for that general version in the current scenario,
but it's maybe a better utility function that way.
BTW, do you find that using `(delete-consecutive-dups (sort...))'
is a whole lot faster than just using `delete-dups'. I guess it
is, but it's ugly - had to read the source code to understand it.
[IMO, the doc should say something about its use cases, i.e., when
to use it instead of `delete-dups'. The doc doesn't even mention
that it's for _sorted_ lists, or at least sorted enough that all
dups you might care about are consecutive.]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Wed, 04 Jun 2025 20:19:02 GMT)
Full text and
rfc822 format available.
Message #86 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > Sounds like we're miscommunicating. You're now talking about
> > `dired-on-marked-files', by which I guess you mean Phil's
> > `dired-on-marked-files-in-all-buffers'. That doesn't require
> > any marking of subdirs.
>
> Yes, I removed the name suffix, but now realized a better name
> for the above logic would be `dired-on-marked-files-in-subdirs'.
"in-subdirs" isn't right, IMO, because it's about marked files in
_any_ Dired buffers - nothing to do with subdirs of any particular
directory.
I think a better name is what I'm using in Dired+,
`diredp-marked-in-any-buffers' (but without the `p').
[I use "any", not "all", because "all" might be misinterpreted as
a requirement to be present in all buffers (AND, not OR). And I
don't include "files" because it's about marked files and dirs
(it's actually about marked lines). You can, for example, mark
only directory lines, and then perform an action on those dirs.]
> Maybe I misunderstood your description, but I thought that
> with the above use case, to be able to include lisp/vc/vc-dir.el
> to the composite Dired bufer, you require also marking
> the subdir 'lisp', and then also marking the subdir 'vc',
> that requires too much extra effort from the user.
The Dired+ feature I described is about selectively choosing
descendant dirs whose marked files you want to act on. Just
as you choose the files, so you choose the dirs. Markings
are selective.
That selectivity is a feature, not a bug. So it makes no
sense to say that what you really want is to act on all marked
files in _all_ descendant dirs, and that that's the "most
common case", and it's too cumbersome to mark all descendant
dirs.
If that's your use case, you can write a simple command to do it,
or use `diredp-mark-directories-recursive' (`M-+ * /') with a
negative prefix arg, which tells it to ignore subdir markings
and act on _all_ subdirs, recursively. I.e., `M-- M-+ * /'.
(All `*-recursive' commands are on prefix key `M-+'. The rest
of the key is `* /', the same non-recursive, vanilla command
`diredp-mark-directories'. Similarly, `M-+ M-DEL' to remove
all markings recursively.)
Again though, is that also your most common case for insertion
of subdirs in a Dired buffer? Do you always or often do that:
insert all descendant dirs into a Dired buffer? I may never
have done that. In any case, it's far from the "most common
case" for users in general, IMO. The same goes for acting on
descendant dirs whose listings are in separate Dired buffers,
IMO.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Thu, 05 Jun 2025 06:40:02 GMT)
Full text and
rfc822 format available.
Message #89 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> Again though, is that also your most common case for insertion
> of subdirs in a Dired buffer? Do you always or often do that:
> insert all descendant dirs into a Dired buffer? I may never
> have done that. In any case, it's far from the "most common
> case" for users in general, IMO. The same goes for acting on
> descendant dirs whose listings are in separate Dired buffers,
> IMO.
Nope, I didn't mean inserting subdirs with 'dired-maybe-insert-subdir'.
I meant only collecting marked files from subdirs.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Thu, 05 Jun 2025 08:31:01 GMT)
Full text and
rfc822 format available.
Message #92 received at 78658 <at> debbugs.gnu.org (full text, mbox):
On 2025-06-05 06:26, Drew Adams wrote:
> I'm afraid I may have led you (and myself) astray, by suggesting to
> use variable `dired-buffers' instead of testing all buffers.
> (I see you adopted that in your latest code.)
>
> It works fine, and it's much faster by not bothering with non-Dired
> buffers. The problem is that it doesn't work with commands
> `find-dired' and `find-lisp-find-dired*'. They produce legitimate
> Dired buffers, and they work fine with the feature we're discussing,
> but they're excluded from `dired-buffers'. They have this binding:
>
> (let ((dired-buffers dired-buffers))...)
Ah, yes :/ Along with their derivative commands.
> _Should_ they be excluded from `dired-buffers'? Maybe so, maybe not.
> They support most Dired features, and their mode is `dired-mode', but
> there are perhaps a few Dired features they don't support (dunno what,
> offhand - they support WDired and everything else that occurs to me
> offhand). (I wish their code included a comment as to _why_ they have
> that binding.)
The following seems to be the best there is, which doesn't help
beyond confirming that it's intentional (which was already clear
from the binding itself).
commit 0322a154b764f8358ba8913dc6fc724ba9f4294d
Author: Richard M. Stallman <rms <at> gnu.org>
Date: Sat Jun 27 21:59:11 1998 +0000
(find-dired): Bind dired-buffers so it can't change. Use
abbreviate-file-name.
The symbol doesn't crop up in too many places:
./find-lisp.el:47:(defvar dired-buffers)
./find-lisp.el:217: (let ((dired-buffers dired-buffers)
./find-dired.el:226: (let ((dired-buffers dired-buffers))
./bs.el:187: ;; Dired-Buffers
./dired.el:1093: dired-buffers)))))
./dired.el:1488:(defvar dired-buffers nil
./dired.el:1520: (let (found (blist dired-buffers)) ; was
(buffer-list)
./dired.el:3592:`dired-buffers'."
./dired.el:3595: (dolist (elt dired-buffers)
./dired.el:3600: (setq dired-buffers (delq elt dired-buffers)))
./dired.el:3619:`dired-buffers'."
./dired.el:3622: (dolist (elt dired-buffers)
./dired.el:3627: (setq dired-buffers (delq elt dired-buffers)))
./dired.el:3667: ;;"Advertise in variable `dired-buffers' that we dired
`default-directory'."
./dired.el:3672: (setq dired-buffers
./dired.el:3674: dired-buffers)))))
./dired.el:3677: ;; Remove DIR from the buffer alist in variable
dired-buffers.
./dired.el:3681: (setq dired-buffers
./dired.el:3682: (delq (assoc (expand-file-name dir) dired-buffers)
dired-buffers)))
./org/org-capture.el:76:(defvar dired-buffers)
./org/org-capture.el:705: dired-buffers))))
So auditing the associated behaviours might be an option,
to see if some reason for it becomes apparent.
Offhand it seems odd to me.
-Phil
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Thu, 05 Jun 2025 16:19:07 GMT)
Full text and
rfc822 format available.
Message #95 received at 78658 <at> debbugs.gnu.org (full text, mbox):
+Eli, Stefan K, Andrea, and RMS, for the find* Dired buffers
question (variable `dired-buffers').
_____
> > _Should_ they be excluded from `dired-buffers'? Maybe so, maybe not.
> > They support most Dired features, and their mode is `dired-mode', but
> > there are perhaps a few Dired features they don't support (dunno what,
> > offhand - they support WDired and everything else that occurs to me
> > offhand). (I wish their code included a comment as to _why_ they have
> > that binding.)
>
> The following seems to be the best there is, which doesn't help
> beyond confirming that it's intentional (which was already clear
> from the binding itself).
>
> commit 0322a154b764f8358ba8913dc6fc724ba9f4294d
> Author: Richard M. Stallman <rms <at> gnu.org>
> Date: Sat Jun 27 21:59:11 1998 +0000
> (find-dired): Bind dired-buffers so it can't change. Use
> abbreviate-file-name.
>
> The symbol doesn't crop up in too many places:
Yes, as I said, only find-dired.el and find-lisp.el.
> So auditing the associated behaviours might be an option,
> to see if some reason for it becomes apparent.
Dunno how to audit such a thing.
> Offhand it seems odd to me.
Yes.
My guess is that it was done only as a precaution, not
knowing what eventual differences might be introduced
between "regular" Dired buffers and the find* ones.
A Dired buffer with cons DIRNAME (i.e., an arbitrary set
of files, not the result of something like `ls') has
similar differences (limitations) wrt "regular" Dired
buffers, and such buffers are included in `dired-buffers'.
To me, the find* Dired buffers are pretty much akin to the
arbitrary-files Dired buffers.
But I may be missing something. Is there a Dired expert
in the house? Or someone with memory of this? Or some
way to check non-vanilla code in the wild, to see if this
really matters for find* buffers?
____
Maybe Eli, Stefan K., Andrea, or RMS has a suggestion.
The question is whether we can reasonably remove this
binding from the find-dired.el and find-lisp.el code:
(let ((dired-buffers dired-buffers))...)
IOW, is there a good reason to preclude find* Dired
buffers from the value of `dired-buffers'?
The advantage of not excluding them is that when looking
for Dired buffers we don't need to filter the entire
`buffer-list'; we can just use `dired-buffers' as the
search space.
Note: `dired-buffers' are buffers with mode derived from
`dired-mode'. The list is filled by `dired-advertise'
and reduced by `dired-unadvertise'. It doesn't include
`wdired-mode' buffers, for example, because WDired uses
`dired-unadvertise'.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Thu, 05 Jun 2025 18:47:02 GMT)
Full text and
rfc822 format available.
Message #98 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> From: Drew Adams <drew.adams <at> oracle.com>
> CC: "78658 <at> debbugs.gnu.org" <78658 <at> debbugs.gnu.org>,
> Juri Linkov
> <juri <at> linkov.net>, Eli Zaretskii <eliz <at> gnu.org>,
> Stefan Kangas
> <stefankangas <at> gmail.com>,
> Andrea Corallo <acorallo <at> gnu.org>, "rms <at> santafe.edu" <rms <at> gnu.org>
> Date: Thu, 5 Jun 2025 16:18:34 +0000
>
> +Eli, Stefan K, Andrea, and RMS, for the find* Dired buffers
> question (variable `dired-buffers').
Sorry, I don't understand the question. This discussion talks about
many different issues, and it's hard for me to re-read all of it to
glean only the parts related to that variable. So please ask the
specific question you have about dired-buffers, and please provide the
necessary background information to understand why let-binding it (or
anything else) is a bother in this case.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Thu, 05 Jun 2025 21:26:02 GMT)
Full text and
rfc822 format available.
Message #101 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > +Eli, Stefan K, Andrea, and RMS, for the find* Dired buffers
> > question (variable `dired-buffers').
>
> Sorry, I don't understand the question. This discussion talks about
> many different issues, and it's hard for me to re-read all of it to
> glean only the parts related to that variable. So please ask the
> specific question you have about dired-buffers, and please provide the
> necessary background information to understand why let-binding it (or
> anything else) is a bother in this case.
I did say this much in the same message, at least:
> > Maybe Eli, Stefan K., Andrea, or RMS has a suggestion.
> > The question is whether we can reasonably remove this
> > binding from the find-dired.el and find-lisp.el code:
> >
> > (let ((dired-buffers dired-buffers))...)
> >
> > IOW, is there a good reason to preclude find* Dired
> > buffers from the value of `dired-buffers'?
> >
> > The advantage of not excluding them is that when looking
> > for Dired buffers we don't need to filter the entire
> > `buffer-list'; we can just use `dired-buffers' as the
> > search space.
> >
> > Note: `dired-buffers' are buffers with mode derived from
> > `dired-mode'. The list is filled by `dired-advertise'
> > and reduced by `dired-unadvertise'. It doesn't include
> > `wdired-mode' buffers, for example, because WDired uses
> > `dired-unadvertise'.
I think that makes the question clear: whether we can remove
the binding that excludes find* Dired buffers from the list,
and if not, why not (what's the value of excluding them)?
But here's some more background -
In the current enhancement request (#78658), the plan is to
add a command that gathers all of the files & dirs that are
marked in any Dired buffers, and open Dired on only those
files & dirs.
(Passing a cons as arg DIRNAME to `dired' opens Dired in the
buffer that's the car of the cons, for just the list of files
that are the cdr.)
To do that, the command needs to work with a list of all
Dired buffers. The ability to do something with the list of
all Dired buffers is of course more general than this command
- more uses.
When `dired-mode' is invoked it calls `dired-advertise',
which adds the Dired buffer to the value of global variable
`dired-buffers'. A couple commands remove a buffer name from
this list, by calling `dired-unadvertise'. In particular,
`wdired-change-to-wdired-mode' does this, because it changes
the major mode from `dired-mode' to `wdired-mode'.
The value of var `dired-buffers' is thus generally a list of
all buffers in `dired-mode'. (This can include buffers that
have been killed, so filtering with `buffer-live-p' is also
needed.)
The only exceptions are (1) commands `find-dired' and its
derivatives such as `find-name-dired', and (2) commands
`find-lisp-dired*'. They're exceptions because they bind
`dired-buffers' around their work (see above), so as not to
add their resulting Dired buffers to `dired-buffers'.
This means that code can't just examine `dired-buffers' to
find the set of Dired buffers (buffers advertised to be in
`dired-mode'). Instead, it needs to filter `buffer-list',
to gather the buffers with modes derived from `dired-mode'.
That's unfortunate - it's much more costly, in general.
The question is whether there's a good reason why find*
buffers, which are in `dired-mode', should be excluded from
being "advertised" as such, i.e., whether they should really
be excluded from `dired-buffers'. And if so, why?
It was apparently a 1998 commit by Richard that added the
protective binding to `find-dired', but with no comment as
to why.
In the Emacs sources, at least, there are no other places
that exclude `dired-mode' buffers from `dired-buffers'.
And grepping for `find-dired' shows that there are no places
that rely on such exclusion for `find-dired' buffers. Same
for `find-lisp-find-dired-internal' (which binds
`dired-buffers' for `find-lisp*').
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sat, 07 Jun 2025 10:20:01 GMT)
Full text and
rfc822 format available.
Message #104 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> From: Drew Adams <drew.adams <at> oracle.com>
> CC: "psainty <at> orcon.net.nz" <psainty <at> orcon.net.nz>,
> "78658 <at> debbugs.gnu.org"
> <78658 <at> debbugs.gnu.org>,
> "juri <at> linkov.net" <juri <at> linkov.net>,
> "stefankangas <at> gmail.com" <stefankangas <at> gmail.com>,
> "acorallo <at> gnu.org"
> <acorallo <at> gnu.org>, "rms <at> gnu.org" <rms <at> gnu.org>
> Date: Thu, 5 Jun 2025 21:25:13 +0000
>
> When `dired-mode' is invoked it calls `dired-advertise',
> which adds the Dired buffer to the value of global variable
> `dired-buffers'. A couple commands remove a buffer name from
> this list, by calling `dired-unadvertise'. In particular,
> `wdired-change-to-wdired-mode' does this, because it changes
> the major mode from `dired-mode' to `wdired-mode'.
>
> The value of var `dired-buffers' is thus generally a list of
> all buffers in `dired-mode'. (This can include buffers that
> have been killed, so filtering with `buffer-live-p' is also
> needed.)
>
> The only exceptions are (1) commands `find-dired' and its
> derivatives such as `find-name-dired', and (2) commands
> `find-lisp-dired*'. They're exceptions because they bind
> `dired-buffers' around their work (see above), so as not to
> add their resulting Dired buffers to `dired-buffers'.
>
> This means that code can't just examine `dired-buffers' to
> find the set of Dired buffers (buffers advertised to be in
> `dired-mode'). Instead, it needs to filter `buffer-list',
> to gather the buffers with modes derived from `dired-mode'.
> That's unfortunate - it's much more costly, in general.
>
> The question is whether there's a good reason why find*
> buffers, which are in `dired-mode', should be excluded from
> being "advertised" as such, i.e., whether they should really
> be excluded from `dired-buffers'. And if so, why?
>
> It was apparently a 1998 commit by Richard that added the
> protective binding to `find-dired', but with no comment as
> to why.
>
> In the Emacs sources, at least, there are no other places
> that exclude `dired-mode' buffers from `dired-buffers'.
> And grepping for `find-dired' shows that there are no places
> that rely on such exclusion for `find-dired' buffers. Same
> for `find-lisp-find-dired-internal' (which binds
> `dired-buffers' for `find-lisp*').
Thanks.
If we allow find-dired to add its buffers to the list in
dired-buffers, we need to make sure they are removed from the list.
We also need to make sure that functions which scan the list and
operate on its buffers will DTRT with find-dired buffers found in the
list. Is all of this reasonable to do, and if so, is it planned to be
done as part of the changes you are discussing?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sat, 07 Jun 2025 16:53:01 GMT)
Full text and
rfc822 format available.
Message #107 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > When `dired-mode' is invoked it calls `dired-advertise',
> > which adds the Dired buffer to the value of global variable
> > `dired-buffers'. A couple commands remove a buffer name from
> > this list, by calling `dired-unadvertise'. In particular,
> > `wdired-change-to-wdired-mode' does this, because it changes
> > the major mode from `dired-mode' to `wdired-mode'.
> >
> > The value of var `dired-buffers' is thus generally a list of
> > all buffers in `dired-mode'. (This can include buffers that
> > have been killed, so filtering with `buffer-live-p' is also
> > needed.)
> >
> > The only exceptions are (1) commands `find-dired' and its
> > derivatives such as `find-name-dired', and (2) commands
> > `find-lisp-dired*'. They're exceptions because they bind
> > `dired-buffers' around their work (see above), so as not to
> > add their resulting Dired buffers to `dired-buffers'.
> >
> > This means that code can't just examine `dired-buffers' to
> > find the set of Dired buffers (buffers advertised to be in
> > `dired-mode'). Instead, it needs to filter `buffer-list',
> > to gather the buffers with modes derived from `dired-mode'.
> > That's unfortunate - it's much more costly, in general.
> >
> > The question is whether there's a good reason why find*
> > buffers, which are in `dired-mode', should be excluded from
> > being "advertised" as such, i.e., whether they should really
> > be excluded from `dired-buffers'. And if so, why?
> >
> > It was apparently a 1998 commit by Richard that added the
> > protective binding to `find-dired', but with no comment as
> > to why.
> >
> > In the Emacs sources, at least, there are no other places
> > that exclude `dired-mode' buffers from `dired-buffers'.
> > And grepping for `find-dired' shows that there are no places
> > that rely on such exclusion for `find-dired' buffers. Same
> > for `find-lisp-find-dired-internal' (which binds
> > `dired-buffers' for `find-lisp*').
>
> Thanks.
>
> If we allow find-dired to add its buffers to the list in
> dired-buffers, we need to make sure they are removed from the list.
> We also need to make sure that functions which scan the list and
> operate on its buffers will DTRT with find-dired buffers found in the
> list. Is all of this reasonable to do, and if so, is it planned to be
> done as part of the changes you are discussing?
I'm afraid I don't understand.
1. What do you mean by making sure they're removed from the list? The only reason to remove a file/dir from the list is, as is the case with WDired, if the mode is changed from `dired-mode' to something else. (WDired removes its buffer from the list, for that reason.)
As I said, there are no uses of `dired-buffers' in the Emacs source code, apart from what I mentioned - no function that accesses `dired-buffers' at all.
2. What do you mean by a function operating on Dired buffers doing the right thing? What can that possibly mean, independent from any particular such function?
Again, no Emacs source code accesses (in order to operate) on its buffers.
___
There's no way to know what might exist in the wild, of course - code that might use `dired-buffers' somehow. (I would guess zero such use, but I could be wrong.)
We could certainly add to the `dired-buffers' doc string, pointing out that `dired-buffers' can include Dired buffers with "listings" created by find* or from an arbitrary list of files&dirs, i.e., the files&dirs listed aren't necessarily the result of `ls'.
I don't think it's necessary to do that, but it wouldn't hurt.
___
The other thing that code should be aware of, and which is not documented AFAIK, is that an entry in `dired-buffers can include buffers that have been killed. Any code that might want to operate on the buffers (there is none, so far, AFAIK) needs to be aware of this. E.g., it will likely want to filter out killed-buffer entries.
I do think it might be good to mention this in the `dired-buffers' doc string.
___
We already "allow" buffers with arbitrary files & dirs to be added to `dired-buffers' (via `dired' with a cons DIRNAME arg). I really don't see how also allowing the Dired buffers with find* files & dirs is different. We don't say or do anything special if you use a Dired buffer with an arbitrary list of files&dirs. I don't see anything different/special about the Dired buffers from find*.
I do understand that historically we've prevented this, so we should think about it. But so far, I don't see any reason for it. I'm generally conservative on such things, but in this case I'd suggest we just do it.
We could also add a defvar that controls whether to do this, to be more conservative. If we do that, I'd suggest that by default it allows find* Dired buffers. Any code that finds their inclusion problematic could change the variable value, by binding or assigning.
___
I suspect that the prohibition for `find*' was overengineering, for lack of full understanding of Dired. There's a lot of stuff in Dired, some of which has never seen a lot of use.
In particular, Dired buffers with lists of arbitrary files&dirs (not from `ls'). That feature was (apparently) provided from the get-go, but I doubt that it's been used much. I feel like I might have been the first to take advantage of it, but I don't know.
I mention this as a possible reason why `dired-buffers' was made off-limits for find*: maybe we just weren't clear enough about what might be involved or what might happen with a non-`ls' buffer. If so, that's kinda where we are today too. It'd be great if Richard happened to recall something about why he made it off-limits, but I don't expect he would 27 years later - I certainly wouldn't.
HTH.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sat, 07 Jun 2025 17:34:02 GMT)
Full text and
rfc822 format available.
Message #110 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> From: Drew Adams <drew.adams <at> oracle.com>
> CC: "psainty <at> orcon.net.nz" <psainty <at> orcon.net.nz>,
> "78658 <at> debbugs.gnu.org"
> <78658 <at> debbugs.gnu.org>,
> "juri <at> linkov.net" <juri <at> linkov.net>,
> "stefankangas <at> gmail.com" <stefankangas <at> gmail.com>,
> "acorallo <at> gnu.org"
> <acorallo <at> gnu.org>, "rms <at> gnu.org" <rms <at> gnu.org>
> Date: Sat, 7 Jun 2025 16:52:14 +0000
>
> > If we allow find-dired to add its buffers to the list in
> > dired-buffers, we need to make sure they are removed from the list.
> > We also need to make sure that functions which scan the list and
> > operate on its buffers will DTRT with find-dired buffers found in the
> > list. Is all of this reasonable to do, and if so, is it planned to be
> > done as part of the changes you are discussing?
>
> I'm afraid I don't understand.
>
> 1. What do you mean by making sure they're removed from the list? The only reason to remove a file/dir from the list is, as is the case with WDired, if the mode is changed from `dired-mode' to something else. (WDired removes its buffer from the list, for that reason.)
>
> As I said, there are no uses of `dired-buffers' in the Emacs source code, apart from what I mentioned - no function that accesses `dired-buffers' at all.
>
> 2. What do you mean by a function operating on Dired buffers doing the right thing? What can that possibly mean, independent from any particular such function?
>
> Again, no Emacs source code accesses (in order to operate) on its buffers.
It is accessed in dired.el, AFAICT.
What I meant is that if find-dired wants to use this variable, it
needs to play by the rules the other users do. Don't ask me about the
details, because I'm not familiar with them. But it is clear that
there's a protocol wrt this variable, which determines when and which
buffers are added to the list and when they are removed. I'm saying
that find-dired should abide by the same protocol.
As for the DTRT part, what I meant was to ask whether the current
users of dired-buffers will know what to do with buffers put there by
find-dired, or might they be surprised and confused by them? Buffers
created by find-dired are in Dired mode, but they are not exactly
Dired buffers, in the sense that they don't necessarily show files
that live in the same directory. E.g., what will happen if the user
invokes Wdired on such a buffer?
Again, please don't ask me to provide you with detailed instructions,
because I don't have them. I asked the questions that bothered me wrt
to allowing find-dired to use this variable, but the answers should
come from people who want to allow that, after they do the necessary
research into the current uses of the variable and the possible
effects of allowing find-dired add its buffers to the list.
Put it in other words: currently dired-buffers seems to be an internal
variable used by Dired for its own purposes; if find-dired wants to
become its user, it should make sure it will play by the same rules so
as not to disrupt its current users.
> I suspect that the prohibition for `find*' was overengineering, for lack of full understanding of Dired.
I rather guess that there was a real problem which caused that, but
that problem is lost to time, or at least I wasn't able to find its
description. The date of the change predates all the mailing lists we
nowadays use, including even my private archives of the private
mailing list we used back then.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#78658
; Package
emacs
.
(Sun, 08 Jun 2025 23:43:01 GMT)
Full text and
rfc822 format available.
Message #113 received at 78658 <at> debbugs.gnu.org (full text, mbox):
> > > If we allow find-dired to add its buffers to the list in
> > > dired-buffers, we need to make sure they are removed from the list.
> > > We also need to make sure that functions which scan the list and
> > > operate on its buffers will DTRT with find-dired buffers found in the
> > > list. Is all of this reasonable to do, and if so, is it planned to be
> > > done as part of the changes you are discussing?
> >
> > I'm afraid I don't understand.
> >
> > 1. What do you mean by making sure they're removed from the list? The only
> reason to remove a file/dir from the list is, as is the case with WDired, if
> the mode is changed from `dired-mode' to something else. (WDired removes its
> buffer from the list, for that reason.)
> >
> > As I said, there are no uses of `dired-buffers' in the Emacs source code,
> apart from what I mentioned - no function that accesses `dired-buffers' at
> all.
> >
> > 2. What do you mean by a function operating on Dired buffers doing the
> right thing? What can that possibly mean, independent from any particular
> such function?
> >
> > Again, no Emacs source code accesses (in order to operate) on its buffers.
>
> It is accessed in dired.el, AFAICT.
Apart from `dired-(un)advertise', which I addressed, it seems
to be used only by `dired-find-buffer-nocreate' and others to
access one of the `dired-buffers', which is normal.
And I don't see any harm from the functions in `dired.el'
using Dired buffers created by find*, and I don't think any
is possible. (Famous last words, perhaps?)
> What I meant is that if find-dired wants to use this variable, it
> needs to play by the rules the other users do.
I don't see any rules" that the others (which means dired.el
functions) play by. `dired-advertise' adds to the list and
`dired-unadvertise' subtracts from it. The other functions
that access it just use a buffer from `dired-buffers' for
Dired, which is normal.
> Don't ask me about the
> details, because I'm not familiar with them.
I won't ask - I think I've said what they are (above).
But if I'm missing something, please let me know what.
> But it is clear that
> there's a protocol wrt this variable, which determines when and which
> buffers are added to the list and when they are removed. I'm saying
> that find-dired should abide by the same protocol.
Adding and removing is done only by `dired-(un)advertise'.
I've spoken to that. `dired' invokes advertise when it
sets the mode to `dired-mode'. The only functions that
call `dired-unadvertise' are `dired-rename-subdir' and
`wdired-change-to-wdired-mode', which I think I've
addressed.
find* has only to remove the binding of `dired-buffers',
to cause it, like `dired', to add an entry. And find* has
no reason to ever remove a `dired-buffers' entry. If one
needs to be removed because of deletion of a top-level
directory then `dired-rename-subdir' will do that. And if
one needs to be removed because of entering WDired mode
then `wdired-change-to-wdired-mode' will do that.
Again, I don't think this is any different than the case of
a Dired buffer with an arbitrary listing (cons DIRNAME arg).
> As for the DTRT part, what I meant was to ask whether the current
> users of dired-buffers will know what to do with buffers put there by
> find-dired, or might they be surprised and confused by them?
I don't see how or why they would be surprised, or even
recognize such a buffer as coming from find*. And they
shouldn't to do anything special or different for such a
buffer.
Again, I think this is the same as the case of a Dired
buffer with an arbitrary listing.
> Buffers
> created by find-dired are in Dired mode, but they are not exactly
> Dired buffers, in the sense that they don't necessarily show files
> that live in the same directory.
That's exactly the case of a Dired buffer with a set of
arbitrary files, i.e., what happens if you invoke `dired'
with a DIRNAME arg that's a cons (of a buffer name and a
list of files from anywhere - even on different file-system
trees, e.g. different Windows drives).
There's no special handling of Dired buffers with arbitrary
files - their buffers are happily included in `dired-buffers',
with no problem. That's been the case since Day One, AFAIK.
> E.g., what will happen if the user invokes Wdired on such a buffer?
I think it should work as well as it does now. After you,
e.g., rename some files and dirs in the buffer, and you use
`C-x C-q' again, those files and dirs should stay renamed.
That's what happens if you do that in a Dired buffer with
arbitrary files.
> Again, please don't ask me to provide you with detailed instructions,
> because I don't have them. I asked the questions that bothered me wrt
> to allowing find-dired to use this variable, but the answers should
> come from people who want to allow that, after they do the necessary
> research into the current uses of the variable and the possible
> effects of allowing find-dired add its buffers to the list.
>
> Put it in other words: currently dired-buffers seems to be an internal
> variable used by Dired for its own purposes; if find-dired wants to
> become its user, it should make sure it will play by the same rules so
> as not to disrupt its current users.
I hear you, but I don't know what else to say. I do
agree that someone should give it a try and see if they
encounter problems that aren't there already. I'm not
too well placed to do that.
I did try, with vanilla Emacs 30.1, to first see what
happens if you just try (with no changes) to use WDired
on a find* Dired listing.
Then I tried doing the same with the only change being
the removal of binding `(dired-buffers dired-buffers)'
from `find-dired-with-command'. (It's actually in that
function that the binding is, in 30.1; it used to be in
function `find-dired' itself.)
In both cases I ran into this error with Emacs 30.1
when I tried to exit WDired mode after renaming a file:
Debugger entered--Lisp error: (void-variable wdired--old-marks)
(dired-mark-remembered wdired--old-marks)
(let ((inhibit-read-only t)) (dired-mark-remembered wdired--old-marks))
(progn (cond ((and (stringp dired-directory) (not (file-directory-p dired-directory)) (null some-file-names-unchanged) (= (length files-renamed) 1)) (setq dired-directory (cdr (car files-renamed)))) ((and (consp dired-directory) (cdr dired-directory) files-renamed) (setq dired-directory (cons (car dired-directory) (let* ((--cl-var-- ...) (f nil) (--cl-var-- nil)) (while (consp --cl-var--) (setq f ...) (setq --cl-var-- ...) (setq --cl-var-- ...)) (nreverse --cl-var--)))))) (revert-buffer) (let ((inhibit-read-only t)) (dired-mark-remembered wdired--old-marks)))
(if changes (progn (cond ((and (stringp dired-directory) (not (file-directory-p dired-directory)) (null some-file-names-unchanged) (= (length files-renamed) 1)) (setq dired-directory (cdr (car files-renamed)))) ((and (consp dired-directory) (cdr dired-directory) files-renamed) (setq dired-directory (cons (car dired-directory) (let* (... ... ...) (while ... ... ... ...) (nreverse --cl-var--)))))) (revert-buffer) (let ((inhibit-read-only t)) (dired-mark-remembered wdired--old-marks))) (let ((inhibit-read-only t)) (remove-text-properties (point-min) (point-max) '(old-name nil end-name nil old-link nil end-link nil end-perm nil old-perm nil perm-changed nil)) (message "(No changes to be performed)") (revert-buffer)))
(let ((changes nil) (errors 0) files-deleted files-renamed some-file-names-unchanged file-old file-new tmp-value) (save-excursion (if (and wdired-allow-to-redirect-links (fboundp 'make-symbolic-link)) (progn (setq tmp-value (wdired-do-symlink-changes)) (setq errors (cdr tmp-value)) (setq changes (car tmp-value)))) (if (and wdired-allow-to-change-permissions wdired--perm-beg) (progn (setq tmp-value (wdired-do-perm-changes)) (setq errors (+ errors (cdr tmp-value))) (setq changes (or changes (car tmp-value))))) (goto-char (point-max)) (while (not (bobp)) (setq file-old (and (wdired--line-preprocessed-p) (wdired-get-filename nil t))) (if file-old (progn (setq file-new (wdired-get-filename)) (if (equal file-new file-old) (setq some-file-names-unchanged t) (setq changes t) (if (not file-new) (setq files-deleted ...) (if wdired-keep-marker-rename ...) (setq files-renamed ...))))) (forward-line -1))) (if files-renamed (progn (let* ((val (wdired-do-renames files-renamed))) (progn (ignore (consp val)) (let* ((x0 ...) (x1 ...)) (let (... ...) (progn ... ...))))))) (wdired-change-to-dired-mode) (if changes (progn (cond ((and (stringp dired-directory) (not (file-directory-p dired-directory)) (null some-file-names-unchanged) (= (length files-renamed) 1)) (setq dired-directory (cdr (car files-renamed)))) ((and (consp dired-directory) (cdr dired-directory) files-renamed) (setq dired-directory (cons (car dired-directory) (let* ... ... ...))))) (revert-buffer) (let ((inhibit-read-only t)) (dired-mark-remembered wdired--old-marks))) (let ((inhibit-read-only t)) (remove-text-properties (point-min) (point-max) '(old-name nil end-name nil old-link nil end-link nil end-perm nil old-perm nil perm-changed nil)) (message "(No changes to be performed)") (revert-buffer))) (if files-deleted (progn (wdired-flag-for-deletion files-deleted))) (if (> errors 0) (progn (dired-log-summary (format "%d actions failed" errors) nil))))
wdired-finish-edit()
(if (y-or-n-p (format "Buffer %s modified; save changes? " (current-buffer))) (wdired-finish-edit) (wdired-abort-changes))
(if (buffer-modified-p) (if (y-or-n-p (format "Buffer %s modified; save changes? " (current-buffer))) (wdired-finish-edit) (wdired-abort-changes)) (wdired-change-to-dired-mode) (set-buffer-modified-p nil) (setq buffer-undo-list nil) (message "(No changes need to be saved)"))
wdired-exit()
funcall-interactively(wdired-exit)
command-execute(wdired-exit)
I tried to do this on Windows (11), with Cygwin. Dunno if
someone else will see the same thing.
I also tried with vanilla Emacs 26.3. There I didn't get any
error, and I saw the same behavior wrt WDired with and without
the (dired-buffers dired-buffers) binding in `find-dired'
(that's the function that has the binding, in Emacs 26.3).
But in Emacs 26 when exiting WDired mode (with or without
the dired-buffers binding) the find Dired buffer is reverted
to the directory where the find was issued (same dir as the
find result), but showing the full directory, not just the
found files. What's more, in that Dired listing, preceding
the privileges (-rw-rw-rw-) there are two additional columns,
with values such as these:
281474977338773 0
281474977338774 1
281474977338792 1
281474977338758 1
...
So in 26.3, at least, there's a problem with exiting
WDired mode, but it's unrelated to the proposed change.
In sum, I don't seem to be able to test this well.
But from what I do see, there's no difference, wrt
using WDired with find*, with or without the binding
(dired-buffers dired-buffers). And in both cases the
renamed files stay renamed, wherever in the find*
results they may be (as one would expect).
I'm hoping someone else will try the same thing or
similar, on Windows or another platform, to see if
removing the dired-buffers binding from find* has any
negative consequence. Even a quick sanity test would
be good. I'm afraid I'm no more help, here.
> > I suspect that the prohibition for `find*' was overengineering, for lack of
> full understanding of Dired.
>
> I rather guess that there was a real problem which caused that, but
> that problem is lost to time, or at least I wasn't able to find its
> description. The date of the change predates all the mailing lists we
> nowadays use, including even my private archives of the private
> mailing list we used back then.
Understood.
My suggestion is to make the proposed change, but to
also provide a defvar to choose to allow/disallow
inclusion of find* Dired buffers in `dired-buffers',
i.e., choose whether to bind `dired-buffers'.
I'd also suggest that by default the defvar should
have find* buffers be included, not excluded. If ever
a problem from that is reported we could change the
default value, but I don't expect such a problem.
Maybe I'm too optimistic. Still, it would be good to
be able to choose, at least.
This bug report was last modified 4 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.