├── .gitignore ├── nimgraphviz.nimble ├── src ├── nimgraphviz │ ├── edges │ │ └── edges.nim │ └── graphs │ │ └── graphs.nim └── nimgraphviz.nim ├── README.md └── docs ├── edges.html ├── index.html └── graphs.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | *.exe 3 | nimcache/ 4 | -------------------------------------------------------------------------------- /nimgraphviz.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | version = "0.3.0" 4 | author = "Quinn Freedman, then Alexis Masson" 5 | description = "Nim bindings for the GraphViz tool and the DOT graph language" 6 | license = "MIT" 7 | srcDir = "src" 8 | 9 | # Dependencies 10 | 11 | requires "nim >= 0.18.0" 12 | -------------------------------------------------------------------------------- /src/nimgraphviz/edges/edges.nim: -------------------------------------------------------------------------------- 1 | import hashes 2 | 3 | type 4 | Edge* = object 5 | ## Represents a non-oriented edge 6 | ## `a -- b` in DOT syntax. 7 | a*, b*: string 8 | Arrow* = object 9 | ## Represents an oriented edge 10 | ## `a -> b` in DOT syntax. 11 | a*, b*: string 12 | 13 | func `==`*(edge1, edge2: Edge):bool = 14 | ## N.B.: `a--b` == `b--a` 15 | return 16 | (edge1.a == edge2.a and edge1.b == edge2.b) or 17 | (edge1.a == edge2.b and edge1.b == edge2.a) 18 | 19 | func `==`*(edge1, edge2:Arrow):bool = 20 | ## N.B.: `a->b` != `b->a` 21 | return 22 | (edge1.a == edge2.a and edge1.b == edge2.b) 23 | 24 | func hash*(edge:Edge): Hash = 25 | # use xor instead of !& to ensure Edge(a,b) == Edge(b, a) 26 | result = hash(edge.a) xor hash(edge.b) 27 | result = !$result 28 | 29 | func hash*(arrow:Arrow): Hash = 30 | result = hash(arrow.a) !& hash(arrow.b) 31 | result = !$result 32 | 33 | func `--`*(a, b:string):Edge = 34 | ## Convenience syntax for Edge(...) 35 | result = Edge(a:a, b:b) 36 | 37 | func `->`*(a,b:string):Arrow = 38 | ## Convenience syntax for Arrow(...) 39 | result = Arrow(a:a, b:b) 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nimgraphviz 2 | 3 | The `nimgraphviz` module is a library for making graphs using 4 | [GraphViz](http://www.graphviz.org) based on 5 | [PyGraphviz](http://pygraphviz.github.io). 6 | 7 | To use it, add 8 | ``` 9 | requires "nimgraphviz >= 0.3.0" 10 | ``` 11 | to your `.nimble` file. 12 | 13 | To export images, you must have GraphViz installed. Download it here: 14 | [https://graphviz.gitlab.io/download](https://graphviz.gitlab.io/download). 15 | 16 | Read the docs [here](https://quinnfreedman.github.io/nimgraphviz/). 17 | 18 | Here is an example of creating a simple graph: 19 | 20 | ```nim 21 | # create a directed graph 22 | let graph = newGraph[Arrow]() 23 | 24 | # You can add subgraphs to it: 25 | let sub = newGraph(graph) 26 | # You can nest subgraphs indefinitely : 27 | # let subsub = newGraph(sub) 28 | 29 | # The subgraph is automatically included in the main graph 30 | # when you export it. It can also work standalone. 31 | # Note that some layout engines behave differently when a subgraph 32 | # name begins with "cluster". Please refer to the official GraphViz 33 | # documentation for details. 34 | 35 | # set some attributes of the graph: 36 | graph["fontsize"] = "32" 37 | graph["label"] = "Test Graph" 38 | # (You can also access nodes and edges attributes this way :) 39 | # graph["a", "bgcolor"] = "red" 40 | # graph["a"->"b", "arrowhead"] = "diamond" 41 | 42 | # add edges: 43 | # (if a node does not exist already it will be created automatically) 44 | graph.addEdge("a"->"b", ("label", "A to B")) 45 | graph.addEdge("c"->"b", ("style", "dotted")) 46 | graph.addEdge("b"->"a") 47 | sub.addEdge("x"->"y") 48 | 49 | graph.addNode("c", ("color", "blue"), ("shape", "box"), 50 | ("style", "filled"), ("fontcolor", "white")) 51 | graph.addNode("d", ("label", "node 'd'")) 52 | 53 | # if you want to export the graph in the DOT language, 54 | # you can do it like this: 55 | # echo graph.exportDot() 56 | 57 | # Export graph as PNG: 58 | graph.exportImage("test_graph.png") 59 | ``` 60 | -------------------------------------------------------------------------------- /src/nimgraphviz.nim: -------------------------------------------------------------------------------- 1 | # nimgraphviz 2 | # Copyright Quinn, Aveheuzed 3 | # Nim bindings for the GraphViz tool and the DOT graph language 4 | 5 | ## The `nimgraphviz` module is a library for making graphs using 6 | ## `GraphViz `_ based on 7 | ## `PyGraphviz `_. 8 | ## 9 | ## To export images, you must have GraphViz installed. Download it here: 10 | ## `https://graphviz.gitlab.io/download `_ 11 | ## 12 | ## Here is an example of creating a simple graph: 13 | ## 14 | ## .. code-block:: nim 15 | ## # create a directed graph 16 | ## let graph = newGraph[Arrow]() 17 | ## 18 | ## # You can add subgraphs to it: 19 | ## let sub = newGraph(graph) 20 | ## # You can nest subgraphs indefinitely : 21 | ## # let subsub = newGraph(sub) 22 | ## 23 | ## # The subgraph is automatically included in the main graph 24 | ## # when you export it. It can also work standalone. 25 | ## # Note that some layout engines behave differently when a subgraph 26 | ## # name begins with "cluster". Please refer to the official GraphViz 27 | ## # documentation for details. 28 | ## 29 | ## 30 | ## # set some attributes of the graph: 31 | ## graph["fontsize"] = "32" 32 | ## graph["label"] = "Test Graph" 33 | ## # (You can also access nodes and edges attributes this way :) 34 | ## # graph["a", "bgcolor"] = "red" 35 | ## # graph["a"->"b", "arrowhead"] = "diamond" 36 | ## 37 | ## # add edges: 38 | ## # (if a node does not exist already it will be created automatically) 39 | ## graph.addEdge("a"->"b", ("label", "A to B")) 40 | ## graph.addEdge("c"->"b", ("style", "dotted")) 41 | ## graph.addEdge("b"->"a") 42 | ## sub.addEdge("x"->"y") 43 | ## 44 | ## graph.addNode("c", ("color", "blue"), ("shape", "box"), 45 | ## ("style", "filled"), ("fontcolor", "white")) 46 | ## graph.addNode("d", ("label", "node 'd'")) 47 | ## 48 | ## # if you want to export the graph in the DOT language, 49 | ## # you can do it like this: 50 | ## # echo graph.exportDot() 51 | ## 52 | ## # Export graph as PNG: 53 | ## graph.exportImage("test_graph.png") 54 | 55 | import "nimgraphviz/edges/edges.nim", "nimgraphviz/graphs/graphs.nim" 56 | export edges, graphs 57 | 58 | when isMainModule : 59 | # create a directed graph 60 | let graph = newGraph[Arrow]() 61 | 62 | # You can add subgraphs to it: 63 | let sub = newGraph(graph) 64 | # You can nest subgraphs indefinitely : 65 | # let subsub = newGraph(sub) 66 | 67 | # The subgraph is automatically included in the main graph 68 | # when you export it. It can also work standalone. 69 | # Note that some layout engines behave differently when a subgraph 70 | # name begins with "cluster". Please refer to the official GraphViz 71 | # documentation for details. 72 | 73 | # set some attributes of the graph: 74 | graph["fontsize"] = "32" 75 | graph["label"] = "Test Graph" 76 | # (You can also access nodes and edges attributes this way :) 77 | # graph["a", "bgcolor"] = "red" 78 | # graph["a"->"b", "arrowhead"] = "diamond" 79 | 80 | # add edges: 81 | # (if a node does not exist already it will be created automatically) 82 | graph.addEdge("a"->"b", ("label", "A to B")) 83 | graph.addEdge("c"->"b", ("style", "dotted")) 84 | graph.addEdge("b"->"a") 85 | sub.addEdge("x"->"y") 86 | 87 | graph.addNode("c", ("color", "blue"), ("shape", "box"), 88 | ("style", "filled"), ("fontcolor", "white")) 89 | graph.addNode("d", ("label", "node 'd'")) 90 | 91 | # if you want to export the graph in the DOT language, 92 | # you can do it like this: 93 | # echo graph.exportDot() 94 | 95 | # Export graph as PNG: 96 | graph.exportImage("test_graph.png") 97 | -------------------------------------------------------------------------------- /src/nimgraphviz/graphs/graphs.nim: -------------------------------------------------------------------------------- 1 | import os 2 | import osproc 3 | import streams 4 | import strformat 5 | import strutils 6 | 7 | import "../edges/edges.nim" 8 | 9 | import tables 10 | export tables 11 | 12 | 13 | type 14 | Graph*[E: Edge or Arrow] = ref object 15 | ## Represents a GraphViz graph or digraph. 16 | ## Graph[Edge] makes a `strict graph` 17 | ## Graph[Arrow] makes a `strict digraph` 18 | ## Notation: for convenience, `Graph` refers to the (generic) nim object 19 | ## whereas `graph` refers to the GraphViz structure, represented by `Graph[Edge]` 20 | 21 | name*: string 22 | ## name of the graph, most often irrelevant but in subgraphs 23 | ## subgraphs whose name begins with "cluster" may be given special treatment 24 | ## by some of graphviz' layout engines. 25 | 26 | graphAttr*: Table[string, string] 27 | ## global graph attributes 28 | 29 | nodeAttrs*: Table[string, Table[string, string]] 30 | ## node attributes; only nodes that are not referenced by edges of the graph 31 | ## need to referenced here in order to appear in the graph 32 | 33 | edges*: Table[E, Table[string, string]] 34 | ## edges with their attributes 35 | 36 | subGraphs: seq[Graph[E]] 37 | ## (private) list of subgraphs. 38 | ## A digraph may only have digraphs as children; 39 | ## a graph may only have graphs as children. 40 | ## This attribute is kept private to warrant against graphs that include each other. 41 | ## You may access the other attributes however you like; 42 | ## sanity checks are run during the dot script generation phase. 43 | 44 | 45 | func newGraph*[E](): Graph[E] = 46 | ## doesn't do anything, the default initialisation procedure is enough. 47 | ## actual body: 48 | ## `result = Graph[E]()` 49 | result = Graph[E]() 50 | 51 | func newGraph*[E](parent: Graph[E]): Graph[E] = 52 | ## Returns a new graph, attached to its parent as subgraph. 53 | ## Some graphviz engines have a specific behaviour when the name of the 54 | ## subgraph begins with "cluster" -- see the official website. 55 | ## Note that the subgraphs are full graphs themselves: you can treat them 56 | ## as standalone objects (e.g. when exporting images) 57 | # result = newGraph[E]() 58 | result = Graph[E]() 59 | parent.subGraphs.add(result) 60 | 61 | 62 | func addEdge*[E](self: Graph[E], edge: E, attr: varargs[(string, string)]) = 63 | ## Add an edge to the graph. Optional attributes may be specified as a serie 64 | ## of (key, value) tuples. 65 | if not self.edges.hasKey(edge) : 66 | self.edges[edge] = initTable[string, string]() 67 | 68 | for (k,v) in attr: 69 | self.edges[edge][k] = v 70 | 71 | func addNode*(self: Graph, node: string, attr: varargs[(string, string)]) = 72 | ## Add a node to the graph. Optional attributes may be specified as a serie 73 | ## of (key, value) tuples. 74 | ## Note that you don't need to add a node manually if it appears in an edge. 75 | if not self.nodeAttrs.hasKey(node) : 76 | self.nodeAttrs[node] = initTable[string, string]() 77 | 78 | for (k,v) in attr: 79 | self.nodeAttrs[node][k] = v 80 | 81 | # get/set graph attr ----------------------------------------------------------- 82 | func `[]`*(self: Graph, gAttr: string): string = 83 | ## Shortcut to access graph attributes 84 | self.graphAttr[gAttr] 85 | 86 | func `[]=`*(self: Graph, gAttr: string, value: string) = 87 | ## Shortcut to set graph attributes 88 | self.graphAttr[gAttr] = value 89 | 90 | # get/set node attr ------------------------------------------------------------ 91 | func `[]`*(self: Graph, node: string, key: string): string = 92 | ## Shortcut to access node attributes 93 | ## Returns the attribute value for the given node, given key. 94 | ## Throws the relevant exception from Table when the node does not exist. 95 | self.nodeAttrs[node][key] 96 | 97 | func `[]=`*(self: Graph, node: string, key: string, value: string) = 98 | ## Shortcut to edit node attributes. 99 | ## If the node hasn't got a table yet, it gets one beforehand. 100 | self.addNode(node) 101 | self.nodeAttrs[node][key] = value 102 | 103 | # get/set edge attr ------------------------------------------------------------ 104 | func `[]`*[E](self: Graph[E], edge: E, key: string): string = 105 | ## Shortcut to access edge attributes 106 | ## Returns the attribute value for the given edge, given key. 107 | ## Throws the relevant exception from Table when the edge does not exist. 108 | self.edges[edge][key] 109 | 110 | func `[]=`*[E](self: Graph[E], edge: E, key: string, value: string) = 111 | ## Shortcut to edit edge attributes. 112 | ## If the edge doesn't exist in the graph yet, it is created beforehand. 113 | self.addEdge(edge) 114 | self.edges[edge][key] = value 115 | 116 | 117 | 118 | iterator iterEdges*[E](self: Graph[E], node: string): E = 119 | ## Iterate over all the edges adjacent to a given node 120 | for edge in self.edges.keys() : 121 | if edge.a == node or edge.b == node: 122 | yield edge 123 | 124 | iterator iterEdgesIn*(self: Graph[Arrow], node: string): Arrow = 125 | ## Oriented version: yields only inbound edges 126 | for edge in self.edges.keys() : 127 | if edge.b == node: 128 | yield edge 129 | iterator iterEdgesOut*(self: Graph[Arrow], node: string): Arrow = 130 | ## Oriented version: yields only outbound edges 131 | for edge in self.edges.keys() : 132 | if edge.a == node: 133 | yield edge 134 | 135 | 136 | func exportIdentifier(identifier:string): string = 137 | if identifier.validIdentifier() : 138 | return identifier 139 | 140 | # if needs be, escape '"' and surround in quotes (do not replace '\' !!) 141 | return "\"" & identifier.replace("\"", "\\\"") & "\"" 142 | 143 | func `$`(edge: Edge): string = 144 | exportIdentifier(edge.a) & " -- " & exportIdentifier(edge.b) 145 | func `$`(edge: Arrow): string = 146 | exportIdentifier(edge.a) & " -> " & exportIdentifier(edge.b) 147 | 148 | func exportSubDot(self: Graph): string # forward declaration 149 | 150 | func tableToAttributes(tbl: Table[string, string]): seq[string] = 151 | for (key, value) in tbl.pairs() : 152 | result.add exportIdentifier(key) & "=" & exportIdentifier(value) 153 | 154 | func exportAttributes(self: Graph): string = 155 | result = tableToAttributes(self.graphAttr).join(";\n") 156 | if len(result) > 0 : 157 | result &= "\n" 158 | 159 | func exportNodes(self: Graph): string = 160 | for (node, tbl) in self.nodeAttrs.pairs() : 161 | result &= exportIdentifier(node) 162 | if tbl.len > 0: 163 | result &= " [" 164 | result &= tableToAttributes(tbl).join(", ") 165 | result &= "]" 166 | result &= ";\n" 167 | 168 | func exportEdges(self: Graph): string = 169 | for (edge, tbl) in self.edges.pairs() : 170 | result &= $edge 171 | if tbl.len > 0: 172 | result &= " [" 173 | result &= tableToAttributes(tbl).join(", ") 174 | result &= "]" 175 | result &= ";\n" 176 | 177 | func buildBody(self: Graph): string = 178 | result = "{\n" 179 | for sub in self.subGraphs : 180 | result &= exportSubDot(sub) 181 | result &= self.exportAttributes() 182 | result &= self.exportNodes() 183 | result &= self.exportEdges() 184 | result &= "}\n" 185 | 186 | func exportSubDot(self: Graph): string = 187 | result = "subgraph " & exportIdentifier(self.name) & " " & self.buildBody() 188 | 189 | func exportDot*(self: Graph[Edge]): string = 190 | ## Returns the dot script corresponding to the graph, including subgraphs. 191 | result = "strict graph " & exportIdentifier(self.name) & " " & self.buildBody() 192 | 193 | func exportDot*(self: Graph[Arrow]): string = 194 | ## Returns the dot script corresponding to the graph, including subgraphs. 195 | result = "strict digraph " & exportIdentifier(self.name) & " " & self.buildBody() 196 | 197 | proc exportImage*(self: Graph, fileName: string, layout="dot", format="", exec="dot") = 198 | ## Exports the graph as an image file. 199 | ## 200 | ## ``filename`` - the name of the file to export to. Should include ".png" 201 | ## or the appropriate file extension. 202 | ## 203 | ## ``layout`` - which of the GraphViz layout engines to use. Default is 204 | ## ``dot``. Can be one of: ``dot``, ``neato``, ``fdp``, ``sfdp``, ``twopi``, 205 | ## ``circo`` (or others if you have them installed). 206 | ## 207 | ## ``format`` - the output format to export to. The default is ``svg``. 208 | ## If not specified, it is deduced from the file name. 209 | ## You can specify more details with 210 | ## ``"{format}:{rendering engine}:{library}"``. 211 | ## (See `GV command-line docs `_ 212 | ## for more details) 213 | ## 214 | ## ``exec`` - path to the ``dot`` command; use this when ``dot`` is not in 215 | ## your PATH 216 | 217 | # This blocks determines the output file name and its content type 218 | # fileName has precedence over self.name 219 | # The content type is deduced from the file name unless explicitely specified. 220 | 221 | var (dir, name, ext) = splitFile(fileName) 222 | if len(dir) == 0 : 223 | dir = "." # current dir 224 | 225 | if ext == "." or ext == "": 226 | ext = ".svg" # default format : SVG 227 | 228 | let actual_format = 229 | if format != "" : 230 | format 231 | else : 232 | ext[1..^1] # remove the '.' in first position 233 | let file = &"{dir}/{name}{ext}" 234 | 235 | let text = self.exportDot() 236 | let args = [ 237 | &"-K{layout}", 238 | &"-o{file}", 239 | &"-T{actual_format}", 240 | "-q" 241 | ] 242 | let process = 243 | try : 244 | startProcess(exec, args=args, options={poUsePath}) 245 | except OSError : 246 | # "command not found", but I think the default message is explicit enough 247 | # the try/except block is just there to show where the error can arise 248 | raise 249 | let stdin = process.inputStream 250 | let stderr = process.errorStream 251 | stdin.write(text) 252 | stdin.close() 253 | let errcode = process.waitForExit() 254 | let errormsg = stderr.readAll() 255 | process.close() 256 | if errcode != 0: 257 | raise newException(OSError, fmt"[errcode {errcode}] " & errormsg) 258 | -------------------------------------------------------------------------------- /docs/edges.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | edges 21 | 787 | 788 | 789 | 790 | 803 | 804 | 805 | 806 |
807 |
808 |

