luquet-ruby-graphviz 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
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