unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: "J.P." <jp@neverwas.me>
To: Pankaj Jangid <pankaj@codeisgreat.org>
Cc: 51753@debbugs.gnu.org, emacs-erc@gnu.org
Subject: bug#51753: ERC switches to channel buffer on reconnect
Date: Sun, 22 May 2022 18:56:07 -0700	[thread overview]
Message-ID: <87a6b92ers.fsf__10809.7206613579$1653271045$gmane$org@neverwas.me> (raw)
In-Reply-To: <878rqwjqua.fsf@codeisgreat.org> (Pankaj Jangid's message of "Fri, 20 May 2022 18:36:37 +0530")

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

Hi Pankaj,

Pankaj Jangid <pankaj@codeisgreat.org> writes:

> 5. While it is connecting to the server, switch to the other frame to
>    work on other stuff
>
> Result: After the ERC connects to the server, it opens the autojoin
> channels in the current frame. Ideally, it should open the channels in
> the (dedicated) original frame where ERC was launched.

Are you saying ERC ought to remember the frame in which an entry-point
command, like `erc-tls', was originally invoked? Or might it be enough
to make a best effort attempt at finding such a "dedicated" frame?

If it's door #2, what if we used the first frame found containing a
buffer belonging to the same connection (and if no such frame exists,
just leave it up to the display-buffer gods)? This way, we could rely
more fully on window.el facilities and avoid having to wrangle yet more
state. Or, if really necessary, we could maybe fall back on a strategy
that uses `window-prev-buffers' (or whatever) to find the most recently
used frame for that connection (overkill, IMO). Either way, any solution
would need to address not just autojoined channels but also
server-initiated JOINs, PMs, etc.

The attached patch claims to do something like I've described. If you're
able to try it, please set these options beforehand:

  (setq erc-join-buffer 'frame
        erc-auto-query 'frame
        erc-query-display 'frame
        erc-reuse-frames 'displayed)

If you're unable to try it, please let me know, and I can maybe add it
temporarily to one of ERC's installable bug packages.

Thanks,
J.P.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Allow-erc-reuse-frames-to-favor-connections.patch --]
[-- Type: text/x-patch, Size: 9892 bytes --]

From be5ec788ea9fa4375b7d0c96b7d646796daf56d0 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@neverwas.me>
Date: Sat, 21 May 2022 00:04:04 -0700
Subject: [PATCH] Allow erc-reuse-frames to favor connections

* lisp/erc/erc.el (erc-reuse-frames): Add alternate value to favor
existing frames already displaying other buffers from the same
connection.
(erc-setup-buffer): Add case for "displayed" variant of
`erc-reuse-frames'.
---
 lisp/erc/erc.el            |  39 ++++++++++---
 test/lisp/erc/erc-tests.el | 115 +++++++++++++++++++++++++++++++++++++
 2 files changed, 146 insertions(+), 8 deletions(-)

diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index ff482d4933..f82fb07a66 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -1536,12 +1536,17 @@ erc-frame-dedicated-flag
   :type 'boolean)
 
 (defcustom erc-reuse-frames t
-  "Determines whether new frames are always created.
-Non-nil means that a new frame is not created to display an ERC
-buffer if there is already a window displaying it.  This only has
-effect when `erc-join-buffer' is set to `frame'."
+  "Non-nil means only create a frame for undisplayed buffers.
+For new target buffers, a value of 'displayed' extends this to mean use
+the frame of any buffer from the same server connection, visible or not.
+When this option is nil, a new frame is always created.  Regardless of
+its value, this option is ignored unless `erc-join-buffer' is set to
+`frame'.  Note that like most options in the `erc-buffer' customize
+group, this has no effect on server buffers while reconnecting."
+  :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
   :group 'erc-buffers
-  :type 'boolean)
+  :type '(choice boolean
+                 (const displayed)))
 
 (defun erc-channel-p (channel)
   "Return non-nil if CHANNEL seems to be an IRC channel name."
@@ -1943,6 +1948,19 @@ erc-update-modules
             (funcall sym 1)
           (error "`%s' is not a known ERC module" mod))))))
 
