all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: "Etienne Prud’homme" <e.e.f.prudhomme@gmail.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: emacs-devel@gnu.org
Subject: Re: Easy traversal of customize groups
Date: Fri, 23 Jun 2017 18:56:25 -0400	[thread overview]
Message-ID: <878tkiia92.fsf@x230.lts> (raw)
In-Reply-To: <jwva84yqwek.fsf-monnier+gmane.emacs.devel@gnu.org> (Stefan Monnier's message of "Fri, 23 Jun 2017 16:34:31 -0400")

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> Another option is to perform one mapatoms traversal which builds a cache
> of the "reverse links" and then use that.

That’s also a solution.  Were you talking about a tree structure?

It think it might over complicate the current implementation since we
would have to remove an entry from the cache when it is unloaded and we
would have to update each possible paths when a new group is loaded.

Here’s a snippet of what I’m using:

> (require 'seq)
> 
> (defun custom-group-parent-group-p (group parent)
>   "Test that GROUP is a direct child of PARENT."
>   (eq 'custom-group (car (alist-get group (get parent 'custom-group)))))
> 
> (defun custom-group-parent-groups (group)
>   "Return a list of parent groups for GROUP.
> 
> E.g. “wdired” would return “(dired)”.
> 
> Note: This function has much faster implementation of finding
> parents than using `custom-group-parent-group-p'.  Around 10x
> faster than mapping with `custom-group-parent-group-p'."
>   (let ((parents))
>     ;; First find the “group” a-list candidates.
>     (mapatoms (lambda (symbol)
>                 (when (alist-get group (get symbol 'custom-group))
>                   (setq parents (cons symbol parents))))
>               obarray)
>     ;; Than filter “group” a-list candidates to only show `custom-group'
>     ;; symbol properties.
>     (seq-filter (lambda (value)
>               (eq (car (alist-get group (get value 'custom-group))) 'custom-gr> oup))
>             parents)))
> 
> (defun custom-group-get-paths (group)
>   "Get an ordered list on the parent paths for GROUP.
> 
> The path is in the form of:
> \((files dired wdired)
>  (environment dired wdired))
> 
> Where “files” is the topmost parent group of the “wdired”
> group (without counting an orphan or the Emacs group)."
>   (let ((tree (custom-group--get-tree group))
>         (paths)
>         (custom-group-get--paths))
>     (setq custom-group-get--paths
>           (lambda (nodes path)
>             "Private.
> 
> Go through all possible NODES and add the PATH to the `paths' variable."
>             (message (prin1-to-string nodes))
>             (let ((newpath (if (listp path)
>                                path
>                              (list path)))
>                   (newnodes (cadr nodes)))
>               (unless (eq nil (car nodes))
>                 (push (car nodes) newpath))
>               (if newnodes
>                   (dolist (node newnodes)
>                     (funcall custom-group-get--paths node newpath))
>                 (add-to-list 'paths newpath)))))
>     (funcall custom-group-get--paths tree nil)
>     paths))
> 
> (defun custom-group--get-tree (group)
>   "Private.
> 
> Get a tree on the parent paths for GROUP.
> 
> The following tree:
> ╔══════════════════════════════════════╗
> ║ files ─────────┐                     ║
> ║                ├─── dired ─── wdired ║
> ║ environment ───┘                     ║
> ╚══════════════════════════════════════╝
> 
> Would give the expression:
> ╔════════════════════════════════════════════════════════╗
> ║ (wdired ((dired ((environment (nil)) (files (nil)))))) ║
> ╚════════════════════════════════════════════════════════╝
> 
> Where nil either represent no more parent or the Emacs group."
>   (let ((parents (custom-group-parent-groups group))
>         (tree))
>     (unless (or (eq nil group) (eq 'emacs group))
>       (cons group
>             (list
>              (dolist (parent parents tree)
>                (push (custom-group--get-tree parent) tree)))))))
 
As an example, if we get “message-forwarding”: 

> (require 'gnus)
> (require 'message)
> (custom-group-get-paths 'message-forwarding)

It becomes quite a large tree:
> (message-forwarding
>  ((message-interface
>    ((message
>      ((news
>        ((applications (nil))))
>       (mail ((applications (nil))))
>       (gnus-message
>        ((gnus
>          ((news ((applications (nil))))
>           (mail ((applications (nil))))))))))))))

Where “nil” is the Emacs group node.

We could of course map their parents instead of making a tree structure,
but it’s almost the same way my suggestion works.

I’m proposing to change the “custom-declare-group” function to add links
to the parent groups wen defining a new group.

--
Etienne



  reply	other threads:[~2017-06-23 22:56 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-23 17:31 Easy traversal of customize groups Etienne Prud’homme
2017-06-23 20:34 ` Stefan Monnier
2017-06-23 22:56   ` Etienne Prud’homme [this message]
2017-06-24  0:06     ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=878tkiia92.fsf@x230.lts \
    --to=e.e.f.prudhomme@gmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.