gographviz
gographviz copied to clipboard
How to define default attributes for node, edge, or graph
Hi, all.
I am trying to use the node, edge, and graph statement from the Lexical and Semantic Notes. However, since this library always sorts and prints nodes, the order is changed. How can I always define it first?
Output:
digraph G {
rank=LR;
Hello->World[ headlabel="head", taillabel="tail" ];
Hello->World:f0;
Hello->World:f1;
Hello->World:f2;
Hello [ label="Hi\nStart", shape=Mrecord ];
World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
node [ shape=Mrecord ];
}
You can see that the node line is defined last.
Expected:
digraph G {
node [ shape=Mrecord ]; <-------------- This line
rank=LR;
Hello->World[ headlabel="head", taillabel="tail" ];
Hello->World:f0;
Hello->World:f1;
Hello->World:f2;
Hello [ label="Hi\nStart", shape=Mrecord ];
World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
}
Only when defined like this, the output I want is completed.
Looking at the source code, there seem to be no solutions. For now, is the only way to add properties to each node?
...
go 1.14
require github.com/awalterschulze/gographviz v2.0.1+incompatible
...
I tried to create this test in analysewrite_test.go
func TestOrder(t *testing.T) {
input := `digraph G {
node [ shape=Mrecord ];
rank=LR;
Hello->World[ headlabel="head", taillabel="tail" ];
Hello->World:f0;
Hello->World:f1;
Hello->World:f2;
Hello [ label="Hi\nStart" ];
World [ label="<f0>one|<f1>two|<f2>three" ];
}`
g, err := parser.ParseString(input)
if err != nil {
t.Fatal(err)
}
t.Logf("Parsed: %v\n", g)
}
It prints out node is the right position, but if I move the node to the bottom it stays at the bottom too.
If you add
ag := NewGraph()
if err := Analyse(g, ag); err != nil {
t.Fatal(err)
}
t.Logf("Analysed: %v\n", ag)
agstr := ag.String()
t.Logf("Written: %v\n", agstr)
Then the node
's properties are applied to all the appropriate nodes
Hello [ label="Hi\nStart", shape=Mrecord ];
World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
So I don't think I understand the problem. Is it possible rephrase it as a test?
Here is my code
package main
import (
"fmt"
"github.com/awalterschulze/gographviz"
)
func main() {
g := gographviz.NewGraph()
g.SetName("G")
g.SetDir(true)
g.AddAttr("G", "rank", "LR")
// This node is ignored.
g.AddNode("G", "node", map[string]string{
"shape": "record",
})
g.AddNode("G", "Hello", map[string]string{
"label": fmt.Sprintf("%q", "Hi\nStart"),
"shape": "Mrecord",
})
g.AddNode("G", "node", map[string]string{
"shape": "Mrecord",
})
g.AddNode("G", "World", map[string]string{
"label": fmt.Sprintf("%q", "<f0>one|<f1>two|<f2>three"),
"shape": "Mrecord",
})
g.AddPortEdge("Hello", "", "World", "", true, map[string]string{
"headlabel": fmt.Sprintf("%q", "head"),
"taillabel": fmt.Sprintf("%q", "tail"),
})
g.AddPortEdge("Hello", "", "World", "f0", true, nil)
g.AddPortEdge("Hello", "", "World", "f1", true, nil)
g.AddPortEdge("Hello", "", "World", "f2", true, nil)
fmt.Println(g.String())
}
Result:
digraph G {
rank=LR;
Hello->World[ headlabel="head", taillabel="tail" ];
Hello->World:f0;
Hello->World:f1;
Hello->World:f2;
Hello [ label="Hi\nStart", shape=Mrecord ];
World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
node [ shape=Mrecord ];
}
I am using this library in my network management program. Therefore, several default nodes can be added to the graph in the program logic.
In an effort to keep the API smaller, the default node, edge and graph attrs are hidden away and get applied to the nodes, edges and graphs for you, during analyses of the parsed graph, see here: https://github.com/awalterschulze/gographviz/blob/master/analyse.go#L118
So this call will treat "node" as a normal node, named node, instead of a keyword.
g.AddNode("G", "node", map[string]string{
"shape": "record",
})
To keep track of default node attrs, I would save them in a map as they come in and apply them to each each node.
Another option is to create your own graph API, that can write to straight to the ast
package.
I am sorry that I can't be of more help here.