A graph layout library for Emacs Lisp.
This is in early alpha so far!
The algorithm is a port from vijual, a Clojure library by Conrad Barski, who deserves most of the credit.
- [X] Customizable text rendering
- [ ] Image rendering
- [X] Trees
- [ ] Undirected graphs
- [ ] Directed graphs
- [X] Binary trees
You can render trees as text with graph-draw-tree
:
(graph-draw-tree '((north-america (usa
(miami)
(seattle)
(idaho (boise))))
(europe (germany)
(france (paris)
(lyon)
(cannes)))))
+------------+ +--------+ | north | | europe | | america | +----+---+ +------+-----+ | | +---------+---------+ + | | | +----+----+ +---+----+ +--+--+ | germany | | france | | usa | +---------+ +---+----+ +--+--+ | | +--------+---------+ +----------+----------+ | | | | | | +---+---+ +--+---+ +---+----+ +---+---+ +----+----+ +---+---+ | paris | | lyon | | cannes | | miami | | seattle | | idaho | +-------+ +------+ +--------+ +-------+ +---------+ +---+---+ | + | +---+---+ | boise | +-------+
(graph-draw-tree '(("Eubacteria" ("Aquificae") ("Nitrospira") ("Proteobacteria") ("Chlamydiae") ("Actinobacteria")) ("Eukaryotes" ("Archaeplastida" ("Green Plants" ("Prasinophytes") ("Chlorophyceae") ("Trebouxiophyceae") ("Ulvophyceae") ("Streptohyta" ("Zygnematales") ("Charales") ("Embryophytes (land plants)"))) ("Rhodophyta") ("Glaucophytes")) ("Unikots" ("Opisthokonts" ("Animals" ("Bilateria" ("Ecdysozoa" ("Nematoda") ("Arthropoda")) ("Lophotrochozoa") ("Deuterostoma" ("Echinodermata") ("Hemichordata") ("Chordata" ("Urochordata") ("Cephalochordata") ("Yonnanozoon") ("Craniata")))) ("Cnidaria") ("Porifera")) ("Choanoflagellates") ("Filasterea") ("Ichthyosporea") ("Fungi") ("Nucleariidae"))) ("Chromalveolates" ("Rhizaria" ("Cercozoa") ("Foraminifera") ("Radiolaria")) ("Alveolates") ("Stramenopiles") ("Hacrobia")) ("Excavates" ("Malawimonads") ("Discicristates" ("Euglenozoa") ("Heterolobosea")) ("Fornicata")))))
+------------+ +------------+ | Eubacteria | | Eukaryotes | +-----+------+ +-----+------+ | | +-------------+--------------+--------------+--------------+ +---------------------------------+----------------------------+-------------+-------------------------------------------------+ | | | | | | | | | +-----+-----+ +-----+------+ +-----+------+ +-----+------+ +-----+------+ +-----+------+ +----+----+ +------+-----+ +-----+-----+ | Aquificae | | Nitrospira | | Proteobact | | Chlamydiae | | Actinobact | | Archaeplas | | Unikots | | Chromalveo | | Excavates | +-----------+ +------------+ | eria | +------------+ | eria | | tida | +----+----+ | lates | +-----+-----+ +------------+ +------------+ +-----+------+ | +------+-----+ | | + | +--------------+--------------+ +--------------+--------------+-------------+ | +-------------+-------+------+-------------+ | | | | | | +------+-----+ | | | | +-----+------+ +-----+------+ +-----+-----+ +-----+------+ +-----+------+ +-----+------+ | Opisthokon | +----+-----+ +-----+------+ +-----+------+ +----+-----+ | Malawimona | | Discicrist | | Fornicata | | Green | | Rhodophyta | | Glaucophyt | | ts | | Rhizaria | | Alveolates | | Stramenopi | | Hacrobia | | ds | | ates | +-----------+ | Plants | +------------+ | es | +------+-----+ +----+-----+ +------------+ | les | +----------+ +------------+ +-----+------+ +-----+------+ +------------+ | | +------------+ | | | | ++-------------+ +--------------+--------------+--------------+--------------+ | +--------------------------+-------------+--------------+ | | | | | | | | | | | +-----+------+ +-----+------+ +-----+------+ +-----+------+ +-----+------+ +-----+------+ +-----+------+ +------------+--------------+-----+--------+------------+-----------+ +----+-----+ +-----+------+ +-----+------+ | Euglenozoa | | Heterolobo | | Prasinophy | | Chlorophyc | | Trebouxiop | | Ulvophycea | | Streptohyt | | | | | | | | Cercozoa | | Foraminife | | Radiolaria | +------------+ | sea | | tes | | eae | | hyceae | | e | | a | +----+----+ +-----+------+ +-----+------+ +-----+------+ +---+---+ +-----+------+ +----------+ | ra | +------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +-----+------+ | Animals | | Choanoflag | | Filasterea | | Ichthyospo | | Fungi | | Nucleariid | +------------+ | +----+----+ | ellates | +------------+ | rea | +-------+ | ae | | | +------------+ +------------+ +------------+ | | | +--------------+------------+------------+ | | | | +-------------+-------------+ +-----+-----+ +----+-----+ +----+-----+ | | | | Bilateria | | Cnidaria | | Porifera | +-----+------+ +----+-----+ +-----+------+ +-----+-----+ +----------+ +----------+ | Zygnematal | | Charales | | Embryophyt | | | es | +----------+ | es (land | | +------------+ | plants) | | +------------+ | | +--------------+--------------+ | | | +-----+-----+ +------+-----+ +------+-----+ | Ecdysozoa | | Lophotroch | | Deuterosto | +-----+-----+ | ozoa | | ma | | +------------+ +------+-----+ +------+------+ | | | +-------+------+-------------+ +-----+----+ +------+-----+ | | | | Nematoda | | Arthropoda | +------+-----+ +------+-----+ +-----+----+ +----------+ +------------+ | Echinoderm | | Hemichorda | | Chordata | | ata | | ta | +-----+----+ +------------+ +------------+ | | +----------------------+--------------+-------------+ | | | | +-----+------+ +------+-----+ +------+-----+ +-----+----+ | Urochordat | | Cephalocho | | Yonnanozoo | | Craniata | | a | | rdata | | n | +----------+ +------------+ +------------+ +------------+
You can render binary trees as text with graph-draw-binary-tree
:
(graph-draw-binary-tree '(1 (2 (3) (4)) (5)))
+---+ | 1 | +---+ / \ / \ +---+ +---+ | 2 | | 5 | +---+ +---+ / \ / \ +---+ +---+ | 3 | | 4 | +---+ +---+
(graph-draw-binary-tree '(organisms (prokaryotes (e-coli)) (eukaryotes (plants (seed-plants (carrot) (oak-tree)) (ferns)) (animalia (invertebrates (sponge) (worm)) (mammals (mouse) (apes (chimpanzee) (human)))))))
+-----------+ | organisms | +-----------+ / \_________________________________________ / \ +-------------+ +------------+ | prokaryotes | | eukaryotes | +-------------+ +------------+ / / \_______________________________ / / \ +--------+ +--------+ +----------+ | e coli | | plants | | animalia | +--------+ +--------+ +----------+ / \_ / \___________ / \ / \ +-------------+ +-------+ +---------------+ +---------+ | seed plants | | ferns | | invertebrates | | mammals | +-------------+ +-------+ +---------------+ +---------+ / \ / \ / \________________ / \ / \ / \ +--------+ +----------+ +--------+ +------+ +-------+ +------+ | carrot | | oak tree | | sponge | | worm | | mouse | | apes | +--------+ +----------+ +--------+ +------+ +-------+ +------+ / \ / \ +------------+ +-------+ | chimpanzee | | human | +------------+ +-------+
This is currently not available for binary trees!
All drawing operations can be customized by setting the respective drawing function variable. You can associate arbitrary data with shapes/nodes, which will be passed to each drawing function. The default functions ignore the user data but it can be used in when customizing the drawing.
To add custom data, use a cons cell instead of a string for a node:
(graph-draw-tree '((("parent with data" . datadatadata) ("plain child")
(("child With data" . somedata)))))
The parent node and the second child have some data associated with them. This data will get passed to all of the drawing functions. By customizing these functions, you can draw colored trees/shapes.
You can also layout a tree once, and just re-render the shapes. The data is available under the :data
slot:
(let* ((shapes (graph-tree-to-shapes '((("node with data" . somedata)))))
(data (graph-shape-data (car shapes))))
(setf (graph-shape-data (car shapes) 'newdata))
(graph-draw-shapes shapes))
In line 1, we layout a tree and convert it into shapes.
The user-data can be accessed via graph-shape-data
(see line 2).
You can also modify the data as shown in line 3 and finally re-render
the shapes with graph-draw-shapes
.
Below is a list of all drawing functions that can be customized:
This is a wrapper around all drawing functions. You can conviniently change customize all drawing globally by setting this function. The function will be called with the drawn text plus optional user-data that was associated with the shape.
(let ((graph-draw-custom-fn (lambda (drawn data) (propertize drawn 'font-lock-face `(:foreground ,data)))))
(graph-draw-tree '((("rednode" . "red") (("bluenode". "blue"))))))
This function is called with a direction and the user-data and should
return a string of length 1. The direction can be 'up
, 'down
, 'left
, 'right
or an arbitrary direction.
This function is called with a direction and the user-data and should
return a string of length 1. The direction can be 'up
, 'down
, 'left, or ='right
.
This function is called with a type and the user-data and should return a string of length 1. It’s used to draw the corners of boxes for example.
This function is called with a width and the user-data and should return a string of length of the given width. It draws the border of a box or shape between the corners.
This function is called with the user-data and should return a string of length 1. It is used to draw the side border of a box.
This function is called with a width and the user-data and should return a string of length of the given width. It’s used to draw the empty space of a shape.
This function is called with some text to render and the user-data.
There are a couple of variables to customize the layout.
graph-ascii-wrap-threshold
: text is wrapped after the number of characters specified.graph-node-padding
: horizontal padding between nodesgraph-row-padding
: vertical padding between rowsgraph-line-wid
: Line widthgraph-line-padding
: Space between lines