gviz 0.0.5 → 0.0.6
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/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
|