]> git.eshelyaron.com Git - emacs.git/commitdiff
Warn of future breaking change to erc-response.tags
authorF. Jason Park <jp@neverwas.me>
Tue, 25 Oct 2022 05:58:13 +0000 (22:58 -0700)
committerF. Jason Park <jp@neverwas.me>
Thu, 17 Nov 2022 05:34:36 +0000 (21:34 -0800)
* 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.)

lisp/erc/erc-backend.el
lisp/erc/erc-common.el

index 51c92e0f12a451ac55cba156049c171227e58607..d49e6a5f1a8d28733e74a80787bdc7cc20cc1e87 100644 (file)
@@ -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))
index d8aac36eab6e4d8707840b43855fb7f0a0067d45..23a193379861d2b2079177368669325dab72dace 100644 (file)
@@ -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)