Subject: Re: bug#42210: bug#41890: 28.0.50; [PATCH]: Add bindings for project.el

From: Sean Whitton <[email-masked]>
Date: Fri, 24 Jul 2020 14:20:59 -0700

Hello,

On Fri 24 Jul 2020 at 07:12PM +03, Eli Zaretskii wrote:

> Just switch to that buffer, I think.

Okay, then I think the attached addresses feedback received.  Thanks!

-- 
Sean Whitton
>From 08394aa143a5e0fc627e259b4deee3a1c3317960 Mon Sep 17 00:00:00 2001
From: Sean Whitton <[email-masked]>
Date: Fri, 24 Jul 2020 13:36:39 -0700
Subject: [PATCH v2 1/3] Factor out project--read-project-buffer from
 project-switch-buffer

* lisp/progmodes/project.el (project--read-project-buffer): New
function extracted from project-switch-buffer.
* lisp/progmodes/project.el (project-switch-buffer): Instead of
unconditionally reading a project buffer from the user, add
buffer-or-name argument, and populate it using
project--read-project-buffer when called interactively.  Update
docstring.
---
 lisp/progmodes/project.el | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index a0930553bd..9534eb2ef6 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -877,14 +877,7 @@ project-compile
          (default-directory (project-root pr)))
     (compile command comint)))
 
