1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-03 08:30:09 +00:00

Add replacement-text field to erc-input struct

* etc/ERC-NEWS: Promote `refoldp' slot from simulated to real.
Mention new `substxt' slot of `erc-input' struct.
* lisp/erc/erc-common.el (erc-input): Add `substxt' and `refoldp'
slots.
(erc--input-split): Move `refoldp' to "superclass".
* lisp/erc/erc-goodies.el (erc--command-indicator-permit-insertion):
Use `substxt' field instead of overloading `insertp'.
(erc--command-indicator-display): Accept extra lines for
compatibility.
* lisp/erc/erc.el (erc-pre-send-functions): Revise doc.
(erc--input-ensure-hook-context, erc-input-refoldp): Remove unused
functions, originally meant to be new in ERC 5.6.
(erc--run-send-hooks): Copy data from additional fields of `erc-input'
object to `erc--input-split' workspace object.
(erc--send-input-lines): Handle `substxt' field of `erc-input' object
when it's non-nil.  (Bug#68265)
This commit is contained in:
F. Jason Park 2024-01-01 06:37:25 -08:00
parent aae131b8dd
commit d6be068ffe
4 changed files with 74 additions and 55 deletions

View File

@ -581,9 +581,17 @@ 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 "phony" 'refoldp' slot that's
only accessible from 'erc-pre-send-functions'. See doc string for
details.
shared among hook members has gained a 'refoldp' slot. See doc string
for details.
*** More flexibility in sending and displaying prompt input.
The abnormal hook 'erc-pre-send-functions' previously married outgoing
message text to its inserted representation in an ERC target buffer.
Going forward, users can populate the new slot 'substxt' with
alternate text to insert in place of the 'string' slot's contents,
which ERC still sends to the server. This dichotomy lets users
completely avoid the often fiddly 'erc-send-modify-hook' and friends
for use cases like language translation and subprotocol encoding.
*** ERC's prompt survives the insertion of user input and messages.
Previously, ERC's prompt and its input marker disappeared while

View File

@ -50,7 +50,23 @@
(declare-function widget-type "wid-edit" (widget))
(cl-defstruct erc-input
string insertp sendp)
"Object shared among members of `erc-pre-send-functions'.
Any use outside of the hook is not supported."
( string "" :type string
:documentation "String to send and, without `substxt', insert.
ERC treats separate lines as separate messages.")
( insertp nil :type boolean
:documentation "Whether to insert outgoing message.
When nil, ERC still sends `string'.")
( sendp nil :type boolean
:documentation "Whether to send and (for compat reasons) insert.
To insert without sending, define a (slash) command.")
( substxt nil :type (or function string null)
:documentation "Alternate string to insert without splitting.
The function form is for internal use.")
( refoldp nil :type boolean
:documentation "Whether to resplit a possibly overlong `string'.
ERC only refolds `string', never `substxt'."))
(cl-defstruct (erc--input-split (:include erc-input
(string "" :read-only t)
@ -58,7 +74,6 @@
(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))

View File

@ -583,15 +583,18 @@ Do nothing if the variable `erc-command-indicator' is nil."
"Insert `erc-input' STATE's message if it's an echoed command."
(cl-assert erc-command-indicator-mode)
(when (erc--input-split-cmdp state)
(setf (erc--input-split-insertp state) #'erc--command-indicator-display)
(setf (erc--input-split-insertp state) t
(erc--input-split-substxt state) #'erc--command-indicator-display)
(erc-send-distinguish-noncommands state)))
;; This function used to be called `erc-display-command'. It was
;; neutered in ERC 5.3.x (Emacs 24.5), commented out in 5.4, removed
;; in 5.5, and restored in 5.6.
(defun erc--command-indicator-display (line)
(defun erc--command-indicator-display (line &rest rest)
"Insert command LINE as echoed input resembling that of REPLs and shells."
(when erc-insert-this
(when rest
(setq line (string-join (cons line rest) "\n")))
(save-excursion
(erc--assert-input-bounds)
(let ((insert-position (marker-position (goto-char erc-insert-marker)))

View File

@ -1235,30 +1235,30 @@ anyway."
(make-obsolete-variable 'erc-send-pre-hook 'erc-pre-send-functions "27.1")
(defcustom erc-pre-send-functions nil
"Special hook run to possibly alter the string that is sent.
The functions are called with one argument, an `erc-input' struct,
and should alter that struct.
"Special hook to possibly alter the string to send and insert.
ERC calls the member functions with one argument, an `erc-input'
struct instance to modify as needed.
The struct has three slots:
The struct has five slots:
`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.
`string': String to send, originally from prompt input.
`insertp': Whether a string should be inserted in the buffer.
`sendp': Whether `string' should be sent to the IRC server.
`substxt': String to display (but not send) instead of `string'.
`refoldp': Whether to re-split `string' 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 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")
the value of `string' comes \"pre-split\" according to the option
`erc-split-line-length'. If you need ERC to refill the entire
payload before sending it, set the `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 and possibly also specify replacement text to
display via the `substxt' slot."
:package-version '(ERC . "5.3")
:group 'erc-hooks
:type 'hook)
(define-obsolete-variable-alias 'erc--pre-send-split-functions
'erc--input-review-functions "30.1")
@ -7899,22 +7899,6 @@ When all lines are empty, remove all but the first."
(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
@ -7932,12 +7916,17 @@ queue. Expect LINES-OBJ to be an `erc--input-split' object."
(state (progn
;; This may change `str' and `erc-*-this'.
(run-hook-with-args 'erc-send-pre-hook str)
(make-erc-input :string str
:insertp erc-insert-this
:sendp erc-send-this))))
(make-erc-input
:string str
:insertp erc-insert-this
:sendp erc-send-this
:substxt (erc--input-split-substxt lines-obj)
:refoldp (erc--input-split-refoldp lines-obj)))))
(run-hook-with-args 'erc-pre-send-functions state)
(setf (erc--input-split-sendp lines-obj) (erc-input-sendp state)
(erc--input-split-insertp lines-obj) (erc-input-insertp state)
(erc--input-split-substxt lines-obj) (erc-input-substxt state)
(erc--input-split-refoldp lines-obj) (erc-input-refoldp state)
;; See note in test of same name re trailing newlines.
(erc--input-split-lines lines-obj)
(let ((lines (split-string (erc-input-string state)
@ -7955,15 +7944,19 @@ queue. Expect LINES-OBJ to be an `erc--input-split' object."
(defun erc--send-input-lines (lines-obj)
"Send lines in `erc--input-split-lines' object LINES-OBJ."
(when (erc--input-split-sendp lines-obj)
(dolist (line (erc--input-split-lines lines-obj))
(when (erc--input-split-insertp lines-obj)
(if (eq (erc--input-split-insertp lines-obj)
'erc--command-indicator-display)
(funcall (erc--input-split-insertp lines-obj) line)
(erc-display-msg line)))
(erc-process-input-line (concat line "\n")
(null erc-flood-protect)
(not (erc--input-split-cmdp lines-obj))))))
(let ((insertp (erc--input-split-insertp lines-obj))
(substxt (erc--input-split-substxt lines-obj)))
(when (and insertp substxt)
(setq insertp nil)
(if (functionp substxt)
(apply substxt (erc--input-split-lines lines-obj))
(erc-display-msg substxt)))
(dolist (line (erc--input-split-lines lines-obj))
(when insertp
(erc-display-msg line))
(erc-process-input-line (concat line "\n")
(null erc-flood-protect)
(not (erc--input-split-cmdp lines-obj)))))))
(defun erc-send-input (input &optional skip-ws-chk)
"Treat INPUT as typed in by the user.