edges

809 |
810 |
811 | 815 |
816 | Search: 818 |
819 |
820 | Group by: 821 | 825 |
826 | 859 | 860 |
861 |
862 |
863 | 864 |

865 |
866 |

Types

867 |
868 | 869 |
Edge = object
870 |   a*, b*: string
871 | 
872 |
873 | 874 | Represents a non-oriented edge a -- b in DOT syntax. 875 | 876 |
877 | 878 |
Arrow = object
879 |   a*, b*: string
880 | 
881 |
882 | 883 | Represents an oriented edge a -> b in DOT syntax. 884 | 885 |
886 | 887 |
888 |
889 |

Funcs

890 |
891 | 892 |
func `==`(edge1, edge2: Edge): bool {...}{.raises: [], tags: [].}
893 |
894 | 895 | N.B.: a--b == b--a 896 | 897 |
898 | 899 |
func `==`(edge1, edge2: Arrow): bool {...}{.raises: [], tags: [].}
900 |
901 | 902 | N.B.: a->b != b->a 903 | 904 |
905 | 906 |
func hash(edge: Edge): Hash {...}{.raises: [], tags: [].}
907 |
908 | 909 | 910 | 911 |
912 | 913 |
func hash(arrow: Arrow): Hash {...}{.raises: [], tags: [].}
914 |
915 | 916 | 917 | 918 |
919 | 920 |
func `--`(a, b: string): Edge {...}{.raises: [], tags: [].}
921 |
922 | 923 | Convenience syntax for Edge(...) 924 | 925 |
926 | 927 |
func `->`(a, b: string): Arrow {...}{.raises: [], tags: [].}
928 |
929 | 930 | Convenience syntax for Arrow(...) 931 | 932 |
933 | 934 |
935 | 936 |
937 |
938 | 939 |
940 | 945 |
946 |
947 |
948 | 949 | 950 | 951 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | nimgraphviz 21 | 787 | 788 | 789 | 790 | 803 | 804 | 805 | 806 |
807 |
808 |

