aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorF. Jason Park2023-06-01 22:07:03 -0700
committerF. Jason Park2023-06-11 19:18:14 -0700
commit67f7ac2bbee2f58d919232682f6ea9e7039eb5f3 (patch)
treef18940773162a6e8d6b51584b1425e1221b734d3
parentbd969326e96584249b6c140d972f7b27ab3274f6 (diff)
downloademacs-67f7ac2bbee2f58d919232682f6ea9e7039eb5f3.tar.gz
emacs-67f7ac2bbee2f58d919232682f6ea9e7039eb5f3.zip
Deprecate nicknames entry in erc-button-alist
* lisp/erc/erc-button.el (erc-button-mode, erc-button-enable, erc-button-disable): Restore running `erc-button-setup' on `erc-mode-hook' and also do so immediately in all ERC buffers. Do this instead of calling `erc-button--check-nicknames-entry. (erc-button-buttonize-nicks): Mention that this option's value must be non-nil for all but the most basic client functionality. (erc-button-alist): Remove `nicknames' entry entirely. Describe deprecation, replacement behavior, and available escape hatches in doc string. Update and improve custom type definition, in particular, by including long supported but never mentioned variants for the "REGEXP" field. (erc-button-keys-added): Deprecate because unused and misleading: keys are bound during module init and remain so while module is enabled. (erc-button--has-nickname-entry): New variable to indicate whether to follow legacy code path when a `nicknames' entry exists in `erc-button-alist'. (erc-button-setup): Rewrite to provide warnings about deprecated values for `erc-button-alist'. (erc-button-nickname-callback-function): Add escape hatch for those needing a custom callback for what was the default `nickname' entry in `erc-button-alist'. (erc-button-add-buttons): Always run `erc-button-add-nickname-buttons' unless `erc-button--has-nickname-entry' is non-nil. (erc-button--maybe-warn-arbitrary-sexp, erc-button--extract-form): Rename former to latter and abstain from emitting a warning. (erc-button--check-nicknames-entry): Remove unused function. (erc-button-add-nickname-buttons): Defer to `erc-button--extract-form' for determining value of third FORM slot of entry. (erc-button-add-buttons-1): Call renamed version of `erc-button--maybe-warn-arbitrary-sexp'. (Bug#60933)
-rw-r--r--lisp/erc/erc-button.el137
1 files changed, 81 insertions, 56 deletions
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 33b93ff6744..3045bb44889 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -52,13 +52,15 @@
52;;;###autoload(autoload 'erc-button-mode "erc-button" nil t) 52;;;###autoload(autoload 'erc-button-mode "erc-button" nil t)
53(define-erc-module button nil 53(define-erc-module button nil
54 "This mode buttonizes all messages according to `erc-button-alist'." 54 "This mode buttonizes all messages according to `erc-button-alist'."
55 ((erc-button--check-nicknames-entry) 55 ((add-hook 'erc-insert-modify-hook #'erc-button-add-buttons 'append)
56 (add-hook 'erc-insert-modify-hook #'erc-button-add-buttons 'append)
57 (add-hook 'erc-send-modify-hook #'erc-button-add-buttons 'append) 56 (add-hook 'erc-send-modify-hook #'erc-button-add-buttons 'append)
57 (add-hook 'erc-mode-hook #'erc-button-setup 91)
58 (unless erc--updating-modules-p (erc-buffer-do #'erc-button-setup))
58 (add-hook 'erc--tab-functions #'erc-button-next) 59 (add-hook 'erc--tab-functions #'erc-button-next)
59 (erc--modify-local-map t "<backtab>" #'erc-button-previous)) 60 (erc--modify-local-map t "<backtab>" #'erc-button-previous))
60 ((remove-hook 'erc-insert-modify-hook #'erc-button-add-buttons) 61 ((remove-hook 'erc-insert-modify-hook #'erc-button-add-buttons)
61 (remove-hook 'erc-send-modify-hook #'erc-button-add-buttons) 62 (remove-hook 'erc-send-modify-hook #'erc-button-add-buttons)
63 (remove-hook 'erc-mode-hook #'erc-button-setup)
62 (remove-hook 'erc--tab-functions #'erc-button-next) 64 (remove-hook 'erc--tab-functions #'erc-button-next)
63 (erc--modify-local-map nil "<backtab>" #'erc-button-previous))) 65 (erc--modify-local-map nil "<backtab>" #'erc-button-previous)))
64 66
@@ -103,7 +105,10 @@ longer than `erc-fill-column'."
103 :type '(choice integer boolean)) 105 :type '(choice integer boolean))
104 106
105(defcustom erc-button-buttonize-nicks t 107(defcustom erc-button-buttonize-nicks t
106 "Flag indicating whether nicks should be buttonized or not." 108 "Flag indicating whether nicks should be buttonized.
109Note that beginning in ERC 5.6, some functionality provided by
110other modules, such as `fill-wrap', may depend on this option
111being non-nil."
107 :type 'boolean) 112 :type 'boolean)
108 113
109(defcustom erc-button-rfc-url "https://tools.ietf.org/html/rfc%s" 114(defcustom erc-button-rfc-url "https://tools.ietf.org/html/rfc%s"
@@ -126,8 +131,7 @@ longer than `erc-fill-column'."
126 ;; a button, it makes no sense to optimize performance by 131 ;; a button, it makes no sense to optimize performance by
127 ;; bytecompiling lambdas in this alist. On the other hand, it makes 132 ;; bytecompiling lambdas in this alist. On the other hand, it makes
128 ;; things hard to maintain. 133 ;; things hard to maintain.
129 '((nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0) 134 '((erc-button-url-regexp 0 t browse-url-button-open-url 0)
130 (erc-button-url-regexp 0 t browse-url-button-open-url 0)
131 ;; ("<URL: *\\([^<> ]+\\) *>" 0 t browse-url-button-open-url 1) 135 ;; ("<URL: *\\([^<> ]+\\) *>" 0 t browse-url-button-open-url 1)
132;;; ("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3) 136;;; ("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3)
133 ;; emacs internal 137 ;; emacs internal
@@ -159,41 +163,45 @@ REGEXP is the string matching text around the button or a symbol
159 strings, or an alist with the strings in the car. Note that 163 strings, or an alist with the strings in the car. Note that
160 entries in lists or alists are considered to be nicks or other 164 entries in lists or alists are considered to be nicks or other
161 complete words. Therefore they are enclosed in \\< and \\> 165 complete words. Therefore they are enclosed in \\< and \\>
162 while searching. REGEXP can also be the symbol 166 while searching. Also, use of the special symbol `nicknames'
163 `nicknames', which matches the nickname of any user on the 167 for this slot was deprecated in ERC 5.6, but users can still
164 current server. 168 use `erc-button-buttonize-nicks' to control whether nicks get
169 buttonized. And because customizing a corresponding CALLBACK
170 is no longer possible, an escape hatch has been provided via
171 the variable `erc-button-nickname-callback-function'.
165 172
166BUTTON is the number of the regexp grouping actually matching the 173BUTTON is the number of the regexp grouping actually matching the
167 button. This is ignored if REGEXP is `nicknames'. 174 button.
168 175
169FORM is either a boolean or a special variable whose value must 176FORM is either a boolean or a special variable whose value must
170 be non-nil for the button to be added. When REGEXP is the 177 be non-nil for the button to be added. It can also be a
171 special symbol `nicknames', FORM must be the symbol 178 function to call in place of `erc-button-add-button' with the
172 `erc-button-buttonize-nicks'. Anything else is deprecated. 179 exact same arguments. When FORM is also a special variable,
173 For all other entries, FORM can also be a function to call in 180 ERC disregards the variable and calls the function. Note that
174 place of `erc-button-add-button' with the exact same arguments. 181 arbitrary s-expressions were deprecated in ERC 5.6 and may not
175 When FORM is also a special variable, ERC disregards the 182 be respected in the future. If necessary, users can instead
176 variable and calls the function. 183 supply a function that calls `erc-button-add-button' when such
184 an expression is non-nil.
177 185
178CALLBACK is the function to call when the user push this button. 186CALLBACK is the function to call when the user push this button.
179 CALLBACK can also be a symbol. Its variable value will be used 187 CALLBACK can also be a symbol. Its variable value will be used
180 as the callback function. 188 as the callback function.
181 189
182PAR is a number of a regexp grouping whose text will be passed to 190PAR is a number of a regexp grouping whose text will be passed to
183 CALLBACK. There can be several PAR arguments. If REGEXP is 191 CALLBACK. There can be several PAR arguments."
184 `nicknames', these are ignored, and CALLBACK will be called with
185 the nickname matched as the argument."
186 :package-version '(ERC . "5.6") ; FIXME sync on release 192 :package-version '(ERC . "5.6") ; FIXME sync on release
187 :type '(repeat 193 :type '(repeat
188 (list :tag "Button" 194 (list :tag "Button"
189 (choice :tag "Matches" 195 (choice :tag "Matches"
190 regexp 196 regexp
191 (variable :tag "Variable containing regexp") 197 (variable :tag "Variable containing regexp")
192 (const :tag "Nicknames" nicknames)) 198 (repeat :tag "List of words" string)
199 (alist :key-type string :value-type sexp))
193 (integer :tag "Number of the regexp section that matches") 200 (integer :tag "Number of the regexp section that matches")
194 (choice :tag "When to buttonize" 201 (choice :tag "When to buttonize"
195 (const :tag "Always" t) 202 (const :tag "Always" t)
196 (sexp :tag "Only when this evaluates to non-nil")) 203 (function :tag "Alternative buttonizing function")
204 (variable :tag "Var with value treated as boolean"))
197 (function :tag "Function to call when button is pressed") 205 (function :tag "Function to call when button is pressed")
198 (repeat :tag "Sections of regexp to send to the function" 206 (repeat :tag "Sections of regexp to send to the function"
199 :inline t 207 :inline t
@@ -239,15 +247,40 @@ constituents.")
239(defvar erc-button-keys-added nil 247(defvar erc-button-keys-added nil
240 "Internal variable used to keep track of whether we've added the 248 "Internal variable used to keep track of whether we've added the
241global-level ERC button keys yet.") 249global-level ERC button keys yet.")
250(make-obsolete-variable 'erc-button-keys-added "no longer relevant" "30.1")
251
252(defvar-local erc-button--has-nickname-entry nil
253 "Whether `erc-button-alist' contains a legacy `nicknames' entry.")
242 254
243;; Maybe deprecate this function and `erc-button-keys-added' if they
244;; continue to go unused for a another version (currently 5.6).
245(defun erc-button-setup () 255(defun erc-button-setup ()
246 "Add ERC mode-level button movement keys. This is only done once." 256 "Perform major-mode setup for ERC's button module.
247 ;; Add keys. 257Note that prior to ERC 5.6, this function used to modify
248 (unless erc-button-keys-added 258`erc-mode-map', but that's now handled by the mode toggles
249 (define-key erc-mode-map (kbd "<backtab>") #'erc-button-previous) 259themselves."
250 (setq erc-button-keys-added t))) 260 (setq erc-button-keys-added t)
261 (cl-assert (derived-mode-p 'erc-mode))
262 ;; It would probably suffice to run this in server buffers alone,
263 ;; even though buttonizing happens in all ERC buffers and users have
264 ;; been known to set `erc-button-alist' locally.
265 (dolist (entry erc-button-alist)
266 (pcase entry
267 ((or `(nicknames ,_ ,sym . ,_) `('nicknames ,_ ,sym . ,_))
268 (setq erc-button--has-nickname-entry t)
269 (unless (eq sym 'erc-button-buttonize-nicks)
270 (erc--warn-once-before-connect 'erc-button-mode
271 "The legacy `nicknames' entry in `erc-button-alist'"
272 " is deprecated. See doc string for details.")))
273 ((and `(,_ ,_ ,form . ,_)
274 (guard (not (or (and (symbolp form)
275 (special-variable-p form))
276 (functionp form)))))
277 (erc--warn-once-before-connect 'erc-button-mode
278 "Arbitrary sexps for the third, FORM slot of `erc-button-alist'"
279 " entries are deprecated. Either use a variable or a function"
280 " that conditionally calls `erc-button-add-button'.")))))
281
282(defvar erc-button-nickname-callback-function #'erc-nick-popup
283 "Escape hatch for those needing a different nickname callback.")
251 284
252(defun erc-button-add-buttons () 285(defun erc-button-add-buttons ()
253 "Find external references in the current buffer and make buttons of them. 286 "Find external references in the current buffer and make buttons of them.
@@ -261,6 +294,11 @@ specified by `erc-button-alist'."
261 (alist erc-button-alist) 294 (alist erc-button-alist)
262 regexp) 295 regexp)
263 (erc-button-remove-old-buttons) 296 (erc-button-remove-old-buttons)
297 (unless (or erc-button--has-nickname-entry
298 (not erc-button-buttonize-nicks))
299 (erc-button-add-nickname-buttons
300 `(_ _ erc-button--modify-nick-function
301 ,erc-button-nickname-callback-function)))
264 (dolist (entry alist) 302 (dolist (entry alist)
265 (if (or (eq (car entry) 'nicknames) 303 (if (or (eq (car entry) 'nicknames)
266 ;; Old form retained for backward compatibility. 304 ;; Old form retained for backward compatibility.
@@ -284,28 +322,18 @@ specified by `erc-button-alist'."
284 (concat "\\<" (regexp-quote (car elem)) "\\>") 322 (concat "\\<" (regexp-quote (car elem)) "\\>")
285 entry))))))))))) 323 entry)))))))))))
286 324
287(defun erc-button--maybe-warn-arbitrary-sexp (form) 325(defun erc-button--extract-form (form)
288 (cl-assert (not (booleanp form))) ; covered by caller
289 ;; If a special-variable is also a function, favor the function. 326 ;; If a special-variable is also a function, favor the function.
290 (cond ((functionp form) form) 327 (cond ((eq t form) t)
291 ((and (symbolp form) (special-variable-p form)) (symbol-value form)) 328 ((functionp form) form)
292 (t (unless (get 'erc-button--maybe-warn-arbitrary-sexp 329 ((and (symbolp form) (special-variable-p form))
293 'warned-arbitrary-sexp) 330 (while (let ((val (symbol-value form)))
294 (put 'erc-button--maybe-warn-arbitrary-sexp 331 (prog1 (and (not (eq val form))
295 'warned-arbitrary-sexp t) 332 (symbolp val)
296 (lwarn 'erc :warning (concat "Arbitrary sexps for the third FORM" 333 (special-variable-p val))
297 " slot of `erc-button-alist' entries" 334 (setq form val))))
298 " have been deprecated."))) 335 form)
299 (eval form t)))) 336 (t (eval form t))))
300
301(defun erc-button--check-nicknames-entry ()
302 ;; This helper exists because the module is defined after its options.
303 (when (eq major-mode 'erc-mode)
304 (unless (eq (nth 1 (alist-get 'nicknames erc-button-alist))
305 'erc-button-buttonize-nicks)
306 (erc-button--display-error-notice-with-keys-and-warn
307 "Values other than `erc-button-buttonize-nicks' in the third slot of "
308 "the `nicknames' entry of `erc-button-alist' are deprecated."))))
309 337
310(cl-defstruct erc-button--nick 338(cl-defstruct erc-button--nick
311 ( bounds nil :type cons 339 ( bounds nil :type cons
@@ -405,12 +433,10 @@ retrieve it during buttonizing via
405 "Search through the buffer for nicknames, and add buttons." 433 "Search through the buffer for nicknames, and add buttons."
406 (let ((form (nth 2 entry)) 434 (let ((form (nth 2 entry))
407 (fun (nth 3 entry)) 435 (fun (nth 3 entry))
436 (erc-button-buttonize-nicks (and erc-button-buttonize-nicks
437 erc-button--modify-nick-function))
408 bounds word) 438 bounds word)
409 (when (eq form 'erc-button-buttonize-nicks) 439 (when (and form (setq form (erc-button--extract-form form)))
410 (setq form (and (symbol-value form) erc-button--modify-nick-function)))
411 (when (or (functionp form)
412 (eq t form)
413 (and form (erc-button--maybe-warn-arbitrary-sexp form)))
414 (goto-char (point-min)) 440 (goto-char (point-min))
415 (while (erc-forward-word) 441 (while (erc-forward-word)
416 (when (setq bounds (erc-bounds-of-word-at-point)) 442 (when (setq bounds (erc-bounds-of-word-at-point))
@@ -456,8 +482,7 @@ retrieve it during buttonizing via
456 (and-let* 482 (and-let*
457 ((raw-form (nth 2 entry)) 483 ((raw-form (nth 2 entry))
458 (res (or (eq t raw-form) 484 (res (or (eq t raw-form)
459 (erc-button--maybe-warn-arbitrary-sexp 485 (erc-button--extract-form raw-form))))
460 raw-form))))
461 (if (functionp res) res #'erc-button-add-button))))) 486 (if (functionp res) res #'erc-button-add-button)))))
462 (let ((start (match-beginning (nth 1 entry))) 487 (let ((start (match-beginning (nth 1 entry)))
463 (end (match-end (nth 1 entry))) 488 (end (match-end (nth 1 entry)))