summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorF. Jason Park <jp@neverwas.me>2024-03-10 23:09:59 -0700
committerF. Jason Park <jp@neverwas.me>2024-03-23 15:10:32 -0700
commita46789b56af05e4cd31ab90495c9f2a4492a9b19 (patch)
tree513f82606d677cb7e17eb945372738e5c32033b7
parentb9bd78f78d62383f2ff84ceecf8e490193594f17 (diff)
downloademacs-a46789b56af05e4cd31ab90495c9f2a4492a9b19.tar.gz
Reuse command-indicator code for script lines in ERC
* 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)
-rw-r--r--lisp/erc/erc-goodies.el42
-rw-r--r--lisp/erc/erc.el58
2 files changed, 57 insertions, 43 deletions
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 883f64d3109..fe44c3bdfcb 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -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
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 3cc9bd54228..0750463a4e7 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -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)