diff --git a/gap/dot.gd b/gap/dot.gd index 4b611d1..dc5a486 100644 --- a/gap/dot.gd +++ b/gap/dot.gd @@ -358,11 +358,11 @@ DeclareOperation("GraphvizFindSubgraphRecursive", #! If a head and tail are provided it will only return edges #! between those two nodes. #! @BeginExampleSession -#! gap> gv:=GraphvizGraph();; -#! gap> GraphvizAddEdge(gv,"a","b");; +#! gap> gv := GraphvizGraph();; +#! gap> GraphvizAddEdge(gv, "a", "b");; #! gap> GraphvizEdges(gv); #! [ ] -#! gap> GraphvizEdges(gv,"a","b"); +#! gap> GraphvizEdges(gv, "a", "b"); #! [ ] #! @EndExampleSession DeclareOperation("GraphvizEdges", [IsGraphvizGraphDigraphOrContext]); @@ -375,8 +375,8 @@ DeclareOperation("GraphvizEdges", #! @Returns a &GAPGraphviz; node object #! @Description Returns the head of the provided &GAPGraphviz; edge. #! @BeginExampleSession -#! gap> gv:=GraphvizGraph();; -#! gap> e:=GraphvizAddEdge(gv,"a","b"); +#! gap> gv := GraphvizGraph();; +#! gap> e := GraphvizAddEdge(gv, "a", "b"); #! #! gap> GraphvizHead(e); #! @@ -387,8 +387,8 @@ DeclareOperation("GraphvizHead", [IsGraphvizEdge]); #! @Returns a &GAPGraphviz; node object #! @Description Returns the tail of the provided &GAPGraphviz; edge. #! @BeginExampleSession -#! gap> gv:=GraphvizGraph();; -#! gap> e:=GraphvizAddEdge(gv,"a","b"); +#! gap> gv := GraphvizGraph();; +#! gap> e := GraphvizAddEdge(gv, "a", "b"); #! #! gap> GraphvizTail(e); #! @@ -404,9 +404,9 @@ DeclareOperation("GraphvizTail", [IsGraphvizEdge]); #! name and return the graph with the new name. #! #! @BeginExampleSession -#! gap> gv:=GraphvizGraph(); +#! gap> gv := GraphvizGraph(); #! -#! gap> GraphvizSetName(gv,"newname"); +#! gap> GraphvizSetName(gv, "newname"); #! #! @EndExampleSession DeclareOperation("GraphvizSetName", @@ -419,9 +419,9 @@ DeclareOperation("GraphvizSetName", #! What constitute a valid node name is found at #! https://graphviz.org/doc/info/lang.html #! @BeginExampleSession -#! gap> gv:=GraphvizGraph(); +#! gap> gv := GraphvizGraph(); #! -#! gap> GraphvizAddNode(gv,"a"); +#! gap> GraphvizAddNode(gv, "a"); #! #! gap> gv; #! @@ -442,9 +442,9 @@ DeclareOperation("GraphvizAddNode", #! added to the graph. If different nodes with the same name are in the graph #! then the operation fails. #! @BeginExampleSession -#! gap> gv:=GraphvizGraph(); +#! gap> gv := GraphvizGraph(); #! -#! gap> GraphvizAddEdge(gv,"a","b"); +#! gap> GraphvizAddEdge(gv, "a", "b"); #! #! gap> gv; #! @@ -504,11 +504,11 @@ DeclareOperation("GraphvizAddComment", #! All edges containing the node are also removed. #! If no such node exists the operation fails. #! @BeginExampleSession -#! gap> gv:=GraphvizGraph();; -#! gap> GraphvizAddNode(gv,"a");; +#! gap> gv := GraphvizGraph();; +#! gap> GraphvizAddNode(gv, "a");; #! gap> gv; #! -#! gap> GraphvizRemoveNode(gv,"a"); +#! gap> GraphvizRemoveNode(gv, "a"); #! #! @EndExampleSession DeclareOperation("GraphvizRemoveNode", @@ -528,11 +528,11 @@ DeclareOperation("GraphvizFilterEdges", #! the specified names. #! If no edges exist between the two nodes, the operation fails. #! @BeginExampleSession -#! gap> gv:=GraphvizGraph();; -#! gap> GraphvizAddEdge(gv,"a","b");; +#! gap> gv := GraphvizGraph();; +#! gap> GraphvizAddEdge(gv, "a", "b");; #! gap> gv; #! -#! gap> GraphvizRemoveEdges(gv,"a","b"); +#! gap> GraphvizRemoveEdges(gv, "a", "b"); #! #! @EndExampleSession DeclareOperation("GraphvizRemoveEdges", @@ -541,23 +541,29 @@ DeclareOperation("GraphvizRemoveEdges", #! @Subsection Modifying object attributes #! Operations for modifying attributes. -#! @BeginGroup -#! @GroupTitle Setting Attributes -#! @Arguments obj, attrs -#! @Returns a &GAPGraphviz; object +#! @Arguments gv, attrs +#! @Returns the &GAPGraphviz; object gv. #! @Description -#! Updates the attributes of the object. -#! All current attributes remain. -#! If an attribute already exists and a new value is provided, the old value -#! will be overwritten. +#! This operation sets the attributes of the &GAPGraphviz; object gv to +#! be the record attrs. No checks are performed that the components of +#! the record attrs correspond to valid &DOT; attribute names. +#! The existing attributes of gv (if any) are not retained. #! @BeginExampleSession #! @EndExampleSession DeclareOperation("GraphvizSetAttrs", [IsGraphvizObject, IsRecord]); -#! @Arguments obj, name, value + +#! @Arguments gv, key, val +#! @Returns the &GAPGraphviz; object gv. +#! @Description +#! This operation sets the attribute key of the &GAPGraphviz; object +#! gv to have the value val. If either key or val +#! is not a string, then they are converted to strings using +#! . +#! No checks are performed that key is a valid attribute nor that +#! val is a valid value for the attribute key. +#! @BeginExampleSession +#! @EndExampleSession DeclareOperation("GraphvizSetAttr", [IsGraphvizObject, IsObject, IsObject]); -#! @Arguments obj, name -DeclareOperation("GraphvizSetAttr", [IsGraphvizObject, IsObject]); -#! @EndGroup #! @Arguments gv, obj #! @Returns the value of an attribute or fail. @@ -579,6 +585,9 @@ DeclareOperation("GraphvizGetAttr", [IsGraphvizObject, IsObject]); #! @EndExampleSession DeclareOperation("GraphvizRemoveAttr", [IsGraphvizObject, IsObject]); +# TODO add GraphvizRemoveNodeAttrs, GraphvizRemoveEdgeAttrs, +# GraphvizeRemoveAttrs, GraphvizeRemoveGraphAttrs + #! @Section Outputting #! @Arguments graph #! @Returns a string @@ -631,6 +640,39 @@ DeclareOperation("GraphvizSetNodeLabels", #! @EndExampleSession DeclareGlobalFunction("ErrorIfNotValidColor"); +######################################################################## +# Convenience functions TODO implement +######################################################################## + +# DeclareOperation("GraphvizSetNodeAttr", +# [IsGraphvizGraphDigraphOrContext, IsObject, IsObject]); +# DeclareOperation("GraphvizSetNodeAttrs", +# [IsGraphvizGraphDigraphOrContext, IsRecord]); +# +# DeclareOperation("GraphvizNodeAttrs", [IsGraphvizGraphDigraphOrContext]); +# +# DeclareOperation("GraphvizSetEdgeAttr", +# [IsGraphvizGraphDigraphOrContext, IsObject, IsObject]); +# DeclareOperation("GraphvizSetEdgeAttrs", +# [IsGraphvizGraphDigraphOrContext, IsRecord]); +# +# DeclareOperation("GraphvizEdgeAttrs", [IsGraphvizGraphDigraphOrContext]); +# +# # NOTE: there is no GraphvizGraphAttrs for a context because graph +# # attributes are global +# DeclareOperation("GraphvizGraphAttrs", [IsGraphvizGraph, IsRecord]); +# DeclareOperation("GraphvizGraphAttrs", [IsGraphvizDigraph, IsRecord]); +# +# DeclareOperation("GraphvizSetGraphAttr", +# [IsGraphvizGraph, IsObject, IsObject]); +# DeclareOperation("GraphvizSetGraphAttr", +# [IsGraphvizDigraph, IsObject, IsObject]); +# DeclareOperation("GraphvizSetGraphAttrs", [IsGraphvizGraph, IsRecord]); +# DeclareOperation("GraphvizSetGraphAttrs", [IsGraphvizDigraph, IsRecord]); +# +# DeclareOperation("GraphvizGraphAttrs", [IsGraphvizGraph]); +# DeclareOperation("GraphvizGraphAttrs", [IsGraphvizDigraph]); + #! @Section Debugging #! @Description #! The info class of this package; its info level is 0 by default. diff --git a/gap/dot.gi b/gap/dot.gi index 0997734..790c327 100644 --- a/gap/dot.gi +++ b/gap/dot.gi @@ -21,7 +21,9 @@ function(name) Contexts := rec(), Nodes := rec(), Edges := [], - Attrs := [], + Attrs := rec(graph := rec(), + edge := rec(), + node := rec()), Parent := fail, Idx := 1, Counter := 1)); @@ -41,7 +43,9 @@ function(name) Contexts := rec(), Nodes := rec(), Edges := [], - Attrs := [], + Attrs := rec(graph := rec(), + edge := rec(), + node := rec()), Parent := fail, Idx := 1, Counter := 1)); @@ -207,6 +211,45 @@ InstallMethod(GraphvizSetName, "for a graphviz (di)graph or context and string", # GraphvizSetAttr(s) ############################################################################# +InstallMethod(GraphvizSetAttr, +"for a graphviz object, object, and object", +[IsGraphvizObject, IsObject, IsObject], +function(gv, key, val) + local record; + + key := String(key); + val := String(val); + + if IsGraphvizGraphDigraphOrContext(gv) then + # By default setting an attribute of a graph, digraph, or context sets a + # graph attribute + record := GraphvizAttrs(gv).graph; + else + record := GraphvizAttrs(gv); + fi; + record.(key) := val; + return gv; +end); + +InstallMethod(GraphvizSetAttr, +"for a graphviz object, string, and record", +[IsGraphvizGraphDigraphOrContext, IsString, IsRecord], +function(gv, key, val) + local possible, name; + + possible := ["graph", "node", "edge"]; + if not key in possible then + ErrorFormatted("invalid argument = {}, when the ", + "argument is a record, must be ", + "one of {}", key, possible); + fi; + for name in RecNames(val) do + val.(name) := String(val.(name)); + od; + GraphvizAttrs(gv).(key) := val; + return gv; +end); + InstallMethod(GraphvizSetAttrs, "for a graphviz object and record", [IsGraphvizObject, IsRecord], function(x, attrs) @@ -217,78 +260,50 @@ function(x, attrs) return x; end); -InstallMethod(GraphvizSetAttr, -"for a graphviz node or edge, object, and object", -[IsGraphvizNodeOrEdge, IsObject, IsObject], -function(x, key, value) - GraphvizAttrs(x).(String(key)) := String(value); - return x; -end); - -InstallMethod(GraphvizSetAttr, -"for a graphviz object with subobjects, object, and object", -[IsGraphvizGraphDigraphOrContext, IsObject, IsObject], -function(x, name, value) - local attrs, string; - - name := String(name); - GV_RemoveGraphAttrIfExists(x, name); - attrs := GraphvizAttrs(x); - value := String(value); - if ' ' in value then - # Replace with call to GV_QuoteName or whatever TODO - value := StringFormatted("\"{}\"", value); +InstallMethod(GraphvizGetAttr, "for a graphviz object and object", +[IsGraphvizObject, IsObject], +function(gv, key) + local record; + if IsGraphvizGraphDigraphOrContext(gv) then + # By default setting an attribute of a graph, digraph, or context sets a + # graph attribute + record := GraphvizAttrs(gv).graph; + else + record := GraphvizAttrs(gv); fi; - string := StringFormatted("{}={}", name, value); - Add(attrs, string); - return x; -end); - -InstallMethod(GraphvizSetAttr, "for a graphviz (di)graph or context and object", -[IsGraphvizGraphDigraphOrContext, IsObject], -function(x, value) - local attrs, match, pred; - - match := function(lookup, target) - local idx, pred; - idx := 1; - - pred := function(i) - return i <= Length(target) and i <= Length(lookup) - and lookup[i] = target[i] and lookup[i] <> '='; - end; - - while pred(idx) do - idx := idx + 1; - od; - if idx > Length(lookup) or idx > Length(lookup) then - return false; - elif lookup[idx] = '=' and target[idx] = '=' then - return true; - fi; - return false; - end; - - attrs := GraphvizAttrs(x); - x!.Attrs := Filtered(attrs, attr -> not match(attr, value)); - attrs := GraphvizAttrs(x); - Add(attrs, String(value)); - return x; -end); + key := String(key); -InstallMethod(GraphvizGetAttr, "for a graphviz (di)graph or context and string", -[IsGraphvizObject, IsString], -function(x, key) - if not IsBound(GraphvizAttrs(x).(key)) then + if not IsBound(record.(key)) then return fail; fi; - return GraphvizAttrs(x).(key); + return record.(key); end); -InstallMethod(GraphvizGetAttr, "for a graphviz (di)graph or context and string", +InstallMethod(GraphvizRemoveAttr, +"for a graphviz (di)graph or context and an object", [IsGraphvizObject, IsObject], -{x, key} -> GraphvizGetAttr(x, String(key))); +function(gv, key) + local record; + + if IsGraphvizGraphDigraphOrContext(gv) then + # By default setting an attribute of a graph, digraph, or context sets a + # graph attribute + record := GraphvizAttrs(gv).graph; + else + record := GraphvizAttrs(gv); + fi; + + key := String(key); + + if not IsBound(record.(key)) then + ErrorFormatted("the 2nd argument (attribute name) \"{}\" ", + "is not defined", key); + fi; + + Unbind(record.(key)); + return gv; +end); ############################################################################# # GraphvizAddNode @@ -587,41 +602,6 @@ InstallMethod(GraphvizRemoveEdges, [IsGraphvizGraphDigraphOrContext, IsObject, IsObject], {gv, o1, o2} -> GraphvizRemoveEdges(gv, String(o1), String(o2))); -InstallMethod(GraphvizRemoveAttr, "for a graphviz object and an object", -[IsGraphvizObject, IsObject], -function(obj, attr) - local attrs; - attrs := GraphvizAttrs(obj); - attr := String(attr); - - if not IsBound(attrs.(attr)) then - ErrorFormatted("the 2nd argument (attribute name) \"{}\" ", - "is not set on the provided object.", - attr); - fi; - - Unbind(attrs.(attr)); - return obj; -end); - -InstallMethod(GraphvizRemoveAttr, -"for a graphviz (di)graph or context and an object", -[IsGraphvizGraphDigraphOrContext, IsObject], -function(obj, attr) - local attrs, len; - attrs := GraphvizAttrs(obj); - len := Length(attrs); - - GV_RemoveGraphAttrIfExists(obj, attr); - # error if no attributes were removed i.e. did not exist - if Length(obj!.Attrs) - len = 0 then - ErrorFormatted("the 2nd argument (attribute name or attribute) \"{}\" ", - "is not set on the provided object.", - attr); - fi; - return obj; -end); - ############################################################################# # Stringify ############################################################################# diff --git a/gap/gv.gd b/gap/gv.gd index ae874f4..d60ade8 100644 --- a/gap/gv.gd +++ b/gap/gv.gd @@ -49,9 +49,6 @@ DeclareOperation("GV_AddEdge", DeclareOperation("GV_GetIdx", [IsGraphvizObject]); DeclareOperation("GV_ConstructHistory", [IsGraphvizGraphDigraphOrContext]); -DeclareOperation("GV_RemoveGraphAttrIfExists", -[IsGraphvizGraphDigraphOrContext, IsString]); - DeclareGlobalFunction("GV_IsValidColor"); DeclareGlobalFunction("GV_ErrorIfNotNodeColoring"); DeclareGlobalFunction("GV_ErrorIfNotValidLabel"); diff --git a/gap/gv.gi b/gap/gv.gi index 9db9dd4..6fd97cd 100644 --- a/gap/gv.gi +++ b/gap/gv.gi @@ -8,6 +8,8 @@ ############################################################################# ## +# TODO remove non-public functions from gv.gd + ############################################################################### # Family + type ############################################################################### @@ -110,7 +112,9 @@ function(parent, name) Contexts := rec(), Nodes := rec(), Edges := [], - Attrs := [], + Attrs := rec(graph := rec(), + edge := rec(), + node := rec()), Parent := parent, Idx := GV_GetCounter(parent), Counter := 1)); @@ -272,39 +276,6 @@ function(x, edge) return x; end); -InstallMethod(GV_RemoveGraphAttrIfExists, -"for a graphviz graph context or digraph and a string", -[IsGraphvizGraphDigraphOrContext, IsString], -function(obj, attr) - local attrs, i, match; - attrs := GraphvizAttrs(obj); - attr := String(attr); - - # checks if they attribute names match the one being removed - match := function(key, str) - for i in [1 .. Length(key)] do - if i > Length(str) or key[i] <> str[i] then - return false; - fi; - od; - - i := i + 1; - while i <= Length(str) do - if str[i] = '=' then - return true; - elif str[i] <> '\s' and str[i] <> '\t' then - return false; - fi; - i := i + 1; - od; - - # attributes which are not key value or removal by value - return true; - end; - - obj!.Attrs := Filtered(attrs, s -> not match(attr, s)); -end); - ############################################################################### # Stringifying ############################################################################### @@ -349,6 +320,39 @@ function(node) return name; end); +BindGlobal("GV_StringifyAttrList", +function(attrs) + local result, n, keys, key, val, i; + + Assert(0, IsRecord(attrs)); + + result := ""; + n := Length(RecNames(attrs)); + keys := SSortedList(RecNames(attrs)); + + if n <> 0 then + Append(result, " ["); + for i in [1 .. n - 1] do + key := keys[i]; + val := attrs.(key); + if not StartsWith(val, "\"") then + val := StringFormatted("\"{}\"", val); + fi; + + Append(result, StringFormatted("{}={}, ", key, val)); + od; + # handle last element + key := keys[n]; + val := attrs.(key); + if not StartsWith(val, "\"") then + val := StringFormatted("\"{}\"", val); + fi; + Append(result, StringFormatted("{}={}]", key, val)); + fi; + + return result; +end); + # @ Return DOT node statement line. InstallMethod(GV_StringifyNode, "for string and record", [IsGraphvizNode], @@ -356,7 +360,7 @@ function(node) local name, attrs; name := GV_StringifyNodeName(node); attrs := GraphvizAttrs(node); - return StringFormatted("\t{}{}\n", name, GV_StringifyNodeEdgeAttrs(attrs)); + return StringFormatted("\t{}{}\n", name, GV_StringifyAttrList(attrs)); end); # @ Return DOT graph edge statement line. @@ -374,69 +378,7 @@ function(edge, edge_str) head, edge_str, tail, - GV_StringifyNodeEdgeAttrs(attrs)); -end); - -InstallMethod(GV_StringifyGraphAttrs, -"for a graphviz graph", -[IsGraphvizGraphDigraphOrContext], -function(graph) - local result, attrs, kv; - attrs := GraphvizAttrs(graph); - result := ""; - - if Length(attrs) <> 0 then - Append(result, "\t"); - for kv in attrs do - Append(result, - StringFormatted("{} ", kv)); - od; - Append(result, "\n"); - fi; - return result; -end); - -InstallMethod(GV_StringifyNodeEdgeAttrs, "for a record", [IsRecord], -function(attrs) - local result, keys, key, val, n, i, tmp, format; - - result := ""; - n := Length(RecNames(attrs)); - keys := SSortedList(RecNames(attrs)); - - # helper for formatting attribute kv pairs - format := function(format, key, val) - tmp := Chomp(val); - if "label" = key and StartsWith(tmp, "<<") and EndsWith(tmp, ">>") then - val := StringFormatted("{}", val); - else - if ' ' in key then - key := StringFormatted("\"{}\"", key); - fi; - - if ' ' in val or '>' in val or '^' in val or '#' in val then - val := StringFormatted("\"{}\"", val); - fi; - fi; - - return StringFormatted(format, key, val); - end; - - if n <> 0 then - Append(result, " ["); - for i in [1 .. n - 1] do - key := keys[i]; - val := attrs.(key); - - Append(result, format("{}={}, ", key, val)); - od; - # handle last element - key := keys[n]; - val := attrs.(key); - Append(result, format("{}={}]", key, val)); - fi; - - return result; + GV_StringifyAttrList(attrs)); end); InstallMethod(GV_GetIdx, @@ -472,7 +414,8 @@ InstallMethod(GV_StringifyGraph, "for a graphviz graph and a string", [IsGraphvizGraphDigraphOrContext, IsBool], function(graph, is_subgraph) - local result, obj; + local result, record, type, obj; + result := ""; # get the correct head to use @@ -493,7 +436,12 @@ function(graph, is_subgraph) "expected a context, digraph or graph."); fi; - Append(result, GV_StringifyGraphAttrs(graph)); + for type in ["graph", "node", "edge"] do + record := GraphvizAttrs(graph).(type); + if Length(RecNames(record)) > 0 then + Append(result, StringFormatted("{} {}\n", type, GV_StringifyAttrList(record))); + fi; + od; # Add child graphviz objects for obj in GV_ConstructHistory(graph) do diff --git a/tst/dot.tst b/tst/dot.tst index 6fa19fe..6acb1f5 100644 --- a/tst/dot.tst +++ b/tst/dot.tst @@ -26,17 +26,20 @@ rec( color := "blue", label := "lab" ) gap> g := GraphvizGraph();; gap> GraphvizSetAttrs(g, rec(color := "red", shape := "circle"));; gap> GraphvizAttrs(g); -[ "color=red", "shape=circle" ] +rec( edge := rec( ), graph := rec( color := "red", shape := "circle" ), + node := rec( ) ) gap> GraphvizSetAttrs(g, rec(color := "blue", label := "test"));; gap> GraphvizAttrs(g); -[ "shape=circle", "label=test", "color=blue" ] +rec( edge := rec( ), + graph := rec( color := "blue", label := "test", shape := "circle" ), + node := rec( ) ) # Test stringify gap> g := GraphvizGraph();; gap> n := GraphvizAddNode(g, "test");; gap> GraphvizSetAttrs(n, rec(color := "red", label := "lab"));; gap> AsString(g); -"//dot\ngraph {\n\ttest [color=red, label=lab]\n}\n" +"//dot\ngraph {\n\ttest [color=\"red\", label=\"lab\"]\n}\n" gap> GraphvizRemoveNode(g, "banana"); Error, the 2nd argument (node name string) "banana" is not a node of the 1st a\ rgument (a graphviz (di)graph/context) @@ -50,8 +53,8 @@ gap> GraphvizSetAttrs(b, rec(color := "red"));; gap> e := GraphvizAddEdge(g, a, b);; gap> GraphvizSetAttrs(e, rec(color := "green"));; gap> AsString(g); -"//dot\ndigraph {\n\ta [color=blue]\n\tb [color=red]\n\ta -> b [color=green]\ -\n}\n" +"//dot\ndigraph {\n\ta [color=\"blue\"]\n\tb [color=\"red\"]\n\ta -> b [color\ +=\"green\"]\n}\n" # Test stringify with edge (graph) gap> g := GraphvizGraph();; @@ -62,8 +65,8 @@ gap> GraphvizSetAttrs(b, rec(color := "red"));; gap> e := GraphvizAddEdge(g, a, b);; gap> GraphvizSetAttrs(e, rec(color := "green"));; gap> AsString(g); -"//dot\ngraph {\n\ta [color=blue]\n\tb [color=red]\n\ta -- b [color=green]\n}\ -\n" +"//dot\ngraph {\n\ta [color=\"blue\"]\n\tb [color=\"red\"]\n\ta -- b [color=\ +\"green\"]\n}\n" # Test stringify empty gap> g := GraphvizGraph();; @@ -157,27 +160,27 @@ gap> GraphvizSetNodeColors(gv, ["red", "green", "blue"]); gap> Print(AsString(gv)); //dot graph xxx { - 1 [color=red, style=filled] - 2 [color=green, style=filled] - 3 [color=blue, style=filled] + 1 [color="red", style="filled"] + 2 [color="green", style="filled"] + 3 [color="blue", style="filled"] } gap> GraphvizSetNodeColors(gv, ["red", "#00FF00", "blue"]); gap> Print(AsString(gv)); //dot graph xxx { - 1 [color=red, style=filled] - 2 [color="#00FF00", style=filled] - 3 [color=blue, style=filled] + 1 [color="red", style="filled"] + 2 [color="#00FF00", style="filled"] + 3 [color="blue", style="filled"] } gap> GraphvizSetNodeColors(gv, ["#FF0000", "#00FF00", "#0000FF"]); gap> Print(AsString(gv)); //dot graph xxx { - 1 [color="#FF0000", style=filled] - 2 [color="#00FF00", style=filled] - 3 [color="#0000FF", style=filled] + 1 [color="#FF0000", style="filled"] + 2 [color="#00FF00", style="filled"] + 3 [color="#0000FF", style="filled"] } gap> GraphvizSetNodeColors(gv, ["#FF0000", "#00FF00", "#0000FG"]); Error, invalid color "#0000FG" (list (string)), valid colors are RGB values or\ @@ -203,14 +206,14 @@ gap> n := GraphvizSetAttr(n, "probably not ok", 1); gap> Print(AsString(gv)); //dot graph xxx { - 1 ["probably not ok"=1] + 1 [probably not ok="1"] } gap> GraphvizSetAttr(n, "label", "<<>>"); gap> Print(AsString(gv)); //dot graph xxx { - 1 [label=<<>>, "probably not ok"=1] + 1 [label="<<>>", probably not ok="1"] } # Issue 68 diff --git a/tst/examples/angles.tst b/tst/examples/angles.tst index 39f730b..43417c0 100644 --- a/tst/examples/angles.tst +++ b/tst/examples/angles.tst @@ -23,9 +23,9 @@ gap> cluster1 := GraphvizAddSubgraph(g, "cluster_1"); gap> GraphvizSetAttr(cluster1, "fontcolor", "white"); -gap> GraphvizSetAttr(cluster1, Concatenation("node[shape=circle, style=filled,", -> "fillcolor=\"white:black\", gradientangle=360, label=\"n9:n360\",", -> "fontcolor=black]")); +gap> GraphvizSetAttrs(cluster1, rec(node := rec(shape := "circle", +> style := "filled", fillcolor := "white:black", gradientangle := 360, +> label := "n9:n360", fontcolor := "black"))); gap> GraphvizAddNode(cluster1, "n9"); @@ -46,9 +46,10 @@ gap> cluster2 := GraphvizAddSubgraph(g, "cluster_2"); gap> GraphvizSetAttr(cluster2, "fontcolor", "white"); -gap> GraphvizSetAttr(cluster2, Concatenation("node[shape=circle, style=radial,", -> "fillcolor=\"white:black\", gradientangle=360,", -> "label=\"n9:n360\", fontcolor=black]")); +gap> GraphvizSetAttrs(cluster2, rec(node := rec( +> shape := "circle", style := "radial", +> fillcolor := "white:black", gradientangle := 360, +> label := "n9:n360", fontcolor := "black"))); gap> GraphvizAddNode(cluster2, "n18"); @@ -69,34 +70,36 @@ gap> GraphvizAddEdge(g, "n5", "n14"); gap> Print(AsString(g)); //dot digraph G { - bgcolor=blue +graph [bgcolor="blue"] subgraph cluster_1 { - fontcolor=white node[shape=circle, style=filled,fillcolor="white:black", grad\ -ientangle=360, label="n9:n360",fontcolor=black] label="Linear Angle Variations\ - (white to black gradient)" +graph [fontcolor="white", label="Linear Angle Variations (white to black grad\ +ient)"] +node [fillcolor="white:black", fontcolor="black", gradientangle="360", label=\ +"n9:n360", shape="circle", style="filled"] n9 - n8 [gradientangle=315, label="n8:315"] - n7 [gradientangle=270, label="n7:270"] - n6 [gradientangle=225, label="n6:225"] - n5 [gradientangle=180, label="n5:180"] - n4 [gradientangle=135, label="n4:135"] - n3 [gradientangle=90, label="n3:90"] - n2 [gradientangle=45, label="n2:45"] - n1 [gradientangle=0, label="n1:0"] + n8 [gradientangle="315", label="n8:315"] + n7 [gradientangle="270", label="n7:270"] + n6 [gradientangle="225", label="n6:225"] + n5 [gradientangle="180", label="n5:180"] + n4 [gradientangle="135", label="n4:135"] + n3 [gradientangle="90", label="n3:90"] + n2 [gradientangle="45", label="n2:45"] + n1 [gradientangle="0", label="n1:0"] } subgraph cluster_2 { - fontcolor=white node[shape=circle, style=radial,fillcolor="white:black", grad\ -ientangle=360,label="n9:n360", fontcolor=black] label="Radial Angle Variations\ - (white to black gradient)" +graph [fontcolor="white", label="Radial Angle Variations (white to black grad\ +ient)"] +node [fillcolor="white:black", fontcolor="black", gradientangle="360", label=\ +"n9:n360", shape="circle", style="radial"] n18 - n17 [gradientangle=315, label="n17:315"] - n16 [gradientangle=270, label="n16:270"] - n15 [gradientangle=225, label="n15:225"] - n14 [gradientangle=180, label="n14:180"] - n13 [gradientangle=135, label="n13:135"] - n12 [gradientangle=90, label="n12:90"] - n11 [gradientangle=45, label="n11:45"] - n10 [gradientangle=0, label="n10:0"] + n17 [gradientangle="315", label="n17:315"] + n16 [gradientangle="270", label="n16:270"] + n15 [gradientangle="225", label="n15:225"] + n14 [gradientangle="180", label="n14:180"] + n13 [gradientangle="135", label="n13:135"] + n12 [gradientangle="90", label="n12:90"] + n11 [gradientangle="45", label="n11:45"] + n10 [gradientangle="0", label="n10:0"] } n5 -> n14 } diff --git a/tst/examples/btree.tst b/tst/examples/btree.tst index 868ba3a..ecc45f0 100644 --- a/tst/examples/btree.tst +++ b/tst/examples/btree.tst @@ -19,7 +19,7 @@ true # gap> s := GraphvizDigraph("g"); -gap> GraphvizSetAttr(s, "node [shape=record, height=.1]"); +gap> GraphvizSetAttrs(s, rec(node := rec(shape := "record", height := ".1"))); gap> GraphvizSetAttr(GraphvizAddNode(s, "node0"), "label", " | G|"); @@ -56,17 +56,17 @@ gap> GraphvizAddEdge(s, "node4:f2", "node6:f1"); gap> GraphvizAddEdge(s, "node4:f0", "node5:f1"); gap> AsString(s) = -> "//dot\ndigraph g {\n\tnode [shape=record, height=.1] \n\tnode0 [label=\" \ -> | G|\"]\n\tnode1 [label=\" | E|\"]\n\tnode2 [label=\" \ -> | B|\"]\n\tnode3 [label=\" | F|\"]\n\tnode4 [label=\" \ -> | R|\"]\n\tnode5 [label=\" | H|\"]\n\tnode6 [label=\" \ -> | Y|\"]\n\tnode7 [label=\" | A|\"]\n\tnode8 [label=\" \ -> | C|\"]\n\tnode0:f2\n\tnode4:f1\n\tnode0:f2 -> node4:f1\n\tnode0:f0\n\ -> \tnode1:f1\n\tnode0:f0 -> node1:f1\n\tnode1:f0\n\tnode2:f1\n\tnode1:f0 -> node\ -> 2:f1\n\tnode1:f2\n\tnode3:f1\n\tnode1:f2 -> node3:f1\n\tnode2:f2\n\tnode8:f1\n\ -> \tnode2:f2 -> node8:f1\n\tnode2:f0\n\tnode7:f1\n\tnode2:f0 -> node7:f1\n\tnode\ -> 4:f2\n\tnode6:f1\n\tnode4:f2 -> node6:f1\n\tnode4:f0\n\tnode5:f1\n\tnode4:f0 -\ -> > node5:f1\n}\n"; +> "//dot\ndigraph g {\nnode [height=\".1\", shape=\"record\"]\n\tnode0 [label=\ +> \" | G|\"]\n\tnode1 [label=\" | E|\"]\n\tnode2 [label=\ +> \" | B|\"]\n\tnode3 [label=\" | F|\"]\n\tnode4 [label=\ +> \" | R|\"]\n\tnode5 [label=\" | H|\"]\n\tnode6 [label=\ +> \" | Y|\"]\n\tnode7 [label=\" | A|\"]\n\tnode8 [label=\ +> \" | C|\"]\n\tnode0:f2\n\tnode4:f1\n\tnode0:f2 -> node4:f1\n\tnode\ +> 0:f0\n\tnode1:f1\n\tnode0:f0 -> node1:f1\n\tnode1:f0\n\tnode2:f1\n\tnode1:f0 -\ +> > node2:f1\n\tnode1:f2\n\tnode3:f1\n\tnode1:f2 -> node3:f1\n\tnode2:f2\n\tnode\ +> 8:f1\n\tnode2:f2 -> node8:f1\n\tnode2:f0\n\tnode7:f1\n\tnode2:f0 -> node7:f1\n\ +> \tnode4:f2\n\tnode6:f1\n\tnode4:f2 -> node6:f1\n\tnode4:f0\n\tnode5:f1\n\tnode\ +> 4:f0 -> node5:f1\n}\n"; true # diff --git a/tst/examples/cluster.tst b/tst/examples/cluster.tst index 0214c8b..b1c97a5 100644 --- a/tst/examples/cluster.tst +++ b/tst/examples/cluster.tst @@ -20,11 +20,11 @@ gap> graph := GraphvizDigraph("G"); # gap> cluster0 := GraphvizAddSubgraph(graph, "cluster_0"); -gap> GraphvizSetAttr(cluster0, "color=\"lightgrey\""); +gap> GraphvizSetAttrs(cluster0, rec(color := "lightgrey")); -gap> GraphvizSetAttr(cluster0, "style=\"filled\""); +gap> GraphvizSetAttrs(cluster0, rec(style := "filled")); -gap> GraphvizSetAttr(cluster0, "node [color=\"white\", style=\"filled\"]"); +gap> GraphvizSetAttrs(cluster0, rec(node := rec(color := "white", style := "filled"))); gap> GraphvizAddEdge(cluster0, "a0", "a1"); @@ -32,15 +32,15 @@ gap> GraphvizAddEdge(cluster0, "a1", "a2"); gap> GraphvizAddEdge(cluster0, "a2", "a3"); -gap> GraphvizSetAttr(cluster0, "label=\"process #1\""); +gap> GraphvizSetAttrs(cluster0, rec(label := "process #1")); # gap> cluster1 := GraphvizAddSubgraph(graph, "cluster_1"); -gap> GraphvizSetAttr(cluster1, "color=\"blue\""); +gap> GraphvizSetAttrs(cluster1, rec(color := "blue")); -gap> GraphvizSetAttr(cluster1, "node [style=\"filled\"]"); +gap> GraphvizSetAttrs(cluster1, rec(node := rec(style := "filled"))); gap> GraphvizAddEdge(cluster1, "b0", "b1"); @@ -48,7 +48,7 @@ gap> GraphvizAddEdge(cluster1, "b1", "b2"); gap> GraphvizAddEdge(cluster1, "b2", "b3"); -gap> GraphvizSetAttr(cluster1, "label=\"process #2\""); +gap> GraphvizSetAttrs(cluster1, rec(label := "process #2")); # @@ -75,13 +75,13 @@ gap> GraphvizSetAttr(GraphvizNode(graph, "end"), "shape", "Msquare"); # gap> AsString(graph); -"//dot\ndigraph G {\nsubgraph cluster_0 {\n\tcolor=\"lightgrey\" style=\"fille\ -d\" node [color=\"white\", style=\"filled\"] label=\"process #1\" \n\ta0\n\ta1\ -\n\ta0 -> a1\n\ta2\n\ta1 -> a2\n\ta3\n\ta2 -> a3\n}\nsubgraph cluster_1 {\n\tc\ -olor=\"blue\" node [style=\"filled\"] label=\"process #2\" \n\tb0\n\tb1\n\tb0 \ --> b1\n\tb2\n\tb1 -> b2\n\tb3\n\tb2 -> b3\n}\n\tstart [shape=Mdiamond]\n\tstar\ -t -> a0\n\tstart -> b0\n\ta1 -> b3\n\tb2 -> a3\n\ta3 -> a0\n\tend [shape=Msqua\ -re]\n\ta3 -> end\n\tb3 -> end\n}\n" +"//dot\ndigraph G {\nsubgraph cluster_0 {\ngraph [color=\"lightgrey\", label=\ +\"process #1\", style=\"filled\"]\nnode [color=\"white\", style=\"filled\"]\n\ +\ta0\n\ta1\n\ta0 -> a1\n\ta2\n\ta1 -> a2\n\ta3\n\ta2 -> a3\n}\nsubgraph cluste\ +r_1 {\ngraph [color=\"blue\", label=\"process #2\"]\nnode [style=\"filled\"]\ +\n\tb0\n\tb1\n\tb0 -> b1\n\tb2\n\tb1 -> b2\n\tb3\n\tb2 -> b3\n}\n\tstart [shap\ +e=\"Mdiamond\"]\n\tstart -> a0\n\tstart -> b0\n\ta1 -> b3\n\tb2 -> a3\n\ta3 ->\ + a0\n\tend [shape=\"Msquare\"]\n\ta3 -> end\n\tb3 -> end\n}\n" # gap> STOP_TEST("graphviz package: examples/cluster.tst"); diff --git a/tst/examples/cluster_edge.tst b/tst/examples/cluster_edge.tst index 05e391e..0a931e5 100644 --- a/tst/examples/cluster_edge.tst +++ b/tst/examples/cluster_edge.tst @@ -19,7 +19,7 @@ true # gap> g := GraphvizDigraph("G"); -gap> GraphvizSetAttr(g, "compound=true"); +gap> GraphvizSetAttrs(g, rec(compound := "true")); gap> cluster0 := GraphvizAddSubgraph(g, "cluster0"); @@ -54,10 +54,11 @@ gap> GraphvizSetAttr(e, "ltail", "cluster0"); gap> GraphvizAddEdge(g, "d", "h"); gap> AsString(g); -"//dot\ndigraph G {\n\tcompound=true \nsubgraph cluster0 {\n\ta\n\tb\n\ta -> b\ -\n\tc\n\ta -> c\n\td\n\tb -> d\n\tc -> d\n}\nsubgraph cluster1 {\n\te\n\tg\n\t\ -e -> g\n\tf\n\te -> f\n}\n\tb -> f [lhead=cluster1]\n\td -> e\n\tc -> g [lhead\ -=cluster1, ltail=cluster0]\n\tc -> e [ltail=cluster0]\n\th\n\td -> h\n}\n" +"//dot\ndigraph G {\ngraph [compound=\"true\"]\nsubgraph cluster0 {\n\ta\n\tb\ +\n\ta -> b\n\tc\n\ta -> c\n\td\n\tb -> d\n\tc -> d\n}\nsubgraph cluster1 {\n\t\ +e\n\tg\n\te -> g\n\tf\n\te -> f\n}\n\tb -> f [lhead=\"cluster1\"]\n\td -> e\n\ +\tc -> g [lhead=\"cluster1\", ltail=\"cluster0\"]\n\tc -> e [ltail=\"cluster0\ +\"]\n\th\n\td -> h\n}\n" # gap> STOP_TEST("graphviz package: examples/cluster_edge.tst"); diff --git a/tst/examples/colors.tst b/tst/examples/colors.tst index 9493086..a7bf9d4 100644 --- a/tst/examples/colors.tst +++ b/tst/examples/colors.tst @@ -59,10 +59,10 @@ gap> AsString(g); #I invalid node name RGBA: #ff000042 using "RGBA: #ff000042" instead #I invalid node name HSV: 0.051 0.718 0.627 using "HSV: 0.051 0.718 0.627" instead #I invalid node name name: deeppink using "name: deeppink" instead -"//dot\ngraph {\n\t\"RGB: #40e0d0\" [fillcolor=\"\"#40e0d0\"\", style=filled]\ -\n\t\"RGBA: #ff000042\" [fillcolor=\"\"#ff000042\"\", style=filled]\n\t\"HSV: \ -0.051 0.718 0.627\" [fillcolor=\"0.051 0.718 0.627\", style=filled]\n\t\"name:\ - deeppink\" [fillcolor=deeppink, style=filled]\n}\n" +"//dot\ngraph {\n\t\"RGB: #40e0d0\" [fillcolor=\"#40e0d0\", style=\"filled\"]\ +\n\t\"RGBA: #ff000042\" [fillcolor=\"#ff000042\", style=\"filled\"]\n\t\"HSV: \ +0.051 0.718 0.627\" [fillcolor=\"0.051 0.718 0.627\", style=\"filled\"]\n\t\"n\ +ame: deeppink\" [fillcolor=\"deeppink\", style=\"filled\"]\n}\n" # gap> STOP_TEST("graphviz package: examples/colors.tst"); diff --git a/tst/examples/er.tst b/tst/examples/er.tst index 859d200..c4fb0ef 100644 --- a/tst/examples/er.tst +++ b/tst/examples/er.tst @@ -19,13 +19,13 @@ true # gap> e := GraphvizGraph("ER"); -gap> GraphvizSetAttr(e, "engine=\"neato\""); +gap> GraphvizSetAttrs(e, rec(engine := "neato")); # gap> start := GraphvizAddContext(e, "context_start"); -gap> GraphvizSetAttr(start, "node[shape=\"box\"]"); +gap> GraphvizSetAttrs(start, rec(node := rec(shape := "box"))); gap> GraphvizAddNode(start, "course"); @@ -37,7 +37,7 @@ gap> GraphvizAddNode(start, "student"); # gap> context1 := GraphvizAddContext(e, "context1"); -gap> GraphvizSetAttr(context1, "node [shape=\"ellipse\"]"); +gap> GraphvizSetAttrs(context1, rec(node := rec(shape := "ellipse"))); gap> GraphvizSetAttr(GraphvizAddNode(context1, "name0"), "label", "name"); @@ -55,8 +55,8 @@ gap> GraphvizAddNode(context1, "number"); # gap> context2 := GraphvizAddContext(e, "context2"); -gap> GraphvizSetAttr(context2, -> "node [shape=\"diamond\", style=\"filled\", color=\"lightgrey\"]"); +gap> GraphvizSetAttrs(context2, +> rec(node := rec(shape := "diamond", style := "filled", color := "lightgrey"))); gap> GraphvizAddNode(context2, "C-I"); @@ -98,9 +98,9 @@ gap> GraphvizSetAttrs(GraphvizAddEdge(e, "course", "S-C"), # -gap> GraphvizSetAttr(e, "label=\"Entity Relation Diagram\ndrawn by NEATO\""); +gap> GraphvizSetAttrs(e, rec(label := "Entity Relation Diagram\ndrawn by NEATO")); -gap> GraphvizSetAttr(e, "fontsize=\"20\""); +gap> GraphvizSetAttrs(e, rec(fontsize := "20")); # @@ -114,17 +114,18 @@ gap> AsString(e); #I invalid node name S-I using "S-I" instead #I invalid node name S-C using "S-C" instead #I invalid node name S-C using "S-C" instead -"//dot\ngraph ER {\n\tengine=\"neato\" label=\"Entity Relation Diagram\ndrawn \ -by NEATO\" fontsize=\"20\" \n// context_start context \n{\n\tnode[shape=\"box\ -\"] \n\tcourse\n\tinstitute\n\tstudent\n}\n// context1 context \n{\n\tnode [sh\ -ape=\"ellipse\"] \n\tname0 [label=name]\n\tname1 [label=name]\n\tname2 [label=\ -name]\n\tcode\n\tgrade\n\tnumber\n}\n// context2 context \n{\n\tnode [shape=\"\ -diamond\", style=\"filled\", color=\"lightgrey\"] \n\t\"C-I\"\n\t\"S-C\"\n\t\"\ -S-I\"\n}\n\tname0 -- course\n\tcode -- course\n\t\"C-I\" -- course [label=n, l\ -en=1.00]\n\tinstitute -- \"C-I\" [label=1, len=1.00]\n\tname1 -- institute\n\t\ -\"S-I\" -- institute [label=1, len=1.00]\n\tstudent -- \"S-I\" [label=n, len=1\ -.00]\n\tgrade -- student\n\tname2 -- student\n\tnumber -- student\n\t\"S-C\" -\ -- student [label=m, len=1.00]\n\tcourse -- \"S-C\" [label=n, len=1.00]\n}\n" +"//dot\ngraph ER {\ngraph [engine=\"neato\", fontsize=\"20\", label=\"Entity \ +Relation Diagram\ndrawn by NEATO\"]\n// context_start context \n{\nnode [shap\ +e=\"box\"]\n\tcourse\n\tinstitute\n\tstudent\n}\n// context1 context \n{\nnode\ + [shape=\"ellipse\"]\n\tname0 [label=\"name\"]\n\tname1 [label=\"name\"]\n\tn\ +ame2 [label=\"name\"]\n\tcode\n\tgrade\n\tnumber\n}\n// context2 context \n{\n\ +node [color=\"lightgrey\", shape=\"diamond\", style=\"filled\"]\n\t\"C-I\"\n\ +\t\"S-C\"\n\t\"S-I\"\n}\n\tname0 -- course\n\tcode -- course\n\t\"C-I\" -- cou\ +rse [label=\"n\", len=\"1.00\"]\n\tinstitute -- \"C-I\" [label=\"1\", len=\"1.\ +00\"]\n\tname1 -- institute\n\t\"S-I\" -- institute [label=\"1\", len=\"1.00\"\ +]\n\tstudent -- \"S-I\" [label=\"n\", len=\"1.00\"]\n\tgrade -- student\n\tnam\ +e2 -- student\n\tnumber -- student\n\t\"S-C\" -- student [label=\"m\", len=\"1\ +.00\"]\n\tcourse -- \"S-C\" [label=\"n\", len=\"1.00\"]\n}\n" # gap> STOP_TEST("graphviz package: examples/er.tst"); diff --git a/tst/examples/fsm.tst b/tst/examples/fsm.tst index 44e1337..ec10d81 100644 --- a/tst/examples/fsm.tst +++ b/tst/examples/fsm.tst @@ -19,15 +19,15 @@ true # gap> f := GraphvizDigraph("finite_state_machine"); -gap> GraphvizSetAttr(f, "rankdir=LR"); +gap> GraphvizSetAttrs(f, rec(rankdir := "LR")); -gap> GraphvizSetAttr(f, "size=\"8,5\""); +gap> GraphvizSetAttrs(f, rec(size := "8,5")); # gap> terminals := GraphvizAddContext(f, "terminals"); -gap> GraphvizSetAttr(terminals, "node [shape=doublecircle]"); +gap> GraphvizSetAttrs(terminals, rec(node := rec(shape := "doublecircle"))); gap> GraphvizAddNode(terminals, "LR_0"); @@ -41,7 +41,7 @@ gap> GraphvizAddNode(terminals, "LR_8"); # gap> nodes := GraphvizAddContext(f, "nodes"); -gap> GraphvizSetAttr(nodes, "node [shape=circle]"); +gap> GraphvizSetAttrs(nodes, rec(node := rec(shape := "circle"))); gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_0", "LR_2"), "label", "\"SS(B)\""); @@ -74,16 +74,16 @@ gap> GraphvizSetAttr(GraphvizAddEdge(nodes, "LR_8", "LR_5"), "label", "\"S(a)\"" # gap> AsString(f); -"//dot\ndigraph finite_state_machine {\n\trankdir=LR size=\"8,5\" \n// termina\ -ls context \n{\n\tnode [shape=doublecircle] \n\tLR_0\n\tLR_3\n\tLR_4\n\tLR_8\n\ -}\n// nodes context \n{\n\tnode [shape=circle] \n\tLR_2\n\tLR_0 -> LR_2 [label\ -=\"SS(B)\"]\n\tLR_1\n\tLR_0 -> LR_1 [label=\"SS(S)\"]\n\tLR_1 -> LR_3 [label=\ -\"S($end)\"]\n\tLR_6\n\tLR_2 -> LR_6 [label=\"SS(b)\"]\n\tLR_5\n\tLR_2 -> LR_5\ - [label=\"SS(a)\"]\n\tLR_2 -> LR_4 [label=\"S(A)\"]\n\tLR_7\n\tLR_5 -> LR_7 [l\ -abel=\"S(b)\"]\n\tLR_5 -> LR_5 [label=\"S(a)\"]\n\tLR_6 -> LR_6 [label=\"S(b)\ -\"]\n\tLR_6 -> LR_5 [label=\"S(a)\"]\n\tLR_7 -> LR_8 [label=\"S(b)\"]\n\tLR_7 \ --> LR_5 [label=\"S(a)\"]\n\tLR_8 -> LR_6 [label=\"S(b)\"]\n\tLR_8 -> LR_5 [lab\ -el=\"S(a)\"]\n}\n}\n" +"//dot\ndigraph finite_state_machine {\ngraph [rankdir=\"LR\", size=\"8,5\"]\ +\n// terminals context \n{\nnode [shape=\"doublecircle\"]\n\tLR_0\n\tLR_3\n\t\ +LR_4\n\tLR_8\n}\n// nodes context \n{\nnode [shape=\"circle\"]\n\tLR_2\n\tLR_\ +0 -> LR_2 [label=\"SS(B)\"]\n\tLR_1\n\tLR_0 -> LR_1 [label=\"SS(S)\"]\n\tLR_1 \ +-> LR_3 [label=\"S($end)\"]\n\tLR_6\n\tLR_2 -> LR_6 [label=\"SS(b)\"]\n\tLR_5\ +\n\tLR_2 -> LR_5 [label=\"SS(a)\"]\n\tLR_2 -> LR_4 [label=\"S(A)\"]\n\tLR_7\n\ +\tLR_5 -> LR_7 [label=\"S(b)\"]\n\tLR_5 -> LR_5 [label=\"S(a)\"]\n\tLR_6 -> LR\ +_6 [label=\"S(b)\"]\n\tLR_6 -> LR_5 [label=\"S(a)\"]\n\tLR_7 -> LR_8 [label=\"\ +S(b)\"]\n\tLR_7 -> LR_5 [label=\"S(a)\"]\n\tLR_8 -> LR_6 [label=\"S(b)\"]\n\tL\ +R_8 -> LR_5 [label=\"S(a)\"]\n}\n}\n" # gap> STOP_TEST("graphviz package: examples/fsm.tst"); diff --git a/tst/examples/g_c_n.tst b/tst/examples/g_c_n.tst index b818846..b555a79 100644 --- a/tst/examples/g_c_n.tst +++ b/tst/examples/g_c_n.tst @@ -19,29 +19,29 @@ true # gap> g := GraphvizGraph("G"); -gap> GraphvizSetAttr(g, -> "bgcolor=\"purple:pink\" label=\"agraph\" fontcolor=\"white\""); +gap> GraphvizSetAttrs(g, rec(bgcolor := "purple:pink", label := "agraph", fontcolor := "white")); gap> cluster1 := GraphvizAddSubgraph(g, "cluster1"); -gap> GraphvizSetAttr(cluster1, Concatenation( -> "fillcolor=\"blue:cyan\" label=\"acluster\" fontcolor=\"white\"", -> "style=\"filled\" gradientangle=270\n")); +gap> GraphvizSetAttrs(cluster1, +> rec(fillcolor := "blue:cyan", label := "acluster", fontcolor := "white", +> style := "filled", gradientangle := 270)); -gap> GraphvizSetAttr(cluster1, Concatenation( -> "node [shape=box, fillcolor=\"red:yellow\",", -> " style=\"filled\", gradientangle=90]")); +gap> GraphvizSetAttrs(cluster1, +> rec(node := rec(shape := "box", fillcolor := "red:yellow", style := "filled", +> gradientangle := 90))); gap> GraphvizAddNode(cluster1, "anode"); gap> Print(AsString(g)); //dot graph G { - bgcolor="purple:pink" label="agraph" fontcolor="white" +graph [bgcolor="purple:pink", fontcolor="white", label="agraph"] subgraph cluster1 { - fillcolor="blue:cyan" label="acluster" fontcolor="white"style="filled" gradie\ -ntangle=270 - node [shape=box, fillcolor="red:yellow", style="filled", gradientangle=90] +graph [fillcolor="blue:cyan", fontcolor="white", gradientangle="270", label="\ +acluster", style="filled"] +node [fillcolor="red:yellow", gradientangle="90", shape="box", style="filled"\ +] anode } } diff --git a/tst/examples/process.tst b/tst/examples/process.tst index 02cbc2e..0cfbd9c 100644 --- a/tst/examples/process.tst +++ b/tst/examples/process.tst @@ -19,7 +19,7 @@ true # gap> graph := GraphvizGraph("G"); -gap> GraphvizSetAttr(graph, "engine=\"sfdp\""); +gap> GraphvizSetAttrs(graph, rec(engine := "sfdp")); # @@ -48,11 +48,11 @@ gap> GraphvizAddEdge(graph, "runswap", "runmem"); gap> GraphvizAddEdge(graph, "new", "runmem"); gap> AsString(graph); -"//dot\ngraph G {\n\tengine=\"sfdp\" \n\trun\n\tintr\n\trun -- intr\n\trunbl\n\ -\tintr -- runbl\n\trunbl -- run\n\tkernel\n\trun -- kernel\n\tzombie\n\tkernel\ - -- zombie\n\tsleep\n\tkernel -- sleep\n\trunmem\n\tkernel -- runmem\n\tswap\n\ -\tsleep -- swap\n\trunswap\n\tswap -- runswap\n\tnew\n\trunswap -- new\n\truns\ -wap -- runmem\n\tnew -- runmem\n}\n" +"//dot\ngraph G {\ngraph [engine=\"sfdp\"]\n\trun\n\tintr\n\trun -- intr\n\tr\ +unbl\n\tintr -- runbl\n\trunbl -- run\n\tkernel\n\trun -- kernel\n\tzombie\n\t\ +kernel -- zombie\n\tsleep\n\tkernel -- sleep\n\trunmem\n\tkernel -- runmem\n\t\ +swap\n\tsleep -- swap\n\trunswap\n\tswap -- runswap\n\tnew\n\trunswap -- new\n\ +\trunswap -- runmem\n\tnew -- runmem\n}\n" # gap> STOP_TEST("graphviz package: examples/process.tst"); diff --git a/tst/examples/rank_same.tst b/tst/examples/rank_same.tst index 5116642..32f7f6d 100644 --- a/tst/examples/rank_same.tst +++ b/tst/examples/rank_same.tst @@ -24,7 +24,7 @@ gap> g := GraphvizDigraph(); # gap> s1 := GraphvizAddSubgraph(g); -gap> GraphvizSetAttr(s1, "rank=same"); +gap> GraphvizSetAttrs(s1, rec(rank := "same")); gap> GraphvizAddNode(s1, "A"); @@ -38,7 +38,7 @@ gap> GraphvizAddNode(g, "C"); # gap> s2 := GraphvizAddSubgraph(g); -gap> GraphvizSetAttr(s2, "rank=same"); +gap> GraphvizSetAttrs(s2, rec(rank := "same")); gap> GraphvizAddNode(s2, "B"); @@ -59,9 +59,9 @@ gap> GraphvizAddEdge(g, "X", "Y"); # gap> AsString(g); -"//dot\ndigraph {\nsubgraph no_name_1 {\n\trank=same \n\tA\n\tX\n}\n\tC\nsubg\ -raph no_name_3 {\n\trank=same \n\tB\n\tD\n\tY\n}\n\tA -> B\n\tA -> C\n\tC -> D\ -\n\tX -> Y\n}\n" +"//dot\ndigraph {\nsubgraph no_name_1 {\ngraph [rank=\"same\"]\n\tA\n\tX\n}\ +\n\tC\nsubgraph no_name_3 {\ngraph [rank=\"same\"]\n\tB\n\tD\n\tY\n}\n\tA -> \ +B\n\tA -> C\n\tC -> D\n\tX -> Y\n}\n" # gap> STOP_TEST("graphviz package: examples/rank_same.tst"); diff --git a/tst/examples/structs.tst b/tst/examples/structs.tst index 2d6492d..7ac00d5 100644 --- a/tst/examples/structs.tst +++ b/tst/examples/structs.tst @@ -17,7 +17,7 @@ gap> LoadPackage("GraphvizForGAP"); true gap> s := GraphvizDigraph("structs"); -gap> GraphvizSetAttr(s, "node [shape=\"plaintext\"]"); +gap> GraphvizSetAttrs(s, rec(node := rec(shape := "plaintext"))); # @@ -64,17 +64,17 @@ gap> GraphvizAddEdge(s, "struct1:f2", "struct3:here"); # gap> AsString(s); -"//dot\ndigraph structs {\n\tnode [shape=\"plaintext\"] \n\tstruct1 [label=<\n\nleft\nmiddleright\n\n>]\n\tstru\ -ct2 [label=<\n\none\n\n\n
two
>]\n\tstruct3 [label=<\n\n<\ -TD ROWSPAN=\"3\">hello
world\nb\ng\nh\n\n\nc\nd\ne\n\n\nf\n\n>]\n\tstruct1:f1\n\tstruct2:f0\n\tstruct1:f1 -> struct2:f0\n\tstruct1:f2\n\ts\ -truct3:here\n\tstruct1:f2 -> struct3:here\n}\n" +D PORT=\"f1\">middleright\n\n>\"]\n\tst\ +ruct2 [label=\"<\n\ +\n\n\n\n
onetwo
>\"]\n\tstruct3 [labe\ +l=\"<\ +\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ +\n
hello
world
bgh
cde
f
>\"]\n\tstruct1:f1\n\tstruct2:f0\n\tstruct1:f1 -> struct2:f0\n\tstru\ +ct1:f2\n\tstruct3:here\n\tstruct1:f2 -> struct3:here\n}\n" # gap> STOP_TEST("graphviz package: examples/structs.tst"); diff --git a/tst/examples/traffic_lights.tst b/tst/examples/traffic_lights.tst index bbdbc1e..5ad450a 100644 --- a/tst/examples/traffic_lights.tst +++ b/tst/examples/traffic_lights.tst @@ -17,13 +17,13 @@ gap> LoadPackage("GraphvizForGAP"); true gap> t := GraphvizDigraph("TrafficLights"); -gap> GraphvizSetAttr(t, "engine=neato"); +gap> GraphvizSetAttrs(t, rec(engine := "neato")); # gap> ctx1 := GraphvizAddSubgraph(t, "ctx1"); -gap> GraphvizSetAttr(ctx1, "node [shape=\"box\"]"); +gap> GraphvizSetAttrs(ctx1, rec(node := rec(shape := "box"))); gap> for i in [2, 1] do > GraphvizAddNode(ctx1, StringFormatted("gy{}", i)); @@ -34,7 +34,8 @@ gap> for i in [2, 1] do # gap> ctx2 := GraphvizAddSubgraph(t, "ctx2"); -gap> GraphvizSetAttr(ctx2, "node [shape=\"circle\", fixedsize=true, width=0.9]"); +gap> GraphvizSetAttrs(ctx2, +> rec(node := rec(shape := "circle", fixedsize := "true", width := "0.9"))); gap> for i in [2, 1] do > GraphvizAddNode(ctx2, StringFormatted("green{}", i)); @@ -68,27 +69,25 @@ gap> for pair in [[2, 1], [1, 2]] do > od; # -gap> GraphvizSetAttr(t, "overlap=\"false\""); +gap> GraphvizSetAttrs(t, rec(overlap := "false")); -gap> GraphvizSetAttr(t, -> """label="PetriNet Model TrafficLights -> Extracted from ConceptBase and laid out by Graphviz" -> """); +gap> GraphvizSetAttrs(t, +> rec(label := "PetriNet Model TrafficLights\nExtracted from ConceptBase and laid out by Graphviz")); -gap> GraphvizSetAttr(t, "fontsize=12"); +gap> GraphvizSetAttrs(t, rec(fontsize := "12")); # gap> AsString(t); -"//dot\ndigraph TrafficLights {\n\tengine=neato overlap=\"false\" label=\"Petr\ -iNet Model TrafficLights\nExtracted from ConceptBase and laid out by Graphviz\ -\"\n fontsize=12 \nsubgraph ctx1 {\n\tnode [shape=\"box\"] \n\tgy2\n\tyr2\n\tr\ -g2\n\tgy1\n\tyr1\n\trg1\n}\nsubgraph ctx2 {\n\tnode [shape=\"circle\", fixedsi\ -ze=true, width=0.9] \n\tgreen2\n\tyellow2\n\tred2\n\tsafe2\n\tgreen1\n\tyellow\ -1\n\tred1\n\tsafe1\n}\n\tgy2 -> yellow2\n\trg2 -> green2\n\tyr2 -> safe1\n\tyr\ -2 -> red2\n\tsafe2 -> rg2\n\tgreen2 -> gy2\n\tyellow2 -> yr2\n\tred2 -> rg2\n\ -\tgy1 -> yellow1\n\trg1 -> green1\n\tyr1 -> safe2\n\tyr1 -> red1\n\tsafe1 -> r\ -g1\n\tgreen1 -> gy1\n\tyellow1 -> yr1\n\tred1 -> rg1\n}\n" +"//dot\ndigraph TrafficLights {\ngraph [engine=\"neato\", fontsize=\"12\", la\ +bel=\"PetriNet Model TrafficLights\nExtracted from ConceptBase and laid out by\ + Graphviz\", overlap=\"false\"]\nsubgraph ctx1 {\nnode [shape=\"box\"]\n\tgy2\ +\n\tyr2\n\trg2\n\tgy1\n\tyr1\n\trg1\n}\nsubgraph ctx2 {\nnode [fixedsize=\"tr\ +ue\", shape=\"circle\", width=\"0.9\"]\n\tgreen2\n\tyellow2\n\tred2\n\tsafe2\n\ +\tgreen1\n\tyellow1\n\tred1\n\tsafe1\n}\n\tgy2 -> yellow2\n\trg2 -> green2\n\t\ +yr2 -> safe1\n\tyr2 -> red2\n\tsafe2 -> rg2\n\tgreen2 -> gy2\n\tyellow2 -> yr2\ +\n\tred2 -> rg2\n\tgy1 -> yellow1\n\trg1 -> green1\n\tyr1 -> safe2\n\tyr1 -> r\ +ed1\n\tsafe1 -> rg1\n\tgreen1 -> gy1\n\tyellow1 -> yr1\n\tred1 -> rg1\n}\n" # gap> STOP_TEST("graphviz package: examples/traffic_lights.tst"); diff --git a/tst/examples/unix.tst b/tst/examples/unix.tst index e3f8eb3..63ea0e7 100644 --- a/tst/examples/unix.tst +++ b/tst/examples/unix.tst @@ -19,8 +19,8 @@ true # gap> u := GraphvizDigraph("unix"); -gap> GraphvizSetAttr( -> u, "node [color=\"lightblue2\", style=\"filled\", size=\"6,6\"]"); +gap> GraphvizSetAttrs(u, +> rec(node := rec(color := "lightblue2", style := "filled", size := "6,6"))); # @@ -125,36 +125,36 @@ gap> GraphvizAddEdge(u, "System V.2", "System V.3"); # gap> AsString(u) = -> "//dot\ndigraph unix {\n\tnode [color=\"lightblue2\", style=\"filled\", size=\ -> \"6,6\"] \n\t\"5th Edition\"\n\t\"6th Edition\"\n\t\"5th Edition\" -> \"6th Ed\ -> ition\"\n\t\"PWB 1.0\"\n\t\"5th Edition\" -> \"PWB 1.0\"\n\tLSX\n\t\"6th Editi\ -> on\" -> LSX\n\t\"1 BSD\"\n\t\"6th Edition\" -> \"1 BSD\"\n\t\"Mini Unix\"\n\t\ -> \"6th Edition\" -> \"Mini Unix\"\n\tWollongong\n\t\"6th Edition\" -> Wollongon\ -> g\n\tInterdata\n\t\"6th Edition\" -> Interdata\n\t\"Unix/TS 3.0\"\n\t\"Unix/TS\ -> 3.0\" -> Interdata\n\t\"PWB 2.0\"\n\tInterdata -> \"PWB 2.0\"\n\t\"7th Editio\ -> n\"\n\tInterdata -> \"7th Edition\"\n\t\"8th Edition\"\n\t\"7th Edition\" -> \ -> \"8th Edition\"\n\t\"32V\"\n\t\"7th Edition\" -> \"32V\"\n\tV7M\n\t\"7th Editi\ -> on\" -> V7M\n\t\"Ultrix-11\"\n\t\"7th Edition\" -> \"Ultrix-11\"\n\tXenix\n\t\ -> \"7th Edition\" -> Xenix\n\t\"UniPlus+\"\n\t\"7th Edition\" -> \"UniPlus+\"\n\ -> \tV7M -> \"Ultrix-11\"\n\t\"9th Edition\"\n\t\"8th Edition\" -> \"9th Edition\ -> \"\n\t\"2 BSD\"\n\t\"1 BSD\" -> \"2 BSD\"\n\t\"2.8 BSD\"\n\t\"2 BSD\" -> \"2.8\ -> BSD\"\n\t\"2.8 BSD\" -> \"Ultrix-11\"\n\t\"2.9 BSD\"\n\t\"2.8 BSD\" -> \"2.9 \ -> BSD\"\n\t\"3 BSD\"\n\t\"32V\" -> \"3 BSD\"\n\t\"4 BSD\"\n\t\"3 BSD\" -> \"4 BS\ -> D\"\n\t\"4.1 BSD\"\n\t\"4 BSD\" -> \"4.1 BSD\"\n\t\"4.2 BSD\"\n\t\"4.1 BSD\" -\ -> > \"4.2 BSD\"\n\t\"4.1 BSD\" -> \"2.8 BSD\"\n\t\"4.1 BSD\" -> \"8th Edition\"\ -> \n\t\"4.3 BSD\"\n\t\"4.2 BSD\" -> \"4.3 BSD\"\n\t\"Ultrix-32\"\n\t\"4.2 BSD\" \ -> -> \"Ultrix-32\"\n\t\"PWB 1.2\"\n\t\"PWB 1.0\" -> \"PWB 1.2\"\n\t\"USG 1.0\"\n\ -> \t\"PWB 1.0\" -> \"USG 1.0\"\n\t\"PWB 1.2\" -> \"PWB 2.0\"\n\t\"CB Unix 1\"\n\ -> \t\"USG 1.0\" -> \"CB Unix 1\"\n\t\"USG 2.0\"\n\t\"USG 1.0\" -> \"USG 2.0\"\n\ -> \t\"CB Unix 2\"\n\t\"CB Unix 1\" -> \"CB Unix 2\"\n\t\"CB Unix 3\"\n\t\"CB Uni\ -> x 2\" -> \"CB Unix 3\"\n\t\"Unix/TS++\"\n\t\"CB Unix 3\" -> \"Unix/TS++\"\n\t\ -> \"PDP-11 Sys V\"\n\t\"CB Unix 3\" -> \"PDP-11 Sys V\"\n\t\"USG 3.0\"\n\t\"USG \ -> 2.0\" -> \"USG 3.0\"\n\t\"USG 3.0\" -> \"Unix/TS 3.0\"\n\t\"PWB 2.0\" -> \"Uni\ -> x/TS 3.0\"\n\t\"Unix/TS 1.0\"\n\t\"Unix/TS 1.0\" -> \"Unix/TS 3.0\"\n\t\"TS 4.\ -> 0\"\n\t\"Unix/TS 3.0\" -> \"TS 4.0\"\n\t\"Unix/TS++\" -> \"TS 4.0\"\n\t\"CB Un\ -> ix 3\" -> \"TS 4.0\"\n\t\"System V.0\"\n\t\"TS 4.0\" -> \"System V.0\"\n\t\"Sy\ -> stem V.2\"\n\t\"System V.0\" -> \"System V.2\"\n\t\"System V.3\"\n\t\"System V\ -> .2\" -> \"System V.3\"\n}\n"; +> "//dot\ndigraph unix {\nnode [color=\"lightblue2\", size=\"6,6\", style=\"fil\ +> led\"]\n\t\"5th Edition\"\n\t\"6th Edition\"\n\t\"5th Edition\" -> \"6th Editi\ +> on\"\n\t\"PWB 1.0\"\n\t\"5th Edition\" -> \"PWB 1.0\"\n\tLSX\n\t\"6th Edition\ +> \" -> LSX\n\t\"1 BSD\"\n\t\"6th Edition\" -> \"1 BSD\"\n\t\"Mini Unix\"\n\t\"6\ +> th Edition\" -> \"Mini Unix\"\n\tWollongong\n\t\"6th Edition\" -> Wollongong\n\ +> \tInterdata\n\t\"6th Edition\" -> Interdata\n\t\"Unix/TS 3.0\"\n\t\"Unix/TS 3.\ +> 0\" -> Interdata\n\t\"PWB 2.0\"\n\tInterdata -> \"PWB 2.0\"\n\t\"7th Edition\"\ +> \n\tInterdata -> \"7th Edition\"\n\t\"8th Edition\"\n\t\"7th Edition\" -> \"8t\ +> h Edition\"\n\t\"32V\"\n\t\"7th Edition\" -> \"32V\"\n\tV7M\n\t\"7th Edition\"\ +> -> V7M\n\t\"Ultrix-11\"\n\t\"7th Edition\" -> \"Ultrix-11\"\n\tXenix\n\t\"7th\ +> Edition\" -> Xenix\n\t\"UniPlus+\"\n\t\"7th Edition\" -> \"UniPlus+\"\n\tV7M \ +> -> \"Ultrix-11\"\n\t\"9th Edition\"\n\t\"8th Edition\" -> \"9th Edition\"\n\t\ +> \"2 BSD\"\n\t\"1 BSD\" -> \"2 BSD\"\n\t\"2.8 BSD\"\n\t\"2 BSD\" -> \"2.8 BSD\"\ +> \n\t\"2.8 BSD\" -> \"Ultrix-11\"\n\t\"2.9 BSD\"\n\t\"2.8 BSD\" -> \"2.9 BSD\"\ +> \n\t\"3 BSD\"\n\t\"32V\" -> \"3 BSD\"\n\t\"4 BSD\"\n\t\"3 BSD\" -> \"4 BSD\"\n\ +> \t\"4.1 BSD\"\n\t\"4 BSD\" -> \"4.1 BSD\"\n\t\"4.2 BSD\"\n\t\"4.1 BSD\" -> \"4\ +> .2 BSD\"\n\t\"4.1 BSD\" -> \"2.8 BSD\"\n\t\"4.1 BSD\" -> \"8th Edition\"\n\t\"\ +> 4.3 BSD\"\n\t\"4.2 BSD\" -> \"4.3 BSD\"\n\t\"Ultrix-32\"\n\t\"4.2 BSD\" -> \"U\ +> ltrix-32\"\n\t\"PWB 1.2\"\n\t\"PWB 1.0\" -> \"PWB 1.2\"\n\t\"USG 1.0\"\n\t\"PW\ +> B 1.0\" -> \"USG 1.0\"\n\t\"PWB 1.2\" -> \"PWB 2.0\"\n\t\"CB Unix 1\"\n\t\"USG\ +> 1.0\" -> \"CB Unix 1\"\n\t\"USG 2.0\"\n\t\"USG 1.0\" -> \"USG 2.0\"\n\t\"CB U\ +> nix 2\"\n\t\"CB Unix 1\" -> \"CB Unix 2\"\n\t\"CB Unix 3\"\n\t\"CB Unix 2\" ->\ +> \"CB Unix 3\"\n\t\"Unix/TS++\"\n\t\"CB Unix 3\" -> \"Unix/TS++\"\n\t\"PDP-11 \ +> Sys V\"\n\t\"CB Unix 3\" -> \"PDP-11 Sys V\"\n\t\"USG 3.0\"\n\t\"USG 2.0\" -> \ +> \"USG 3.0\"\n\t\"USG 3.0\" -> \"Unix/TS 3.0\"\n\t\"PWB 2.0\" -> \"Unix/TS 3.0\ +> \"\n\t\"Unix/TS 1.0\"\n\t\"Unix/TS 1.0\" -> \"Unix/TS 3.0\"\n\t\"TS 4.0\"\n\t\ +> \"Unix/TS 3.0\" -> \"TS 4.0\"\n\t\"Unix/TS++\" -> \"TS 4.0\"\n\t\"CB Unix 3\" \ +> -> \"TS 4.0\"\n\t\"System V.0\"\n\t\"TS 4.0\" -> \"System V.0\"\n\t\"System V.\ +> 2\"\n\t\"System V.0\" -> \"System V.2\"\n\t\"System V.3\"\n\t\"System V.2\" ->\ +> \"System V.3\"\n}\n"; #I invalid node name 5th Edition using "5th Edition" instead #I invalid node name 6th Edition using "6th Edition" instead #I invalid node name 5th Edition using "5th Edition" instead diff --git a/tst/graph.tst b/tst/graph.tst index 02ec5cf..c8a36b2 100644 --- a/tst/graph.tst +++ b/tst/graph.tst @@ -182,14 +182,14 @@ gap> GraphvizSetName(g, "test"); gap> g := GraphvizGraph();; gap> GraphvizSetAttr(g, "color", "red");; gap> GraphvizAttrs(g); -[ "color=red" ] +rec( edge := rec( ), graph := rec( color := "red" ), node := rec( ) ) # Test stringify attributes graph gap> g := GraphvizGraph();; gap> GraphvizSetAttr(g, "color", "red");; gap> GraphvizSetAttr(g, "color", "blue");; gap> AsString(g); -"//dot\ngraph {\n\tcolor=blue \n}\n" +"//dot\ngraph {\ngraph [color=\"blue\"]\n}\n" # # Test removing attributes from a graph TODO uncomment or delete # gap> g := GraphvizGraph();; @@ -223,64 +223,64 @@ gap> GraphvizNode(g, ["a"]); gap> g := GraphvizGraph();; gap> GraphvizSetAttr(g, "label", "test");; gap> GraphvizAttrs(g); -[ "label=test" ] +rec( edge := rec( ), graph := rec( label := "test" ), node := rec( ) ) gap> GraphvizSetAttr(g, 1, 2); gap> GraphvizAttrs(g); -[ "label=test", "1=2" ] +rec( edge := rec( ), graph := rec( 1 := "2", label := "test" ), + node := rec( ) ) gap> GraphvizRemoveAttr(g, "label=tes"); -Error, the 2nd argument (attribute name or attribute) "label=tes" is not set o\ -n the provided object. +Error, the 2nd argument (attribute name) "label=tes" is not defined gap> GraphvizAttrs(g); -[ "label=test", "1=2" ] -gap> GraphvizRemoveAttr(g, "1=2"); +rec( edge := rec( ), graph := rec( 1 := "2", label := "test" ), + node := rec( ) ) +gap> GraphvizRemoveAttr(g, 1); gap> GraphvizAttrs(g); -[ "label=test" ] +rec( edge := rec( ), graph := rec( label := "test" ), node := rec( ) ) gap> GraphvizSetAttr(g, 1, 2);; gap> GraphvizAttrs(g); -[ "label=test", "1=2" ] +rec( edge := rec( ), graph := rec( 1 := "2", label := "test" ), + node := rec( ) ) gap> GraphvizRemoveAttr(g, "1"); gap> GraphvizAttrs(g); -[ "label=test" ] +rec( edge := rec( ), graph := rec( label := "test" ), node := rec( ) ) gap> GraphvizRemoveAttr(g, "label");; gap> GraphvizAttrs(g); -[ ] +rec( edge := rec( ), graph := rec( ), node := rec( ) ) gap> GraphvizSetAttr(g, "label", "test");; gap> GraphvizAttrs(g); -[ "label=test" ] -gap> GraphvizRemoveAttr(g, "label=test");; +rec( edge := rec( ), graph := rec( label := "test" ), node := rec( ) ) +gap> GraphvizRemoveAttr(g, "label");; gap> GraphvizAttrs(g); -[ ] +rec( edge := rec( ), graph := rec( ), node := rec( ) ) # Test set color (graph) gap> g := GraphvizGraph();; gap> GraphvizSetAttr(g, "color", "red");; gap> GraphvizAttrs(g); -[ "color=red" ] +rec( edge := rec( ), graph := rec( color := "red" ), node := rec( ) ) # Test removing attributes which do not exist gap> g := GraphvizGraph();; gap> GraphvizRemoveAttr(g, "test"); -Error, the 2nd argument (attribute name or attribute) "test" is not set on the\ - provided object. +Error, the 2nd argument (attribute name) "test" is not defined gap> n := GraphvizAddNode(g, "a");; gap> GraphvizRemoveAttr(n, "test"); -Error, the 2nd argument (attribute name) "test" is not set on the provided obj\ -ect. +Error, the 2nd argument (attribute name) "test" is not defined # Test overwriting attributes removes them gap> g := GraphvizGraph();; gap> GraphvizSetAttr(g, "color", "red");; gap> GraphvizAttrs(g); -[ "color=red" ] +rec( edge := rec( ), graph := rec( color := "red" ), node := rec( ) ) gap> GraphvizSetAttr(g, "color", "blue");; gap> GraphvizAttrs(g); -[ "color=blue" ] -gap> GraphvizSetAttr(g, "color=green");; +rec( edge := rec( ), graph := rec( color := "blue" ), node := rec( ) ) +gap> GraphvizSetAttrs(g, rec(color := "green"));; gap> GraphvizAttrs(g); -[ "color=green" ] +rec( edge := rec( ), graph := rec( color := "green" ), node := rec( ) ) # gap> STOP_TEST("graphviz package: graph.tst", 0); diff --git a/tst/graphvizforgap01.tst b/tst/graphvizforgap01.tst index b06ca3b..14e47e3 100644 --- a/tst/graphvizforgap01.tst +++ b/tst/graphvizforgap01.tst @@ -10,7 +10,7 @@ # gap> START_TEST("graphvizforgap01.tst"); -# gap/dot.gd:219-230 +# doc/_Chapter_Full_Reference.xml:78-89 gap> gv := GraphvizGraph("GraphyMcGraphFace"); gap> GraphvizName(gv); @@ -22,7 +22,7 @@ gap> gv := GraphvizGraph(); gap> GraphvizName(gv); "" -# gap/dot.gd:258-269 +# doc/_Chapter_Full_Reference.xml:131-142 gap> gv := GraphvizDigraph("GraphyMcGraphFace"); gap> GraphvizName(gv); @@ -34,7 +34,7 @@ gap> gv := GraphvizDigraph(); gap> GraphvizName(gv); "" -# gap/dot.gd:284-295 +# doc/_Chapter_Full_Reference.xml:167-178 gap> dot := GraphvizDigraph("The Round Table");; gap> GraphvizName(dot); "The Round Table" @@ -46,55 +46,103 @@ gap> e := GraphvizAddEdge(dot, "A", "B");; gap> GraphvizName(e); "(A, B)" -# gap/dot.gd:320-321 +# doc/_Chapter_Full_Reference.xml:191-192 -# gap/dot.gd:327-328 +# doc/_Chapter_Full_Reference.xml:211-212 -# gap/dot.gd:335-336 +# doc/_Chapter_Full_Reference.xml:226-227 -# gap/dot.gd:346-347 +# doc/_Chapter_Full_Reference.xml:240-241 -# gap/dot.gd:358-359 +# doc/_Chapter_Full_Reference.xml:255-256 -# gap/dot.gd:372-373 +# doc/_Chapter_Full_Reference.xml:272-273 -# gap/dot.gd:379-380 +# doc/_Chapter_Full_Reference.xml:290-297 +gap> gv := GraphvizGraph();; +gap> GraphvizAddEdge(gv, "a", "b");; +gap> GraphvizEdges(gv); +[ ] +gap> GraphvizEdges(gv, "a", "b"); +[ ] -# gap/dot.gd:392-393 +# doc/_Chapter_Full_Reference.xml:311-317 +gap> gv := GraphvizGraph();; +gap> e := GraphvizAddEdge(gv, "a", "b"); + +gap> GraphvizHead(e); + -# gap/dot.gd:401-402 +# doc/_Chapter_Full_Reference.xml:330-336 +gap> gv := GraphvizGraph();; +gap> e := GraphvizAddEdge(gv, "a", "b"); + +gap> GraphvizTail(e); + -# gap/dot.gd:420-421 +# doc/_Chapter_Full_Reference.xml:358-363 +gap> gv := GraphvizGraph(); + +gap> GraphvizSetName(gv, "newname"); + -# gap/dot.gd:433-434 +# doc/_Chapter_Full_Reference.xml:379-386 +gap> gv := GraphvizGraph(); + +gap> GraphvizAddNode(gv, "a"); + +gap> gv; + -# gap/dot.gd:457-458 +# doc/_Chapter_Full_Reference.xml:408-415 +gap> gv := GraphvizGraph(); + +gap> GraphvizAddEdge(gv, "a", "b"); + +gap> gv; + + +# doc/_Chapter_Full_Reference.xml:433-434 -# gap/dot.gd:476-477 +# doc/_Chapter_Full_Reference.xml:461-462 + +# doc/_Chapter_Full_Reference.xml:481-488 +gap> gv := GraphvizGraph();; +gap> GraphvizAddNode(gv, "a");; +gap> gv; + +gap> GraphvizRemoveNode(gv, "a"); + -# gap/dot.gd:484-485 +# doc/_Chapter_Full_Reference.xml:501-502 -# gap/dot.gd:494-495 +# doc/_Chapter_Full_Reference.xml:517-524 +gap> gv := GraphvizGraph();; +gap> GraphvizAddEdge(gv, "a", "b");; +gap> gv; + +gap> GraphvizRemoveEdges(gv, "a", "b"); + -# gap/dot.gd:511-512 +# doc/_Chapter_Full_Reference.xml:547-548 -# gap/dot.gd:526-527 +# doc/_Chapter_Full_Reference.xml:566-567 -# gap/dot.gd:534-535 +# doc/_Chapter_Full_Reference.xml:582-583 -# gap/dot.gd:543-544 +# doc/_Chapter_Full_Reference.xml:599-600 -# gap/dot.gd:554-555 +# doc/_Chapter_Full_Reference.xml:619-620 -# gap/dot.gd:567-568 +# doc/_Chapter_Full_Reference.xml:634-635 -# gap/dot.gd:578-579 +# doc/_Chapter_Full_Reference.xml:750-751 -# gap/dot.gd:588-589 +# doc/_Chapter_Full_Reference.xml:768-769 -# gap/dot.gd:600-601 +# doc/_Chapter_Full_Reference.xml:784-785 -# gap/dot.gd:611-612 +# doc/_Chapter_Full_Reference.xml:798-799 # gap> STOP_TEST("graphvizforgap01.tst", 1); diff --git a/tst/subgraph.tst b/tst/subgraph.tst index fa74c7d..e2ca8ba 100644 --- a/tst/subgraph.tst +++ b/tst/subgraph.tst @@ -147,44 +147,44 @@ gap> g := GraphvizDigraph();; gap> s := GraphvizAddSubgraph(g, "a");; gap> GraphvizAddEdge(g, "x", "y");; gap> GraphvizSetAttr(s, "color", "red");; -gap> GraphvizSetAttr(s, "node [color=red]");; -gap> GraphvizSetAttr(s, "edge [color=red]");; +gap> GraphvizSetAttrs(s, rec(node := rec(color := "red")));; +gap> GraphvizSetAttrs(s, rec(edge := rec(color := "red")));; gap> AsString(g); -"//dot\ndigraph {\nsubgraph a {\n\tcolor=red node [color=red] edge [color=red\ -] \n}\n\tx\n\ty\n\tx -> y\n}\n" +"//dot\ndigraph {\nsubgraph a {\ngraph [color=\"red\"]\nnode [color=\"red\"\ +]\nedge [color=\"red\"]\n}\n\tx\n\ty\n\tx -> y\n}\n" # Test stringifying subgraph graph gap> g := GraphvizGraph();; gap> s := GraphvizAddSubgraph(g, "a");; gap> GraphvizAddEdge(g, "x", "y");; gap> GraphvizSetAttr(s, "color", "red");; -gap> GraphvizSetAttr(s, "node [color=red]");; -gap> GraphvizSetAttr(s, "edge [color=red]");; +gap> GraphvizSetAttrs(s, rec(node := rec(color := "red")));; +gap> GraphvizSetAttrs(s, rec(edge := rec(color := "red")));; gap> AsString(g); -"//dot\ngraph {\nsubgraph a {\n\tcolor=red node [color=red] edge [color=red] \ -\n}\n\tx\n\ty\n\tx -- y\n}\n" +"//dot\ngraph {\nsubgraph a {\ngraph [color=\"red\"]\nnode [color=\"red\"]\ +\nedge [color=\"red\"]\n}\n\tx\n\ty\n\tx -- y\n}\n" # Test stringifying subgraph context (graph) gap> g := GraphvizGraph();; gap> s := GraphvizAddContext(g, "a");; gap> GraphvizAddEdge(g, "x", "y");; gap> GraphvizSetAttr(s, "color", "red");; -gap> GraphvizSetAttr(s, "node [color=red]");; -gap> GraphvizSetAttr(s, "edge [color=red]");; +gap> GraphvizSetAttrs(s, rec(node := rec(color := "red")));; +gap> GraphvizSetAttrs(s, rec(edge := rec(color := "red")));; gap> AsString(g); -"//dot\ngraph {\n// a context \n{\n\tcolor=red node [color=red] edge [color=r\ -ed] \n}\n\tx\n\ty\n\tx -- y\n}\n" +"//dot\ngraph {\n// a context \n{\ngraph [color=\"red\"]\nnode [color=\"red\ +\"]\nedge [color=\"red\"]\n}\n\tx\n\ty\n\tx -- y\n}\n" # Test stringifying subgraph context (digraph) gap> g := GraphvizDigraph();; gap> s := GraphvizAddContext(g, "a");; gap> GraphvizAddEdge(g, "x", "y");; gap> GraphvizSetAttr(s, "color", "red");; -gap> GraphvizSetAttr(s, "node [color=red]");; -gap> GraphvizSetAttr(s, "edge [color=red]");; +gap> GraphvizSetAttrs(s, rec(node := rec(color := "red")));; +gap> GraphvizSetAttrs(s, rec(edge := rec(color := "red")));; gap> AsString(g); -"//dot\ndigraph {\n// a context \n{\n\tcolor=red node [color=red] edge [color\ -=red] \n}\n\tx\n\ty\n\tx -> y\n}\n" +"//dot\ndigraph {\n// a context \n{\ngraph [color=\"red\"]\nnode [color=\"r\ +ed\"]\nedge [color=\"red\"]\n}\n\tx\n\ty\n\tx -> y\n}\n" # Test stringifying subgraph w/o name gap> g := GraphvizDigraph();; @@ -254,14 +254,14 @@ rec( c := ) gap> g := GraphvizDigraph();; gap> ctx := GraphvizAddContext(g);; gap> GraphvizSetAttr(g, "color", "green");; -gap> GraphvizSetAttr(g, "edge [label=testing123]");; -gap> GraphvizSetAttr(g, "node[color=blue]");; -gap> GraphvizSetAttr(g, "edge[color=blue]");; -gap> GraphvizSetAttr(ctx, "node[color=red]");; +gap> GraphvizSetAttrs(g, rec(node := rec(color := "blue"), +> edge := rec(label := "testing123", color := "blue")));; +gap> GraphvizSetAttrs(ctx, rec(node := rec(color := "red")));; gap> GraphvizAddNode(ctx, "a");; gap> AsString(g); -"//dot\ndigraph {\n\tcolor=green edge [label=testing123] node[color=blue] edg\ -e[color=blue] \n// no_name_1 context \n{\n\tnode[color=red] \n\ta\n}\n}\n" +"//dot\ndigraph {\ngraph [color=\"green\"]\nnode [color=\"blue\"]\nedge [c\ +olor=\"blue\", label=\"testing123\"]\n// no_name_1 context \n{\nnode [color=\ +\"red\"]\n\ta\n}\n}\n" # Test adding subgraphs with the same name gap> g := GraphvizDigraph();; @@ -402,25 +402,25 @@ true # Test a context containing a subgraph gap> gv := GraphvizGraph("context+subgraph");; -gap> GraphvizSetAttr(gv, "node [shape=\"box\"]"); +gap> GraphvizSetAttrs(gv, rec(node := rec(shape := "box"))); gap> legend := GraphvizAddContext(gv, "legend"); -gap> GraphvizSetAttr(legend, "node [shape=plaintext]"); +gap> GraphvizSetAttrs(legend, rec(node := rec(shape := "plaintext"))); gap> GraphvizAddSubgraph(legend, "legend"); gap> AsString(gv); -"//dot\ngraph context+subgraph {\n\tnode [shape=\"box\"] \n// legend context \ -\n{\n\tnode [shape=plaintext] \nsubgraph legend {\n}\n}\n}\n" +"//dot\ngraph context+subgraph {\nnode [shape=\"box\"]\n// legend context \n{\ +\nnode [shape=\"plaintext\"]\nsubgraph legend {\n}\n}\n}\n" # Test a context containing a subdigraph gap> gv := GraphvizDigraph("context+subgraph");; -gap> GraphvizSetAttr(gv, "node [shape=\"box\"]"); +gap> GraphvizSetAttrs(gv, rec(node := rec(shape := "box"))); gap> legend := GraphvizAddContext(gv, "legend"); -gap> GraphvizSetAttr(legend, "node [shape=plaintext]"); +gap> GraphvizSetAttrs(legend, rec(node := rec(shape := "plaintext"))); gap> GraphvizAddSubgraph(legend, "legend");