]> git.eshelyaron.com Git - emacs.git/commitdiff
Reuse command-indicator code for script lines in ERC
authorF. Jason Park <jp@neverwas.me>
Mon, 11 Mar 2024 06:09:59 +0000 (23:09 -0700)
committerEshel Yaron <me@eshelyaron.com>
Sun, 24 Mar 2024 14:22:06 +0000 (15:22 +0100)
* lisp/erc/erc-goodies.el (erc-load-irc-script-lines): Move here from
main file and rework to always use `command-indicator' instead of only
partially, when available.  Also use internal "send-action" and
"send-message" interfaces to defer command-handler output until
command lines have been inserted.
* lisp/erc/erc.el (erc-process-input-line): Redo doc string.
(erc-process-script-line): Fold exceptionally overlong line.
(erc-load-irc-script-lines): Move to erc-goodies.el.  (Bug#67032)

(cherry picked from commit a46789b56af05e4cd31ab90495c9f2a4492a9b19)

lisp/erc/erc-goodies.el
lisp/erc/erc.el

index 883f64d310936aa087520732721c37e43174fdea..fe44c3bdfcbd1c2aeec3f362753e4cf7922c28b3 100644 (file)
@@ -625,6 +625,48 @@ Do nothing if the variable `erc-command-indicator' is nil."
                                 erc--msg-props))))
       (erc--refresh-prompt))))
 
+;;;###autoload
+(defun erc-load-irc-script-lines (lines &optional force noexpand)
+  "Process a list of LINES as prompt input submissions.
+If optional NOEXPAND is non-nil, do not expand script-specific
+substitution sequences via `erc-process-script-line' and instead
+process LINES as literal prompt input.  With FORCE, bypass flood
+protection."
+  ;; The various erc-cmd-CMDs were designed to return non-nil when
+  ;; their command line should be echoed.  But at some point, these
+  ;; handlers began displaying their own output, which naturally
+  ;; appeared *above* the echoed command.  This tries to intercept
+  ;; these insertions, deferring them until the command has returned
+  ;; and its command line has been printed.
+  (cl-assert (eq 'erc-mode major-mode))
+  (let ((args (and erc-script-args
+                   (if (string-match "^ " erc-script-args)
+                       (substring erc-script-args 1)
+                     erc-script-args))))
+    (with-silent-modifications
+      (dolist (line lines)
+        (erc-log (concat "erc-load-script: CMD: " line))
+        (unless (string-match (rx bot (* (syntax whitespace)) eot) line)
+          (unless noexpand
+            (setq line (erc-process-script-line line args)))
+          (let ((erc--current-line-input-split (erc--make-input-split line))
+                calls insertp)
+            (add-function :around (local 'erc--send-message-nested-function)
+                          (lambda (&rest args) (push args calls))
+                          '((name . erc-script-lines-fn) (depth . -80)))
+            (add-function :around (local 'erc--send-action-function)
+                          (lambda (&rest args) (push args calls))
+                          '((name . erc-script-lines-fn) (depth . -80)))
+            (setq insertp
+                  (unwind-protect (erc-process-input-line line force)
+                    (remove-function (local 'erc--send-action-function)
+                                     'erc-script-lines-fn)
+                    (remove-function (local 'erc--send-message-nested-function)
+                                     'erc-script-lines-fn)))
+            (when (and insertp erc-script-echo)
+              (erc--command-indicator-display line)
+              (dolist (call calls)
+                (apply (car call) (cdr call))))))))))
 
 ;;; IRC control character processing.
 (defgroup erc-control-characters nil
index 3cc9bd5422802255dedc460b0a5e3ab42a1f9125..0750463a4e7bdc4bb7f817d525df21b7f4ba3b19 100644 (file)
@@ -4004,17 +4004,19 @@ erc-cmd-FOO, this returns a string /FOO."
       command-name)))
 
 (defun erc-process-input-line (line &optional force no-command)
-  "Translate LINE to an RFC1459 command and send it based.
-Returns non-nil if the command is actually sent to the server, and nil
-otherwise.
-
-If the command in the LINE is not bound as a function `erc-cmd-<COMMAND>',
-it is passed to `erc-cmd-default'.  If LINE is not a command (i.e. doesn't
-start with /<COMMAND>) then it is sent as a message.
-
-An optional FORCE argument forces sending the line when flood
-protection is in effect.  The optional NO-COMMAND argument prohibits
-this function from interpreting the line as a command."
+  "Dispatch a slash-command or chat-input handler from user-input LINE.
+If simplistic validation fails, print an error and return nil.
+Otherwise, defer to an appropriate handler.  For \"slash\" commands,
+like \"/JOIN\", expect a handler, like `erc-cmd-JOIN', to return non-nil
+if LINE is fit for echoing as a command line when executing scripts.
+For normal chat input, expect a handler to return non-nil if a message
+was successfully processed as an outgoing \"PRIVMSG\".  If LINE is a
+slash command, and ERC can't find a corresponding handler of the form
+`erc-cmd-<COMMAND>', pass LINE to `erc-cmd-default', treating it as a
+catch-all handler.  Otherwise, for normal chat input, pass LINE and the
+boolean argument FORCE to `erc-send-input-line-function'.  With a
+non-nil NO-COMMAND, always treat LINE as normal chat input rather than a
+slash command."
   (let ((command-list (erc-extract-command-from-line line)))
     (if (and command-list
              (not no-command))
@@ -8512,7 +8514,8 @@ and so on."
                     ((string-match "^%[Ss]$" esc) server)
                     ((string-match "^%[Nn]$" esc) nick)
                     ((string-match "^%\\(.\\)$" esc) (match-string 1 esc))
-                    (t (erc-log (format "BUG in erc-process-script-line: bad escape sequence: %S\n" esc))
+                    (t (erc-log (format "Bad escape sequence in %s: %S\n"
+                                        'erc-process-script-line esc))
                        (message "BUG IN ERC: esc=%S" esc)
                        "")))
         (setq line tail)
@@ -8531,37 +8534,6 @@ and so on."
                (buffer-string))))
     (erc-load-irc-script-lines (erc-split-multiline-safe str) force)))
 
-(defun erc-load-irc-script-lines (lines &optional force noexpand)
-  "Load IRC script LINES (a list of strings).
-
-If optional NOEXPAND is non-nil, do not expand script-specific
-sequences, process the lines verbatim.  Use this for multiline
-user input."
-  (let* ((cb (current-buffer))
-         (s "")
-         (sp (or (and (bound-and-true-p erc-command-indicator-mode)
-                      (fboundp 'erc-command-indicator)
-                      (erc-command-indicator))
-                 (erc-prompt)))
-         (args (and (boundp 'erc-script-args) erc-script-args)))
-    (if (and args (string-match "^ " args))
-        (setq args (substring args 1)))
-    ;; prepare the prompt string for echo
-    (erc-put-text-property 0 (length sp)
-                           'font-lock-face 'erc-command-indicator-face sp)
-    (while lines
-      (setq s (car lines))
-      (erc-log (concat "erc-load-script: CMD: " s))
-      (unless (string-match "^\\s-*$" s)
-        (let ((line (if noexpand s (erc-process-script-line s args))))
-          (if (and (erc-process-input-line line force)
-                   erc-script-echo)
-              (progn
-                (erc-put-text-property 0 (length line)
-                                       'font-lock-face 'erc-input-face line)
-                (erc-display-line (concat sp line) cb)))))
-      (setq lines (cdr lines)))))
-
 ;; authentication
 
 (defun erc--unfun (maybe-fn)