Don't send empty lines for implicit targets in ERC

* erc.el (erc-send-input-line): Previously, any line typed into a
query or channel buffer without an explicit user-command
handler (meaning most lines), would be sent twice because a trailing
newline (linefeed) would be appended. This has been verified by
checking IRCd server logs. IRCds won't return an error upon receiving
an empty message, but they also won't forward them to channel
subscribers and DM pals.

* erc-tests.el: Add test for erc-process-input-line, which also
indirectly tests erc-send-input-line. It also tests the command
lookup and dispatch facility (bug#50008).
This commit is contained in:
F. Jason Park 2021-11-06 03:09:43 +01:00 committed by Lars Ingebrigtsen
parent 82d0550648
commit 4d656ea5ff
2 changed files with 71 additions and 12 deletions

View file

@ -2817,20 +2817,17 @@ present."
(let ((prop-val (erc-get-parsed-vector position)))
(and prop-val (member (erc-response.command prop-val) list))))
(defvar-local erc-send-input-line-function 'erc-send-input-line)
(defvar-local erc-send-input-line-function 'erc-send-input-line
"Function for sending lines lacking a leading user command.
When a line typed into a buffer contains an explicit command, like /msg,
a corresponding handler (here, erc-cmd-MSG) is called. But lines typed
into a channel or query buffer already have an implicit target and
command (PRIVMSG). This function is called on such occasions and also
for special purposes (see erc-dcc.el).")
(defun erc-send-input-line (target line &optional force)
"Send LINE to TARGET.
See also `erc-server-send'."
(setq line (format "PRIVMSG %s :%s"
target
;; If the line is empty, we still want to
;; send it - i.e. an empty pasted line.
(if (string= line "\n")
" \n"
line)))
(erc-server-send line force target))
"Send LINE to TARGET."
(erc-message "PRIVMSG" (concat target " " line) force))
(defun erc-get-arglist (fun)
"Return the argument list of a function without the parens."

View file

@ -228,4 +228,66 @@
(kill-buffer "*erc-protocol*")
(should-not erc-debug-irc-protocol)))
;; The point of this test is to ensure output is handled identically
;; regardless of whether a command handler is summoned.
(ert-deftest erc-process-input-line ()
(let (erc-server-last-sent-time
erc-server-flood-queue
(orig-erc-cmd-MSG (symbol-function 'erc-cmd-MSG))
calls)
(with-temp-buffer
(cl-letf (((symbol-function 'erc-cmd-MSG)
(lambda (line)
(push line calls)
(funcall orig-erc-cmd-MSG line)))
((symbol-function 'erc-server-buffer)
(lambda () (current-buffer)))
((symbol-function 'erc-server-process-alive)
(lambda () t))
((symbol-function 'erc-server-send-queue)
#'ignore)
((symbol-function 'erc-default-target)
(lambda () "" "#chan")))
(ert-info ("Dispatch to user command handler")
(ert-info ("Baseline")
(erc-process-input-line "/msg #chan hi\n")
(should (equal (pop calls) " #chan hi"))
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :hi\r\n" . utf-8))))
(ert-info ("Spaces preserved")
(erc-process-input-line "/msg #chan hi you\n")
(should (equal (pop calls) " #chan hi you"))
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :hi you\r\n" . utf-8))))
(ert-info ("Empty line honored")
(erc-process-input-line "/msg #chan\n")
(should (equal (pop calls) " #chan"))
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :\r\n" . utf-8)))))
(ert-info ("Implicit cmd via `erc-send-input-line-function'")
(ert-info ("Baseline")
(erc-process-input-line "hi")
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :hi\r\n" . utf-8))))
(ert-info ("Spaces preserved")
(erc-process-input-line "hi you")
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :hi you\r\n" . utf-8))))
(ert-info ("Empty line transmitted without injected-space kludge")
(erc-process-input-line "")
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :\r\n" . utf-8))))
(should-not calls))))))
;;; erc-tests.el ends here