From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: "J.P." Newsgroups: gmane.emacs.bugs Subject: bug#64855: 30.0.50; ERC 5.6: Make scrolltobottom less erratic Date: Wed, 26 Jul 2023 06:27:58 -0700 Message-ID: <87351ax0o1.fsf__40818.3792418399$1690394229$gmane$org@neverwas.me> References: <87h6psyurb.fsf@neverwas.me> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="23796"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: emacs-erc@gnu.org To: 64855@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Jul 26 19:57:00 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qOikt-0005uB-DR for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 26 Jul 2023 19:56:59 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qOiDe-0000r4-I6; Wed, 26 Jul 2023 13:22:38 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qOeZb-0004jT-7r for bug-gnu-emacs@gnu.org; Wed, 26 Jul 2023 09:29:03 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qOeZb-00040W-0f for bug-gnu-emacs@gnu.org; Wed, 26 Jul 2023 09:29:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qOeZa-00087y-Sd for bug-gnu-emacs@gnu.org; Wed, 26 Jul 2023 09:29:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: "J.P." Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 26 Jul 2023 13:29:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 64855 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 64855-submit@debbugs.gnu.org id=B64855.169037809131126 (code B ref 64855); Wed, 26 Jul 2023 13:29:02 +0000 Original-Received: (at 64855) by debbugs.gnu.org; 26 Jul 2023 13:28:11 +0000 Original-Received: from localhost ([127.0.0.1]:47723 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qOeYk-00085x-14 for submit@debbugs.gnu.org; Wed, 26 Jul 2023 09:28:10 -0400 Original-Received: from mail-108-mta74.mxroute.com ([136.175.108.74]:46257) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qOeYh-00085i-Mh for 64855@debbugs.gnu.org; Wed, 26 Jul 2023 09:28:09 -0400 Original-Received: from mail-111-mta2.mxroute.com ([136.175.111.2] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta74.mxroute.com (ZoneMTA) with ESMTPSA id 189926295400004cef.001 for <64855@debbugs.gnu.org> (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Wed, 26 Jul 2023 13:28:01 +0000 X-Zone-Loop: 9655449b70fb01798a690afc88204fd2d73ff57bb88a X-Originating-IP: [136.175.111.2] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=fdH8WGFL0syyAMwhMx+kvQrFMdIJsr0x8N+3o07csec=; b=FHY79HJlyb2zs990ykLdf3cWq7 fHX0/SJ6sgminKZpSAc4Wj/prCNYtL/O1DfEW4y35rI/ZhwD73Zwvu9PHFdDGE5JMB9vnZjONjpn/ HYM3eczZGNBVJevDWLJ3v/W/mVYEjUE+GpMYTCj7l3YdVN45jFb+h64a9cYZNQzAXjI0D0XO+z7dx 0oG3CFxCUoG8zUgx9dJrd325Pu5rVwcuR1foFEYlnq6b6qFuDYgUKw0nFRNJA0EA3CzFI8LLxuLv3 UT/FnckohduwW/ApvFHpkfHOTm3D/n5/MtBLd4ucaiHlIt8LKNPn56E1mpe+AiOgiH4pALxNxmR6S R+F9lZPw==; In-Reply-To: <87h6psyurb.fsf@neverwas.me> (J. P.'s message of "Tue, 25 Jul 2023 06:40:24 -0700") X-Authenticated-Id: masked@neverwas.me X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:266119 Archived-At: --=-=-= Content-Type: text/plain v2. Stash and restore `window-start' for all windows when inserting messages. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v1-v2.diff >From 49e66fee68a4ad69418dae329e24e5611ea8de6e Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Wed, 26 Jul 2023 05:33:54 -0700 Subject: [PATCH 0/1] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (1): [5.6] Consider all windows in erc-scrolltobottom-mode lisp/erc/erc-goodies.el | 102 +++++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 11 deletions(-) Interdiff: diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index af44b98e0bf..e82dc73f82f 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el @@ -52,22 +52,26 @@ erc-input-line-position (define-erc-module scrolltobottom nil "This mode causes the prompt to stay at the end of the window." ((add-hook 'erc-mode-hook #'erc-add-scroll-to-bottom) - (add-hook 'erc-insert-pre-hook #'erc--on-pre-insert) + (add-hook 'erc-insert-pre-hook #'erc--scroll-to-bottom-on-pre-insert) + (add-hook 'erc-send-pre-functions #'erc--scroll-to-bottom-on-pre-insert) (add-hook 'erc-insert-done-hook #'erc--scroll-to-bottom-all) (add-hook 'erc-send-completed-hook #'erc--scroll-to-bottom-all) (unless erc--updating-modules-p (erc-buffer-do #'erc-add-scroll-to-bottom))) ((remove-hook 'erc-mode-hook #'erc-add-scroll-to-bottom) - (remove-hook 'erc-insert-pre-hook #'erc--on-pre-insert) + (remove-hook 'erc-insert-pre-hook #'erc--scroll-to-bottom-on-pre-insert) + (remove-hook 'erc-send-pre-functions #'erc--scroll-to-bottom-on-pre-insert) (remove-hook 'erc-insert-done-hook #'erc--scroll-to-bottom-all) (remove-hook 'erc-send-completed-hook #'erc--scroll-to-bottom-all) (erc-buffer-do #'erc-add-scroll-to-bottom))) (defvar-local erc--scroll-to-bottom-debounce-expire nil - "Time after which `scrolltobottom' is allowed to run. -Set to a fraction of a second in the future on every refresh.") + "A cons of some window and the expiration time in seconds. +The CAR is a window in whose buffer this variable is local. The +CDR is a half second after the last attempted refresh of such a +window.") (defvar-local erc--scroll-to-bottom-last-window-start nil - "A cons of a window and a starting position.") + "Alist whose members are a cons of a window and a starting position.") (defun erc-possibly-scroll-to-bottom () "Like `erc-add-scroll-to-bottom', but only if window is selected." @@ -76,18 +80,36 @@ erc-possibly-scroll-to-bottom (defun erc--possibly-scroll-to-bottom () "Call `erc-scroll-to-bottom' when buffer occupies selected window. -Skip when `erc--scroll-to-bottom-debounce-expire' has not yet -arrived." +Expect narrowing not to be in effect. Skip when +`erc--scroll-to-bottom-debounce-expire' has not yet transpired." (when (eq (selected-window) (get-buffer-window)) - (unless (eq this-command 'recenter-top-bottom) - (let (erc--scroll-to-bottom-last-window-start) - (erc--scroll-to-bottom))))) + (unless (or (eq this-command 'recenter-top-bottom) (input-pending-p)) + (let ((now (erc-current-time)) + (at-prompt-p (>= (point) erc-input-marker))) + (unless (and at-prompt-p + erc--scroll-to-bottom-debounce-expire + (eq (car erc--scroll-to-bottom-debounce-expire) + (selected-window)) + (< now (cdr erc--scroll-to-bottom-debounce-expire))) + (erc--scroll-to-bottom)) + (setq erc--scroll-to-bottom-debounce-expire + (and at-prompt-p (cons (selected-window) (+ now 0.5)))))))) (defun erc--scroll-to-bottom-all (&rest _) - "Run `erc-scroll-to-bottom' in all windows showing current buffer." + "Maybe put prompt on last line in all windows displaying current buffer. +Expect to run when narrowing is in effect, such as on insertion +or send-related hooks. When recentering has not been performed, +attempt to restore last `window-start', if known." (dolist (window (get-buffer-window-list nil nil 'visible)) (with-selected-window window - (erc--scroll-to-bottom)))) + (when-let + (((not (erc--scroll-to-bottom))) + (erc--scroll-to-bottom-last-window-start) + (found (assq window erc--scroll-to-bottom-last-window-start))) + (setf (window-start window) (cdr found))))) + ;; Necessary unless we're sure `erc--scroll-to-bottom-on-pre-insert' + ;; always runs between calls to this function. + (setq erc--scroll-to-bottom-last-window-start nil)) (defun erc-add-scroll-to-bottom () "Arrange for `scrolltobottom' to refresh on window configuration changes. @@ -110,31 +132,30 @@ erc-add-scroll-to-bottom (remove-hook 'post-command-hook #'erc--possibly-scroll-to-bottom t))) -(defun erc--on-pre-insert (&rest _) - (when (eq (selected-window) (get-buffer-window)) - (setq erc--scroll-to-bottom-last-window-start - (cons (selected-window) (window-start))))) +(cl-defmethod erc--scroll-to-bottom-on-pre-insert (_input-or-string) + "Remember the `window-start' before inserting a message." + (setq erc--scroll-to-bottom-last-window-start + (mapcar (lambda (w) (cons w (window-start w))) + (get-buffer-window-list nil nil 'visible)))) + +(cl-defmethod erc--scroll-to-bottom-on-pre-insert ((input erc-input)) + "Remember the `window-start' before inserting a message." + (when (erc-input-insertp input) + (cl-call-next-method))) (defun erc--scroll-to-bottom () "Like `erc-scroll-to-bottom', but use `window-point'. Expect to run in some window, not necessarily the user-selected -one." +one. Return non-nil when recentering has occurred." (when erc-insert-marker (let ((resize-mini-windows nil)) (save-restriction (widen) - (if (>= (window-point) erc-input-marker) - (save-excursion - (goto-char (point-max)) - (recenter (or erc-input-line-position -1))) - (when (and erc--scroll-to-bottom-last-window-start - ;; `selected-window' means the one being visited. - (eq (selected-window) - (car erc--scroll-to-bottom-last-window-start))) - (save-excursion - (goto-char (cdr erc--scroll-to-bottom-last-window-start)) - (let ((recenter-positions '(top))) - (recenter-top-bottom))))))))) + (when (>= (window-point) erc-input-marker) + (save-excursion + (goto-char (point-max)) + (recenter (or erc-input-line-position -1)) + t)))))) (defun erc-scroll-to-bottom () "Recenter WINDOW so that `point' is on the last line. -- 2.41.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-5.6-Consider-all-windows-in-erc-scrolltobottom-mode.patch >From 49e66fee68a4ad69418dae329e24e5611ea8de6e Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sat, 22 Jul 2023 00:46:44 -0700 Subject: [PATCH 1/1] [5.6] Consider all windows in erc-scrolltobottom-mode * lisp/erc/erc-goodies.el (erc-scrolltobottom-mode, erc-scrolltobottom-enable, erc-scrolltobottom-disable): Use `erc--scroll-to-bottom-all' instead of `erc-possibly-scroll-to-bottom' for `erc-insert-done-hook' and now also `erc-send-completed-hook'. Add `erc--scroll-to-bottom-on-pre-insert' to `erc-insert-pre-hook' and `erc-send-pre-functions'. Call `erc-add-scroll-to-bottom' for teardown as well. (erc--scroll-to-bottom-debounce-expire): New variable to help ERC refrain from calling `recenter' when the user is typing at the prompt. (erc--scroll-to-bottom-last-window-start): New variable used by `erc--scroll-to-bottom-on-pre-insert' and `erc--scroll-to-bottom' for stashing and restoring the `window-start' of all windows displaying the buffer. (erc--possibly-scroll-to-bottom): New function resembling `erc-possibly-scroll-to-bottom' that tries to avoid scrolling again when user has done so recently. (erc--scroll-to-bottom-all): New function to scroll all windows displaying the current buffer. (erc-add-scroll-to-bottom): Perform teardown as well when mode is disabled. Also run on `window-configuration-changed-hook'. (erc-scroll-to-bottom): Use `window-point' instead of `point'. (erc--scroll-to-bottom-on-pre-insert): New generic function that remembers the `window-start' before inserting a message in order to restore it afterward. (erc--scroll-to-bottom): New function, a replacement for `erc-scroll-to-bottom', that takes returns non-nil when it's actually performed a recentering. (Bug#64855) --- lisp/erc/erc-goodies.el | 102 +++++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 11 deletions(-) diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index d9ededa8e68..e82dc73f82f 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el @@ -52,34 +52,114 @@ erc-input-line-position (define-erc-module scrolltobottom nil "This mode causes the prompt to stay at the end of the window." ((add-hook 'erc-mode-hook #'erc-add-scroll-to-bottom) - (add-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom) + (add-hook 'erc-insert-pre-hook #'erc--scroll-to-bottom-on-pre-insert) + (add-hook 'erc-send-pre-functions #'erc--scroll-to-bottom-on-pre-insert) + (add-hook 'erc-insert-done-hook #'erc--scroll-to-bottom-all) + (add-hook 'erc-send-completed-hook #'erc--scroll-to-bottom-all) (unless erc--updating-modules-p (erc-buffer-do #'erc-add-scroll-to-bottom))) ((remove-hook 'erc-mode-hook #'erc-add-scroll-to-bottom) - (remove-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom) - (dolist (buffer (erc-buffer-list)) - (with-current-buffer buffer - (remove-hook 'post-command-hook #'erc-scroll-to-bottom t))))) + (remove-hook 'erc-insert-pre-hook #'erc--scroll-to-bottom-on-pre-insert) + (remove-hook 'erc-send-pre-functions #'erc--scroll-to-bottom-on-pre-insert) + (remove-hook 'erc-insert-done-hook #'erc--scroll-to-bottom-all) + (remove-hook 'erc-send-completed-hook #'erc--scroll-to-bottom-all) + (erc-buffer-do #'erc-add-scroll-to-bottom))) + +(defvar-local erc--scroll-to-bottom-debounce-expire nil + "A cons of some window and the expiration time in seconds. +The CAR is a window in whose buffer this variable is local. The +CDR is a half second after the last attempted refresh of such a +window.") + +(defvar-local erc--scroll-to-bottom-last-window-start nil + "Alist whose members are a cons of a window and a starting position.") (defun erc-possibly-scroll-to-bottom () "Like `erc-add-scroll-to-bottom', but only if window is selected." (when (eq (selected-window) (get-buffer-window)) (erc-scroll-to-bottom))) +(defun erc--possibly-scroll-to-bottom () + "Call `erc-scroll-to-bottom' when buffer occupies selected window. +Expect narrowing not to be in effect. Skip when +`erc--scroll-to-bottom-debounce-expire' has not yet transpired." + (when (eq (selected-window) (get-buffer-window)) + (unless (or (eq this-command 'recenter-top-bottom) (input-pending-p)) + (let ((now (erc-current-time)) + (at-prompt-p (>= (point) erc-input-marker))) + (unless (and at-prompt-p + erc--scroll-to-bottom-debounce-expire + (eq (car erc--scroll-to-bottom-debounce-expire) + (selected-window)) + (< now (cdr erc--scroll-to-bottom-debounce-expire))) + (erc--scroll-to-bottom)) + (setq erc--scroll-to-bottom-debounce-expire + (and at-prompt-p (cons (selected-window) (+ now 0.5)))))))) + +(defun erc--scroll-to-bottom-all (&rest _) + "Maybe put prompt on last line in all windows displaying current buffer. +Expect to run when narrowing is in effect, such as on insertion +or send-related hooks. When recentering has not been performed, +attempt to restore last `window-start', if known." + (dolist (window (get-buffer-window-list nil nil 'visible)) + (with-selected-window window + (when-let + (((not (erc--scroll-to-bottom))) + (erc--scroll-to-bottom-last-window-start) + (found (assq window erc--scroll-to-bottom-last-window-start))) + (setf (window-start window) (cdr found))))) + ;; Necessary unless we're sure `erc--scroll-to-bottom-on-pre-insert' + ;; always runs between calls to this function. + (setq erc--scroll-to-bottom-last-window-start nil)) + (defun erc-add-scroll-to-bottom () - "A hook function for `erc-mode-hook' to recenter output at bottom of window. + "Arrange for `scrolltobottom' to refresh on window configuration changes. +Undo that arrangement when `erc-scrolltobottom-mode' is disabled. If you find that ERC hangs when using this function, try customizing the value of `erc-input-line-position'. -This works whenever scrolling happens, so it's added to -`window-scroll-functions' rather than `erc-insert-post-hook'." - (add-hook 'post-command-hook #'erc-scroll-to-bottom nil t)) +Note that the prior suggestion comes from a time when this +function used `window-scroll-functions', which was replaced by +`post-command-hook' in ERC 5.3." + (if erc-scrolltobottom-mode + (progn + (add-hook 'window-configuration-change-hook + #'erc--possibly-scroll-to-bottom nil t) + (add-hook 'post-command-hook + #'erc--possibly-scroll-to-bottom nil t)) + (remove-hook 'window-configuration-change-hook + #'erc--possibly-scroll-to-bottom t) + (remove-hook 'post-command-hook + #'erc--possibly-scroll-to-bottom t))) + +(cl-defmethod erc--scroll-to-bottom-on-pre-insert (_input-or-string) + "Remember the `window-start' before inserting a message." + (setq erc--scroll-to-bottom-last-window-start + (mapcar (lambda (w) (cons w (window-start w))) + (get-buffer-window-list nil nil 'visible)))) + +(cl-defmethod erc--scroll-to-bottom-on-pre-insert ((input erc-input)) + "Remember the `window-start' before inserting a message." + (when (erc-input-insertp input) + (cl-call-next-method))) + +(defun erc--scroll-to-bottom () + "Like `erc-scroll-to-bottom', but use `window-point'. +Expect to run in some window, not necessarily the user-selected +one. Return non-nil when recentering has occurred." + (when erc-insert-marker + (let ((resize-mini-windows nil)) + (save-restriction + (widen) + (when (>= (window-point) erc-input-marker) + (save-excursion + (goto-char (point-max)) + (recenter (or erc-input-line-position -1)) + t)))))) (defun erc-scroll-to-bottom () "Recenter WINDOW so that `point' is on the last line. -This is added to `window-scroll-functions' by `erc-add-scroll-to-bottom'. - You can control which line is recentered to by customizing the variable `erc-input-line-position'." ;; Temporarily bind resize-mini-windows to nil so that users who have it -- 2.41.0 --=-=-=--