[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 69ca2cc1138 05/19: Add utility for iterating over arrays in ERC
From: |
F. Jason Park |
Subject: |
master 69ca2cc1138 05/19: Add utility for iterating over arrays in ERC |
Date: |
Sun, 17 Dec 2023 23:21:37 -0500 (EST) |
branch: master
commit 69ca2cc1138b0fe722d601c2113c83f2a6f791ed
Author: F. Jason Park <jp@neverwas.me>
Commit: F. Jason Park <jp@neverwas.me>
Add utility for iterating over arrays in ERC
* lisp/erc/erc-common.el (erc--doarray): Add macro for mapping over
arrays. ERC has the uncommon requirement of having to repeatedly
traverse strings that contain flags for advertised server features.
It doesn't make sense to translate these meanings into enums or
dynamically generate variables for each flag. Hash tables and lists
require additional setup and aren't as compact to inspect.
* lisp/erc/erc-dcc.el (erc-dcc-handle-ctcp-send): Use `string-search'
instead of `seq-contains-p' even though performance doesn't matter
here.
* lisp/erc/erc.el (erc--channel-mode-types): Use `erc--doarray'
instead of `dolist'.
(erc--process-channel-modes): Use `erc--doarray' instead of `dolist',
and don't create a string from current char until needed.
(erc--parse-user-modes): Use `erc--doarray' instead of `dolist'.
* test/lisp/erc/erc-tests.el (erc--doarray): New test. (Bug#67677)
---
lisp/erc/erc-common.el | 19 +++++++++++++++++++
lisp/erc/erc-dcc.el | 4 ++--
lisp/erc/erc.el | 35 ++++++++++++++++-------------------
test/lisp/erc/erc-tests.el | 13 +++++++++++++
4 files changed, 50 insertions(+), 21 deletions(-)
diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index c79954cdee5..fd6ad476641 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -543,6 +543,25 @@ the resulting variables will end up with more useful doc
strings."
(declare (indent 1))
`(erc--define-catalog ,language ,entries))
+(defmacro erc--doarray (spec &rest body)
+ "Map over ARRAY, running BODY with VAR bound to iteration element.
+Behave more or less like `seq-doseq', but tailor operations for
+arrays.
+
+\(fn (VAR ARRAY [RESULT]) BODY...)"
+ (declare (indent 1) (debug ((symbolp form &optional form) body)))
+ (let ((array (make-symbol "array"))
+ (len (make-symbol "len"))
+ (i (make-symbol "i")))
+ `(let* ((,array ,(nth 1 spec))
+ (,len (length ,array))
+ (,i 0))
+ (while-let (((< ,i ,len))
+ (,(car spec) (aref ,array ,i)))
+ ,@body
+ (cl-incf ,i))
+ ,(nth 2 spec))))
+
(provide 'erc-common)
;;; erc-common.el ends here
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index 3bcdfb96eb8..ac7fc817cb9 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -713,8 +713,8 @@ It extracts the information about the dcc request and adds
it to
(port (match-string 4 query))
(size (match-string 5 query))
(sub (substring (match-string 6 query) 0 -4))
- (secure (seq-contains-p sub ?S #'eq))
- (turbo (seq-contains-p sub ?T #'eq)))
+ (secure (string-search "S" sub))
+ (turbo (string-search "T" sub)))
;; FIXME: a warning really should also be sent
;; if the ip address != the host the dcc sender is on.
(erc-display-message
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index c499afb22f7..4d027f0e6c4 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -6781,7 +6781,7 @@ Use the getter of the same name to retrieve the current
value.")
(ct (make-char-table 'erc--channel-mode-types))
(type ?a))
(dolist (cs types)
- (dolist (c (append cs nil))
+ (erc--doarray (c cs)
(aset ct c type))
(cl-incf type))
(make-erc--channel-mode-types :key key
@@ -6800,21 +6800,20 @@ complement relevant letters in STRING."
(table (erc--channel-mode-types-table obj))
(fallbackp (erc--channel-mode-types-fallbackp obj))
(+p t))
- (dolist (c (append string nil))
- (let ((letter (char-to-string c)))
- (cond ((= ?+ c) (setq +p t))
- ((= ?- c) (setq +p nil))
- ((and status-letters (string-search letter status-letters))
- (erc--update-membership-prefix (pop args) c (if +p 'on 'off)))
- ((and-let* ((group (or (aref table c) (and fallbackp ?d))))
- (erc--handle-channel-mode group c +p
- (and (/= group ?d)
- (or (/= group ?c) +p)
- (pop args)))
- t))
- ((not fallbackp)
- (erc-display-message nil '(notice error) (erc-server-buffer)
- (format "Unknown channel mode: %S" c))))))
+ (erc--doarray (c string)
+ (cond ((= ?+ c) (setq +p t))
+ ((= ?- c) (setq +p nil))
+ ((and status-letters (string-search (string c) status-letters))
+ (erc--update-membership-prefix (pop args) c (if +p 'on 'off)))
+ ((and-let* ((group (or (aref table c) (and fallbackp ?d))))
+ (erc--handle-channel-mode group c +p
+ (and (/= group ?d)
+ (or (/= group ?c) +p)
+ (pop args)))
+ t))
+ ((not fallbackp)
+ (erc-display-message nil '(notice error) (erc-server-buffer)
+ (format "Unknown channel mode: %S" c)))))
(setq erc-channel-modes (sort erc-channel-modes #'string<))
(setq erc--mode-line-mode-string
(concat "+" (erc--channel-modes erc--mode-line-chanmodes-arg-len)))
@@ -6894,9 +6893,7 @@ dropped were they not already absent."
(let ((addp t)
;;
redundant-add redundant-drop adding dropping)
- ;; For short strings, `append' appears to be no slower than
- ;; iteration var + `aref' or `mapc' + closure.
- (dolist (c (append string nil))
+ (erc--doarray (c string)
(pcase c
(?+ (setq addp t))
(?- (setq addp nil))
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 1b610a367b6..361e12c2a91 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -142,6 +142,19 @@
(widget-editable-list-match w v))
'(face)))))
+(ert-deftest erc--doarray ()
+ (let ((array "abcdefg")
+ out)
+ ;; No return form.
+ (should-not (erc--doarray (c array) (push c out)))
+ (should (equal out '(?g ?f ?e ?d ?c ?b ?a)))
+
+ ;; Return form evaluated upon completion.
+ (setq out nil)
+ (should (= 42 (erc--doarray (c array (+ 39 (length out)))
+ (when (cl-evenp c) (push c out)))))
+ (should (equal out '(?f ?d ?b)))))
+
(defun erc-tests--send-prep ()
;; Caller should probably shadow `erc-insert-modify-hook' or
;; populate user tables for erc-button.
- master updated (64a4904353f -> 8e06f224a9e), F. Jason Park, 2023/12/17
- master 61b22ae9f37 03/19: Sequester some special-variable declarations in ERC, F. Jason Park, 2023/12/17
- master 0f058244ab7 18/19: Cache shortened channel names in erc-track, F. Jason Park, 2023/12/17
- master 49bfea4386f 12/19: Use templates for formatting chat messages in ERC, F. Jason Park, 2023/12/17
- master 1e2b156f040 04/19: Double hyphenate internal ERC 5.6 text props, F. Jason Park, 2023/12/17
- master b5da8ba8070 02/19: Define ERC message-formatting templates with defvar, F. Jason Park, 2023/12/17
- master 69ca2cc1138 05/19: Add utility for iterating over arrays in ERC,
F. Jason Park <=
- master 4ee4865ce20 07/19: Add erc-server-396 response handler, F. Jason Park, 2023/12/17
- master 741bce84890 16/19: Forgo excess nick buttonizing on JOINs and QUITs, F. Jason Park, 2023/12/17
- master 7c2e02e6d79 01/19: Remove module from suggested lineup in ERC's manual, F. Jason Park, 2023/12/17
- master 11bae96d23b 08/19: Clarify warning for process-dependent input in ERC, F. Jason Park, 2023/12/17
- master 6e4417eaa7e 14/19: Consolidate status-prefix slots of erc-channel-user, F. Jason Park, 2023/12/17
- master 7db500b50be 09/19: Make erc-get-user-mode-prefix more flexible, F. Jason Park, 2023/12/17
- master 9d961b31070 13/19: Demote erc-fill-line-spacing to a normal variable, F. Jason Park, 2023/12/17
- master c1befaf0a8b 10/19: Skip erc-ignored-user-p when erc-ignore-list is empty, F. Jason Park, 2023/12/17
- master 236a416be76 11/19: Add erc--spkr text property to chat messages, F. Jason Park, 2023/12/17
- master 951b115c2ac 06/19: Make erc-input's refoldp slot conditionally available, F. Jason Park, 2023/12/17