[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 3a5a6fce957 10/14: Redo line splitting for outgoing messages in E
From: |
F. Jason Park |
Subject: |
master 3a5a6fce957 10/14: Redo line splitting for outgoing messages in ERC |
Date: |
Fri, 5 May 2023 20:30:51 -0400 (EDT) |
branch: master
commit 3a5a6fce957468be5ef0a8ac76fec8507c3e4e99
Author: F. Jason Park <jp@neverwas.me>
Commit: F. Jason Park <jp@neverwas.me>
Redo line splitting for outgoing messages in ERC
* lisp/erc/erc-backend.el (erc--reject-unbreakable-lines): New
variable, an escape hatch for somewhat regaining pre-5.6
line-splitting behavior.
(erc--split-line): New utility function that doesn't rely on
column-oriented filling.
* lisp/erc/erc.el (erc--pre-send-split-functions): Append
`erc--split-lines' to value.
(erc--split-lines): New function to re-split current selection of
lines.
(erc-send-input): Hard-code line preparation instead of calling
`erc--pre-send-split-functions', in order to bake in traditional
behavior before move to "pre-splitting".
* test/lisp/erc/erc-scenarios-base-split-line.el: New file.
* test/lisp/erc/erc-tests.el (erc--split-line): New test.
(erc-send-current-line): Don't expect a flood argument when
interpreting a command because it's not passed along to the command's
handler. This was previously misleading because it assigned undue
significance to something that had no bearing on the fate of a
command.
* test/lisp/erc/resources/base/flood/ascii.eld: New file.
* test/lisp/erc/resources/base/flood/koi8-r.eld: New file.
* test/lisp/erc/resources/base/flood/utf-8.eld: New file.
* test/lisp/erc/resources/erc-d/erc-d.el: Don't decode input.
(Bug#62947)
---
lisp/erc/erc-backend.el | 41 +++++
lisp/erc/erc.el | 41 +++--
test/lisp/erc/erc-scenarios-base-split-line.el | 202 +++++++++++++++++++++++++
test/lisp/erc/erc-tests.el | 50 +++++-
test/lisp/erc/resources/base/flood/ascii.eld | 49 ++++++
test/lisp/erc/resources/base/flood/koi8-r.eld | 47 ++++++
test/lisp/erc/resources/base/flood/utf-8.eld | 54 +++++++
test/lisp/erc/resources/erc-d/erc-d.el | 2 +-
8 files changed, 467 insertions(+), 19 deletions(-)
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 0c970a9d586..bc8e603e10a 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -572,6 +572,47 @@ If this is set to nil, never try to reconnect."
;;;; Helper functions
+(defvar erc--reject-unbreakable-lines nil
+ "Signal an error when a line exceeds `erc-split-line-length'.
+Sending such lines and hoping for the best is no longer supported
+in ERC 5.6. This internal var exists as a possibly temporary
+escape hatch for inhibiting their transmission.")
+
+(defun erc--split-line (longline)
+ (let* ((coding (erc-coding-system-for-target nil))
+ (original-window-buf (window-buffer (selected-window)))
+ out)
+ (when (consp coding)
+ (setq coding (car coding)))
+ (setq coding (coding-system-change-eol-conversion coding 'unix))
+ (unwind-protect
+ (with-temp-buffer
+ (set-window-buffer (selected-window) (current-buffer))
+ (insert longline)
+ (goto-char (point-min))
+ (while (not (eobp))
+ (let ((upper (filepos-to-bufferpos erc-split-line-length
+ 'exact coding)))
+ (goto-char (or upper (point-max)))
+ (unless (eobp)
+ (skip-chars-backward "^ \t"))
+ (when (bobp)
+ (when erc--reject-unbreakable-lines
+ (user-error
+ (substitute-command-keys
+ (concat "Unbreakable line encountered "
+ "(Recover input with \\[erc-previous-command])"))))
+ (goto-char upper))
+ (when-let ((cmp (find-composition (point) (1+ (point)))))
+ (if (= (car cmp) (point-min))
+ (goto-char (nth 1 cmp))
+ (goto-char (car cmp)))))
+ (cl-assert (/= (point-min) (point)))
+ (push (buffer-substring-no-properties (point-min) (point)) out)
+ (delete-region (point-min) (point)))
+ (or (nreverse out) (list "")))
+ (set-window-buffer (selected-window) original-window-buf))))
+
;; From Circe
(defun erc-split-line (longline)
"Return a list of lines which are not too long for IRC.
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 8552023804a..bc2285a5560 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -909,6 +909,9 @@ Flooding is sending too much information to the server in
too
short of an interval, which may cause the server to terminate the
connection.
+Note that older code conflated rate limiting and line splitting.
+Starting in ERC 5.6, this option no longer influences the latter.
+
See `erc-server-flood-margin' for other flood-related parameters.")
;; Script parameters
@@ -1103,7 +1106,8 @@ The struct has three slots:
;; remove this hook and the struct completely. IOW, if you need this,
;; please say so.
-(defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls)
+(defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls
+ erc--split-lines)
"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.
@@ -6211,6 +6215,14 @@ an `erc--input-split' object."
(setq reversed (cdr reversed)))
(setf (erc--input-split-lines state) (nreverse reversed)))))
+(defun erc--split-lines (state)
+ "Partition non-command input into lines of protocol-compliant length."
+ ;; Prior to ERC 5.6, line splitting used to be predicated on
+ ;; `erc-flood-protect' being non-nil.
+ (unless (erc--input-split-cmdp state)
+ (setf (erc--input-split-lines state)
+ (mapcan #'erc--split-line (erc--input-split-lines state)))))
+
(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.
@@ -6241,23 +6253,22 @@ Return non-nil only if we actually send anything."
: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 ((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)
+ (if-let* ((first (split-string (erc-input-string state)
+ erc--input-line-delim-regexp))
+ (split (mapcan #'erc--split-line first))
+ (lines (nreverse (seq-drop-while #'string-empty-p
+ (nreverse split))))
+ ((string-match erc-command-regexp (car lines))))
+ (progn
+ ;; Asking users what to do here might make more sense.
+ (cl-assert (not (cdr lines)))
+ ;; The `force' arg (here t) is ignored for command lines.
+ (erc-process-input-line (concat (car lines) "\n") t nil))
+ (progn ; temporarily preserve indentation
(dolist (line lines)
- (dolist (line (or (and erc-flood-protect (erc-split-line line))
- (list line)))
+ (progn ; temporarily preserve indentation
(when (erc-input-insertp state)
(erc-display-msg line))
(erc-process-input-line (concat line "\n")
diff --git a/test/lisp/erc/erc-scenarios-base-split-line.el
b/test/lisp/erc/erc-scenarios-base-split-line.el
new file mode 100644
index 00000000000..f6d888c1f28
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-split-line.el
@@ -0,0 +1,202 @@
+;;; erc-scenarios-base-split-line.el --- ERC line splitting -*-
lexical-binding: t -*-
+
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-split-line--koi8-r ()
+ :tags '(:expensive-test)
+ (should (equal erc-split-line-length 440))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/flood")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'koi8-r))
+ (erc-encoding-coding-alist '(("#koi8" . cyrillic-koi8)))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to server")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 10 "debug mode")
+ (erc-cmd-JOIN "#koi8")))
+
+ (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#koi8"))
+ (funcall expect 10 "короче теперь")
+ (ert-info ("Message well within `erc-split-line-length'")
+ (erc-scenarios-common-say
+ (concat
+ "короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"))
+ (funcall expect 1 "<tester>")
+ (funcall expect -0.1 "<tester>"))
+
+ (ert-info ("Message over `erc-split-line-length'")
+ (erc-scenarios-common-say
+ (concat
+ "короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " будет разрыв строки непонятно где"))
+ (funcall expect 1 "<tester>")
+ (funcall expect 1 "<tester> разрыв")))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT "")
+ (funcall expect 10 "finished"))))
+
+(ert-deftest erc-scenarios-base-split-line--ascii ()
+ :tags '(:expensive-test)
+ (should (equal erc-split-line-length 440))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/flood")
+ (msg-432 (string-join (make-list 18 "twenty-three characters") " "))
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'ascii))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to server")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 10 "debug mode")
+ (erc-cmd-JOIN "#ascii")))
+
+ (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#ascii"))
+ (ert-info ("Message with spaces fits exactly")
+ (funcall expect 10 "Welcome")
+ (should (= (length (concat msg-432 " 12345678")) 440))
+ (erc-scenarios-common-say (concat msg-432 " 12345678"))
+ (funcall expect 1 "<tester>")
+ ;; Sent in a single go, hence no second <speaker>.
+ (funcall expect -0.1 "<tester>")
+ (funcall expect 0.1 "12345678"))
+
+ (ert-info ("Message with spaces too long.")
+ (erc-scenarios-common-say (concat msg-432 " 123456789"))
+ (funcall expect 1 "<tester>")
+ ;; Sent in two passes, split at last word.
+ (funcall expect 0.1 "<tester> 123456789"))
+
+ (ert-info ("Message sans spaces fits exactly")
+ (erc-scenarios-common-say (make-string 440 ?x))
+ (funcall expect 1 "<tester>")
+ ;; Sent in a single go, hence no second <speaker>.
+ (funcall expect -0.1 "<tester>"))
+
+ (ert-info ("Message sans spaces too long.")
+ (erc-scenarios-common-say (concat (make-string 440 ?y) "z"))
+ (funcall expect 1 "<tester>")
+ ;; Sent in two passes, split at last word.
+ (funcall expect 0.1 "<tester> z"))
+
+ (ert-info ("Rejected when escape-hatch set")
+ (let ((erc--reject-unbreakable-lines t))
+ (should-error
+ (erc-scenarios-common-say
+ (concat
+ "https://mail.example.org/verify?token="
+ (string-join (make-list 18 "twenty-three_characters") "_")))))))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT "")
+ (funcall expect 10 "finished"))))
+
+(ert-deftest erc-scenarios-base-split-line--utf-8 ()
+ :tags '(:expensive-test)
+ (unless (> emacs-major-version 27)
+ (ert-skip "No emojis in Emacs 27"))
+
+ (should (equal erc-split-line-length 440))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/flood")
+ (msg-432 (string-join (make-list 18 "twenty-three characters") " "))
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'utf-8))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to server")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 10 "debug mode")
+ (erc-cmd-JOIN "#utf-8")))
+
+ (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#utf-8"))
+ (funcall expect 10 "Welcome")
+
+ (ert-info ("Message with spaces over `erc-split-line-length'")
+ (erc-scenarios-common-say
+ (concat
+ "короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " короче теперь если по русски написать все четко или все равно"
+ " будет разрыв строки непонятно где"
+ " будет разрыв строки непонятно где"))
+ (funcall expect 1 "<tester> короче")
+ (funcall expect 1 "<tester> все")
+ (funcall expect 1 "<tester> разрыв")
+ (funcall expect 1 "Entirely honour"))
+
+ (ert-info ("Message sans spaces over `erc-split-line-length'")
+ (erc-scenarios-common-say
+ (concat "話說天下大勢,分久必合,合久必分:周末七國分爭,并入於秦。"
+ "及秦滅之後,楚、漢分爭,又并入於漢。漢朝自高祖斬白蛇而起義,"
+ "一統天下。後來光武中興,傳至獻帝,遂分為三國。推其致亂之由,"
+ "殆始於桓、靈二帝。桓帝禁錮善類,崇信宦官。及桓帝崩,靈帝即位,"
+ "大將軍竇武、太傅陳蕃,共相輔佐。時有宦官曹節等弄權,竇武、陳蕃謀誅之,"
+ "作事不密,反為所害。中涓自此愈橫"))
+ (funcall expect 1 "<tester>")
+ ;; Sent in two passes, split at last word.
+ (funcall expect 0.1 "<tester> 竇武")
+ (funcall expect 1 "this prey out"))
+
+ ;; Combining emojis are respected.
+ (ert-info ("Message sans spaces over small `erc-split-line-length'")
+ (let ((erc-split-line-length 100))
+ (erc-scenarios-common-say
+ "будет разрыв строки непонятно где🏁🚩🎌🏴🏳️🏳️🌈🏳️⚧️🏴☠️"))
+ (funcall expect 1 "<tester>")
+ (funcall expect 1 "<tester> 🏳️🌈")))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT "")
+ (funcall expect 10 "finished"))))
+
+;;; erc-scenarios-base-split-line.el ends here
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 4725d289e5b..b6702617aeb 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1044,6 +1044,48 @@
(kill-buffer "*erc-protocol*")
(should-not erc-debug-irc-protocol)))
+(ert-deftest erc--split-line ()
+ (let ((erc-default-recipients '("#chan"))
+ (erc-split-line-length 10))
+ (should (equal (erc--split-line "") '("")))
+ (should (equal (erc--split-line "0123456789") '("0123456789")))
+ (should (equal (erc--split-line "0123456789a") '("0123456789" "a")))
+
+ (should (equal (erc--split-line "0123456789 ") '("0123456789" " ")))
+ (should (equal (erc--split-line "01234567 89") '("01234567 " "89")))
+ (should (equal (erc--split-line "0123456 789") '("0123456 " "789")))
+ (should (equal (erc--split-line "0 123456789") '("0 " "123456789")))
+ (should (equal (erc--split-line " 0123456789") '(" " "0123456789")))
+ (should (equal (erc--split-line "012345678 9a") '("012345678 " "9a")))
+ (should (equal (erc--split-line "0123456789 a") '("0123456789" " a")))
+
+ ;; UTF-8 vs. KOI-8
+ (should (= 10 (string-bytes "Русск"))) ; utf-8
+ (should (equal (erc--split-line "Русск") '("Русск")))
+ (should (equal (erc--split-line "РусскийТекст") '("Русск" "ийТек" "ст")))
+ (should (equal (erc--split-line "Русский Текст") '("Русск" "ий " "Текст")))
+ (let ((erc-encoding-coding-alist '(("#chan" . cyrillic-koi8))))
+ (should (equal (erc--split-line "Русск") '("Русск")))
+ (should (equal (erc--split-line "РусскийТекст") '("РусскийТек" "ст")))
+ (should (equal (erc--split-line "Русский Текст") '("Русский " "Текст"))))
+
+ ;; UTF-8 vs. Latin 1
+ (should (= 17 (string-bytes "Hyvää päivää")))
+ (should (equal (erc--split-line "Hyvää päivää") '("Hyvää " "päivää")))
+ (should (equal (erc--split-line "HyvääPäivää") '("HyvääPä" "ivää")))
+ (let ((erc-encoding-coding-alist '(("#chan" . latin-1))))
+ (should (equal (erc--split-line "Hyvää päivää") '("Hyvää " "päivää")))
+ (should (equal (erc--split-line "HyvääPäivää") '("HyvääPäivä" "ä"))))
+
+ ;; Combining characters
+ (should (= 10 (string-bytes "Åström")))
+ (should (equal (erc--split-line "_Åström") '("_Åströ" "m")))
+ (should (equal (erc--split-line "__Åström") '("__Åstr" "öm")))
+ (should (equal (erc--split-line "___Åström") '("___Åstr" "öm")))
+ (when (> emacs-major-version 27)
+ (should (equal (erc--split-line "🏁🚩🎌🏴🏳️🏳️🌈🏳️⚧️🏴☠️")
+ '("🏁🚩" "🎌🏴" "🏳️" "🏳️🌈" "🏳️⚧️" "🏴☠️"))))))
+
(ert-deftest erc--input-line-delim-regexp ()
(let ((p erc--input-line-delim-regexp))
;; none
@@ -1181,8 +1223,9 @@
(ert-info ("Input cleared")
(erc-bol)
(should (eq (point) (point-max))))
- ;; Commands are forced (no flood protection)
- (should (equal (funcall next) '("/msg #chan hi\n" t nil))))
+ ;; The `force' argument is irrelevant here because it can't
+ ;; influence dispatched handlers, such as `erc-cmd-MSG'.
+ (should (pcase (funcall next) (`("/msg #chan hi\n" ,_ nil) t))))
(ert-info ("Simple non-command")
(insert "hi")
@@ -1190,7 +1233,8 @@
(should (eq (point) (point-max)))
(should (save-excursion (forward-line -1)
(search-forward "<tester> hi")))
- ;; Non-ommands are forced only when `erc-flood-protect' is nil
+ ;; Non-commands are forced only when `erc-flood-protect' is
+ ;; nil, which conflates two orthogonal concerns.
(should (equal (funcall next) '("hi\n" nil t))))
(should (consp erc-last-input-time)))))
diff --git a/test/lisp/erc/resources/base/flood/ascii.eld
b/test/lisp/erc/resources/base/flood/ascii.eld
new file mode 100644
index 00000000000..a3d127326c3
--- /dev/null
+++ b/test/lisp/erc/resources/base/flood/ascii.eld
@@ -0,0 +1,49 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running
version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Sun, 12 Mar 2023
02:30:29 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios
CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=#
CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by
this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4
MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+
TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by
this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1
server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.foonet.org 375 tester :- irc.foonet.org Message of the day - ")
+ (0.00 ":irc.foonet.org 372 tester :- This is the default Ergo MOTD.")
+ (0.01 ":irc.foonet.org 372 tester :- ")
+ (0.02 ":irc.foonet.org 372 tester :- For more information on using these, see
MOTDFORMATTING.md")
+ (0.00 ":irc.foonet.org 376 tester :End of MOTD command"))
+
+((mode-tester 10 "MODE tester +i")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is
logging all user I/O. If you do not wish for everything you send to be readable
by the server owner(s), please disconnect.")
+ (0.05 ":irc.foonet.org 221 tester +i"))
+
+((join-spam 10 "JOIN #ascii")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #ascii")
+ (0 ":irc.foonet.org 353 tester = #ascii :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #ascii :End of NAMES list"))
+
+((mode-spam 10 "MODE #ascii")
+ (0 ":irc.foonet.org 324 tester #ascii +nt")
+ (0 ":irc.foonet.org 329 tester #ascii 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #ascii :tester, welcome!")
+ (0.0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #ascii :tester, welcome!"))
+
+((privmsg 10 "PRIVMSG #ascii :twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters 12345678"))
+((privmsg 10 "PRIVMSG #ascii :twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters twenty-three characters twenty-three characters
twenty-three characters "))
+((privmsg 10 "PRIVMSG #ascii :123456789"))
+((privmsg 10 "PRIVMSG #ascii
:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"))
+((privmsg 10 "PRIVMSG #ascii
:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"))
+((privmsg 10 "PRIVMSG #ascii :z"))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.07 ":tester!~u@h3f95zveyc38a.irc QUIT :Quit: \2ERC\2 5.5 (IRC client for
GNU Emacs 30.0.50)")
+ (0.01 "ERROR :Quit: \2ERC\2 5.5 (IRC client for GNU Emacs 30.0.50)"))
diff --git a/test/lisp/erc/resources/base/flood/koi8-r.eld
b/test/lisp/erc/resources/base/flood/koi8-r.eld
new file mode 100644
index 00000000000..0f10717fc2c
--- /dev/null
+++ b/test/lisp/erc/resources/base/flood/koi8-r.eld
@@ -0,0 +1,47 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running
version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Sun, 12 Mar 2023
02:30:29 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios
CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=#
CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by
this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4
MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+
TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by
this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1
server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.foonet.org 375 tester :- irc.foonet.org Message of the day - ")
+ (0.00 ":irc.foonet.org 372 tester :- This is the default Ergo MOTD.")
+ (0.01 ":irc.foonet.org 372 tester :- ")
+ (0.02 ":irc.foonet.org 372 tester :- For more information on using these, see
MOTDFORMATTING.md")
+ (0.00 ":irc.foonet.org 376 tester :End of MOTD command"))
+
+((mode-tester 10 "MODE tester +i")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is
logging all user I/O. If you do not wish for everything you send to be readable
by the server owner(s), please disconnect.")
+ (0.05 ":irc.foonet.org 221 tester +i"))
+
+((join-chan 6 "JOIN #koi8")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #koi8")
+ (0 ":irc.foonet.org 353 tester = #koi8 :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #koi8 :End of NAMES list"))
+
+((mode-chan 8 "MODE #koi8")
+ (0 ":irc.foonet.org 324 tester #koi8 +nt")
+ (0 ":irc.foonet.org 329 tester #koi8 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #koi8 :tester, welcome!")
+ (0.0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #koi8 :tester, welcome!")
+ (0.0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #koi8 :\313\317\322\317\336\305
\324\305\320\305\322\330 \305\323\314\311 \320\317 \322\325\323\323\313\311
\316\301\320\311\323\301\324\330 \327\323\305 \336\305\324\313\317 \311\314\311
\327\323\305 \322\301\327\316\317 \313\317\322\317\336\305
\324\305\320\305\322\330 \305\323\314\311 \320\317 \322\325\323\323\313\311
\316\301\320\311\323\301\324\330 \327\323\305 \336\305\324\313\317 \311\314\311
\327\323\305 \322\301\327\316\317"))
+
+((privmsg 10 "PRIVMSG #koi8 :\313\317\322\317\336\305 \324\305\320\305\322\330
\305\323\314\311 \320\317 \322\325\323\323\313\311
\316\301\320\311\323\301\324\330 \327\323\305 \336\305\324\313\317 \311\314\311
\327\323\305 \322\301\327\316\317 \313\317\322\317\336\305
\324\305\320\305\322\330 \305\323\314\311 \320\317 \322\325\323\323\313\311
\316\301\320\311\323\301\324\330 \327\323\305 \336\305\324\313\317 \311\314\311
\327\323\305 \322\301\327\316\317 \313\317\322\317\336\305 \324\305 [...]
+((privmsg 10 "PRIVMSG #koi8 :\313\317\322\317\336\305 \324\305\320\305\322\330
\305\323\314\311 \320\317 \322\325\323\323\313\311
\316\301\320\311\323\301\324\330 \327\323\305 \336\305\324\313\317 \311\314\311
\327\323\305 \322\301\327\316\317 \313\317\322\317\336\305
\324\305\320\305\322\330 \305\323\314\311 \320\317 \322\325\323\323\313\311
\316\301\320\311\323\301\324\330 \327\323\305 \336\305\324\313\317 \311\314\311
\327\323\305 \322\301\327\316\317 \313\317\322\317\336\305 \324\305 [...]
+((privmsg 10 "PRIVMSG #koi8 :\322\301\332\322\331\327 \323\324\322\317\313\311
\316\305\320\317\316\321\324\316\317 \307\304\305"))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.07 ":tester!~u@h3f95zveyc38a.irc QUIT :Quit: \2ERC\2 5.5 (IRC client for
GNU Emacs 30.0.50)")
+ (0.01 "ERROR :Quit: \2ERC\2 5.5 (IRC client for GNU Emacs 30.0.50)"))
diff --git a/test/lisp/erc/resources/base/flood/utf-8.eld
b/test/lisp/erc/resources/base/flood/utf-8.eld
new file mode 100644
index 00000000000..8e7f8f7eed2
--- /dev/null
+++ b/test/lisp/erc/resources/base/flood/utf-8.eld
@@ -0,0 +1,54 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running
version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Sun, 12 Mar 2023
02:30:29 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios
CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=#
CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by
this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4
MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+
TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by
this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1
server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.foonet.org 375 tester :- irc.foonet.org Message of the day - ")
+ (0.00 ":irc.foonet.org 372 tester :- This is the default Ergo MOTD.")
+ (0.01 ":irc.foonet.org 372 tester :- ")
+ (0.02 ":irc.foonet.org 372 tester :- For more information on using these, see
MOTDFORMATTING.md")
+ (0.00 ":irc.foonet.org 376 tester :End of MOTD command"))
+
+((mode-tester 10 "MODE tester +i")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is
logging all user I/O. If you do not wish for everything you send to be readable
by the server owner(s), please disconnect.")
+ (0.05 ":irc.foonet.org 221 tester +i"))
+
+((join-spam 10 "JOIN #utf-8")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #utf-8")
+ (0 ":irc.foonet.org 353 tester = #utf-8 :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #utf-8 :End of NAMES list"))
+
+((mode-spam 10 "MODE #utf-8")
+ (0 ":irc.foonet.org 324 tester #utf-8 +nt")
+ (0 ":irc.foonet.org 329 tester #utf-8 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #utf-8 :tester, welcome!")
+ (0.0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #utf-8 :tester, welcome!"))
+
+((privmsg-a 10 "PRIVMSG #utf-8
:\320\272\320\276\321\200\320\276\321\207\320\265
\321\202\320\265\320\277\320\265\321\200\321\214
\320\265\321\201\320\273\320\270 \320\277\320\276
\321\200\321\203\321\201\321\201\320\272\320\270
\320\275\320\260\320\277\320\270\321\201\320\260\321\202\321\214
\320\262\321\201\320\265 \321\207\320\265\321\202\320\272\320\276
\320\270\320\273\320\270 \320\262\321\201\320\265
\321\200\320\260\320\262\320\275\320\276
\320\272\320\276\321\200\320\276\321\207\ [...]
+((privmsg-b 10 "PRIVMSG #utf-8 :\320\262\321\201\320\265
\321\200\320\260\320\262\320\275\320\276
\320\272\320\276\321\200\320\276\321\207\320\265
\321\202\320\265\320\277\320\265\321\200\321\214
\320\265\321\201\320\273\320\270 \320\277\320\276
\321\200\321\203\321\201\321\201\320\272\320\270
\320\275\320\260\320\277\320\270\321\201\320\260\321\202\321\214
\320\262\321\201\320\265 \321\207\320\265\321\202\320\272\320\276
\320\270\320\273\320\270 \320\262\321\201\320\265 \321\200\320\260 [...]
+((privmsg-c 10 "PRIVMSG #utf-8
:\321\200\320\260\320\267\321\200\321\213\320\262
\321\201\321\202\321\200\320\276\320\272\320\270
\320\275\320\265\320\277\320\276\320\275\321\217\321\202\320\275\320\276
\320\263\320\264\320\265")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #utf-8 :alice: Entirely honour; I
would not be delay'd."))
+
+((privmsg-g 10 "PRIVMSG #utf-8
:\350\251\261\350\252\252\345\244\251\344\270\213\345\244\247\345\213\242\357\274\214\345\210\206\344\271\205\345\277\205\345\220\210\357\274\214\345\220\210\344\271\205\345\277\205\345\210\206\357\274\232\345\221\250\346\234\253\344\270\203\345\234\213\345\210\206\347\210\255\357\274\214\345\271\266\345\205\245\346\226\274\347\247\246\343\200\202\345\217\212\347\247\246\346\273\205\344\271\213\345\276\214\357\274\214\346\245\232\343\200\201\346\274\242\345
[...]
+((privmsg-h 10 "PRIVMSG #utf-8
:\347\253\207\346\255\246\343\200\201\351\231\263\350\225\203\350\254\200\350\252\205\344\271\213\357\274\214\344\275\234\344\272\213\344\270\215\345\257\206\357\274\214\345\217\215\347\202\272\346\211\200\345\256\263\343\200\202\344\270\255\346\266\223\350\207\252\346\255\244\346\204\210\346\251\253")
+ (0.0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #utf-8 :Shall seize this prey out
of his father's hands."))
+
+((privmsg-d 10 "PRIVMSG #utf-8
:\320\261\321\203\320\264\320\265\321\202\302\240\321\200\320\260\320\267\321\200\321\213\320\262\302\240\321\201\321\202\321\200\320\276\320\272\320\270\302\240\320\275\320\265\320\277\320\276\320\275\321\217\321\202\320\275\320\276\302\240\320\263\320\264\320\265\360\237\217\201\360\237\232\251\360\237\216\214\360\237\217\264\360\237\217\263\357\270\217"))
+((privmsg-e 10 "PRIVMSG #utf-8
:\360\237\217\263\357\270\217\342\200\215\360\237\214\210\360\237\217\263\357\270\217\342\200\215\342\232\247\357\270\217\360\237\217\264\342\200\215\342\230\240\357\270\217"))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.07 ":tester!~u@h3f95zveyc38a.irc QUIT :Quit: \2ERC\2 5.5 (IRC client for
GNU Emacs 30.0.50)")
+ (0.01 "ERROR :Quit: \2ERC\2 5.5 (IRC client for GNU Emacs 30.0.50)"))
diff --git a/test/lisp/erc/resources/erc-d/erc-d.el
b/test/lisp/erc/resources/erc-d/erc-d.el
index 43f6552f0f3..e9d880644d4 100644
--- a/test/lisp/erc/resources/erc-d/erc-d.el
+++ b/test/lisp/erc/resources/erc-d/erc-d.el
@@ -456,7 +456,7 @@ including line delimiters."
(setq string (unless (= (match-end 0) (length string))
(substring string (match-end 0))))
(erc-d--log process line nil)
- (ring-insert queue (erc-d-i--parse-message line 'decode))))
+ (ring-insert queue (erc-d-i--parse-message line nil))))
(when string
(setf (process-get process :stashed-input) string))))
- master 8654cea5843 02/14: Move ERC's buffer-display tests to separate file, (continued)
- master 8654cea5843 02/14: Move ERC's buffer-display tests to separate file, F. Jason Park, 2023/05/05
- master 5de90fa9611 03/14: Extend erc-interactive-display to cover /JOINs, F. Jason Park, 2023/05/05
- master 9e1a5a389ed 04/14: Ignore erc-reconnect-display after a timeout, F. Jason Park, 2023/05/05
- master 90a9c7b7b59 05/14: Actually define erc-default-server-functions, F. Jason Park, 2023/05/05
- master b0d761be0f9 08/14: Restore module var toggles in ERC's Custom buffers, F. Jason Park, 2023/05/05
- master 2e18ba6302f 07/14: Simplify erc-button movement commands, F. Jason Park, 2023/05/05
- master 2641dfd4b43 06/14: Add erc-timestamp property to invisible messages, F. Jason Park, 2023/05/05
- master 16306567706 09/14: Don't send multiline commands as messages in ERC, F. Jason Park, 2023/05/05
- master 35dd1ade7f1 11/14: Preprocess prompt input linewise in ERC, F. Jason Park, 2023/05/05
- master ba44b481844 14/14: Add interface for finding users in erc-server-PRIVMSG, F. Jason Park, 2023/05/05
- master 3a5a6fce957 10/14: Redo line splitting for outgoing messages in ERC,
F. Jason Park <=
- master 5adda2f4683 12/14: Revise FORM-as-function interface in erc-button-alist, F. Jason Park, 2023/05/05
- master d141f7149b6 13/14: Improve erc-button--modify-nick-function interface, F. Jason Park, 2023/05/05