From unknown Sun Jun 15 13:01:06 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#54536 <54536@debbugs.gnu.org> To: bug#54536 <54536@debbugs.gnu.org> Subject: Status: 29.0.50; Improve ERC's handling of multiline prompt input Reply-To: bug#54536 <54536@debbugs.gnu.org> Date: Sun, 15 Jun 2025 20:01:06 +0000 retitle 54536 29.0.50; Improve ERC's handling of multiline prompt input reassign 54536 emacs submitter 54536 "J.P." severity 54536 normal tag 54536 patch thanks From debbugs-submit-bounces@debbugs.gnu.org Wed Mar 23 09:27:01 2022 Received: (at submit) by debbugs.gnu.org; 23 Mar 2022 13:27:01 +0000 Received: from localhost ([127.0.0.1]:43137 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nX10t-0001ft-NF for submit@debbugs.gnu.org; Wed, 23 Mar 2022 09:27:01 -0400 Received: from lists.gnu.org ([209.51.188.17]:50042) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nX10r-0001fk-5k for submit@debbugs.gnu.org; Wed, 23 Mar 2022 09:26:58 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46828) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nX10q-0001ma-Ae for bug-gnu-emacs@gnu.org; Wed, 23 Mar 2022 09:26:57 -0400 Received: from mail-108-mta94.mxroute.com ([136.175.108.94]:34415) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nX10m-0007b7-8j for bug-gnu-emacs@gnu.org; Wed, 23 Mar 2022 09:26:56 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta94.mxroute.com (ZoneMTA) with ESMTPSA id 17fb6f55b21000fe85.001 for (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Wed, 23 Mar 2022 13:26:47 +0000 X-Zone-Loop: bfd407eab9988c48a665033a0c3fa039fb83f4271dea X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:Date:Subject:Cc:To:From:Sender: Reply-To:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date :Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=0lJyincDSBojSRdaYrPT/7AqudF21vOkESzXWkaQS5U=; b=U r3zVcuR2BT7AdjpaFmsG9O2m9m2ot8EDDQg5SnZLSa5lseuKewKxg4WeHW3FfnU+hMASKi7f/0p0j fj6+Z+s/o3HmyYaAgwh0eekA5p3bsEpqNbaD4jOdA/pbmqJP3mN5DONX2QAzMA8/yrWfzYWllLPzH QZR6XvLYDaWbvwVKuw9ozNe27YbleN5HohHIX2DGY+saTh9W4bmOEUMaerN07ZvMS5NFMRIBPIp58 Ohl7Yajd0r95gaIWbubUEBkJ46Lp+XUWasZt1EDmxEEjNFWY3xcHHa62Gm1bsq8kS74EVAGTaiprf m5cIHfo+JSayl8spfOwWBZdsA/LDgnTCg==; From: "J.P." To: bug-gnu-emacs@gnu.org Subject: 29.0.50; Improve ERC's handling of multiline prompt input Date: Wed, 23 Mar 2022 06:26:44 -0700 Message-ID: <87k0ckg5pn.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-AuthUser: masked@neverwas.me Received-SPF: pass client-ip=136.175.108.94; envelope-from=jp@neverwas.me; helo=mail-108-mta94.mxroute.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.4 (-) X-Debbugs-Envelope-To: submit Cc: emacs-erc@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.4 (--) --=-=-= Content-Type: text/plain Tags: patch ERC suffers from a few related issues concerning the early handling of user input at the prompt. Especially troublesome is "multiline" input containing line feeds and/or carriage returns. This patch (or at least this discussion) aims to tackle both. Any solution should probably address these fundamental UX questions: 1. What should happen when a user submits multiline input containing empty lines? Should these be padded so they're not rejected by the server? If so, where in the processing pipeline should that occur? Should `erc-send-whitespace-lines' play a role here? This patch says yes to the latter and interprets that option as meaning "preserve whitespace-only lines and create them as necessary from blank ones." As to where padding should happen, this patch punts and retains the existing (unfortunate) practice of treating them at the last minute. 2. Should trailing blank lines be treated differently? If so, how? Should they be auto-padded? Simply dropped? Or should encountering them raise an error? When `erc-send-whitespace-lines' is non-nil, this patch drops trailing blanks by default, but it also provides an escape hatch. 3. When `erc-send-whitespace-lines' is non-nil, should it auto-pad a submission consisting of a single empty line? Should it allow a whitespace-only singleton through? This patch says no to the first and yes to the second. 4. Should slash commands, like /MSG be allowed to lead a multiline submission? This patch says no, still choosing to interpret commands as always consisting of a single line. To offer some flexibility, I'm introducing a hook to perform some validation on the input being submitted. It comes prepopulated with functions that replicate existing behavior, such as ensuring point resides within the input area. It also contains an additional function to perform the blank-detection business. While it's true that multiple members of this hook may end up repeating some basic operations (such as splitting the input string), at present, this isn't the case, and such waste is pretty negligible anyway since this is an interactive function. There is one behavioral change being introduced that doesn't come with an escape hatch, and that's the preservation of input when a validation check fails. Previously, a user's input would be wiped out, which seems undesirable and unnecessary in all cases (IMO). For these and any other, less significant changes not mentioned, the floor is open for questions and debate, as usual. Thanks. (See also: "bug#50008: 28.0.50; ERC sends empty lines with user input" and "bug#50006: 28.0.50; remove deprecated option erc-send-pre-hook".) In GNU Emacs 29.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.31, cairo version 1.17.4) of 2022-03-23 built on localhost Repository revision: fed9a353dbe79a7a6acc74c1e223c46e7541e627 Repository branch: master Windowing system distributor 'The X.Org Foundation', version 11.0.12014000 System Description: Fedora Linux 35 (Workstation Edition) Configured using: 'configure --enable-check-lisp-object-type --enable-checking=yes,glyphs 'CFLAGS=-O0 -g3' PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig' Configured features: ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XPM GTK3 ZLIB Important settings: value of $LANG: en_US.UTF-8 value of $XMODIFIERS: @im=ibus locale-coding-system: utf-8-unix Major mode: Lisp Interaction Minor modes in effect: tooltip-mode: t global-eldoc-mode: t eldoc-mode: t show-paren-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t line-number-mode: t indent-tabs-mode: t transient-mark-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t Load-path shadows: None found. Features: (shadow sort mail-extr emacsbug message mailcap yank-media rmc puny dired dired-loaddefs rfc822 mml mml-sec password-cache epa derived epg rfc6068 epg-config gnus-util text-property-search time-date seq gv subr-x byte-opt bytecomp byte-compile cconv mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader cl-loaddefs cl-lib sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils iso-transl tooltip eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors frame minibuffer nadvice simple cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help abbrev obarray cl-preloaded button loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget keymap hashtable-print-readable backquote threads dbusbind inotify lcms2 dynamic-setting system-font-setting font-render-setting cairo move-toolbar gtk x-toolkit x multi-tty make-network-process emacs) Memory information: ((conses 16 43960 5198) (symbols 48 5704 1) (strings 32 15802 1589) (string-bytes 1 526831) (vectors 16 12066) (vector-slots 8 167842 8149) (floats 8 20 55) (intervals 56 241 0) (buffers 992 11)) --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Fix-regression-in-erc-send-input-line.patch >From fe1f21eeb9027116f263b968d792943b92064df3 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 19:21:57 -0700 Subject: [PATCH 1/2] Fix regression in erc-send-input-line * lisp/erc/erc.el (erc-send-input-line): Restore remedial single-space padding to ensure empty messages typed at the prompt without an explicit /msg aren't rejected by the server. This behavior is only noticeable when `erc-send-whitespace-lines' is active. * test/lisp/erc/erc-tests.el (erc-process-input-line): Add trailing newline to more correctly simulate how it's actually called by `erc-send-input'. (Bug#50008) --- lisp/erc/erc.el | 2 ++ test/lisp/erc/erc-tests.el | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 52fe106f2d..d8ef62cf93 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2817,6 +2817,8 @@ erc-send-input-line-function (defun erc-send-input-line (target line &optional force) "Send LINE to TARGET." + (when (string= line "\n") + (setq line " \n")) (erc-message "PRIVMSG" (concat target " " line) force)) (defun erc-get-arglist (fun) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 520f10dd4e..10e3c16dfc 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -340,19 +340,19 @@ erc-process-input-line (ert-info ("Implicit cmd via `erc-send-input-line-function'") (ert-info ("Baseline") - (erc-process-input-line "hi") + (erc-process-input-line "hi\n") (should (equal (pop erc-server-flood-queue) '("PRIVMSG #chan :hi\r\n" . utf-8)))) (ert-info ("Spaces preserved") - (erc-process-input-line "hi you") + (erc-process-input-line "hi you\n") (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 "") + (ert-info ("Empty line transmitted with injected-space kludge") + (erc-process-input-line "\n") (should (equal (pop erc-server-flood-queue) - '("PRIVMSG #chan :\r\n" . utf-8)))) + '("PRIVMSG #chan : \r\n" . utf-8)))) (should-not calls)))))) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Improve-ERC-s-handling-of-multiline-prompt-input.patch >From 8a921612bdafdc5720fe12b49d215c1a42f9c0d0 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 05:40:16 -0700 Subject: [PATCH 2/2] Improve ERC's handling of multiline prompt input * lisp/erc/erc.el (erc-pre-send-functions, erc-discard-trailing-multiline-nulls): Add the latter, a new function, that drops any trailing null lines from a multiline sequence submitted for processing. Add it to `erc-pre-send-functions' as the lone new default. (erc-last-input-time): Tweak meaning of variable to match likely original intent, which is that it's only updated on successful calls to `erc-send-current-line'. (erc--input-line-delim-regexp): Add regex var for splitting multiline prompt input. (erc--blank-in-multiline-p): Add helper for detecting blank lines. (erc-check-prompt-input-for-multiline-blanks, erc-check-prompt-input-for-point-in-bounds, erc-check-prompt-input-for-running-process): New functions to encapsulate logic for various pre-flight idiot checks. (erc-check-prompt-input-functions): Add new hook for validating prompt input prior to clearing it. (erc-send-current-line): pre-screen for blank lines and bail out if necessary. (erc-send-input): Add optional param to skip checking for blank lines. * test/lisp/erc/erc-tests.el (erc-ring-previous-command): Use new test helper. (erc--input-line-delim-regexp, erc--blank-in-multiline-input-p): Add tests. (erc-tests--send-prep, erc-tests--set-fake-server-process, erc-tests--with-process-input-spy): Add test helpers. (erc-check-prompt-input-functions, erc-send-current-line, erc-send-whitespace-lines): Add tests. --- lisp/erc/erc.el | 103 ++++++++++++++----- test/lisp/erc/erc-tests.el | 200 +++++++++++++++++++++++++++++++++++-- 2 files changed, 273 insertions(+), 30 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index d8ef62cf93..cbb30bab5b 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1040,7 +1040,7 @@ erc-send-pre-hook :type 'hook) (make-obsolete-variable 'erc-send-pre-hook 'erc-pre-send-functions "27.1") -(defcustom erc-pre-send-functions nil +(defcustom erc-pre-send-functions '(erc-discard-trailing-multiline-nulls) "Special hook run to possibly alter the string that is sent. The functions are called with one argument, an `erc-input' struct, and should alter that struct. @@ -5536,7 +5536,7 @@ erc-end-of-input-line (point-max)) (defvar erc-last-input-time 0 - "Time of last call to `erc-send-current-line'. + "Time of last successful call to `erc-send-current-line'. If that function has never been called, the value is 0.") (defcustom erc-accidental-paste-threshold-seconds 0.2 @@ -5552,6 +5552,66 @@ erc-accidental-paste-threshold-seconds :version "26.1" :type '(choice number (other :tag "disabled" nil))) +(defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r))) + +(defun erc--blank-in-multiline-input-p (string) + "Detect whether STRING contains any blank lines. +When `erc-send-whitespace-lines' is in effect and the input is not a +\"command\", like /msg, return nil if the input is multiline or the line +is non-empty. When `erc-send-whitespace-lines' is nil, return non-nil +when any line is empty or consists of one or more spaces, tabs, or +form-feeds." + (catch 'return + (let ((lines (split-string string erc--input-line-delim-regexp)) + (cmdp '--?--)) + (dolist (line lines) + (when (if erc-send-whitespace-lines + (and (string= line "") + (or (null (cdr lines)) ; string is one line + (if (eq cmdp '--?--) ; string is /cmd + (setq cmdp (string-match erc-command-regexp + (car lines))) + cmdp))) + (string-match (rx bot (* (in " \t\f")) eot) line)) + (throw 'return t)))))) + +(defun erc-discard-trailing-multiline-nulls (state) + "Ensure last line of `erc-input' STATE's string is non-null. +But only when `erc-send-whitespace-lines' is non-nil." + (when erc-send-whitespace-lines + (cl-callf (lambda (s) (string-trim-right s "[\r\n]+")) + (erc-input-string state)))) + +(defun erc-check-prompt-input-for-multiline-blanks (string) + "Return non-nil when multiline prompt input has blank lines." + (when (erc--blank-in-multiline-input-p string) + (if erc-warn-about-blank-lines + "Blank line - ignoring..." + 'invalid))) + +(defun erc-check-prompt-input-for-point-in-bounds (_) + "Return non-nil when point is before prompt." + (when (< (point) (erc-beg-of-input-line)) + "Point is not in the input area")) + +(defun erc-check-prompt-input-for-running-process (string) + "Return non-nil unless in an active ERC server buffer." + (unless (or (erc-server-buffer-live-p) + (erc-command-no-process-p string)) + "ERC: No process running")) + +(defcustom erc-check-prompt-input-functions + '(erc-check-prompt-input-for-point-in-bounds + erc-check-prompt-input-for-multiline-blanks + erc-check-prompt-input-for-running-process) + "Validators for user input typed at prompt. +Called with latest input string submitted by user. If any member +returns non-nil, processing is abandoned and input is left untouched. +When the returned value is a string, pass it to `erc-error'." + :group 'erc + :version "29.1" + :type 'hook) + (defun erc-send-current-line () "Parse current line and send it to IRC." (interactive) @@ -5565,20 +5625,20 @@ erc-send-current-line (eolp)) (expand-abbrev)) (widen) - (if (< (point) (erc-beg-of-input-line)) - (erc-error "Point is not in the input area") + (if-let* ((str (erc-user-input)) + (msg (run-hook-with-args-until-success + 'erc-check-prompt-input-functions str))) + (when (stringp msg) + (erc-error msg)) (let ((inhibit-read-only t) - (str (erc-user-input)) (old-buf (current-buffer))) - (if (and (not (erc-server-buffer-live-p)) - (not (erc-command-no-process-p str))) - (erc-error "ERC: No process running") + (progn ; unprogn this during next major surgery (erc-set-active-buffer (current-buffer)) ;; Kill the input and the prompt (delete-region (erc-beg-of-input-line) (erc-end-of-input-line)) (unwind-protect - (erc-send-input str) + (erc-send-input str 'skip-ws-chk) ;; Fix the buffer if the command didn't kill it (when (buffer-live-p old-buf) (with-current-buffer old-buf @@ -5593,8 +5653,8 @@ erc-send-current-line (set-buffer-modified-p buffer-modified)))))) ;; Only when last hook has been run... - (run-hook-with-args 'erc-send-completed-hook str)))) - (setq erc-last-input-time now)) + (run-hook-with-args 'erc-send-completed-hook str))) + (setq erc-last-input-time now))) (switch-to-buffer "*ERC Accidental Paste Overflow*") (lwarn 'erc :warning "You seem to have accidentally pasted some text!")))) @@ -5611,21 +5671,16 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) -(defun erc-send-input (input) +(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. Return non-nil only if we actually send anything." ;; Handle different kinds of inputs - (cond - ;; Ignore empty input - ((if erc-send-whitespace-lines - (string= input "") - (string-match "\\`[ \t\r\f\n]*\\'" input)) - (when erc-warn-about-blank-lines - (message "Blank line - ignoring...") - (beep)) - nil) - (t + (if (and (not skip-ws-chk) + (erc-check-prompt-input-for-multiline-blanks input)) + (when erc-warn-about-blank-lines + (message "Blank line - ignoring...") ; compat + (beep)) ;; This dynamic variable is used by `erc-send-pre-hook'. It's ;; obsolete, and when it's finally removed, this binding should ;; also be removed. @@ -5663,9 +5718,9 @@ erc-send-input (null erc-flood-protect) t)) (or (and erc-flood-protect (erc-split-line line)) (list line)))) - (split-string string "\n")) + (split-string string erc--input-line-delim-regexp)) (erc-process-input-line (concat string "\n") t nil)) - t)))))) + t))))) ;; (defun erc-display-command (line) ;; (when erc-insert-this diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 10e3c16dfc..6a9d291f8a 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -197,14 +197,10 @@ erc-ring-previous-command-base-case (ert-deftest erc-ring-previous-command () (with-current-buffer (get-buffer-create "*#fake*") (erc-mode) - (insert "\n\n") + (erc-tests--send-prep) + (setq-local erc-last-input-time 0) (should-not (local-variable-if-set-p 'erc-send-completed-hook)) (set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals) - (setq erc-input-marker (make-marker) - erc-insert-marker (make-marker)) - (set-marker erc-insert-marker (point-max)) - (erc-display-prompt) - (should (= (point) erc-input-marker)) ;; Just in case erc-ring-mode is already on (setq-local erc-pre-send-functions nil) (add-hook 'erc-pre-send-functions #'erc-add-to-input-ring) @@ -285,6 +281,198 @@ erc-log-irc-protocol (kill-buffer "*erc-protocol*") (should-not erc-debug-irc-protocol))) +(ert-deftest erc--input-line-delim-regexp () + (let ((p erc--input-line-delim-regexp)) + ;; none + (should (equal '("a" "b") (split-string "a\r\nb" p))) + (should (equal '("a" "b") (split-string "a\nb" p))) + (should (equal '("a" "b") (split-string "a\rb" p))) + + ;; one + (should (equal '("") (split-string "" p))) + (should (equal '("a" "" "b") (split-string "a\r\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\nb" p))) + (should (equal '("a" "" "b") (split-string "a\r\r\nb" p))) + (should (equal '("a" "" "b") (split-string "a\n\r\nb" p))) + (should (equal '("a" "") (split-string "a\n" p))) + (should (equal '("a" "") (split-string "a\r" p))) + (should (equal '("a" "") (split-string "a\r\n" p))) + (should (equal '("" "b") (split-string "\nb" p))) + (should (equal '("" "b") (split-string "\rb" p))) + (should (equal '("" "b") (split-string "\r\nb" p))) + + ;; two + (should (equal '("" "") (split-string "\r" p))) + (should (equal '("" "") (split-string "\n" p))) + (should (equal '("" "") (split-string "\r\n" p))) + + ;; three + (should (equal '("" "" "") (split-string "\r\r" p))) + (should (equal '("" "" "") (split-string "\n\n" p))) + (should (equal '("" "" "") (split-string "\n\r" p))))) + +(ert-deftest erc--blank-in-multiline-input-p () + (ert-info ("With `erc-send-whitespace-lines'") + (let ((erc-send-whitespace-lines t)) + (should (erc--blank-in-multiline-input-p "")) + (should (erc--blank-in-multiline-input-p "/msg a\n")) ; likely oops + (should (erc--blank-in-multiline-input-p "/msg a\n\nb")) ; "" not allowed + (should-not (erc--blank-in-multiline-input-p "a\n\nb")) ; "" allowed + (should-not (erc--blank-in-multiline-input-p " ")) + (should-not (erc--blank-in-multiline-input-p "\t")) + (should-not (erc--blank-in-multiline-input-p "a\nb")) + (should-not (erc--blank-in-multiline-input-p "a\n ")) + (should-not (erc--blank-in-multiline-input-p "a\n \t")) + (should-not (erc--blank-in-multiline-input-p "a\n \f")) + (should-not (erc--blank-in-multiline-input-p "a\n \nb")) + (should-not (erc--blank-in-multiline-input-p "a\n \t\nb")) + (should-not (erc--blank-in-multiline-input-p "a\n \f\nb")))) + + (should (erc--blank-in-multiline-input-p "")) + (should (erc--blank-in-multiline-input-p " ")) + (should (erc--blank-in-multiline-input-p "\t")) + (should (erc--blank-in-multiline-input-p "a\n\nb")) + (should (erc--blank-in-multiline-input-p "a\n\nb")) + (should (erc--blank-in-multiline-input-p "a\n ")) + (should (erc--blank-in-multiline-input-p "a\n \t")) + (should (erc--blank-in-multiline-input-p "a\n \f")) + (should (erc--blank-in-multiline-input-p "a\n \nb")) + (should (erc--blank-in-multiline-input-p "a\n \t\nb")) + + (should-not (erc--blank-in-multiline-input-p "a\rb")) + (should-not (erc--blank-in-multiline-input-p "a\nb")) + (should-not (erc--blank-in-multiline-input-p "a\r\nb"))) + +(defun erc-tests--send-prep () + (erc-mode) + (insert "\n\n") + (setq erc-input-marker (make-marker) + erc-insert-marker (make-marker)) + (set-marker erc-insert-marker (point-max)) + (erc-display-prompt) + (should (= (point) erc-input-marker))) + +(defun erc-tests--set-fake-server-process (&rest args) + (setq erc-server-process + (apply #'start-process (car args) (current-buffer) args)) + (set-process-query-on-exit-flag erc-server-process nil)) + +(defmacro erc-tests--with-process-input-spy (calls-var &rest body) + (declare (indent 1)) + `(with-current-buffer (get-buffer-create "FakeNet") + (let ((erc-pre-send-functions + (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now + (inhibit-message noninteractive) + (erc-server-current-nick "tester") + (erc-last-input-time 0) + erc-accidental-paste-threshold-seconds + ,calls-var) + (cl-letf (((symbol-function 'erc-process-input-line) + (lambda (&rest r) (push r ,calls-var))) + ((symbol-function 'erc-server-buffer) + (lambda () (current-buffer)))) + (erc-tests--send-prep) + ,@body)) + (when noninteractive (kill-buffer)))) + +(ert-deftest erc-check-prompt-input-functions () + (erc-tests--with-process-input-spy calls + + (ert-info ("Errors when point not in prompt area") ; actually just dings + (insert "/msg #chan hi") + (forward-line -1) + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Point is not in the input area" (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when no process running") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "ERC: No process running" (cadr e)))) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when line contains empty newline") + (erc-bol) + (delete-region (point) (point-max)) + (insert "one\n") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Blank line - ignoring..." (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (goto-char erc-input-marker) + (looking-at "one\n"))))) + + (should (= 0 erc-last-input-time)) + (should-not calls))) + +;; These also indirectly tests `erc-send-input' + +(ert-deftest erc-send-current-line () + (erc-tests--with-process-input-spy calls + + (erc-tests--set-fake-server-process "sleep" "1") + (should (= 0 erc-last-input-time)) + + (ert-info ("Simple command") + (insert "/msg #chan hi") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + ;; Commands are forced (no flood protection) + (should (equal (pop calls) '("/msg #chan hi\n" t nil)))) + + (ert-info ("Simple non-command") + (insert "hi") + (erc-send-current-line) + (should (eq (point) (point-max))) + (should (save-excursion (forward-line -1) + (search-forward " hi"))) + ;; Non-ommands are forced only when `erc-flood-protect' is nil + (should (equal (pop calls) '("hi\n" nil t)))) + + (should (consp erc-last-input-time)))) + +(ert-deftest erc-send-whitespace-lines () + (erc-tests--with-process-input-spy calls + + (erc-tests--set-fake-server-process "sleep" "1") + (setq-local erc-send-whitespace-lines t) + + (ert-info ("Multiline hunk with blank line correctly split") + (insert "one\n\ntwo") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (pop calls) '("two\n" nil t))) + (should (equal (pop calls) '("\n" nil t))) + (should (equal (pop calls) '("one\n" nil t)))) + + (ert-info ("Multiline hunk with trailing blank filtered") + (insert "hi\n") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (pop calls) '("hi\n" nil t))) + (should-not (pop calls))) + + (ert-info ("Multiline hunk with trailing whitespace not filtered") + (insert "there\n ") + (erc-send-current-line) + (should (equal (pop calls) '(" \n" nil t))) + (should (equal (pop calls) '("there\n" nil t))) + (should-not (pop calls))))) ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.35.1 --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Wed Mar 23 09:50:26 2022 Received: (at 54536) by debbugs.gnu.org; 23 Mar 2022 13:50:26 +0000 Received: from localhost ([127.0.0.1]:43187 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nX1Na-0006gx-2A for submit@debbugs.gnu.org; Wed, 23 Mar 2022 09:50:26 -0400 Received: from quimby.gnus.org ([95.216.78.240]:46448) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nX1NY-0006gj-4d for 54536@debbugs.gnu.org; Wed, 23 Mar 2022 09:50:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=ew+btwU4R6an/Ugi6pTomFQm6pgBRzaPCrbDnarKCU0=; b=nN/vvppDbECHIFkjBRu7ixlDcv Ehj/kB3YFb4885nGz//QMW2wBom6t3XqMlzY+aPds0BaHHfSPDXtCuVFEHO0vuq/Z98Djrnfrd3jg WuHZmtPF+ooLvgSjVNJ3YNSCJE7KR004vx3hlemYKiZWY/j6ZYxiyakke+VFZIT5GLJc=; Received: from 109.179.236.69.tmi.telenormobil.no ([109.179.236.69] helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nX1NO-0004IQ-Hh; Wed, 23 Mar 2022 14:50:16 +0100 From: Lars Ingebrigtsen To: "J.P." Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> Date: Wed, 23 Mar 2022 14:50:13 +0100 In-Reply-To: <87k0ckg5pn.fsf@neverwas.me> (J. P.'s message of "Wed, 23 Mar 2022 06:26:44 -0700") Message-ID: <87czic93sa.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: "J.P." writes: > 1. What should happen when a user submits multiline input containing > empty lines? Should these be padded so they're not rejected by the > server? If so, where in the processing pipeline should tha [...] Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP 0.0 TVD_RCVD_IP Message was received from an IP address -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) "J.P." writes: > 1. What should happen when a user submits multiline input containing > empty lines? Should these be padded so they're not rejected by the > server? If so, where in the processing pipeline should that occur? > Should `erc-send-whitespace-lines' play a role here? > > This patch says yes to the latter and interprets that option as > meaning "preserve whitespace-only lines and create them as necessary > from blank ones." As to where padding should happen, this patch punts > and retains the existing (unfortunate) practice of treating them at > the last minute. Makes sense to me. > 2. Should trailing blank lines be treated differently? If so, how? > Should they be auto-padded? Simply dropped? Or should encountering > them raise an error? > > When `erc-send-whitespace-lines' is non-nil, this patch drops > trailing blanks by default, but it also provides an escape hatch. Dropping trailing blank lines is a good thing, I think. > 3. When `erc-send-whitespace-lines' is non-nil, should it auto-pad a > submission consisting of a single empty line? Should it allow a > whitespace-only singleton through? > > This patch says no to the first and yes to the second. Sounds good. > 4. Should slash commands, like /MSG be allowed to lead a multiline > submission? > > This patch says no, still choosing to interpret commands as always > consisting of a single line. Ditto. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no From debbugs-submit-bounces@debbugs.gnu.org Thu Mar 24 15:51:09 2022 Received: (at 54536) by debbugs.gnu.org; 24 Mar 2022 19:51:09 +0000 Received: from localhost ([127.0.0.1]:49455 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXTUD-0005ia-Fn for submit@debbugs.gnu.org; Thu, 24 Mar 2022 15:51:09 -0400 Received: from mail-108-mta173.mxroute.com ([136.175.108.173]:40331) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXTUC-0005iN-D4 for 54536@debbugs.gnu.org; Thu, 24 Mar 2022 15:51:08 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta173.mxroute.com (ZoneMTA) with ESMTPSA id 17fbd7b7ad7000fe85.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Thu, 24 Mar 2022 19:51:00 +0000 X-Zone-Loop: fb6cc62911413ba4970da9bd9c13a9ec482b73e80e1f X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=yYGJLZrn7srvOtgd/YvPcFGNLLDMCAb2qZi+j7Ev89I=; b=jmLhLEE9K0RW1iDj5twwGYjbz6 4KrNXaLb+LSe8x/yPC6LvzFvOWzNuN9vmv0ogKXCx0muemptO/TAFH0e9VF7eluVl3ZlGM4TBctvm naOdaEPT4KeZMoutyL3S/uQV9sLl2ojg15a4pxXHX3SLr2HZxgqSnG9mXP7I23B3qBiZ5Z2U6XG8P h130IXf3S7Kn2nxBWuRzxfgz1v46QkYKskU9ZXxlOy2CMUaRSALmhCQmhX65miqRpP4ytO+kHAPJ1 YfCCxIWrA2LrItJfiCQH7eo2cFjHuJoaZzdTMF1H/xvu0mJCplzwUj2MuYHTen50L0w8Urpnqzp61 pbalW6UQ==; From: "J.P." To: Lars Ingebrigtsen Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> Date: Thu, 24 Mar 2022 12:50:57 -0700 In-Reply-To: <87czic93sa.fsf@gnus.org> (Lars Ingebrigtsen's message of "Wed, 23 Mar 2022 14:50:13 +0100") Message-ID: <87ee2rb04e.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Lars Ingebrigtsen writes: > "J.P." writes: > >> 1. What should happen when a user submits multiline input containing >> empty lines? [...] This patch says [...] > > Makes sense to me. > >> 2. Should trailing blank lines be treated differently? [...] >> > Dropping trailing blank lines is a good thing, I think. > >> 3. When `erc-send-whitespace-lines' is non-nil, should it [...] >> This patch says no to the first and yes to the second. > > Sounds good. Appreciate the feedback! I'd like to get #48598 ("buffer-naming collisions involving bouncers in ERC") up to snuff relatively soon. Would it make sense to petition emacs-devel for eyeballs at some point? Also, is there any way to try out some patches on EMBA CI? I have a feeling some of my tests that work locally and on GitLab.com's GCP runners may have to be tuned a bit for EMBA. (Or would these questions be better put to the build-automation folks?) Thanks. From debbugs-submit-bounces@debbugs.gnu.org Thu Mar 24 16:16:27 2022 Received: (at 54536) by debbugs.gnu.org; 24 Mar 2022 20:16:27 +0000 Received: from localhost ([127.0.0.1]:49492 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXTsh-0006Me-EC for submit@debbugs.gnu.org; Thu, 24 Mar 2022 16:16:27 -0400 Received: from mout.gmx.net ([212.227.17.21]:37021) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXTsd-0006MQ-LU for 54536@debbugs.gnu.org; Thu, 24 Mar 2022 16:16:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1648152974; bh=Pf99kGWFZ1bR/n8DUStRROiQS5bFbS6ReTe+rN6DNtM=; h=X-UI-Sender-Class:From:To:Cc:Subject:References:Date:In-Reply-To; b=XnvEslrBZLjhA62S/1JrC53TvT23+ushq/tHWGk0nSHIyHT8M4X6ZqnFXyzvorwoc lVcS8kEO/wPHUDQcqHI+hKH7hBsch4pEXyHmjbBYH3BUMS276etTme54KSko8cQLHW ED5hAR9kFOXa4YBx9+u4UQMbUUQqRIcTlQFvFiQ8= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from gandalf.gmx.de ([79.140.118.40]) by mail.gmx.net (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MNKlu-1nixHz43xa-00Oo2d; Thu, 24 Mar 2022 21:16:14 +0100 From: Michael Albinus To: "J.P." Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> <87ee2rb04e.fsf__35149.1299386666$1648151549$gmane$org@neverwas.me> Date: Thu, 24 Mar 2022 21:16:12 +0100 In-Reply-To: <87ee2rb04e.fsf__35149.1299386666$1648151549$gmane$org@neverwas.me> (J. P.'s message of "Thu, 24 Mar 2022 12:50:57 -0700") Message-ID: <8735j7jecz.fsf@gmx.de> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Provags-ID: V03:K1:IziMF4ARJhBQydO6tQDtEeWEe66fxE+lRUgQNen3u9bRRhUxi6t VcEoCERzerYAQxfw4lBZcMwjcvnQRxpBcXjYSaliYDAG9Wmj9WWlZw0lMyQlidM6L9XUrwE uIHsoxH0MhHKApHIkQAkAPfaVvjJoejl1epUmY6jZEaWrtnjwerRG1eJZcqY88Ksv2avscA LHqE7g75aG9bEvfYqJNpw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:7cNyLOBVNOI=:y8nMDjQa87wR6RtQl1RLIP rMsKenTJPAnkaOcnpmHfBPtFfsFC+Yi9vsDP++H/I+Qwr04inZnaXksEfkBVGC69YvSZTENY6 roiz7RRmLymfX7GcPr3fGLUeuel5AHp/juEdsU90iBgpb7J8BNufF/5eI711eu2D7P+WiUj1h 7bPPnE9Z3qSwdcw6PA/tGIl3ZbFrZB2XQwEWWpU/iHV9+T9Kyh2rHs/r9LbmvJTT0k5dBvIc4 F9XhLLx6/S0pqa7KEJuXIdMySu3vlY5nTry6BEbygqTrkfTfz/QgkvtHoKVfm+9MMc6KzWtdR 8R9zPn42en8C0HEiA0naOfd5Xuy1FjW0LrIbH8MyFcCqUi2RluM8mcQQ8/pXKgfWKLaHRyHz+ K0m4eqMI4LFEouo7on02VpGmic1kTyQ7ZdXV32dLmeKx3opVpZq9qLPPDSHqY3Bn6Z3W5euB1 oupdIBGIVTqVQFqASm7x01W5gzrkQA1kako6pEihSuLCI+9fzJgdai+pQB6yHK5Q1Fp1PEgb/ knKtvmgS88JsJR9hxbmFgfR6dJxXr6HG4P4AOGR/P69HJrJGr27uNwvj25Y9wwrzD9YdsXYrf Ss8buquboEQSMp770JouTJZFqm6QhM8OptFbwuiyfz2gOEd/MbpRxWnJ4ybUlwspQAadW4iuo BhSLTeSUMvh8dmjFuDugb5Lc3CMOIMESzEnh4gZ1/a0ZxpXrzIu4rwewQ/z3X6n4CAMqyX2rF khmVyy1I8efRkqBtMbfNcrfb1dlMKXxXPvFsXR5wx3k7qerOn3G/+h/KcbWRacCT0Wb6Bc3U5 DMS6e2/C88HusAoqOdZZsJwdpUPzvTG5nftKj4TcwkDw4/9LlOQvtkqxa9Kilv/dO92ObxLCU f6Jn+flQIpdHWCS7a5H1rdkbPdVDZqhQDDOZ8EoAxaFPrhWQYPb/qfNKoGfIYhQD4wBoDp3pT y2mx6e+Ai1iFZ/rJ6OMyDqmVQZr2PZ4TWPqbbD6V8aaT98FA3xttzA9jafmcj3wG+urcB45f+ OXvmWzmHw8t93Unu8DVsLfrNrtbxGnH8B0acY8tSgTC5MbELpG2pWSs6FsBq3sAC9IHx5DyFq DjCwJgRZ/ozdXk= X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 54536 Cc: Lars Ingebrigtsen , emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) "J.P." writes: Hi, > I'd like to get #48598 ("buffer-naming collisions involving bouncers in > ERC") up to snuff relatively soon. Would it make sense to petition > emacs-devel for eyeballs at some point? Also, is there any way to try > out some patches on EMBA CI? I have a feeling some of my tests that work > locally and on GitLab.com's GCP runners may have to be tuned a bit for > EMBA. (Or would these questions be better put to the build-automation > folks?) Thanks. On EMBA, also git branches run the CI tests. See file test/infra/gitlab-ci.yml: --8<---------------cut here---------------start------------->8--- - if: '$CI_COMMIT_BRANCH !~ /^(master|emacs|feature|fix)/' when: never --8<---------------cut here---------------end--------------->8--- So your branch name must start with one of these words. Best regards, Michael. From debbugs-submit-bounces@debbugs.gnu.org Thu Mar 24 19:39:08 2022 Received: (at 54536) by debbugs.gnu.org; 24 Mar 2022 23:39:08 +0000 Received: from localhost ([127.0.0.1]:49665 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXX2p-0003Ca-Rv for submit@debbugs.gnu.org; Thu, 24 Mar 2022 19:39:08 -0400 Received: from mail-108-mta12.mxroute.com ([136.175.108.12]:38043) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXX2n-0003C0-CF for 54536@debbugs.gnu.org; Thu, 24 Mar 2022 19:39:06 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta12.mxroute.com (ZoneMTA) with ESMTPSA id 17fbe4c27ae000fe85.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Thu, 24 Mar 2022 23:38:56 +0000 X-Zone-Loop: 23e841f0b2a8c0e0218d41fc1f37cdfa19efe2908955 X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=SFcOMhVeccS5nN0+1KeqRf5Hld0N1rLOTIIt+Jg7l7g=; b=bSpZKIFDQa1QMVixFlKjR0p8HI P46DYZPiw1cpzf3REJwDJ/1jDEB79Fj/NedFhi2OKiUmBbCLI9GIECpqwl0w1UxvUzyBvMcIROcXS KeM6muSCwM2ighonIe1uf5xK5kPb9tSi0JZUWHYJFwTAJdmzwlraqhyd+6duFClz+sxHMeEBwzKE9 F16+LzttwtbInXV0ca7thyG43ME3/Ttda4QxUy54C9SwWbgeSXxr1LT2pN+C3k705OAtq7+tVSRc7 LW/Zq0UmwLvE08O2yyVAE7Te3lrA0CH5qXbWHh2D/hfgqW/U1eaMciMvPFwIaed4f6mM3bYQT+sGM ORcKtK1Q==; From: "J.P." To: Michael Albinus Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> <87ee2rb04e.fsf__35149.1299386666$1648151549$gmane$org@neverwas.me> <8735j7jecz.fsf@gmx.de> Date: Thu, 24 Mar 2022 16:38:52 -0700 In-Reply-To: <8735j7jecz.fsf@gmx.de> (Michael Albinus's message of "Thu, 24 Mar 2022 21:16:12 +0100") Message-ID: <87tubm53ar.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: Lars Ingebrigtsen , emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi Michael, Michael Albinus writes: > So your branch name must start with one of these words. Thanks a lot for the explanation. Among those prefixes, "fix" seems the least misleading for my purposes, those being (1) rapid iteration toward a passing pipeline and (2) minimal distraction for others. Hopefully, there's already precedent for more ephemeral, fly-by-night "fix/*" branches. If so, and there's a prescribed naming scheme to that end (something like "fix/bug-48598-temp" or similar), perusing the remote refs hasn't revealed it. Regardless, I'll wait for a go-ahead before trying anything. Thanks again, J.P. From debbugs-submit-bounces@debbugs.gnu.org Fri Mar 25 11:29:58 2022 Received: (at 54536) by debbugs.gnu.org; 25 Mar 2022 15:29:58 +0000 Received: from localhost ([127.0.0.1]:52183 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXlt0-00013g-2u for submit@debbugs.gnu.org; Fri, 25 Mar 2022 11:29:58 -0400 Received: from quimby.gnus.org ([95.216.78.240]:42674) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXlsx-00013S-Me for 54536@debbugs.gnu.org; Fri, 25 Mar 2022 11:29:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=y50Zvsf1nFFMUP8OvXr3b9gKS+CmOyOu8io2H66uay4=; b=ja9EOj0u8byMxJhR6C8fWFQaG2 IC3ajqGw84MRWSesiSfWKSwQ9XOjPkPaeTMpnfL1Xv1dijmB8b19zpD3EiW03JvMJU+/M47fjtkrn JyoxFQVjFdurBMQe6GcPK6VG7y7zn+0WjZwypS8QBHuY0yruv6NcxvReq+0T0iKmw0Rc=; Received: from [84.212.220.105] (helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nXlso-0004JB-KR; Fri, 25 Mar 2022 16:29:48 +0100 From: Lars Ingebrigtsen To: "J.P." Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> <87ee2rb04e.fsf__35149.1299386666$1648151549$gmane$org@neverwas.me> <8735j7jecz.fsf@gmx.de> <87tubm53ar.fsf@neverwas.me> Date: Fri, 25 Mar 2022 16:29:46 +0100 In-Reply-To: <87tubm53ar.fsf@neverwas.me> (J. P.'s message of "Thu, 24 Mar 2022 16:38:52 -0700") Message-ID: <874k3mf3th.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: "J.P." writes: > Thanks a lot for the explanation. Among those prefixes, "fix" seems the > least misleading for my purposes, those being (1) rapid iteration toward > a passing pipeline and (2) minimal distraction fo [...] Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 54536 Cc: 54536@debbugs.gnu.org, emacs-erc@gnu.org, Michael Albinus X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) "J.P." writes: > Thanks a lot for the explanation. Among those prefixes, "fix" seems the > least misleading for my purposes, those being (1) rapid iteration toward > a passing pipeline and (2) minimal distraction for others. Hopefully, > there's already precedent for more ephemeral, fly-by-night "fix/*" > branches. If so, and there's a prescribed naming scheme to that end > (something like "fix/bug-48598-temp" or similar), perusing the remote > refs hasn't revealed it. Regardless, I'll wait for a go-ahead before > trying anything. Calling the branch fix/whatever is fine. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no From debbugs-submit-bounces@debbugs.gnu.org Fri Mar 25 11:31:36 2022 Received: (at 54536) by debbugs.gnu.org; 25 Mar 2022 15:31:36 +0000 Received: from localhost ([127.0.0.1]:52200 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXlua-00018x-E7 for submit@debbugs.gnu.org; Fri, 25 Mar 2022 11:31:36 -0400 Received: from quimby.gnus.org ([95.216.78.240]:42702) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXluY-00018k-Fz for 54536@debbugs.gnu.org; Fri, 25 Mar 2022 11:31:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=O+XCgErxTwRaXf70cmfrAwn8donqG2k4D9bLvuAlYAM=; b=kNULfIk6fg1AXxPohiqTynQZFQ BCptvYRijtZTzCElKiS+jam3XzNbqQGfmwAidjOLx9FvJ78Xs0zpvE/MAwbfY/Nb0hl9GI0EMeRYo awcYoQ3xyZUAkBunfn5FOzqzir2oUy4Kzbind7kAjmV/PzyKOMoZ19dKDBu0+UUAnQ2o=; Received: from [84.212.220.105] (helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nXluQ-0004MD-CF; Fri, 25 Mar 2022 16:31:28 +0100 From: Lars Ingebrigtsen To: "J.P." Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> <87ee2rb04e.fsf@neverwas.me> Date: Fri, 25 Mar 2022 16:31:25 +0100 In-Reply-To: <87ee2rb04e.fsf@neverwas.me> (J. P.'s message of "Thu, 24 Mar 2022 12:50:57 -0700") Message-ID: <87zgledp6a.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: "J.P." writes: > I'd like to get #48598 ("buffer-naming collisions involving bouncers in > ERC") up to snuff relatively soon. Would it make sense to petition > emacs-devel for eyeballs at some point? Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) "J.P." writes: > I'd like to get #48598 ("buffer-naming collisions involving bouncers in > ERC") up to snuff relatively soon. Would it make sense to petition > emacs-devel for eyeballs at some point? Sure, if you want to. I had a brief peek myself, but the patch series was so long that I didn't really have anything to say. :-/ -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no From debbugs-submit-bounces@debbugs.gnu.org Fri Mar 25 15:20:55 2022 Received: (at 54536) by debbugs.gnu.org; 25 Mar 2022 19:20:55 +0000 Received: from localhost ([127.0.0.1]:52462 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXpUU-0000gR-UI for submit@debbugs.gnu.org; Fri, 25 Mar 2022 15:20:55 -0400 Received: from mail-108-mta154.mxroute.com ([136.175.108.154]:40605) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXpUT-0000gD-Af for 54536@debbugs.gnu.org; Fri, 25 Mar 2022 15:20:53 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta154.mxroute.com (ZoneMTA) with ESMTPSA id 17fc286229d000fe85.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Fri, 25 Mar 2022 19:20:44 +0000 X-Zone-Loop: fc846c47a576acf7d9dd21926ff85c230070018d1d2e X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=1aSXPbavvrX3ZsbS1iK5H41YAS0QvhkjcV+MalkBPSs=; b=R79LOygvE30YT6qkiVatk6dOGb yWJQEU1idCgv7lzj5rUBZBSK2/SHvcxGC+icXmidgNPjQQwp/ptPwxchmsWQ2Wdmd72nGCuRhh0yY CT15tT/9I37xmCSOT1DKdSZhbEIl4LE2hKagLSLWbLRCYVo+Ukh3o7aMa0aUxxKq00HntyaJGscDz fFRlsDDpZeud5Idx44GB1S3geSRQKfe6+F1knrc0d4nLU8SB/oXAeG42VvwR3M8evw/5V5zEF2tp7 wzG+aQ7QLB6Tz+yECi2ba6PGdB1i3DB1fJl0B+QL8yaQBstyVE6uhPKWvt0ZnBE0FCzlFgaoNaLBv mDJEPkIg==; From: "J.P." To: Lars Ingebrigtsen Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> <87ee2rb04e.fsf@neverwas.me> <87zgledp6a.fsf@gnus.org> Date: Fri, 25 Mar 2022 12:20:41 -0700 In-Reply-To: <87zgledp6a.fsf@gnus.org> (Lars Ingebrigtsen's message of "Fri, 25 Mar 2022 16:31:25 +0100") Message-ID: <87lewx3kl2.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Lars Ingebrigtsen writes: > "J.P." writes: > >> I'd like to get #48598 ("buffer-naming collisions involving bouncers in >> ERC") up to snuff relatively soon. Would it make sense to petition >> emacs-devel for eyeballs at some point? > > Sure, if you want to. I had a brief peek myself, but the patch series > was so long that I didn't really have anything to say. :-/ Thanks for the peek. Your impression is more than fair. I think for now I'll try soliciting specific questions, perhaps via top-level replies to that bug but with subject headers changed to reflect whatever's being posed (while also Cc-ing various persons where appropriate). And in cases where a question may have broader relevance, I'll hit up help-gnu-emacs first/instead. From debbugs-submit-bounces@debbugs.gnu.org Fri Mar 25 15:23:26 2022 Received: (at 54536) by debbugs.gnu.org; 25 Mar 2022 19:23:26 +0000 Received: from localhost ([127.0.0.1]:52480 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXpWw-0000m6-8C for submit@debbugs.gnu.org; Fri, 25 Mar 2022 15:23:26 -0400 Received: from mail-108-mta119.mxroute.com ([136.175.108.119]:42639) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nXpWs-0000lc-5R for 54536@debbugs.gnu.org; Fri, 25 Mar 2022 15:23:22 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta119.mxroute.com (ZoneMTA) with ESMTPSA id 17fc288664e000fe85.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Fri, 25 Mar 2022 19:23:13 +0000 X-Zone-Loop: a7ba8173ef6bddd7b040771e7bf5a365d4e41ab0e728 X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=nWqfHroeCmTnpUfGBFfUG2TYM++0/WcIw8/jFdiewww=; b=VB36m1B6RrYzkU2rE6cKaoxeCJ nh2rDI03LGzwXB4Q/qstuG66nXx15C7wHay7S1vYnecKFzChQoBcZS1foD8uJNJ0J6Qk87q5ISktj tqN5pTvzDBAYx5doVNt1unIJw27tV06GrfbR7MVSv0CYEuxk43VVqYWYxYj7fbcgVzLFFWZFXzQNa 7SKsrobx0xCnjSRz64qPd9w8poKUm1dTS5LQ/Xg/zmV/sZB07XgOhRVbyii+eHWn3yRJZbv7RhGfY YXUF892CL/y2NJxI2lQxPrm8/cXT1LZ6NTVVc4iDvOY/EssXA76D/8dbnxjZf7CFEvxhUzOCqibin oXkwm+rA==; From: "J.P." To: Lars Ingebrigtsen Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> <87ee2rb04e.fsf__35149.1299386666$1648151549$gmane$org@neverwas.me> <8735j7jecz.fsf@gmx.de> <87tubm53ar.fsf@neverwas.me> <874k3mf3th.fsf@gnus.org> Date: Fri, 25 Mar 2022 12:23:10 -0700 In-Reply-To: <874k3mf3th.fsf@gnus.org> (Lars Ingebrigtsen's message of "Fri, 25 Mar 2022 16:29:46 +0100") Message-ID: <87ee2p3kgx.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: 54536@debbugs.gnu.org, emacs-erc@gnu.org, Michael Albinus X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Lars Ingebrigtsen writes: > Calling the branch fix/whatever is fine. Thanks. BTW, I think these can go: refs/heads/features/erc-message-tags refs/heads/fix/bug-34657-erc-hooks Is it customary to contact the authors before deleting? From debbugs-submit-bounces@debbugs.gnu.org Sat Mar 26 12:44:48 2022 Received: (at 54536) by debbugs.gnu.org; 26 Mar 2022 16:44:48 +0000 Received: from localhost ([127.0.0.1]:54617 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nY9Wy-0002Ku-CL for submit@debbugs.gnu.org; Sat, 26 Mar 2022 12:44:48 -0400 Received: from quimby.gnus.org ([95.216.78.240]:54976) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nY9Ww-0002Kg-Sa for 54536@debbugs.gnu.org; Sat, 26 Mar 2022 12:44:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=sT78at6y285yDWtPhOk8/P7H5fVCJz6+KMWMdLYOY28=; b=Ba49QXMqEl8p2U4j5T/4fdSDCd dbaRc8eQdAUZnkhWwaLN5d/M+9o7qFERttmR1F798UDLTuIKi4Mdv/irmHpwiCAPzpGj0nPhfSTAL MMlLAjc62nWEatQ80QjcwreTWI4ASTN+GgRZLF2p2vZ8H55BNXEWju7FynpynkQlns8w=; Received: from [84.212.220.105] (helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nY9Wo-00017q-5Y; Sat, 26 Mar 2022 17:44:40 +0100 From: Lars Ingebrigtsen To: "J.P." Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <87czic93sa.fsf@gnus.org> <87ee2rb04e.fsf__35149.1299386666$1648151549$gmane$org@neverwas.me> <8735j7jecz.fsf@gmx.de> <87tubm53ar.fsf@neverwas.me> <874k3mf3th.fsf@gnus.org> <87ee2p3kgx.fsf@neverwas.me> Date: Sat, 26 Mar 2022 17:44:37 +0100 In-Reply-To: <87ee2p3kgx.fsf@neverwas.me> (J. P.'s message of "Fri, 25 Mar 2022 12:23:10 -0700") Message-ID: <87bkxsd5oq.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: "J.P." writes: > BTW, I think these can go: > > refs/heads/features/erc-message-tags > refs/heads/fix/bug-34657-erc-hooks > > Is it customary to contact the authors before deleting? If the branches have been merged (or their contents have been applied to the trunk otherwise), it's OK to delete them. If not, it's better to contact the authors first. Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 54536 Cc: 54536@debbugs.gnu.org, emacs-erc@gnu.org, Michael Albinus X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) "J.P." writes: > BTW, I think these can go: > > refs/heads/features/erc-message-tags > refs/heads/fix/bug-34657-erc-hooks > > Is it customary to contact the authors before deleting? If the branches have been merged (or their contents have been applied to the trunk otherwise), it's OK to delete them. If not, it's better to contact the authors first. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no From debbugs-submit-bounces@debbugs.gnu.org Sun Apr 03 15:44:54 2022 Received: (at 54536) by debbugs.gnu.org; 3 Apr 2022 19:44:54 +0000 Received: from localhost ([127.0.0.1]:49600 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nb69e-0003qI-H8 for submit@debbugs.gnu.org; Sun, 03 Apr 2022 15:44:54 -0400 Received: from mail-108-mta149.mxroute.com ([136.175.108.149]:34735) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nb69b-0003pt-Tn for 54536@debbugs.gnu.org; Sun, 03 Apr 2022 15:44:52 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta149.mxroute.com (ZoneMTA) with ESMTPSA id 17ff0f551b9000fe85.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Sun, 03 Apr 2022 19:44:43 +0000 X-Zone-Loop: d4d0e64bb61567b17bfb221b74bccbb5551e5a6d8a55 X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=jV1DJuDtsPIXmlCO0JIyVuIsE5opJgs7T6idCIGa74c=; b=YnSEV1kIfxmQixxd/GUqHnWXAA XSYZzHgDjvaP7IkT2UiYg0NHtXm5bKxlLUlywh8YbGgouDqnr/HU7uffTjaDEYlHBxabOovhdqZ4h Mh5TkPOadaLrnf5pWJLSgcwgX2WpTMp5fHjWbZ0zKZo5GAvvKJmyEZ16pQniLqxmJ54lG4KINcWws W4eqKui8jaYPAborzxCt6dDdLeuNoF/kAoH95Ev3HGJayp9iAmEwNoC1EHRWqqy0RiIyMltxjhUJ1 l6LOZUdA8/7xFsFbmi+DOCeXX11TDa+x49Un9c3CiEGvx9iSwFYGrZnOduJd1ipG3kHRaGyXncGkN /Xoy9zWg==; From: "J.P." To: Matheus Fillipe Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: Date: Sun, 03 Apr 2022 12:44:39 -0700 In-Reply-To: (Matheus Fillipe's message of "Sat, 2 Apr 2022 19:11:25 -0300") Message-ID: <87y20m7xzs.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Matheus Fillipe writes: > I've been testing this and as an evil-mode user I had a problem that > whenever I paste something or sometimes just out of the blue I would > send one empty line after my message. After a few hours using erc this > it only happened once but Im not able to reproduce it so... I think > this is a great addition and it solves my problem! Appreciate the feedback! (Although, we ought not settle for "it only happened once," if we can help it.) A few silly questions: 1. In your testing, what was the value of `erc-send-whitespace-lines'? 2. Do you have any unusual bindings or minor modes going (other than Evil)? Just asking to try and gauge whether it's worth doing something like an emacs -Q. 3. How do you send input normally? For example: switch to insert state, type stuff after the prompt, hit RET. Just asking in case I try recreating your setup. 4. Are you willing to keep testing it? If so and it happens again, can you try a `view-lossage' and maybe also a `report-emacs-bug', and just copy-paste all the generated facts into a reply? BTW, I guess the "reply" button on the MHonArc-generated bug-gnu-emacs pages doesn't do a "reply all" (or else there's some trick I don't know about to get it to include Cc participants). From debbugs-submit-bounces@debbugs.gnu.org Sun Apr 03 16:56:13 2022 Received: (at 54536) by debbugs.gnu.org; 3 Apr 2022 20:56:13 +0000 Received: from localhost ([127.0.0.1]:49668 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nb7Ge-0005gD-EV for submit@debbugs.gnu.org; Sun, 03 Apr 2022 16:56:13 -0400 Received: from mail-oi1-f175.google.com ([209.85.167.175]:36840) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nb6dH-0004el-34 for 54536@debbugs.gnu.org; Sun, 03 Apr 2022 16:15:31 -0400 Received: by mail-oi1-f175.google.com with SMTP id z8so8182937oix.3 for <54536@debbugs.gnu.org>; Sun, 03 Apr 2022 13:15:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=date:from:to:cc:message-id:in-reply-to:references:subject :mime-version; bh=IFHqqJe35WEIH6C8WR7AOwKUvvCNmtXRNyNyhxk4wNA=; b=HGm+h+SrgAV+wRK/mWOIdgJSwU3d5ckuqWTFV9qrL+ZSR1e59yXfFL0jusYmYxI0oZ Ywr8z+/unjuFiPRr6DyBc9+ffS1jqPLO6p2IltE7Vdxr4tn/Bx49n1g6CMRpSMGMdIkX 2GsfQ8DT2CTU/Coj5+nXTlcUZeZE8dhOdLKk9y+7RayuK06VOruQFvw/ZhXFUmEf46Vt lbnpfBtASSGOdOgMsSfeJ/Bu+2hQYYcvXQIAEGwXwnd7AePepCEfLSo4nEpxwAIuKbb6 56+lDQjeFmTPL+CXE2gRMx+3uAtFeQ6i/PrZc/ST8KF3lkAbHszdzEhd7tFOErVI0RwB Ob5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:message-id:in-reply-to :references:subject:mime-version; bh=IFHqqJe35WEIH6C8WR7AOwKUvvCNmtXRNyNyhxk4wNA=; b=HhAEp+Rguod/FfZdLknTKKsBOXL+CxdQ2QQJmgF1dr9hkge9cPLcCWw3wVZHpGJeWO /OWl9zqMdMnC2Z2/Iui0+Llohxpxa/fNJubKlAd4hmsWs9xtk9iR4WLUHWYnJ1Xyvsio aki35jAMYldiSZyapmouogkanyHw/BFRKWhZhjlFB84QIgQFdtng7yoYef9VWfdBkZzV 9iVGqEBCzxrykMJHmT+5h3e40irQ0miWs2Gujq9z2HxQ9Fp/+OggEsHaZYVz8L9LgWOT HonSk3/H53KsjfjWmDHK2iDxKWfmdXNyuok5ulHb/r95F9ofZrrzfsO1EMKT+/Fy5yrz CKkg== X-Gm-Message-State: AOAM533uMCNed63RR3gjlirEzP5Gwulwm2UFw2Bs7uZvJiMfzilQP5BB zyyPvwN5fKESja1KuZ7Wgh09XTiozcbf6Q== X-Google-Smtp-Source: ABdhPJzQA6jnvbiBtZQjt+/PIEp/A9GhVDzFQF/ng+zbFyNyBHz670NIqE+XLRKUEdxooRjADIr+BA== X-Received: by 2002:a05:6808:199c:b0:2da:854a:204d with SMTP id bj28-20020a056808199c00b002da854a204dmr9119235oib.184.1649016925371; Sun, 03 Apr 2022 13:15:25 -0700 (PDT) Received: from arch-matheus (179-189-87-107.goldnettelecom.com.br. [179.189.87.107]) by smtp.gmail.com with ESMTPSA id o185-20020acabec2000000b002ecf1218c53sm3462765oif.15.2022.04.03.13.15.23 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Sun, 03 Apr 2022 13:15:24 -0700 (PDT) Date: Sun, 3 Apr 2022 17:15:21 -0300 From: Matheus Fillipe To: "J.P." Message-ID: In-Reply-To: <87y20m7xzs.fsf@neverwas.me> References: <87y20m7xzs.fsf@neverwas.me> Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input X-Mailer: Mailspring MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="624a0059_18b1eebd_20f272" X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 X-Mailman-Approved-At: Sun, 03 Apr 2022 16:56:10 -0400 Cc: "=?utf-8?Q?emacs-erc=40gnu.org?=" , "=?utf-8?Q?54536=40debbugs.gnu.org?=" <54536@debbugs.gnu.org> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --624a0059_18b1eebd_20f272 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline So far the patches seem to have fixed the issue I long had sending empty lines randomly. Here are my replies to your questions. 1) erc-send-whitespace-lines was set to nil 2) Hmm no I don't have nothing quite unusual on erc that i can think of now. I have erc-nl-nicks. 3) Yes exactly nothing unusual about that. 4) I will since it seems to have "fixed" the issue so far. I will keep that in mind in case it happens again. That one case was the only until now. Didn't happen again and I've tried to reproduce but would never happen, so I'm not sure if it really matters. I will keep testing. On Apr 3 2022, at 4:44 pm, J.P. wrote: > Matheus Fillipe writes: > > > I've been testing this and as an evil-mode user I had a problem that > > whenever I paste something or sometimes just out of the blue I would > > send one empty line after my message. After a few hours using erc this > > it only happened once but Im not able to reproduce it so... I think > > this is a great addition and it solves my problem! > > Appreciate the feedback! (Although, we ought not settle for "it > only happened once," if we can help it.) A few silly questions: > > 1. In your testing, what was the value of `erc-send-whitespace-lines'? > 2. Do you have any unusual bindings or minor modes going (other than > Evil)? Just asking to try and gauge whether it's worth doing > something like an emacs -Q. > > 3. How do you send input normally? For example: switch to insert state, > type stuff after the prompt, hit RET. Just asking in case I try > recreating your setup. > > 4. Are you willing to keep testing it? If so and it happens again, can > you try a `view-lossage' and maybe also a `report-emacs-bug', and > just copy-paste all the generated facts into a reply? > > BTW, I guess the "reply" button on the MHonArc-generated bug-gnu-emacs > pages doesn't do a "reply all" (or else there's some trick I don't know > about to get it to include Cc participants). > --624a0059_18b1eebd_20f272 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline
So far the patches seem to have fixed the issue I long had sending e= mpty lines randomly.