+(defun erc--setup-buffer-frame-displayed (buffer)
+  "Maybe display BUFFER in an existing frame for the same connection.
+If performed, return window used; otherwise, return nil."
+  (when-let*
+      ((bs (erc-buffer-list nil erc-server-process))
+       (visit (lambda (w) (when (memq (window-buffer w) bs) (throw 'found t))))
+       (test (lambda (fr) (catch 'found (walk-windows visit 0 fr))))
+       ((or (cdr (frame-list)) (funcall test (selected-frame)))))
+    (display-buffer buffer `((display-buffer-use-some-frame)
+                             (inhibit-switch-frame . t)
+                             (inhibit-same-window . t)
+                             (frame-predicate . ,test)))))
+
 (defun erc-setup-buffer (buffer)
   "Consults `erc-join-buffer' to find out how to display `BUFFER'."
   (pcase erc-join-buffer
@@ -1955,15 +1973,20 @@ erc-setup-buffer
     ('bury
      nil)
     ('frame
-     (when (or (not erc-reuse-frames)
-               (not (get-buffer-window buffer t)))
+     (cond
+      ((and (eq erc-reuse-frames 'displayed)
+            erc-default-recipients ; change this to `erc--target' after bug#48598
+            (not (get-buffer-window buffer t))
+            (erc--setup-buffer-frame-displayed buffer)))
+      ((or (not erc-reuse-frames)
+           (not (get-buffer-window buffer t)))
        (let ((frame (make-frame (or erc-frame-alist
                                     default-frame-alist))))
          (raise-frame frame)
          (select-frame frame))
        (switch-to-buffer buffer)
        (when erc-frame-dedicated-flag
-         (set-window-dedicated-p (selected-window) t))))
+         (set-window-dedicated-p (selected-window) t)))))
     (_
      (if (active-minibuffer-window)
          (display-buffer buffer)
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 520f10dd4e..1eac6b22c9 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -171,6 +171,121 @@ erc--switch-to-buffer
     (dolist (b '("server" "other" "#chan" "#foo" "#fake"))
       (kill-buffer b))))
 
+(ert-deftest erc-reuse-frames ()
+  ;; TODO run this in a pseudo terminal subprocess for EMBA
+  (skip-unless (not noninteractive))
+  (should-not erc-frame-dedicated-flag)
+  (let ((erc-join-buffer 'frame)
+        (erc-reuse-frames t)
+        (orig-frame (selected-frame))
+        erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+    (ert-info ("Value: t")
+      (with-current-buffer (generate-new-buffer "server")
+        (erc-mode)
+        (setq erc-server-process (start-process "server" (current-buffer)
+                                                "sleep" "1")
+              erc-frame-alist (cons '(name . "server") default-frame-alist))
+        (set-process-query-on-exit-flag erc-server-process nil)
+        (should-not (get-buffer-window (current-buffer) t))
+        (erc-setup-buffer (current-buffer))
+        ;; New frame created and raised
+        (should (equal "server" (frame-parameter (window-frame) 'name)))
+        (should (get-buffer-window (current-buffer) t))
+
+        (with-current-buffer (generate-new-buffer "#chan")
+          (erc-mode)
+          (setq erc-server-process erc-server-process
+                erc-frame-alist (cons '(name . "#chan") default-frame-alist)
+                erc-default-recipients '("#chan"))
+          (should-not (get-buffer-window (current-buffer) t))
+          (erc-setup-buffer (current-buffer))
+          ;; Another frame was created just for #chan
+          (should (equal "#chan" (frame-parameter (window-frame) 'name)))
+          (should (get-buffer-window (current-buffer) t))
+          (delete-frame))
+
+        (select-frame-by-name "server")
+        (pop-to-buffer "#chan")
+        ;; The server frame contains two vertical windows
+        (let ((tree (window-tree)))
+          (should (memq (get-buffer-window "server" t) (car tree)))
+          (should (memq (get-buffer-window "#chan" t) (car tree))))
+        (should (eq (get-buffer "#chan") (window-buffer (selected-window))))
+        (should (eq (get-buffer "server") (window-buffer (next-window))))))
+
+    (ert-info ("Value: displayed, scratch frame selected")
+      (select-frame orig-frame)
+      (with-current-buffer "*scratch*"
+        (with-current-buffer (generate-new-buffer "#spam")
+          (erc-mode)
+          (setq erc-server-process (buffer-local-value 'erc-server-process
+                                                       (get-buffer "server"))
+                erc-reuse-frames 'displayed
+                erc-frame-alist (cons '(name . "#spam") default-frame-alist)
+                erc-default-recipients '("#spam"))
+          (should-not (get-buffer-window (current-buffer) t))
+          (erc-setup-buffer (current-buffer))
+          ;; Window shows up in other frame
+          (should (eq (selected-frame) orig-frame))
+          (let ((fr (window-frame (get-buffer-window (current-buffer) t))))
+            (should (equal "server" (frame-parameter fr 'name)))
+            (with-selected-frame fr
+              (should (memq (get-buffer-window "#spam" t)
+                            (car (window-tree))))))))
+
+      (with-current-buffer "server"
+        (ert-info ("Value: displayed, server frame selected")
+          (select-frame-by-name "server")
+          (select-window (get-buffer-window "#spam"))
+          (with-current-buffer (generate-new-buffer "bob")
+            (erc-mode)
+            (setq erc-server-process (buffer-local-value 'erc-server-process
+                                                         (get-buffer "server"))
+                  erc-frame-alist (cons '(name . "bob") default-frame-alist)
+                  erc-default-recipients '("bob"))
+            (should-not (get-buffer-window (current-buffer) t))
+            (erc-setup-buffer (current-buffer))
+            ;; Window shows up in this frame
+            (let ((fr (window-frame (get-buffer-window (current-buffer) t))))
+              (should (eq fr (selected-frame)))
+              (should (equal "server" (frame-parameter fr 'name)))
+              (with-selected-frame fr
+                (should (memq (get-buffer-window "bob" t)
+                              (car (window-tree)))))
+              ;; `inhibit-same-window' respected
+              (should-not (eq (get-buffer-window "bob") (selected-window))))))
+
+        (ert-info ("Value: displayed, other frames deleted")
+          (with-selected-frame orig-frame
+            (delete-frame))
+          (should-not (cdr (frame-list)))
+          (select-window (get-buffer-window "bob"))
+          (with-current-buffer (generate-new-buffer "alice")
+            (erc-mode)
+            (setq erc-server-process (buffer-local-value 'erc-server-process
+                                                         (get-buffer "server"))
+                  erc-frame-alist (cons '(name . "alice") default-frame-alist)
+                  erc-default-recipients '("alice"))
+            (should-not (get-buffer-window (current-buffer) t))
+            (erc-setup-buffer (current-buffer))
+            (let ((fr (window-frame (get-buffer-window (current-buffer) t))))
+              (should (eq fr (selected-frame)))
+              (should (equal "server" (frame-parameter fr 'name)))
+              (with-selected-frame fr
+                (should (memq (get-buffer-window "alice" t)
+                              (car (window-tree)))))
+              (should-not (eq (get-buffer-window "alice")
+                              (selected-window)))))))))
+
+  (should-not (cdr (frame-list)))
+  (delete-other-windows)
+  (kill-buffer "server")
+  (kill-buffer "bob")
+  (kill-buffer "alice")
+  (kill-buffer "#spam")
+  (kill-buffer "#chan"))
+
 (ert-deftest erc-lurker-maybe-trim ()
   (let (erc-lurker-trim-nicks
         (erc-lurker-ignore-chars "_`"))
-- 
2.36.1


  parent reply	other threads:[~2022-05-23  1:56 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-20 13:06 bug#55540: 29.0.50; ERC launches autojoin-channels in current frame instead of original frame Pankaj Jangid
2022-05-20 13:10 ` Lars Ingebrigtsen
2022-05-20 13:31   ` Pankaj Jangid
2022-05-20 13:37     ` Lars Ingebrigtsen
2022-05-23  1:56 ` J.P. [this message]
     [not found] ` <87a6b92ers.fsf@neverwas.me>
2022-05-23  2:50   ` bug#51753: ERC switches to channel buffer on reconnect Pankaj Jangid
2022-05-23  7:48     ` J.P.
     [not found]     ` <87fsl0zo2e.fsf@neverwas.me>
2022-08-10 13:15       ` bug#51753: bug#55540: 29.0.50; ERC launches autojoin-channels in current frame J.P.
     [not found]       ` <87a68cnss7.fsf_-_@neverwas.me>
2022-08-11  2:55         ` Pankaj Jangid
     [not found]         ` <87sfm3tro1.fsf@codeisgreat.org>
2022-09-06 11:01           ` bug#51753: bug#55540: 29.0.50; ERC launches autojoin-channels in current frame instead of original frame Lars Ingebrigtsen
2022-09-06 11:01           ` Lars Ingebrigtsen
     [not found]           ` <87o7vsu5pc.fsf_-_@gnus.org>
2022-09-06 13:53             ` bug#51753: " J.P.
2022-09-06 13:53             ` J.P.
     [not found]             ` <87o7vs38yp.fsf@neverwas.me>
2022-09-06 14:02               ` bug#51753: " Lars Ingebrigtsen
2022-09-07  3:10                 ` J.P.
2022-09-07  3:10                 ` bug#51753: " J.P.
     [not found]                 ` <874jxj282o.fsf@neverwas.me>
2022-09-07 12:55                   ` Lars Ingebrigtsen
2022-09-07 12:55                   ` Lars Ingebrigtsen
     [not found]                   ` <87mtbbmjho.fsf@gnus.org>
2022-09-20 13:11                     ` bug#51753: " J.P.
2022-09-20 13:11                     ` J.P.
     [not found]                     ` <87pmfq198w.fsf@neverwas.me>
2022-09-22  3:07                       ` Pankaj Jangid
2022-09-22  3:07                       ` bug#51753: " Pankaj Jangid
     [not found]                       ` <87y1uc150p.fsf@codeisgreat.org>
2022-09-22  6:22                         ` J.P.
2023-04-08 23:25                           ` J.P.
2023-04-08 23:25                           ` bug#51753: " J.P.
     [not found]                   ` <87pmg77tpc.fsf@dataswamp.org>
2022-12-30 14:28                     ` J.P.
  -- strict thread matches above, loose matches on Subject: below --
2021-11-10 15:09 bug#51753: ERC switches to channel buffer on reconnect Stefan Kangas
2021-11-11  3:14 ` J.P.
2021-11-11  3:29   ` Lars Ingebrigtsen
     [not found]   ` <87bl2re5eg.fsf@gnus.org>
2021-11-11  5:13     ` J.P.
     [not found]     ` <87lf1ve0m4.fsf@neverwas.me>
2021-11-11  5:22       ` Lars Ingebrigtsen
     [not found]       ` <877ddf9sht.fsf@gnus.org>
2021-11-19 10:36         ` J.P.
     [not found]         ` <87czmwjutj.fsf@neverwas.me>
2021-11-19 11:45           ` Stefan Kangas
     [not found]           ` <CADwFkm=_RaiRkwte+JPRvuM4fntevprWr-qjaBaG6D+Gud_UoQ@mail.gmail.com>
2021-11-19 13:13             ` J.P.
2021-11-20  7:21             ` J.P.
     [not found]             ` <87ilwnnvfs.fsf@neverwas.me>
2021-11-20  9:09               ` Stefan Kangas
     [not found]               ` <CADwFkmnL1ugFn4VYi--5ygJnYu4RmES6VGjku6j92fy+8B6yeA@mail.gmail.com>
2021-11-21 22:54                 ` J.P.
     [not found]                 ` <87sfvp5dd5.fsf@neverwas.me>
2021-12-02 19:43                   ` Stefan Kangas
     [not found]                   ` <CADwFkmmqNW-CyrxUU1-TiqEvUhwYe=zzVOO_q2iEAHmQYorudw@mail.gmail.com>
2021-12-03  5:31                     ` J.P.

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='87a6b92ers.fsf__10809.7206613579$1653271045$gmane$org@neverwas.me' \
    --to=jp@neverwas.me \
    --cc=51753@debbugs.gnu.org \
    --cc=emacs-erc@gnu.org \
    --cc=pankaj@codeisgreat.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).