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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.