dotr 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/dotr.rb +57 -33
- data/test/dotr_test.rb +36 -1
- metadata +2 -2
data/lib/dotr.rb
CHANGED
@@ -1,4 +1,22 @@
|
|
1
1
|
module DotR
|
2
|
+
module Styled # :nodoc:
|
3
|
+
def method_missing(method, *args)
|
4
|
+
return super unless /^(\w+)=$/ =~ method.to_s && args.size == 1
|
5
|
+
style_attrs()[$1.to_sym] = args.first
|
6
|
+
end
|
7
|
+
|
8
|
+
def style
|
9
|
+
return '' if style_attrs.empty?
|
10
|
+
" [" + style_attrs.keys.sort_by { |k| k.to_s }.map { |k| "#{k}=\"#{style_attrs[k]}\"" }.join(',') + "]"
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def style_attrs
|
16
|
+
@style_attrs ||= {}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
2
20
|
# This class represents a directed graph that can be rendered to a graphics
|
3
21
|
# image using its #diagram method.
|
4
22
|
#
|
@@ -14,12 +32,20 @@ module DotR
|
|
14
32
|
# end
|
15
33
|
# File.open('diagram.png', 'w') { |f| f.write(d.diagram(:png)) }
|
16
34
|
class Digraph
|
35
|
+
include Styled
|
17
36
|
attr_accessor :name
|
37
|
+
|
18
38
|
# Create a new Digraph. If a block is provided it will be called with
|
19
39
|
# the graph as a parameter.
|
20
|
-
|
40
|
+
#
|
41
|
+
# Specify styles on this object by setting instance attributes.
|
42
|
+
# Possible attributes include 'label' and 'fontsize'; the attribute names and
|
43
|
+
# possible values correspond to the style attributes described in the 'dot' manual.
|
44
|
+
def initialize(name="diagram", style={}, &block)
|
21
45
|
@name = name
|
22
46
|
@nodes = []
|
47
|
+
@subgraphs = []
|
48
|
+
style_attrs.update(style)
|
23
49
|
yield self if block
|
24
50
|
end
|
25
51
|
|
@@ -31,7 +57,7 @@ module DotR
|
|
31
57
|
end
|
32
58
|
|
33
59
|
# Create a connection in the graph between two nodes with the given names.
|
34
|
-
# If a block is provided
|
60
|
+
# If a block is provided it will be called with the connection as a parameter,
|
35
61
|
# for convenient specification of styles.
|
36
62
|
#
|
37
63
|
# Nodes with the given names are implicitly created if they have not
|
@@ -42,10 +68,24 @@ module DotR
|
|
42
68
|
end
|
43
69
|
end
|
44
70
|
|
71
|
+
# Create a subgraph of the same type, which can have distinct formatting
|
72
|
+
# and its own nodes.
|
73
|
+
#
|
74
|
+
# Example:
|
75
|
+
#
|
76
|
+
# d = DotR::Digraph.new('myname') do |g|
|
77
|
+
# g.subgraph('subg', :color => "lightgrey") do |s|
|
78
|
+
# s.connection("foo", "bar")
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
def subgraph(name, style={}, &block)
|
82
|
+
@subgraphs << self.class.new(name, style, &block)
|
83
|
+
end
|
84
|
+
|
45
85
|
# Returns the dot input script equivalent of this digraph
|
46
86
|
def to_s
|
47
87
|
script = []
|
48
|
-
render_to(script)
|
88
|
+
render_to("digraph", script)
|
49
89
|
script.flatten.join("\n") + "\n"
|
50
90
|
end
|
51
91
|
|
@@ -61,35 +101,19 @@ module DotR
|
|
61
101
|
end
|
62
102
|
end
|
63
103
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
output_lines
|
68
|
-
|
69
|
-
|
104
|
+
def render_to(graph_type, output_lines, indent="")
|
105
|
+
output_lines << "#{indent}#{graph_type} \"#{name}\" {"
|
106
|
+
@subgraphs.each { |node| node.render_to("subgraph", output_lines, indent + " ") }
|
107
|
+
@nodes.each { |node| node.render_to(output_lines, indent + " ") }
|
108
|
+
style_attrs.each do |k,v|
|
109
|
+
output_lines << "#{indent} #{k}=\"#{v}\";"
|
110
|
+
end
|
111
|
+
output_lines << "#{indent}}"
|
70
112
|
end
|
71
|
-
|
72
113
|
end
|
73
114
|
|
74
|
-
private
|
75
|
-
|
76
|
-
module Styled # :nodoc:
|
77
|
-
def method_missing(method, *args)
|
78
|
-
return super unless /^(\w+)=$/ =~ method.to_s && args.size == 1
|
79
|
-
style_attrs()[$1.to_sym] = args.first
|
80
|
-
end
|
81
|
-
|
82
|
-
def style
|
83
|
-
return '' if style_attrs.empty?
|
84
|
-
" [" + style_attrs.keys.sort_by { |k| k.to_s }.map { |k| "#{k}=\"#{style_attrs[k]}\"" }.join(',') + "]"
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
115
|
|
89
|
-
|
90
|
-
@style_attrs ||= {}
|
91
|
-
end
|
92
|
-
end
|
116
|
+
private
|
93
117
|
|
94
118
|
# Represents a node in a digraph. Instances of this class are created by calling
|
95
119
|
# Digraph#node.
|
@@ -113,9 +137,9 @@ module DotR
|
|
113
137
|
@connections << Connection.new(self.name, other_node_name, style, &block)
|
114
138
|
end
|
115
139
|
|
116
|
-
def render_to(output_lines) #:nodoc:
|
117
|
-
output_lines << "\"#{self.name}\"" + style + ";"
|
118
|
-
@connections.each { |c| c.render_to(output_lines) }
|
140
|
+
def render_to(output_lines, indent) #:nodoc:
|
141
|
+
output_lines << "#{indent}\"#{self.name}\"" + style + ";"
|
142
|
+
@connections.each { |c| c.render_to(output_lines, indent) }
|
119
143
|
end
|
120
144
|
end
|
121
145
|
|
@@ -137,8 +161,8 @@ module DotR
|
|
137
161
|
yield self if block
|
138
162
|
end
|
139
163
|
|
140
|
-
def render_to(output_lines) # :nodoc:
|
141
|
-
output_lines << "\"#{from_name}\" -> \"#{to_name}\"" + style + ";"
|
164
|
+
def render_to(output_lines, indent) # :nodoc:
|
165
|
+
output_lines << "#{indent}\"#{from_name}\" -> \"#{to_name}\"" + style + ";"
|
142
166
|
end
|
143
167
|
end
|
144
168
|
end
|
data/test/dotr_test.rb
CHANGED
@@ -102,10 +102,45 @@ class DotRDigraphTest < Test::Unit::TestCase
|
|
102
102
|
END
|
103
103
|
end
|
104
104
|
|
105
|
+
def test_can_style_nodes_independently
|
106
|
+
d = DotR::Digraph.new do |graph|
|
107
|
+
graph.node('foo', :fontsize => 8)
|
108
|
+
graph.node('bar', :fontsize => 5, :label => "Bar")
|
109
|
+
end
|
110
|
+
assert_digraph_equals <<-END, d
|
111
|
+
digraph "diagram" {
|
112
|
+
"foo" [fontsize="8",label="foo"];
|
113
|
+
"bar" [fontsize="5",label="Bar"];
|
114
|
+
}
|
115
|
+
END
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_can_style_empty_graph
|
119
|
+
d = DotR::Digraph.new('myname', :fontsize => 6)
|
120
|
+
assert_digraph_equals <<-END, d
|
121
|
+
digraph "myname" {
|
122
|
+
fontsize="6";
|
123
|
+
}
|
124
|
+
END
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_can_define_empty_subgraph
|
128
|
+
d = DotR::Digraph.new('myname') do |g|
|
129
|
+
g.subgraph('subg')
|
130
|
+
end
|
131
|
+
assert_digraph_equals <<-END, d
|
132
|
+
digraph "myname" {
|
133
|
+
subgraph "subg" {
|
134
|
+
}
|
135
|
+
}
|
136
|
+
END
|
137
|
+
end
|
138
|
+
|
105
139
|
private
|
106
140
|
|
107
141
|
def assert_digraph_equals expected, digraph
|
108
|
-
|
142
|
+
prefix = expected.scan(/^(\s+)/).first
|
143
|
+
assert_equal(expected.strip.gsub(/^#{prefix}/, ''), digraph.to_s.strip)
|
109
144
|
end
|
110
145
|
|
111
146
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: dotr
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date:
|
6
|
+
version: "0.3"
|
7
|
+
date: 2007-02-11 00:00:00 +01:00
|
8
8
|
summary: Produce directed graph images using the 'dot' utility.
|
9
9
|
require_paths:
|
10
10
|
- lib
|