Here are my replies to your questions.=
1) erc-send-whitespace-lines was set to nil
2) Hmm n= o I don't have nothing quite unusual on erc that i can think of now. I ha= ve erc-nl-nicks.
3) Yes exactly nothing unusual about that.
4) I will since it seems to have =22fixed=22 the issue so far. I w= ill keep that in mind in case it happens again.

That one ca= se was the only until now. Didn't happen again and I've tried to reproduc= e but would never happen, so I'm not sure if it really matters. I will ke= ep testing.
On Apr 3 = 2022, at 4:44 pm, J.P. <jp=40neverwas.me> wrote:
<= div>
Matheus =46illipe <matheusfillipeag=40gmail.com> writes:
> I've been testing this and as an evil-mode user I had a= problem that
> whenever I paste something or sometimes just= out of the blue I would
> send one empty line after my mess= age. After a few hours using erc this
> it only happened onc= e but Im not able to reproduce it so... I think
> this is a = great addition and it solves my problem=21

Appreciate the f= eedback=21 (Although, we ought not settle for =22it
only happen= ed once,=22 if we can help it.) A few silly questions:

1. I= n your testing, what was the value of =60erc-send-whitespace-lines'=3F
2. Do you have any unusual bindings or minor modes going (oth= er than
Evil)=3F Just asking to try and gauge whether it's wort= h doing
something like an emacs -Q.

