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#60936: 30.0.50; ERC >5.5: Add erc-fill style based on visual-line-mode Date: Fri, 22 Sep 2023 07:11:08 -0700 Message-ID: <87a5te47sz.fsf__35053.5101069667$1695391935$gmane$org@neverwas.me> References: <87tu0nao77.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="18322"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: emacs-erc@gnu.org To: 60936@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Fri Sep 22 16:12:07 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 1qjgt5-0004Wn-4v for geb-bug-gnu-emacs@m.gmane-mx.org; Fri, 22 Sep 2023 16:12:07 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qjgsr-0005d2-6R; Fri, 22 Sep 2023 10:11:53 -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 1qjgsp-0005ca-Um for bug-gnu-emacs@gnu.org; Fri, 22 Sep 2023 10:11:51 -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 1qjgsp-0000Tb-N0 for bug-gnu-emacs@gnu.org; Fri, 22 Sep 2023 10:11:51 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qjgsz-0002C7-Vl for bug-gnu-emacs@gnu.org; Fri, 22 Sep 2023 10:12: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: Fri, 22 Sep 2023 14:12:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 60936 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 60936-submit@debbugs.gnu.org id=B60936.16953918928398 (code B ref 60936); Fri, 22 Sep 2023 14:12:01 +0000 Original-Received: (at 60936) by debbugs.gnu.org; 22 Sep 2023 14:11:32 +0000 Original-Received: from localhost ([127.0.0.1]:37034 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjgsU-0002BM-T9 for submit@debbugs.gnu.org; Fri, 22 Sep 2023 10:11:32 -0400 Original-Received: from mail-108-mta116.mxroute.com ([136.175.108.116]:42783) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qjgsP-0002BA-Qe for 60936@debbugs.gnu.org; Fri, 22 Sep 2023 10:11:29 -0400 Original-Received: from mail-111-mta2.mxroute.com ([136.175.111.2] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta116.mxroute.com (ZoneMTA) with ESMTPSA id 18abd3af79b000d7b6.001 for <60936@debbugs.gnu.org> (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Fri, 22 Sep 2023 14:11:12 +0000 X-Zone-Loop: ed607968ac776a6656a2ec97229e2079fa8d030b1261 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=kwX36DY8VV/Fycd1jSackMfWEQQ5tP3AqXXJvOIclKs=; b=lwAs59VLhC0FWdkv4sSyaCP358 XndQNt4NW/GhCWOoqutXlOowx3KwJ4sE06fiA42z/4lngOQ72DeQN1zF9CZkTYw8sYQ7Wu7TXIOzu 7139SkdDtW8hxOIMKQukmwCfqxDG7lF2inMjYxu0NgaiwjDD372O2KuP3T7RscNQWooNYlSUuKqKW wtJpl2TV7nKgp8vMc3MbFNjyL+odZtOvW8JiGotbvjkFRcKbiN5yreuXzMGzUCBVmq3ilXU5ZHy1I OnIInu3I7Pbqfaa2yZnHCojh4NzIZ2okoVKDtNzTv+N1cudVK/XQUBQnszGn76vFCyGCN5tNu1lcc yQ1pPwCA==; In-Reply-To: <87tu0nao77.fsf@neverwas.me> (J. P.'s message of "Wed, 18 Jan 2023 06:53:48 -0800") 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:271100 Archived-At: --=-=-= Content-Type: text/plain A couple more bugs stemming from this feature's introduction have surfaced. The first involves stamp hiding when `erc-fill-wrap-mode' is enabled. To reproduce from emacs -Q: - Connect and join a channel - In the channel buffer, set `erc-timestamp-last-inserted-left' to nil - Say something and notice a new date stamp inserted - Run M-x erc-toggle-timestamps RET - Notice that the message after the stamp is dedented incorrectly This problem occurs because date stamps are not well defined and straddle roles occupied by normal stamps and standalone messages. The remedy I've chosen retains compatibility at the cost of kicking the can down the road WRT defining the precise role and expected behavior of date stamps. (If still unclear, I say "date stamp" to mean a left-sided stamp inserted by the function `erc-insert-timestamp-left-and-right' and formatted using the string `erc-timestamp-format-left'.) This issue is closely related to the interplay between normal right-hand stamps and non-`fill-wrap' fill functions because the latter hard-wrap (i.e., "fill") messages, which results in a stamp often residing on its own line. The second issue comes down to the lack of an integration with `text-scale-mode'. To reproduce from emacs -Q: - Connect from a graphical Emacs - In the server buffer, hit C-x C-=, and notice misaligned speaker tags among the upscaled text - Run a command, like "/msg NickServ help", and notice the leading `erc-notice-prefix' portion of new messages correctly dedented - Hit C-x C-0 and observe the just-inserted messages now looking mangled and the preexisting ones seemingly restored The problem is that our `line-prefix' values use display specs with pixel widths, which is needed for speakers with variable-width faces and non-ascii chars. (Based on a cursory glance at relevant sections of the manual, it doesn't look like there's an easy way to adjust these automatically.) For now, I'm proposing we include a command to manually traverse and refill target buffers. Luckily, this is much faster than it'd be with some other `erc-fill-function' because no actual "filling" takes place. We're just remeasuring speaker tags and replacing existing display-spec values. If you're affected by these bugs, please try these patches. Thanks. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-5.6-Prefer-ticks-hz-pairs-for-erc-timestamp-values-o.patch >From c4d98ab82a9edac04abdde59df4055685f17b6cb Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 18 Sep 2023 22:50:28 -0700 Subject: [PATCH 1/3] [5.6] Prefer ticks/hz pairs for erc-timestamp values on <29 * lisp/erc/erc-compat.el (erc-compat--current-lisp-time): New macro to prefer ticks/hz pairs on older Emacs versions. They're easier to compare at a glance when used as values for text properties. * lisp/erc/erc-stamp.el (erc-stamp--current-time): Use compat macro. (Bug#60936) --- lisp/erc/erc-compat.el | 6 ++++++ lisp/erc/erc-stamp.el | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el index 109b5d245ab..4dae578de67 100644 --- a/lisp/erc/erc-compat.el +++ b/lisp/erc/erc-compat.el @@ -444,6 +444,12 @@ erc-compat--29-browse-url-irc (cons '("\\`irc6?s?://" . erc-compat--29-browse-url-irc) existing)))))) +(defmacro erc-compat--current-lisp-time () + "Return `current-time' as a frequency pair." + (if (>= emacs-major-version 29) + '(let (current-time-list) (current-time)) + '(time-convert nil t))) + (provide 'erc-compat) diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el index f159b6d226f..0f3163bf68d 100644 --- a/lisp/erc/erc-stamp.el +++ b/lisp/erc/erc-stamp.el @@ -215,7 +215,7 @@ erc-stamp--current-time (cl-defgeneric erc-stamp--current-time () "Return a lisp time object to associate with an IRC message. This becomes the message's `erc-timestamp' text property." - (let (current-time-list) (current-time))) + (erc-compat--current-lisp-time)) (cl-defmethod erc-stamp--current-time :around () (or erc-stamp--current-time (cl-call-next-method))) -- 2.41.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-5.6-Fix-date-stamp-invisibility-in-erc-fill-wrap.patch >From 0c2b76532490d85a5b622e57af5aa1320278a20c Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 21 Sep 2023 23:54:31 -0700 Subject: [PATCH 2/3] [5.6] Fix date-stamp invisibility in erc-fill-wrap * lisp/erc/erc-fill.el (erc-fill--wrap-measure): New helper function, factored out from common code shared by `erc-fill-wrap' and `erc-fill--wrap-stamp-insert-prefixed-date'. (erc-fill--wrap-stamp-insert-prefixed-date): Refactor for more general use and decrement `invisible' bounds, when applicable. (erc-fill-wrap): Use helper `erc-fill--wrap-measure'. * lisp/erc/erc-stamp.el (erc-insert-timestamp-left-and-right): Mention intervals of relevant text props in doc string. * lisp/erc/erc.el (erc--hide-message): Don't bother offsetting start of first message in a buffer. (erc--own-property-names): Add `erc-stamp-type'. * test/lisp/erc/erc-scenarios-match.el (erc-scenarios-match--fill-wrap-stamp-dedented-p): New function. (erc-scenarios-match--stamp-both-invisible-fill-wrap) New test. (Bug#60936) --- lisp/erc/erc-fill.el | 54 ++++++++----- lisp/erc/erc-stamp.el | 9 ++- lisp/erc/erc.el | 9 ++- test/lisp/erc/erc-scenarios-match.el | 112 ++++++++++++++++++++++++++- 4 files changed, 162 insertions(+), 22 deletions(-) diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el index f4835f71278..6d39bcb19b9 100644 --- a/lisp/erc/erc-fill.el +++ b/lisp/erc/erc-fill.el @@ -484,25 +484,45 @@ erc-fill--wrap-continued-message-p ((erc-nick-equal-p props nick)))) (set-marker erc-fill--wrap-last-msg (point-min)))) -(defun erc-fill--wrap-stamp-insert-prefixed-date (&rest args) - "Apply `line-prefix' property to args." - (let* ((ts-left (car args)) - (start) +(defun erc-fill--wrap-measure (beg end) + "Return display spec width for inserted region between BEG and END. +Ignore any `invisible' props that may be present when figuring." + (if (and erc-fill-wrap-use-pixels (fboundp 'buffer-text-pixel-size)) + (save-restriction + (narrow-to-region beg end) + (let (buffer-invisibility-spec) + (list (car (buffer-text-pixel-size))))) + (- end beg))) + +(defun erc-fill--wrap-stamp-insert-prefixed-date (&rest _) + "Apply `line-prefix' property to args. +Expect a multi-line \"date\" stamp, similar to that provided by +the default value of `erc-timestamp-format-left'. Add +`erc-stamp-type' property with the symbol `date-left' as its +value. Possibly adjust invisibility interval to begin at the +previous newline and extend until the end of the last line of the +stamp, not including its line ending." + (let* ((beg) ;; Insert " " to simulate gap between and msg beg. (end (save-excursion (skip-chars-backward "\n") - (setq start (pos-bol)) + (setq beg (pos-bol)) (insert " ") (point))) - (width (if (and erc-fill-wrap-use-pixels - (fboundp 'buffer-text-pixel-size)) - (save-restriction (narrow-to-region start end) - (list (car (buffer-text-pixel-size)))) - (length (string-trim-left ts-left))))) + (width (erc-fill--wrap-measure beg end))) (delete-region (1- end) end) - ;; Use `point-min' instead of `start' to cover leading newilnes. + ;; Offset existing invisibility bounds by decrementing. See + ;; `erc-legacy-invisible-bounds-p'. + (when-let ((invisible (get-text-property (point) 'invisible)) + (min (point-min))) + (save-restriction + (widen) + (remove-text-properties (max 1 (1- min)) (1+ (point)) '(invisible nil)) + (narrow-to-region min (1+ (point))) + (erc--hide-message invisible))) + (put-text-property (point-min) (point) 'erc-stamp-type 'date-left) + ;; Use `point-min' instead of `beg' to cover leading newilnes. (put-text-property (point-min) (point) 'line-prefix - `(space :width (- erc-fill--wrap-value ,width)))) - args) + `(space :width (- erc-fill--wrap-value ,width))))) ;; An escape hatch for third-party code expecting speakers of ACTION ;; messages to be exempt from `line-prefix'. This could be converted @@ -536,12 +556,8 @@ erc-fill-wrap (put-text-property (point-min) (point) 'display "") 0) - ((and erc-fill-wrap-use-pixels - (fboundp 'buffer-text-pixel-size)) - (save-restriction - (narrow-to-region (point-min) (point)) - (list (car (buffer-text-pixel-size))))) - (t (- (point) (point-min)))))))) + (t + (erc-fill--wrap-measure (point-min) (point)))))))) (erc-put-text-properties (point-min) (1- (point-max)) ; exclude "\n" '(line-prefix wrap-prefix) nil `((space :width (- erc-fill--wrap-value ,len)) diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el index 0f3163bf68d..4e16906c550 100644 --- a/lisp/erc/erc-stamp.el +++ b/lisp/erc/erc-stamp.el @@ -609,7 +609,14 @@ erc-insert-timestamp-left-and-right When the deprecated option `erc-timestamp-format-right' is nil, use STRING, which originates from `erc-timestamp-format', for the right-hand stamp. Use `erc-timestamp-format-left' for the -left-hand stamp and expect it to change less frequently." +left-hand stamp and expect it to change less frequently. Include +line endings present in `erc-timestamp-format-left' as part of +the `erc-timestamp' field, which extends to the start of the +message proper. Do this so other code knows the stamp is part of +the subsequent IRC message even though it may appear on its own +line. However, allow the stamp's `invisible' property to span a +different interval, in order to satisfy newer folding +requirements related to `erc-legacy-invisible-bounds-p'." (let* ((ct (or erc-stamp--current-time (erc-stamp--current-time))) (ts-left (erc-format-timestamp ct erc-timestamp-format-left)) (ts-right (with-suppressed-warnings diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index ec4fae548c7..e4b0cd0ddbe 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -3046,7 +3046,11 @@ erc-legacy-invisible-bounds-p (defun erc--hide-message (value) "Apply `invisible' text-property with VALUE to current message. -Expect to run in a narrowed buffer during message insertion." +Expect to run in a narrowed buffer during message insertion. +Begin the invisible interval at the previous message's trailing +newline and end before the current message's. If the preceding +message ends in a double newline or there is no previous message, +don't bother including the preceding newline." (if erc-legacy-invisible-bounds-p ;; Before ERC 5.6, this also used to add an `intangible' ;; property, but the docs say it's now obsolete. @@ -3055,6 +3059,8 @@ erc--hide-message (end (point-max))) (save-restriction (widen) + (when (or (<= beg 4) (= ?\n (char-before (- beg 2)))) + (cl-incf beg)) (erc--merge-prop (1- beg) (1- end) 'invisible value))))) (defun erc-display-message-highlight (type string) @@ -4770,6 +4776,7 @@ erc--own-property-names rear-nonsticky erc-prompt field front-sticky read-only ;; stamp cursor-intangible cursor-sensor-functions isearch-open-invisible + erc-stamp-type ;; match invisible intangible ;; button diff --git a/test/lisp/erc/erc-scenarios-match.el b/test/lisp/erc/erc-scenarios-match.el index cd899fddb98..bf74806207d 100644 --- a/test/lisp/erc/erc-scenarios-match.el +++ b/test/lisp/erc/erc-scenarios-match.el @@ -167,7 +167,6 @@ erc-scenarios-match--find-eol ;; In most cases, `erc-hide-fools' makes line endings invisible. (defun erc-scenarios-match--stamp-right-fools-invisible () - :tags '(:expensive-test) (let ((erc-insert-timestamp-function #'erc-insert-timestamp-right)) (erc-scenarios-match--invisible-stamp @@ -271,6 +270,117 @@ erc-scenarios-match--stamp-right-invisible-fill-wrap (let ((inv-beg (next-single-property-change (1- (pos-bol)) 'invisible))) (should (eq (get-text-property inv-beg 'invisible) 'timestamp))))))) +(defun erc-scenarios-match--fill-wrap-stamp-dedented-p (point) + (pcase (get-text-property point 'line-prefix) + (`(space :width (- erc-fill--wrap-value (,n))) + (if (display-graphic-p) (< 100 n 200) (< 10 n 30))) + (`(space :width (- erc-fill--wrap-value ,n)) + (< 10 n 30)))) + +(ert-deftest erc-scenarios-match--stamp-both-invisible-fill-wrap () + + ;; Rewind the clock to known date artificially. + (let ((erc-stamp--current-time 704591940) + (erc-stamp--tz t) + (erc-fill-function #'erc-fill-wrap) + (bob-utterance-counter 0)) + + (erc-scenarios-match--invisible-stamp + + (lambda () + (ert-info ("Baseline check") + ;; False date printed initially before anyone speaks. + (when (zerop bob-utterance-counter) + (save-excursion + (goto-char (point-min)) + (search-forward "[Wed Apr 29 1992]") + ;; First stamp in a buffer is not invisible from previous + ;; newline (before stamp's own leading newline). + (should (= 4 (match-beginning 0))) + (should (get-text-property 3 'invisible)) + (should-not (get-text-property 2 'invisible)) + (should (erc-scenarios-match--fill-wrap-stamp-dedented-p 4)) + (search-forward "[23:59]")))) + + (ert-info ("Line endings in Bob's messages are invisible") + ;; The message proper has the `invisible' property `match-fools'. + (should (eq (get-text-property (pos-bol) 'invisible) 'match-fools)) + (let* ((mbeg (or (and (get-text-property (pos-bol) 'erc-command) + (pos-bol)) + (next-single-property-change (pos-bol) + 'erc-command))) + (mend (text-property-not-all + mbeg (point-max) 'erc-command + (get-text-property mbeg 'erc-command)))) + + (if (/= 1 bob-utterance-counter) + (should-not (field-at-pos mend)) + ;; For Bob's stamped message, check newline after stamp. + (should (eq (field-at-pos mend) 'erc-timestamp)) + (setq mend (field-end mend))) + + ;; The `erc-timestamp' property spans entire messages, + ;; including stamps and filled text, which makes for + ;; convenient traversal when `erc-stamp-mode' is enabled. + (should (get-text-property (pos-bol) 'erc-timestamp)) + (should (= (next-single-property-change (pos-bol) 'erc-timestamp) + mend)) + + ;; Line ending has the `invisible' property `match-fools'. + (should (= (char-after mend) ?\n)) + (with-suppressed-warnings ((obsolete erc-legacy-invisible-bounds-p)) + (if erc-legacy-invisible-bounds-p + (should (eq (get-text-property mend 'invisible) 'match-fools)) + (should (eq (get-text-property mbeg 'invisible) 'match-fools)) + (should-not (get-text-property mend 'invisible)))))) + + ;; Only the message right after Alice speaks contains stamps. + (when (= 1 bob-utterance-counter) + + (ert-info ("Date stamp occupying previous line is invisible") + (save-excursion + (forward-line -1) + (goto-char (pos-bol)) + (should (looking-at (rx "[Mon May 4 1992]"))) + (should (erc-scenarios-match--fill-wrap-stamp-dedented-p (point))) + ;; Date stamp has a combined `invisible' property value + ;; that starts at the previous message's trailing newline + ;; and extends until the start of the message proper. + (should (equal ?\n (char-before (point)))) + (should (equal ?\n (char-before (1- (point))))) + (let ((val (get-text-property (- (point) 2) 'invisible))) + (should (equal val '(timestamp match-fools))) + (should (= (text-property-not-all (- (point) 2) (point-max) + 'invisible val) + (pos-eol)))))) + + (ert-info ("Current message's RHS stamp is hidden") + ;; Right stamp has `match-fools' property. + (save-excursion + (should-not (field-at-pos (point))) + (should (eq (field-at-pos (1- (pos-eol))) 'erc-timestamp))) + + ;; Stamp invisibility starts where message's ends. + (let ((msgend (next-single-property-change (pos-bol) 'invisible))) + ;; Stamp has a combined `invisible' property value. + (should (equal (get-text-property msgend 'invisible) + '(timestamp match-fools))) + + ;; Combined `invisible' property spans entire timestamp. + (should (= (next-single-property-change msgend 'invisible) + (pos-eol)))))) + + (cl-incf bob-utterance-counter)) + + ;; Alice. + (lambda () + ;; Set clock ahead a week or so. + (setq erc-stamp--current-time 704962800) + + ;; This message has no time stamp and is completely visible. + (should-not (eq (field-at-pos (1- (pos-eol))) 'erc-timestamp)) + (should-not (next-single-property-change (pos-bol) 'invisible)))))) + (defun erc-scenarios-match--stamp-both-invisible-fill-static () (should (eq erc-insert-timestamp-function #'erc-insert-timestamp-left-and-right)) -- 2.41.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-5.6-Add-command-to-refill-buffer-with-erc-fill-wrap-.patch >From 2dd2c5c00e5a405f74ee0c7d61b35ba2f1e633e1 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 21 Sep 2023 06:54:27 -0700 Subject: [PATCH 3/3] [5.6] Add command to refill buffer with erc-fill-wrap-mode * lisp/erc/erc-fill.el (erc-fill--wrap-rejigger-last-message): New internal variable. (erc-fill--wrap-rejigger-region, erc-fill-wrap-refill-buffer): New command and helper function. (Bug#60936) --- lisp/erc/erc-fill.el | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el index 6d39bcb19b9..78b29b51cf7 100644 --- a/lisp/erc/erc-fill.el +++ b/lisp/erc/erc-fill.el @@ -563,6 +563,57 @@ erc-fill-wrap `((space :width (- erc-fill--wrap-value ,len)) (space :width erc-fill--wrap-value)))))) +(defvar erc-fill--wrap-rejigger-last-message nil + "Temporary working instance of `erc-fill--wrap-last-msg'.") + +(defun erc-fill--wrap-rejigger-region (start finish on-next) + "Recalculate `line-prefix' from START to FINISH. +After refilling each message, call ON-NEXT with no args. But +stash and restore `erc-fill--wrap-last-msg' before doing so, in +case this module's insert hooks run by way of the process filter." + (goto-char start) + (cl-assert (null erc-fill--wrap-rejigger-last-message)) + (let (erc-fill--wrap-rejigger-last-message) + (while-let + (((< (point) finish)) + (beg (if (get-text-property (point) 'line-prefix) + (point) + (next-single-property-change (point) 'line-prefix))) + (val (get-text-property beg 'line-prefix)) + (end (text-property-not-all beg finish 'line-prefix val))) + ;; If this is a left-side stamp on its own line. + (remove-text-properties beg (1+ end) '(line-prefix nil wrap-prefix nil)) + (save-restriction + (narrow-to-region beg (1+ end)) + (if-let (((eq 'erc-timestamp (field-at-pos beg))) + ((eq 'date-left (get-text-property beg 'erc-stamp-type)))) + (progn + (goto-char (field-end beg)) + (erc-fill--wrap-stamp-insert-prefixed-date)) + (let ((erc-fill--wrap-last-msg erc-fill--wrap-rejigger-last-message)) + (erc-fill-wrap) + (setq erc-fill--wrap-rejigger-last-message + erc-fill--wrap-last-msg)))) + (when on-next + (funcall on-next)) + (goto-char end)))) + +(defun erc-fill-wrap-refill-buffer () + "Recalculate all `fill-wrap' prefixes in the current buffer." + (interactive) + (unless erc-fill-wrap-mode + (user-error "Module `fill-wrap' not active in current buffer.")) + (save-excursion + (with-silent-modifications + (let* ((rep (make-progress-reporter + "Rewrap" 0 (line-number-at-pos erc-insert-marker) 1)) + (seen 0) + (callback (lambda () + (progress-reporter-update rep (cl-incf seen)) + (accept-process-output nil 0.000001)))) + (erc-fill--wrap-rejigger-region (point-min) erc-insert-marker callback) + (progress-reporter-done rep))))) + ;; FIXME use own text property to avoid false positives. (defun erc-fill--wrap-merged-button-p (point) (equal "" (get-text-property point 'display))) -- 2.41.0 --=-=-=--