# Graphvix
[![Build Status](https://travis-ci.org/mikowitz/graphvix.svg?branch=master)](https://travis-ci.org/mikowitz/graphvix)
Graphviz in Elixir
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed as:
1. Add `graphvix` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[{:graphvix, "~> 1.0.0"}]
end
```
# Usage
See [the wiki](https://github.com/mikowitz/graphvix/wiki/Examples) for examples.
## API Overview
* Create a new graph
`Graphvix.Graph.new/0`
* Add a vertex to a graph
`Graphvix.Graph.add_vertex/2`
`Graphvix.Graph.add_vertex/3`
* Add an edge between two vertices
`Graphvix.Graph.add_edge/3`
`Graphvix.Graph.add_edge/4`
* Create a vertex with type `record`
`Graphvix.Record.new/1`
`Graphvix.Record.new/2`
* Add a record vertex to a graph
`Graphvix.Graph.add_record/2`
* Create a vertex using HTML table markup
`Graphvix.HTMLRecord.new/1`
`Graphvix.HTMLRecord.new/2`
* Add an HTML table vertex to a graph
`Graphvix.Graph.add_html_record/2`
* Save a graph to disk in `.dot` format
`Graphvix.Graph.write/2`
* Save and compile a graph (defaults to `.png`)
`Graphvix.Graph.compile/2`
`Graphvix.Graph.compile/3`
* Save, compile and open a graph (defaults to `.png` and your OS's default image viewer)
`Graphvix.Graph.graph/2`
`Graphvix.Graph.graph/3`
## Basic Usage
1. Alias the necessary module for ease of use
```elixir
alias Graphvix.Graph
```
1. Create a new graph.
```elixir
graph = Graph.new()
```
1. Add a simple vertex with a label
```elixir
{graph, vertex_id} = Graph.add_vertex(graph, "vertex label")
```
1. Add a vertex with a label and attributes
```elixir
{graph, vertex2_id} = Graph.add_vertex(
graph,
"my other vertex",
color: "blue", shape: "diamond"
)
```
1. Add an edge between two existing vertices
```elixir
{graph, edge_id} = Graph.add_edge(
graph,
vertex_id, vertex2_id,
label: "Edge", color: "green"
)
```
1. Add a cluster containing one or more nodes
```elixir
{graph, cluster_id} = Graph.add_cluster(graph, [vertex_id, vertex2_id])
```
## Records
1. Alias the necessary module for ease of use
```elixir
alias Graphvix.Record
```
1. Create a simple record that contains only a row of cells
```elixir
record = Record.new(Record.row(["a", "b", "c"]))
```
* A record with a top-level row can also be created by just passing a list
```elixir
record = Record.new(["a", "b", "c"])
```
1. Create a record with a single column of cells
```elixir
record = Record.new(Record.column(["a", "b", "c"]))
```
1. Create a record with nested rows and columns
```elixir
import Graphvix.Record, only: [column: 1, row: 1]
record = Record.new(row([
"a",
column([
"b",
row(["c", "d", "e"]),
"f"
]),
"g"
])
```
### Ports
1. Ports can be attached to record cells by passing a tuple of `{port_name, label}`
```elixir
import Graphvix.Record, only: [column: 1, row: 1]
record = Record.new(row([
{"port_a", "a"},
column([
"b",
row(["c", {"port_d", "d"}, "e"]),
"f"
]),
"g"
])
```
1. Edges can be drawn from specific ports on a record
```elixir
{graph, record_id} = Graph.add_record(graph, record)
{graph, _edge_id} = Graph.add_edge({record_id, "port_a"}, vertex_id)
```
## HTML Table Records
1. Alias the necessary modules for ease of use
```elixir
alias Graphvix.HTMLRecord
```
1. Create a simple table
```elixir
record = HTMLRecord.new([
tr([
td("a"),
td("b"),
td("c")
]),
tr([
td("d", port: "port_d"),
td("e"),
td("f")
])
])
```
1. Or a more complex table
```elixir
record = HTMLRecord.new([
tr([
td("a", rowspan: 3),
td("b", colspan: 2),
td("f", rowspan: 3)
]),
tr([
td("c"),
td("d")
])
tr([
td("e", colspan: 2)
])
])
```
Cells can also use the `font/2` and `br/0` helper methods to add font styling and forced line breaks. See
the documentation for `Graphvix.HTMLRecord` for examples.
## Output
1. Convert the graph to DOT format
```elixir
Graph.to_dot(graph)
"""
digraph G {
cluster c0 {
v0 [label="vertex label"]
v1 [label="my other vertex",color="blue",shape="diamond"]
v0 -> v1 [label="Edge",color="green"]
}
}
"""
```
1. Save the graph to a .dot file, with an optional filename
```elixir
Graph.write(graph, "first_graph") #=> creates "first_graph.dot"
```
1. Compile the graph to a .png or .pdf using the `dot` command
```elixir
## creates first_graph.dot and first_graph.png
Graph.compile(graph, "first_graph")
## creates first_graph.dot and first_graph.pdf
Graph.compile(graph, "first_graph", :pdf)
```
1. Compile the graph using the `dot` command and open the resulting file
```elixir
## creates first_graph.dot and first_graph.pdf; opens first_graph.png
Graph.graph(graph, "first_graph")
## creates first_graph.dot and first_graph.pdf; opens first_graph.pdf
Graph.graph(graph, "first_graph", :pdf)
```