luquet-ruby-graphviz 0.9.5

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 (65) hide show
  1. data/AUTHORS +7 -0
  2. data/COPYING +340 -0
  3. data/ChangeLog +66 -0
  4. data/README.rdoc +69 -0
  5. data/bin/ruby2gv +194 -0
  6. data/examples/HTML-Labels.rb +20 -0
  7. data/examples/arrowhead.rb +97 -0
  8. data/examples/dot/cluster.dot +31 -0
  9. data/examples/dot/fsm.dot +20 -0
  10. data/examples/dot/genetic.dot +118 -0
  11. data/examples/dot/hello.dot +1 -0
  12. data/examples/dot/hello_test.rb +14 -0
  13. data/examples/dot/lion_share.dot +103 -0
  14. data/examples/dot/prof.dot +150 -0
  15. data/examples/dot/psg.dot +28 -0
  16. data/examples/dot/sdh.dot +284 -0
  17. data/examples/dot/siblings.dot +492 -0
  18. data/examples/dot/test.dot +17 -0
  19. data/examples/dot/unix.dot +104 -0
  20. data/examples/graphviz.org/TrafficLights.rb +62 -0
  21. data/examples/graphviz.org/cluster.rb +62 -0
  22. data/examples/graphviz.org/hello_world.rb +10 -0
  23. data/examples/graphviz.org/lion_share.rb +215 -0
  24. data/examples/graphviz.org/process.rb +37 -0
  25. data/examples/maketest.sh +85 -0
  26. data/examples/p2p.rb +35 -0
  27. data/examples/sample01.rb +32 -0
  28. data/examples/sample02.rb +42 -0
  29. data/examples/sample03.rb +31 -0
  30. data/examples/sample04.rb +22 -0
  31. data/examples/sample05.rb +32 -0
  32. data/examples/sample06.rb +46 -0
  33. data/examples/sample07.rb +23 -0
  34. data/examples/sample08.rb +34 -0
  35. data/examples/sample09.rb +50 -0
  36. data/examples/sample10.rb +50 -0
  37. data/examples/sample11.rb +42 -0
  38. data/examples/sample12.rb +55 -0
  39. data/examples/sample13.rb +48 -0
  40. data/examples/sample14.rb +44 -0
  41. data/examples/sample15.rb +23 -0
  42. data/examples/sample16.rb +8 -0
  43. data/examples/sample17.rb +92 -0
  44. data/examples/sample18.rb +24 -0
  45. data/examples/sample19.rb +59 -0
  46. data/examples/sample20.rb +47 -0
  47. data/examples/sample21.rb +12 -0
  48. data/examples/sample22.rb +10 -0
  49. data/examples/sample23.rb +11 -0
  50. data/examples/sample24.rb +11 -0
  51. data/examples/sample25.rb +11 -0
  52. data/examples/shapes.rb +24 -0
  53. data/examples/test.xml +26 -0
  54. data/examples/testorder.rb +43 -0
  55. data/examples/testxml.rb +7 -0
  56. data/lib/graphviz.rb +655 -0
  57. data/lib/graphviz/attrs.rb +51 -0
  58. data/lib/graphviz/constants.rb +246 -0
  59. data/lib/graphviz/dot.treetop +97 -0
  60. data/lib/graphviz/edge.rb +130 -0
  61. data/lib/graphviz/node.rb +129 -0
  62. data/lib/graphviz/parser.rb +249 -0
  63. data/lib/graphviz/xml.rb +131 -0
  64. data/setup.rb +1585 -0
  65. metadata +176 -0
