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

From: Stefan Monnier <[email-masked]>
Date: Mon, 05 Jun 2023 10:44:11 -0400

Juri Linkov [2023-06-05 09:50:44] wrote:

>>> And indeed with the following patch replacing the current definition of
>>> 'project-switch-project' with just:
>>>
>>>   (defun project-switch-project (dir)
>>>     (interactive (list (funcall project-prompter)))
>>>     (setq next-default-directory dir))
>>
>> This would be a new "prefix command", like the `universal-argument`,
>> `C-x RET c`, the `ofw-other-window`, vc-edit-next-command,
>> `ofw-other-frame` from the `other-frame-window` package, and a few more.
>>
>> In order for this new prefix to interact correctly with those other
>> ones, it should probably use `prefix-command-preserve-state` and it
>> would be good to make it show some visual feedback via
>> `prefix-command-echo-keystrokes-functions`.
>
> Here is the same function turned into a prefix command,
> so it supports both cases:
>
> 1. 'C-x p p d'      -- keys from project-prefix-map
> 2. 'C-x p p C-x d'  -- global keybindings
>
> ```
> (defun project-switch-project (dir)
>   (interactive (list (funcall project-prompter)))
>   (if (symbolp project-switch-commands)
>       (let ((default-directory dir))
>         (call-interactively project-switch-commands))
>     (let* ((echofun (lambda () "[switch-project]"))
>            (postfun (lambda () (remove-hook
>                                 'prefix-command-echo-keystrokes-functions
>                                 echofun))))
>       (setq next-default-directory dir)
>       (add-hook 'prefix-command-echo-keystrokes-functions echofun)
>       (message (project--keymap-prompt))
>       (prefix-command-update)
>       (set-transient-map project-prefix-map nil postfun))))
> ```

I think you need to call `prefix-command-preserve-state` as well, so
that the order of prefix commands doesn't matter (e.g. user can do `C-u
C-x p` instead of `C-x p C-u`).

[ Note: I'm still not really happy with the way prefix commands work.
  I can't remember what problems are still lurking, but IIRC interaction
  with minibuffer is a source of problems (e.g. prefix commands from
  before we entered the minibuffer can affect operations within the
  minibuffer and prefix commands from within the minibuffer can affect
  the behavior after exiting the minibuffer).  I think last time
  I looked at it, I concluded that maybe it should be reimplemented such
  that the state is kept in a single object to which prefix commands can
  add/remove properties, and the minibuffer code would automatically
  suspend and then reinstall that state (and could emit a warning when
  throwing away "unused state", such as when leaving a minibuffer).  ]

> If this is conceptually ok, then more customization could be ported
> from project--switch-project-command such as project-switch-use-entire-map.

Looks OK to me [ modulo the fact that I don't really understand what
this is doing (I don't understand the `project-switch-commands` bit, nor
do I understand why a prefix command which temporarily changes the
`default-directory` would be called `project-switch-project`).  ]

        Stefan