-;;;###autoload
-(defun project-switch-to-buffer ()
-  "Switch to another buffer belonging to the current project.
-This function prompts for another buffer, offering as candidates
-buffers that belong to the same project as the current buffer.
-Two buffers belong to the same project if their project instances,
-as reported by `project-current' in each buffer, are identical."
-  (interactive)
+(defun project--read-project-buffer ()
   (let* ((pr (project-current t))
          (current-buffer (current-buffer))
          (other-buffer (other-buffer current-buffer))
@@ -896,13 +889,22 @@ project-switch-to-buffer
                  (equal pr
                         (with-current-buffer (cdr buffer)
                           (project-current)))))))
-    (switch-to-buffer
-     (read-buffer
-      "Switch to buffer: "
-      (when (funcall predicate (cons other-name other-buffer))
-        other-name)
-      nil
-      predicate))))
+    (read-buffer
+     "Switch to buffer: "
+     (when (funcall predicate (cons other-name other-buffer))
+       other-name)
+     nil
+     predicate)))
+
+;;;###autoload
+(defun project-switch-to-buffer (buffer-or-name)
+  "Display buffer BUFFER-OR-NAME in the selected window.
+When called interactively, prompts for a buffer belonging to the
+current project.  Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical."
+  (interactive (list (project--read-project-buffer)))
+  (switch-to-buffer buffer))
 
 (defcustom project-kill-buffers-ignores
   '("\\*Help\\*")
-- 
2.27.0

>From a86e847607b281643603865c7231e52fb467da9c Mon Sep 17 00:00:00 2001
From: Sean Whitton <[email-masked]>
Date: Fri, 24 Jul 2020 13:54:49 -0700
Subject: [PATCH v2 2/3] Add project-display-buffer and
 project-display-buffer-other-frame

* lisp/progmodes/project.el (project-display-buffer,
project-display-buffer-other-frame): Add commands.
---
 lisp/progmodes/project.el | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 9534eb2ef6..f674749497 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -906,6 +906,30 @@ project-switch-to-buffer
   (interactive (list (project--read-project-buffer)))
   (switch-to-buffer buffer))
 
+;;;###autoload
+(defun project-display-buffer (buffer-or-name)
+  "Display BUFFER-OR-NAME in some window, without selecting it.
+When called interactively, prompts for a buffer belonging to the
+current project.  Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical."
+  (interactive (list (project--read-project-buffer)))
+  (display-buffer buffer))
+
+;;;###autoload
+(defun project-display-buffer-other-frame (buffer-or-name)
+  "Display BUFFER-OR-NAME preferably in another frame.
+When called interactively, prompts for a buffer belonging to the
+current project.  Two buffers belong to the same project if their
+project instances, as reported by `project-current' in each
+buffer, are identical.
+
+This function uses `display-buffer-other-frame' as a subroutine,
+which see for how it is determined where the buffer will be
+displayed."
+  (interactive (list (project--read-project-buffer)))
+  (display-buffer-other-frame buffer))
+
 (defcustom project-kill-buffers-ignores
   '("\\*Help\\*")
   "Conditions for buffers `project-kill-buffers' should not kill.
-- 
2.27.0

>From f2b038a73a6868a0b6a3b1396ce670cdeeeb75cc Mon Sep 17 00:00:00 2001
From: Sean Whitton <[email-masked]>
Date: Thu, 23 Jul 2020 18:55:42 -0700
Subject: [PATCH v2 3/3] Add project other place commands

* lisp/progmodes/project.el (project-other-window-map,
project-other-frame-map, project--other-place-command,
project-other-window-command, project-other-frame-command,
project-other-tab-command): Add these functions and maps.
* lisp/progmodes/project.el: Bind project-other-window-command to C-x
4 p, project-other-frame-command to C-x 5 p and
project-other-tab-command to C-x t p.
---
 lisp/progmodes/project.el | 67 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index f674749497..7a0bf1fdbf 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -592,6 +592,73 @@ project-prefix-map
 
 ;;;###autoload (define-key ctl-x-map "p" project-prefix-map)
 
+;; We can't have these place-specific maps inherit from
+;; project-prefix-map because project--other-place-command needs to
+;; know which map the key binding came from, as if it came from one of
+;; these maps, we don't want to set display-buffer-overriding-action
+
+(defvar project-other-window-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-o" #'project-display-buffer)
+    map)
+  "Keymap for project commands that display buffers in other windows.")
+
+(defvar project-other-frame-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-o" #'project-display-buffer-other-frame)
+    map)
+  "Keymap for project commands that display buffers in other frames.")
+
+(defun project--other-place-command (action &optional map)
+  (let* ((key (read-key-sequence-vector nil t))
+         (place-cmd (lookup-key map key))
+         (generic-cmd (lookup-key project-prefix-map key))
+         (display-buffer-overriding-action (unless place-cmd action)))
+    (if-let ((cmd (or place-cmd generic-cmd)))
+        (call-interactively cmd)
+      (user-error "%s is undefined" (key-description key)))))
+
+;;;###autoload
+(defun project-other-window-command ()
+  "Run project command, displaying resultant buffer in another window.
+
+The following commands are available:
+
+\\{project-prefix-map}
+\\{project-other-window-map}"
+  (interactive)
+  (project--other-place-command '((display-buffer-pop-up-window)
+                                  (inhibit-same-window . t))
+                                project-other-window-map))
+
+;;;###autoload (define-key ctl-x-4-map "p" #'project-other-window-command)
+
+;;;###autoload
+(defun project-other-frame-command ()
+  "Run project command, displaying resultant buffer in another frame.
+
+The following commands are available:
+
+\\{project-prefix-map}
+\\{project-other-frame-map}"
+  (interactive)
+  (project--other-place-command '((display-buffer-pop-up-frame))
+                                project-other-frame-map))
+
+;;;###autoload (define-key ctl-x-5-map "p" #'project-other-frame-command)
+
+;;;###autoload
+(defun project-other-tab-command ()
+  "Run project command, displaying resultant buffer in a new tab.
+
+The following commands are available:
+
+\\{project-prefix-map}"
+  (interactive)
+  (project--other-place-command '((display-buffer-in-new-tab))))
+
+;;;###autoload (define-key tab-prefix-map "p" #'project-other-tab-command)
+
 (defun project--value-in-dir (var dir)
   (with-temp-buffer
     (setq default-directory dir)
-- 
2.27.0