I use graphviz to draw a diagram.
The placement of the nodes are not ideal. I would like the six nodes to be roughly placed in a 2 by 3 table:
file_in stdin_in string_in
file_out stdout_out variable_out
I have tried to add weights to some edges but still fails to move the nodes into such a table. See my dot program below. Thanks.
digraph G {
/* directly betw inputs */
node [color=black]
string_in -> stdin_in [label="redirection"];
file_in -> stdin_in [label="redirection"];
stdin_in -> file_in [label="device file /dev/stdin, or arg -", weight=8];
stdin_in -> string_in [label="xargs"];
/* directly betw outputs */
node [color=red]
edge [color=red]
stdout_out -> file_out [label="redirection" fontcolor="red"];
file_out -> stdout_out [label="/dev/stdout or arg -" fontcolor="red"];
/* directly from input to output */
edge [color=blue]
stdin_in -> stdout_out [label="cat or tee" fontcolor="blue" weight=8];
stdin_in -> file_out [label = "tee > /dev/null" fontcolor = "blue"];
string_in -> stdout_out [label="echo -n" fontcolor="blue" weight=2];
file_in -> stdout_out [label="cat" fontcolor="blue"];
file_in -> file_out [label="none" fontcolor="blue"];
string_in -> variable_out [label="assignment" fontcolor="blue"];
/* directly from output to input */
edge [color=green]
stdout_out -> stdin_in [label="pipe" fontcolor="green"];
stdout_out -> file_in [label="process substitution" fontcolor="green"];
stdout_out -> string_in [label="command substitution" fontcolor="green"];
file_out -> file_in [label="none" fontcolor="green"];
variable_out -> string_in [label="parameter expansion" fontcolor="green"];
}
The key point here is using rank = same
; I have added this instruction at the top of your code. I have also increased the distance between the two rank levels so that there is more space for the edge labels. I have also changed the weights you had given to the edges in order to have a matrix like appearance.
Two more things I would recommend:
- rather than the HTML-like syntax for the node, use the standard graphviz format; matter of taste, but I find it easier to read and it is more flexible, see (How shall escape `>` in an edge label?),
- when creating edges from nodes lower in the hierarchy to higher ones, don't use
b->a
, rather write a->b[dir="back"]
; this avoids graphviz getting confused when the number of nodes increases
I have not completely edited the file, as it is not strictly necessary for the two items just mentioned - here the job I have done:
digraph G {
# layout
ranksep = 2
{ rank = same; file_in stdin_in string_in }
{ rank = same; file_out stdout_out variable_out }
/* directly betw inputs */
node [color=black]
string_in -> stdin_in [label="redirection"];
file_in -> stdin_in [label="redirection"];
stdin_in -> file_in [label="device file /dev/stdin, or arg -"]
stdin_in -> string_in [label="xargs"];
/* directly betw outputs */
node [color=red]
edge [color=red]
stdout_out -> file_out [label=<<font color="red">redirection</font>>];
file_out -> stdout_out [label=<<font color="red">/dev/stdout or arg -</font>>];
/* directly from input to output */
edge [color=blue]
stdin_in -> stdout_out [label=<<font color="blue">cat or tee</font>> weight = 10];
# stdin_in -> file_out [label=<<font color="blue">tee /dev/null</font>>];
stdin_in -> file_out[ label = "tee > /dev/null" fontcolor = "blue" ];
string_in -> stdout_out [label=<<font color="blue">echo -n</font>> ];
file_in -> stdout_out [label=<<font color="blue">cat</font>> ];
file_in -> file_out [label = "none" fontcolor = "blue" weight = 10];
string_in -> variable_out [label = "assignment" fontcolor = "blue" weight = 10 ];
/* directly from output to input */
edge [color=green]
stdout_out -> stdin_in [label=<<font color="green">pipe</font>>];
stdout_out -> file_in [label=<<font color="green">process substitution</font>>];
stdout_out -> string_in [label=<<font color="green">command substitution</font>>];
file_in -> file_out [label="none" fontcolor="green" dir = back ];
variable_out -> string_in [label=<<font color="green">parameter expansion</font>>];
}
which gives you