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.
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