This project got integrated into Emacs core in release 28.1. Please contribute patches to Emacs core directly instead of here.
Library to create, query, navigate and display hierarchy structures. You might want to read the introductory blog post.
Use melpa.
After having created a hierarchy with hierarchy-new
, populate it by
calling hierarchy-add-tree
or hierarchy-add-trees
. You can
then optionally sort its element with hierarchy-sort
. For example,
you can create an animal hierarchy by passing a child-to-parent
function to hierarchy-add-tree
:
(require 'hierarchy)
(setq animals (hierarchy-new))
(let ((parentfn
;; Given an item, return its parent
(lambda (item)
(cl-case item
(dove 'bird)
(pigeon 'bird)
(bird 'animal)
(dolphin 'animal)
(cow 'animal)))))
(hierarchy-add-tree animals 'dove parentfn)
(hierarchy-add-tree animals 'pigeon parentfn)
(hierarchy-add-tree animals 'dolphin parentfn)
(hierarchy-add-tree animals 'cow parentfn))
(hierarchy-sort animals)
You can learn more about your hierarchy by using functions such as
hierarchy-roots
, hierarchy-length
, hierarchy-children
,
hierarchy-descendant-p
. For example, hierarchy-roots
returns any
item without a parent in a hierarchy:
(hierarchy-roots animals)
animal |
animal
is the only item of the animals
hierarchy with no
parent. To get all items with no child, use hierarchy-leafs
:
(hierarchy-leafs animals)
dove | pigeon | dolphin | cow |
It is possible to get the children of an item by using
hierarchy-children
:
(hierarchy-children animals 'animal)
bird | cow | dolphin |
We see here that animal
has three children.
You can navigate a hierarchy using hierarchy-map-item
,
hierarchy-map
and hierarchy-map-tree
. For example, this code
inserts a text view of a hierarchy in a buffer:
(with-temp-buffer
(hierarchy-map
(hierarchy-labelfn-indent
(lambda (animal _) (insert (symbol-name animal) "\n")))
animals)
(buffer-substring (point-min) (point-max)))
animal bird dove pigeon cow dolphin
The indentation between a parent and its child can be configured by
passing one more parameter to hierarchy-labelfn-indent
. You can also
display clickable buttons instead of just plain text using either
hierarchy-labelfn-button
or hierarchy-labelfn-button-if
.
If you want a buffer containing only a hierarchy while being able to
navigate it with standard key-bindings use either
hierarchy-tabulated-display
or hierarchy-tree-display
as
shown in below animated pictures.
(switch-to-buffer
(hierarchy-tabulated-display
animals
(hierarchy-labelfn-indent
(hierarchy-labelfn-button
(lambda (item _) (insert (symbol-name item)))
(lambda (item _) (message "You clicked on: %s" item))))))
(switch-to-buffer
(hierarchy-tree-display
animals
(lambda (item _) (insert (symbol-name item)))))
The hierarchy library can be used to display any kind of hierarchy you need. For example, a file-system navigator is provided as an example.
(load "./examples/hierarchy-examples-fs.el")
;; Execute one of the following lines to show the `.emacd.d' hierarchy
;; in either a tabulated list or a tree widget. This takes around 3
;; seconds on my computer.
(hierarchy-examples-fs-display-filesystem "~/.emacs.d")
(hierarchy-examples-fs-display-filesystem-tree "~/.emacs.d")
Emacs and packages define quite a lot of faces. Because a face may inherit from another one, we can get a hierarchy of them:
This is based on an idea and code from Yuan Fu.
Emacs and packages define quite a lot of major modes. A major mode usually derives from another one which means we can get a hierarchy of major modes:
With a bit more work, the hierarchy library can also be used to display class hierarchies (as I am currently experimenting in this project).
A JSON navigator is also implemented as yet another example.
Yes, please do! See CONTRIBUTING for guidelines.
See COPYING. Copyright (c) 2017 Damien Cassou.