dotr 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/dotr.rb +57 -33
  2. data/test/dotr_test.rb +36 -1
  3. metadata +2 -2
@@ -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
- def initialize(name="diagram", &block)
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 # it will be called with the connection as a parameter,
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
- private
65
-
66
- def render_to(output_lines)
67
- output_lines << "digraph \"#{name}\" {"
68
- @nodes.each { |node| node.render_to(output_lines) }
69
- output_lines << '}'
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
- def style_attrs
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
@@ -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
- assert_equal(expected.strip.gsub(/^\s+/, ''), digraph.to_s.strip)
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.2"
7
- date: 2006-12-03 00:00:00 +01:00
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