unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Dmitry Gutov <dgutov@yandex.ru>
To: Sean Devlin <spd@toadstyle.org>, 58784@debbugs.gnu.org
Subject: bug#58784: 28.2; project-buffers incorrect under let-bound default-directory
Date: Sat, 29 Oct 2022 03:49:09 +0300	[thread overview]
Message-ID: <0b56cc0a-b8d4-86dc-4b67-217387aeb1b2@yandex.ru> (raw)
In-Reply-To: <BC98CEE6-8E88-4D9F-955F-8B96DDF1D98E@toadstyle.org>

[-- Attachment #1: Type: text/plain, Size: 2563 bytes --]

Hi!

On 26.10.2022 03:13, Sean Devlin wrote:
> The project.el function project-buffers can return incorrect results
> when invoked while a let-binding for default-directory is in
> effect. This is because project-buffers (both the default and vc-based
> implementations) does its work by inspecting the local value of
> default-directory in each buffer, and the let-binding temporarily
> affects this value.
> 
> To see this in action, start emacs with -Q and evaluate the following
> forms in order:
> 
> (require 'project)
> 
> (find-file-noselect "/tmp/tmpfile")
> (setq my-project '(transient . "/tmp/"))
> 
> ;; just the tmpfile
> (project-buffers my-project)
> 
> ;; both tmpfile and scratch
> (let ((default-directory "/tmp/"))
>    (project-buffers my-project))

Thanks for the report, I can see the problem.

> In the last form, project-buffers includes the current buffer (i.e. the
> scratch buffer in our example) with the results. (This is true even if
> the current buffer is visiting a file in some unrelated directory.)
> 
> This matters because the command project-switch-project let-binds
> default-directory before calling project-switch-commands. This means
> that if you set project-switch-commands to some function that calls
> project-buffers, you will get incorrect results.
> 
> For example, evaluate the following forms in order:
> 
> (defun my-list-project-buffers ()
>    "List the current project's buffers."
>    (interactive)
>    (let ((buffer-list (project-buffers (project-current t)))
> 	(buffer-name (project-prefixed-buffer-name "my-project-buffer-list")))
>      (with-current-buffer (get-buffer-create buffer-name)
>        (erase-buffer)
>        (save-excursion
> 	(dolist (buffer buffer-list)
> 	  (insert (buffer-name buffer))
> 	  (insert ?\n))))
>      (switch-to-buffer buffer-name)))
> 
> (setq project-switch-commands #'my-list-project-buffers)

Looks like a reimplementation of projectile-ibuffer, seems useful.

> ;; list tmpfile but also scratch
> (project-switch-project "/tmp/")

Not sure how to fix this, though. In bug#53626 we discussed a somewhat 
similar problem, and a let-binding seems impossible to "escape".

What else can we do? One option is to change the signature of every 
compatible command to take the project object as its first argument. 
Might have been more realistic when the package was first written, too 
much breakage now, probably.

Another would be to add a new var to help override the project choice 
without touch default-directory.

Something like the attached. Please try it out.

[-- Attachment #2: project-current-directory-override.diff --]
[-- Type: text/x-patch, Size: 1839 bytes --]

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index ac278edd40..48ed033fa1 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -175,8 +175,14 @@ project-find-functions
 `cl-defmethod' can dispatch on, like a cons cell, or a list, or a
 CL struct.")
 
-(defvar project-current-inhibit-prompt nil
-  "Non-nil to skip prompting the user in `project-current'.")
+(define-obsolete-variable-alias
+  'project-current-inhibit-prompt
+  'project-current-directory-override
+  "29.1")
+
+(defvar project-current-directory-override nil
+  "Value to use instead of `default-directory' when detecting the project.
+When it is non-nil, `project-current' will skip always skip prompting.")
 
 ;;;###autoload
 (defun project-current (&optional maybe-prompt directory)
@@ -195,11 +201,12 @@ project-current
 
 See the doc string of `project-find-functions' for the general form
 of the project instance object."
-  (unless directory (setq directory default-directory))
+  (unless directory (setq directory (or project-current-directory-override
+                                        default-directory)))
   (let ((pr (project--find-in-directory directory)))
     (cond
      (pr)
-     ((unless project-current-inhibit-prompt
+     ((unless project-current-directory-override
         maybe-prompt)
       (setq directory (project-prompt-project-dir)
             pr (project--find-in-directory directory))))
@@ -1667,8 +1674,7 @@ project-switch-project
   (let ((command (if (symbolp project-switch-commands)
                      project-switch-commands
                    (project--switch-project-command))))
-    (let ((default-directory dir)
-          (project-current-inhibit-prompt t))
+    (let ((project-current-directory-override dir))
       (call-interactively command))))
 
 (provide 'project)

  reply	other threads:[~2022-10-29  0:49 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-26  0:13 bug#58784: 28.2; project-buffers incorrect under let-bound default-directory Sean Devlin
2022-10-29  0:49 ` Dmitry Gutov [this message]
2022-10-31 17:47   ` Sean Devlin
2022-11-01 23:35     ` Dmitry Gutov
2022-11-02 15:18       ` Sean Devlin
2022-11-04  1:18         ` Dmitry Gutov
2022-11-04 16:39           ` Sean Devlin
2022-11-21 18:24       ` Juri Linkov
2022-11-23  3:48         ` Dmitry Gutov
2022-11-24  2:37           ` Dmitry Gutov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0b56cc0a-b8d4-86dc-4b67-217387aeb1b2@yandex.ru \
    --to=dgutov@yandex.ru \
    --cc=58784@debbugs.gnu.org \
    --cc=spd@toadstyle.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).