gviz 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -0
- data/bin/gviz +36 -0
- data/gviz.gemspec +3 -0
- data/lib/gviz.rb +3 -210
- data/lib/gviz/core.rb +154 -0
- data/lib/gviz/edge.rb +29 -0
- data/lib/gviz/node.rb +11 -0
- data/lib/gviz/version.rb +2 -2
- data/spec/graph.ru +2 -0
- data/spec/gviz_command_spec.rb +49 -0
- data/spec/gviz_edge_spec.rb +67 -0
- data/spec/gviz_node_spec.rb +38 -0
- data/spec/gviz_spec.rb +1 -102
- data/spec/spec_helper.rb +8 -1
- metadata +50 -5
data/README.md
CHANGED
@@ -105,6 +105,28 @@ This outputs below.
|
|
105
105
|
|
106
106
|
Another examples are at `examples` directory
|
107
107
|
|
108
|
+
## gviz command
|
109
|
+
It comes with a `gviz` command. This works with a graph spec file. If 'graph.ru' file exist on a directory of the execution, it will be automatically loaded as a graph spec file.
|
110
|
+
|
111
|
+
Example of graph.ru:
|
112
|
+
|
113
|
+
route :main => [:init, :parse, :cleanup, :printf]
|
114
|
+
route :init => :make, :parse => :execute
|
115
|
+
route :execute => [:make, :compare, :printf]
|
116
|
+
|
117
|
+
save(:sample, :png)
|
118
|
+
|
119
|
+
Usage:
|
120
|
+
|
121
|
+
gviz [options] <graph filename>
|
122
|
+
|
123
|
+
where [options] are:
|
124
|
+
|
125
|
+
--name, -n : Graph name (default: G)
|
126
|
+
--type, -t : Graph type (default: digraph)
|
127
|
+
--version, -v: Print version and exit
|
128
|
+
--help, -h: Show this message
|
129
|
+
|
108
130
|
## Contributing
|
109
131
|
|
110
132
|
1. Fork it
|
data/bin/gviz
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "gviz"
|
3
|
+
require "trollop"
|
4
|
+
|
5
|
+
def gfile_eval(gfile, opts)
|
6
|
+
Graph(opts[:name], opts[:type]) { instance_eval ::File.read(gfile) }
|
7
|
+
rescue Errno::ENOENT
|
8
|
+
abort "graph file `#{gfile}` not found"
|
9
|
+
end
|
10
|
+
|
11
|
+
opts = Trollop::options do
|
12
|
+
version "Gviz #{Gviz::VERSION} (c) 2012 kyoendo"
|
13
|
+
banner <<-EOS
|
14
|
+
Gviz is a tool for generating graphviz dot data with simple Ruby's syntax. It works with a graph spec file in which a graph spec describes with several gviz commands. If 'graph.ru' file exist on a directory of the execution, it will be automatically loaded as a graph spec file.
|
15
|
+
|
16
|
+
Example of graph.ru:
|
17
|
+
|
18
|
+
route :main => [:init, :parse, :cleanup, :printf]
|
19
|
+
route :init => :make, :parse => :execute
|
20
|
+
route :execute => [:make, :compare, :printf]
|
21
|
+
|
22
|
+
save(:sample, :png)
|
23
|
+
|
24
|
+
Usage:
|
25
|
+
|
26
|
+
gviz [options] <graph filename>
|
27
|
+
|
28
|
+
where [options] are:
|
29
|
+
EOS
|
30
|
+
|
31
|
+
opt :name, "Graph name", :default => 'G'
|
32
|
+
opt :type, "Graph type", :default => 'digraph'
|
33
|
+
end
|
34
|
+
|
35
|
+
gfile = ARGV[0] || "graph.ru"
|
36
|
+
gfile_eval(gfile, opts)
|
data/gviz.gemspec
CHANGED
@@ -16,4 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
|
+
gem.required_ruby_version = '>=1.9.3'
|
20
|
+
gem.add_development_dependency 'rspec'
|
21
|
+
gem.add_dependency 'thor'
|
19
22
|
end
|
data/lib/gviz.rb
CHANGED
@@ -1,218 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# encoding: UTF-8
|
3
2
|
class Gviz
|
4
|
-
class Node < Struct.new(:id, :attrs)
|
5
|
-
def initialize(id, attrs={})
|
6
|
-
raise ArgumentError, "`id` must not include underscores" if id.match(/_/)
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_s
|
11
|
-
"#{id}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class Edge < Struct.new(:id, :attrs)
|
16
|
-
attr_reader :st, :ed, :seq, :st_port, :ed_port
|
17
|
-
def initialize(id, attrs={})
|
18
|
-
raise ArgumentError, "`attrs` must a hash" unless attrs.is_a?(Hash)
|
19
|
-
id, @st, @ed, @seq, @st_port, @ed_port = parse_id(id)
|
20
|
-
super(id, attrs)
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_s
|
24
|
-
stp = ":#{st_port}" if st_port
|
25
|
-
edp = ":#{ed_port}" if ed_port
|
26
|
-
"#{st}#{stp} -> #{ed}#{edp}"
|
27
|
-
end
|
28
|
-
|
29
|
-
def nodes
|
30
|
-
[st, ed]
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
def parse_id(id)
|
35
|
-
raise ArgumentError, "id must not include other than words or a colon" if id.match(/[^\w:]/)
|
36
|
-
st, ed, seq = "#{id}".split('_')
|
37
|
-
st, st_port = st.split(':').map(&:intern)
|
38
|
-
ed, ed_port = ed.split(':').map(&:intern)
|
39
|
-
id = (seq ? [st, ed, seq] : [st, ed]).join('_').intern
|
40
|
-
[id, st, ed, seq.to_i, st_port, ed_port]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
attr_reader :gnode_attrs, :gedge_attrs, :graph_attrs, :subgraphs, :ranks
|
45
|
-
def initialize(name=:G, type=:digraph)
|
46
|
-
@name, @type = name, type
|
47
|
-
@edges = {}
|
48
|
-
@nodes = {}
|
49
|
-
@gnode_attrs = {}
|
50
|
-
@gedge_attrs = {}
|
51
|
-
@graph_attrs = {}
|
52
|
-
@subgraphs = []
|
53
|
-
@ranks = []
|
54
|
-
end
|
55
|
-
|
56
|
-
def nodeset
|
57
|
-
@nodes.values
|
58
|
-
end
|
59
|
-
|
60
|
-
def edgeset
|
61
|
-
@edges.values
|
62
|
-
end
|
63
|
-
|
64
|
-
def node(id, attrs={})
|
65
|
-
raise ArgumentError, '`id` must a symbol' unless id.is_a?(Symbol)
|
66
|
-
Node[id, attrs].tap do |node|
|
67
|
-
if exist = @nodes[node.id]
|
68
|
-
exist.attrs.update(node.attrs)
|
69
|
-
else
|
70
|
-
@nodes.update(node.id => node)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def edge(id, attrs={})
|
76
|
-
unless id.match(/._./)
|
77
|
-
raise ArgumentError, '`id` must a symbol in which node names joined with "_"'
|
78
|
-
end
|
79
|
-
Edge[id.intern, attrs].tap do |edge|
|
80
|
-
if exist = @edges[id.intern]
|
81
|
-
exist.attrs.update(edge.attrs)
|
82
|
-
else
|
83
|
-
@edges.update(edge.id => edge)
|
84
|
-
create_nodes
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def nodes(attrs)
|
90
|
-
@gnode_attrs.update(attrs)
|
91
|
-
end
|
92
|
-
|
93
|
-
def edges(attrs)
|
94
|
-
@gedge_attrs.update(attrs)
|
95
|
-
end
|
96
|
-
|
97
|
-
def global(attrs)
|
98
|
-
@graph_attrs.update(attrs)
|
99
|
-
end
|
100
|
-
|
101
|
-
def subgraph(&blk)
|
102
|
-
Gviz.new("cluster#{subgraphs.size}", :subgraph).tap do |graph|
|
103
|
-
subgraphs << graph
|
104
|
-
graph.instance_eval &blk
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def graph(&blk)
|
109
|
-
instance_eval(&blk)
|
110
|
-
self
|
111
|
-
end
|
112
|
-
|
113
|
-
def add(*nodes_or_routes)
|
114
|
-
nodes_or_routes.each do |unit|
|
115
|
-
case unit
|
116
|
-
when Hash
|
117
|
-
unit.each do |sts, eds|
|
118
|
-
Array(sts).product(Array(eds))
|
119
|
-
.each { |st, ed| edge([st,ed].join('_').intern) }
|
120
|
-
end
|
121
|
-
when Symbol
|
122
|
-
node(unit)
|
123
|
-
else
|
124
|
-
raise ArgumentError, 'pass nodes in symbol or edges in hash'
|
125
|
-
end
|
126
|
-
end
|
127
|
-
self
|
128
|
-
end
|
129
|
-
alias :route :add
|
130
|
-
|
131
|
-
def rank(type, *nodes)
|
132
|
-
types = [:same, :min, :max, :source, :sink]
|
133
|
-
unless types.include?(type)
|
134
|
-
raise ArgumentError, "type must match any of #{types.join(', ')}"
|
135
|
-
end
|
136
|
-
@ranks << [type, nodes]
|
137
|
-
end
|
138
|
-
|
139
|
-
def to_s
|
140
|
-
result = []
|
141
|
-
tabs = " "
|
142
|
-
result << "#{@type} #{@name} {"
|
143
|
-
|
144
|
-
unless graph_attrs.empty?
|
145
|
-
result << tabs + build_attrs(graph_attrs, false).join(";\n#{tabs}") + ";"
|
146
|
-
end
|
147
|
-
|
148
|
-
unless gnode_attrs.empty?
|
149
|
-
result << tabs + "node#{build_attrs(gnode_attrs)};"
|
150
|
-
end
|
151
|
-
|
152
|
-
unless gedge_attrs.empty?
|
153
|
-
result << tabs + "edge#{build_attrs(gedge_attrs)};"
|
154
|
-
end
|
155
|
-
|
156
|
-
@nodes.values.each do |node|
|
157
|
-
result << tabs + "#{node.id}#{build_attrs(node.attrs)};"
|
158
|
-
end
|
159
|
-
|
160
|
-
@edges.values.each do |edge|
|
161
|
-
result << tabs + "#{edge}#{build_attrs(edge.attrs)};"
|
162
|
-
end
|
163
|
-
|
164
|
-
subgraphs.each do |graph|
|
165
|
-
graph.to_s.lines do |line|
|
166
|
-
result << tabs + line.chomp
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
@ranks.each do |type, nodes|
|
171
|
-
result << tabs + "{ rank=#{type}; #{nodes.join('; ')}; }"
|
172
|
-
end
|
173
|
-
|
174
|
-
result << "}\n"
|
175
|
-
result.join("\n")
|
176
|
-
end
|
177
|
-
|
178
|
-
def save(path, type=nil)
|
179
|
-
File.open("#{path}.dot", "w") { |f| f.puts self }
|
180
|
-
system "dot -T#{type} #{path}.dot -o #{path}.#{type}" if type
|
181
|
-
end
|
182
|
-
|
183
|
-
private
|
184
|
-
def create_nodes
|
185
|
-
# only create unregistered nodes
|
186
|
-
ids = @edges.values.flat_map(&:nodes).uniq - @nodes.keys
|
187
|
-
ids.each { |id| node(id) }
|
188
|
-
@nodes
|
189
|
-
end
|
190
|
-
|
191
|
-
def build_attrs(attrs, join=true)
|
192
|
-
return nil if attrs.empty?
|
193
|
-
arr = attrs.map { |k, v| %(#{k}="#{v}").gsub("\n", "\\n") }
|
194
|
-
join ? '[' + arr.join(',') + ']' : arr
|
195
|
-
end
|
196
3
|
end
|
197
4
|
|
198
5
|
def Graph(name=:G, type=:digraph, &blk)
|
199
6
|
Gviz.new(name, type).graph(&blk)
|
200
7
|
end
|
201
8
|
|
202
|
-
|
203
|
-
|
204
|
-
g.graph do
|
205
|
-
add(:main => [:printf, :parse, :init, :cleanup])
|
206
|
-
add(:parse => :execute, :init => :make)
|
207
|
-
add(:execute => [:printf, :compare, :make])
|
208
|
-
node(:main, :shape => 'box')
|
209
|
-
node(:make, :label => "make a\nstring")
|
210
|
-
node(:compare, :shape => 'box', :style => 'filled', :color => ".7 .3 1.0")
|
211
|
-
edge(:main_parse, :weight => 8)
|
212
|
-
edge(:main_init, :style => 'dotted')
|
213
|
-
edge(:main_printf, :style => 'bold', :label => "100 times", :color => 'red')
|
214
|
-
edge(:execute_compare, :color => 'red')
|
215
|
-
end
|
216
|
-
puts g
|
9
|
+
%w(core node edge version system_extension).each do |lib|
|
10
|
+
require_relative 'gviz/' + lib
|
217
11
|
end
|
218
|
-
|
data/lib/gviz/core.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
class Gviz
|
2
|
+
attr_reader :gnode_attrs, :gedge_attrs, :graph_attrs, :subgraphs, :ranks
|
3
|
+
def initialize(name=:G, type=:digraph)
|
4
|
+
@name, @type = name, type
|
5
|
+
@edges = {}
|
6
|
+
@nodes = {}
|
7
|
+
@gnode_attrs = {}
|
8
|
+
@gedge_attrs = {}
|
9
|
+
@graph_attrs = {}
|
10
|
+
@subgraphs = []
|
11
|
+
@ranks = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def nodeset
|
15
|
+
@nodes.values
|
16
|
+
end
|
17
|
+
|
18
|
+
def edgeset
|
19
|
+
@edges.values
|
20
|
+
end
|
21
|
+
|
22
|
+
def node(id, attrs={})
|
23
|
+
raise ArgumentError, '`id` must a symbol' unless id.is_a?(Symbol)
|
24
|
+
Node[id, attrs].tap do |node|
|
25
|
+
if exist = @nodes[node.id]
|
26
|
+
exist.attrs.update(node.attrs)
|
27
|
+
else
|
28
|
+
@nodes.update(node.id => node)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def edge(id, attrs={})
|
34
|
+
unless id.match(/._./)
|
35
|
+
raise ArgumentError, '`id` must a symbol in which node names joined with "_"'
|
36
|
+
end
|
37
|
+
Edge[id.intern, attrs].tap do |edge|
|
38
|
+
if exist = @edges[id.intern]
|
39
|
+
exist.attrs.update(edge.attrs)
|
40
|
+
else
|
41
|
+
@edges.update(edge.id => edge)
|
42
|
+
create_nodes
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def nodes(attrs)
|
48
|
+
@gnode_attrs.update(attrs)
|
49
|
+
end
|
50
|
+
|
51
|
+
def edges(attrs)
|
52
|
+
@gedge_attrs.update(attrs)
|
53
|
+
end
|
54
|
+
|
55
|
+
def global(attrs)
|
56
|
+
@graph_attrs.update(attrs)
|
57
|
+
end
|
58
|
+
|
59
|
+
def subgraph(&blk)
|
60
|
+
Gviz.new("cluster#{subgraphs.size}", :subgraph).tap do |graph|
|
61
|
+
subgraphs << graph
|
62
|
+
graph.instance_eval &blk
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def graph(&blk)
|
67
|
+
instance_eval(&blk)
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def add(*nodes_or_routes)
|
72
|
+
nodes_or_routes.each do |unit|
|
73
|
+
case unit
|
74
|
+
when Hash
|
75
|
+
unit.each do |sts, eds|
|
76
|
+
Array(sts).product(Array(eds))
|
77
|
+
.each { |st, ed| edge([st,ed].join('_').intern) }
|
78
|
+
end
|
79
|
+
when Symbol
|
80
|
+
node(unit)
|
81
|
+
else
|
82
|
+
raise ArgumentError, 'pass nodes in symbol or edges in hash'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
self
|
86
|
+
end
|
87
|
+
alias :route :add
|
88
|
+
|
89
|
+
def rank(type, *nodes)
|
90
|
+
types = [:same, :min, :max, :source, :sink]
|
91
|
+
unless types.include?(type)
|
92
|
+
raise ArgumentError, "type must match any of #{types.join(', ')}"
|
93
|
+
end
|
94
|
+
@ranks << [type, nodes]
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_s
|
98
|
+
result = []
|
99
|
+
tabs = " "
|
100
|
+
result << "#{@type} #{@name} {"
|
101
|
+
|
102
|
+
unless graph_attrs.empty?
|
103
|
+
result << tabs + build_attrs(graph_attrs, false).join(";\n#{tabs}") + ";"
|
104
|
+
end
|
105
|
+
|
106
|
+
unless gnode_attrs.empty?
|
107
|
+
result << tabs + "node#{build_attrs(gnode_attrs)};"
|
108
|
+
end
|
109
|
+
|
110
|
+
unless gedge_attrs.empty?
|
111
|
+
result << tabs + "edge#{build_attrs(gedge_attrs)};"
|
112
|
+
end
|
113
|
+
|
114
|
+
@nodes.values.each do |node|
|
115
|
+
result << tabs + "#{node.id}#{build_attrs(node.attrs)};"
|
116
|
+
end
|
117
|
+
|
118
|
+
@edges.values.each do |edge|
|
119
|
+
result << tabs + "#{edge}#{build_attrs(edge.attrs)};"
|
120
|
+
end
|
121
|
+
|
122
|
+
subgraphs.each do |graph|
|
123
|
+
graph.to_s.lines do |line|
|
124
|
+
result << tabs + line.chomp
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
@ranks.each do |type, nodes|
|
129
|
+
result << tabs + "{ rank=#{type}; #{nodes.join('; ')}; }"
|
130
|
+
end
|
131
|
+
|
132
|
+
result << "}\n"
|
133
|
+
result.join("\n")
|
134
|
+
end
|
135
|
+
|
136
|
+
def save(path, type=nil)
|
137
|
+
File.open("#{path}.dot", "w") { |f| f.puts self }
|
138
|
+
system "dot -T#{type} #{path}.dot -o #{path}.#{type}" if type
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
def create_nodes
|
143
|
+
# only create unregistered nodes
|
144
|
+
ids = @edges.values.flat_map(&:nodes).uniq - @nodes.keys
|
145
|
+
ids.each { |id| node(id) }
|
146
|
+
@nodes
|
147
|
+
end
|
148
|
+
|
149
|
+
def build_attrs(attrs, join=true)
|
150
|
+
return nil if attrs.empty?
|
151
|
+
arr = attrs.map { |k, v| %(#{k}="#{v}").gsub("\n", "\\n") }
|
152
|
+
join ? '[' + arr.join(',') + ']' : arr
|
153
|
+
end
|
154
|
+
end
|
data/lib/gviz/edge.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
class Gviz::Edge < Struct.new(:id, :attrs)
|
2
|
+
attr_reader :st, :ed, :seq, :st_port, :ed_port
|
3
|
+
def initialize(id, attrs={})
|
4
|
+
raise ArgumentError, "`attrs` must a hash" unless attrs.is_a?(Hash)
|
5
|
+
id, @st, @ed, @seq, @st_port, @ed_port = parse_id(id)
|
6
|
+
super(id, attrs)
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
stp = ":#{st_port}" if st_port
|
11
|
+
edp = ":#{ed_port}" if ed_port
|
12
|
+
"#{st}#{stp} -> #{ed}#{edp}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def nodes
|
16
|
+
[st, ed]
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def parse_id(id)
|
21
|
+
raise ArgumentError, "id must not include other than words or a colon" if id.match(/[^\w:]/)
|
22
|
+
st, ed, seq = "#{id}".split('_')
|
23
|
+
st, st_port = st.split(':').map(&:intern)
|
24
|
+
ed, ed_port = ed.split(':').map(&:intern)
|
25
|
+
id = (seq ? [st, ed, seq] : [st, ed]).join('_').intern
|
26
|
+
[id, st, ed, seq.to_i, st_port, ed_port]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
data/lib/gviz/node.rb
ADDED
data/lib/gviz/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.0.
|
1
|
+
class Gviz
|
2
|
+
VERSION = "0.0.6"
|
3
3
|
end
|
data/spec/graph.ru
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
ROOT = File.expand_path(File.dirname(__FILE__) + "/..")
|
4
|
+
|
5
|
+
describe "gviz command" do
|
6
|
+
context "when a graph file exist" do
|
7
|
+
subject { syscmd "#{ROOT}/bin/gviz spec/graph.ru" }
|
8
|
+
it do
|
9
|
+
should eql ~<<-EOS
|
10
|
+
digraph G {
|
11
|
+
a;
|
12
|
+
b;
|
13
|
+
a -> b;
|
14
|
+
}
|
15
|
+
EOS
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when a graph file not exist" do
|
20
|
+
subject { syscmd "#{ROOT}/bin/gviz", :err }
|
21
|
+
it { should eql "graph file `graph.ru` not found\n" }
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when a name option passed" do
|
25
|
+
subject { syscmd "#{ROOT}/bin/gviz -n ABC spec/graph.ru" }
|
26
|
+
it do
|
27
|
+
should eql ~<<-EOS
|
28
|
+
digraph ABC {
|
29
|
+
a;
|
30
|
+
b;
|
31
|
+
a -> b;
|
32
|
+
}
|
33
|
+
EOS
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when a type option passed" do
|
38
|
+
subject { syscmd "#{ROOT}/bin/gviz -t graph spec/graph.ru" }
|
39
|
+
it do
|
40
|
+
should eql ~<<-EOS
|
41
|
+
graph G {
|
42
|
+
a;
|
43
|
+
b;
|
44
|
+
a -> b;
|
45
|
+
}
|
46
|
+
EOS
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require_relative "spec_helper"
|
3
|
+
|
4
|
+
describe Gviz::Edge do
|
5
|
+
describe ".new" do
|
6
|
+
context "when a symbol with an underscore passed" do
|
7
|
+
subject { Gviz::Edge.new(:a_b) }
|
8
|
+
it { should be_a_instance_of Gviz::Edge }
|
9
|
+
its(:id) { should be :a_b }
|
10
|
+
its(:st) { should be :a }
|
11
|
+
its(:ed) { should be :b }
|
12
|
+
its(:seq) { should eq 0 }
|
13
|
+
its(:st_port) { should be_nil }
|
14
|
+
its(:ed_port) { should be_nil }
|
15
|
+
its(:to_s) { should eq "a -> b" }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when a string with an underscore passed" do
|
19
|
+
subject { Gviz::Edge.new('a_b') }
|
20
|
+
it { should be_a_instance_of Gviz::Edge }
|
21
|
+
its(:id) { should be :a_b }
|
22
|
+
its(:st) { should be :a }
|
23
|
+
its(:ed) { should be :b }
|
24
|
+
its(:seq) { should eq 0 }
|
25
|
+
its(:st_port) { should be_nil }
|
26
|
+
its(:ed_port) { should be_nil }
|
27
|
+
its(:to_s) { should eq "a -> b" }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when a symbol with two underscores passed" do
|
31
|
+
subject { Gviz::Edge.new('a_b_1') }
|
32
|
+
it { should be_a_instance_of Gviz::Edge }
|
33
|
+
its(:id) { should be :a_b_1 }
|
34
|
+
its(:st) { should be :a }
|
35
|
+
its(:ed) { should be :b }
|
36
|
+
its(:seq) { should eq 1 }
|
37
|
+
its(:st_port) { should be_nil }
|
38
|
+
its(:ed_port) { should be_nil }
|
39
|
+
its(:to_s) { should eq "a -> b" }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when a string with a colon passed" do
|
43
|
+
subject { Gviz::Edge.new('a:x_b:y') }
|
44
|
+
it { should be_a_instance_of Gviz::Edge }
|
45
|
+
its(:id) { should be :a_b }
|
46
|
+
its(:st) { should be :a }
|
47
|
+
its(:ed) { should be :b }
|
48
|
+
its(:seq) { should eq 0 }
|
49
|
+
its(:st_port) { should be :x }
|
50
|
+
its(:ed_port) { should be :y }
|
51
|
+
its(:to_s) { should eq "a:x -> b:y" }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when a symbol and hash options passed" do
|
55
|
+
opts = { style:'bold', color:'red' }
|
56
|
+
subject { Gviz::Edge.new(:a_b, opts) }
|
57
|
+
its(:id) { should be :a_b }
|
58
|
+
its(:attrs) { should eq opts }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when a string with other than words or colon passed" do
|
62
|
+
it "raise an error" do
|
63
|
+
->{ Gviz::Edge.new('a!b_c') }.should raise_error(ArgumentError)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require_relative "spec_helper"
|
3
|
+
|
4
|
+
describe Gviz::Node do
|
5
|
+
describe ".new" do
|
6
|
+
context "when only a symbol passed" do
|
7
|
+
subject { Gviz::Node.new(:a) }
|
8
|
+
it { should be_a_instance_of Gviz::Node }
|
9
|
+
its(:id) { should be :a }
|
10
|
+
its(:attrs) { should be_empty }
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when only a string passed" do
|
14
|
+
subject { Gviz::Node.new('a') }
|
15
|
+
it { should be_a_instance_of Gviz::Node }
|
16
|
+
its(:id) { should eq 'a' }
|
17
|
+
its(:attrs) { should be_empty }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when a symbol and hash options passed" do
|
21
|
+
opts = { shape:'circle', style:'filled' }
|
22
|
+
subject { Gviz::Node.new(:a, opts) }
|
23
|
+
its(:id) { should be :a }
|
24
|
+
its(:attrs) { should eq opts }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when a symbol with underscore passed" do
|
28
|
+
it "raise an error" do
|
29
|
+
->{ Gviz::Node.new(:a_b) }.should raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_s" do
|
35
|
+
subject { Gviz::Node.new(:a, style:'filled').to_s }
|
36
|
+
it { should eq "a" }
|
37
|
+
end
|
38
|
+
end
|
data/spec/gviz_spec.rb
CHANGED
@@ -1,106 +1,5 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
|
3
|
-
|
4
|
-
describe Gviz::Node do
|
5
|
-
describe ".new" do
|
6
|
-
context "when only a symbol passed" do
|
7
|
-
subject { Gviz::Node.new(:a) }
|
8
|
-
it { should be_a_instance_of Gviz::Node }
|
9
|
-
its(:id) { should be :a }
|
10
|
-
its(:attrs) { should be_empty }
|
11
|
-
end
|
12
|
-
|
13
|
-
context "when only a string passed" do
|
14
|
-
subject { Gviz::Node.new('a') }
|
15
|
-
it { should be_a_instance_of Gviz::Node }
|
16
|
-
its(:id) { should eq 'a' }
|
17
|
-
its(:attrs) { should be_empty }
|
18
|
-
end
|
19
|
-
|
20
|
-
context "when a symbol and hash options passed" do
|
21
|
-
opts = { shape:'circle', style:'filled' }
|
22
|
-
subject { Gviz::Node.new(:a, opts) }
|
23
|
-
its(:id) { should be :a }
|
24
|
-
its(:attrs) { should eq opts }
|
25
|
-
end
|
26
|
-
|
27
|
-
context "when a symbol with underscore passed" do
|
28
|
-
it "raise an error" do
|
29
|
-
->{ Gviz::Node.new(:a_b) }.should raise_error(ArgumentError)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "#to_s" do
|
35
|
-
subject { Gviz::Node.new(:a, style:'filled').to_s }
|
36
|
-
it { should eq "a" }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe Gviz::Edge do
|
41
|
-
describe ".new" do
|
42
|
-
context "when a symbol with an underscore passed" do
|
43
|
-
subject { Gviz::Edge.new(:a_b) }
|
44
|
-
it { should be_a_instance_of Gviz::Edge }
|
45
|
-
its(:id) { should be :a_b }
|
46
|
-
its(:st) { should be :a }
|
47
|
-
its(:ed) { should be :b }
|
48
|
-
its(:seq) { should eq 0 }
|
49
|
-
its(:st_port) { should be_nil }
|
50
|
-
its(:ed_port) { should be_nil }
|
51
|
-
its(:to_s) { should eq "a -> b" }
|
52
|
-
end
|
53
|
-
|
54
|
-
context "when a string with an underscore passed" do
|
55
|
-
subject { Gviz::Edge.new('a_b') }
|
56
|
-
it { should be_a_instance_of Gviz::Edge }
|
57
|
-
its(:id) { should be :a_b }
|
58
|
-
its(:st) { should be :a }
|
59
|
-
its(:ed) { should be :b }
|
60
|
-
its(:seq) { should eq 0 }
|
61
|
-
its(:st_port) { should be_nil }
|
62
|
-
its(:ed_port) { should be_nil }
|
63
|
-
its(:to_s) { should eq "a -> b" }
|
64
|
-
end
|
65
|
-
|
66
|
-
context "when a symbol with two underscores passed" do
|
67
|
-
subject { Gviz::Edge.new('a_b_1') }
|
68
|
-
it { should be_a_instance_of Gviz::Edge }
|
69
|
-
its(:id) { should be :a_b_1 }
|
70
|
-
its(:st) { should be :a }
|
71
|
-
its(:ed) { should be :b }
|
72
|
-
its(:seq) { should eq 1 }
|
73
|
-
its(:st_port) { should be_nil }
|
74
|
-
its(:ed_port) { should be_nil }
|
75
|
-
its(:to_s) { should eq "a -> b" }
|
76
|
-
end
|
77
|
-
|
78
|
-
context "when a string with a colon passed" do
|
79
|
-
subject { Gviz::Edge.new('a:x_b:y') }
|
80
|
-
it { should be_a_instance_of Gviz::Edge }
|
81
|
-
its(:id) { should be :a_b }
|
82
|
-
its(:st) { should be :a }
|
83
|
-
its(:ed) { should be :b }
|
84
|
-
its(:seq) { should eq 0 }
|
85
|
-
its(:st_port) { should be :x }
|
86
|
-
its(:ed_port) { should be :y }
|
87
|
-
its(:to_s) { should eq "a:x -> b:y" }
|
88
|
-
end
|
89
|
-
|
90
|
-
context "when a symbol and hash options passed" do
|
91
|
-
opts = { style:'bold', color:'red' }
|
92
|
-
subject { Gviz::Edge.new(:a_b, opts) }
|
93
|
-
its(:id) { should be :a_b }
|
94
|
-
its(:attrs) { should eq opts }
|
95
|
-
end
|
96
|
-
|
97
|
-
context "when a string with other than words or colon passed" do
|
98
|
-
it "raise an error" do
|
99
|
-
->{ Gviz::Edge.new('a!b_c') }.should raise_error(ArgumentError)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
2
|
+
require_relative "spec_helper"
|
104
3
|
|
105
4
|
describe Gviz do
|
106
5
|
let(:gv) { Gviz.new }
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
require "gviz"
|
2
2
|
require "rspec"
|
3
|
+
require "stringio"
|
4
|
+
require "open3"
|
3
5
|
|
4
6
|
class String
|
5
7
|
def ~
|
6
8
|
margin = scan(/^ +/).map(&:size).min
|
7
9
|
gsub(/^ {#{margin}}/, '')
|
8
10
|
end
|
9
|
-
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def syscmd(cmd, io=:out)
|
14
|
+
idx = [:stdin, :stdout, :stderr].index { |st| st.match /#{io}/ }
|
15
|
+
Open3.popen3(cmd)[idx].read
|
16
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gviz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,45 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
13
|
-
dependencies:
|
12
|
+
date: 2012-10-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: thor
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
14
46
|
description: Ruby's interface of graphviz
|
15
47
|
email:
|
16
48
|
- postagie@gmail.com
|
17
|
-
executables:
|
49
|
+
executables:
|
50
|
+
- gviz
|
18
51
|
extensions: []
|
19
52
|
extra_rdoc_files: []
|
20
53
|
files:
|
@@ -23,6 +56,7 @@ files:
|
|
23
56
|
- LICENSE.txt
|
24
57
|
- README.md
|
25
58
|
- Rakefile
|
59
|
+
- bin/gviz
|
26
60
|
- examples/arrows.rb
|
27
61
|
- examples/colors.rb
|
28
62
|
- examples/examples.rb
|
@@ -32,8 +66,15 @@ files:
|
|
32
66
|
- examples/shapes.rb
|
33
67
|
- gviz.gemspec
|
34
68
|
- lib/gviz.rb
|
69
|
+
- lib/gviz/core.rb
|
70
|
+
- lib/gviz/edge.rb
|
71
|
+
- lib/gviz/node.rb
|
35
72
|
- lib/gviz/system_extension.rb
|
36
73
|
- lib/gviz/version.rb
|
74
|
+
- spec/graph.ru
|
75
|
+
- spec/gviz_command_spec.rb
|
76
|
+
- spec/gviz_edge_spec.rb
|
77
|
+
- spec/gviz_node_spec.rb
|
37
78
|
- spec/gviz_spec.rb
|
38
79
|
- spec/spec_helper.rb
|
39
80
|
- spec/system_extension_spec.rb
|
@@ -48,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
48
89
|
requirements:
|
49
90
|
- - ! '>='
|
50
91
|
- !ruby/object:Gem::Version
|
51
|
-
version:
|
92
|
+
version: 1.9.3
|
52
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
94
|
none: false
|
54
95
|
requirements:
|
@@ -62,6 +103,10 @@ signing_key:
|
|
62
103
|
specification_version: 3
|
63
104
|
summary: Ruby's interface of graphviz. It generate a dot file with simple ruby's syntax.
|
64
105
|
test_files:
|
106
|
+
- spec/graph.ru
|
107
|
+
- spec/gviz_command_spec.rb
|
108
|
+
- spec/gviz_edge_spec.rb
|
109
|
+
- spec/gviz_node_spec.rb
|
65
110
|
- spec/gviz_spec.rb
|
66
111
|
- spec/spec_helper.rb
|
67
112
|
- spec/system_extension_spec.rb
|