nimgraphviz

809 |
810 |
811 | 815 |
816 | Search: 818 |
819 |
820 | Group by: 821 | 825 |
826 |
    827 |
  • 828 | Imports 829 |
      830 | 831 |
    832 |
  • 833 |
  • 834 | Exports 835 |
      836 | 837 |
    838 |
  • 839 | 840 |
841 | 842 |
843 |
844 |
845 | 846 |

The nimgraphviz module is a library for making graphs using GraphViz based on PyGraphviz.

847 |

To export images, you must have GraphViz installed. Download it here: https://graphviz.gitlab.io/download

848 |

Here is an example of creating a simple graph:

849 |
# create a directed graph
850 | let graph = newGraph[Arrow]()
851 | 
852 | # You can add subgraphs to it:
853 | let sub = newGraph(graph)
854 | # You can nest subgraphs indefinitely :
855 | # let subsub = newGraph(sub)
856 | 
857 | # The subgraph is automatically included in the main graph
858 | # when you export it. It can also work standalone.
859 | # Note that some layout engines behave differently when a subgraph
860 | # name begins with "cluster". Please refer to the official GraphViz
861 | # documentation for details.
862 | 
863 | 
864 | # set some attributes of the graph:
865 | graph["fontsize"] = "32"
866 | graph["label"] = "Test Graph"
867 | # (You can also access nodes and edges attributes this way :)
868 | # graph["a", "bgcolor"] = "red"
869 | # graph["a"->"b", "arrowhead"] = "diamond"
870 | 
871 | # add edges:
872 | # (if a node does not exist already it will be created automatically)
873 | graph.addEdge("a"->"b", ("label", "A to B"))
874 | graph.addEdge("c"->"b", ("style", "dotted"))
875 | graph.addEdge("b"->"a")
876 | sub.addEdge("x"->"y")
877 | 
878 | graph.addNode("c", ("color", "blue"), ("shape", "box"),
879 |                     ("style", "filled"), ("fontcolor", "white"))
880 | graph.addNode("d", ("label", "node 'd'"))
881 | 
882 | # if you want to export the graph in the DOT language,
883 | # you can do it like this:
884 | # echo graph.exportDot()
885 | 
886 | # Export graph as PNG:
887 | graph.exportImage("test_graph.png")

