ruby-graphviz 1.0.0 → 1.0.1
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/.gemrc +0 -0
- data/.gitignore +6 -0
- data/AUTHORS +3 -0
- data/Gemfile +4 -0
- data/README.rdoc +25 -45
- data/Rakefile +59 -0
- data/bin/dot2ruby +0 -0
- data/bin/gem2gv +0 -0
- data/bin/git2gv +0 -0
- data/bin/ruby2gv +0 -0
- data/bin/xml2gv +0 -0
- data/examples/sample48.rb +2 -2
- data/examples/sample62.rb +24 -0
- data/examples/sample63.rb +32 -0
- data/examples/sample64.rb +31 -0
- data/examples/sample65.rb +9 -0
- data/lib/graphviz.rb +55 -25
- data/lib/graphviz/constants.rb +103 -100
- data/lib/graphviz/core_ext.rb +57 -34
- data/lib/graphviz/dot2ruby.rb +9 -0
- data/lib/graphviz/dsl.rb +59 -0
- data/lib/graphviz/node.rb +2 -1
- data/lib/graphviz/types.rb +0 -4
- data/lib/graphviz/types/arrow_type.rb +32 -0
- data/lib/graphviz/types/color.rb +56 -0
- data/lib/graphviz/types/color_list.rb +22 -0
- data/lib/graphviz/types/esc_string.rb +5 -14
- data/lib/graphviz/types/gv_bool.rb +49 -0
- data/lib/graphviz/types/gv_double.rb +12 -2
- data/lib/graphviz/types/html_string.rb +3 -1
- data/lib/graphviz/types/lbl_string.rb +2 -1
- data/lib/graphviz/types/rect.rb +34 -0
- data/lib/graphviz/types/spline_type.rb +75 -0
- data/lib/graphviz/utils.rb +2 -2
- data/lib/graphviz/utils/colors.rb +1019 -0
- data/ruby-graphviz.gemspec +57 -0
- data/test/test_examples.rb +4 -0
- data/test/{test_init.rb → test_graph.rb} +1 -1
- data/test/test_types.rb +65 -0
- data/test/test_utils_colors.rb +57 -0
- metadata +100 -112
- data/examples/rgv/rgv.ps +0 -125
- data/examples/rgv/test_rgv.rb +0 -12
- data/examples/rgv/test_rgv.rb.ps +0 -393
- data/examples/simpsons.gv +0 -69
- data/test/output/sample01.rb.png +0 -0
- data/test/output/sample02.rb.png +0 -0
- data/test/output/sample03.rb.png +0 -0
- data/test/output/sample04.rb.png +0 -0
- data/test/output/sample05.rb.png +0 -0
- data/test/output/sample06.rb.png +0 -0
- data/test/output/sample07.rb.png +0 -0
- data/test/output/sample08.rb.png +0 -0
- data/test/output/sample09.rb.png +0 -0
- data/test/output/sample10.rb.png +0 -0
- data/test/output/sample11.rb.png +0 -0
- data/test/output/sample12.rb.png +0 -0
- data/test/output/sample13.rb.png +0 -0
- data/test/output/sample14.rb.png +0 -0
- data/test/output/sample15.rb.png +0 -0
- data/test/output/sample16.rb.png +0 -0
- data/test/output/sample17.rb.png +0 -0
- data/test/output/sample18.rb.png +0 -0
- data/test/output/sample19.rb.png +0 -0
- data/test/output/sample20.rb.png +0 -0
- data/test/output/sample21.rb.html +0 -3
- data/test/output/sample21.rb.png +0 -0
- data/test/output/sample22.rb.html +0 -5
- data/test/output/sample22.rb.png +0 -0
- data/test/output/sample23.rb.png +0 -0
- data/test/output/sample24.rb.png +0 -0
- data/test/output/sample25.rb.png +0 -0
- data/test/output/sample26.rb.png +0 -0
- data/test/output/sample28.rb.png +0 -0
- data/test/output/sample29.rb.svg +0 -21
- data/test/output/sample30.rb.ps +0 -923
- data/test/output/sample31.rb.png +0 -0
- data/test/output/sample32.rb.png +0 -0
- data/test/output/sample35.rb.gv +0 -24
- data/test/output/sample35.rb.png +0 -0
- data/test/output/sample37.rb.dot +0 -50
- data/test/output/sample37.rb.png +0 -0
- data/test/output/sample38.rb.png +0 -0
- data/test/output/sample39.rb.png +0 -0
- data/test/output/sample40.rb.png +0 -0
- data/test/output/sample41.rb.svg +0 -8
- data/test/output/sample42.rb.png +0 -0
- data/test/output/sample43.rb.png +0 -0
- data/test/output/sample44.rb.png +0 -0
- data/test/output/sample45.rb.png +0 -0
- data/test/output/sample46.rb.png +0 -0
- data/test/output/sample47.rb.png +0 -0
- data/test/output/sample48.rb.png +0 -0
- data/test/output/sample49.rb.png +0 -0
- data/test/output/sample50.rb.png +0 -0
- data/test/output/sample51.rb.png +0 -0
- data/test/output/sample52.rb.png +0 -0
- data/test/output/sample53.rb.png +0 -0
- data/test/output/sample54.rb.png +0 -0
- data/test/output/sample55.rb.png +0 -0
- data/test/output/sample56.rb.svg +0 -28
- data/test/output/sample58.rb.png +0 -0
- data/test/output/sample59.rb.png +0 -0
- data/test/output/sample60.rb.png +0 -0
- data/test/output/sample61.rb.png +0 -0
- data/test/output/sample99.rb.png +0 -0
data/lib/graphviz/core_ext.rb
CHANGED
@@ -1,43 +1,66 @@
|
|
1
1
|
class String
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
def self.random(size)
|
3
|
+
s = ""
|
4
|
+
d = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
|
5
|
+
size.times {
|
6
|
+
s << d[rand(d.size)]
|
7
|
+
}
|
8
|
+
return s
|
9
|
+
end
|
10
|
+
|
11
|
+
def convert_base(from, to)
|
12
|
+
self.to_i(from).to_s(to)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Object
|
17
|
+
def to_ruby
|
18
|
+
begin
|
19
|
+
eval self
|
20
|
+
rescue => e
|
21
|
+
self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Array
|
27
|
+
def all?(&b)
|
28
|
+
r = self.delete_if { |x|
|
29
|
+
yield x
|
30
|
+
}
|
31
|
+
r.size == 0
|
32
|
+
end
|
10
33
|
end
|
11
34
|
|
12
35
|
# From : http://www.geekmade.co.uk/2008/09/ruby-tip-normalizing-hash-keys-as-symbols/
|
13
36
|
class Hash
|
14
|
-
|
15
|
-
|
16
|
-
|
37
|
+
def symbolize_keys
|
38
|
+
inject({}) do |options, (key, value)|
|
39
|
+
options[(key.to_sym rescue key) || key] = value
|
17
40
|
options
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# x = {
|
45
|
+
# :none => String,
|
46
|
+
# :png => "file.png",
|
47
|
+
# :svg => "file.svg"
|
48
|
+
# }
|
49
|
+
#
|
50
|
+
# x.each_except( :key => [:none], :value => [/\.png$/] ) do |k, v|
|
51
|
+
# puts "#{k} -> #{v}"
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# => svg -> file.svg
|
55
|
+
def each_except( e, &b )
|
56
|
+
key_table = (e[:key]||[]).clone.delete_if {|i| i.kind_of? Regexp }
|
57
|
+
key_regexp = (e[:key]||[]).clone.delete_if {|i| key_table.include? i }.map {|i| i.to_s }.join("|")
|
35
58
|
|
36
|
-
|
37
|
-
|
59
|
+
value_table = (e[:value]||[]).clone.delete_if {|i| i.kind_of? Regexp }
|
60
|
+
value_regexp = (e[:value]||[]).clone.delete_if {|i| value_table.include? i }.map {|i| i.to_s }.join("|")
|
38
61
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
62
|
+
self.each do |k, v|
|
63
|
+
yield( k, v ) unless (key_table.size > 0 and key_table.include?(k)) or (key_regexp.size > 0 and k.to_s.match(key_regexp)) or (value_table.size > 0 and value_table.include?(v)) or (value_regexp.size > 0 and v.to_s.match(value_regexp))
|
64
|
+
end
|
65
|
+
end
|
43
66
|
end
|
data/lib/graphviz/dot2ruby.rb
CHANGED
@@ -47,4 +47,13 @@ class Dot2Ruby #:nodoc:
|
|
47
47
|
instance_eval(xOutput)
|
48
48
|
return @_graph_eval
|
49
49
|
end
|
50
|
+
|
51
|
+
def eval_string( data ) #:nodoc:
|
52
|
+
t = Tempfile::open( File.basename(__FILE__) )
|
53
|
+
t.print( data )
|
54
|
+
t.close
|
55
|
+
result = self.eval(t.path)
|
56
|
+
t.close
|
57
|
+
return result
|
58
|
+
end
|
50
59
|
end
|
data/lib/graphviz/dsl.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'graphviz'
|
2
|
+
|
3
|
+
class GraphViz::DSL
|
4
|
+
attr_accessor :graph
|
5
|
+
|
6
|
+
def initialize(name, hOpts = {}, &block)
|
7
|
+
@graph = GraphViz.new(name, hOpts)
|
8
|
+
instance_eval(&block) if block
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(sym, *args, &block)
|
12
|
+
return @graph.get_graph(sym.to_s) unless @graph.get_graph(sym.to_s).nil?
|
13
|
+
return @graph.get_node(sym.to_s) unless @graph.get_node(sym.to_s).nil?
|
14
|
+
if(@graph.respond_to?(sym, true))
|
15
|
+
@graph.send(sym, *args)
|
16
|
+
elsif(block)
|
17
|
+
@graph.add_graph(GraphViz::DSL.new(sym, { :parent => @graph, :type => @graph.type }, &block).graph)
|
18
|
+
else
|
19
|
+
@graph.add_node(sym.to_s, *args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def n(name)
|
24
|
+
return @graph.get_node(name) unless @graph.get_node(name.to_s).nil?
|
25
|
+
@graph.add_node(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def e(*args)
|
29
|
+
e = nil
|
30
|
+
last = args.shift
|
31
|
+
while current = args.shift
|
32
|
+
e = @graph.add_edge(last, current)
|
33
|
+
last = current
|
34
|
+
end
|
35
|
+
return e
|
36
|
+
end
|
37
|
+
|
38
|
+
def subgraph(name, &block)
|
39
|
+
@graph.add_graph(GraphViz::DSL.new(name, { :parent => @graph, :type => @graph.type }, &block).graph)
|
40
|
+
end
|
41
|
+
alias :cluster :subgraph
|
42
|
+
|
43
|
+
def output(hOpts = {})
|
44
|
+
@graph.output(hOpts)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def graph(name, hOpts = {}, &block)
|
49
|
+
GraphViz::DSL.new(name, hOpts.merge( { :type => "graph" } ), &block).graph
|
50
|
+
end
|
51
|
+
|
52
|
+
def digraph(name, hOpts = {}, &block)
|
53
|
+
GraphViz::DSL.new(name, hOpts.merge( { :type => "digraph" } ), &block).graph
|
54
|
+
end
|
55
|
+
|
56
|
+
def strict(name, hOpts = {}, &block)
|
57
|
+
GraphViz::DSL.new(name, hOpts.merge( { :type => "strict digraph" } ), &block).graph
|
58
|
+
end
|
59
|
+
|
data/lib/graphviz/node.rb
CHANGED
@@ -62,7 +62,7 @@ class GraphViz
|
|
62
62
|
return( (self.pg.nil?) ? nil : self.pg.root_graph )
|
63
63
|
end
|
64
64
|
|
65
|
-
|
65
|
+
#
|
66
66
|
# Set value +xAttrValue+ to the node attribut +xAttrName+
|
67
67
|
#
|
68
68
|
def []=( xAttrName, xAttrValue )
|
@@ -78,6 +78,7 @@ class GraphViz
|
|
78
78
|
xAttrName.each do |key, value|
|
79
79
|
self[key] = value
|
80
80
|
end
|
81
|
+
return self
|
81
82
|
else
|
82
83
|
(@oAttrNode[xAttrName.to_s].nil?)?nil:@oAttrNode[xAttrName.to_s].clone
|
83
84
|
end
|
data/lib/graphviz/types.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
# >> x = "hello\n\t\\l\"world\""
|
2
|
+
# => "hello\n\t\\l\"world\""
|
3
|
+
# >> puts x.inspect.gsub( "\\\\", "\\" )
|
4
|
+
# "hello\n\t\l\"world\""
|
5
|
+
#
|
6
|
+
# OR
|
7
|
+
#
|
8
|
+
# >> x = 'hello\n\t\l"world"'
|
9
|
+
# => "hello\\n\\t\\l\"world\""
|
10
|
+
# >> puts x.inspect.gsub( "\\\\", "\\" )
|
11
|
+
# "hello\n\t\l\"world\""
|
12
|
+
|
13
|
+
class GraphViz
|
14
|
+
class Types
|
15
|
+
class ArrowType < Common
|
16
|
+
def check(data)
|
17
|
+
return data
|
18
|
+
end
|
19
|
+
|
20
|
+
def output
|
21
|
+
return @data.to_s.inspect.gsub( "\\\\", "\\" )
|
22
|
+
end
|
23
|
+
|
24
|
+
alias :to_gv :output
|
25
|
+
alias :to_s :output
|
26
|
+
|
27
|
+
def to_ruby
|
28
|
+
@data
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'graphviz/utils/colors'
|
2
|
+
|
3
|
+
class ColorException < RuntimeError
|
4
|
+
end
|
5
|
+
|
6
|
+
class GraphViz
|
7
|
+
class Types
|
8
|
+
class Color < Common
|
9
|
+
HEX_FOR_COLOR = /[0-9a-fA-F]{2}/
|
10
|
+
RGBA = /^#(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})?$/
|
11
|
+
|
12
|
+
def check(data)
|
13
|
+
data = data.to_s if data.is_a?(Symbol)
|
14
|
+
if data[0].chr == "#"
|
15
|
+
m = RGBA.match(data)
|
16
|
+
if m.nil?
|
17
|
+
raise ColorException, "Wrong color definition RGBA #{data}"
|
18
|
+
end
|
19
|
+
@to_ruby = GraphViz::Utils::Colors.rgb(m[1], m[2], m[3], m[4])
|
20
|
+
return data
|
21
|
+
elsif data.include?(",") or data.include?(" ")
|
22
|
+
m = data.split(/(?:\s*,\s*|\s+)/).map { |x| x.to_f }
|
23
|
+
if m.size != 3
|
24
|
+
raise ColorException, "Wrong color definition HSV #{data}"
|
25
|
+
end
|
26
|
+
@to_ruby = GraphViz::Utils::Colors.hsv(m[0], m[1], m[2])
|
27
|
+
return data
|
28
|
+
elsif data.is_a?(Array)
|
29
|
+
if data.all? { |x| x.is_a?(String) and x =~ /^#{HEX_FOR_COLOR}$/ } and [3,4].include?(data.size)
|
30
|
+
@to_ruby = GraphViz::Utils::Colors.rgb(data[0], data[1], data[2], data[3])
|
31
|
+
return data
|
32
|
+
elsif data.all? { |x| x.kind_of?(Numeric) } and data.size == 3
|
33
|
+
@to_ruby = GraphViz::Utils::Colors.hsv(data[0], data[1], data[2])
|
34
|
+
return data
|
35
|
+
end
|
36
|
+
|
37
|
+
raise ColorException, "Wrong color definition Array #{data}"
|
38
|
+
else
|
39
|
+
@to_ruby = GraphViz::Utils::Colors.name(data)
|
40
|
+
return data
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def output
|
45
|
+
return @data.to_s.inspect.gsub( "\\\\", "\\" )
|
46
|
+
end
|
47
|
+
|
48
|
+
alias :to_gv :output
|
49
|
+
alias :to_s :output
|
50
|
+
|
51
|
+
def to_ruby
|
52
|
+
@to_ruby
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class GraphViz
|
2
|
+
class Types
|
3
|
+
class ColorList < Common
|
4
|
+
def check(data)
|
5
|
+
data = data.to_s if data.is_a?(Symbol)
|
6
|
+
@to_ruby = data.split(/\s*:\s*/).map { |c| GraphViz::Types::Color.new(c).to_ruby }
|
7
|
+
return data
|
8
|
+
end
|
9
|
+
|
10
|
+
def output
|
11
|
+
return @data.to_s.inspect.gsub( "\\\\", "\\" )
|
12
|
+
end
|
13
|
+
|
14
|
+
alias :to_gv :output
|
15
|
+
alias :to_s :output
|
16
|
+
|
17
|
+
def to_ruby
|
18
|
+
@data
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,16 +1,3 @@
|
|
1
|
-
# >> x = "hello\n\t\\l\"world\""
|
2
|
-
# => "hello\n\t\\l\"world\""
|
3
|
-
# >> puts x.inspect.gsub( "\\\\", "\\" )
|
4
|
-
# "hello\n\t\l\"world\""
|
5
|
-
#
|
6
|
-
# OR
|
7
|
-
#
|
8
|
-
# >> x = 'hello\n\t\l"world"'
|
9
|
-
# => "hello\\n\\t\\l\"world\""
|
10
|
-
# >> puts x.inspect.gsub( "\\\\", "\\" )
|
11
|
-
# "hello\n\t\l\"world\""
|
12
|
-
|
13
|
-
|
14
1
|
class GraphViz
|
15
2
|
class Types
|
16
3
|
class EscString < Common
|
@@ -24,6 +11,10 @@ class GraphViz
|
|
24
11
|
|
25
12
|
alias :to_gv :output
|
26
13
|
alias :to_s :output
|
14
|
+
|
15
|
+
def to_ruby
|
16
|
+
@data
|
17
|
+
end
|
27
18
|
end
|
28
19
|
end
|
29
|
-
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class BoolException < RuntimeError
|
2
|
+
end
|
3
|
+
|
4
|
+
# bool
|
5
|
+
#
|
6
|
+
# For the bool type,
|
7
|
+
# - TRUE values are represented by "true" or "yes" (case-insensitive), true and any non-zero integer
|
8
|
+
# - FALSE values by "false" or "no" (case-insensitive), false and zero.
|
9
|
+
#
|
10
|
+
# Example
|
11
|
+
#
|
12
|
+
# graph[:center] = "true"
|
13
|
+
# or
|
14
|
+
# graph[:center] = true
|
15
|
+
# or
|
16
|
+
# graph[:center] = 23
|
17
|
+
class GraphViz
|
18
|
+
class Types
|
19
|
+
class GvBool < Common
|
20
|
+
BOOL_TRUE = ["true", "yes"]
|
21
|
+
BOOL_FALSE = ["false", "no"]
|
22
|
+
|
23
|
+
def check(data)
|
24
|
+
if true == data or (data.is_a?(Integer) and data != 0) or (data.is_a?(String) and BOOL_TRUE.include?(data.downcase))
|
25
|
+
@to_ruby = true
|
26
|
+
return data
|
27
|
+
end
|
28
|
+
|
29
|
+
if false == data or (data.is_a?(Integer) and data == 0) or (data.is_a?(String) and BOOL_FALSE.include?(data.downcase))
|
30
|
+
@to_ruby = false
|
31
|
+
return data
|
32
|
+
end
|
33
|
+
|
34
|
+
raise BoolException, "Invalid bool value"
|
35
|
+
end
|
36
|
+
|
37
|
+
def output
|
38
|
+
return @data.to_s.inspect.gsub( "\\\\", "\\" )
|
39
|
+
end
|
40
|
+
|
41
|
+
alias :to_gv :output
|
42
|
+
alias :to_s :output
|
43
|
+
|
44
|
+
def to_ruby
|
45
|
+
@to_ruby
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,8 +1,17 @@
|
|
1
|
+
class DoubleException < RuntimeError
|
2
|
+
end
|
3
|
+
|
1
4
|
class GraphViz
|
2
5
|
class Types
|
3
6
|
class GvDouble < Common
|
7
|
+
FLOAT_MASK = /[-+]?(?:[0-9]*\.[0-9]+|[0-9]+)/
|
8
|
+
|
4
9
|
def check(data)
|
5
|
-
|
10
|
+
if data.kind_of?(Numeric) or (data.is_a?(String) and FLOAT_MASK.match(data))
|
11
|
+
return data
|
12
|
+
end
|
13
|
+
|
14
|
+
raise DoubleException, "Invalid double value"
|
6
15
|
end
|
7
16
|
|
8
17
|
def output
|
@@ -15,6 +24,7 @@ class GraphViz
|
|
15
24
|
|
16
25
|
alias :to_gv :output
|
17
26
|
alias :to_s :output
|
27
|
+
alias :to_ruby :to_f
|
18
28
|
end
|
19
29
|
end
|
20
|
-
end
|
30
|
+
end
|