Documentation
¶
Overview ¶
Package dot writes graphs in the DOT language of Graphviz, which dot, the other Graphviz layout tools and many viewers and editor plugins read.
Every vertex gets a generated node ID (n0, n1, ...) and its label goes in the label attribute, so two labels that print the same don't collide. Attribute values are written in quotes, with double quotes and backslashes escaped, & written as & so Graphviz doesn't read it as the start of an entity, newlines written as \n, and NUL bytes written as U+FFFD. A value set by an option is written as is instead when Graphviz reads all of it as one HTML-like label: it starts with <, its angle brackets balance, the first < closes at the last character, and there is more than spaces between them, as in <<b>bold</b>>. Any other value is quoted, so <b>bold</b> is drawn as that text.
Directed graphs are written as a digraph with -> for edges, and undirected graphs as a graph with --. Each undirected edge is written once, even though the graph stores it in both directions. Vertices without edges are still declared, so they appear in the drawing. Edges show their label in the label attribute when one is set, and otherwise their weight on weighted graphs. The weight attribute of Graphviz isn't set, since it changes the layout and dot only accepts non-negative integers for it.
The output is stable: a graph built the same way gives the same text on every run, so it can be checked into a repository or compared in tests. Vertices are sorted the same way as in the mermaid package, and attributes by name.
Example ¶
package main
import (
"fmt"
"github.com/hmdsefi/gograph"
"github.com/hmdsefi/gograph/encoding/dot"
)
func main() {
g := gograph.New[string](gograph.Directed(), gograph.Weighted())
a := g.AddVertexByLabel("A")
_, _ = g.AddEdge(a, gograph.NewVertex("B"), gograph.WithEdgeWeight(4))
out, err := dot.Marshal(g)
if err != nil {
fmt.Println(err)
return
}
fmt.Print(string(out))
}
Output: digraph { n0 [label="A"]; n1 [label="B"]; n0 -> n1 [label="4"]; }
Index ¶
- func Marshal[T comparable](g gograph.Graph[T], opts ...Option[T]) ([]byte, error)
- func Write[T comparable](w io.Writer, g gograph.Graph[T], opts ...Option[T]) error
- type Option
- func WithEdgeAttributes[T comparable](fn func(*gograph.Edge[T]) map[string]string) Option[T]
- func WithGraphAttributes[T comparable](attrs map[string]string) Option[T]
- func WithName[T comparable](name string) Option[T]
- func WithVertexAttributes[T comparable](fn func(*gograph.Vertex[T]) map[string]string) Option[T]
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Option ¶
type Option[T comparable] func(*options[T])
Option configures Marshal and Write.
func WithEdgeAttributes ¶
WithEdgeAttributes sets attributes for each edge, for example its color or style. By default an edge's label attribute is its label when one is set, or its weight on a weighted graph, and fn can replace it by setting label too. For an undirected edge, fn gets the direction that starts at the vertex that is written first. Attribute names follow the same rule as the name in WithName.
func WithGraphAttributes ¶
func WithGraphAttributes[T comparable](attrs map[string]string) Option[T]
WithGraphAttributes sets attributes for the whole graph, for example {"rankdir": "LR"} to lay it out from left to right.
func WithName ¶
func WithName[T comparable](name string) Option[T]
WithName sets the name of the graph, which is written after digraph or graph. By default the graph has no name. A DOT ID can't have a backslash at the end or before a double quote or a line break, so Marshal and Write return an error for such a name or attribute name.
func WithVertexAttributes ¶
WithVertexAttributes sets attributes for each vertex, for example its shape or color. By default a vertex has a label attribute with fmt.Sprint of its label, and fn can replace it by setting label too. Attribute names follow the same rule as the name in WithName.
Example ¶
package main
import (
"fmt"
"os"
"github.com/hmdsefi/gograph"
"github.com/hmdsefi/gograph/encoding/dot"
)
func main() {
g := gograph.New[string](gograph.Directed())
_, _ = g.AddEdge(gograph.NewVertex("checkout"), gograph.NewVertex("build"))
_, _ = g.AddEdge(g.GetVertexByID("build"), gograph.NewVertex("test"))
// highlight the vertices that failed
failed := map[string]bool{"test": true}
err := dot.Write(os.Stdout, g,
dot.WithName[string]("pipeline"),
dot.WithGraphAttributes[string](map[string]string{"rankdir": "LR"}),
dot.WithVertexAttributes(func(v *gograph.Vertex[string]) map[string]string {
if failed[v.Label()] {
return map[string]string{"color": "red", "style": "filled", "fillcolor": "#ffdddd"}
}
return map[string]string{"shape": "box"}
}),
)
if err != nil {
fmt.Println(err)
}
}
Output: digraph pipeline { rankdir="LR"; n0 [label="build", shape="box"]; n1 [label="checkout", shape="box"]; n2 [color="red", fillcolor="#ffdddd", label="test", style="filled"]; n0 -> n2; n1 -> n0; }