Package: emacs;
Reported by: Phil Sainty <psainty <at> orcon.net.nz>
Date: Sun, 1 Jun 2025 03:20:06 UTC
Severity: normal
Tags: patch
Found in version 30.1
Message #113 received at 78658 <at> debbugs.gnu.org (full text, mbox):
From: Drew Adams <drew.adams <at> oracle.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: "rms <at> gnu.org" <rms <at> gnu.org>, "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> Subject: RE: [External] : Re: bug#78658: 30.1; [PATCH] Dired feature suggestion: dired-on-marked-files-in-all-buffers Date: Sun, 8 Jun 2025 23:42:21 +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. 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.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.