Simplify ISUPPORT-derived data wrangling in ERC

* lisp/erc/erc-backend.el (erc--get-isupport-entry): Check server
buffer for `erc-server-parameters' when (re)initializing value.  This
function was previously unreliable from a target buffer on cache
misses.
(erc--with-isupport-data): New macro for accessing and caching data
derived from an ISUPPORT parameter.  Late-arriving params break the
cache.
(erc-server-005): Rewrite pattern as `rx' form, factoring out bol/eol.
* lisp/erc/erc-common.el (erc--isupport-data): New struct to be
subclassed for storing cached ISUPPORT-derived data.
* test/lisp/erc/erc-scenarios-display-message.el: Remove stray
`require'.  (Bug#67220)
This commit is contained in:
F. Jason Park 2023-11-13 18:24:59 -08:00
parent cc7e008dce
commit b088222ec9
3 changed files with 29 additions and 5 deletions

View file

@ -2098,7 +2098,9 @@ primitive value."
(erc-with-server-buffer erc--isupport-params)))
(value (with-memoization (gethash key table)
(when-let ((v (assoc (symbol-name key)
erc-server-parameters)))
(or erc-server-parameters
(erc-with-server-buffer
erc-server-parameters)))))
(if (cdr v)
(erc--parse-isupport-value (cdr v))
'--empty--)))))
@ -2108,6 +2110,22 @@ primitive value."
(when table
(remhash key table))))
;; While it's better to depend on interfaces than specific types,
;; using `cl-struct-slot-value' or similar to extract a known slot at
;; runtime would incur a small "ducktyping" tax, which should probably
;; be avoided when running dozens of times per incoming message.
(defmacro erc--with-isupport-data (param var &rest body)
"Return structured data stored in VAR for \"ISUPPORT\" PARAM.
Expect VAR's value to be an instance of `erc--isupport-data'. If
VAR is uninitialized or stale, evaluate BODY and assign the
result to VAR."
(declare (indent defun))
`(erc-with-server-buffer
(pcase-let (((,@(list '\` (list param '\, 'key)))
(erc--get-isupport-entry ',param)))
(or (and ,var (eq key (erc--isupport-data-key ,var)) ,var)
(setq ,var (progn ,@body))))))
(define-erc-response-handler (005)
"Set the variable `erc-server-parameters' and display the received message.
@ -2128,8 +2146,11 @@ A server may send more than one 005 message."
key
value
negated)
(when (string-match "^\\([A-Z]+\\)=\\(.*\\)$\\|^\\(-\\)?\\([A-Z]+\\)$"
section)
(when (string-match
(rx bot (| (: (group (+ (any "A-Z"))) "=" (group (* nonl)))
(: (? (group "-")) (group (+ (any "A-Z")))))
eot)
section)
(setq key (or (match-string 1 section) (match-string 4 section))
value (match-string 2 section)
negated (and (match-string 3 section) '-))

View file

@ -101,6 +101,11 @@
(contents "" :type string)
(tags '() :type list))
(cl-defstruct erc--isupport-data
"Abstract \"class\" for parsed ISUPPORT data.
For use with the macro `erc--with-isupport-data'."
(key nil :type (or null cons)))
;; After dropping 28, we can use prefixed "erc-autoload" cookies.
(defun erc--normalize-module-symbol (symbol)
"Return preferred SYMBOL for `erc--modules'."

View file

@ -59,6 +59,4 @@
(erc-cmd-QUIT "")))
(eval-when-compile (require 'erc-join))
;;; erc-scenarios-display-message.el ends here