@@ -0,0 +1,129 @@
1
+ # Copyright (C) 2004, 2005, 2006, 2007, 2008 Gregoire Lejeune <gregoire.lejeune@free.fr>
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, write to the Free Software
15
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
+
17
+ require 'graphviz/attrs'
18
+ require 'graphviz/constants'
19
+
20
+ class GraphViz
21
+ class Node
22
+ include Constants
23
+ @xNodeName
24
+ @oAttrNode
25
+ @oGParrent
26
+
27
+ #
28
+ # Create a new node
29
+ #
30
+ # In:
31
+ # * xNodeName : Name of the node
32
+ # * oGParrent : Graph
33
+ #
34
+ def initialize( xNodeName, oGParrent = nil )
35
+ @xNodeName = xNodeName
36
+ @oGParrent = oGParrent
37
+ @oAttrNode = GraphViz::Attrs::new( nil, "node", NODESATTRS )
38
+ end
39
+
40
+ #
41
+ # Get the node name
42
+ #
43
+ def name
44
+ @xNodeName.clone
45
+ end
46
+
47
+ #
48
+ # Set value +xAttrValue+ to the node attribut +xAttrName+
49
+ #
50
+ def []=( xAttrName, xAttrValue )
51
+ xAttrValue = xAttrValue.to_s if xAttrValue.class == Symbol
52
+ @oAttrNode[xAttrName.to_s] = xAttrValue
53
+ end
54
+
55
+ #
56
+ # Get the value of the node attribut +xAttrName+
57
+ #
58
+ def []( xAttrName )
59
+ @oAttrNode[xAttrName.to_s].clone
60
+ end
61
+
62
+ #
63
+ # Create an edge between the current node and the node +oNode+
64
+ #
65
+ def <<( oNode )
66
+ if( oNode.class == Array )
67
+ oNode.each do |no|
68
+ self << no
69
+ end
70
+ else
71
+ return GraphViz::commonGraph( oNode, self ).add_edge( self, oNode )
72
+ end
73
+ end
74
+ alias :> :<<
75
+ alias :- :<<
76
+ alias :>> :<<
77
+
78
+ #
79
+ # Set node attributs
80
+ #
81
+ # Example :
82
+ # n = graph.add_node( ... )
83
+ # ...
84
+ # n.set { |_n|
85
+ # _n.color = "blue"
86
+ # _n.fontcolor = "red"
87
+ # }
88
+ #
89
+ def set( &b )
90
+ yield( self )
91
+ end
92
+
93
+ # Add node options
94
+ # use node.<option>=<value> or node.<option>( <value> )
95
+ def method_missing( idName, *args, &block ) #:nodoc:
96
+ xName = idName.id2name
97
+
98
+ self[xName.gsub( /=$/, "" )]=args[0]
99
+ end
100
+
101
+ def pg #:nodoc:
102
+ @oGParrent
103
+ end
104
+
105
+ def output #:nodoc:
106
+ #xNodeName = @xNodeName.clone
107
+ #xNodeName = '"' << xNodeName << '"' if xNodeName.match( /^[a-zA-Z_]+[a-zA-Z0-9_\.]*$/ ).nil?
108
+ xNodeName = GraphViz.escape(@xNodeName)
109
+
110
+ xOut = "" << xNodeName
111
+ xAttr = ""
112
+ xSeparator = ""
113
+ @oAttrNode.data.each do |k, v|
114
+ if k == "html"
115
+ xAttr << xSeparator + "label = <" + v + ">"
116
+ else
117
+ xAttr << xSeparator + k + " = " + GraphViz.escape(v, true)
118
+ end
119
+ xSeparator = ", "
120
+ end
121
+ if xAttr.length > 0
122
+ xOut << " [" + xAttr + "]"
123
+ end
124
+ xOut << ";"
125
+
126
+ return( xOut )
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,249 @@
1
+ require 'rubygems'
2
+ require 'treetop'
3
+
4
+ Treetop.load File.dirname(__FILE__) + '/dot.treetop'
5
+
6
+ class GraphViz
7
+ class Parser
8
+
9
+ class Context
10
+ def initialize
11
+ @graph = nil
12
+ @nodes = {}
13
+ @edges = []
14
+ @options = {
15
+ :node => {},
16
+ :edge => {}
17
+ }
18
+ end
19
+
20
+ def graph
21
+ @graph
22
+ end
23
+
24
+ def graph=(g)
25
+ @graph = g
26
+ end
27
+
28
+ def nodes
29
+ @nodes
30
+ end
31
+
32
+ def edges
33
+ @edges
34
+ end
35
+
36
+ def options
37
+ @options
38
+ end
39
+
40
+ def options=(o)
41
+ @options = o
42
+ end
43
+ end
44
+
45
+ class Graph < Treetop::Runtime::SyntaxNode
46
+ def eval( context, hOpts )
47
+ # puts "GRAPH TYPE = #{type.text_value}"
48
+ # puts "GRAPH NAME = #{name.text_value}"
49
+
50
+ hOpts = hOpts[0].merge( {:type => type.text_value} )
51
+
52
+ # Create Graph
53
+ context.graph = GraphViz.new( name.text_value.gsub(/"/, ""), hOpts )
54
+
55
+ # Eval cluster
56
+ cluster.eval( context )
57
+
58
+ return context.graph
59
+ end
60
+ end
61
+
62
+ class Cluster < Treetop::Runtime::SyntaxNode
63
+ def eval( context )
64
+ content.elements.each do |e|
65
+ e.eval( context )
66
+ end
67
+ end
68
+ end
69
+
70
+ class GraphPreference < Treetop::Runtime::SyntaxNode
71
+ def eval( context )
72
+ # puts "GRAPH PREFERENCE : "
73
+ # puts " #{key.text_value} = #{value.text_value.gsub(/"/, "")}"
74
+ context.graph[key.text_value] = value.text_value.gsub(/"/, "")
75
+ end
76
+ end
77
+
78
+ class NamedGraphPreference < Treetop::Runtime::SyntaxNode
79
+ def eval( context )
80
+ # puts "GRAPH PREFERENCES :"
81
+ options.eval().each do |k,v|
82
+ context.graph[k] = v
83
+ end
84
+ end
85
+ end
86
+
87
+ class NodePreference < Treetop::Runtime::SyntaxNode
88
+ def eval( context )
89
+ # puts "NODE PREFERENCES :"
90
+ context.options[:node] = context.options[:node].merge( options.eval() )
91
+ end
92
+ end
93
+
94
+ class EdgePreference < Treetop::Runtime::SyntaxNode
95
+ def eval( context )
96
+ # puts "EDGE PREFERENCES :"
97
+ context.options[:edge] = context.options[:edge].merge( options.eval() )
98
+ end
99
+ end
100
+
101
+ class Node < Treetop::Runtime::SyntaxNode
102
+ def eval( context )
103
+ node_name = name.text_value.gsub( /"/, "" )
104
+ # puts "NODE NAME = #{node_name}"
105
+ # puts "OPTIONS = "
106
+
107
+ # Create node
108
+ node = context.nodes[node_name] || context.graph.add_node( node_name )
109
+
110
+ # Add global options
111
+ context.options[:node].each do |k, v|
112
+ node[k] = v
113
+ end
114
+
115
+ # Add custom options
116
+ unless options.terminal?
117
+ options.eval().each do |k, v|
118
+ node[k] = v
119
+ end
120
+ end
121
+
122
+ # Save node
123
+ context.nodes[node_name] = node
124
+ end
125
+ end
126
+
127
+ class Edge < Treetop::Runtime::SyntaxNode
128
+ def create_node( name, context )
129
+ # puts " NEED TO CREATE NODE : #{name}"
130
+ # Create the node
131
+ node = context.graph.add_node( name )
132
+
133
+ # Add global options
134
+ context.options[:node].each do |k, v|
135
+ node[k] = v
136
+ end
137
+
138
+ # Save node
139
+ context.nodes[name] = node
140
+ end
141
+
142
+ def create_edge( one, two, edge_options, context )
143
+ # Create edge
144
+ edge = context.graph.add_edge( one, two )
145
+
146
+ # Add global options
147
+ context.options[:edge].each do |k, v|
148
+ edge[k] = v
149
+ end
150
+
151
+ # Add custom options
152
+ edge_options.each do |k, v|
153
+ edge[k] = v
154
+ end
155
+
156
+ # Save edge
157
+ context.edges << edge
158
+ end
159
+
160
+ def eval( context )
161
+ one_name = node_one.text_value.gsub( /"/, "" )
162
+ two_name = node_two.text_value.gsub( /"/, "" )
163
+ # puts "EDGE"
164
+ # puts "NODE ONE = #{one_name}"
165
+ # puts "NODE TWO = #{two_name}"
166
+ # puts "OPTIONS = "
167
+
168
+ # Get or create node one
169
+ one = context.nodes[one_name] || create_node( one_name, context )
170
+
171
+ # Get or create node two
172
+ two = context.nodes[two_name] || create_node( two_name, context )
173
+
174
+ # Get options
175
+ edge_options = {}
176
+ edge_options = options.eval() unless options.terminal?
177
+
178
+ # Create edge
179
+ create_edge( one, two, edge_options, context )
180
+
181
+ last_node = two
182
+ other_nodes.elements.each do |e|
183
+ new_node_name = e.next_node.text_value.gsub( /"/, "" )
184
+ # puts "OTHER NODE : #{new_node_name}"
185
+
186
+ new_node = context.nodes[new_node_name] || create_node( new_node_name, context )
187
+ create_edge( last_node, new_node, edge_options, context )
188
+
189
+ last_node = new_node
190
+ end
191
+ end
192
+ end
193
+
194
+ class Subgraph < Treetop::Runtime::SyntaxNode
195
+ def eval( context )
196
+ # puts "CREATE SUBGRAPH : #{name.text_value}"
197
+
198
+ # Save options
199
+ saved_options = context.options.clone
200
+ # Save graph
201
+ saved_graph = context.graph
202
+
203
+ # Create Graph
204
+ context.graph = context.graph.add_graph( name.text_value.gsub(/"/, "") )
205
+ #context.options = {
206
+ # :node => {},
207
+ # :edge => {}
208
+ #}
209
+
210
+ # Eval cluster
211
+ cluster.eval( context )
212
+
213
+ # Reinitialize graph and options
214
+ context.graph = saved_graph
215
+ context.options = saved_options
216
+ end
217
+ end
218
+
219
+ class Options < Treetop::Runtime::SyntaxNode
220
+ def eval
221
+ options = {}
222
+ elements[2].elements.each do |e|
223
+ # puts " #{e.elements[0].text_value} = #{e.elements[4].text_value}"
224
+ options[e.elements[0].text_value] = e.elements[4].text_value.gsub( /"/, "" )
225
+ end
226
+ # puts " #{elements[3].text_value} = #{elements[7].text_value}"
227
+ options[elements[3].text_value] = elements[7].text_value.gsub( /"/, "" )
228
+
229
+ return options
230
+ end
231
+ end
232
+
233
+ class Rank < Treetop::Runtime::SyntaxNode
234
+ def eval( context )
235
+ end
236
+ end
237
+
238
+ def self.parse( file, *hOpts, &block )
239
+ dot = open(file).read
240
+ parser = DotParser.new()
241
+ tree = parser.parse( dot )
242
+ graph = tree.eval( GraphViz::Parser::Context.new(), hOpts )
243
+
244
+ yield( graph ) if( block and graph.nil? == false )
245
+
246
+ return graph
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,131 @@
1
+ # Copyright (C) 2004, 2005, 2006, 2007, 2008 Gregoire Lejeune <gregoire.lejeune@free.fr>
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, write to the Free Software
15
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
+
17
+ require 'graphviz'
18
+ require 'rexml/document'
19
+
20
+ class GraphViz
21
+ class XML
22
+
23
+ @oReXML
24
+ @oGraph
25
+ @xNodeName
26
+ @bShowText
27
+ @bShowAttrs
28
+
29
+ #
30
+ # Generate the graph
31
+ #
32
+ # Options :
33
+ # * :output : Output format (Constants::FORMATS)
34
+ # * :file : Output file name
35
+ # * :use : Program to use (Constants::PROGRAMS)
36
+ # * :path : Program PATH
37
+ # * :<format> => <file> : <file> can be
38
+ # * a file name
39
+ # * nil, then the output will be printed to STDOUT
40
+ # * String, then the output will be returned as a String
41
+ # * :errors : DOT error level (default 1)
42
+ # * 0 = Error + Warning
43
+ # * 1 = Error
44
+ # * 2 = none
45
+ #
46
+ def output( *hOpt )
47
+ @oGraph.output( *hOpt )
48
+ end
49
+
50
+ private
51
+
52
+ #
53
+ # Create a graph from a XML file
54
+ #
55
+ # In:
56
+ # * xFile : XML File
57
+ # * *hOpt : Graph options
58
+ #
59
+ def initialize( xFile, *hOpt )
60
+ @xNodeName = "00000"
61
+ @bShowText = true
62
+ @bShowAttrs = true
63
+
64
+ if hOpt.nil? == false and hOpt[0].nil? == false
65
+ hOpt[0].each do |xKey, xValue|
66
+ case xKey.to_s
67
+ when "text"
68
+ @bShowText = xValue
69
+ hOpt[0].delete( xKey )
70
+ when "attrs"
71
+ @bShowAttrs = xValue
72
+ hOpt[0].delete( xKey )
73
+ end
74
+ end
75
+ end
76
+
77
+ @oReXML = REXML::Document::new( File::new( xFile ) )
78
+ @oGraph = GraphViz::new( "XML", *hOpt )
79
+ _init( @oReXML.root() )
80
+ end
81
+
82
+ def _init( oXMLNode ) #:nodoc:
83
+ xLocalNodeName = @xNodeName.clone
84
+ @xNodeName.succ!
85
+
86
+ label = oXMLNode.name
87
+ if oXMLNode.has_attributes? == true and @bShowAttrs == true
88
+ label = "{ " + oXMLNode.name
89
+
90
+ oXMLNode.attributes.each do |xName, xValue|
91
+ label << "| { #{xName} | #{xValue} } "
92
+ end
93
+
94
+ label << "}"
95
+ end
96
+ @oGraph.add_node( xLocalNodeName, "label" => label, "color" => "blue", "shape" => "record" )
97
+
98
+ ## Act: Search and add Text nodes
99
+ if oXMLNode.has_text? == true and @bShowText == true
100
+ xTextNodeName = xLocalNodeName.clone
101
+ xTextNodeName << "111"
102
+
103
+ xText = ""
104
+ xSep = ""
105
+ oXMLNode.texts().each do |l|
106
+ x = l.value.chomp.strip
107
+ if x.length > 0
108
+ xText << xSep << x
109
+ xSep = "\n"
110
+ end
111
+ end
112
+
113
+ if xText.length > 0
114
+ @oGraph.add_node( xTextNodeName, "label" => xText, "color" => "black", "shape" => "ellipse" )
115
+ @oGraph.add_edge( xLocalNodeName, xTextNodeName )
116
+ end
117
+ end
118
+
119
+ ## Act: Search and add attributs
120
+ ## TODO
121
+
122
+ oXMLNode.each_element( ) do |oXMLChild|
123
+ xChildNodeName = _init( oXMLChild )
124
+ @oGraph.add_edge( xLocalNodeName, xChildNodeName )
125
+ end
126
+
127
+ return( xLocalNodeName )
128
+ end
129
+
130
+ end
131
+ end