From: F. Jason Park Date: Tue, 25 Oct 2022 05:58:13 +0000 (-0700) Subject: Warn of future breaking change to erc-response.tags X-Git-Tag: emacs-29.0.90~1616^2~132 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=d4028ead897464c9799847900b4acb2276acaac6;p=emacs.git Warn of future breaking change to erc-response.tags * lisp/erc/erc-backend.el (erc-parse-tags-format): New option to determine type of the `erc-response' "tags" field. (erc-parse-tags): Defer to internal generic function. (erc--parse-tags): New function to hold original `erc-parse-tags' implementation. (erc--parse-message-tags): New generic function that conditionally calls `erc--parse-tags', perhaps emitting a warning beforehand. (erc-parse-server-response): Call `erc--parse-message-tags'. (Bug#58797.) --- diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 51c92e0f12a..d49e6a5f1a8 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -1122,8 +1122,37 @@ See also `erc-server-send'." ;;;; Handling responses +(defcustom erc-tags-format 'overridable + "Shape of the `tags' alist in `erc-response' objects. +When set to `legacy', pre-5.5 parsing behavior takes effect for +the tags portion of every message. The resulting alist contains +conses of the form (STRING . LIST), in which LIST is comprised of +at most one, possibly empty string. When set to nil, ERC only +parses tags if an active module defines an implementation. It +otherwise ignores them. In such cases, each alist element is a +cons of a symbol and an optional, nonempty string. + +With the default value of `overridable', ERC behaves as it does +with `legacy' except that it emits a warning whenever first +encountering a message containing tags in a given Emacs session. +But it only does so when a module implementing overriding, +non-legacy behavior isn't already active in the current network +context. + +Note that future bundled modules providing IRCv3 functionality +will not be compatible with the legacy format. User code should +eventually transition to expecting this \"5.5+ variant\" and set +this option to nil." + :package-version '(ERC . "5.4.1") ; FIXME increment on next release + :type '(choice (const nil) + (const legacy) + (const overridable))) + (defun erc-parse-tags (string) "Parse IRCv3 tags list in STRING to a (tag . value) alist." + (erc--parse-message-tags string)) + +(defun erc--parse-tags (string) (let ((tags) (tag-strings (split-string string ";"))) (dolist (tag-string tag-strings tags) @@ -1133,6 +1162,28 @@ See also `erc-server-send'." `(,pair)) tags))))) +;; A benefit of this function being internal is not having to define a +;; separate method just to ensure an `erc-tags-format' value of +;; `legacy' always wins. A downside is that module code must take +;; care to preserve that promise manually. + +(cl-defgeneric erc--parse-message-tags (string) + "Parse STRING into an alist of (TAG . VALUE) conses. +Expect TAG to be a symbol and VALUE nil or a nonempty string. +Don't split composite raw-input values containing commas; +instead, leave them as a single string." + (when erc-tags-format + (unless (or (eq erc-tags-format 'legacy) + (get 'erc-parse-tags 'erc-v3-warned-p)) + (put 'erc-parse-tags 'erc-v3-warned-p t) + (display-warning + 'ERC + (concat + "Legacy ERC tags behavior is currently in effect, but other modules," + " including those bundled with ERC, may override this in future" + " releases. See `erc-tags-format' for more info."))) + (erc--parse-tags string))) + (defun erc-parse-server-response (proc string) "Parse and act upon a complete line from an IRC server. PROC is the process (connection) from which STRING was received. @@ -1142,9 +1193,9 @@ PROCs `process-buffer' is `current-buffer' when this function is called." (let* ((tag-list (when (eq (aref string 0) ?@) (substring string 1 (string-search " " string)))) - (msg (make-erc-response :unparsed string :tags (when tag-list - (erc-parse-tags - tag-list)))) + (msg (make-erc-response :unparsed string :tags + (when tag-list + (erc--parse-message-tags tag-list)))) (string (if tag-list (substring string (+ 1 (string-search " " string))) string)) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index d8aac36eab6..23a19337986 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -77,6 +77,9 @@ (cl-defstruct (erc--target-channel (:include erc--target))) (cl-defstruct (erc--target-channel-local (:include erc--target-channel))) +;; Beginning in 5.5/29.1, the `tags' field may take on one of two +;; differing types. See `erc-tags-format' for details. + (cl-defstruct (erc-response (:conc-name erc-response.)) (unparsed "" :type string) (sender "" :type string)