>From b58ad0d7c08d0002276f261d508cfca4056cc9ac Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 22 Apr 2022 03:56:25 -0700 Subject: [PATCH 4/4] [SQUASH-ME] Add hook for splitting multiline input in ERC * lisp/erc/erc.el (erc-pre-send-split-functions): Add new hook allowing members to revise individual lines before sending. (erc-discard-trailing-multiline-nulls): Conditionally truncate list of lines to be sent, skipping trailing blanks. (erc-input-split): Add new struct containing split input line. (erc-send-input): Call hook `erc-pre-send-split-functions'. --- lisp/erc/erc.el | 74 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index f3685dd2a7..e2fe5c6476 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1040,7 +1040,7 @@ erc-send-pre-hook :type 'hook) (make-obsolete-variable 'erc-send-pre-hook 'erc-pre-send-functions "27.1") -(defcustom erc-pre-send-functions '(erc-discard-trailing-multiline-nulls) +(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. @@ -1052,7 +1052,26 @@ erc-pre-send-functions `sendp': Whether the string should be sent to the irc server." :group 'erc :type 'hook - :package-version '(ERC . "5.4.1")) ; FIXME increment upon publishing to ELPA + :version "27.1") + +(defcustom erc-pre-send-split-functions '(erc-discard-trailing-multiline-nulls) + "Special hook for modifying individual lines in multiline prompt input. +The functions are called with one argument, an `erc-input-split' struct, +which they can optionally modify. + +The struct has five slots: + + `string': The input string delivered by `erc-pre-send-functions'. + `insertp': Whether the lines should be inserted into the ERC buffer. + `sendp': Whether the lines should be sent to the IRC server. + `lines': A list of lines to be sent, each one a `string'. + `cmdp': Whether to interpret the input as a command, like /ignore. + +The `string' field is effectively read-only. When `cmdp' is non-nil, +all but the first line will be discarded." + :group 'erc + :type 'hook + :package-version '(ERC . "5.4.1")) (defvar erc-insert-this t "Insert the text into the target buffer or not. @@ -5572,8 +5591,13 @@ erc-discard-trailing-multiline-nulls "Ensure last line of `erc-input' STATE's string is non-null. But only when `erc-send-whitespace-lines' is non-nil." (when erc-send-whitespace-lines - (cl-callf (lambda (s) (string-trim-right s "[\r\n]+")) - (erc-input-string state)))) + (when (string-match "[\r\n]+\\'" (erc-input-string state)) + (setf (erc-input-split-lines state) + (split-string (substring (erc-input-string state) + 0 + (match-beginning 0)) + erc--input-line-delim-regexp) + (erc-input-split-cmdp state) nil)))) (defun erc-check-prompt-input-for-multiline-blanks (string) "Return non-nil when multiline prompt input has blank lines." @@ -5664,6 +5688,9 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) +(cl-defstruct (erc-input-split (:include erc-input)) + lines cmdp) + (defun erc-send-input (input &optional skip-ws-chk) "Treat INPUT as typed in by the user. It is assumed that the input and the prompt is already deleted. @@ -5693,26 +5720,27 @@ erc-send-input :insertp erc-insert-this :sendp erc-send-this)) (run-hook-with-args 'erc-pre-send-functions state) + (setq state (make-erc-input-split + :string (erc-input-string state) + :insertp (erc-input-insertp state) + :sendp (erc-input-sendp state) + :lines (split-string (erc-input-string state) + erc--input-line-delim-regexp) + :cmdp (string-match erc-command-regexp + (erc-input-string state)))) + (run-hook-with-args 'erc-pre-send-split-functions state) (when (and (erc-input-sendp state) - erc-send-this) - (let ((string (erc-input-string state))) - (if (or (if (>= emacs-major-version 28) - (string-search "\n" string) - (string-match "\n" string)) - (not (string-match erc-command-regexp string))) - (mapc - (lambda (line) - (mapc - (lambda (line) - ;; Insert what has to be inserted for this. - (when (erc-input-insertp state) - (erc-display-msg line)) - (erc-process-input-line (concat line "\n") - (null erc-flood-protect) t)) - (or (and erc-flood-protect (erc-split-line line)) - (list line)))) - (split-string string erc--input-line-delim-regexp)) - (erc-process-input-line (concat string "\n") t nil)) + erc-send-this) + (let ((lines (erc-input-split-lines state))) + (if (and (erc-input-split-cmdp state) (not (cdr lines))) + (erc-process-input-line (concat (car lines) "\n") t nil) + (dolist (line lines) + (dolist (line (or (and erc-flood-protect (erc-split-line line)) + (list line))) + (when (erc-input-insertp state) + (erc-display-msg line)) + (erc-process-input-line (concat line "\n") + (null erc-flood-protect) t)))) t))))) ;; (defun erc-display-command (line) -- 2.35.1