Subject: bug#76587: 31.0.50; [FR] project.el should have a way to exclude certain projects from being saved

From: Visuwesh <[email-masked]>
Date: Mon, 03 Mar 2025 13:57:45 +0530

[திங்கள் மார்ச் 03, 2025] Dmitry Gutov wrote:

> On 02/03/2025 06:31, Visuwesh wrote:
>> +return non-nil if the project should not be saved."
>
> "should not be remembered", perhaps. Neither adding it to the var
> (storing in memory), nor saving the result to disk.

Thanks, I went with this.

[ஞாயிறு மார்ச் 02, 2025] Eli Zaretskii wrote:

>> Cc: [email-masked], Juri Linkov <[email-masked]>
>> From: Visuwesh <[email-masked]>
>> Date: Sun, 02 Mar 2025 10:01:58 +0530
>> 
>> +(defcustom project-list-exclude nil
>> +  "List of regexps and predicates for project root and objects to ignore.
>> +The predicate should take one argument, the projet object, and should
>> +return non-nil if the project should not be saved."
>
> The first line of the doc string says "to ignore", and the name of the
> variable (*-exclude) also hints to that effect, but the rest of the
> doc strings seems to tell that the matching projects are only
> "ignored" in the sense that they "should not be saved"?  Moreover, the
> code seems to imply that those projects are being ignored by
> project-remember-project, which the doc string doesn't mention at all?
> Can we make the variable name and the first line of the doc string
> more consistent with the actual meaning of this variable, and mention
> the functions that use it in the doc string?

I've now tried to make this clearer.  I don't know what a better name
for the user option could be.

I also updated the manual to mention this user option, and announced the
change in NEWS in the attached.

>From 375ed6b2a972b18359407e6ed0a80e2b7dedb74b Mon Sep 17 00:00:00 2001
From: Visuwesh <[email-masked]>
Date: Mon, 3 Mar 2025 13:56:04 +0530
Subject: [PATCH] Add new user option to ignore projects from being saved

* lisp/progmodes/project.el (project-list-exclude): Add new user
option to exclude projects from being remembers.
(project-remember-project): Consider the user option above.
(project-switch-project): Use 'project-remember-project' instead.
* doc/emacs/maintaining.texi (Managing Projects): Mention the new user option.
* etc/NEWS: Announce the change.  (Bug#76587)
---
 doc/emacs/maintaining.texi |  9 +++++++++
 etc/NEWS                   |  7 +++++++
 lisp/progmodes/project.el  | 21 +++++++++++++++++++--
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index dc61cb008fa..84f5382e20a 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -2041,6 +2041,15 @@ Managing Projects
 prompts you to choose one of the available projects, and then removes
 it from the file.
 
+@vindex project-list-exclude
+  The user option @code{project-list-exclude} may be set to always
+ignore certain projects from being remembered, and saved to
+@code{project-list-file}.  It is a list of regexps and predicates for
+project roots and objects.  The regexp specified is matched against the
+project root, and the predicate should take the project object as the
+only argument and should return non-@code{nil} if the project should not
+be saved to @code{project-list-file}.
+
 @node Change Log
 @section Change Logs
 
diff --git a/etc/NEWS b/etc/NEWS
index 6ae648ab8cf..423ffd82947 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -335,6 +335,13 @@ It can be used when switching between projects with similar file trees
 (such as Git worktrees of the same repository).  It supports being
 invoked standalone or from the 'project-switch-commands' dispatch menu.
 
++++
+*** New user option 'project-list-exclude'.
+This user option lists projects that should be ignored by
+'project-remember-project' always.
+
+***
+
 ** Registers
 
 *** New functions 'buffer-to-register' and 'file-to-register'.
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 35bf66c9ffb..f93d0051cd3 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1837,6 +1837,16 @@ project-list-file
   :version "28.1"
   :group 'project)
 
+(defcustom project-list-exclude nil
+  "Exclude projects from being remembered by `project-remember-project'.
+It should be a list of regexps and predicates for project roots and
+objects to always exclude from being remembered.  The predicate should
+take one argument, the project object, and should return non-nil if the
+project should not be remembered."
+  :type '(repeat (choice regexp function))
+  :version "31.1"
+  :group 'project)
+
 (defvar project--list 'unset
   "List structure containing root directories of known projects.
 With some possible metadata (to be decided).")
@@ -1902,9 +1912,16 @@ project--remember-dir
 ;;;###autoload
 (defun project-remember-project (pr &optional no-write)
   "Add project PR to the front of the project list.
+If project PR satisfies `project-list-exclude', then nothing is done.
 Save the result in `project-list-file' if the list of projects
 has changed, and NO-WRITE is nil."
-  (project--remember-dir (project-root pr) no-write))
+  (let ((root (project-root pr)))
+    (when (or (null project-list-exclude)
+              (null (seq-some (lambda (r)
+                                (if (functionp r) (funcall r pr)
+                                  (string-match-p r root)))
+                              project-list-exclude)))
+      (project--remember-dir root no-write))))
 
 (defun project--remove-from-project-list (project-root report-message)
   "Remove directory PROJECT-ROOT of a missing project from the project list.
@@ -2274,7 +2291,7 @@ project-switch-project
 When called in a program, it will use the project corresponding
 to directory DIR."
   (interactive (list (funcall project-prompter)))
-  (project--remember-dir dir)
+  (project-remember-project (project-current nil dir))
   (let ((command (if (symbolp project-switch-commands)
                      project-switch-commands
                    (project--switch-project-command dir)))
-- 
2.47.2