bug#81295: 32.0.50; dired-auto-toggle-b-switch problem with subdirectory
Filipp Gunbin <[email protected]>
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Organization | https://plainsoftware.org |
| Message-ID | <[email protected]> |
On 26/07/2026 18:05 +0200, Stephen Berman wrote: > On Mon, 20 Jul 2026 17:14:38 +0300 Filipp Gunbin <[email protected]> wrote: > >> On 18/07/2026 12:01 +0200, Stephen Berman wrote: >> >>> On Sat, 18 Jul 2026 03:22:22 +0300 Filipp Gunbin <[email protected]> wrote: >>> >>>> On 17/07/2026 16:08 +0200, Stephen Berman wrote: >>>> >>>> [...] >>>> >>>>> - Typing `C-u i RET' calls `dired-maybe-insert-subdir' with argument >>>>> SWITCHES set to the default value "-al". This gets passed to >>>>> `dired-insert-subdir', which in turn passes it to >>>>> `dired-insert-subdir-validate', which return `(t t)' because neither >>>>> SWITCHES nor `dired-actual-switches' includes either the "F" or "b" >>>>> switch. Hence, directory 2 gets inserted as a subdir. Before >>>>> `dired-insert-subdir' returns, the value of SWITCHES gets added to >>>>> `dired-switches-alist'. >>>>> >>>>> - When `dired-insert-subdir' returns, `dired--toggle-b-switch' gets >>>>> called from `post-command-hook' (since `dired-auto-toggle-b-switch' is >>>>> t), and since directory 2 contains a file name with a newline >>>>> `(dired--filename-with-newline-p)' returns t, and this results in the >>>>> "b" switch getting added to `dired-actual-switches' and then >>>>> `dired-revert' is called. >>>> >>>> I think the problem is that dired--toggle-b-switch only modifies >>>> dired-actual-switches, while it should also modify dired-switches-alist. >>>> Otherwise they go out of sync, may conflict, and lead to problematic >>>> cases like this. >>>> >>>> From your description it looks like that would naturally solve the >>>> current problem. >>> >>> I don't see a way to make `dired--toggle-b-switch' modify >>> `dired-switches-alist' that isn't much more complex than the solution I >>> proposed in patch 1. If you do, can you post a patch? >> >> Alas, currently I don't have enough time, maybe later. I've tried to >> explain my thoughts in more detail below. >> >>>> But it would also mean that any switches that user enters in C-u i >>>> should be modified with respect to dired-auto-toggle-b-switch. It's >>>> "auto-toggle", after all. >>> >>> Right, that's what patch 1 does. >> >> I don't like this change: >> >> - (and (not switches) cons (setq switches (cdr cons))) >> + (and (not switches) (not (dired-switches-escape-p dired-actual-switches)) >> + cons (setq switches (cdr cons))) >> >> because it makes a non-obvious special case. Currently it is: unless >> the switches are specified, take them from dired-switches-alist. The >> patch makes an exclusion, a non-obvious one. >> >> The very fact that you're trying to escape validation doesn't make it >> better either: the validation is there for a reason, right? > > The validation is to prevent the situation where the Dired buffer uses > one or both of the -b or -F switches while the inserted subdirs do not, > or vice versa. Your case demonstrates that validation is problematic > precisely when the -b switch gets added by dired--toggle-b-switch, so > circumventing validation in this case is a simple and effective way of > avoiding the problem, given the current handling of file names with > newlines. No doubt a more intuitively appealing solution is possible, > but my impression is it would require fairly involved changes in the > current handling of file names with newlines. I think the constraints which validation imposes are reasonable, so I wouldn't want to circumvent it here. Letting different combinations of -b/-F now will make it harder to do things "the right way" later. That said, I don't know the exact reasons why the validations were added originally. But we should either keep them (and don't try to circumvent), or remove them altogether. >>>> And this brings one more thing. It seems like you use >>>> dired-listing-switches as "the original" switches, for example in >>>> dired-internal-noselect: >>>> >>>> (unless (or dired-auto-toggle-b-switch >>>> (dired-switches-escape-p dired-listing-switches) >>>> (dired-switches-escape-p dired-actual-switches)) >>>> >>>> But C-u C-x d will ask you for your custom switches, and >>>> dired-listing-switches is only initial input there. There's also code >>>> in dired--toggle-b-switch which uses dired-listing-switches in this way: >>>> >>>> (unless (dired-switches-escape-p dired-listing-switches) >>>> (when (dired-switches-escape-p dired-actual-switches) >>>> (setq dired-actual-switches (dired--remove-b-switch)) >>>> (dired-revert)))))) >>>> >>>> Perhaps we should have buffer-local variables which record the initial >>>> top-level and subdirectory switches, and consult them when deciding what >>>> to do in dired--toggle-b-switch. >>> >>> I don't follow you here; AFAIU the user option `dired-listing-switches' >>> can be overriden by `C-u C-x d', and the resulting switches are then the >>> value of `dired-actual-switches', otherwise, `dired-listing-switches' >>> and `dired-actual-switches' have the same value (unless something like >>> `dired--toggle-b-switch' changes the latter). Can you elaborate on what >>> you're proposing (or considering) for `dired--toggle-b-switch'? >> >> "Then" branch currently adds the "-b" switch when we have newlines in >> files, and when the user option is enabled: >> >> (if (and (dired--filename-with-newline-p) dired-auto-toggle-b-switch) >> (unless (dired-switches-escape-p dired-actual-switches) >> (setq dired-actual-switches (concat dired-actual-switches " -b")) >> (dired-revert)) >> >> But the logic in "else" branch is, I think, incomplete. >> >> Here we're checking that user hasn't specified -b explicitly by testing >> dired-listing-switches, and this doesn't account for the case of C-u C-x >> d, because dired-listing-switches then have nothing to do with the >> user's choice: >> >> (unless (dired-switches-escape-p dired-listing-switches) >> (when (dired-switches-escape-p dired-actual-switches) >> (setq dired-actual-switches (dired--remove-b-switch)) >> (dired-revert)))))) >> >> So I was thinking what the root cause of the problem is, and it appeared >> to me that we don't have enough variables currently: >> >> Top-level switches: >> >> (1) defcustom for default switches - dired-listing-switches >> >> (2) The value that user actually entered dired with: missing > > You mean with `C-u C-x d', right? Yes. > That value is assigned to dired-actual-switches in dired-mode: > > (setq-local dired-actual-switches > (or switches (connection-local-value dired-listing-switches))) But with dired-auto-toggle-b-switch feature dired-actual-switches may be modified, and so we lose information about whether the user explicitly specified -b or not. That's why I separated (2) and (3). >> (3) The value of actual ls invocation: dired-actual-switches > > As the code snippet from dired-mode shows, this is either (1) or (2). See above. >> Subdir switches: >> >> (4) defcustom for default switches - (or dired-subdir-switches >> dired-listing-switches) >> >> (5) The value that user actually entered dired with, per subdir: >> dired-subdir-switches alist >> >> (6) The value of actual ls invocation, per subdir: missing > > Here, too, it's dired-actual-switches, let-bound in > dired-insert-subdir-doinsert: > > (let ((dired-actual-switches > (or switches > dired-subdir-switches > (string-replace "R" "" dired-actual-switches)))) This defaults to (adjusted) dired-actual-switches, yes, but otherwise the same reasoning as above applies. The caller of this function, dired-insert-subdir, uses dired-switches-alist to store specific switches per subdir (5). >> The validation currently ensures that either all directories in dired >> have -b, or none. In the current problematic case, we end up with: >> >> - "-alb" in dired-actual-switches. This value is ok. >> >> - "-al" in dired-switches-alist. This value is not ok, because we're >> now in situtation which validation was trying to prevent. IMO we >> should have state for (6), and dired--toggle-b-switch should adjust it >> by adding -b to dired-subdir-switches (5). We should also store >> dired-subdir-switches (5) as it is, as currently, because we need to >> tell whether -b was present in initial user choice, to be able to >> decide whether we need to remove it in "auto" case. >> >> Just trying to silence the validation IMO seems wrong. >> >> Not having the "full" state (current plus (2) and (6)) also makes for >> more moot points, like the extract from dired-internal-noselect I posted >> above. >> >> If no one currently can provide the full patch (if my logic is right, of >> course), then perhaps we better leave this unfixed for now. You've >> fixed my original complaint in this bug, this is already an improvement. > > I probably need to see an implementation to really understand what > you're proposing. But in the mean time, I think it would be better to > install the last patch I posted (with the change you don't like) than to > leave the `C-u i' case unhandled, because it's a serious problem (having > the subdir not appear at all), and the patch prevents that problem, even > if a better solution is possible. We could certainly add a FIXME to the > code referring to this bug report, which can be left open. I still think I'm opposed to the fix, because 1) it surely will introduce more subtle bugs (I think I can come up with the cases easily), 2) it will be harder to clean up later. A FIXME is IMO better for now, given that we don't have bug reports on this other than mine. I'll try to come up with an implementation of what I proposed, but later.