888 |
889 |

Imports

890 |
891 | edges, graphs 892 |
893 | 898 | 899 |
900 |
901 | 902 |
903 | 908 |
909 |
910 |
911 | 912 | 913 | 914 | -------------------------------------------------------------------------------- /docs/graphs.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | graphs 21 | 787 | 788 | 789 | 790 | 803 | 804 | 805 | 806 |
807 |
808 |

graphs

809 |
810 |
811 | 815 |
816 | Search: 818 |
819 |
820 | Group by: 821 | 825 |
826 | 906 | 907 |
908 |
909 |
910 | 911 |

912 |
913 |

Imports

914 |
915 | edges 916 |
917 |
918 |

Types

919 |
920 | 921 |
Graph[E] = ref object
 922 |   name*: string ## name of the graph, most often irrelevant but in subgraphs
 923 |               ## subgraphs whose name begins with "cluster" may be given special treatment
 924 |               ## by some of graphviz' layout engines.
 925 |   graphAttr*: Table[string, string] ## global graph attributes
 926 |   nodeAttrs*: Table[string, Table[string, string]] ## node attributes; only nodes that are not referenced by edges of the graph
 927 |                                                ## need to referenced here in order to appear in the graph
 928 |   edges*: Table[E, Table[string, string]] ## edges with their attributes
 929 |   subGraphs: seq[Graph[E]] ## (private) list of subgraphs.
 930 |                          ## A digraph may only have digraphs as children;
 931 |                          ## a graph may only have graphs as children.
 932 |                          ## This attribute is kept private to warrant against graphs that include each other.
 933 |                          ## You may access the other attributes however you like;
 934 |                          ## sanity checks are run during the dot script generation phase.
 935 |   
