From 6d6bfee8180c9ba37545c18aed46ddc8dc43732f Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 1 Dec 2023 13:54:12 -0800 Subject: [PATCH 06/11] [5.6] Make erc-input's refoldp slot conditionally available * etc/ERC-NEWS: Fix entry regarding `erc-input-refoldp'. * lisp/erc/erc-common.el (erc-input): Remove `refoldp' slot to reduce churn in the unlikely event that third-party code subclasses `erc-input' for use outside of `erc-pre-send-functions'. (erc--input-split) Add `refoldp' slot here instead. * lisp/erc/erc.el (erc-pre-send-functions): Amend doc string to stress that `refoldp' is not a real slot. (erc--input-ensure-hook-context, erc-input-refoldp): New function, an impostor accessor for the nonexistent `refoldp' slot of `erc-input', and a helper function for asserting a valid context at runtime. (erc--run-send-hooks): Don't copy over `refoldp' from the `erc--input-lines' object to the working `erc-insert' object. Check the insertion context's `erc--input-split' object instead of the hook's `erc-insert' object when deciding whether to resplit. * test/lisp/erc/erc-tests.el: Adjust test environment to satisfy assertion. (Bug#62947) --- etc/ERC-NEWS | 5 +++-- lisp/erc/erc-common.el | 3 ++- lisp/erc/erc.el | 31 +++++++++++++++++++++++++------ test/lisp/erc/erc-tests.el | 7 ++++--- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index f6a9d934e80..540d9e98751 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -460,8 +460,9 @@ ERC now adjusts input lines to fall within allowed length limits before showing hook members the result. For compatibility, third-party code can request that the final input be adjusted again prior to being sent. To facilitate this, the 'erc-input' object -shared among hook members has gained a new 'refoldp' slot, making this -a breaking change, if only in theory. See doc string for details. +shared among hook members has gained a "phony" 'refoldp' slot that's +only accessible from 'erc-pre-send-functions'. See doc string for +details. *** ERC's prompt survives the insertion of user input and messages. Previously, ERC's prompt and its input marker disappeared while diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index e9e494720e5..cb820c812b3 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -49,7 +49,7 @@ erc-session-server (declare-function widget-type "wid-edit" (widget)) (cl-defstruct erc-input - string insertp sendp refoldp) + string insertp sendp) (cl-defstruct (erc--input-split (:include erc-input (string :read-only) @@ -57,6 +57,7 @@ erc-input (sendp (with-suppressed-warnings ((obsolete erc-send-this)) erc-send-this)))) + (refoldp nil :type boolean) (lines nil :type (list-of string)) (abortp nil :type (list-of symbol)) (cmdp nil :type boolean)) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 9084b7ee042..bb05f17bee6 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1197,13 +1197,18 @@ erc-pre-send-functions `string': The current input string. `insertp': Whether the string should be inserted into the erc buffer. `sendp': Whether the string should be sent to the irc server. + +And one \"phony\" slot only accessible by hook members at runtime: + `refoldp': Whether the string should be re-split per protocol limits. This hook runs after protocol line splitting has taken place, so the value of `string' is originally \"pre-filled\". If you need -ERC to refill the entire payload before sending it, set the -`refoldp' slot to a non-nil value. Preformatted text and encoded -subprotocols should probably be handled manually." +ERC to refill the entire payload before sending it, set the phony +`refoldp' slot to a non-nil value. Note that this refilling is +only a convenience, and modules with special needs, such as +preserving \"preformatted\" text or encoding for subprotocol +\"tunneling\", should handle splitting manually." :group 'erc :type 'hook :version "27.1") @@ -7424,6 +7429,22 @@ erc--split-lines (setf (erc--input-split-lines state) (mapcan #'erc--split-line (erc--input-split-lines state))))) +(defun erc--input-ensure-hook-context () + (unless (erc--input-split-p erc--current-line-input-split) + (error "Invoked outside of `erc-pre-send-functions'"))) + +(defun erc-input-refoldp (_) + "Impersonate accessor for phony `erc-input' `refoldp' slot. +This function only works inside `erc-pre-send-functions' members." + (declare (gv-setter (lambda (v) + `(progn + (erc--input-ensure-hook-context) + (setf (erc--input-split-refoldp + erc--current-line-input-split) + ,v))))) + (erc--input-ensure-hook-context) + (erc--input-split-refoldp erc--current-line-input-split)) + (defun erc--run-send-hooks (lines-obj) "Run send-related hooks that operate on the entire prompt input. Sequester some of the back and forth involved in honoring old @@ -7443,8 +7464,6 @@ erc--run-send-hooks (run-hook-with-args 'erc-send-pre-hook str) (make-erc-input :string str :insertp erc-insert-this - :refoldp (erc--input-split-refoldp - lines-obj) :sendp erc-send-this)))) (run-hook-with-args 'erc-pre-send-functions state) (setf (erc--input-split-sendp lines-obj) (erc-input-sendp state) @@ -7456,7 +7475,7 @@ erc--run-send-hooks (if erc--allow-empty-outgoing-lines-p lines (cl-nsubst " " "" lines :test #'equal)))) - (when (erc-input-refoldp state) + (when (erc--input-split-refoldp lines-obj) (erc--split-lines lines-obj))))) (when (and (erc--input-split-cmdp lines-obj) (cdr (erc--input-split-lines lines-obj))) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 2c70f100c3f..28c1e403e41 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -2256,10 +2256,11 @@ erc--run-send-hooks erc-pre-send-functions (lambda (o) (setf (erc-input-string o) "foo bar baz" (erc-input-refoldp o) t))) - (let ((erc-split-line-length 8)) + (let* ((split (make-erc--input-split :string "foo" :lines '("foo"))) + (erc--current-line-input-split split) + (erc-split-line-length 8)) (should - (pcase (erc--run-send-hooks (make-erc--input-split - :string "foo" :lines '("foo"))) + (pcase (erc--run-send-hooks split) ((cl-struct erc--input-split (string "foo") (sendp 't) (insertp 't) (lines '("foo bar " "baz")) (cmdp 'nil)) -- 2.42.0