Packages

Build directed graphs, query them, and compile into common diagramming languages ([d2] for now).

Current section

Files

Jump to
graphic lib graphic.ex
Raw

lib/graphic.ex

defmodule Graphic do
@moduledoc """
Build directed graphs, query them,
and compile into common diagramming languages.
iex> alias Graphic, as: G
...> g = G.new()
...> g |> G.bridge("a", "b")
...> g |> G.edges()
[
{[:"$e" | 0], "a", "b", []}
]
"""
@moduledoc since: "0.1.1"
@dg :digraph
def new(), do: :digraph.new()
@doc "add a plain edge, and any missing nodes."
def bridge(g, a, b) do
if !(g|>@dg.vertex(a)), do: g|>@dg.add_vertex(a)
if !(g|>@dg.vertex(b)), do: g|>@dg.add_vertex(b)
g|>@dg.add_edge(a, b)
end
@doc "add a labeled edge, and any missing nodes."
def bridge(g, a, b, label) do
if !(g|>@dg.vertex(a)), do: g|>@dg.add_vertex(a)
if !(g|>@dg.vertex(b)), do: g|>@dg.add_vertex(b)
g|>@dg.add_edge(a, b, label)
end
@doc "query all edges in graph."
def edges(g), do: g|>@dg.edges()|>Enum.map(& g|>@dg.edge(&1))
# choose a logical order, used in rendering.
defp order(g), do: g|>:digraph_utils.topsort()
@doc "render graph as a d2 diagram."
def as_d2(g), do: g|>order()|>Enum.map(&
g|>neighbors(&1)|>Enum.map(fn n -> "#{&1} -> #{n}"
end) )|>List.flatten()|>Enum.join("\n")
@doc "describe neighboring nodes."
def neighbors(g, n), do: g|>@dg.out_neighbours(n)
end