From ff74bec6e42aa9eede09f9361410f8bd14755027 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 9 Jun 2023 21:00:03 -0700 Subject: [PATCH 3/5] [5.6] Simplify logic for inserting ERC prompt input * lisp/erc/erc.el (erc--current-line-input-split): New variable bound to the current `erc--input-split' object, post review, for the extent of display processing, so that "slash" commands can access it. (erc-cmd-SAY): Defer to `erc--send-message'. (erc--send-message): New implementation. When called internally and the variable `erc--current-line-input-split' is non-nil, treat input as an outgoing message to ensure "send" hooks run and invariants for prompt markers are preserved. For example, this means noncommands, like /SV will have `erc-input-face' applied, which is correct because this message is sent to an actual target on the server. (erc--make-input-split): New function. (erc-send-current-line): Bind `erc--current-line-input-split' when dispatching prompt-input handlers. Use helper `erc--make-input-split'. (erc--run-send-hooks): Honor existing `refoldp' slot from `erc--input-split' object. --- lisp/erc/erc.el | 50 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index a885038411d..4828319727e 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -3659,6 +3659,12 @@ erc--called-as-input-p "Non-nil when a user types a \"/slash\" command. Remains bound until `erc-cmd-SLASH' returns.") +(defvar erc--current-line-input-split nil + "Current `erc--input-split' instance when processing user input. +This is for special cases in which a \"slash\" command needs +details about the input it's handling or needs to detect whether +it's been dispatched by `erc-send-current-line'.") + (defvar-local erc-send-input-line-function #'erc-send-input-line "Function for sending lines lacking a leading \"slash\" command. When prompt input starts with a \"slash\" command, like \"/MSG\", @@ -3795,9 +3801,7 @@ erc-cmd-SAY (if (string-match "^\\s-*$" line) nil (string-match "^ ?\\(.*\\)" line) - (let ((msg (match-string 1 line))) - (erc-display-msg msg) - (erc-process-input-line msg nil t)))) + (erc--send-message (match-string 1 line) nil))) (put 'erc-cmd-SAY 'do-not-parse-args t) (defun erc-cmd-SET (line) @@ -4507,6 +4511,27 @@ erc--send-message ;; FIXME - treat multiline, run hooks, or remove me? t) +;; When running inside insert and send hooks, take more care in +;; dealing with the prompt. +(cl-defmethod erc--send-message + (input-line force &context (erc--current-line-input-split erc--input-split)) + "Process non-command INPUT-LINE almost as if it's normal chat input. +Expect INPUT-LINE to differ from the `string' slot of the calling +context's `erc--current-line-input-split' object because the +latter is likely a slash command invocation whose handler +generated INPUT-LINE. Before inserting INPUT-LINE, split it and +run `erc-send-modify-hook' and `erc-send-post-hook' on each +actual outgoing line. Forgo input validation because this isn't +interactive input, and skip `erc-send-completed-hook' because it +will run just before the outer `erc-send-current-line' call +returns." + (let* ((erc-flood-protect (not force)) + (lines-obj (erc--make-input-split input-line))) + (setf (erc--input-split-refoldp lines-obj) t + (erc--input-split-cmdp lines-obj) nil) + (erc--send-input-lines (erc--run-send-hooks lines-obj))) + t) + (defun erc-cmd-MODE (line) "Change or display the mode value of a channel or user. The first word specifies the target. The rest is the mode string @@ -6880,6 +6905,14 @@ erc--inhibit-slash-cmd-insertion (when (erc--input-split-cmdp state) (setf (erc--input-split-insertp state) nil))) +(defun erc--make-input-split (string) + (make-erc--input-split + :string string + :insertp erc-insert-this + :sendp erc-send-this + :lines (split-string string erc--input-line-delim-regexp) + :cmdp (string-match erc-command-regexp string))) + (defun erc-send-current-line () "Parse current line and send it to IRC." (interactive) @@ -6894,16 +6927,11 @@ erc-send-current-line (expand-abbrev)) (widen) (let* ((str (erc-user-input)) - (state (make-erc--input-split - :string str - :insertp erc-insert-this - :sendp erc-send-this - :lines (split-string - str erc--input-line-delim-regexp) - :cmdp (string-match erc-command-regexp str)))) + (state (erc--make-input-split str))) (run-hook-with-args 'erc--input-review-functions state) (when-let (((not (erc--input-split-abortp state))) (inhibit-read-only t) + (erc--current-line-input-split state) (old-buf (current-buffer))) (let ((erc--msg-prop-overrides `((erc-msg . msg) ,@erc--msg-prop-overrides))) @@ -6969,6 +6997,8 @@ 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) -- 2.41.0