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 Subject: bug#60935: 30.0.50; ERC >5.5: Improve ERC's treatment of customization groups Date: Tue, 07 Feb 2023 07:23:04 -0800 Message-ID: <87sffh8ppj.fsf__16167.6958364964$1675783468$gmane$org@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="25664"; 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 Feb 07 16:24:22 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 1pPPpV-0006Uw-3w for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 07 Feb 2023 16:24:21 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pPPpP-0004KL-Tl; Tue, 07 Feb 2023 10:24:16 -0500 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 1pPPpD-0004Hh-KP for bug-gnu-emacs@gnu.org; Tue, 07 Feb 2023 10:24:05 -0500 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 1pPPpC-0002Ba-HI for bug-gnu-emacs@gnu.org; Tue, 07 Feb 2023 10:24:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pPPpC-0007cv-6s for bug-gnu-emacs@gnu.org; Tue, 07 Feb 2023 10:24:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: "J.P." Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 07 Feb 2023 15:24: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.167578340129247 (code B ref 60935); Tue, 07 Feb 2023 15:24:02 +0000 Original-Received: (at 60935) by debbugs.gnu.org; 7 Feb 2023 15:23:21 +0000 Original-Received: from localhost ([127.0.0.1]:53779 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pPPoW-0007bd-BT for submit@debbugs.gnu.org; Tue, 07 Feb 2023 10:23:21 -0500 Original-Received: from mail-108-mta242.mxroute.com ([136.175.108.242]:45553) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pPPoU-0007bR-3r for 60935@debbugs.gnu.org; Tue, 07 Feb 2023 10:23:19 -0500 Original-Received: from mail-111-mta2.mxroute.com ([136.175.111.2] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta242.mxroute.com (ZoneMTA) with ESMTPSA id 1862c793a24000011e.001 for <60935@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Tue, 07 Feb 2023 15:23:07 +0000 X-Zone-Loop: f057f329dd8319e98be54d5555bfe895c3884220c558 X-Originating-IP: [136.175.111.2] 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=kjnTg4DPUNW0ODwe+e0kbIQ0GRAuJPc/B3Bj9Iy/mQw=; b=DJwYqOqwDrNaRafIZNK5DdOHGp HoHgPgxrcGD2T7mAyAJyStoLMM0KxdxgJvMaLkNj8iciRX6I5HPHQUhCfTqimLVtvDzTmNSRPwMKa W09rmofJmv+2yvWVpdmeB1K5blCyDhcKAIcQQwMJRN9lgH3mdq3Og6F1ZkzkXJobSctiTckUm6yca c5Oqp8JT6e/QS/PegqOIyXn8iUFe2j5zyEyGcX+LCdTG7LddH+1MwdwH9kM5pxQeTz/zC8ofbVKCn W5Y2OExwIUXkRHpRI9q8VFC8dAy5V9yJtlDXNVwMUnLy+OIPvP+sZiVFiUwYmXvGdJlQks7wAMrSL /vnWrXjg==; 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:255060 Archived-At: --=-=-= Content-Type: text/plain v2. Use autoloads for resolving groups in corner cases. Don't change decades-old preferred module name. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v1-v2.diff >From e4e270a4bf556ce238bc42c8549d4c443f3a969a Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Tue, 7 Feb 2023 00:08:34 -0800 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 | 136 +++++++++++++++++++++++++++++++++---- lisp/erc/erc.el | 3 +- test/lisp/erc/erc-tests.el | 78 ++++++++++++++++----- 4 files changed, 187 insertions(+), 31 deletions(-) Interdiff: diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el index 25cdea9e777..bb0921da7f0 100644 --- a/lisp/erc/erc-capab.el +++ b/lisp/erc/erc-capab.el @@ -89,7 +89,8 @@ erc-capab-identify-unidentified ;;; Define module: ;;;###autoload(autoload 'erc-capab-identify-mode "erc-capab" nil t) -(define-erc-module capab-identify capab +(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' ((add-hook 'erc-server-005-functions #'erc-capab-identify-setup t) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index f488244ef9c..cc278428d5d 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -97,7 +97,7 @@ erc--target ;; TODO move goodies modules here after 29 is released. (defconst erc--features-to-modules '((erc-pcomplete completion pcomplete) - (erc-capab capab capab-identify) + (erc-capab capab-identify) (erc-join autojoin) (erc-page page ctcp-page) (erc-sound sound ctcp-sound) @@ -173,23 +173,27 @@ erc--assemble-toggle ;; For corner cases where this fails and where the catch-all of `erc' ;; is inappropriate, (global) modules can declare a top-level ;; -;; (custom-add-to-group 'erc-foo 'erc-bar-mode 'custom-variable) +;; (put 'foo 'erc-group 'erc-bar) ;; -;; *before* the module's definition. If `define-erc-module' ever -;; accepts arbitrary keywords, passing an explicit `:group' will +;; 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 - (while symbols - (when-let* ((s (pop symbols)) - (downed (concat "erc-" (downcase (symbol-name s)))) - (known (intern-soft downed))) - (when-let ((found (custom-group-of-mode known))) - (throw 'found found)) - (when (or (get known 'group-documentation) - (rassq known custom-current-group-alist)) - (throw 'found known)))) + (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)) (defun erc--custom-set-minor-mode (variable value) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 70ba82fd4bf..5e971f15f5d 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1854,9 +1854,10 @@ erc-modules (const :tag "autojoin: Join channels automatically" autojoin) (const :tag "button: Buttonize URLs, nicknames, and other text" button) (const :tag "capab: Mark unidentified users on servers supporting CAPAB" - capab) + capab-identify) (const :tag "completion: Complete nicknames and commands (programmable)" completion) + (const :tag "hecomplete: Complete nicknames and commands (obsolete, use \"completion\")" hecomplete) (const :tag "dcc: Provide Direct Client-to-Client support" dcc) (const :tag "fill: Wrap long lines" fill) (const :tag "identd: Launch an identd server on port 8113" identd) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 703b26dcea0..e5db78ef2e1 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1214,29 +1214,33 @@ erc--find-group (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) "")) + (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 'foo nil) 'erc)) + (should (eq (erc--find-group 'fake 'baz) 'erc-foo)))) (ert-deftest erc--find-group--real () :tags '(:unstable) - (let (out) - (pcase-dolist (`(,feat . ,syms) erc--features-to-modules) - (require feat) - (push (cons syms (apply #'erc--find-group syms)) out)) - ;; Remove local modules, which are mapped to the catch-all - (while (and-let* ((m (rassq 'erc out))) ; while-let - (setq out (remq m out)))) - (should (equal out - '(((services nickserv) . erc-services) - ((stamp timestamp) . erc-stamp) - ((sound ctcp-sound) . erc-sound) - ((page ctcp-page) . erc-page) - ((autojoin) . erc-autojoin) - ((capab capab-identify) . erc-capab) - ((completion pcomplete) . erc-pcomplete)))))) + (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 -- 2.39.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-5.6-Don-t-associate-ERC-modules-with-undefined-group.patch >From 380ea8edc391aa75be9b7c7019bfc8c3db57e4f4 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 994555acecf..bf3bce74cfd 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -148,6 +148,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 will appear 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 where this fails and where the catch-all of `erc' +;; is 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. @@ -182,7 +213,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 @@ -193,10 +223,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 40a2d2de657..24a4f9d0639 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.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-5.6-Warn-when-setting-minor-mode-vars-for-ERC-module.patch >From 84bdae341ec2e19ba45c6dd9547dc3a5db43cbea 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 | 78 +++++++++++++++++++++++++++++++++++--- lisp/erc/erc.el | 3 +- test/lisp/erc/erc-tests.el | 13 +++++-- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index bf3bce74cfd..ec3a7cf9e85 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) @@ -123,6 +129,15 @@ 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 mode toggle is updating module membership. +This serves as a flag to inhibit the mutual recursion that +otherwise occurs 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.") + (defun erc--assemble-toggle (localp name ablsym mode val body) (let ((arg (make-symbol "arg"))) `(defun ,ablsym ,(if localp `(&optional ,arg) '()) @@ -140,11 +155,13 @@ 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))) + `((unless erc--inside-mode-toggle-p + ,(if val + `(cl-pushnew ',(erc--normalize-module-symbol name) + erc-modules) + `(setq erc-modules + (delq ',(erc--normalize-module-symbol name) + erc-modules)))) (setq ,mode ,val) ,@body))))) @@ -179,6 +196,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)) + (customize-set-variable + '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. @@ -225,6 +291,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 ff1820cfaf2..5e971f15f5d 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1845,7 +1845,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 24a4f9d0639..e254b00454b 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,14 +1336,16 @@ define-erc-module--global (defun erc-mname-enable () "Enable ERC mname mode." (interactive) - (cl-pushnew 'mname erc-modules) + (unless erc--inside-mode-toggle-p + (cl-pushnew 'mname erc-modules)) (setq erc-mname-mode t) (ignore a) (ignore b)) (defun erc-mname-disable () "Disable ERC mname mode." (interactive) - (setq erc-modules (delq 'mname erc-modules)) + (unless erc--inside-mode-toggle-p + (setq erc-modules (delq 'mname erc-modules))) (setq erc-mname-mode nil) (ignore c) (ignore d)) -- 2.39.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-5.6-Fill-doc-strings-for-ERC-modules.patch >From e4e270a4bf556ce238bc42c8549d4c443f3a969a 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 ec3a7cf9e85..cc278428d5d 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -141,7 +141,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 @@ -245,6 +245,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. @@ -284,11 +298,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 e254b00454b..e5db78ef2e1 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 @@ -1359,7 +1360,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)) @@ -1371,10 +1372,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 @@ -1383,7 +1385,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 @@ -1395,7 +1398,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.1 --=-=-=--