Subject: Re: bug#63648: 29.0.90; project.el: with switch-use-entire-map, switch-project errors on non-project commands

From: Juri Linkov <[email-masked]>
Date: Fri, 01 Sep 2023 09:46:27 +0300

>> (let ((default-directory "/tmp/"))
>>    (list default-directory
>>          (buffer-local-value 'default-directory (current-buffer))))
>> => ("/tmp/" "/tmp/")
>> Here is the shortest test case: 'C-x p p C-b' shows buffers
>> from two projects when using let-binding for default-directory,
>> because 'project-buffers' relies on
>>    (buffer-local-value 'default-directory buf)
>> This could be fixed by adding special-handling of the default-directory
>> for the current buffer in 'project-buffers'.
>
> What kind of special handling? The "real" buffer-local value is hidden
> until the "let" exists, the global value is nil, and if the buffer is not
> a file-visiting one, there is no other file name to test against.

Additional buffer-local variable like 'buffer-default-directory' could help.
Or additional global variable 'global-default-directory'.  Or even
using the global value of the existing variable 'default-directory'.

> Finally, whatever special handling we invent, would have to be mirrored by
> all subsequent new commands (built-in and third-party) which look up the
> value of default-directory. Especially project-related ones. How to
> popularize that knowledge, would be the next question for whatever solution
> we invent.

Hopefully there should be not much trouble such as in 'project-buffers'.

>>> A general question regarding this approach, for me, is: is a "prefix
>>> command" a real command?
>> It's a real command that prepares some transient values for the next
>> command.
>> Most existing prefix commands have no problems because they modify global
>> values.  But 'default-directory' is the first buffer-local variable
>> used for the next command, therefore it requires special-handling.
>> Too bad that 'default-directory' is not a function.
>
> I suppose the new code could check against some property or dynamic var to
> distinguish prefix commands from "terminal" ones.

Currently I see no need for this.

>>> And would they "swallow" these prepared variable bindings too early?
>> The scope of the modified variable depends on concrete needs.
>> For example, set-transient-map restores its old value in pre-command-hook,
>> but display-buffer-override-next-command does this in post-command-hook.
>
> That can also work - though the odds of getting into an unrecoverable state
> (such as one I described) would be higher.

This is strange, no one reported an unrecoverable state for set-transient-map.