From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: "J.P." Newsgroups: gmane.emacs.bugs,gmane.emacs.erc.general Subject: bug#60935: 30.0.50; ERC >5.5: Improve ERC's treatment of customization groups Date: Tue, 14 Mar 2023 06:43:15 -0700 Message-ID: <87jzzjih3g.fsf@neverwas.me> References: <87v8l3aod4.fsf@neverwas.me> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="36579"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: emacs-erc@gnu.org To: 60935@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Mar 14 14:57:27 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pc59b-0009El-Fa for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 14 Mar 2023 14:57:27 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pc52S-0001Lb-JM; Tue, 14 Mar 2023 09:50:04 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pc52Q-0001L4-U0 for bug-gnu-emacs@gnu.org; Tue, 14 Mar 2023 09:50:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pc52Q-0002hp-Jh for bug-gnu-emacs@gnu.org; Tue, 14 Mar 2023 09:50:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pc52Q-0004gR-Gl for bug-gnu-emacs@gnu.org; Tue, 14 Mar 2023 09:50:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: "J.P." Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 14 Mar 2023 13:50:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 60935 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 60935-submit@debbugs.gnu.org id=B60935.167880177717964 (code B ref 60935); Tue, 14 Mar 2023 13:50:02 +0000 Original-Received: (at 60935) by debbugs.gnu.org; 14 Mar 2023 13:49:37 +0000 Original-Received: from localhost ([127.0.0.1]:36693 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pc51z-0004fd-MN for submit@debbugs.gnu.org; Tue, 14 Mar 2023 09:49:37 -0400 Original-Received: from relay0-k.mailbaby.net ([174.138.190.34]:25149) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pc51w-0004fQ-Cm for 60935@debbugs.gnu.org; Tue, 14 Mar 2023 09:49:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbaby.net; q=dns/txt; s=bambino; bh=Bzg/4pfKL0X5PEOAJ8jTiR8lS8KaiS5v/BMReax4/Ao=; h=from:subject:date:message-id:to:cc:mime-version:content-type:in-reply-to:references; b=MgDxAJWUButg73aKKt4OxRMSSwyAGUDFpbtMP9p5i+O8yLj/TVppEOscqnMiO1LuG2PyiNeuB kPO0LhQDjr+JpXKSV7qneHy4FLqmjQ4MFwgzFeiwAoC9CA+gtU5OLzdtbaBFH4qK1HY3IIRBzaN bGNIzGueYRxn+LoQ2OmUgtg= Original-Received: from zmta1 ([45.76.239.126] 45.76.239.126.vultrusercontent.com) (Authenticated sender: mb25440) by relay0-k.mailbaby.net (InterServerMTA) with ESMTPSA id 186e061d523000f13e.001 for <60935@debbugs.gnu.org> (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256); Tue, 14 Mar 2023 13:49:13 +0000 X-Zone-Loop: b49a279d37cdc7f08f9a883a116d1ec7ebd4c8ffd48e ARC-Authentication-Results: i=1; rspamd3.mailbaby.net; auth=pass smtp.auth=mb25440 smtp.mailfrom=jp@neverwas.me ARC-Seal: i=1; s=detka; d=mailbaby.net; t=1678801753; a=rsa-sha256; cv=none; b=n00x1inOKb6Ke63YhdXUrpFlo6ryOr8B4DKENX7vx4XnYX9jGGzrAu+fEd63mR24Wlf3mX BihDBfXTGK40jfRAKPIRT+iUhWDtc+nB4+06L5ndBGPLMZeXa9rjCYGjyZMvUaExdExH6W wviTto2gvvGOlj41vZLzoP1xPwuppexqLLMr25M/56CTs7DeoSzfMgYzUgkYOylvPv3xhD sGtziNt3LPhyvA24evUv6GVp8TZrYDklMbUcCdSb6PP7g7UhqJOGvozeKVjg3cg86ir4ur oJ2ARy2XKV9LPJEsg6PKIVhdTXr/RAsLswXrA4w6PPDjKEie05Unna+sAOaPAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbaby.net; s=detka; t=1678801753; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references:dkim-signature; bh=Bzg/4pfKL0X5PEOAJ8jTiR8lS8KaiS5v/BMReax4/Ao=; b=Gj+iWTQOGzBsLcRic8mUJLbkRYHbznwj/w+gJrbC7zdVPTfQavh1rec7geP6nkp9HVirKR uuqHAMNcje1hH4eSJzzWkWHTbSqNsL1YktuS4ONS8V7YDOR2UlbswBegswCWQa78T4xUJd mR6F3PDtoOGsblUJ9lyAo1MOKi66FIIMV0qbsAEJFZeJilVGbz3zGWefSEtG7W8Va2XJ/F hagxNENaxZTP58qFHbtLe91/H4wBDLICqRuFbfTG04bQ6Uc4j1mk3NeLyYDB/NVWMEcFqp 6Hi60Ju/uFkkX9bkYxVMaNnHK5Ci9rQHkcnDuVgrXz3U8V96BCv8aQ4Cv5wBlg== Original-Received: from mail-111-mta2.mxroute.com ([136.175.111.2] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by zmta1 (ZoneMTA) with ESMTPSA id 186e05cd74a000edb4.001 for <60935@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Tue, 14 Mar 2023 13:43:46 +0000 X-Zone-Loop: 265efb5cf16dd1825bbad70a2c82939ef7ae12455397 X-Originating-IP: [45.76.239.126] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=Bzg/4pfKL0X5PEOAJ8jTiR8lS8KaiS5v/BMReax4/Ao=; b=FtjNcrC82Ji7f9k+RkHBCWDsqH 6Dd1jlJDovXAwkyXT2UEj6NRHNKp9TbSOZQ71HlYPHEzaOGG1WivOGZ0Bk6h0EoqsAW6lAvxfuJRq e7diEsWhi6sCRsjGFq9F4QuKAHxWel1ZKtgOS+U0JaaUOWeNGhTn20nPReSyfMlKscwrGDa3Noh+h ZXe3gBIDWGqKNnJPC9OxRlJDF7ZzygSZk8gXZMpK8TxniJj4k5T9CSUvGTTaqvPRlYQJcXqG7+N1y g7KgiLigWxjpHMxmkYfnv/rs+Nybn2W74G4sGnFimuihQE74DYk/JpS5BMPDAIdrPE3X6sZXsOmwV xOzTH6Nw==; In-Reply-To: <87v8l3aod4.fsf@neverwas.me> (J. P.'s message of "Wed, 18 Jan 2023 06:50:15 -0800") X-Authenticated-Id: masked@neverwas.me X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:257934 gmane.emacs.erc.general:2108 Archived-At: --=-=-= Content-Type: text/plain v4. Use `custom-set-variables' instead of `customize-set-variable'. Munge `standard-value' of deprecated `erc-foo-mode' variables when called by `erc-update-modules' (but not interactively). --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v3-v4.diff >From a6662c04e156b1dd37661991a045acaf3c5cb9b4 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Tue, 14 Mar 2023 06:25:32 -0700 Subject: [PATCH 0/3] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (3): [5.6] Don't associate ERC modules with undefined groups [5.6] Warn when setting minor-mode vars for ERC modules [5.6] Fill doc strings for ERC modules. lisp/erc/erc-capab.el | 1 + lisp/erc/erc-common.el | 146 +++++++++++++++++++++++++++++++++---- lisp/erc/erc.el | 3 +- test/lisp/erc/erc-tests.el | 88 +++++++++++++++++----- 4 files changed, 207 insertions(+), 31 deletions(-) Interdiff: diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index 4332ed00cfb..522803b91e2 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -162,11 +162,14 @@ erc--assemble-toggle erc-modules))) `(,(if val v `(not ,v))))) (let ((erc--inside-mode-toggle-p t)) - (customize-set-variable - 'erc-modules (,(if val 'cons 'delq) - ',(erc--normalize-module-symbol name) - erc-modules)))) + (custom-set-variables + `(erc-modules ',(,(if val 'cons 'delq) + ',(erc--normalize-module-symbol name) + erc-modules))))) (setq ,mode ,val) + ;; Avoid "changed" state from `erc-update-modules' + (unless (called-interactively-p 'any) + (put ',mode 'standard-value (list ,val))) ,@body))))) ;; This is a migration helper that determines a module's `:group' @@ -203,9 +206,9 @@ erc--find-group (defun erc--custom-set-minor-mode (variable value) (let ((name (get variable 'erc-module)) (erc--inside-mode-toggle-p t)) - (customize-set-variable - 'erc-modules - (if value (cl-pushnew name erc-modules) (delq name erc-modules))) + (custom-set-variables + `(erc-modules + ',(if value (cl-pushnew name erc-modules) (delq name erc-modules)))) (custom-set-minor-mode variable value))) ;; This exists as a separate, top-level function to prevent the byte diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 62480c0604e..ef742c853d6 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1340,9 +1340,11 @@ define-erc-module--global (unless (or erc--inside-mode-toggle-p (memq 'mname erc-modules)) (let ((erc--inside-mode-toggle-p t)) - (customize-set-variable - 'erc-modules (cons 'mname erc-modules)))) + (custom-set-variables + `(erc-modules ',(cons 'mname erc-modules))))) (setq erc-mname-mode t) + (unless (called-interactively-p 'any) + (put 'erc-mname-mode 'standard-value (list t))) (ignore a) (ignore b)) (defun erc-mname-disable () @@ -1351,9 +1353,11 @@ define-erc-module--global (unless (or erc--inside-mode-toggle-p (not (memq 'mname erc-modules))) (let ((erc--inside-mode-toggle-p t)) - (customize-set-variable - 'erc-modules (delq 'mname erc-modules)))) + (custom-set-variables + `(erc-modules ',(delq 'mname erc-modules))))) (setq erc-mname-mode nil) + (unless (called-interactively-p 'any) + (put 'erc-mname-mode 'standard-value (list nil))) (ignore c) (ignore d)) (defalias 'erc-malias-mode #'erc-mname-mode) -- 2.39.2 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-5.6-Don-t-associate-ERC-modules-with-undefined-group.patch >From 12dd0075b751a9dbdfae57a500425f177158bb73 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sat, 14 Jan 2023 19:05:59 -0800 Subject: [PATCH 1/3] [5.6] Don't associate ERC modules with undefined groups * lisp/erc/erc-capab.el Add property crutch to help ERC find module's custom group. * lisp/erc/erc-common.el (erc--find-group): Add new function, a helper for finding an existing ERC custom group based on `define-erc-module' params. Prefer `group-documentation' as a sentinel over symbol properties owned by Customize because they might not be present if the group isn't yet associated with any custom variables. (define-erc-module): Set `:group' keyword value more accurately, falling back to `erc' group when no associated group has been defined. * test/lisp/erc/erc-tests.el (erc--find-group, erc--find-group--real): New tests. (define-erc-module--global, define-erc-module--local): Expect the :group keyword to be the unevaluated `erc--find-group' form. (Bug#60935.) --- lisp/erc/erc-capab.el | 1 + lisp/erc/erc-common.el | 38 +++++++++++++++++++++++++++++++++----- test/lisp/erc/erc-tests.el | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el index 650c5fa84ac..bb0921da7f0 100644 --- a/lisp/erc/erc-capab.el +++ b/lisp/erc/erc-capab.el @@ -89,6 +89,7 @@ erc-capab-identify-unidentified ;;; Define module: ;;;###autoload(autoload 'erc-capab-identify-mode "erc-capab" nil t) +(put 'capab-identify 'erc-group 'erc-capab) (define-erc-module capab-identify nil "Handle dancer-ircd's CAPAB IDENTIFY-MSG and IDENTIFY-CTCP." ;; append so that `erc-server-parameters' is already set by `erc-server-005' diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index 0279b0a0bc4..0eabd3a2fe9 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -145,6 +145,37 @@ erc--assemble-toggle (setq ,mode ,val) ,@body))))) +;; This is a migration helper that determines a module's `:group' +;; keyword argument from its name or alias. A (global) module's minor +;; mode variable appears under the group's Custom menu. Like +;; `erc--normalize-module-symbol', it must run when the module's +;; definition (rather than that of `define-erc-module') is expanded. +;; For corner cases in which this fails or the catch-all of `erc' is +;; more inappropriate, (global) modules can declare a top-level +;; +;; (put 'foo 'erc-group 'erc-bar) +;; +;; where `erc-bar' is the group and `foo' is the normalized module. +;; Do this *before* the module's definition. If `define-erc-module' +;; ever accepts arbitrary keywords, passing an explicit `:group' will +;; obviously be preferable. + +(defun erc--find-group (&rest symbols) + (catch 'found + (dolist (s symbols) + (let* ((downed (downcase (symbol-name s))) + (known (intern-soft (concat "erc-" downed)))) + (when (and known + (or (get known 'group-documentation) + (rassq known custom-current-group-alist))) + (throw 'found known)) + (when (setq known (intern-soft (concat "erc-" downed "-mode"))) + (when-let ((found (custom-group-of-mode known))) + (throw 'found found)))) + (when-let ((found (get (erc--normalize-module-symbol s) 'erc-group))) + (throw 'found found))) + 'erc)) + (defmacro define-erc-module (name alias doc enable-body disable-body &optional local-p) "Define a new minor mode using ERC conventions. @@ -179,7 +210,6 @@ define-erc-module (declare (doc-string 3) (indent defun)) (let* ((sn (symbol-name name)) (mode (intern (format "erc-%s-mode" (downcase sn)))) - (group (intern (format "erc-%s" (downcase sn)))) (enable (intern (format "erc-%s-enable" (downcase sn)))) (disable (intern (format "erc-%s-disable" (downcase sn))))) `(progn @@ -190,10 +220,8 @@ define-erc-module and disable it otherwise. If called from Lisp, enable the mode if ARG is omitted or nil. %s" name name doc) - ;; FIXME: We don't know if this group exists, so this `:group' may - ;; actually just silence a valid warning about the fact that the var - ;; is not associated with any group. - :global ,(not local-p) :group (quote ,group) + :global ,(not local-p) + :group (erc--find-group ',name ,(and alias (list 'quote alias))) (if ,mode (,enable) (,disable))) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index d6c63934163..13ef99be167 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1209,6 +1209,39 @@ erc-migrate-modules ;; Default unchanged (should (equal (erc-migrate-modules erc-modules) erc-modules))) +(ert-deftest erc--find-group () + ;; These two are loaded by default + (should (eq (erc--find-group 'keep-place nil) 'erc)) + (should (eq (erc--find-group 'networks nil) 'erc-networks)) + ;; These are fake + (cl-letf (((get 'erc-bar 'group-documentation) "") + ((get 'baz 'erc-group) 'erc-foo)) + (should (eq (erc--find-group 'foo 'bar) 'erc-bar)) + (should (eq (erc--find-group 'bar 'foo) 'erc-bar)) + (should (eq (erc--find-group 'bar nil) 'erc-bar)) + (should (eq (erc--find-group 'foo nil) 'erc)) + (should (eq (erc--find-group 'fake 'baz) 'erc-foo)))) + +(ert-deftest erc--find-group--real () + :tags '(:unstable) + (require 'erc-services) + (require 'erc-stamp) + (require 'erc-sound) + (require 'erc-page) + (require 'erc-join) + (require 'erc-capab) + (require 'erc-pcomplete) + (should (eq (erc--find-group 'services 'nickserv) 'erc-services)) + (should (eq (erc--find-group 'stamp 'timestamp) 'erc-stamp)) + (should (eq (erc--find-group 'sound 'ctcp-sound) 'erc-sound)) + (should (eq (erc--find-group 'page 'ctcp-page) 'erc-page)) + (should (eq (erc--find-group 'autojoin) 'erc-autojoin)) + (should (eq (erc--find-group 'pcomplete 'Completion) 'erc-pcomplete)) + (should (eq (erc--find-group 'capab-identify) 'erc-capab)) + ;; No group specified. + (should (eq (erc--find-group 'smiley nil) 'erc)) + (should (eq (erc--find-group 'unmorse nil) 'erc))) + (ert-deftest erc--update-modules () (let (calls erc-modules @@ -1290,7 +1323,7 @@ define-erc-module--global if ARG is omitted or nil. Some docstring" :global t - :group 'erc-mname + :group (erc--find-group 'mname 'malias) (if erc-mname-mode (erc-mname-enable) (erc-mname-disable))) @@ -1336,7 +1369,7 @@ define-erc-module--local if ARG is omitted or nil. Some docstring" :global nil - :group 'erc-mname + :group (erc--find-group 'mname nil) (if erc-mname-mode (erc-mname-enable) (erc-mname-disable))) -- 2.39.2 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-5.6-Warn-when-setting-minor-mode-vars-for-ERC-module.patch >From 764dc63582a440495ab53a9986003d5d1a794bcf Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sat, 14 Jan 2023 19:08:11 -0800 Subject: [PATCH 2/3] [5.6] Warn when setting minor-mode vars for ERC modules (erc--inside-mode-toggle-p): Add global var to inhibit mode toggles from being run by `erc-update-modules'. It must be non-nil inside custom-set functions for mode toggles created by `define-erc-module'. (erc--assemble-toggle): Don't modify `erc-modules' when run from custom-set function. (erc--custom-set-minor-mode): Add new custom-set function for module minor modes. Update `erc-modules' before calling a minor-mode toggle via `custom-set-minor-mode'. (erc--tick-module-checkbox): Add helper to toggle the appropriate checkbox in the `erc-modules' widget when a user interactively toggles a minor-mode state variable. (erc--prepare-custom-module-type): Create spec for minor-mode custom `:type', deferring various aspects until module-definition time. (define-erc-module): Add `:set' and `:type' keywords for global modules. * lisp/erc/erc.el (erc-modules): Inhibit `erc-update-modules' when run from a minor-mode toggle's custom-set function. * test/lisp/erc/erc-tests.el (define-erc-module--global, define-erc-module--local): Update `erc-modules' mutations with `erc--inside-mode-toggle-p' guard conditions. (Bug#60935.) --- lisp/erc/erc-common.el | 88 +++++++++++++++++++++++++++++++++++--- lisp/erc/erc.el | 3 +- test/lisp/erc/erc-tests.el | 23 ++++++++-- 3 files changed, 105 insertions(+), 9 deletions(-) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index 0eabd3a2fe9..cd0fc79e568 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -29,6 +29,7 @@ (defvar erc--casemapping-rfc1459) (defvar erc--casemapping-rfc1459-strict) (defvar erc-channel-users) +(defvar erc-modules) (defvar erc-dbuf) (defvar erc-log-p) (defvar erc-server-users) @@ -37,6 +38,11 @@ erc-session-server (declare-function erc--get-isupport-entry "erc-backend" (key &optional single)) (declare-function erc-get-buffer "erc" (target &optional proc)) (declare-function erc-server-buffer "erc" nil) +(declare-function widget-apply-action "wid-edit" (widget &optional event)) +(declare-function widget-at "wid-edit" (&optional pos)) +(declare-function widget-get-sibling "wid-edit" (widget)) +(declare-function widget-move "wid-edit" (arg &optional suppress-echo)) +(declare-function widget-type "wid-edit" (widget)) (cl-defstruct erc-input string insertp sendp) @@ -120,6 +126,16 @@ erc--normalize-module-symbol (setq symbol (intern (downcase (symbol-name symbol)))) (or (cdr (assq symbol erc--module-name-migrations)) symbol)) +(defvar erc--inside-mode-toggle-p nil + "Non-nil when a module's mode toggle is updating module membership. +This serves as a flag to inhibit the mutual recursion that would +otherwise occur between an ERC-defined minor-mode function, such +as `erc-services-mode', and the custom-set function for +`erc-modules'. For historical reasons, the latter calls +`erc-update-modules', which, in turn, enables the minor-mode +functions for all member modules. Also non-nil when a mode's +widget runs its set function.") + (defun erc--assemble-toggle (localp name ablsym mode val body) (let ((arg (make-symbol "arg"))) `(defun ,ablsym ,(if localp `(&optional ,arg) '()) @@ -137,12 +153,23 @@ erc--assemble-toggle (,ablsym)) (setq ,mode ,val) ,@body))) - `(,(if val - `(cl-pushnew ',(erc--normalize-module-symbol name) - erc-modules) - `(setq erc-modules (delq ',(erc--normalize-module-symbol name) - erc-modules))) + ;; No need for `default-value', etc. because a buffer-local + ;; `erc-modules' only influences the next session and + ;; doesn't survive the major-mode reset that soon follows. + `((unless + (or erc--inside-mode-toggle-p + ,@(let ((v `(memq ',(erc--normalize-module-symbol name) + erc-modules))) + `(,(if val v `(not ,v))))) + (let ((erc--inside-mode-toggle-p t)) + (custom-set-variables + `(erc-modules ',(,(if val 'cons 'delq) + ',(erc--normalize-module-symbol name) + erc-modules))))) (setq ,mode ,val) + ;; Avoid "changed" state from `erc-update-modules' + (unless (called-interactively-p 'any) + (put ',mode 'standard-value (list ,val))) ,@body))))) ;; This is a migration helper that determines a module's `:group' @@ -176,6 +203,55 @@ erc--find-group (throw 'found found))) 'erc)) +(defun erc--custom-set-minor-mode (variable value) + (let ((name (get variable 'erc-module)) + (erc--inside-mode-toggle-p t)) + (custom-set-variables + `(erc-modules + ',(if value (cl-pushnew name erc-modules) (delq name erc-modules)))) + (custom-set-minor-mode variable value))) + +;; This exists as a separate, top-level function to prevent the byte +;; compiler from warning about widget-related dependencies not being +;; loaded at runtime. + +(defun erc--tick-module-checkbox (name &rest _) ; `name' must be normalized + (customize-variable-other-window 'erc-modules) + ;; Move to `erc-modules' section. + (while (not (eq (widget-type (widget-at)) 'checkbox)) + (widget-move 1 t)) + ;; This search for a checkbox can fail when `name' refers to a + ;; third-party module that modifies `erc-modules' (improperly) on + ;; load. + (let (w) + (while (and (eq (widget-type (widget-at)) 'checkbox) + (not (and (setq w (widget-get-sibling (widget-at))) + (eq (widget-value w) name)))) + (setq w nil) + (widget-move 1 t)) ; the `suppress-echo' arg exists in 27.2 + (if w + (progn (widget-apply-action (widget-at)) + (message "Hit %s to apply or %s to apply and save." + (substitute-command-keys "\\[Custom-set]") + (substitute-command-keys "\\[Custom-save]"))) + (error "Failed to find %s in `erc-modules' checklist" name)))) + +(defun erc--prepare-custom-module-type (name) + `(let* ((name (erc--normalize-module-symbol ',name)) + (fmtd (format " `%s' " name))) + `(boolean + :button-face '(error custom-button) + :format "%{%t%}: %[Deprecated Toggle%] \n%d\n" + :doc ,(concat "Setting a module's minor-mode variable is " + (propertize "ineffective" 'face 'error) ".\nPlease add" + fmtd "directly to `erc-modules' instead.\nYou can do so" + " now by clicking the scary button above.") + :help-echo ,(lambda (_) + (let ((hasp (memq name erc-modules))) + (concat (if hasp "Remove" "Add") fmtd + (if hasp "from" "to") " `erc-modules'."))) + :action ,(apply-partially #'erc--tick-module-checkbox name)))) + (defmacro define-erc-module (name alias doc enable-body disable-body &optional local-p) "Define a new minor mode using ERC conventions. @@ -222,6 +298,8 @@ define-erc-module %s" name name doc) :global ,(not local-p) :group (erc--find-group ',name ,(and alias (list 'quote alias))) + ,@(unless local-p '(:set #'erc--custom-set-minor-mode)) + ,@(unless local-p `(:type ,(erc--prepare-custom-module-type name))) (if ,mode (,enable) (,disable))) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 69bdb5d71b1..59ab1f1eab3 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1846,7 +1846,8 @@ erc-modules (set sym val) ;; this test is for the case where erc hasn't been loaded yet (when (fboundp 'erc-update-modules) - (erc-update-modules))) + (unless erc--inside-mode-toggle-p + (erc-update-modules)))) :type '(set :greedy t diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 13ef99be167..a31c2c530a3 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1313,7 +1313,10 @@ define-erc-module--global ((ignore a) (ignore b)) ((ignore c) (ignore d))))) - (should (equal (macroexpand global-module) + (should (equal (cl-letf (((symbol-function + 'erc--prepare-custom-module-type) + #'symbol-name)) + (macroexpand global-module)) `(progn (define-minor-mode erc-mname-mode @@ -1324,6 +1327,8 @@ define-erc-module--global Some docstring" :global t :group (erc--find-group 'mname 'malias) + :set #'erc--custom-set-minor-mode + :type "mname" (if erc-mname-mode (erc-mname-enable) (erc-mname-disable))) @@ -1331,15 +1336,27 @@ define-erc-module--global (defun erc-mname-enable () "Enable ERC mname mode." (interactive) - (cl-pushnew 'mname erc-modules) + (unless (or erc--inside-mode-toggle-p + (memq 'mname erc-modules)) + (let ((erc--inside-mode-toggle-p t)) + (custom-set-variables + `(erc-modules ',(cons 'mname erc-modules))))) (setq erc-mname-mode t) + (unless (called-interactively-p 'any) + (put 'erc-mname-mode 'standard-value (list t))) (ignore a) (ignore b)) (defun erc-mname-disable () "Disable ERC mname mode." (interactive) - (setq erc-modules (delq 'mname erc-modules)) + (unless (or erc--inside-mode-toggle-p + (not (memq 'mname erc-modules))) + (let ((erc--inside-mode-toggle-p t)) + (custom-set-variables + `(erc-modules ',(delq 'mname erc-modules))))) (setq erc-mname-mode nil) + (unless (called-interactively-p 'any) + (put 'erc-mname-mode 'standard-value (list nil))) (ignore c) (ignore d)) (defalias 'erc-malias-mode #'erc-mname-mode) -- 2.39.2 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-5.6-Fill-doc-strings-for-ERC-modules.patch >From a6662c04e156b1dd37661991a045acaf3c5cb9b4 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 16 Jan 2023 20:18:32 -0800 Subject: [PATCH 3/3] [5.6] Fill doc strings for ERC modules. * lisp/erc/erc-common.el (erc--fill-module-docstring): Add helper to fill doc strings. (erc--assemble-toggle, define-erc-module): Use helper to fill doc string. * test/lisp/erc/erc-tests.el (define-minor-mode--global, define-minor-mode--local): Adjust expected output for generated doc strings. (Bug#60935.) --- lisp/erc/erc-common.el | 20 +++++++++++++++++--- test/lisp/erc/erc-tests.el | 28 ++++++++++++++++------------ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index cd0fc79e568..522803b91e2 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -139,7 +139,7 @@ erc--inside-mode-toggle-p (defun erc--assemble-toggle (localp name ablsym mode val body) (let ((arg (make-symbol "arg"))) `(defun ,ablsym ,(if localp `(&optional ,arg) '()) - ,(concat + ,(erc--fill-module-docstring (if val "Enable" "Disable") " ERC " (symbol-name name) " mode." (when localp @@ -252,6 +252,20 @@ erc--prepare-custom-module-type (if hasp "from" "to") " `erc-modules'."))) :action ,(apply-partially #'erc--tick-module-checkbox name)))) +(defun erc--fill-module-docstring (&rest strings) + (with-temp-buffer + (emacs-lisp-mode) + (insert "(defun foo ()\n" + (format "%S" (apply #'concat strings)) + "\n(ignore))") + (goto-char (point-min)) + (forward-line 2) + (let ((emacs-lisp-docstring-fill-column 65) + (sentence-end-double-space t)) + (fill-paragraph)) + (goto-char (point-min)) + (nth 3 (read (current-buffer))))) + (defmacro define-erc-module (name alias doc enable-body disable-body &optional local-p) "Define a new minor mode using ERC conventions. @@ -291,11 +305,11 @@ define-erc-module `(progn (define-minor-mode ,mode - ,(format "Toggle ERC %S mode. + ,(erc--fill-module-docstring (format "Toggle ERC %s mode. With a prefix argument ARG, enable %s if ARG is positive, and disable it otherwise. If called from Lisp, enable the mode if ARG is omitted or nil. -%s" name name doc) +\n%s" name name doc)) :global ,(not local-p) :group (erc--find-group ',name ,(and alias (list 'quote alias))) ,@(unless local-p '(:set #'erc--custom-set-minor-mode)) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index a31c2c530a3..ef742c853d6 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1309,7 +1309,7 @@ erc--merge-local-modes (ert-deftest define-erc-module--global () (let ((global-module '(define-erc-module mname malias - "Some docstring" + "Some docstring." ((ignore a) (ignore b)) ((ignore c) (ignore d))))) @@ -1321,10 +1321,11 @@ define-erc-module--global (define-minor-mode erc-mname-mode "Toggle ERC mname mode. -With a prefix argument ARG, enable mname if ARG is positive, -and disable it otherwise. If called from Lisp, enable the mode -if ARG is omitted or nil. -Some docstring" +With a prefix argument ARG, enable mname if ARG is positive, and +disable it otherwise. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Some docstring." :global t :group (erc--find-group 'mname 'malias) :set #'erc--custom-set-minor-mode @@ -1369,7 +1370,7 @@ define-erc-module--global (ert-deftest define-erc-module--local () (let* ((global-module '(define-erc-module mname nil ; no alias - "Some docstring" + "Some docstring." ((ignore a) (ignore b)) ((ignore c) (ignore d)) 'local)) @@ -1381,10 +1382,11 @@ define-erc-module--local `(progn (define-minor-mode erc-mname-mode "Toggle ERC mname mode. -With a prefix argument ARG, enable mname if ARG is positive, -and disable it otherwise. If called from Lisp, enable the mode -if ARG is omitted or nil. -Some docstring" +With a prefix argument ARG, enable mname if ARG is positive, and +disable it otherwise. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Some docstring." :global nil :group (erc--find-group 'mname nil) (if erc-mname-mode @@ -1393,7 +1395,8 @@ define-erc-module--local (defun erc-mname-enable (&optional ,arg-en) "Enable ERC mname mode. -When called interactively, do so in all buffers for the current connection." +When called interactively, do so in all buffers for the current +connection." (interactive "p") (when (derived-mode-p 'erc-mode) (if ,arg-en @@ -1405,7 +1408,8 @@ define-erc-module--local (defun erc-mname-disable (&optional ,arg-dis) "Disable ERC mname mode. -When called interactively, do so in all buffers for the current connection." +When called interactively, do so in all buffers for the current +connection." (interactive "p") (when (derived-mode-p 'erc-mode) (if ,arg-dis -- 2.39.2 --=-=-=--