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

From: Spencer Baugh <[email-masked]>
Date: Tue, 29 Aug 2023 17:47:18 -0400

Dmitry Gutov <[email-masked]> writes:

> Sorry for the possible duplicate, but it seems this message didn't
> reach the bug tracker, or other recipients. Resending contents below.
>
> On 23/08/2023 20:54, Juri Linkov wrote:
>> There is no code where to bind a dynamic variable, because its value
>> should be available for the next command in the command loop.
>> If you agree there is no other way to implement this than next-default-directory,
>> then I could bring up the discussion on emacs-devel.
>
> Before we dive into all that, why not try advice on 'command-execute'?
> For the PoC code at least. It's in Lisp since 2013.
>
> The comment in its body does say "Called directly from the C code",
> but I'm not sure if that has any direct implications for us.
>
> This attached piece of code implements the project-switch-project as
> you outlined. Does it work well for you/others? Careful when testing
> or modifying: a typo can break the command loop (and thus the
> session).
>
> To me it seems a little too bare-bones, lacking the instructive hints
> project-switch-project currently has.

Nice!

One thing at least to make it not quite so bare-bones is:

(defun project-switch-project (dir)
  (interactive (list (funcall project-prompter)))
  (setq project--next-dd dir)
  (advice-add 'command-execute :around #'project--with-next-dd)
  (message "Run next command in project %s..." (project-name (project-current nil dir))))

which matches other-window-prefix.

Will try running with this for a while and see how it goes.  (I'm
already missing the short form of project-find-files, but maybe I'll get
used to it... or maybe we should remap C-x C-f to project-find-files
while in this prefix, or something wacky like that)

> (defvar project--next-dd nil)
>
> (defun project--with-next-dd (fun &rest args)
>   (advice-remove 'command-execute #'project--with-next-dd)
>   (let ((default-directory project--next-dd))
>     (apply fun args)))
>
> (defun project-switch-project (dir)
>   (interactive (list (funcall project-prompter)))
>   (setq project--next-dd dir)
>   (advice-add 'command-execute :around #'project--with-next-dd))