bug#3811: 23.0.96; custom-group-members

"Drew Adams" <[email protected]>
Newsgroups gmane.emacs.bugs,gmane.emacs.pretest.bugs
Message-ID <[email protected]>
> It might be useful to have another function (or perhaps 
> another optional arg to this function), which would act 
> recursively to give you all members, indirect or direct, that 
> belong to the group - IOW, anything that belongs to the group 
> or to one of its subgroups (recursively).

To be clear what I meant, something like this:

(defun custom-group-members (symbol groups-only
                             &optional recursivep)
  "Return members of the custom group for SYMBOL.
If GROUPS-ONLY is non-nil, return only those direct members
 that are groups.
If RECURSIVEP is non-nil and GROUPS-ONLY is nil, return
 non-group direct and indirect members."
  (let ((members  ()))
    (cond (groups-only
           (dolist (entry  (get symbol 'custom-group))
             (when (eq (cadr entry) 'custom-group)
               (push entry members)))
           (nreverse members))
          (recursivep
           (let ((direct-members  (custom-group-members symbol nil)))
             (dolist (dm  direct-members)
               (if (eq (cadr dm) 'custom-group)
                   (setq members
                         (nconc (custom-group-members (car dm) nil t)
                                members))
                 (push dm members)))
             (nreverse members)))
          (t
           (get symbol 'custom-group)))))

It would be even better to combine args GROUPS-ONLY and RECURSIVEP, but that
might mean problems for backward incompatibility. But perhaps something like
this would be OK?

(defun custom-group-members (symbol arg)
  "Return members of the custom group for SYMBOL.
ARG nil means return all direct group members: groups and non-groups.
ARG `nongroups' means return all nongroup members, recursively.
ARG anything else means return all direct group members."
  (let ((members  ()))
    (case arg
      ((nil) (get symbol 'custom-group))
      (nongroups
       (let ((direct-members  (custom-group-members symbol nil)))
         (dolist (dm  direct-members)
           (if (eq (cadr dm) 'custom-group)
               (setq members
                     (nconc (custom-group-members
                             (car dm) 'nongroups)
                            members))
             (push dm members)))
         (nreverse members)))
      (t (dolist (entry  (get symbol 'custom-group))
           (when (eq (cadr entry) 'custom-group)
             (push entry members)))
         (nreverse members)))))

That would still work for any existing code that used a value other than
`nongroups' as the second arg, which probably means there would be no problems
in practice.

We might also consider making this a command. Users could use it to print out a
list of the options and faces for a group.

Note that one use of the proposed recursive behavior is for a user to create a
custom group that represents a collection of personal settings (across other
custom groups), and then to share those settings with others. (See the
emacs-devel discussion of "skins" as custom groups.)

A user Jane could, for example, use `custom-add-to-group' with group `jane', and
then she could publish the `jane' settings for others, retrieving them using
`custom-group-members'. The only other piece missing would then be a way for
non-Lisp users to do the equivalent of `custom-add-to-group' using only the
Customize UI. That is, we would provide easy ways to specify that certain
options and faces should be added to group `jane'.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.