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.