dotr 0.2 → 0.3
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/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
|