3. How do you= send input normally=3F =46or example: switch to insert state,
= type stuff after the prompt, hit RET. Just asking in case I try
recreating your setup.

4. Are you willing to keep testing = it=3F If so and it happens again, can
you try a =60view-lossage= ' and maybe also a =60report-emacs-bug', and
just copy-paste al= l the generated facts into a reply=3F

BTW, I guess the =22r= eply=22 button on the MHonArc-generated bug-gnu-emacs
pages doe= sn't do a =22reply all=22 (or else there's some trick I don't know
<= div>about to get it to include Cc participants).
--624a0059_18b1eebd_20f272-- From debbugs-submit-bounces@debbugs.gnu.org Fri Apr 22 23:18:20 2022 Received: (at 54536) by debbugs.gnu.org; 23 Apr 2022 03:18:21 +0000 Received: from localhost ([127.0.0.1]:54966 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ni6Hq-0004bJ-R2 for submit@debbugs.gnu.org; Fri, 22 Apr 2022 23:18:20 -0400 Received: from mail-108-mta45.mxroute.com ([136.175.108.45]:45065) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ni6Hl-0004aw-8C for 54536@debbugs.gnu.org; Fri, 22 Apr 2022 23:18:17 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta45.mxroute.com (ZoneMTA) with ESMTPSA id 180546d2b74000fe85.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Sat, 23 Apr 2022 03:18:02 +0000 X-Zone-Loop: 5ff72b196fd821b648407ef29be7cc23ccebd0ab9cfa X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=Qg2aKAxOr8VzRoDy/cfUHI8zbwJqW/jPYX5Q5LTWNIM=; b=S2Vo7W8w3LVXq5U+WytJQmJf4L qmcFOphPllQGD9PTD2b4oN2EWb/oTdKVVDQ5i6LMnYJiwctj3MVKVbSYZPNvyJ8hkiqa3GaRcOhXj 7kLnIyqb4vV0Cfdgd2GkuLd1iT7c/jVVVq69pbM3hk5MD2TATjjApqiAgmJgn0BW+tU0c3000vLpU HTvN5+Dxpr58Rv1I6Hfmz6s1/O3OR9DE5IrGeL2SupaLm5XmfMTTLNgxQMQrvBGG7Pa/7Rh5mbB0O 1PV+gtlFTcfgWlvIJZXIfAmzELc0sjFqeILqNf6bdNRkWTgQcymsorZW4UTooHaBocXu7IIBhWbmo 5xkF1+Gg==; From: "J.P." To: 54536@debbugs.gnu.org Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> Date: Fri, 22 Apr 2022 20:17:58 -0700 In-Reply-To: <87k0ckg5pn.fsf@neverwas.me> (J. P.'s message of "Wed, 23 Mar 2022 06:26:44 -0700") Message-ID: <87o80sebdl.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --=-=-= Content-Type: text/plain v3. Except for a subtle change involving compatibility, there aren't any real differences in behavior. "J.P." writes: > 4. Should slash commands, like /MSG be allowed to lead a multiline > submission? > > This patch says no, still choosing to interpret commands as always > consisting of a single line. This description is rather sloppy and ambiguous, so I have attempted to clarify things below (underscores are spaces). The subtle compat change happens between the first two examples. Basically, when the option `erc-send-whitespace-lines' is active and trailing blank lines are present, the new (v3) iteration of this patch no longer interprets slash commands but instead just sends lines as text. This more closely mirrors traditional ERC behavior. (I suppose we could also have an option to go the other, v2 route, if people want.) Patch v2 (previous) ~~~~~~~~~~~~~~~~~~~ - `erc-send-whitespace-lines' ON - All trailing blanks stripped - Command interpreted - Nothing inserted (unless echo-message cap negotiated, coming in #49860) input: . ERC> /msg #chan hi . . [RET] I/O: -> PRIVMSG #chan :hi shown: (nothing) Patch v3 (this) ~~~~~~~~~~~~~~~ - `erc-send-whitespace-lines' ON - Trailing blanks stripped - Command not interpreted input: . ERC> /msg #chan hi . . [RET] I/O: -> PRIVMSG #chan :/msg #chan hi shown: /msg #chan hi The rest are just included for good measure, but none has changed: HEAD ~~~~ - `erc-send-whitespace-lines' ON or OFF - Trailing blanks not stripped or padded - Command not interpreted - Protocol violation (my fault from #50008, not in 5.4.1 or 28) input: . ERC> /msg #chan hi . [RET] I/O: -> PRIVMSG #chan :/msg #chan hi -> PRIVMSG #chan : <- :irc.foonet.org 412 me :No text to send shown: . /msg #chan hi . . *** No text to send Patch v2 and v3 ~~~~~~~~~~~~~~~ - `erc-send-whitespace-lines' OFF - ding, input remains, echo area says "Blank line - ignoring ..." input: . ERC> /msg #chan hi . _* [RET] I/O: (nothing) shown: (nothing) All (HEAD, v2, v3) ~~~~~~~~~~~~~~~~~~ - `erc-send-whitespace-lines' ON (or OFF when old) - Command not interpreted - User-padded trailing blank preserved input: . ERC > /msg #chan hi . _ [RET] I/O: -> PRIVMSG #chan :/msg #chan hi -> PRIVMSG #chan :_ shown: /msg #chan hi - `erc-send-whitespace-lines' ON (or OFF when old) - Command not interpreted - Intervening blank padded input: . ERC> /msg #chan hi . . again [RET] I/O: -> PRIVMSG #chan :/msg #chan hi -> PRIVMSG #chan :_ -> PRIVMSG #chan :again shown: /msg #chan hi again --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v2-v3.diff >From b58ad0d7c08d0002276f261d508cfca4056cc9ac Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 22 Apr 2022 17:35:46 -0700 Subject: [PATCH 0/4] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (4): Fix regression in erc-send-input-line Add some ERC test helpers Improve ERC's handling of multiline prompt input [SQUASH-ME] Add hook for splitting multiline input in ERC lisp/erc/erc.el | 160 +++++++++++++++++++------- test/lisp/erc/erc-tests.el | 229 +++++++++++++++++++++++++++++++++++-- 2 files changed, 337 insertions(+), 52 deletions(-) Interdiff: diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index ab786c1989..e2fe5c6476 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1040,7 +1040,7 @@ erc-send-pre-hook :type 'hook) (make-obsolete-variable 'erc-send-pre-hook 'erc-pre-send-functions "27.1") -(defcustom erc-pre-send-functions '(erc-discard-trailing-multiline-nulls) +(defcustom erc-pre-send-functions nil "Special hook run to possibly alter the string that is sent. The functions are called with one argument, an `erc-input' struct, and should alter that struct. @@ -1052,7 +1052,26 @@ erc-pre-send-functions `sendp': Whether the string should be sent to the irc server." :group 'erc :type 'hook - :package-version '(ERC . "5.4.1")) ; FIXME increment upon publishing to ELPA + :version "27.1") + +(defcustom erc-pre-send-split-functions '(erc-discard-trailing-multiline-nulls) + "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. + +The struct has five slots: + + `string': The input string delivered by `erc-pre-send-functions'. + `insertp': Whether the lines should be inserted into the ERC buffer. + `sendp': Whether the lines should be sent to the IRC server. + `lines': A list of lines to be sent, each one a `string'. + `cmdp': Whether to interpret the input as a command, like /ignore. + +The `string' field is effectively read-only. When `cmdp' is non-nil, +all but the first line will be discarded." + :group 'erc + :type 'hook + :package-version '(ERC . "5.4.1")) (defvar erc-insert-this t "Insert the text into the target buffer or not. @@ -5556,22 +5575,15 @@ erc--input-line-delim-regexp (defun erc--blank-in-multiline-input-p (string) "Detect whether STRING contains any blank lines. -When `erc-send-whitespace-lines' is in effect and the input is not a -\"command\", like /msg, return nil if the input is multiline or the line -is non-empty. When `erc-send-whitespace-lines' is nil, return non-nil -when any line is empty or consists of one or more spaces, tabs, or -form-feeds." +When `erc-send-whitespace-lines' is in effect, return nil if the input +is multiline or the line is non-empty. When `erc-send-whitespace-lines' +is nil, return non-nil when any line is empty or consists of one or more +spaces, tabs, or form-feeds." (catch 'return - (let ((lines (split-string string erc--input-line-delim-regexp)) - (cmdp '--?--)) + (let ((lines (split-string string erc--input-line-delim-regexp))) (dolist (line lines) (when (if erc-send-whitespace-lines - (and (string= line "") - (or (null (cdr lines)) ; string is one line - (if (eq cmdp '--?--) ; string is /cmd - (setq cmdp (string-match erc-command-regexp - (car lines))) - cmdp))) + (and (string= line "") (null (cdr lines))) (string-match (rx bot (* (in " \t\f")) eot) line)) (throw 'return t)))))) @@ -5579,8 +5591,13 @@ erc-discard-trailing-multiline-nulls "Ensure last line of `erc-input' STATE's string is non-null. But only when `erc-send-whitespace-lines' is non-nil." (when erc-send-whitespace-lines - (cl-callf (lambda (s) (string-trim-right s "[\r\n]+")) - (erc-input-string state)))) + (when (string-match "[\r\n]+\\'" (erc-input-string state)) + (setf (erc-input-split-lines state) + (split-string (substring (erc-input-string state) + 0 + (match-beginning 0)) + erc--input-line-delim-regexp) + (erc-input-split-cmdp state) nil)))) (defun erc-check-prompt-input-for-multiline-blanks (string) "Return non-nil when multiline prompt input has blank lines." @@ -5671,6 +5688,9 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) +(cl-defstruct (erc-input-split (:include erc-input)) + lines cmdp) + (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. @@ -5700,26 +5720,27 @@ erc-send-input :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 ((string (erc-input-string state))) - (if (or (if (>= emacs-major-version 28) - (string-search "\n" string) - (string-match "\n" string)) - (not (string-match erc-command-regexp string))) - (mapc - (lambda (line) - (mapc - (lambda (line) - ;; Insert what has to be inserted for this. - (when (erc-input-insertp state) - (erc-display-msg line)) - (erc-process-input-line (concat line "\n") - (null erc-flood-protect) t)) - (or (and erc-flood-protect (erc-split-line line)) - (list line)))) - (split-string string erc--input-line-delim-regexp)) - (erc-process-input-line (concat string "\n") t nil)) + 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) + (dolist (line lines) + (dolist (line (or (and erc-flood-protect (erc-split-line line)) + (list line))) + (when (erc-input-insertp state) + (erc-display-msg line)) + (erc-process-input-line (concat line "\n") + (null erc-flood-protect) t)))) t))))) ;; (defun erc-display-command (line) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 53461accbc..3746f4862e 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -330,9 +330,9 @@ erc--blank-in-multiline-input-p (ert-info ("With `erc-send-whitespace-lines'") (let ((erc-send-whitespace-lines t)) (should (erc--blank-in-multiline-input-p "")) - (should (erc--blank-in-multiline-input-p "/msg a\n")) ; likely oops - (should (erc--blank-in-multiline-input-p "/msg a\n\nb")) ; "" not allowed + (should-not (erc--blank-in-multiline-input-p "/msg a\n")) ; real /cmd (should-not (erc--blank-in-multiline-input-p "a\n\nb")) ; "" allowed + (should-not (erc--blank-in-multiline-input-p "/msg a\n\nb")) ; non-/cmd (should-not (erc--blank-in-multiline-input-p " ")) (should-not (erc--blank-in-multiline-input-p "\t")) (should-not (erc--blank-in-multiline-input-p "a\nb")) @@ -358,121 +358,140 @@ erc--blank-in-multiline-input-p (should-not (erc--blank-in-multiline-input-p "a\nb")) (should-not (erc--blank-in-multiline-input-p "a\r\nb"))) -(defmacro erc-tests--with-process-input-spy (calls-var &rest body) - (declare (indent 1)) - `(with-current-buffer (get-buffer-create "FakeNet") - (let ((erc-pre-send-functions +(defun erc-tests--with-process-input-spy (test) + (with-current-buffer (get-buffer-create "FakeNet") + (let* ((erc-pre-send-functions (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now (inhibit-message noninteractive) (erc-server-current-nick "tester") (erc-last-input-time 0) erc-accidental-paste-threshold-seconds - ,calls-var) - (cl-letf (((symbol-function 'erc-process-input-line) - (lambda (&rest r) (push r ,calls-var))) - ((symbol-function 'erc-server-buffer) - (lambda () (current-buffer)))) - (erc-tests--send-prep) - ,@body)) - (when noninteractive (kill-buffer)))) + ;; + calls) + (cl-letf (((symbol-function 'erc-process-input-line) + (lambda (&rest r) (push r calls))) + ((symbol-function 'erc-server-buffer) + (lambda () (current-buffer)))) + (erc-tests--send-prep) + (funcall test (lambda () (pop calls))))) + (when noninteractive (kill-buffer)))) (ert-deftest erc-check-prompt-input-functions () - (erc-tests--with-process-input-spy calls - - (ert-info ("Errors when point not in prompt area") ; actually just dings - (insert "/msg #chan hi") - (forward-line -1) - (let ((e (should-error (erc-send-current-line)))) - (should (equal "Point is not in the input area" (cadr e)))) - (goto-char (point-max)) - (ert-info ("Input remains untouched") - (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) - - (ert-info ("Errors when no process running") - (let ((e (should-error (erc-send-current-line)))) - (should (equal "ERC: No process running" (cadr e)))) - (ert-info ("Input remains untouched") - (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) - - (ert-info ("Errors when line contains empty newline") - (erc-bol) - (delete-region (point) (point-max)) - (insert "one\n") - (let ((e (should-error (erc-send-current-line)))) - (should (equal "Blank line - ignoring..." (cadr e)))) - (goto-char (point-max)) - (ert-info ("Input remains untouched") - (should (save-excursion (goto-char erc-input-marker) - (looking-at "one\n"))))) - - (should (= 0 erc-last-input-time)) - (should-not calls))) + (erc-tests--with-process-input-spy + (lambda (next) + + (ert-info ("Errors when point not in prompt area") ; actually just dings + (insert "/msg #chan hi") + (forward-line -1) + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Point is not in the input area" (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when no process running") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "ERC: No process running" (cadr e)))) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when line contains empty newline") + (erc-bol) + (delete-region (point) (point-max)) + (insert "one\n") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Blank line - ignoring..." (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (goto-char erc-input-marker) + (looking-at "one\n"))))) + + (should (= 0 erc-last-input-time)) + (should-not (funcall next))))) ;; These also indirectly tests `erc-send-input' (ert-deftest erc-send-current-line () - (erc-tests--with-process-input-spy calls - - (erc-tests--set-fake-server-process "sleep" "1") - (should (= 0 erc-last-input-time)) - - (ert-info ("Simple command") - (insert "/msg #chan hi") - (erc-send-current-line) - (ert-info ("Prompt restored") - (forward-line 0) - (should (looking-at-p erc-prompt))) - (ert-info ("Input cleared") - (erc-bol) - (should (eq (point) (point-max)))) - ;; Commands are forced (no flood protection) - (should (equal (pop calls) '("/msg #chan hi\n" t nil)))) - - (ert-info ("Simple non-command") - (insert "hi") - (erc-send-current-line) - (should (eq (point) (point-max))) - (should (save-excursion (forward-line -1) - (search-forward " hi"))) - ;; Non-ommands are forced only when `erc-flood-protect' is nil - (should (equal (pop calls) '("hi\n" nil t)))) - - (should (consp erc-last-input-time)))) + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (should (= 0 erc-last-input-time)) + + (ert-info ("Simple command") + (insert "/msg #chan hi") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (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)))) + + (ert-info ("Simple non-command") + (insert "hi") + (erc-send-current-line) + (should (eq (point) (point-max))) + (should (save-excursion (forward-line -1) + (search-forward " hi"))) + ;; Non-ommands are forced only when `erc-flood-protect' is nil + (should (equal (funcall next) '("hi\n" nil t)))) + + (should (consp erc-last-input-time))))) (ert-deftest erc-send-whitespace-lines () - (erc-tests--with-process-input-spy calls - - (erc-tests--set-fake-server-process "sleep" "1") - (setq-local erc-send-whitespace-lines t) - - (ert-info ("Multiline hunk with blank line correctly split") - (insert "one\n\ntwo") - (erc-send-current-line) - (ert-info ("Prompt restored") - (forward-line 0) - (should (looking-at-p erc-prompt))) - (ert-info ("Input cleared") - (erc-bol) - (should (eq (point) (point-max)))) - (should (equal (pop calls) '("two\n" nil t))) - (should (equal (pop calls) '("\n" nil t))) - (should (equal (pop calls) '("one\n" nil t)))) - - (ert-info ("Multiline hunk with trailing blank filtered") - (insert "hi\n") - (erc-send-current-line) - (ert-info ("Input cleared") - (erc-bol) - (should (eq (point) (point-max)))) - (should (equal (pop calls) '("hi\n" nil t))) - (should-not (pop calls))) - - (ert-info ("Multiline hunk with trailing whitespace not filtered") - (insert "there\n ") - (erc-send-current-line) - (should (equal (pop calls) '(" \n" nil t))) - (should (equal (pop calls) '("there\n" nil t))) - (should-not (pop calls))))) + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (setq-local erc-send-whitespace-lines t) + + (ert-info ("Multiline hunk with blank line correctly split") + (insert "one\n\ntwo") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("two\n" nil t))) + (should (equal (funcall next) '("\n" nil t))) + (should (equal (funcall next) '("one\n" nil t)))) + + (ert-info ("Multiline hunk with trailing newline filtered") + (insert "hi\n") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing carriage filtered") + (insert "hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline command with trailing blank filtered") + (insert "/msg #chan hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("/msg #chan hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing whitespace not filtered") + (insert "there\n ") + (erc-send-current-line) + (should (equal (funcall next) '(" \n" nil t))) + (should (equal (funcall next) '("there\n" nil t))) + (should-not (funcall next)))))) ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Fix-regression-in-erc-send-input-line.patch >From aa381598d4ab452bf1a40269cd7c728e3c113a1b Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 19:21:57 -0700 Subject: [PATCH 1/4] Fix regression in erc-send-input-line * lisp/erc/erc.el (erc-send-input-line): Restore remedial single-space padding to ensure empty messages typed at the prompt without an explicit /msg aren't rejected by the server. This behavior is only noticeable when `erc-send-whitespace-lines' is active. * test/lisp/erc/erc-tests.el (erc-process-input-line): Add trailing newline to more correctly simulate how it's actually called by `erc-send-input'. (Bug#50008) --- lisp/erc/erc.el | 2 ++ test/lisp/erc/erc-tests.el | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 52fe106f2d..d8ef62cf93 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2817,6 +2817,8 @@ erc-send-input-line-function (defun erc-send-input-line (target line &optional force) "Send LINE to TARGET." + (when (string= line "\n") + (setq line " \n")) (erc-message "PRIVMSG" (concat target " " line) force)) (defun erc-get-arglist (fun) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 520f10dd4e..10e3c16dfc 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -340,19 +340,19 @@ erc-process-input-line (ert-info ("Implicit cmd via `erc-send-input-line-function'") (ert-info ("Baseline") - (erc-process-input-line "hi") + (erc-process-input-line "hi\n") (should (equal (pop erc-server-flood-queue) '("PRIVMSG #chan :hi\r\n" . utf-8)))) (ert-info ("Spaces preserved") - (erc-process-input-line "hi you") + (erc-process-input-line "hi you\n") (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 "") + (ert-info ("Empty line transmitted with injected-space kludge") + (erc-process-input-line "\n") (should (equal (pop erc-server-flood-queue) - '("PRIVMSG #chan :\r\n" . utf-8)))) + '("PRIVMSG #chan : \r\n" . utf-8)))) (should-not calls)))))) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Add-some-ERC-test-helpers.patch >From 914a58579c6efcdc6746763e382004b1f4e2a2fb Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Tue, 5 Apr 2022 17:45:00 -0700 Subject: [PATCH 2/4] Add some ERC test helpers * test/lisp/erc/erc-tests.el (erc-tests--test-prep, erc-tests--set-fake-server-process): Factor out some common buffer-prep boilerplate involving user input and the server process. Shared with bug#54536. --- test/lisp/erc/erc-tests.el | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 10e3c16dfc..c9254e6d42 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -114,6 +114,20 @@ erc-with-all-buffers-of-server (should (get-buffer "#spam")) (kill-buffer "#spam"))) +(defun erc-tests--send-prep () + (erc-mode) + (insert "\n\n") + (setq erc-input-marker (make-marker) + erc-insert-marker (make-marker)) + (set-marker erc-insert-marker (point-max)) + (erc-display-prompt) + (should (= (point) erc-input-marker))) + +(defun erc-tests--set-fake-server-process (&rest args) + (setq erc-server-process + (apply #'start-process (car args) (current-buffer) args)) + (set-process-query-on-exit-flag erc-server-process nil)) + (ert-deftest erc--switch-to-buffer () (defvar erc-modified-channels-alist) ; lisp/erc/erc-track.el @@ -197,14 +211,10 @@ erc-ring-previous-command-base-case (ert-deftest erc-ring-previous-command () (with-current-buffer (get-buffer-create "*#fake*") (erc-mode) - (insert "\n\n") + (erc-tests--send-prep) + (setq-local erc-last-input-time 0) (should-not (local-variable-if-set-p 'erc-send-completed-hook)) (set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals) - (setq erc-input-marker (make-marker) - erc-insert-marker (make-marker)) - (set-marker erc-insert-marker (point-max)) - (erc-display-prompt) - (should (= (point) erc-input-marker)) ;; Just in case erc-ring-mode is already on (setq-local erc-pre-send-functions nil) (add-hook 'erc-pre-send-functions #'erc-add-to-input-ring) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-Improve-ERC-s-handling-of-multiline-prompt-input.patch >From 6f084d00e7776527b58bf9ed3c4356b85c1dadd7 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 05:40:16 -0700 Subject: [PATCH 3/4] Improve ERC's handling of multiline prompt input * lisp/erc/erc.el (erc-pre-send-functions, erc-discard-trailing-multiline-nulls): Add the latter, a new function, that drops any trailing null lines from a multiline sequence submitted for processing. Add it to `erc-pre-send-functions' as the lone new default. (erc-last-input-time): Tweak meaning of variable to match likely original intent, which is that it's only updated on successful calls to `erc-send-current-line'. (erc--input-line-delim-regexp): Add regex var for splitting multiline prompt input. (erc--blank-in-multiline-p): Add helper for detecting blank lines. (erc-check-prompt-input-for-multiline-blanks, erc-check-prompt-input-for-point-in-bounds, erc-check-prompt-input-for-running-process): New functions to encapsulate logic for various pre-flight idiot checks. (erc-check-prompt-input-functions): Add new hook for validating prompt input prior to clearing it. (erc-send-current-line): pre-screen for blank lines and bail out if necessary. (erc-send-input): Add optional param to skip checking for blank lines. * test/lisp/erc/erc-tests.el (erc-ring-previous-command): Use new test helper. (erc--input-line-delim-regexp, erc--blank-in-multiline-input-p): Add tests. (erc-tests--send-prep, erc-tests--set-fake-server-process, erc-tests--with-process-input-spy): Add test helpers. (erc-check-prompt-input-functions, erc-send-current-line, erc-send-whitespace-lines): Add tests. --- lisp/erc/erc.el | 98 +++++++++++++----- test/lisp/erc/erc-tests.el | 197 +++++++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+), 25 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index d8ef62cf93..f3685dd2a7 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1040,7 +1040,7 @@ erc-send-pre-hook :type 'hook) (make-obsolete-variable 'erc-send-pre-hook 'erc-pre-send-functions "27.1") -(defcustom erc-pre-send-functions nil +(defcustom erc-pre-send-functions '(erc-discard-trailing-multiline-nulls) "Special hook run to possibly alter the string that is sent. The functions are called with one argument, an `erc-input' struct, and should alter that struct. @@ -1052,7 +1052,7 @@ erc-pre-send-functions `sendp': Whether the string should be sent to the irc server." :group 'erc :type 'hook - :version "27.1") + :package-version '(ERC . "5.4.1")) ; FIXME increment upon publishing to ELPA (defvar erc-insert-this t "Insert the text into the target buffer or not. @@ -5536,7 +5536,7 @@ erc-end-of-input-line (point-max)) (defvar erc-last-input-time 0 - "Time of last call to `erc-send-current-line'. + "Time of last successful call to `erc-send-current-line'. If that function has never been called, the value is 0.") (defcustom erc-accidental-paste-threshold-seconds 0.2 @@ -5552,6 +5552,59 @@ erc-accidental-paste-threshold-seconds :version "26.1" :type '(choice number (other :tag "disabled" nil))) +(defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r))) + +(defun erc--blank-in-multiline-input-p (string) + "Detect whether STRING contains any blank lines. +When `erc-send-whitespace-lines' is in effect, return nil if the input +is multiline or the line is non-empty. When `erc-send-whitespace-lines' +is nil, return non-nil when any line is empty or consists of one or more +spaces, tabs, or form-feeds." + (catch 'return + (let ((lines (split-string string erc--input-line-delim-regexp))) + (dolist (line lines) + (when (if erc-send-whitespace-lines + (and (string= line "") (null (cdr lines))) + (string-match (rx bot (* (in " \t\f")) eot) line)) + (throw 'return t)))))) + +(defun erc-discard-trailing-multiline-nulls (state) + "Ensure last line of `erc-input' STATE's string is non-null. +But only when `erc-send-whitespace-lines' is non-nil." + (when erc-send-whitespace-lines + (cl-callf (lambda (s) (string-trim-right s "[\r\n]+")) + (erc-input-string state)))) + +(defun erc-check-prompt-input-for-multiline-blanks (string) + "Return non-nil when multiline prompt input has blank lines." + (when (erc--blank-in-multiline-input-p string) + (if erc-warn-about-blank-lines + "Blank line - ignoring..." + 'invalid))) + +(defun erc-check-prompt-input-for-point-in-bounds (_) + "Return non-nil when point is before prompt." + (when (< (point) (erc-beg-of-input-line)) + "Point is not in the input area")) + +(defun erc-check-prompt-input-for-running-process (string) + "Return non-nil unless in an active ERC server buffer." + (unless (or (erc-server-buffer-live-p) + (erc-command-no-process-p string)) + "ERC: No process running")) + +(defcustom erc-check-prompt-input-functions + '(erc-check-prompt-input-for-point-in-bounds + erc-check-prompt-input-for-multiline-blanks + erc-check-prompt-input-for-running-process) + "Validators for user input typed at prompt. +Called with latest input string submitted by user. If any member +returns non-nil, processing is abandoned and input is left untouched. +When the returned value is a string, pass it to `erc-error'." + :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA + :group 'erc + :type 'hook) + (defun erc-send-current-line () "Parse current line and send it to IRC." (interactive) @@ -5565,20 +5618,20 @@ erc-send-current-line (eolp)) (expand-abbrev)) (widen) - (if (< (point) (erc-beg-of-input-line)) - (erc-error "Point is not in the input area") + (if-let* ((str (erc-user-input)) + (msg (run-hook-with-args-until-success + 'erc-check-prompt-input-functions str))) + (when (stringp msg) + (erc-error msg)) (let ((inhibit-read-only t) - (str (erc-user-input)) (old-buf (current-buffer))) - (if (and (not (erc-server-buffer-live-p)) - (not (erc-command-no-process-p str))) - (erc-error "ERC: No process running") + (progn ; unprogn this during next major surgery (erc-set-active-buffer (current-buffer)) ;; Kill the input and the prompt (delete-region (erc-beg-of-input-line) (erc-end-of-input-line)) (unwind-protect - (erc-send-input str) + (erc-send-input str 'skip-ws-chk) ;; Fix the buffer if the command didn't kill it (when (buffer-live-p old-buf) (with-current-buffer old-buf @@ -5593,8 +5646,8 @@ erc-send-current-line (set-buffer-modified-p buffer-modified)))))) ;; Only when last hook has been run... - (run-hook-with-args 'erc-send-completed-hook str)))) - (setq erc-last-input-time now)) + (run-hook-with-args 'erc-send-completed-hook str))) + (setq erc-last-input-time now))) (switch-to-buffer "*ERC Accidental Paste Overflow*") (lwarn 'erc :warning "You seem to have accidentally pasted some text!")))) @@ -5611,21 +5664,16 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) -(defun erc-send-input (input) +(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. Return non-nil only if we actually send anything." ;; Handle different kinds of inputs - (cond - ;; Ignore empty input - ((if erc-send-whitespace-lines - (string= input "") - (string-match "\\`[ \t\r\f\n]*\\'" input)) - (when erc-warn-about-blank-lines - (message "Blank line - ignoring...") - (beep)) - nil) - (t + (if (and (not skip-ws-chk) + (erc-check-prompt-input-for-multiline-blanks input)) + (when erc-warn-about-blank-lines + (message "Blank line - ignoring...") ; compat + (beep)) ;; This dynamic variable is used by `erc-send-pre-hook'. It's ;; obsolete, and when it's finally removed, this binding should ;; also be removed. @@ -5663,9 +5711,9 @@ erc-send-input (null erc-flood-protect) t)) (or (and erc-flood-protect (erc-split-line line)) (list line)))) - (split-string string "\n")) + (split-string string erc--input-line-delim-regexp)) (erc-process-input-line (concat string "\n") t nil)) - t)))))) + t))))) ;; (defun erc-display-command (line) ;; (when erc-insert-this diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index c9254e6d42..3746f4862e 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -295,6 +295,203 @@ erc-log-irc-protocol (kill-buffer "*erc-protocol*") (should-not erc-debug-irc-protocol))) +(ert-deftest erc--input-line-delim-regexp () + (let ((p erc--input-line-delim-regexp)) + ;; none + (should (equal '("a" "b") (split-string "a\r\nb" p))) + (should (equal '("a" "b") (split-string "a\nb" p))) + (should (equal '("a" "b") (split-string "a\rb" p))) + + ;; one + (should (equal '("") (split-string "" p))) + (should (equal '("a" "" "b") (split-string "a\r\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\nb" p))) + (should (equal '("a" "" "b") (split-string "a\r\r\nb" p))) + (should (equal '("a" "" "b") (split-string "a\n\r\nb" p))) + (should (equal '("a" "") (split-string "a\n" p))) + (should (equal '("a" "") (split-string "a\r" p))) + (should (equal '("a" "") (split-string "a\r\n" p))) + (should (equal '("" "b") (split-string "\nb" p))) + (should (equal '("" "b") (split-string "\rb" p))) + (should (equal '("" "b") (split-string "\r\nb" p))) + + ;; two + (should (equal '("" "") (split-string "\r" p))) + (should (equal '("" "") (split-string "\n" p))) + (should (equal '("" "") (split-string "\r\n" p))) + + ;; three + (should (equal '("" "" "") (split-string "\r\r" p))) + (should (equal '("" "" "") (split-string "\n\n" p))) + (should (equal '("" "" "") (split-string "\n\r" p))))) + +(ert-deftest erc--blank-in-multiline-input-p () + (ert-info ("With `erc-send-whitespace-lines'") + (let ((erc-send-whitespace-lines t)) + (should (erc--blank-in-multiline-input-p "")) + (should-not (erc--blank-in-multiline-input-p "/msg a\n")) ; real /cmd + (should-not (erc--blank-in-multiline-input-p "a\n\nb")) ; "" allowed + (should-not (erc--blank-in-multiline-input-p "/msg a\n\nb")) ; non-/cmd + (should-not (erc--blank-in-multiline-input-p " ")) + (should-not (erc--blank-in-multiline-input-p "\t")) + (should-not (erc--blank-in-multiline-input-p "a\nb")) + (should-not (erc--blank-in-multiline-input-p "a\n ")) + (should-not (erc--blank-in-multiline-input-p "a\n \t")) + (should-not (erc--blank-in-multiline-input-p "a\n \f")) + (should-not (erc--blank-in-multiline-input-p "a\n \nb")) + (should-not (erc--blank-in-multiline-input-p "a\n \t\nb")) + (should-not (erc--blank-in-multiline-input-p "a\n \f\nb")))) + + (should (erc--blank-in-multiline-input-p "")) + (should (erc--blank-in-multiline-input-p " ")) + (should (erc--blank-in-multiline-input-p "\t")) + (should (erc--blank-in-multiline-input-p "a\n\nb")) + (should (erc--blank-in-multiline-input-p "a\n\nb")) + (should (erc--blank-in-multiline-input-p "a\n ")) + (should (erc--blank-in-multiline-input-p "a\n \t")) + (should (erc--blank-in-multiline-input-p "a\n \f")) + (should (erc--blank-in-multiline-input-p "a\n \nb")) + (should (erc--blank-in-multiline-input-p "a\n \t\nb")) + + (should-not (erc--blank-in-multiline-input-p "a\rb")) + (should-not (erc--blank-in-multiline-input-p "a\nb")) + (should-not (erc--blank-in-multiline-input-p "a\r\nb"))) + +(defun erc-tests--with-process-input-spy (test) + (with-current-buffer (get-buffer-create "FakeNet") + (let* ((erc-pre-send-functions + (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now + (inhibit-message noninteractive) + (erc-server-current-nick "tester") + (erc-last-input-time 0) + erc-accidental-paste-threshold-seconds + ;; + calls) + (cl-letf (((symbol-function 'erc-process-input-line) + (lambda (&rest r) (push r calls))) + ((symbol-function 'erc-server-buffer) + (lambda () (current-buffer)))) + (erc-tests--send-prep) + (funcall test (lambda () (pop calls))))) + (when noninteractive (kill-buffer)))) + +(ert-deftest erc-check-prompt-input-functions () + (erc-tests--with-process-input-spy + (lambda (next) + + (ert-info ("Errors when point not in prompt area") ; actually just dings + (insert "/msg #chan hi") + (forward-line -1) + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Point is not in the input area" (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when no process running") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "ERC: No process running" (cadr e)))) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when line contains empty newline") + (erc-bol) + (delete-region (point) (point-max)) + (insert "one\n") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Blank line - ignoring..." (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (goto-char erc-input-marker) + (looking-at "one\n"))))) + + (should (= 0 erc-last-input-time)) + (should-not (funcall next))))) + +;; These also indirectly tests `erc-send-input' + +(ert-deftest erc-send-current-line () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (should (= 0 erc-last-input-time)) + + (ert-info ("Simple command") + (insert "/msg #chan hi") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (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)))) + + (ert-info ("Simple non-command") + (insert "hi") + (erc-send-current-line) + (should (eq (point) (point-max))) + (should (save-excursion (forward-line -1) + (search-forward " hi"))) + ;; Non-ommands are forced only when `erc-flood-protect' is nil + (should (equal (funcall next) '("hi\n" nil t)))) + + (should (consp erc-last-input-time))))) + +(ert-deftest erc-send-whitespace-lines () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (setq-local erc-send-whitespace-lines t) + + (ert-info ("Multiline hunk with blank line correctly split") + (insert "one\n\ntwo") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("two\n" nil t))) + (should (equal (funcall next) '("\n" nil t))) + (should (equal (funcall next) '("one\n" nil t)))) + + (ert-info ("Multiline hunk with trailing newline filtered") + (insert "hi\n") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing carriage filtered") + (insert "hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline command with trailing blank filtered") + (insert "/msg #chan hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("/msg #chan hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing whitespace not filtered") + (insert "there\n ") + (erc-send-current-line) + (should (equal (funcall next) '(" \n" nil t))) + (should (equal (funcall next) '("there\n" nil t))) + (should-not (funcall next)))))) ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-SQUASH-ME-Add-hook-for-splitting-multiline-input-in-.patch >From b58ad0d7c08d0002276f261d508cfca4056cc9ac Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 22 Apr 2022 03:56:25 -0700 Subject: [PATCH 4/4] [SQUASH-ME] Add hook for splitting multiline input in ERC * lisp/erc/erc.el (erc-pre-send-split-functions): Add new hook allowing members to revise individual lines before sending. (erc-discard-trailing-multiline-nulls): Conditionally truncate list of lines to be sent, skipping trailing blanks. (erc-input-split): Add new struct containing split input line. (erc-send-input): Call hook `erc-pre-send-split-functions'. --- lisp/erc/erc.el | 74 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index f3685dd2a7..e2fe5c6476 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1040,7 +1040,7 @@ erc-send-pre-hook :type 'hook) (make-obsolete-variable 'erc-send-pre-hook 'erc-pre-send-functions "27.1") -(defcustom erc-pre-send-functions '(erc-discard-trailing-multiline-nulls) +(defcustom erc-pre-send-functions nil "Special hook run to possibly alter the string that is sent. The functions are called with one argument, an `erc-input' struct, and should alter that struct. @@ -1052,7 +1052,26 @@ erc-pre-send-functions `sendp': Whether the string should be sent to the irc server." :group 'erc :type 'hook - :package-version '(ERC . "5.4.1")) ; FIXME increment upon publishing to ELPA + :version "27.1") + +(defcustom erc-pre-send-split-functions '(erc-discard-trailing-multiline-nulls) + "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. + +The struct has five slots: + + `string': The input string delivered by `erc-pre-send-functions'. + `insertp': Whether the lines should be inserted into the ERC buffer. + `sendp': Whether the lines should be sent to the IRC server. + `lines': A list of lines to be sent, each one a `string'. + `cmdp': Whether to interpret the input as a command, like /ignore. + +The `string' field is effectively read-only. When `cmdp' is non-nil, +all but the first line will be discarded." + :group 'erc + :type 'hook + :package-version '(ERC . "5.4.1")) (defvar erc-insert-this t "Insert the text into the target buffer or not. @@ -5572,8 +5591,13 @@ erc-discard-trailing-multiline-nulls "Ensure last line of `erc-input' STATE's string is non-null. But only when `erc-send-whitespace-lines' is non-nil." (when erc-send-whitespace-lines - (cl-callf (lambda (s) (string-trim-right s "[\r\n]+")) - (erc-input-string state)))) + (when (string-match "[\r\n]+\\'" (erc-input-string state)) + (setf (erc-input-split-lines state) + (split-string (substring (erc-input-string state) + 0 + (match-beginning 0)) + erc--input-line-delim-regexp) + (erc-input-split-cmdp state) nil)))) (defun erc-check-prompt-input-for-multiline-blanks (string) "Return non-nil when multiline prompt input has blank lines." @@ -5664,6 +5688,9 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) +(cl-defstruct (erc-input-split (:include erc-input)) + lines cmdp) + (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. @@ -5693,26 +5720,27 @@ erc-send-input :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 ((string (erc-input-string state))) - (if (or (if (>= emacs-major-version 28) - (string-search "\n" string) - (string-match "\n" string)) - (not (string-match erc-command-regexp string))) - (mapc - (lambda (line) - (mapc - (lambda (line) - ;; Insert what has to be inserted for this. - (when (erc-input-insertp state) - (erc-display-msg line)) - (erc-process-input-line (concat line "\n") - (null erc-flood-protect) t)) - (or (and erc-flood-protect (erc-split-line line)) - (list line)))) - (split-string string erc--input-line-delim-regexp)) - (erc-process-input-line (concat string "\n") t nil)) + 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) + (dolist (line lines) + (dolist (line (or (and erc-flood-protect (erc-split-line line)) + (list line))) + (when (erc-input-insertp state) + (erc-display-msg line)) + (erc-process-input-line (concat line "\n") + (null erc-flood-protect) t)))) t))))) ;; (defun erc-display-command (line) -- 2.35.1 --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Fri Apr 29 09:05:42 2022 Received: (at 54536) by debbugs.gnu.org; 29 Apr 2022 13:05:42 +0000 Received: from localhost ([127.0.0.1]:51208 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nkQJX-0000iO-O5 for submit@debbugs.gnu.org; Fri, 29 Apr 2022 09:05:42 -0400 Received: from mail-108-mta173.mxroute.com ([136.175.108.173]:36263) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nkQJT-0000i6-OJ for 54536@debbugs.gnu.org; Fri, 29 Apr 2022 09:05:38 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta173.mxroute.com (ZoneMTA) with ESMTPSA id 180756d291b000fe85.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Fri, 29 Apr 2022 13:05:29 +0000 X-Zone-Loop: 24c3a5babbcb6f265efacedbacbbeafb7c8e60a56999 X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=f6zD8XfzRuaNEyme0QlZf039wB4DFtaXK7CT4tGNW9E=; b=jZe2XKva9Gel2rB37pFUh8bRiC 6kOc+0fYwicsTvKX0NQ5nLL1bBfSyrpy6TL+rx1kLf2MASkOyat6xnaGwRm4wwMpeur/mK1pZrfiY 8TX5pWndZFpkx2o2SpK7TGisLCslIYJ1+lW2Osq1Gl09KynY5mB+Z1FifUCfueaBxk7ODWhtux940 wydc0l3yObt1JKg0XL8RfzQr7JLer5XQptWALvs0CVACNruvwbXrmEX1Kzf7QGndinwOMDrRx5F2h ZylI5R5G7danrbtwcvLdP4zCNtnH3Srb8ANRuvKvtKw+nROiFkyxKLcYu/toaYUOK6dOIeQcn2lwp yx+1+/zQ==; From: "J.P." To: 54536@debbugs.gnu.org Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> Date: Fri, 29 Apr 2022 06:05:26 -0700 In-Reply-To: <87k0ckg5pn.fsf@neverwas.me> (J. P.'s message of "Wed, 23 Mar 2022 06:26:44 -0700") Message-ID: <87bkwk2g6h.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --=-=-= Content-Type: text/plain v4. I've decided it's probably better to abstain from exporting the input validation hooks or their members without good reason. Likewise for the hook involving split-lines and command-detection. So they've all been renamed as internal, for now. This version also brings with it some out-of-scope feature creep in response to recent clamoring for a way to prevent all multiline input. I've therefore added two options and wired them into the pre-send validation mechanism introduced earlier in this series. The first is called `erc-inhibit-multiline-input', which must be either a positive integer or t. As an int, it indicates the maximum number of lines allowed to be submitted for sending (above which a beep and a scolding result). The second is called `erc-ask-about-multiline-input'. When non-nil, instead of getting scolded, the user is asked whether to go ahead and send anyway (just this once). A few (arguably surprising) idiosyncrasies surround the interaction between `erc-send-whitespace-lines' and these newly proposed options, but nothing too radical or inconsistent (IMO). For example, during the reckoning of `erc-inhibit-multiline-input', trailing blanks are always trimmed, but when `erc-send-whitespace-lines' is nil, this becomes irrelevant because the send is preempted beforehand, which is in line with the behavior described in the initial bug report. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v3-v4.diff >From bb190883389de0bdcdfa39bfdbb5d8953bf115fd Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Wed, 27 Apr 2022 04:33:06 -0700 Subject: [PATCH 0/4] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (4): Fix regression in erc-send-input-line Add some ERC test helpers Improve ERC's handling of multiline prompt input Optionally prevent sending multiline input in ERC lisp/erc/erc.el | 195 ++++++++++++++++++++++------ test/lisp/erc/erc-tests.el | 259 +++++++++++++++++++++++++++++++++++-- 2 files changed, 402 insertions(+), 52 deletions(-) Interdiff: diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 472c103ee4..8e96dd30c4 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -224,6 +224,20 @@ erc-send-whitespace-lines :group 'erc :type 'boolean) +(defcustom erc-inhibit-multiline-input nil + "Conditionally disallow input consisting of multiple lines. +Issue an error when the number of input lines submitted for sending +exceeds this value." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type '(choice integer boolean)) + +(defcustom erc-ask-about-multiline-input nil + "Ask to ignore `erc-inhibit-multiline-input' when tripped." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type 'boolean) + (defcustom erc-hide-prompt nil "If non-nil, do not display the prompt for commands. @@ -1054,10 +1068,16 @@ erc-pre-send-functions :type 'hook :version "27.1") -(defcustom erc-pre-send-split-functions '(erc-discard-trailing-multiline-nulls) +;; This is being auditioned for possible exporting (as a custom +;; option). Likewise for (public versions of) `erc--input-split' and +;; `erc--discard-trailing-multiline-nulls'. If unneeded, we'll just +;; run the latter on the input after `erc-pre-send-functions', and +;; remove this hook and the struct completely. + +(defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls) "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. +The functions are called with one argument, an `erc--input-split' +struct, which they can optionally modify. The struct has five slots: @@ -1068,10 +1088,7 @@ erc-pre-send-split-functions `cmdp': Whether to interpret the input as a command, like /ignore. The `string' field is effectively read-only. When `cmdp' is non-nil, -all but the first line will be discarded." - :group 'erc - :type 'hook - :package-version '(ERC . "5.4.1")) +all but the first line will be discarded.") (defvar erc-insert-this t "Insert the text into the target buffer or not. @@ -5573,61 +5590,77 @@ erc-accidental-paste-threshold-seconds (defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r))) -(defun erc--blank-in-multiline-input-p (string) - "Detect whether STRING contains any blank lines. -When `erc-send-whitespace-lines' is in effect, return nil if the input -is multiline or the line is non-empty. When `erc-send-whitespace-lines' -is nil, return non-nil when any line is empty or consists of one or more +(defun erc--blank-in-multiline-input-p (lines) + "Detect whether LINES contains a blank line. +When `erc-send-whitespace-lines' is in effect, return nil if LINES is +multiline or the first non-empty. When `erc-send-whitespace-lines' is +nil, return non-nil when any line is empty or consists of one or more spaces, tabs, or form-feeds." (catch 'return - (let ((lines (split-string string erc--input-line-delim-regexp))) + (let ((multilinep (cdr lines))) (dolist (line lines) (when (if erc-send-whitespace-lines - (and (string= line "") (null (cdr lines))) + (and (string-empty-p line) (not multilinep)) (string-match (rx bot (* (in " \t\f")) eot) line)) (throw 'return t)))))) -(defun erc-discard-trailing-multiline-nulls (state) +(defun erc--discard-trailing-multiline-nulls (state) "Ensure last line of `erc-input' STATE's string is non-null. But only when `erc-send-whitespace-lines' is non-nil." (when erc-send-whitespace-lines (when (string-match "[\r\n]+\\'" (erc-input-string state)) - (setf (erc-input-split-lines state) + (setf (erc--input-split-lines state) (split-string (substring (erc-input-string state) 0 (match-beginning 0)) erc--input-line-delim-regexp) - (erc-input-split-cmdp state) nil)))) - -(defun erc-check-prompt-input-for-multiline-blanks (string) - "Return non-nil when multiline prompt input has blank lines." - (when (erc--blank-in-multiline-input-p string) + (erc--input-split-cmdp state) nil)))) + +(defun erc--check-prompt-input-for-excess-lines (_ lines) + "Return non-nil when trying to send too many LINES." + (when erc-inhibit-multiline-input + ;; Assume `erc--discard-trailing-multiline-nulls' is set to run + (let ((reversed (seq-drop-while #'string-empty-p (reverse lines))) + (max (if (eq erc-inhibit-multiline-input t) + 2 + erc-inhibit-multiline-input)) + (seen 0) + msg) + (while (and (pop reversed) (< (cl-incf seen) max))) + (when (= seen max) + (setq msg (format "(exceeded by %d)" (1+ (length reversed)))) + (unless (and erc-ask-about-multiline-input + (y-or-n-p (concat "Send input " msg "?"))) + (concat "Too many lines " msg)))))) + +(defun erc--check-prompt-input-for-multiline-blanks (_ lines) + "Return non-nil when multiline prompt input has blank LINES." + (when (erc--blank-in-multiline-input-p lines) (if erc-warn-about-blank-lines "Blank line - ignoring..." 'invalid))) -(defun erc-check-prompt-input-for-point-in-bounds (_) +(defun erc--check-prompt-input-for-point-in-bounds (_ _) "Return non-nil when point is before prompt." (when (< (point) (erc-beg-of-input-line)) "Point is not in the input area")) -(defun erc-check-prompt-input-for-running-process (string) +(defun erc--check-prompt-input-for-running-process (string _) "Return non-nil unless in an active ERC server buffer." (unless (or (erc-server-buffer-live-p) (erc-command-no-process-p string)) "ERC: No process running")) -(defcustom erc-check-prompt-input-functions - '(erc-check-prompt-input-for-point-in-bounds - erc-check-prompt-input-for-multiline-blanks - erc-check-prompt-input-for-running-process) +(defvar erc--check-prompt-input-functions + '(erc--check-prompt-input-for-point-in-bounds + erc--check-prompt-input-for-multiline-blanks + erc--check-prompt-input-for-running-process + erc--check-prompt-input-for-excess-lines) "Validators for user input typed at prompt. -Called with latest input string submitted by user. If any member -returns non-nil, processing is abandoned and input is left untouched. -When the returned value is a string, pass it to `erc-error'." - :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA - :group 'erc - :type 'hook) +Called with latest input string submitted by user and the list of lines +produced by splitting it. If any member function returns non-nil, +processing is abandoned and input is left untouched. When the returned +value is a string, pass it to `erc-error'.") (defun erc-send-current-line () "Parse current line and send it to IRC." @@ -5644,7 +5677,8 @@ erc-send-current-line (widen) (if-let* ((str (erc-user-input)) (msg (run-hook-with-args-until-success - 'erc-check-prompt-input-functions str))) + 'erc--check-prompt-input-functions str + (split-string str erc--input-line-delim-regexp)))) (when (stringp msg) (erc-error msg)) (let ((inhibit-read-only t) @@ -5688,7 +5722,7 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) -(cl-defstruct (erc-input-split (:include erc-input)) +(cl-defstruct (erc--input-split (:include erc-input)) lines cmdp) (defun erc-send-input (input &optional skip-ws-chk) @@ -5697,7 +5731,8 @@ erc-send-input Return non-nil only if we actually send anything." ;; Handle different kinds of inputs (if (and (not skip-ws-chk) - (erc-check-prompt-input-for-multiline-blanks input)) + (erc--check-prompt-input-for-multiline-blanks + input (split-string input erc--input-line-delim-regexp))) (when erc-warn-about-blank-lines (message "Blank line - ignoring...") ; compat (beep)) @@ -5720,7 +5755,7 @@ erc-send-input :insertp erc-insert-this :sendp erc-send-this)) (run-hook-with-args 'erc-pre-send-functions state) - (setq state (make-erc-input-split + (setq state (make-erc--input-split :string (erc-input-string state) :insertp (erc-input-insertp state) :sendp (erc-input-sendp state) @@ -5728,11 +5763,11 @@ erc-send-input 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) + (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))) + (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) (dolist (line lines) (dolist (line (or (and erc-flood-protect (erc-split-line line)) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 3746f4862e..fa39f4fcc6 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -327,36 +327,41 @@ erc--input-line-delim-regexp (should (equal '("" "" "") (split-string "\n\r" p))))) (ert-deftest erc--blank-in-multiline-input-p () - (ert-info ("With `erc-send-whitespace-lines'") - (let ((erc-send-whitespace-lines t)) - (should (erc--blank-in-multiline-input-p "")) - (should-not (erc--blank-in-multiline-input-p "/msg a\n")) ; real /cmd - (should-not (erc--blank-in-multiline-input-p "a\n\nb")) ; "" allowed - (should-not (erc--blank-in-multiline-input-p "/msg a\n\nb")) ; non-/cmd - (should-not (erc--blank-in-multiline-input-p " ")) - (should-not (erc--blank-in-multiline-input-p "\t")) - (should-not (erc--blank-in-multiline-input-p "a\nb")) - (should-not (erc--blank-in-multiline-input-p "a\n ")) - (should-not (erc--blank-in-multiline-input-p "a\n \t")) - (should-not (erc--blank-in-multiline-input-p "a\n \f")) - (should-not (erc--blank-in-multiline-input-p "a\n \nb")) - (should-not (erc--blank-in-multiline-input-p "a\n \t\nb")) - (should-not (erc--blank-in-multiline-input-p "a\n \f\nb")))) - - (should (erc--blank-in-multiline-input-p "")) - (should (erc--blank-in-multiline-input-p " ")) - (should (erc--blank-in-multiline-input-p "\t")) - (should (erc--blank-in-multiline-input-p "a\n\nb")) - (should (erc--blank-in-multiline-input-p "a\n\nb")) - (should (erc--blank-in-multiline-input-p "a\n ")) - (should (erc--blank-in-multiline-input-p "a\n \t")) - (should (erc--blank-in-multiline-input-p "a\n \f")) - (should (erc--blank-in-multiline-input-p "a\n \nb")) - (should (erc--blank-in-multiline-input-p "a\n \t\nb")) - - (should-not (erc--blank-in-multiline-input-p "a\rb")) - (should-not (erc--blank-in-multiline-input-p "a\nb")) - (should-not (erc--blank-in-multiline-input-p "a\r\nb"))) + (let ((check (lambda (s) + (erc--blank-in-multiline-input-p + (split-string s erc--input-line-delim-regexp))))) + + (ert-info ("With `erc-send-whitespace-lines'") + (let ((erc-send-whitespace-lines t)) + (should (funcall check "")) + (should-not (funcall check "\na")) + (should-not (funcall check "/msg a\n")) ; real /cmd + (should-not (funcall check "a\n\nb")) ; "" allowed + (should-not (funcall check "/msg a\n\nb")) ; non-/cmd + (should-not (funcall check " ")) + (should-not (funcall check "\t")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\n ")) + (should-not (funcall check "a\n \t")) + (should-not (funcall check "a\n \f")) + (should-not (funcall check "a\n \nb")) + (should-not (funcall check "a\n \t\nb")) + (should-not (funcall check "a\n \f\nb")))) + + (should (funcall check "")) + (should (funcall check " ")) + (should (funcall check "\t")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n ")) + (should (funcall check "a\n \t")) + (should (funcall check "a\n \f")) + (should (funcall check "a\n \nb")) + (should (funcall check "a\n \t\nb")) + + (should-not (funcall check "a\rb")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\r\nb")))) (defun erc-tests--with-process-input-spy (test) (with-current-buffer (get-buffer-create "FakeNet") @@ -376,7 +381,7 @@ erc-tests--with-process-input-spy (funcall test (lambda () (pop calls))))) (when noninteractive (kill-buffer)))) -(ert-deftest erc-check-prompt-input-functions () +(ert-deftest erc--check-prompt-input-functions () (erc-tests--with-process-input-spy (lambda (next) @@ -493,6 +498,31 @@ erc-send-whitespace-lines (should (equal (funcall next) '("there\n" nil t))) (should-not (funcall next)))))) +(ert-deftest erc--check-prompt-input-for-excess-lines () + (ert-info ("Without `erc-inhibit-multiline-input'") + (should-not erc-inhibit-multiline-input) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))) + + (ert-info ("With `erc-inhibit-multiline-input' as t (2)") + (let ((erc-inhibit-multiline-input t)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + + (ert-info ("With `erc-inhibit-multiline-input' as 3") + (let ((erc-inhibit-multiline-input 3)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b" "c"))))) + + (ert-info ("With `erc-ask-about-multiline-input'") + (let ((erc-inhibit-multiline-input t) + (erc-ask-about-multiline-input t)) + (ert-simulate-keys '(?n ?\r ?y ?\r) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + (should-not erc-ask-about-multiline-input))) + ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Fix-regression-in-erc-send-input-line.patch >From bdfb502f7f0e6b1fbc0ea8cfb0336757bf813ab5 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 19:21:57 -0700 Subject: [PATCH 1/4] Fix regression in erc-send-input-line * lisp/erc/erc.el (erc-send-input-line): Restore remedial single-space padding to ensure empty messages typed at the prompt without an explicit /msg aren't rejected by the server. This behavior is only noticeable when `erc-send-whitespace-lines' is active. * test/lisp/erc/erc-tests.el (erc-process-input-line): Add trailing newline to more correctly simulate how it's actually called by `erc-send-input'. (Bug#50008) --- lisp/erc/erc.el | 2 ++ test/lisp/erc/erc-tests.el | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 06381c5ebe..29a465a759 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2817,6 +2817,8 @@ erc-send-input-line-function (defun erc-send-input-line (target line &optional force) "Send LINE to TARGET." + (when (string= line "\n") + (setq line " \n")) (erc-message "PRIVMSG" (concat target " " line) force)) (defun erc-get-arglist (fun) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 520f10dd4e..10e3c16dfc 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -340,19 +340,19 @@ erc-process-input-line (ert-info ("Implicit cmd via `erc-send-input-line-function'") (ert-info ("Baseline") - (erc-process-input-line "hi") + (erc-process-input-line "hi\n") (should (equal (pop erc-server-flood-queue) '("PRIVMSG #chan :hi\r\n" . utf-8)))) (ert-info ("Spaces preserved") - (erc-process-input-line "hi you") + (erc-process-input-line "hi you\n") (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 "") + (ert-info ("Empty line transmitted with injected-space kludge") + (erc-process-input-line "\n") (should (equal (pop erc-server-flood-queue) - '("PRIVMSG #chan :\r\n" . utf-8)))) + '("PRIVMSG #chan : \r\n" . utf-8)))) (should-not calls)))))) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Add-some-ERC-test-helpers.patch >From 97f18350d52791c57e325e828997e4440119b7ff Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Tue, 5 Apr 2022 17:45:00 -0700 Subject: [PATCH 2/4] Add some ERC test helpers * test/lisp/erc/erc-tests.el (erc-tests--test-prep, erc-tests--set-fake-server-process): Factor out some common buffer-prep boilerplate involving user input and the server process. Shared with bug#54536. --- test/lisp/erc/erc-tests.el | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 10e3c16dfc..c9254e6d42 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -114,6 +114,20 @@ erc-with-all-buffers-of-server (should (get-buffer "#spam")) (kill-buffer "#spam"))) +(defun erc-tests--send-prep () + (erc-mode) + (insert "\n\n") + (setq erc-input-marker (make-marker) + erc-insert-marker (make-marker)) + (set-marker erc-insert-marker (point-max)) + (erc-display-prompt) + (should (= (point) erc-input-marker))) + +(defun erc-tests--set-fake-server-process (&rest args) + (setq erc-server-process + (apply #'start-process (car args) (current-buffer) args)) + (set-process-query-on-exit-flag erc-server-process nil)) + (ert-deftest erc--switch-to-buffer () (defvar erc-modified-channels-alist) ; lisp/erc/erc-track.el @@ -197,14 +211,10 @@ erc-ring-previous-command-base-case (ert-deftest erc-ring-previous-command () (with-current-buffer (get-buffer-create "*#fake*") (erc-mode) - (insert "\n\n") + (erc-tests--send-prep) + (setq-local erc-last-input-time 0) (should-not (local-variable-if-set-p 'erc-send-completed-hook)) (set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals) - (setq erc-input-marker (make-marker) - erc-insert-marker (make-marker)) - (set-marker erc-insert-marker (point-max)) - (erc-display-prompt) - (should (= (point) erc-input-marker)) ;; Just in case erc-ring-mode is already on (setq-local erc-pre-send-functions nil) (add-hook 'erc-pre-send-functions #'erc-add-to-input-ring) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-Improve-ERC-s-handling-of-multiline-prompt-input.patch >From 0898d4eb0b37e3faae8cd8c37c756a2cfde1873d Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 05:40:16 -0700 Subject: [PATCH 3/4] Improve ERC's handling of multiline prompt input * lisp/erc/erc.el (erc--pre-send-split-functions): Add new internal hook allowing members to revise individual lines before sending. This was created with an eye toward possibly exporting it publicly as a customizable option. (erc-last-input-time): Tweak meaning of variable to match likely original intent, which is that it's only updated on successful calls to `erc-send-current-line'. (erc--discard-trailing-multiline-nulls): Conditionally truncate list of lines to be sent, skipping trailing blanks. This constitutes a behavioral change, but considering the nature of the bug being fixed, is thought to be justified. (erc--input-split): Add new internal struct containing split input lines and flag for command detection. (erc--input-line-delim-regexp): Add regex var for splitting multiline prompt input. (erc--blank-in-multiline-p): Add helper for detecting blank lines. (erc--check-prompt-input-for-multiline-blanks, erc--check-prompt-input-for-point-in-bounds, erc--check-prompt-input-for-running-process): New functions to encapsulate logic for various pre-flight idiot checks. (erc--check-prompt-input-functions): Add new hook for validating prompt input prior to clearing it. Keep it internal for now. (erc-send-current-line): pre-screen for blank lines and bail out if necessary. (erc-send-input): Add optional param to skip checking for blank lines. Call hook `erc--pre-send-split-functions'. * test/lisp/erc/erc-tests.el (erc-ring-previous-command): Use new test helper. (erc--input-line-delim-regexp, erc--blank-in-multiline-input-p): Add tests. (erc-tests--send-prep, erc-tests--set-fake-server-process, erc-tests--with-process-input-spy): Add test helpers. (erc--check-prompt-input-functions, erc-send-current-line, erc-send-whitespace-lines): Add tests. (Bug#54536) --- lisp/erc/erc.el | 161 +++++++++++++++++++++-------- test/lisp/erc/erc-tests.el | 202 +++++++++++++++++++++++++++++++++++++ 2 files changed, 322 insertions(+), 41 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 29a465a759..d4ca8665a4 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1054,6 +1054,28 @@ erc-pre-send-functions :type 'hook :version "27.1") +;; This is being auditioned for possible exporting (as a custom +;; option). Likewise for (public versions of) `erc--input-split' and +;; `erc--discard-trailing-multiline-nulls'. If unneeded, we'll just +;; run the latter on the input after `erc-pre-send-functions', and +;; remove this hook and the struct completely. + +(defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls) + "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. + +The struct has five slots: + + `string': The input string delivered by `erc-pre-send-functions'. + `insertp': Whether the lines should be inserted into the ERC buffer. + `sendp': Whether the lines should be sent to the IRC server. + `lines': A list of lines to be sent, each one a `string'. + `cmdp': Whether to interpret the input as a command, like /ignore. + +The `string' field is effectively read-only. When `cmdp' is non-nil, +all but the first line will be discarded.") + (defvar erc-insert-this t "Insert the text into the target buffer or not. Functions on `erc-insert-pre-hook' can set this variable to nil @@ -5536,7 +5558,7 @@ erc-end-of-input-line (point-max)) (defvar erc-last-input-time 0 - "Time of last call to `erc-send-current-line'. + "Time of last successful call to `erc-send-current-line'. If that function has never been called, the value is 0.") (defcustom erc-accidental-paste-threshold-seconds 0.2 @@ -5552,6 +5574,62 @@ erc-accidental-paste-threshold-seconds :version "26.1" :type '(choice number (other :tag "disabled" nil))) +(defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r))) + +(defun erc--blank-in-multiline-input-p (lines) + "Detect whether LINES contains a blank line. +When `erc-send-whitespace-lines' is in effect, return nil if LINES is +multiline or the first non-empty. When `erc-send-whitespace-lines' is +nil, return non-nil when any line is empty or consists of one or more +spaces, tabs, or form-feeds." + (catch 'return + (let ((multilinep (cdr lines))) + (dolist (line lines) + (when (if erc-send-whitespace-lines + (and (string-empty-p line) (not multilinep)) + (string-match (rx bot (* (in " \t\f")) eot) line)) + (throw 'return t)))))) + +(defun erc--discard-trailing-multiline-nulls (state) + "Ensure last line of `erc-input' STATE's string is non-null. +But only when `erc-send-whitespace-lines' is non-nil." + (when erc-send-whitespace-lines + (when (string-match "[\r\n]+\\'" (erc-input-string state)) + (setf (erc--input-split-lines state) + (split-string (substring (erc-input-string state) + 0 + (match-beginning 0)) + erc--input-line-delim-regexp) + (erc--input-split-cmdp state) nil)))) + +(defun erc--check-prompt-input-for-multiline-blanks (_ lines) + "Return non-nil when multiline prompt input has blank LINES." + (when (erc--blank-in-multiline-input-p lines) + (if erc-warn-about-blank-lines + "Blank line - ignoring..." + 'invalid))) + +(defun erc--check-prompt-input-for-point-in-bounds (_ _) + "Return non-nil when point is before prompt." + (when (< (point) (erc-beg-of-input-line)) + "Point is not in the input area")) + +(defun erc--check-prompt-input-for-running-process (string _) + "Return non-nil unless in an active ERC server buffer." + (unless (or (erc-server-buffer-live-p) + (erc-command-no-process-p string)) + "ERC: No process running")) + +(defvar erc--check-prompt-input-functions + '(erc--check-prompt-input-for-point-in-bounds + erc--check-prompt-input-for-multiline-blanks + erc--check-prompt-input-for-running-process) + "Validators for user input typed at prompt. +Called with latest input string submitted by user and the list of lines +produced by splitting it. If any member function returns non-nil, +processing is abandoned and input is left untouched. When the returned +value is a string, pass it to `erc-error'.") + (defun erc-send-current-line () "Parse current line and send it to IRC." (interactive) @@ -5565,20 +5643,21 @@ erc-send-current-line (eolp)) (expand-abbrev)) (widen) - (if (< (point) (erc-beg-of-input-line)) - (erc-error "Point is not in the input area") + (if-let* ((str (erc-user-input)) + (msg (run-hook-with-args-until-success + 'erc--check-prompt-input-functions str + (split-string str erc--input-line-delim-regexp)))) + (when (stringp msg) + (erc-error msg)) (let ((inhibit-read-only t) - (str (erc-user-input)) (old-buf (current-buffer))) - (if (and (not (erc-server-buffer-live-p)) - (not (erc-command-no-process-p str))) - (erc-error "ERC: No process running") + (progn ; unprogn this during next major surgery (erc-set-active-buffer (current-buffer)) ;; Kill the input and the prompt (delete-region (erc-beg-of-input-line) (erc-end-of-input-line)) (unwind-protect - (erc-send-input str) + (erc-send-input str 'skip-ws-chk) ;; Fix the buffer if the command didn't kill it (when (buffer-live-p old-buf) (with-current-buffer old-buf @@ -5593,8 +5672,8 @@ erc-send-current-line (set-buffer-modified-p buffer-modified)))))) ;; Only when last hook has been run... - (run-hook-with-args 'erc-send-completed-hook str)))) - (setq erc-last-input-time now)) + (run-hook-with-args 'erc-send-completed-hook str))) + (setq erc-last-input-time now))) (switch-to-buffer "*ERC Accidental Paste Overflow*") (lwarn 'erc :warning "You seem to have accidentally pasted some text!")))) @@ -5611,21 +5690,20 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) -(defun erc-send-input (input) +(cl-defstruct (erc--input-split (:include erc-input)) + lines cmdp) + +(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. Return non-nil only if we actually send anything." ;; Handle different kinds of inputs - (cond - ;; Ignore empty input - ((if erc-send-whitespace-lines - (string= input "") - (string-match "\\`[ \t\r\f\n]*\\'" input)) - (when erc-warn-about-blank-lines - (message "Blank line - ignoring...") - (beep)) - nil) - (t + (if (and (not skip-ws-chk) + (erc--check-prompt-input-for-multiline-blanks + input (split-string input erc--input-line-delim-regexp))) + (when erc-warn-about-blank-lines + (message "Blank line - ignoring...") ; compat + (beep)) ;; This dynamic variable is used by `erc-send-pre-hook'. It's ;; obsolete, and when it's finally removed, this binding should ;; also be removed. @@ -5645,27 +5723,28 @@ erc-send-input :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 ((string (erc-input-string state))) - (if (or (if (>= emacs-major-version 28) - (string-search "\n" string) - (string-match "\n" string)) - (not (string-match erc-command-regexp string))) - (mapc - (lambda (line) - (mapc - (lambda (line) - ;; Insert what has to be inserted for this. - (when (erc-input-insertp state) - (erc-display-msg line)) - (erc-process-input-line (concat line "\n") - (null erc-flood-protect) t)) - (or (and erc-flood-protect (erc-split-line line)) - (list line)))) - (split-string string "\n")) - (erc-process-input-line (concat string "\n") t nil)) - t)))))) + 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) + (dolist (line lines) + (dolist (line (or (and erc-flood-protect (erc-split-line line)) + (list line))) + (when (erc-input-insertp state) + (erc-display-msg line)) + (erc-process-input-line (concat line "\n") + (null erc-flood-protect) t)))) + t))))) ;; (defun erc-display-command (line) ;; (when erc-insert-this diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index c9254e6d42..c076503933 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -295,6 +295,208 @@ erc-log-irc-protocol (kill-buffer "*erc-protocol*") (should-not erc-debug-irc-protocol))) +(ert-deftest erc--input-line-delim-regexp () + (let ((p erc--input-line-delim-regexp)) + ;; none + (should (equal '("a" "b") (split-string "a\r\nb" p))) + (should (equal '("a" "b") (split-string "a\nb" p))) + (should (equal '("a" "b") (split-string "a\rb" p))) + + ;; one + (should (equal '("") (split-string "" p))) + (should (equal '("a" "" "b") (split-string "a\r\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\nb" p))) + (should (equal '("a" "" "b") (split-string "a\r\r\nb" p))) + (should (equal '("a" "" "b") (split-string "a\n\r\nb" p))) + (should (equal '("a" "") (split-string "a\n" p))) + (should (equal '("a" "") (split-string "a\r" p))) + (should (equal '("a" "") (split-string "a\r\n" p))) + (should (equal '("" "b") (split-string "\nb" p))) + (should (equal '("" "b") (split-string "\rb" p))) + (should (equal '("" "b") (split-string "\r\nb" p))) + + ;; two + (should (equal '("" "") (split-string "\r" p))) + (should (equal '("" "") (split-string "\n" p))) + (should (equal '("" "") (split-string "\r\n" p))) + + ;; three + (should (equal '("" "" "") (split-string "\r\r" p))) + (should (equal '("" "" "") (split-string "\n\n" p))) + (should (equal '("" "" "") (split-string "\n\r" p))))) + +(ert-deftest erc--blank-in-multiline-input-p () + (let ((check (lambda (s) + (erc--blank-in-multiline-input-p + (split-string s erc--input-line-delim-regexp))))) + + (ert-info ("With `erc-send-whitespace-lines'") + (let ((erc-send-whitespace-lines t)) + (should (funcall check "")) + (should-not (funcall check "\na")) + (should-not (funcall check "/msg a\n")) ; real /cmd + (should-not (funcall check "a\n\nb")) ; "" allowed + (should-not (funcall check "/msg a\n\nb")) ; non-/cmd + (should-not (funcall check " ")) + (should-not (funcall check "\t")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\n ")) + (should-not (funcall check "a\n \t")) + (should-not (funcall check "a\n \f")) + (should-not (funcall check "a\n \nb")) + (should-not (funcall check "a\n \t\nb")) + (should-not (funcall check "a\n \f\nb")))) + + (should (funcall check "")) + (should (funcall check " ")) + (should (funcall check "\t")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n ")) + (should (funcall check "a\n \t")) + (should (funcall check "a\n \f")) + (should (funcall check "a\n \nb")) + (should (funcall check "a\n \t\nb")) + + (should-not (funcall check "a\rb")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\r\nb")))) + +(defun erc-tests--with-process-input-spy (test) + (with-current-buffer (get-buffer-create "FakeNet") + (let* ((erc-pre-send-functions + (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now + (inhibit-message noninteractive) + (erc-server-current-nick "tester") + (erc-last-input-time 0) + erc-accidental-paste-threshold-seconds + ;; + calls) + (cl-letf (((symbol-function 'erc-process-input-line) + (lambda (&rest r) (push r calls))) + ((symbol-function 'erc-server-buffer) + (lambda () (current-buffer)))) + (erc-tests--send-prep) + (funcall test (lambda () (pop calls))))) + (when noninteractive (kill-buffer)))) + +(ert-deftest erc--check-prompt-input-functions () + (erc-tests--with-process-input-spy + (lambda (next) + + (ert-info ("Errors when point not in prompt area") ; actually just dings + (insert "/msg #chan hi") + (forward-line -1) + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Point is not in the input area" (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when no process running") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "ERC: No process running" (cadr e)))) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when line contains empty newline") + (erc-bol) + (delete-region (point) (point-max)) + (insert "one\n") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Blank line - ignoring..." (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (goto-char erc-input-marker) + (looking-at "one\n"))))) + + (should (= 0 erc-last-input-time)) + (should-not (funcall next))))) + +;; These also indirectly tests `erc-send-input' + +(ert-deftest erc-send-current-line () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (should (= 0 erc-last-input-time)) + + (ert-info ("Simple command") + (insert "/msg #chan hi") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (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)))) + + (ert-info ("Simple non-command") + (insert "hi") + (erc-send-current-line) + (should (eq (point) (point-max))) + (should (save-excursion (forward-line -1) + (search-forward " hi"))) + ;; Non-ommands are forced only when `erc-flood-protect' is nil + (should (equal (funcall next) '("hi\n" nil t)))) + + (should (consp erc-last-input-time))))) + +(ert-deftest erc-send-whitespace-lines () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (setq-local erc-send-whitespace-lines t) + + (ert-info ("Multiline hunk with blank line correctly split") + (insert "one\n\ntwo") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("two\n" nil t))) + (should (equal (funcall next) '("\n" nil t))) + (should (equal (funcall next) '("one\n" nil t)))) + + (ert-info ("Multiline hunk with trailing newline filtered") + (insert "hi\n") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing carriage filtered") + (insert "hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline command with trailing blank filtered") + (insert "/msg #chan hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("/msg #chan hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing whitespace not filtered") + (insert "there\n ") + (erc-send-current-line) + (should (equal (funcall next) '(" \n" nil t))) + (should (equal (funcall next) '("there\n" nil t))) + (should-not (funcall next)))))) ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-Optionally-prevent-sending-multiline-input-in-ERC.patch >From cb445bf2b95737df7fdcb47be3e9937c983cd705 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Wed, 27 Apr 2022 02:27:32 -0700 Subject: [PATCH 4/4] Optionally prevent sending multiline input in ERC * lisp/erc/erc.el (erc-inhibit-multiline-input): Add option to cap the number of lines to be sent before admonishing the user. (erc-ask-about-multiline-input): Add option to ask instead of warning user when `erc-inhibit-multiline-input' is reached. (erc--check-prompt-input-for-excess-lines): Add validator to check to possibly warn when too many lines are submitted for transmission. * test/lisp/erc/erc-tests.el (erc--check-prompt-input-for-excess-lines): Add test. (Bug#54536) --- lisp/erc/erc.el | 34 +++++++++++++++++++++++++++++++++- test/lisp/erc/erc-tests.el | 25 +++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index d4ca8665a4..8e96dd30c4 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -224,6 +224,20 @@ erc-send-whitespace-lines :group 'erc :type 'boolean) +(defcustom erc-inhibit-multiline-input nil + "Conditionally disallow input consisting of multiple lines. +Issue an error when the number of input lines submitted for sending +exceeds this value." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type '(choice integer boolean)) + +(defcustom erc-ask-about-multiline-input nil + "Ask to ignore `erc-inhibit-multiline-input' when tripped." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type 'boolean) + (defcustom erc-hide-prompt nil "If non-nil, do not display the prompt for commands. @@ -5602,6 +5616,23 @@ erc--discard-trailing-multiline-nulls erc--input-line-delim-regexp) (erc--input-split-cmdp state) nil)))) +(defun erc--check-prompt-input-for-excess-lines (_ lines) + "Return non-nil when trying to send too many LINES." + (when erc-inhibit-multiline-input + ;; Assume `erc--discard-trailing-multiline-nulls' is set to run + (let ((reversed (seq-drop-while #'string-empty-p (reverse lines))) + (max (if (eq erc-inhibit-multiline-input t) + 2 + erc-inhibit-multiline-input)) + (seen 0) + msg) + (while (and (pop reversed) (< (cl-incf seen) max))) + (when (= seen max) + (setq msg (format "(exceeded by %d)" (1+ (length reversed)))) + (unless (and erc-ask-about-multiline-input + (y-or-n-p (concat "Send input " msg "?"))) + (concat "Too many lines " msg)))))) + (defun erc--check-prompt-input-for-multiline-blanks (_ lines) "Return non-nil when multiline prompt input has blank LINES." (when (erc--blank-in-multiline-input-p lines) @@ -5623,7 +5654,8 @@ erc--check-prompt-input-for-running-process (defvar erc--check-prompt-input-functions '(erc--check-prompt-input-for-point-in-bounds erc--check-prompt-input-for-multiline-blanks - erc--check-prompt-input-for-running-process) + erc--check-prompt-input-for-running-process + erc--check-prompt-input-for-excess-lines) "Validators for user input typed at prompt. Called with latest input string submitted by user and the list of lines produced by splitting it. If any member function returns non-nil, diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index c076503933..fa39f4fcc6 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -498,6 +498,31 @@ erc-send-whitespace-lines (should (equal (funcall next) '("there\n" nil t))) (should-not (funcall next)))))) +(ert-deftest erc--check-prompt-input-for-excess-lines () + (ert-info ("Without `erc-inhibit-multiline-input'") + (should-not erc-inhibit-multiline-input) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))) + + (ert-info ("With `erc-inhibit-multiline-input' as t (2)") + (let ((erc-inhibit-multiline-input t)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + + (ert-info ("With `erc-inhibit-multiline-input' as 3") + (let ((erc-inhibit-multiline-input 3)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b" "c"))))) + + (ert-info ("With `erc-ask-about-multiline-input'") + (let ((erc-inhibit-multiline-input t) + (erc-ask-about-multiline-input t)) + (ert-simulate-keys '(?n ?\r ?y ?\r) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + (should-not erc-ask-about-multiline-input))) + ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.35.1 --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Tue May 17 09:10:22 2022 Received: (at 54536) by debbugs.gnu.org; 17 May 2022 13:10:22 +0000 Received: from localhost ([127.0.0.1]:56070 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nqwxw-0001rF-QZ for submit@debbugs.gnu.org; Tue, 17 May 2022 09:10:22 -0400 Received: from mail-108-mta223.mxroute.com ([136.175.108.223]:39413) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nqwxt-0001qx-TV for 54536@debbugs.gnu.org; Tue, 17 May 2022 09:10:19 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta223.mxroute.com (ZoneMTA) with ESMTPSA id 180d223e35c000fc5d.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Tue, 17 May 2022 13:10:08 +0000 X-Zone-Loop: 41e5894e9ba8ca860aafe10863bba85bd40034bae220 X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=yWH6nbmUrDXTBUosB0YKGgi0EEsm2B9w36e+hUZ6d6I=; b=NR5K2EiQlwj0gXK5hKwhfRAArz Ht9AaRuJlg88dUUnTHX6SrC28Lrs4DuVeSRfU/MLgci7zs6bjhjaCPYDvR6Uj+Enzmwu2Gzq9JaHp 6CHcOWYsrLuuMQ4NdC321KLhBuGnyrvM6Ioq0gQtSIBKzBKlzzExsaTltqibo4qBAxQaThRCe2Sk4 3FRnOKUgEEfRGPYIC4k3lozYeG0riDA4u9pRmGFJwL39CwEdR/gznRrFthwFrhgJ8tZZ/YWKJA7/8 H8o0JuMppqQV1iotAbyFauuWcYqynYi5kVmvk1fNNQWAYwzs6jDsA7b4Ieh7rfrcO+kH4EouH6SAT HOWYtPSA==; From: "J.P." To: 54536@debbugs.gnu.org Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> Date: Tue, 17 May 2022 06:10:05 -0700 In-Reply-To: <87k0ckg5pn.fsf@neverwas.me> (J. P.'s message of "Wed, 23 Mar 2022 06:26:44 -0700") Message-ID: <874k1os3te.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --=-=-= Content-Type: text/plain v5. Fix compiler error and other minor issues. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v4-v5.diff >From aaf22460711d8d669da296dfbf024053270e1cef Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Tue, 17 May 2022 05:43:52 -0700 Subject: [PATCH 0/4] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (4): Fix regression in erc-send-input-line Add some ERC test helpers Improve ERC's handling of multiline prompt input Optionally prevent sending multiline input in ERC lisp/erc/erc.el | 195 +++++++++++++++++++++------ test/lisp/erc/erc-tests.el | 267 +++++++++++++++++++++++++++++++++++-- 2 files changed, 410 insertions(+), 52 deletions(-) Interdiff: diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 14194492e8..17bf3c9c0c 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1068,11 +1068,12 @@ erc-pre-send-functions :type 'hook :version "27.1") -;; This is being auditioned for possible exporting (as a custom +;; This is being auditioned for possible exporting (as a custom hook ;; option). Likewise for (public versions of) `erc--input-split' and ;; `erc--discard-trailing-multiline-nulls'. If unneeded, we'll just ;; run the latter on the input after `erc-pre-send-functions', and -;; remove this hook and the struct completely. +;; remove this hook and the struct completely. It you need this, +;; please say so! (defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls) "Special hook for modifying individual lines in multiline prompt input. @@ -5594,18 +5595,6 @@ erc--blank-in-multiline-input-p (string-match (rx bot (* (in " \t\f")) eot) line)) (throw 'return t)))))) -(defun erc--discard-trailing-multiline-nulls (state) - "Ensure last line of `erc-input' STATE's string is non-null. -But only when `erc-send-whitespace-lines' is non-nil." - (when erc-send-whitespace-lines - (when (string-match "[\r\n]+\\'" (erc-input-string state)) - (setf (erc--input-split-lines state) - (split-string (substring (erc-input-string state) - 0 - (match-beginning 0)) - erc--input-line-delim-regexp) - (erc--input-split-cmdp state) nil)))) - (defun erc--check-prompt-input-for-excess-lines (_ lines) "Return non-nil when trying to send too many LINES." (when erc-inhibit-multiline-input @@ -5715,6 +5704,17 @@ erc-input (cl-defstruct (erc--input-split (:include erc-input)) lines cmdp) +(defun erc--discard-trailing-multiline-nulls (state) + "Ensure last line of STATE's string is non-null. +But only when `erc-send-whitespace-lines' is non-nil. STATE is an +`erc--input-split' object." + (when (and erc-send-whitespace-lines (erc--input-split-lines state)) + (let ((reversed (nreverse (erc--input-split-lines state)))) + (when (string-empty-p (car reversed)) + (pop reversed) + (setf (erc--input-split-cmdp state) nil)) + (nreverse (seq-drop-while #'string-empty-p reversed))))) + (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. diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index fa39f4fcc6..e956538afa 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -115,6 +115,8 @@ erc-with-all-buffers-of-server (kill-buffer "#spam"))) (defun erc-tests--send-prep () + ;; Caller should probably shadow `erc-insert-modify-hook' or + ;; populate user tables for erc-button. (erc-mode) (insert "\n\n") (setq erc-input-marker (make-marker) @@ -483,13 +485,19 @@ erc-send-whitespace-lines (should-not (funcall next))) (ert-info ("Multiline command with trailing blank filtered") - (insert "/msg #chan hi\r") - (erc-send-current-line) - (ert-info ("Input cleared") + (pcase-dolist (`(,p . ,q) + '(("/a b\r" "/a b\n") ("/a b\n" "/a b\n") + ("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n") + ("a b\nc\n\n" "c\n" "a b\n") + ("/a b\nc\n\n" "c\n" "/a b\n") + ("/a b\n\nc\n\n" "c\n" "\n" "/a b\n"))) + (insert p) + (erc-send-current-line) (erc-bol) - (should (eq (point) (point-max)))) - (should (equal (funcall next) '("/msg #chan hi\n" nil t))) - (should-not (funcall next))) + (should (eq (point) (point-max))) + (while q + (should (equal (funcall next) (list (pop q) nil t)))) + (should-not (funcall next)))) (ert-info ("Multiline hunk with trailing whitespace not filtered") (insert "there\n ") -- 2.36.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Fix-regression-in-erc-send-input-line.patch >From 64ab9c43c08a7f2e5fb0b02c562f460dcf849c22 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 19:21:57 -0700 Subject: [PATCH 1/4] Fix regression in erc-send-input-line * lisp/erc/erc.el (erc-send-input-line): Restore remedial single-space padding to ensure empty messages typed at the prompt without an explicit /msg aren't rejected by the server. This behavior is only noticeable when `erc-send-whitespace-lines' is active. * test/lisp/erc/erc-tests.el (erc-process-input-line): Add trailing newline to more correctly simulate how it's actually called by `erc-send-input'. (Bug#50008) --- lisp/erc/erc.el | 2 ++ test/lisp/erc/erc-tests.el | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index ff482d4933..6725226d11 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2817,6 +2817,8 @@ erc-send-input-line-function (defun erc-send-input-line (target line &optional force) "Send LINE to TARGET." + (when (string= line "\n") + (setq line " \n")) (erc-message "PRIVMSG" (concat target " " line) force)) (defun erc-get-arglist (fun) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 520f10dd4e..10e3c16dfc 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -340,19 +340,19 @@ erc-process-input-line (ert-info ("Implicit cmd via `erc-send-input-line-function'") (ert-info ("Baseline") - (erc-process-input-line "hi") + (erc-process-input-line "hi\n") (should (equal (pop erc-server-flood-queue) '("PRIVMSG #chan :hi\r\n" . utf-8)))) (ert-info ("Spaces preserved") - (erc-process-input-line "hi you") + (erc-process-input-line "hi you\n") (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 "") + (ert-info ("Empty line transmitted with injected-space kludge") + (erc-process-input-line "\n") (should (equal (pop erc-server-flood-queue) - '("PRIVMSG #chan :\r\n" . utf-8)))) + '("PRIVMSG #chan : \r\n" . utf-8)))) (should-not calls)))))) -- 2.36.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Add-some-ERC-test-helpers.patch >From 4f71ec838470b8435d490e582177b7a9c2c8d520 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Tue, 5 Apr 2022 17:45:00 -0700 Subject: [PATCH 2/4] Add some ERC test helpers * test/lisp/erc/erc-tests.el (erc-tests--test-prep, erc-tests--set-fake-server-process): Factor out some common buffer-prep boilerplate involving user input and the server process. Shared with bug#54536. --- test/lisp/erc/erc-tests.el | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 10e3c16dfc..8b2af6e7c8 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -114,6 +114,22 @@ erc-with-all-buffers-of-server (should (get-buffer "#spam")) (kill-buffer "#spam"))) +(defun erc-tests--send-prep () + ;; Caller should probably shadow `erc-insert-modify-hook' or + ;; populate user tables for erc-button. + (erc-mode) + (insert "\n\n") + (setq erc-input-marker (make-marker) + erc-insert-marker (make-marker)) + (set-marker erc-insert-marker (point-max)) + (erc-display-prompt) + (should (= (point) erc-input-marker))) + +(defun erc-tests--set-fake-server-process (&rest args) + (setq erc-server-process + (apply #'start-process (car args) (current-buffer) args)) + (set-process-query-on-exit-flag erc-server-process nil)) + (ert-deftest erc--switch-to-buffer () (defvar erc-modified-channels-alist) ; lisp/erc/erc-track.el @@ -197,14 +213,10 @@ erc-ring-previous-command-base-case (ert-deftest erc-ring-previous-command () (with-current-buffer (get-buffer-create "*#fake*") (erc-mode) - (insert "\n\n") + (erc-tests--send-prep) + (setq-local erc-last-input-time 0) (should-not (local-variable-if-set-p 'erc-send-completed-hook)) (set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals) - (setq erc-input-marker (make-marker) - erc-insert-marker (make-marker)) - (set-marker erc-insert-marker (point-max)) - (erc-display-prompt) - (should (= (point) erc-input-marker)) ;; Just in case erc-ring-mode is already on (setq-local erc-pre-send-functions nil) (add-hook 'erc-pre-send-functions #'erc-add-to-input-ring) -- 2.36.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-Improve-ERC-s-handling-of-multiline-prompt-input.patch >From 7bf47171db925286f293b995826b5a649702bff8 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 21 Mar 2022 05:40:16 -0700 Subject: [PATCH 3/4] Improve ERC's handling of multiline prompt input * lisp/erc/erc.el (erc--pre-send-split-functions): Add new internal hook allowing members to revise individual lines before sending. This was created with an eye toward possibly exporting it publicly as a customizable option. (erc-last-input-time): Tweak meaning of variable to match likely original intent, which is that it's only updated on successful calls to `erc-send-current-line'. (erc--discard-trailing-multiline-nulls): Conditionally truncate list of lines to be sent, skipping trailing blanks. This constitutes a behavioral change, but considering the nature of the bug being fixed, is thought to be justified. (erc--input-split): Add new internal struct containing split input lines and flag for command detection. (erc--input-line-delim-regexp): Add regex var for splitting multiline prompt input. (erc--blank-in-multiline-p): Add helper for detecting blank lines. (erc--check-prompt-input-for-multiline-blanks, erc--check-prompt-input-for-point-in-bounds, erc--check-prompt-input-for-running-process): New functions to encapsulate logic for various pre-flight idiot checks. (erc--check-prompt-input-functions): Add new hook for validating prompt input prior to clearing it. Keep it internal for now. (erc-send-current-line): pre-screen for blank lines and bail out if necessary. (erc-send-input): Add optional param to skip checking for blank lines. Call hook `erc--pre-send-split-functions'. * test/lisp/erc/erc-tests.el (erc-ring-previous-command): Use new test helper. (erc--input-line-delim-regexp, erc--blank-in-multiline-input-p): Add tests. (erc-tests--send-prep, erc-tests--set-fake-server-process, erc-tests--with-process-input-spy): Add test helpers. (erc--check-prompt-input-functions, erc-send-current-line, erc-send-whitespace-lines): Add tests. (Bug#54536) --- lisp/erc/erc.el | 161 ++++++++++++++++++++-------- test/lisp/erc/erc-tests.el | 208 +++++++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+), 41 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 6725226d11..a23ccbb0ab 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1054,6 +1054,29 @@ erc-pre-send-functions :type 'hook :version "27.1") +;; This is being auditioned for possible exporting (as a custom hook +;; option). Likewise for (public versions of) `erc--input-split' and +;; `erc--discard-trailing-multiline-nulls'. If unneeded, we'll just +;; run the latter on the input after `erc-pre-send-functions', and +;; remove this hook and the struct completely. It you need this, +;; please say so! + +(defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls) + "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. + +The struct has five slots: + + `string': The input string delivered by `erc-pre-send-functions'. + `insertp': Whether the lines should be inserted into the ERC buffer. + `sendp': Whether the lines should be sent to the IRC server. + `lines': A list of lines to be sent, each one a `string'. + `cmdp': Whether to interpret the input as a command, like /ignore. + +The `string' field is effectively read-only. When `cmdp' is non-nil, +all but the first line will be discarded.") + (defvar erc-insert-this t "Insert the text into the target buffer or not. Functions on `erc-insert-pre-hook' can set this variable to nil @@ -5526,7 +5549,7 @@ erc-end-of-input-line (point-max)) (defvar erc-last-input-time 0 - "Time of last call to `erc-send-current-line'. + "Time of last successful call to `erc-send-current-line'. If that function has never been called, the value is 0.") (defcustom erc-accidental-paste-threshold-seconds 0.2 @@ -5542,6 +5565,50 @@ erc-accidental-paste-threshold-seconds :version "26.1" :type '(choice number (other :tag "disabled" nil))) +(defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r))) + +(defun erc--blank-in-multiline-input-p (lines) + "Detect whether LINES contains a blank line. +When `erc-send-whitespace-lines' is in effect, return nil if LINES is +multiline or the first non-empty. When `erc-send-whitespace-lines' is +nil, return non-nil when any line is empty or consists of one or more +spaces, tabs, or form-feeds." + (catch 'return + (let ((multilinep (cdr lines))) + (dolist (line lines) + (when (if erc-send-whitespace-lines + (and (string-empty-p line) (not multilinep)) + (string-match (rx bot (* (in " \t\f")) eot) line)) + (throw 'return t)))))) + +(defun erc--check-prompt-input-for-multiline-blanks (_ lines) + "Return non-nil when multiline prompt input has blank LINES." + (when (erc--blank-in-multiline-input-p lines) + (if erc-warn-about-blank-lines + "Blank line - ignoring..." + 'invalid))) + +(defun erc--check-prompt-input-for-point-in-bounds (_ _) + "Return non-nil when point is before prompt." + (when (< (point) (erc-beg-of-input-line)) + "Point is not in the input area")) + +(defun erc--check-prompt-input-for-running-process (string _) + "Return non-nil unless in an active ERC server buffer." + (unless (or (erc-server-buffer-live-p) + (erc-command-no-process-p string)) + "ERC: No process running")) + +(defvar erc--check-prompt-input-functions + '(erc--check-prompt-input-for-point-in-bounds + erc--check-prompt-input-for-multiline-blanks + erc--check-prompt-input-for-running-process) + "Validators for user input typed at prompt. +Called with latest input string submitted by user and the list of lines +produced by splitting it. If any member function returns non-nil, +processing is abandoned and input is left untouched. When the returned +value is a string, pass it to `erc-error'.") + (defun erc-send-current-line () "Parse current line and send it to IRC." (interactive) @@ -5555,20 +5622,21 @@ erc-send-current-line (eolp)) (expand-abbrev)) (widen) - (if (< (point) (erc-beg-of-input-line)) - (erc-error "Point is not in the input area") + (if-let* ((str (erc-user-input)) + (msg (run-hook-with-args-until-success + 'erc--check-prompt-input-functions str + (split-string str erc--input-line-delim-regexp)))) + (when (stringp msg) + (erc-error msg)) (let ((inhibit-read-only t) - (str (erc-user-input)) (old-buf (current-buffer))) - (if (and (not (erc-server-buffer-live-p)) - (not (erc-command-no-process-p str))) - (erc-error "ERC: No process running") + (progn ; unprogn this during next major surgery (erc-set-active-buffer (current-buffer)) ;; Kill the input and the prompt (delete-region (erc-beg-of-input-line) (erc-end-of-input-line)) (unwind-protect - (erc-send-input str) + (erc-send-input str 'skip-ws-chk) ;; Fix the buffer if the command didn't kill it (when (buffer-live-p old-buf) (with-current-buffer old-buf @@ -5583,8 +5651,8 @@ erc-send-current-line (set-buffer-modified-p buffer-modified)))))) ;; Only when last hook has been run... - (run-hook-with-args 'erc-send-completed-hook str)))) - (setq erc-last-input-time now)) + (run-hook-with-args 'erc-send-completed-hook str))) + (setq erc-last-input-time now))) (switch-to-buffer "*ERC Accidental Paste Overflow*") (lwarn 'erc :warning "You seem to have accidentally pasted some text!")))) @@ -5601,21 +5669,31 @@ erc-command-regexp (cl-defstruct erc-input string insertp sendp) -(defun erc-send-input (input) +(cl-defstruct (erc--input-split (:include erc-input)) + lines cmdp) + +(defun erc--discard-trailing-multiline-nulls (state) + "Ensure last line of STATE's string is non-null. +But only when `erc-send-whitespace-lines' is non-nil. STATE is an +`erc--input-split' object." + (when (and erc-send-whitespace-lines (erc--input-split-lines state)) + (let ((reversed (nreverse (erc--input-split-lines state)))) + (when (string-empty-p (car reversed)) + (pop reversed) + (setf (erc--input-split-cmdp state) nil)) + (nreverse (seq-drop-while #'string-empty-p reversed))))) + +(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. Return non-nil only if we actually send anything." ;; Handle different kinds of inputs - (cond - ;; Ignore empty input - ((if erc-send-whitespace-lines - (string= input "") - (string-match "\\`[ \t\r\f\n]*\\'" input)) - (when erc-warn-about-blank-lines - (message "Blank line - ignoring...") - (beep)) - nil) - (t + (if (and (not skip-ws-chk) + (erc--check-prompt-input-for-multiline-blanks + input (split-string input erc--input-line-delim-regexp))) + (when erc-warn-about-blank-lines + (message "Blank line - ignoring...") ; compat + (beep)) ;; This dynamic variable is used by `erc-send-pre-hook'. It's ;; obsolete, and when it's finally removed, this binding should ;; also be removed. @@ -5635,27 +5713,28 @@ erc-send-input :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 ((string (erc-input-string state))) - (if (or (if (>= emacs-major-version 28) - (string-search "\n" string) - (string-match "\n" string)) - (not (string-match erc-command-regexp string))) - (mapc - (lambda (line) - (mapc - (lambda (line) - ;; Insert what has to be inserted for this. - (when (erc-input-insertp state) - (erc-display-msg line)) - (erc-process-input-line (concat line "\n") - (null erc-flood-protect) t)) - (or (and erc-flood-protect (erc-split-line line)) - (list line)))) - (split-string string "\n")) - (erc-process-input-line (concat string "\n") t nil)) - t)))))) + 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) + (dolist (line lines) + (dolist (line (or (and erc-flood-protect (erc-split-line line)) + (list line))) + (when (erc-input-insertp state) + (erc-display-msg line)) + (erc-process-input-line (concat line "\n") + (null erc-flood-protect) t)))) + t))))) ;; (defun erc-display-command (line) ;; (when erc-insert-this diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 8b2af6e7c8..af8cdb6016 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -297,6 +297,214 @@ erc-log-irc-protocol (kill-buffer "*erc-protocol*") (should-not erc-debug-irc-protocol))) +(ert-deftest erc--input-line-delim-regexp () + (let ((p erc--input-line-delim-regexp)) + ;; none + (should (equal '("a" "b") (split-string "a\r\nb" p))) + (should (equal '("a" "b") (split-string "a\nb" p))) + (should (equal '("a" "b") (split-string "a\rb" p))) + + ;; one + (should (equal '("") (split-string "" p))) + (should (equal '("a" "" "b") (split-string "a\r\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\nb" p))) + (should (equal '("a" "" "b") (split-string "a\r\r\nb" p))) + (should (equal '("a" "" "b") (split-string "a\n\r\nb" p))) + (should (equal '("a" "") (split-string "a\n" p))) + (should (equal '("a" "") (split-string "a\r" p))) + (should (equal '("a" "") (split-string "a\r\n" p))) + (should (equal '("" "b") (split-string "\nb" p))) + (should (equal '("" "b") (split-string "\rb" p))) + (should (equal '("" "b") (split-string "\r\nb" p))) + + ;; two + (should (equal '("" "") (split-string "\r" p))) + (should (equal '("" "") (split-string "\n" p))) + (should (equal '("" "") (split-string "\r\n" p))) + + ;; three + (should (equal '("" "" "") (split-string "\r\r" p))) + (should (equal '("" "" "") (split-string "\n\n" p))) + (should (equal '("" "" "") (split-string "\n\r" p))))) + +(ert-deftest erc--blank-in-multiline-input-p () + (let ((check (lambda (s) + (erc--blank-in-multiline-input-p + (split-string s erc--input-line-delim-regexp))))) + + (ert-info ("With `erc-send-whitespace-lines'") + (let ((erc-send-whitespace-lines t)) + (should (funcall check "")) + (should-not (funcall check "\na")) + (should-not (funcall check "/msg a\n")) ; real /cmd + (should-not (funcall check "a\n\nb")) ; "" allowed + (should-not (funcall check "/msg a\n\nb")) ; non-/cmd + (should-not (funcall check " ")) + (should-not (funcall check "\t")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\n ")) + (should-not (funcall check "a\n \t")) + (should-not (funcall check "a\n \f")) + (should-not (funcall check "a\n \nb")) + (should-not (funcall check "a\n \t\nb")) + (should-not (funcall check "a\n \f\nb")))) + + (should (funcall check "")) + (should (funcall check " ")) + (should (funcall check "\t")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n ")) + (should (funcall check "a\n \t")) + (should (funcall check "a\n \f")) + (should (funcall check "a\n \nb")) + (should (funcall check "a\n \t\nb")) + + (should-not (funcall check "a\rb")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\r\nb")))) + +(defun erc-tests--with-process-input-spy (test) + (with-current-buffer (get-buffer-create "FakeNet") + (let* ((erc-pre-send-functions + (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now + (inhibit-message noninteractive) + (erc-server-current-nick "tester") + (erc-last-input-time 0) + erc-accidental-paste-threshold-seconds + ;; + calls) + (cl-letf (((symbol-function 'erc-process-input-line) + (lambda (&rest r) (push r calls))) + ((symbol-function 'erc-server-buffer) + (lambda () (current-buffer)))) + (erc-tests--send-prep) + (funcall test (lambda () (pop calls))))) + (when noninteractive (kill-buffer)))) + +(ert-deftest erc--check-prompt-input-functions () + (erc-tests--with-process-input-spy + (lambda (next) + + (ert-info ("Errors when point not in prompt area") ; actually just dings + (insert "/msg #chan hi") + (forward-line -1) + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Point is not in the input area" (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when no process running") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "ERC: No process running" (cadr e)))) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when line contains empty newline") + (erc-bol) + (delete-region (point) (point-max)) + (insert "one\n") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Blank line - ignoring..." (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (goto-char erc-input-marker) + (looking-at "one\n"))))) + + (should (= 0 erc-last-input-time)) + (should-not (funcall next))))) + +;; These also indirectly tests `erc-send-input' + +(ert-deftest erc-send-current-line () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (should (= 0 erc-last-input-time)) + + (ert-info ("Simple command") + (insert "/msg #chan hi") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (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)))) + + (ert-info ("Simple non-command") + (insert "hi") + (erc-send-current-line) + (should (eq (point) (point-max))) + (should (save-excursion (forward-line -1) + (search-forward " hi"))) + ;; Non-ommands are forced only when `erc-flood-protect' is nil + (should (equal (funcall next) '("hi\n" nil t)))) + + (should (consp erc-last-input-time))))) + +(ert-deftest erc-send-whitespace-lines () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (setq-local erc-send-whitespace-lines t) + + (ert-info ("Multiline hunk with blank line correctly split") + (insert "one\n\ntwo") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("two\n" nil t))) + (should (equal (funcall next) '("\n" nil t))) + (should (equal (funcall next) '("one\n" nil t)))) + + (ert-info ("Multiline hunk with trailing newline filtered") + (insert "hi\n") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing carriage filtered") + (insert "hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline command with trailing blank filtered") + (pcase-dolist (`(,p . ,q) + '(("/a b\r" "/a b\n") ("/a b\n" "/a b\n") + ("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n") + ("a b\nc\n\n" "c\n" "a b\n") + ("/a b\nc\n\n" "c\n" "/a b\n") + ("/a b\n\nc\n\n" "c\n" "\n" "/a b\n"))) + (insert p) + (erc-send-current-line) + (erc-bol) + (should (eq (point) (point-max))) + (while q + (should (equal (funcall next) (list (pop q) nil t)))) + (should-not (funcall next)))) + + (ert-info ("Multiline hunk with trailing whitespace not filtered") + (insert "there\n ") + (erc-send-current-line) + (should (equal (funcall next) '(" \n" nil t))) + (should (equal (funcall next) '("there\n" nil t))) + (should-not (funcall next)))))) ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.36.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-Optionally-prevent-sending-multiline-input-in-ERC.patch >From aaf22460711d8d669da296dfbf024053270e1cef Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Wed, 27 Apr 2022 02:27:32 -0700 Subject: [PATCH 4/4] Optionally prevent sending multiline input in ERC * lisp/erc/erc.el (erc-inhibit-multiline-input): Add option to cap the number of lines to be sent before admonishing the user. (erc-ask-about-multiline-input): Add option to ask instead of warning user when `erc-inhibit-multiline-input' is reached. (erc--check-prompt-input-for-excess-lines): Add validator to check to possibly warn when too many lines are submitted for transmission. * test/lisp/erc/erc-tests.el (erc--check-prompt-input-for-excess-lines): Add test. (Bug#54536) --- lisp/erc/erc.el | 34 +++++++++++++++++++++++++++++++++- test/lisp/erc/erc-tests.el | 25 +++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index a23ccbb0ab..17bf3c9c0c 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -224,6 +224,20 @@ erc-send-whitespace-lines :group 'erc :type 'boolean) +(defcustom erc-inhibit-multiline-input nil + "Conditionally disallow input consisting of multiple lines. +Issue an error when the number of input lines submitted for sending +exceeds this value." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type '(choice integer boolean)) + +(defcustom erc-ask-about-multiline-input nil + "Ask to ignore `erc-inhibit-multiline-input' when tripped." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type 'boolean) + (defcustom erc-hide-prompt nil "If non-nil, do not display the prompt for commands. @@ -5581,6 +5595,23 @@ erc--blank-in-multiline-input-p (string-match (rx bot (* (in " \t\f")) eot) line)) (throw 'return t)))))) +(defun erc--check-prompt-input-for-excess-lines (_ lines) + "Return non-nil when trying to send too many LINES." + (when erc-inhibit-multiline-input + ;; Assume `erc--discard-trailing-multiline-nulls' is set to run + (let ((reversed (seq-drop-while #'string-empty-p (reverse lines))) + (max (if (eq erc-inhibit-multiline-input t) + 2 + erc-inhibit-multiline-input)) + (seen 0) + msg) + (while (and (pop reversed) (< (cl-incf seen) max))) + (when (= seen max) + (setq msg (format "(exceeded by %d)" (1+ (length reversed)))) + (unless (and erc-ask-about-multiline-input + (y-or-n-p (concat "Send input " msg "?"))) + (concat "Too many lines " msg)))))) + (defun erc--check-prompt-input-for-multiline-blanks (_ lines) "Return non-nil when multiline prompt input has blank LINES." (when (erc--blank-in-multiline-input-p lines) @@ -5602,7 +5633,8 @@ erc--check-prompt-input-for-running-process (defvar erc--check-prompt-input-functions '(erc--check-prompt-input-for-point-in-bounds erc--check-prompt-input-for-multiline-blanks - erc--check-prompt-input-for-running-process) + erc--check-prompt-input-for-running-process + erc--check-prompt-input-for-excess-lines) "Validators for user input typed at prompt. Called with latest input string submitted by user and the list of lines produced by splitting it. If any member function returns non-nil, diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index af8cdb6016..e956538afa 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -506,6 +506,31 @@ erc-send-whitespace-lines (should (equal (funcall next) '("there\n" nil t))) (should-not (funcall next)))))) +(ert-deftest erc--check-prompt-input-for-excess-lines () + (ert-info ("Without `erc-inhibit-multiline-input'") + (should-not erc-inhibit-multiline-input) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))) + + (ert-info ("With `erc-inhibit-multiline-input' as t (2)") + (let ((erc-inhibit-multiline-input t)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + + (ert-info ("With `erc-inhibit-multiline-input' as 3") + (let ((erc-inhibit-multiline-input 3)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b" "c"))))) + + (ert-info ("With `erc-ask-about-multiline-input'") + (let ((erc-inhibit-multiline-input t) + (erc-ask-about-multiline-input t)) + (ert-simulate-keys '(?n ?\r ?y ?\r) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + (should-not erc-ask-about-multiline-input))) + ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. -- 2.36.1 --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Tue May 17 21:34:22 2022 Received: (at 54536) by debbugs.gnu.org; 18 May 2022 01:34:22 +0000 Received: from localhost ([127.0.0.1]:58468 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nr8Zy-0008Ht-FD for submit@debbugs.gnu.org; Tue, 17 May 2022 21:34:22 -0400 Received: from mail-108-mta244.mxroute.com ([136.175.108.244]:42287) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nr8Zx-0008Hg-0O for 54536@debbugs.gnu.org; Tue, 17 May 2022 21:34:21 -0400 Received: from filter006.mxroute.com ([140.82.40.27] 140.82.40.27.vultrusercontent.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta244.mxroute.com (ZoneMTA) with ESMTPSA id 180d4cd1ce5000fc5d.001 for <54536@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Wed, 18 May 2022 01:34:13 +0000 X-Zone-Loop: 0ebc79fc62302c9de87ae98cb6479fbecbf9abec9bc9 X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=jqg6w9wr24mXhnTMYUxoUXv3Fw5EFLUJW+u7HI1z/1U=; b=X1kNsOQH0KpM3Yh8369UJeim4U gW+/0XXpW+Vy/U9d7fjEpmLJosLweG994S7XNsNtNfL2ddoeyvU8sx3iqrUBT9iKXqPZPUXg5FvBM UcZV9lrt82asBiuyCBgHEtAFL4Gc6MUDMfMM0ZBiO5kQsUbKqbP599wqz9nfL0YyBdLoAM++B+oaO EIi8CndYrJZvoONipzlF+hO0VlN/Lvai/iGzaS+mV+JJYzrY9GfffxcIoYsmMwOrAlk8iLDo0UcoD wS9i6D9qk2pCaZoU2kQaijplmdkKZ0FLVvjSsrjCmz+GcA8XH3ScV3b6DOtUHXwPXI09QdNHtre4l G1GZRVJQ==; From: "J.P." To: Will Mengarini Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input References: <87k0ckg5pn.fsf@neverwas.me> <874k1os3te.fsf@neverwas.me> Date: Tue, 17 May 2022 18:34:10 -0700 In-Reply-To: (Will Mengarini's message of "Tue, 17 May 2022 15:48:52 -0700") Message-ID: <87ilq3r5d9.fsf@neverwas.me> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 Cc: emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Will Mengarini writes: > "It you need this" should be "If you need this". Whoops! Thanks. -- "It you build it, they will come." From debbugs-submit-bounces@debbugs.gnu.org Wed May 18 01:25:31 2022 Received: (at 54536) by debbugs.gnu.org; 18 May 2022 05:25:31 +0000 Received: from localhost ([127.0.0.1]:58614 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nrCBe-0007qz-SG for submit@debbugs.gnu.org; Wed, 18 May 2022 01:25:31 -0400 Received: from mail.eskimo.com ([204.122.16.222]:48816) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nr5zp-0008CS-Jz for 54536@debbugs.gnu.org; Tue, 17 May 2022 18:48:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eskimo.com; s=default; t=1652827732; bh=34BHYdJC9mEUWrSt9f4hGt8oKOpNG0V2cqm9tondH/U=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=dzDQqrw4DS5+erEIIMeKHmsC5pXEZFr2jSl/u1Tc3XEPIfeaNFgMoOZt2cKEbTU/a /hg9NTKfjcJY+OUpmJIx/UzivlaSJEUyrMyAqLsK3NJ01fNthOUeEZGTwwXUeBtj8a BcANa0UGUW/e+CWrmFGdZvAiViSYJAN95ChIlbpYfw2axmGYJ67bYEFZRAh/iMmjSx XYUo6Qmy1DE10WCT74pG2FwlIagKXOHM8nHXgPg3mXUnF84ihrTiI2xT0/drV+2GtH nDBtZCBGohfFlkaFkazO33Eq0E0p+5Y/I82EwEjvGV6dKJVySfPxYxnKDMh50tJNtJ s3gYl83bqB/OQ== Received: from eskimo.com (debian.eskimo.com [204.122.16.15]) by mail.eskimo.com (Postfix) with SMTP id C18A83C97D1; Tue, 17 May 2022 15:48:52 -0700 (PDT) Received: (nullmailer pid 2797501 invoked by uid 25013); Tue, 17 May 2022 22:48:52 -0000 Date: Tue, 17 May 2022 15:48:52 -0700 From: Will Mengarini To: "J.P." Subject: Re: bug#54536: 29.0.50; Improve ERC's handling of multiline prompt input Message-ID: References: <87k0ckg5pn.fsf@neverwas.me> <874k1os3te.fsf@neverwas.me> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <874k1os3te.fsf@neverwas.me> X-Virus-Scanned: clamav-milter 0.103.5 at mail.eskimo.com X-Virus-Status: Clean X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 54536 X-Mailman-Approved-At: Wed, 18 May 2022 01:25:30 -0400 Cc: emacs-erc@gnu.org, 54536@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) "It you need this" should be "If you need this". From debbugs-submit-bounces@debbugs.gnu.org Fri Jul 01 21:01:46 2022 Received: (at control) by debbugs.gnu.org; 2 Jul 2022 01:01:46 +0000 Received: from localhost ([127.0.0.1]:39395 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1o7RW6-0006Ua-KL for submit@debbugs.gnu.org; Fri, 01 Jul 2022 21:01:46 -0400 Received: from mail-108-mta64.mxroute.com ([136.175.108.64]:42967) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1o7RW4-0006Og-KF for control@debbugs.gnu.org; Fri, 01 Jul 2022 21:01:45 -0400 Received: from filter006.mxroute.com ([140.82.40.27] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta64.mxroute.com (ZoneMTA) with ESMTPSA id 181bc6d659600095ec.001 for (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Sat, 02 Jul 2022 01:01:34 +0000 X-Zone-Loop: f1fa3276d4511e608dd9cead08968453d6826a014f3b X-Originating-IP: [140.82.40.27] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender: Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=Fu99PH+XJN6ng6B3JWwra0z1hGXsE+wuoCT3vST3tbo=; b=RZxECYlhkRxO4pchTxlDGWaplA NGB86MM9V1IYCw8ydby/AMb8/PkZRjlPd6SWmmw5hFqr80uKw2HkchtqtfpDOzXE5POwFDR3xx/XX dpaPlLVbQyaINpASQREsChhqpdTkES9C/YywO6aII4vOFmG/HNRx2ReJrwCf37WKvLTsb/Vs7cKpH UrqLdAiD8jRqQziKG3J9dpn9NIozktbcLXMq2ISYkCFEKlVI4KrUhqiY/UI9maaEXZHryHvf5rHoE Wj6pqf/g81fId2KrOK+4+ovKjM0UD7uZ1CLyCpAfVDNEPZqnu0jK2R8aOQ0vTBdKLVtIwEsttKUNm uoTBCfxA==; From: "J.P." To: control@debbugs.gnu.org Subject: control message for bug #54536 Date: Fri, 01 Jul 2022 18:01:32 -0700 Message-ID: <87h7408h03.fsf@neverwas.me> MIME-Version: 1.0 Content-Type: text/plain X-AuthUser: masked@neverwas.me X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) close 54536 29.1 quit Thanks to those who gave feedback, here and on Libera. From unknown Sun Jun 15 13:01:06 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Sat, 30 Jul 2022 11:24:07 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator