Subject: Re: bug#76500: [PATCH] Allow numbered buffer selection for project shell commands

From: "Paul D. Nelson" <[email-masked]>
Date: Mon, 28 Jul 2025 12:30:44 +0200

Juri Linkov <[email-masked]> writes:

>> This patch for project.el adds numeric prefix buffer naming to the
>> project-shell and project-eshell commands, aligning their behavior with
>> that of eshell.
>> [...]
>> Any comments or feedback would be welcome.
>
> I think this would be a useful addition like e.g.
> a numeric argument allows selecting an Info buffer
> with 'C-2 C-h i', etc.
>

This patch received a positive response back in February, but nothing
further, so I figured I'd send a follow-up, rebased onto a recent
master.  Any other feedback would be welcome.

>From 07c1b6ea5dffaf2cf0d19a32a843daf80bbbe87a Mon Sep 17 00:00:00 2001
From: Paul Nelson <[email-masked]>
Date: Mon, 28 Jul 2025 11:52:16 +0200
Subject: [PATCH] Allow numbered buffer selection for project-shell

* project.el (project-shell, project-eshell): When a numeric
prefix is supplied, the command switches to or creates a session
buffer whose name has that number as a suffix.  For instance,
C-2 yields "*name-of-project-shell<2>*".  As before, a plain
universal argument C-u creates a new session with an
automatically generated numeric suffix.  This change makes the
behavior of the project-shell commands consistent with how M-x
eshell handles numeric prefixes.
* etc/NEWS: Announce the change. (bug#76500)
---
 etc/NEWS                  |  7 +++++++
 lisp/progmodes/project.el | 28 +++++++++++++++++-----------
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 8d41efdaf64..121db04b1d8 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -478,6 +478,13 @@ This is like 'C-x s', but only for this project's buffers.
 
 *** 'project-remember-project' can now be called interactively.
 
+---
+*** 'project-shell' and 'project-eshell' support numeric prefix buffer naming.
+They now accept numeric prefix arguments to select or create numbered
+shell sessions.  For example, 'C-2 C-x p s' switches to or creates a
+buffer named "*name-of-project-shell<2>*".  By comparison, a plain
+universal argument as in 'C-u C-x p s' always creates a new session.
+
 ** Registers
 
 *** New functions 'buffer-to-register' and 'file-to-register'.
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 68179206017..a51376144a9 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1414,18 +1414,26 @@ project-shell
 If a buffer already exists for running a shell in the project's root,
 switch to it.  Otherwise, create a new shell buffer.
 With \\[universal-argument] prefix arg, create a new inferior shell buffer even
-if one already exists."
+if one already exists.
+With numeric prefix arg, switch to the session with that number, or
+create it if it doesn't already exist."
   (interactive)
   (require 'comint)
   (let* ((default-directory (project-root (project-current t)))
-         (default-project-shell-name (project-prefixed-buffer-name "shell"))
-         (shell-buffer (get-buffer default-project-shell-name)))
+         (base-name (project-prefixed-buffer-name "shell"))
+         (shell-buffer-name
+          (cond ((numberp current-prefix-arg)
+                 (format "%s<%d>" base-name current-prefix-arg))
+                (current-prefix-arg
+                 (generate-new-buffer-name base-name))
+                (t base-name)))
+         (shell-buffer (get-buffer shell-buffer-name)))
     (if (and shell-buffer (not current-prefix-arg))
         (if (comint-check-proc shell-buffer)
             (pop-to-buffer shell-buffer (append display-buffer--same-window-action
                                                 '((category . comint))))
           (shell shell-buffer))
-      (shell (generate-new-buffer-name default-project-shell-name)))))
+      (shell shell-buffer-name))))
 
 ;;;###autoload
 (defun project-eshell ()
@@ -1433,16 +1441,14 @@ project-eshell
 If a buffer already exists for running Eshell in the project's root,
 switch to it.  Otherwise, create a new Eshell buffer.
 With \\[universal-argument] prefix arg, create a new Eshell buffer even
-if one already exists."
+if one already exists.
+With numeric prefix arg, switch to the session with that number, or
+create it if it doesn't already exist."
   (interactive)
   (defvar eshell-buffer-name)
   (let* ((default-directory (project-root (project-current t)))
-         (eshell-buffer-name (project-prefixed-buffer-name "eshell"))
-         (eshell-buffer (get-buffer eshell-buffer-name)))
-    (if (and eshell-buffer (not current-prefix-arg))
-        (pop-to-buffer eshell-buffer (append display-buffer--same-window-action
-                                             '((category . comint))))
-      (eshell t))))
+         (eshell-buffer-name (project-prefixed-buffer-name "eshell")))
+    (eshell current-prefix-arg)))
 
 ;;;###autoload
 (defun project-async-shell-command ()
-- 
2.39.3 (Apple Git-145)