GraphvizR 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +7 -1
- data/README.txt +7 -3
- data/lib/graphviz_r.rb +78 -17
- data/test/test_graphviz_r.rb +107 -44
- metadata +2 -2
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
GraphvizR
|
1
|
+
= GraphvizR
|
2
2
|
by ANDO Yasushi
|
3
3
|
http://blog.technohippy.net
|
4
4
|
|
@@ -39,9 +39,13 @@ replies the dot code:
|
|
39
39
|
|
40
40
|
To know more detail, please see test/test_graphviz_r.rb
|
41
41
|
|
42
|
-
==
|
42
|
+
== DEPENDENCIES:
|
43
43
|
|
44
|
-
*
|
44
|
+
* Graphviz (http://www.graphviz.org/)
|
45
|
+
|
46
|
+
== TODO:
|
47
|
+
|
48
|
+
* rails plugin
|
45
49
|
|
46
50
|
== INSTALL:
|
47
51
|
|
data/lib/graphviz_r.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class GraphvizR
|
2
|
-
VERSION = '0.0
|
2
|
+
VERSION = '0.1.0'
|
3
|
+
INDENT_UNIT = ' '
|
3
4
|
|
4
5
|
class Attributes
|
5
6
|
def initialize(name, dot)
|
@@ -27,8 +28,18 @@ class GraphvizR
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def >>(node)
|
31
|
+
@dot.directed!
|
32
|
+
add_edge_on_dot node
|
33
|
+
end
|
34
|
+
|
35
|
+
def -(node)
|
36
|
+
@dot.undirected!
|
37
|
+
add_edge_on_dot node
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_edge_on_dot(node)
|
30
41
|
prop = @prop.merge node.prop
|
31
|
-
edge = Edge.new(self, node, prop)
|
42
|
+
edge = Edge.new(self, node, @dot, prop)
|
32
43
|
@dot.add_edge edge
|
33
44
|
edge
|
34
45
|
end
|
@@ -51,14 +62,14 @@ class GraphvizR
|
|
51
62
|
name = @port.dup
|
52
63
|
name.unshift @name
|
53
64
|
name.map{|e| e.to_dot}.join(':')
|
54
|
-
#@name.to_dot
|
55
65
|
end
|
56
66
|
end
|
57
67
|
|
58
68
|
class Edge
|
59
|
-
def initialize(from, to, prop={})
|
69
|
+
def initialize(from, to, dot, prop={})
|
60
70
|
@from = from
|
61
71
|
@to = to
|
72
|
+
@dot = dot
|
62
73
|
@property = prop
|
63
74
|
end
|
64
75
|
|
@@ -71,7 +82,7 @@ class GraphvizR
|
|
71
82
|
end
|
72
83
|
|
73
84
|
def to_dot
|
74
|
-
dot = "#{node_to_dot @from} -> #{node_to_dot @to}"
|
85
|
+
dot = "#{node_to_dot @from} #{@dot.directed? ? '->' : '--'} #{node_to_dot @to}"
|
75
86
|
dot += " #{@property.to_dot}" unless @property.empty?
|
76
87
|
dot
|
77
88
|
end
|
@@ -85,7 +96,7 @@ class GraphvizR
|
|
85
96
|
GraphvizR.new(name, prop).to_dot
|
86
97
|
end
|
87
98
|
|
88
|
-
def initialize(name, prop={},
|
99
|
+
def initialize(name, prop={}, parent=nil, indent=0)
|
89
100
|
if name.is_a? Array
|
90
101
|
initialize(*name)
|
91
102
|
else
|
@@ -95,7 +106,9 @@ class GraphvizR
|
|
95
106
|
@node_properties = {}
|
96
107
|
@graph_properties = {}
|
97
108
|
@subgraphs = []
|
98
|
-
@
|
109
|
+
@indent = indent + 1
|
110
|
+
@parent = parent
|
111
|
+
@directed = true
|
99
112
|
interprete prop
|
100
113
|
end
|
101
114
|
end
|
@@ -128,24 +141,60 @@ class GraphvizR
|
|
128
141
|
f = from.keys[0]
|
129
142
|
t = from[f]
|
130
143
|
p = to
|
131
|
-
@edges << Edge.new(f, t, p)
|
144
|
+
@edges << Edge.new(f, t, self, p)
|
132
145
|
elsif to.nil?
|
133
146
|
# from is Edge instance
|
134
147
|
@edges << from
|
135
148
|
else
|
136
|
-
@edges << Edge.new(from, to)
|
149
|
+
@edges << Edge.new(from, to, self)
|
137
150
|
end
|
138
151
|
end
|
139
152
|
|
140
153
|
def add_subgraph(graphs)
|
141
154
|
graphs.to_a.sort.each do |key_prop|
|
142
|
-
@subgraphs << self.class.new(key_prop[0], key_prop[1],
|
155
|
+
@subgraphs << self.class.new(key_prop[0], key_prop[1], self, @indent)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def subgraph?
|
160
|
+
not @parent.nil?
|
161
|
+
end
|
162
|
+
|
163
|
+
def directed!
|
164
|
+
if subgraph?
|
165
|
+
@parent.directed!
|
166
|
+
else
|
167
|
+
@directed = true
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def undirected!
|
172
|
+
if subgraph?
|
173
|
+
@parent.undirected!
|
174
|
+
else
|
175
|
+
@directed = false
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def directed?
|
180
|
+
if subgraph?
|
181
|
+
@parent.directed?
|
182
|
+
else
|
183
|
+
@directed
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def undirected?
|
188
|
+
if subgraph?
|
189
|
+
@parent.undirected?
|
190
|
+
else
|
191
|
+
!@directed
|
143
192
|
end
|
144
193
|
end
|
145
194
|
|
146
195
|
def [](key, *args, &block)
|
147
196
|
if block
|
148
|
-
subgraph = self.class.new
|
197
|
+
subgraph = self.class.new key, {}, self, @indent
|
149
198
|
block.call subgraph
|
150
199
|
@subgraphs << subgraph
|
151
200
|
else
|
@@ -176,16 +225,28 @@ class GraphvizR
|
|
176
225
|
end
|
177
226
|
|
178
227
|
def to_dot
|
179
|
-
|
180
|
-
|
181
|
-
|
228
|
+
graph_type = if subgraph?
|
229
|
+
'subgraph'
|
230
|
+
elsif directed?
|
231
|
+
'digraph'
|
232
|
+
else
|
233
|
+
'graph'
|
234
|
+
end
|
235
|
+
dot = indent_enter("#{graph_type} #{@name} {", true)
|
236
|
+
dot += indent_enter("graph #{@graph_properties.to_dot};") unless @graph_properties.empty?
|
237
|
+
#dot += indent_enter(@subgraphs.map{|e| e.to_dot}.join("\n")) unless @subgraphs.empty?
|
238
|
+
dot += @subgraphs.map{|e| e.to_dot}.join('') unless @subgraphs.empty?
|
182
239
|
dot += properties_to_dot(@default_node_properties) unless @default_node_properties.empty?
|
183
240
|
dot += properties_to_dot(@node_properties) unless @node_properties.empty?
|
184
|
-
dot += @edges.sort.map{|e| "#{e.to_dot};"}.join("
|
185
|
-
dot += "}"
|
241
|
+
dot += @edges.sort.map{|e| indent_enter("#{e.to_dot};")}.join("")
|
242
|
+
dot += indent_enter("}", true)
|
186
243
|
dot
|
187
244
|
end
|
188
245
|
|
246
|
+
def indent_enter(str, is_first=false)
|
247
|
+
"#{INDENT_UNIT * (@indent - (is_first ? 1 : 0))}#{str}\n"
|
248
|
+
end
|
249
|
+
|
189
250
|
def data(format='png')
|
190
251
|
gv = IO.popen "dot -q -T#{format || 'png'}", "w+"
|
191
252
|
gv.puts to_dot
|
@@ -216,7 +277,7 @@ class GraphvizR
|
|
216
277
|
protected
|
217
278
|
|
218
279
|
def properties_to_dot(hash)
|
219
|
-
hash.to_a.sort.map{|e| "#{e[0]} #{e[1].to_dot};"}.join(
|
280
|
+
hash.to_a.sort.map{|e| indent_enter "#{e[0]} #{e[1].to_dot};"}.join()
|
220
281
|
end
|
221
282
|
end
|
222
283
|
|
data/test/test_graphviz_r.rb
CHANGED
@@ -17,7 +17,7 @@ class TestGraphvizR < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_basic
|
20
|
-
|
20
|
+
gvr = GraphvizR.dot(:sample,
|
21
21
|
:graph => {:size => "1.5, 2.5"},
|
22
22
|
:label => 'example',
|
23
23
|
:node_properties => {
|
@@ -28,7 +28,8 @@ class TestGraphvizR < Test::Unit::TestCase
|
|
28
28
|
:beta => :delta,
|
29
29
|
:delta => 'size'
|
30
30
|
)
|
31
|
-
assert_equal <<-end_of_string.gsub(/\s/, ''),
|
31
|
+
#assert_equal <<-end_of_string.gsub(/\s/, ''), gvr.gsub(/\s/, '')
|
32
|
+
assert_equal <<-end_of_string, gvr
|
32
33
|
digraph sample {
|
33
34
|
graph [label = "example", size = "1.5, 2.5"];
|
34
35
|
beta [shape = box];
|
@@ -40,20 +41,20 @@ digraph sample {
|
|
40
41
|
end_of_string
|
41
42
|
end
|
42
43
|
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
44
|
+
#gvr.graph = {:label => 'example', :size => '1.5, 2.5'}
|
45
|
+
#gvr.beta = {:shape => :box}
|
46
|
+
#gvr.graph[:label => 'example', :size => '1.5, 2.5']
|
47
|
+
#gvr.beta[:shape => :box]
|
47
48
|
def test_basic_dynamic
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
(
|
53
|
-
(
|
54
|
-
|
55
|
-
|
56
|
-
assert_equal <<-end_of_string
|
49
|
+
gvr = GraphvizR.new 'sample'
|
50
|
+
gvr.graph [:label => 'example', :size => '1.5, 2.5']
|
51
|
+
gvr.beta [:shape => :box]
|
52
|
+
gvr.alpha >> gvr.beta
|
53
|
+
(gvr.alpha >> gvr.gamma) [:label => 'label1']
|
54
|
+
(gvr.beta >> gvr.delta) [:label => 'label2']
|
55
|
+
gvr.delta >> gvr[:size]
|
56
|
+
|
57
|
+
assert_equal <<-end_of_string, gvr.to_dot
|
57
58
|
digraph sample {
|
58
59
|
graph [label = "example", size = "1.5, 2.5"];
|
59
60
|
beta [shape = box];
|
@@ -66,7 +67,7 @@ digraph sample {
|
|
66
67
|
end
|
67
68
|
|
68
69
|
def test_record
|
69
|
-
|
70
|
+
gvr = GraphvizR.dot(:sample,
|
70
71
|
:graph => {:size => "1.5, 2.5"},
|
71
72
|
:node => {:shape => :record},
|
72
73
|
:node_properties => {
|
@@ -78,7 +79,8 @@ digraph sample {
|
|
78
79
|
:node2 => [:node1, :p_center],
|
79
80
|
{:node2 => [:node1, :p_right]} => {:label => 'record'}
|
80
81
|
)
|
81
|
-
assert_equal <<-end_of_string.gsub(/\s/, ''),
|
82
|
+
#assert_equal <<-end_of_string.gsub(/\s/, ''), gvr.gsub(/\s/, '')
|
83
|
+
assert_equal <<-end_of_string, gvr
|
82
84
|
digraph sample {
|
83
85
|
graph [size = "1.5, 2.5"];
|
84
86
|
node [shape = record];
|
@@ -92,22 +94,22 @@ digraph sample {
|
|
92
94
|
end_of_string
|
93
95
|
end
|
94
96
|
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#d
|
98
|
-
#
|
97
|
+
#gvr.size = '1.5, 2.5'
|
98
|
+
#gvr.node = {:shape => :record}
|
99
|
+
#d gvr.node1 = {:label => "<p_left> left|<p_center>center|<p_right> right"}
|
100
|
+
#gvr.node2 = {:label => "left|center|right"}
|
99
101
|
def test_record_dynamic
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
(
|
109
|
-
|
110
|
-
assert_equal <<-end_of_string
|
102
|
+
gvr = GraphvizR.new 'sample'
|
103
|
+
gvr.graph [:size => '1.5, 2.5']
|
104
|
+
gvr.node [:shape => :record]
|
105
|
+
gvr.node1 [:label => "<p_left> left|<p_center>center|<p_right> right"]
|
106
|
+
gvr.node2 [:label => "left|center|right"]
|
107
|
+
gvr.node1 >> gvr.node2
|
108
|
+
gvr.node1(:p_left) >> gvr.node2
|
109
|
+
gvr.node2 >> gvr.node1(:p_center)
|
110
|
+
(gvr.node2 >> gvr.node1(:p_right)) [:label => 'record']
|
111
|
+
|
112
|
+
assert_equal <<-end_of_string, gvr.to_dot
|
111
113
|
digraph sample {
|
112
114
|
graph [size = "1.5, 2.5"];
|
113
115
|
node [shape = record];
|
@@ -122,7 +124,7 @@ digraph sample {
|
|
122
124
|
end
|
123
125
|
|
124
126
|
def test_subgraph
|
125
|
-
|
127
|
+
gvr = GraphvizR.dot(:sample,
|
126
128
|
:subgraphs => {
|
127
129
|
:cluster0 => {
|
128
130
|
:color => :blue,
|
@@ -144,10 +146,11 @@ digraph sample {
|
|
144
146
|
{:c => :f} => {:lhead => :cluster1},
|
145
147
|
{:a => :f} => {:ltail => :cluster0, :lhead => :cluster1}
|
146
148
|
)
|
147
|
-
assert_equal <<-end_of_string.gsub(/\s/, ''),
|
149
|
+
#assert_equal <<-end_of_string.gsub(/\s/, ''), gvr.gsub(/\s/, '')
|
150
|
+
assert_equal <<-end_of_string, gvr
|
148
151
|
digraph sample {
|
149
152
|
subgraph cluster0 {
|
150
|
-
graph [color = blue, label ="area 0", style = bold];
|
153
|
+
graph [color = blue, label = "area 0", style = bold];
|
151
154
|
a -> b;
|
152
155
|
a -> c;
|
153
156
|
}
|
@@ -171,26 +174,26 @@ digraph sample {
|
|
171
174
|
#c1.label = 'area 1'
|
172
175
|
#c1.style = :filled
|
173
176
|
def test_subgrpah_dynamic
|
174
|
-
|
175
|
-
|
177
|
+
gvr = GraphvizR.new 'sample'
|
178
|
+
gvr.cluster0 do |c0|
|
176
179
|
c0.graph [:color => :blue, :label => 'area 0', :style => :bold]
|
177
180
|
c0.a >> c0.b
|
178
181
|
c0.a >> c0.c
|
179
182
|
end
|
180
|
-
|
183
|
+
gvr.cluster1 do |c1|
|
181
184
|
c1.graph [:fillcolor => '#cc9966', :label => 'area 1', :style => :filled]
|
182
185
|
c1.d >> c1.e
|
183
186
|
c1.d >> c1.f
|
184
187
|
end
|
185
|
-
(
|
186
|
-
|
187
|
-
(
|
188
|
-
(
|
188
|
+
(gvr.a >> gvr.f) [:lhead => :cluster1, :ltail => :cluster0]
|
189
|
+
gvr.b >> gvr.d
|
190
|
+
(gvr.c >> gvr.d) [:ltail => :cluster0]
|
191
|
+
(gvr.c >> gvr.f) [:lhead => :cluster1]
|
189
192
|
|
190
|
-
assert_equal <<-end_of_string
|
193
|
+
assert_equal <<-end_of_string, gvr.to_dot
|
191
194
|
digraph sample {
|
192
195
|
subgraph cluster0 {
|
193
|
-
graph [color = blue, label ="area 0", style = bold];
|
196
|
+
graph [color = blue, label = "area 0", style = bold];
|
194
197
|
a -> b;
|
195
198
|
a -> c;
|
196
199
|
}
|
@@ -203,6 +206,66 @@ digraph sample {
|
|
203
206
|
b -> d;
|
204
207
|
c -> d [ltail = cluster0];
|
205
208
|
c -> f [lhead = cluster1];
|
209
|
+
}
|
210
|
+
end_of_string
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_undirected_graph
|
214
|
+
gvr = GraphvizR.new 'sample'
|
215
|
+
gvr.graph [:label => 'example', :size => '1.5, 2.5']
|
216
|
+
gvr.beta [:shape => :box]
|
217
|
+
gvr.alpha - gvr.beta
|
218
|
+
(gvr.alpha - gvr.gamma) [:label => 'label1']
|
219
|
+
(gvr.beta - gvr.delta) [:label => 'label2']
|
220
|
+
gvr.delta - gvr[:size]
|
221
|
+
|
222
|
+
#assert_equal <<-end_of_string.gsub(/\s/, ''), gvr.to_dot.gsub(/\s/, '')
|
223
|
+
assert_equal <<-end_of_string, gvr.to_dot
|
224
|
+
graph sample {
|
225
|
+
graph [label = "example", size = "1.5, 2.5"];
|
226
|
+
beta [shape = box];
|
227
|
+
alpha -- beta;
|
228
|
+
alpha -- gamma [label = "label1"];
|
229
|
+
beta -- delta [label = "label2"];
|
230
|
+
delta -- size;
|
231
|
+
}
|
232
|
+
end_of_string
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_undirected_subgrpah
|
236
|
+
gvr = GraphvizR.new 'sample'
|
237
|
+
gvr.cluster0 do |c0|
|
238
|
+
c0.graph [:color => :blue, :label => 'area 0', :style => :bold]
|
239
|
+
c0.a - c0.b
|
240
|
+
c0.a - c0.c
|
241
|
+
end
|
242
|
+
gvr.cluster1 do |c1|
|
243
|
+
c1.graph [:fillcolor => '#cc9966', :label => 'area 1', :style => :filled]
|
244
|
+
c1.d - c1.e
|
245
|
+
c1.d - c1.f
|
246
|
+
end
|
247
|
+
(gvr.a - gvr.f) [:lhead => :cluster1, :ltail => :cluster0]
|
248
|
+
gvr.b - gvr.d
|
249
|
+
(gvr.c - gvr.d) [:ltail => :cluster0]
|
250
|
+
(gvr.c - gvr.f) [:lhead => :cluster1]
|
251
|
+
|
252
|
+
#assert_equal <<-end_of_string.gsub(/\s/, ''), gvr.to_dot.gsub(/\s/, '')
|
253
|
+
assert_equal <<-end_of_string, gvr.to_dot
|
254
|
+
graph sample {
|
255
|
+
subgraph cluster0 {
|
256
|
+
graph [color = blue, label = "area 0", style = bold];
|
257
|
+
a -- b;
|
258
|
+
a -- c;
|
259
|
+
}
|
260
|
+
subgraph cluster1 {
|
261
|
+
graph [fillcolor = "#cc9966", label = "area 1", style = filled];
|
262
|
+
d -- e;
|
263
|
+
d -- f;
|
264
|
+
}
|
265
|
+
a -- f [lhead = cluster1, ltail = cluster0];
|
266
|
+
b -- d;
|
267
|
+
c -- d [ltail = cluster0];
|
268
|
+
c -- f [lhead = cluster1];
|
206
269
|
}
|
207
270
|
end_of_string
|
208
271
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: GraphvizR
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0
|
7
|
-
date: 2007-02-
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-02-15 00:00:00 +09:00
|
8
8
|
summary: The author was too lazy to write a summary
|
9
9
|
require_paths:
|
10
10
|
- lib
|