CL-DOT is a small package for easily generating Dot (a program in the GraphViz suite) output from arbitrary Lisp data. It works with the following Common Lisp implementations:
Original author is Juho Snellman, current maintainer is Michael Weber. The code is covered by the MIT license, see Copying.
This manual is also available in PDF format.
Download shortcut: http://www.foldr.org/~michaelw/projects/cl-dot/cl-dot.tar.gz
CL-DOT together with this documentation can be downloaded from
http://www.foldr.org/~michaelw/projects/cl-dot/cl-dot.tar.gz
Alternatively, it can be installed via ASDF-Install:
(asdf-install:install "http://www.foldr.org/~michaelw/projects/cl-dot/cl-dot.tar.gz")
or simply (via CLiki)
(asdf-install:install :cl-dot)
A Subversion repository is available at http://svn.foldr.org/~michaelw/cl-dot/.
The current version is 0.8.0.
CL-DOT has no dependencies on other systems, but it requires the GraphViz suite to be installed for rendering.
First, we define methods for the generic functions in the
GRAPH-OBJECT protocol (see The GRAPH-OBJECT Protocol) for all
objects that can appear in our graph. graph-object-node must
be defined for all objects, the others have a default implementation.
For example:
;; Conses (defmethodcl-dot:graph-object-node((graph (eql 'example)) (object cons)) (make-instance 'cl-dot:node:attributes '(:label "cell \\N" :shape :box))) (defmethodcl-dot:graph-object-points-to((graph (eql 'example)) (object cons)) (list (car object) (make-instance 'cl-dot:attributed:object (cdr object) :attributes '(:weight 3)))) ;; Symbols (defmethodcl-dot:graph-object-node((graph (eql 'example)) (object symbol)) (make-instance 'cl-dot:node:attributes `(:label ,object :shape :hexagon :style :filled :color :black :fillcolor "#ccccff")))
Note that in this example, the first argument to all GRAPH-OBJECT
functions, graph, is only used to segregate the rendering of cons
cells and symbols from those of other uses of CL-DOT. However, it could
also be used to look up node information which is stored external to
object.
A call to generate-graph-from-roots generates an instance of
graph for our data. From this graph instance, we can either
generate dot-format output to some stream with print-graph, or
call dot directly on the data with dot-graph. For example:
(let* ((data '(a b c #1=(b z) c d #1#))
(dgraph (cl-dot:generate-graph-from-roots 'example (list data))))
(cl-dot:dot-graph dgraph "test.png" :format :png))
We can also specify attributes for the whole graph:
(let* ((data '(a b c #1=(b z) c d #1#))
(dgraph (cl-dot:generate-graph-from-roots 'example (list data)
'(:rankdir "LR"))))
(cl-dot:dot-graph dgraph "test-lr.png" :format :png))

Figure 2.1: Graph of conses (A B C #1=(B Z) C D #1#), generated by
dot-graph with attributes (:RANKDIR "LR")
In order to render an undirected graph we can call dot-graph
in the following way:
(cl-dot:dot-graph dgraph "test.png"
:format :png
:directed nil)

Figure 2.2: Graph of conses (A B C #1=(B Z) C D #1#), generated by
dot-graph with option :directed nil
When the directed keyword argument is set to NIL (the
default value is T) dot-graph outputs an undirected
graph instead of a directed. To do that it needs the neato
program from the Graphviz package, which is used to layout undirected
graphs. The path to the neato program is stored in the
*neato-path* special variable.
Note that neato will not automatically fold duplicate edges. I.e., an edge from node a to node b and another from b to a will both end up being part of the graph.
Not all of the functionality of the GraphViz suite is accessible from CL-DOT. Patches which add more features are highly welcome.
Path to the dot and neato commands, both from the GraphViz suite.
GRAPH-OBJECT ProtocolThe GRAPH-OBJECT protocol is used to translate Lisp data into a
graph representation suitable for rendering with the Dot
program.
All protocol functions take as first parameter a context object graph. This allows to render objects like cons cells differently for different graphs.
Another use of the graph parameter is to look up node information
needed for rendering. For example, if nodes are represented as integers
and edges between nodes can be looked up in an external table, this
table can be made accessible to the GRAPH-OBJECT functions via
the graph parameter.
&optional attributesT T &optional attributesConstruct a graph with attributes, starting from objects (a sequence). Other functions of the
GRAPH-OBJECTprotocol are subsequently called on objects to discover other graph nodes and edges between them.
T TReturns a list of objects that object knows should be part of the graph, but which it has no direct connections to.
The default method returns the empty list.
Returns a
nodeinstance for object, orNIL. In the latter case the object will not be included in the constructed ouput, but it can still have an indirect effect via other protocol functions (e.g.,graph-object-knows-of). This function will only be called once for each object during the generation of a graph.
T TReturns a list of objects to which the node of object should be connected. The edges will be directed from the other objects to this one.
To assign Dot attributes to the generated edges, each object can optionally be wrapped in an instance of class
attributed.The default method returns the empty list.
T TReturns a list of objects to which the
nodeof object should be connected. The edges will be directed from object to the others.To assign Dot attributes to the generated edges, each object can optionally be wrapped in an instance of class
attributed.The default method returns the empty list.
The rendering of Dot graphs, their nodes and edges can be influenced by attributes. Attributes are represented as keywords of the same name. Multiple attributes can be given in form of a plist.
CL-DOT supports most Dot attributes, a detailed list follows. Attributes which are not recognized result in an error when generating a graph.
Most attributes have self-explanatory names, for more information we refer to the documentation of Dot.
Graph attributes can be given to
generate-graph-from-roots and apply to the whole graph.
:bgcolor text:center integer:color text:edge edge-attribute (generate-graph-from-roots graph initial-states
'(:edge (:arrowhead :odot)))
:layers text:margin float:mclimit float:node node-attribute (generate-graph-from-roots graph initial-states
'(:node (:shape :box)
:node (:color :red)))
:nodesep float:nslimit float:ordering (:out):page text:pagedir text:rank (:same :min :max):rankdir ("LR" "RL" "BT"):ranksep float:ratio (:fill :compress :auto):rotate integer:size text:color text:fillcolor text:fixed-size boolean:fontname text:fontsize integer:height integer:label label Note that verbatim backslashes inside of Lisp strings must be escaped
themselves. E.g., the attribute :label "Node \\N\\l" produces a
left-justified node label which includes the node identifier.
By default, #\Newline-delimited lines contained in label
are horizontally centered in Dot output. However, if the value of
label is a list (alignment text), then
alignment specifies how lines in string text are rendered.
alignment can be one of :left, :center,
:right.
:layer text:shape shape :record :plaintext :ellipse :circle :egg :triangle :box
:diamond :trapezium :parallelogram :house :hexagon :octagon
:style (:filled :solid :dashed :dotted :bold :invis):width integer:arrowhead arrow-spec :none :normal :inv :dot :odot :invdot :invodot :tee :empty
:invempty :open :halfopen :diamond :odiamond :box :obox :crow
:arrowtail arrow-spec :none :normal :inv :dot :odot :invdot :invodot :tee :empty
:invempty :open :halfopen :diamond :odiamond :box :obox :crow
:color text:constraint boolean:decorate boolean:dir (:forward :back :both :none):fontcolor text:fontname text:fontsize integer:headclip boolean:headlabel text:label text:labeldistance integer:labelfontcolor text:labelfontname text:labelfontsize integer:layer text:minlen integer:port-label-distance integer:samehead boolean:sametail boolean:style (:solid :dashed :dotted :bold :invis):tailclip boolean:taillabel text:weight integer&key format directedRenders graph (an instance of
graph, see Classes) to outfile, by running the program in either*dot-path*or*neato-path*.When directed is
T(the default) it will use the program specified in*dot-path*to render a directed graph. Otherwise, (when directed isNIL)dot-graphwill render an undirected graph using the program specified in*neato-path*.The default format is Postscript.
&optional streamPrints a dot-format representation of graph (an instance of
graph, see Classes) to stream.
A graph suitable for rendering with the Dot command. Instance of this class are most often generated with
generate-graph-from-roots(see The GRAPH-OBJECT Protocol) orgenerate-graph(see The Object Protocol).
:attributes attributes :id idA graph node with dot attributes (a plist, initarg attributes, see Dot Attributes) and an optional node identifier (initarg id, auto-generated by default).
:object object :attributes attributesWraps an object (initarg object) with edge attribute information (a plist, initarg attributes, see Dot Attributes). See Usage, for an example of how to use
attributed.
The OBJECT protocol has been deprecated in favor of the more
general GRAPH-OBJECT protocol (see The GRAPH-OBJECT Protocol), which allows objects to be presented differently for
different graphs. For backwards compatibility, the OBJECT
protocol functions are called by their respective GRAPH-OBJECT
equivalents when generate-graph is used.
OBJECT Protocol&optional attributesT &optional attributesConstruct a graph with attributes starting from object, using the
OBJECTprotocol.The default method calls
generate-graph-from-rootswith a singleton list of object.
TThe default method returns the empty list.
Returns a
nodeinstance for object, orNIL. In the latter case the object will not be included in the constructed ouput, but it can still have an indirect effect via other protocol functions (e.g.,object-knows-of). This function will only be called once for each object during the generation of a graph.
TThe default method returns the empty list.
TThe default method returns the empty list.
Please direct bug reports, patches, questions, and any other feedback to Michael Weber. A small check list helps to stream-line the process of submitting patches:1
The following Lisp projects provide similar functionality:
Quoting the main developer, Attila Lendvai:2
“[...] if you only want to layout a few graphs from the repl then trivial-shell and the utils in cl-graph are your friends to exec the dot binary. cl-graphviz only helps if you want to have a web service or something and want to avoid exec'ing.”
This manual is for CL-DOT, version 0.8.0.
Copyright © 2005 Juho Snellman
Copyright © 2007,2008 Michael Weber
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
dot-graph: Generating Outputgenerate-graph: Deprecated Functionalitygenerate-graph-from-roots: The GRAPH-OBJECT Protocolgraph-object-knows-of: The GRAPH-OBJECT Protocolgraph-object-node: The GRAPH-OBJECT Protocolgraph-object-pointed-to-by: The GRAPH-OBJECT Protocolgraph-object-points-to: The GRAPH-OBJECT Protocolobject-knows-of: Deprecated Functionalityobject-node: Deprecated Functionalityobject-pointed-to-by: Deprecated Functionalityobject-points-to: Deprecated Functionalityprint-graph: Generating Output[1] lifted from http://weitz.de/patches.html
[2] Message-Id: <49d30481-63ee-475e-be17-07cc684f2a56@w34g2000hsg.googlegroups.com>