aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorF. Jason Park2023-04-14 00:07:31 -0700
committerF. Jason Park2023-05-05 17:18:01 -0700
commitb0d761be0f9b0180566d7cde1ef2eea33402dd4e (patch)
treeb36e54f3a9374c08558910f267096f1a188c4c68
parent2e18ba6302f3e4aa5485eeaca39c747beb55ca8f (diff)
downloademacs-b0d761be0f9b0180566d7cde1ef2eea33402dd4e.tar.gz
emacs-b0d761be0f9b0180566d7cde1ef2eea33402dd4e.zip
Restore module var toggles in ERC's Custom buffers
* lisp/erc/erc-common.el (erc--neuter-custom-variable-state): Remove function. ERC famously toggles global minor-mode vars during normal operations, which adds noise to its customization buffers because `customize-variable-state' always sees an activated module's mode variable as having "CHANGED". To suppress this annoyance, a workaround was employed that used a dishonest `:get' function to simply return the "saved value," when present. While this improved the Customize experience, it also misled users, which likely wasn't justified. (erc--make-show-me-widget): Add helper to avoid forward declarations. (erc--prepare-custom-module-type): Don't deprive users of a working minor-mode toggle. (erc--find-feature): New function to guess the feature of a module's containing library. (define-erc-module): Remove `:get' keyword. Specify `:require' instead, whose value may be nil. Users who currently have mode vars in their `custom-file' won't be impacted by this addition because those `custom-set-variables' entries will still lack a REQUEST list and hence won't incur a startup penalty. And new users intent on using the toggle will hopefully do so with the knowledge they're opting in to requiring ERC on startup, which is not the case if they follow the recommended practice of using `erc-modules' instead. (erc-with-server-buffer): Inline `erc-server-buffer'. * test/lisp/erc/erc-tests.el (erc-process-input-line): Use helper. (define-erc-module--global): Change expected expansion. (Bug#60935)
-rw-r--r--lisp/erc/erc-common.el76
-rw-r--r--test/lisp/erc/erc-tests.el7
2 files changed, 49 insertions, 34 deletions
diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index 6c015c71ff9..708cdb0c422 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -32,6 +32,7 @@
32(defvar erc-dbuf) 32(defvar erc-dbuf)
33(defvar erc-log-p) 33(defvar erc-log-p)
34(defvar erc-modules) 34(defvar erc-modules)
35(defvar erc-server-process)
35(defvar erc-server-users) 36(defvar erc-server-users)
36(defvar erc-session-server) 37(defvar erc-session-server)
37 38
@@ -40,6 +41,9 @@
40(declare-function erc-server-buffer "erc" nil) 41(declare-function erc-server-buffer "erc" nil)
41(declare-function widget-apply-action "wid-edit" (widget &optional event)) 42(declare-function widget-apply-action "wid-edit" (widget &optional event))
42(declare-function widget-at "wid-edit" (&optional pos)) 43(declare-function widget-at "wid-edit" (&optional pos))
44(declare-function widget-create-child-and-convert "wid-edit"
45 (parent type &rest args))
46(declare-function widget-default-format-handler "wid-edit" (widget escape))
43(declare-function widget-get-sibling "wid-edit" (widget)) 47(declare-function widget-get-sibling "wid-edit" (widget))
44(declare-function widget-move "wid-edit" (arg &optional suppress-echo)) 48(declare-function widget-move "wid-edit" (arg &optional suppress-echo))
45(declare-function widget-type "wid-edit" (widget)) 49(declare-function widget-type "wid-edit" (widget))
@@ -195,16 +199,6 @@ instead of a `set' state, which precludes any actual saving."
195 (throw 'found found))) 199 (throw 'found found)))
196 'erc)) 200 'erc))
197 201
198(defun erc--neuter-custom-variable-state (variable)
199 "Lie to Customize about VARIABLE's true state.
200Do so by always returning its standard value, namely nil."
201 ;; Make a module's global minor-mode toggle blind to Customize, so
202 ;; that `customize-variable-state' never sees it as "changed",
203 ;; regardless of its value. This snippet is
204 ;; `custom--standard-value' from Emacs 28+.
205 (cl-assert (null (eval (car (get variable 'standard-value)) t)))
206 nil)
207
208;; This exists as a separate, top-level function to prevent the byte 202;; This exists as a separate, top-level function to prevent the byte
209;; compiler from warning about widget-related dependencies not being 203;; compiler from warning about widget-related dependencies not being
210;; loaded at runtime. 204;; loaded at runtime.
@@ -230,25 +224,42 @@ Do so by always returning its standard value, namely nil."
230 (substitute-command-keys "\\[Custom-set]") 224 (substitute-command-keys "\\[Custom-set]")
231 (substitute-command-keys "\\[Custom-save]")))) 225 (substitute-command-keys "\\[Custom-save]"))))
232 226
227;; This stands apart to avoid needing forward declarations for
228;; `wid-edit' functions in every file requiring `erc-common'.
229(defun erc--make-show-me-widget (widget escape &rest plist)
230 (if (eq escape ?i)
231 (apply #'widget-create-child-and-convert widget 'push-button plist)
232 (widget-default-format-handler widget escape)))
233
233(defun erc--prepare-custom-module-type (name) 234(defun erc--prepare-custom-module-type (name)
234 `(let* ((name (erc--normalize-module-symbol ',name)) 235 `(let* ((name (erc--normalize-module-symbol ',name))
235 (fmtd (format " `%s' " name))) 236 (fmtd (format " `%s' " name)))
236 `(boolean 237 `(boolean
237 :button-face '(custom-variable-obsolete custom-button) 238 :format "%{%t%}: %i %[Deprecated Toggle%] %v \n%h\n"
238 :format "%{%t%}: %[Deprecated Toggle%] \n%h\n" 239 :format-handler
240 ,(lambda (widget escape)
241 (erc--make-show-me-widget
242 widget escape
243 :button-face '(custom-variable-obsolete custom-button)
244 :tag "Show Me"
245 :action (apply-partially #'erc--tick-module-checkbox name)
246 :help-echo (lambda (_)
247 (let ((hasp (memq name erc-modules)))
248 (concat (if hasp "Remove" "Add") fmtd
249 (if hasp "from" "to")
250 " `erc-modules'.")))))
251 :action widget-toggle-action
239 :documentation-property 252 :documentation-property
240 ,(lambda (_) 253 ,(lambda (_)
241 (let ((hasp (memq name erc-modules))) 254 (let ((hasp (memq name erc-modules)))
242 (concat "Setting a module's minor-mode variable is " 255 (concat
243 (propertize "ineffective" 'face 'error) 256 "Setting a module's minor-mode variable is "
244 ".\nPlease " (if hasp "remove" "add") fmtd 257 (propertize "ineffective" 'face 'error)
245 (if hasp "from" "to") " `erc-modules' directly instead.\n" 258 ".\nPlease " (if hasp "remove" "add") fmtd
246 "You can do so now by clicking the scary button above."))) 259 (if hasp "from" "to") " `erc-modules' directly instead.\n"
247 :help-echo ,(lambda (_) 260 "You can do so now by clicking "
248 (let ((hasp (memq name erc-modules))) 261 (propertize "Show Me" 'face 'custom-variable-obsolete)
249 (concat (if hasp "Remove" "Add") fmtd 262 " above."))))))
250 (if hasp "from" "to") " `erc-modules'.")))
251 :action ,(apply-partially #'erc--tick-module-checkbox name))))
252 263
253(defun erc--fill-module-docstring (&rest strings) 264(defun erc--fill-module-docstring (&rest strings)
254 (with-temp-buffer 265 (with-temp-buffer
@@ -264,6 +275,12 @@ Do so by always returning its standard value, namely nil."
264 (goto-char (point-min)) 275 (goto-char (point-min))
265 (nth 3 (read (current-buffer))))) 276 (nth 3 (read (current-buffer)))))
266 277
278(defmacro erc--find-feature (name alias)
279 `(pcase (erc--find-group ',name ,(and alias (list 'quote alias)))
280 ('erc (and-let* ((file (or (macroexp-file-name) buffer-file-name)))
281 (intern (file-name-base file))))
282 (v v)))
283
267(defmacro define-erc-module (name alias doc enable-body disable-body 284(defmacro define-erc-module (name alias doc enable-body disable-body
268 &optional local-p) 285 &optional local-p)
269 "Define a new minor mode using ERC conventions. 286 "Define a new minor mode using ERC conventions.
@@ -310,7 +327,7 @@ if ARG is omitted or nil.
310\n%s" name name doc)) 327\n%s" name name doc))
311 :global ,(not local-p) 328 :global ,(not local-p)
312 :group (erc--find-group ',name ,(and alias (list 'quote alias))) 329 :group (erc--find-group ',name ,(and alias (list 'quote alias)))
313 ,@(unless local-p '(:get #'erc--neuter-custom-variable-state)) 330 ,@(unless local-p `(:require ',(erc--find-feature name alias)))
314 ,@(unless local-p `(:type ,(erc--prepare-custom-module-type name))) 331 ,@(unless local-p `(:type ,(erc--prepare-custom-module-type name)))
315 (if ,mode 332 (if ,mode
316 (,enable) 333 (,enable)
@@ -371,12 +388,13 @@ If no server buffer exists, return nil."
371 (not (cdr body)) 388 (not (cdr body))
372 (special-variable-p (car body)))) 389 (special-variable-p (car body))))
373 (buffer (make-symbol "buffer"))) 390 (buffer (make-symbol "buffer")))
374 `(let ((,buffer (erc-server-buffer))) 391 `(when-let* (((processp erc-server-process))
375 (when (buffer-live-p ,buffer) 392 (,buffer (process-buffer erc-server-process))
376 ,(if varp 393 ((buffer-live-p ,buffer)))
377 `(buffer-local-value ',(car body) ,buffer) 394 ,(if varp
378 `(with-current-buffer ,buffer 395 `(buffer-local-value ',(car body) ,buffer)
379 ,@body)))))) 396 `(with-current-buffer ,buffer
397 ,@body)))))
380 398
381(defmacro erc-with-all-buffers-of-server (process pred &rest forms) 399(defmacro erc-with-all-buffers-of-server (process pred &rest forms)
382 "Execute FORMS in all buffers which have same process as this server. 400 "Execute FORMS in all buffers which have same process as this server.
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 5aaf7e499e3..bafe418f0cd 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1289,15 +1289,12 @@
1289 (erc-default-recipients '("#chan")) 1289 (erc-default-recipients '("#chan"))
1290 calls) 1290 calls)
1291 (with-temp-buffer 1291 (with-temp-buffer
1292 (erc-tests--set-fake-server-process "sleep" "1")
1292 (cl-letf (((symbol-function 'erc-cmd-MSG) 1293 (cl-letf (((symbol-function 'erc-cmd-MSG)
1293 (lambda (line) 1294 (lambda (line)
1294 (push line calls) 1295 (push line calls)
1295 (should erc--called-as-input-p) 1296 (should erc--called-as-input-p)
1296 (funcall orig-erc-cmd-MSG line))) 1297 (funcall orig-erc-cmd-MSG line)))
1297 ((symbol-function 'erc-server-buffer)
1298 (lambda () (current-buffer)))
1299 ((symbol-function 'erc-server-process-alive)
1300 (lambda () t))
1301 ((symbol-function 'erc-server-send-queue) 1298 ((symbol-function 'erc-server-send-queue)
1302 #'ignore)) 1299 #'ignore))
1303 1300
@@ -2018,7 +2015,7 @@ ARG is omitted or nil.
2018Some docstring." 2015Some docstring."
2019 :global t 2016 :global t
2020 :group (erc--find-group 'mname 'malias) 2017 :group (erc--find-group 'mname 'malias)
2021 :get #'erc--neuter-custom-variable-state 2018 :require 'nil
2022 :type "mname" 2019 :type "mname"
2023 (if erc-mname-mode 2020 (if erc-mname-mode
2024 (erc-mname-enable) 2021 (erc-mname-enable)