summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorF. Jason Park <jp@neverwas.me>2022-04-27 02:27:32 -0700
committerF. Jason Park <jp@neverwas.me>2022-06-30 15:19:53 -0700
commit10237840d03c4ba647fd3045ee500af950a5df6e (patch)
tree80c58e07ade459bb1db98c0c051406a2e82b1ca1
parentf46547294d2684d80bb473bd4c85f273ff661a7d (diff)
downloademacs-10237840d03c4ba647fd3045ee500af950a5df6e.tar.gz
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 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)
-rw-r--r--lisp/erc/erc.el34
-rw-r--r--test/lisp/erc/erc-tests.el25
2 files changed, 58 insertions, 1 deletions
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 89ce713fe02..6f17e4ee7b7 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -260,6 +260,20 @@ node `(auth) Top' and info node `(erc) Connecting'.")
: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-prompt-hidden ">"
"Text to show in lieu of the prompt when hidden."
:package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release
@@ -5890,6 +5904,23 @@ is empty or consists of one or more spaces, tabs, or form-feeds."
(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)
@@ -5911,7 +5942,8 @@ is empty or consists of one or more spaces, tabs, or form-feeds."
(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
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 986988a3356..62bea8fb3f0 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -797,6 +797,31 @@
(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.