936 |
937 | 938 | Represents a GraphViz graph or digraph. Graph[Edge] makes a strict graph Graph[Arrow] makes a strict digraph Notation: for convenience, Graph refers to the (generic) nim object whereas graph refers to the GraphViz structure, represented by Graph[Edge] 939 | 940 |
941 | 942 |
943 |
944 |

Procs

945 |
946 | 947 |
proc exportImage(self: Graph; fileName: string; layout = "dot"; format = ""; exec = "dot")
948 |
949 | 950 |

Exports the graph as an image file.

951 |

filename - the name of the file to export to. Should include ".png" or the appropriate file extension.

952 |

layout - which of the GraphViz layout engines to use. Default is dot. Can be one of: dot, neato, fdp, sfdp, twopi, circo (or others if you have them installed).

953 |

format - the output format to export to. The default is svg. If not specified, it is deduced from the file name. You can specify more details with "{format}:{rendering engine}:{library}". (See GV command-line docs for more details)

954 |

exec - path to the dot command; use this when dot is not in your PATH

955 | 956 | 957 |
958 | 959 |
960 |
961 |

Funcs

962 |
963 | 964 |
func newGraph[E](): Graph[E]
965 |
966 | 967 | doesn't do anything, the default initialisation procedure is enough. actual body: result = Graph[E]() 968 | 969 |
970 | 971 |
func newGraph[E](parent: Graph[E]): Graph[E]
972 |
973 | 974 | Returns a new graph, attached to its parent as subgraph. Some graphviz engines have a specific behaviour when the name of the subgraph begins with "cluster" -- see the official website. Note that the subgraphs are full graphs themselves: you can treat them as standalone objects (e.g. when exporting images) 975 | 976 |
977 | 978 |
func addEdge[E](self: Graph[E]; edge: E; attr: varargs[(string, string)])
979 |
980 | 981 | Add an edge to the graph. Optional attributes may be specified as a serie of (key, value) tuples. 982 | 983 |
984 | 985 |
func addNode(self: Graph; node: string; attr: varargs[(string, string)])
986 |
987 | 988 | Add a node to the graph. Optional attributes may be specified as a serie of (key, value) tuples. Note that you don't need to add a node manually if it appears in an edge. 989 | 990 |
991 | 992 |
func `[]`(self: Graph; gAttr: string): string
993 |
994 | 995 | Shortcut to access graph attributes 996 | 997 |
998 | 999 |
func `[]=`(self: Graph; gAttr: string; value: string)
1000 |
1001 | 1002 | Shortcut to set graph attributes 1003 | 1004 |
1005 | 1006 |
func `[]`(self: Graph; node: string; key: string): string
1007 |
1008 | 1009 | Shortcut to access node attributes Returns the attribute value for the given node, given key. Throws the relevant exception from Table when the node does not exist. 1010 | 1011 |
1012 | 1013 |
func `[]=`(self: Graph; node: string; key: string; value: string)
1014 |
1015 | 1016 | Shortcut to edit node attributes. If the node hasn't got a table yet, it gets one beforehand. 1017 | 1018 |
1019 | 1020 |
func `[]`[E](self: Graph[E]; edge: E; key: string): string
1021 |
1022 | 1023 | Shortcut to access edge attributes Returns the attribute value for the given edge, given key. Throws the relevant exception from Table when the edge does not exist. 1024 | 1025 |
1026 | 1027 |
func `[]=`[E](self: Graph[E]; edge: E; key: string; value: string)
1028 |
1029 | 1030 | Shortcut to edit edge attributes. If the edge doesn't exist in the graph yet, it is created beforehand. 1031 | 1032 |
1033 | 1034 |
func exportDot(self: Graph[Edge]): string {...}{.raises: [], tags: [].}
1035 |
1036 | 1037 | Returns the dot script corresponding to the graph, including subgraphs. 1038 | 1039 |
1040 | 1041 |
func exportDot(self: Graph[Arrow]): string {...}{.raises: [], tags: [].}
1042 |
1043 | 1044 | Returns the dot script corresponding to the graph, including subgraphs. 1045 | 1046 |
1047 | 1048 |
1049 |
1050 |

Iterators

1051 |
1052 | 1053 |
iterator iterEdges[E](self: Graph[E]; node: string): E
1054 |
1055 | 1056 | Iterate over all the edges adjacent to a given node 1057 | 1058 |
1059 | 1060 |
iterator iterEdgesIn(self: Graph[Arrow]; node: string): Arrow {...}{.raises: [], tags: [].}
1061 |
1062 | 1063 | Oriented version: yields only inbound edges 1064 | 1065 |
1066 | 1067 |
iterator iterEdgesOut(self: Graph[Arrow]; node: string): Arrow {...}{.raises: [], tags: [].}
1068 |
1069 | 1070 | Oriented version: yields only outbound edges 1071 | 1072 |
1073 | 1074 |
1075 | 1076 |
1077 |
1078 | 1079 |
1080 | 1085 |
1086 |
1087 |
1088 | 1089 | 1090 | 1091 | --------------------------------------------------------------------------------