Subject: Re: bug#70577: [PATCH] New command other-project-prefix

From: Sean Whitton <[email-masked]>
Date: Sun, 28 Apr 2024 13:13:13 +0100

Hello,

On Fri 26 Apr 2024 at 07:20pm +03, Dmitry Gutov wrote:

> +;;;###autoload
> +(defun other-project-prefix ()
> +  "\"Switch\" to another project before running an Emacs command.
> +Makes sure the next command invoked asks for the project to run it in."
> +  (interactive)
> +  (prefix-command-preserve-state)
> +  (letrec ((depth (minibuffer-depth))
> +           (echofun (lambda () "[switch-project]"))
> +           (around-fun
> +            (lambda (command &rest _args)
> +              (advice-remove this-command around-fun)
> +              (unless (or (eq this-command 'other-project-prefix)
> +                          (eq last-command-event help-char))
> +                (let ((root (funcall project-prompter)))
> +                  (if (or (string-prefix-p "project-"
> +                                           (symbol-name this-command))
> +                          (get this-command 'project-aware))
> +                      (let ((project-current-directory-override root))
> +                        (call-interactively command))
> +                    (let ((default-directory root))
> +                      (call-interactively command)))))))
> +           (prefun
> +            (lambda ()
> +              (unless (> (minibuffer-depth) depth)
> +                (remove-hook 'pre-command-hook prefun)
> +                (remove-hook 'prefix-command-echo-keystrokes-functions echofun)
> +                (when (and this-command (symbolp this-command))
> +                  (advice-add this-command :around around-fun))))))
> +    (add-hook 'pre-command-hook prefun)
> +    (add-hook 'prefix-command-echo-keystrokes-functions echofun)
> +    (let ((map (make-sparse-keymap)))
> +      (set-keymap-parent map project-prefix-map)
> +      ;; Doesn't work ;-(
> +      ;; (define-key map (vector help-char)
> +      ;;             (lambda () (interactive) (help-form-show)))
> +      (set-transient-map map))
> +    (message (concat "Type " (project--keymap-prompt) " or any global key"))))

In passing, this pattern where you letrec a hook that removes itself,
and also consider minibuffer-depth, is now in several places.
The one I am thinking of is vc-edit-next-command but I based that on
some code of Juri's somewhere.

It would be good to factor out a macro for this pattern, I think.

-- 
Sean Whitton