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: Sun, 19 Feb 2023 07:03:18 -0800 Message-ID: <87k00dwvd5.fsf__27309.2275647045$1676819065$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="23070"; 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 Sun Feb 19 16:04:18 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 1pTlEf-0005pr-H1 for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 19 Feb 2023 16:04:17 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pTlES-0007w9-1l; Sun, 19 Feb 2023 10:04:04 -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 1pTlEQ-0007vv-Mw for bug-gnu-emacs@gnu.org; Sun, 19 Feb 2023 10:04:02 -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 1pTlEQ-0000xD-E1 for bug-gnu-emacs@gnu.org; Sun, 19 Feb 2023 10:04:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pTlEQ-0001tm-9X for bug-gnu-emacs@gnu.org; Sun, 19 Feb 2023 10:04: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: Sun, 19 Feb 2023 15:04: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.16768190167255 (code B ref 60935); Sun, 19 Feb 2023 15:04:02 +0000 Original-Received: (at 60935) by debbugs.gnu.org; 19 Feb 2023 15:03:36 +0000 Original-Received: from localhost ([127.0.0.1]:49453 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pTlDz-0001sw-Ct for submit@debbugs.gnu.org; Sun, 19 Feb 2023 10:03:36 -0500 Original-Received: from mail-108-mta246.mxroute.com ([136.175.108.246]:39039) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pTlDw-0001se-1Q for 60935@debbugs.gnu.org; Sun, 19 Feb 2023 10:03:33 -0500 Original-Received: from mail-111-mta2.mxroute.com ([136.175.111.2] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta246.mxroute.com (ZoneMTA) with ESMTPSA id 1866a33753d000edb4.001 for <60935@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Sun, 19 Feb 2023 15:03:22 +0000 X-Zone-Loop: 098574eabb886f89db902b50a6099cae63755749b196 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=z3UP0gqcJN4IWW8RyT4GTp3yQYbclXjTg9UqPKVElUk=; b=Nn7Sh0vH0TZkMbnYapNwmyPxcy 6WSspGYSqPCT7YFGPzAz0SBbD67un0rdq1lilaDp5k64Dbl4nIzgiSa7CKQM4ule+Dzfd4ch0SIqf KocJvmItLc2gt2C6Os5ekvXXYP7pCoqnrATuwCeujjHMflv/JK7KvvrYsv2snTzt5EgtZTMkG8Jn2 e+M6wPvewhP7oYrU6FcfOSA8dX6ckEuwhsB2sJtBNNiR5UapD/SCvwRta7vv5EZCIb8grDDuLjTyd Wv+SgJrfGWLrdZYSMpbmlZWSf0AlW84hfnV3Mx2OUvWbACjsMLBaQ4bv21kZEt4vXEwyxgGeArdhO sKHlgPxw==; 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:256075 Archived-At: --=-=-= Content-Type: text/plain v3. Run custom :set function inside toggles. (Now depends on bug#60954.) --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v2-v3.diff >From 23b193168c03c9d36307986f87f2789cafae9b41 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 16 Feb 2023 22:51:42 -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 | 143 +++++++++++++++++++++++++++++++++---- lisp/erc/erc.el | 3 +- test/lisp/erc/erc-tests.el | 84 +++++++++++++++++----- 4 files changed, 200 insertions(+), 31 deletions(-) Interdiff: diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index cc278428d5d..6d09ac25a0a 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -130,13 +130,14 @@ erc--normalize-module-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 + "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.") +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"))) @@ -155,23 +156,29 @@ erc--assemble-toggle (,ablsym)) (setq ,mode ,val) ,@body))) - `((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)))) + ;; 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)) + (customize-set-variable + 'erc-modules (,(if val 'cons 'delq) + ',(erc--normalize-module-symbol name) + erc-modules)))) (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 +;; 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 where this fails and where the catch-all of `erc' -;; is inappropriate, (global) modules can declare a top-level +;; 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) ;; diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index e5db78ef2e1..8e41d428ce9 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1337,16 +1337,22 @@ define-erc-module--global (defun erc-mname-enable () "Enable ERC mname mode." (interactive) - (unless erc--inside-mode-toggle-p - (cl-pushnew 'mname erc-modules)) + (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)))) (setq erc-mname-mode t) (ignore a) (ignore b)) (defun erc-mname-disable () "Disable ERC mname mode." (interactive) - (unless erc--inside-mode-toggle-p - (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)) + (customize-set-variable + '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=0001-5.6-Don-t-associate-ERC-modules-with-undefined-group.patch >From f976c06bd1bff9921ecef743076d0c4c5cfeb9fd 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..1503dc99d72 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 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. @@ -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 c790bfcac0275222cc5d54c95db4717bb67c6bfc 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 | 85 +++++++++++++++++++++++++++++++++++--- lisp/erc/erc.el | 3 +- test/lisp/erc/erc-tests.el | 19 +++++++-- 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index 1503dc99d72..bc67bf94a67 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,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) '()) @@ -140,11 +156,19 @@ 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)) + (customize-set-variable + 'erc-modules (,(if val 'cons 'delq) + ',(erc--normalize-module-symbol name) + erc-modules)))) (setq ,mode ,val) ,@body))))) @@ -179,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)) + (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 +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 d35907a1677..0087c7a09a1 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..26d986823b3 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,22 @@ 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)) + (customize-set-variable + 'erc-modules (cons '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 (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)))) (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 23b193168c03c9d36307986f87f2789cafae9b41 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 bc67bf94a67..6d09ac25a0a 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -142,7 +142,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 26d986823b3..8e41d428ce9 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 @@ -1365,7 +1366,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)) @@ -1377,10 +1378,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 @@ -1389,7 +1391,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 @@ -1401,7 +1404,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 --=-=-=--