iownbey-rdoc 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/History.txt +13 -0
  2. data/Manifest.txt +61 -0
  3. data/README.txt +34 -0
  4. data/bin/rdoc +22 -0
  5. data/bin/ri +6 -0
  6. data/lib/rdoc.rb +277 -0
  7. data/lib/rdoc/code_objects.rb +776 -0
  8. data/lib/rdoc/diagram.rb +338 -0
  9. data/lib/rdoc/dot.rb +249 -0
  10. data/lib/rdoc/generator.rb +1050 -0
  11. data/lib/rdoc/generator/chm.rb +113 -0
  12. data/lib/rdoc/generator/chm/chm.rb +98 -0
  13. data/lib/rdoc/generator/html.rb +370 -0
  14. data/lib/rdoc/generator/html/hefss.rb +414 -0
  15. data/lib/rdoc/generator/html/html.rb +704 -0
  16. data/lib/rdoc/generator/html/kilmer.rb +418 -0
  17. data/lib/rdoc/generator/html/one_page_html.rb +121 -0
  18. data/lib/rdoc/generator/ri.rb +229 -0
  19. data/lib/rdoc/generator/texinfo.rb +84 -0
  20. data/lib/rdoc/generator/texinfo/class.texinfo.erb +44 -0
  21. data/lib/rdoc/generator/texinfo/file.texinfo.erb +6 -0
  22. data/lib/rdoc/generator/texinfo/method.texinfo.erb +6 -0
  23. data/lib/rdoc/generator/texinfo/texinfo.erb +28 -0
  24. data/lib/rdoc/generator/xml.rb +120 -0
  25. data/lib/rdoc/generator/xml/rdf.rb +113 -0
  26. data/lib/rdoc/generator/xml/xml.rb +111 -0
  27. data/lib/rdoc/markup.rb +473 -0
  28. data/lib/rdoc/markup/attribute_manager.rb +274 -0
  29. data/lib/rdoc/markup/formatter.rb +14 -0
  30. data/lib/rdoc/markup/fragments.rb +337 -0
  31. data/lib/rdoc/markup/inline.rb +101 -0
  32. data/lib/rdoc/markup/lines.rb +152 -0
  33. data/lib/rdoc/markup/preprocess.rb +71 -0
  34. data/lib/rdoc/markup/to_flow.rb +185 -0
  35. data/lib/rdoc/markup/to_html.rb +354 -0
  36. data/lib/rdoc/markup/to_html_crossref.rb +86 -0
  37. data/lib/rdoc/markup/to_latex.rb +328 -0
  38. data/lib/rdoc/markup/to_test.rb +50 -0
  39. data/lib/rdoc/markup/to_texinfo.rb +69 -0
  40. data/lib/rdoc/options.rb +621 -0
  41. data/lib/rdoc/parsers/parse_c.rb +775 -0
  42. data/lib/rdoc/parsers/parse_f95.rb +1841 -0
  43. data/lib/rdoc/parsers/parse_rb.rb +2584 -0
  44. data/lib/rdoc/parsers/parse_simple.rb +40 -0
  45. data/lib/rdoc/parsers/parserfactory.rb +99 -0
  46. data/lib/rdoc/rdoc.rb +277 -0
  47. data/lib/rdoc/ri.rb +4 -0
  48. data/lib/rdoc/ri/cache.rb +188 -0
  49. data/lib/rdoc/ri/descriptions.rb +150 -0
  50. data/lib/rdoc/ri/display.rb +274 -0
  51. data/lib/rdoc/ri/driver.rb +452 -0
  52. data/lib/rdoc/ri/formatter.rb +616 -0
  53. data/lib/rdoc/ri/paths.rb +102 -0
  54. data/lib/rdoc/ri/reader.rb +106 -0
  55. data/lib/rdoc/ri/util.rb +81 -0
  56. data/lib/rdoc/ri/writer.rb +68 -0
  57. data/lib/rdoc/stats.rb +25 -0
  58. data/lib/rdoc/template.rb +64 -0
  59. data/lib/rdoc/tokenstream.rb +33 -0
  60. data/test/test_rdoc_c_parser.rb +261 -0
  61. data/test/test_rdoc_info_formatting.rb +179 -0
  62. data/test/test_rdoc_info_sections.rb +93 -0
  63. data/test/test_rdoc_markup.rb +613 -0
  64. data/test/test_rdoc_markup_attribute_manager.rb +224 -0
  65. data/test/test_rdoc_ri_attribute_formatter.rb +42 -0
  66. data/test/test_rdoc_ri_default_display.rb +295 -0
  67. data/test/test_rdoc_ri_formatter.rb +318 -0
  68. data/test/test_rdoc_ri_overstrike_formatter.rb +69 -0
  69. metadata +142 -0
@@ -0,0 +1,338 @@
1
+ # A wonderful hack by to draw package diagrams using the dot package.
2
+ # Originally written by Jah, team Enticla.
3
+ #
4
+ # You must have the V1.7 or later in your path
5
+ # http://www.research.att.com/sw/tools/graphviz/
6
+
7
+ require 'rdoc/dot'
8
+
9
+ module RDoc
10
+
11
+ ##
12
+ # Draw a set of diagrams representing the modules and classes in the
13
+ # system. We draw one diagram for each file, and one for each toplevel
14
+ # class or module. This means there will be overlap. However, it also
15
+ # means that you'll get better context for objects.
16
+ #
17
+ # To use, simply
18
+ #
19
+ # d = Diagram.new(info) # pass in collection of top level infos
20
+ # d.draw
21
+ #
22
+ # The results will be written to the +dot+ subdirectory. The process
23
+ # also sets the +diagram+ attribute in each object it graphs to
24
+ # the name of the file containing the image. This can be used
25
+ # by output generators to insert images.
26
+
27
+ class Diagram
28
+
29
+ FONT = "Arial"
30
+
31
+ DOT_PATH = "dot"
32
+
33
+ ##
34
+ # Pass in the set of top level objects. The method also creates the
35
+ # subdirectory to hold the images
36
+
37
+ def initialize(info, options)
38
+ @info = info
39
+ @options = options
40
+ @counter = 0
41
+ FileUtils.mkdir_p(DOT_PATH)
42
+ @diagram_cache = {}
43
+ end
44
+
45
+ ##
46
+ # Draw the diagrams. We traverse the files, drawing a diagram for each. We
47
+ # also traverse each top-level class and module in that file drawing a
48
+ # diagram for these too.
49
+
50
+ def draw
51
+ unless @options.quiet
52
+ $stderr.print "Diagrams: "
53
+ $stderr.flush
54
+ end
55
+
56
+ @info.each_with_index do |i, file_count|
57
+ @done_modules = {}
58
+ @local_names = find_names(i)
59
+ @global_names = []
60
+ @global_graph = graph = DOT::Digraph.new('name' => 'TopLevel',
61
+ 'fontname' => FONT,
62
+ 'fontsize' => '8',
63
+ 'bgcolor' => 'lightcyan1',
64
+ 'compound' => 'true')
65
+
66
+ # it's a little hack %) i'm too lazy to create a separate class
67
+ # for default node
68
+ graph << DOT::Node.new('name' => 'node',
69
+ 'fontname' => FONT,
70
+ 'color' => 'black',
71
+ 'fontsize' => 8)
72
+
73
+ i.modules.each do |mod|
74
+ draw_module(mod, graph, true, i.file_relative_name)
75
+ end
76
+ add_classes(i, graph, i.file_relative_name)
77
+
78
+ i.diagram = convert_to_png("f_#{file_count}", graph)
79
+
80
+ # now go through and document each top level class and
81
+ # module independently
82
+ i.modules.each_with_index do |mod, count|
83
+ @done_modules = {}
84
+ @local_names = find_names(mod)
85
+ @global_names = []
86
+
87
+ @global_graph = graph = DOT::Digraph.new('name' => 'TopLevel',
88
+ 'fontname' => FONT,
89
+ 'fontsize' => '8',
90
+ 'bgcolor' => 'lightcyan1',
91
+ 'compound' => 'true')
92
+
93
+ graph << DOT::Node.new('name' => 'node',
94
+ 'fontname' => FONT,
95
+ 'color' => 'black',
96
+ 'fontsize' => 8)
97
+ draw_module(mod, graph, true)
98
+ mod.diagram = convert_to_png("m_#{file_count}_#{count}",
99
+ graph)
100
+ end
101
+ end
102
+ $stderr.puts unless @options.quiet
103
+ end
104
+
105
+ private
106
+
107
+ def find_names(mod)
108
+ return [mod.full_name] + mod.classes.collect{|cl| cl.full_name} +
109
+ mod.modules.collect{|m| find_names(m)}.flatten
110
+ end
111
+
112
+ def find_full_name(name, mod)
113
+ full_name = name.dup
114
+ return full_name if @local_names.include?(full_name)
115
+ mod_path = mod.full_name.split('::')[0..-2]
116
+ unless mod_path.nil?
117
+ until mod_path.empty?
118
+ full_name = mod_path.pop + '::' + full_name
119
+ return full_name if @local_names.include?(full_name)
120
+ end
121
+ end
122
+ return name
123
+ end
124
+
125
+ def draw_module(mod, graph, toplevel = false, file = nil)
126
+ return if @done_modules[mod.full_name] and not toplevel
127
+
128
+ @counter += 1
129
+ url = mod.http_url("classes")
130
+ m = DOT::Subgraph.new('name' => "cluster_#{mod.full_name.gsub( /:/,'_' )}",
131
+ 'label' => mod.name,
132
+ 'fontname' => FONT,
133
+ 'color' => 'blue',
134
+ 'style' => 'filled',
135
+ 'URL' => %{"#{url}"},
136
+ 'fillcolor' => toplevel ? 'palegreen1' : 'palegreen3')
137
+
138
+ @done_modules[mod.full_name] = m
139
+ add_classes(mod, m, file)
140
+ graph << m
141
+
142
+ unless mod.includes.empty?
143
+ mod.includes.each do |inc|
144
+ m_full_name = find_full_name(inc.name, mod)
145
+ if @local_names.include?(m_full_name)
146
+ @global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
147
+ 'to' => "#{mod.full_name.gsub( /:/,'_' )}",
148
+ 'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}",
149
+ 'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
150
+ else
151
+ unless @global_names.include?(m_full_name)
152
+ path = m_full_name.split("::")
153
+ url = File.join('classes', *path) + ".html"
154
+ @global_graph << DOT::Node.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
155
+ 'shape' => 'box',
156
+ 'label' => "#{m_full_name}",
157
+ 'URL' => %{"#{url}"})
158
+ @global_names << m_full_name
159
+ end
160
+ @global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
161
+ 'to' => "#{mod.full_name.gsub( /:/,'_' )}",
162
+ 'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ def add_classes(container, graph, file = nil )
169
+
170
+ use_fileboxes = @options.fileboxes
171
+
172
+ files = {}
173
+
174
+ # create dummy node (needed if empty and for module includes)
175
+ if container.full_name
176
+ graph << DOT::Node.new('name' => "#{container.full_name.gsub( /:/,'_' )}",
177
+ 'label' => "",
178
+ 'width' => (container.classes.empty? and
179
+ container.modules.empty?) ?
180
+ '0.75' : '0.01',
181
+ 'height' => '0.01',
182
+ 'shape' => 'plaintext')
183
+ end
184
+
185
+ container.classes.each_with_index do |cl, cl_index|
186
+ last_file = cl.in_files[-1].file_relative_name
187
+
188
+ if use_fileboxes && !files.include?(last_file)
189
+ @counter += 1
190
+ files[last_file] =
191
+ DOT::Subgraph.new('name' => "cluster_#{@counter}",
192
+ 'label' => "#{last_file}",
193
+ 'fontname' => FONT,
194
+ 'color'=>
195
+ last_file == file ? 'red' : 'black')
196
+ end
197
+
198
+ next if cl.name == 'Object' || cl.name[0,2] == "<<"
199
+
200
+ url = cl.http_url("classes")
201
+
202
+ label = cl.name.dup
203
+ if use_fileboxes && cl.in_files.length > 1
204
+ label << '\n[' +
205
+ cl.in_files.collect {|i|
206
+ i.file_relative_name
207
+ }.sort.join( '\n' ) +
208
+ ']'
209
+ end
210
+
211
+ attrs = {
212
+ 'name' => "#{cl.full_name.gsub( /:/, '_' )}",
213
+ 'fontcolor' => 'black',
214
+ 'style'=>'filled',
215
+ 'color'=>'palegoldenrod',
216
+ 'label' => label,
217
+ 'shape' => 'ellipse',
218
+ 'URL' => %{"#{url}"}
219
+ }
220
+
221
+ c = DOT::Node.new(attrs)
222
+
223
+ if use_fileboxes
224
+ files[last_file].push c
225
+ else
226
+ graph << c
227
+ end
228
+ end
229
+
230
+ if use_fileboxes
231
+ files.each_value do |val|
232
+ graph << val
233
+ end
234
+ end
235
+
236
+ unless container.classes.empty?
237
+ container.classes.each_with_index do |cl, cl_index|
238
+ cl.includes.each do |m|
239
+ m_full_name = find_full_name(m.name, cl)
240
+ if @local_names.include?(m_full_name)
241
+ @global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
242
+ 'to' => "#{cl.full_name.gsub( /:/,'_' )}",
243
+ 'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}")
244
+ else
245
+ unless @global_names.include?(m_full_name)
246
+ path = m_full_name.split("::")
247
+ url = File.join('classes', *path) + ".html"
248
+ @global_graph << DOT::Node.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
249
+ 'shape' => 'box',
250
+ 'label' => "#{m_full_name}",
251
+ 'URL' => %{"#{url}"})
252
+ @global_names << m_full_name
253
+ end
254
+ @global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
255
+ 'to' => "#{cl.full_name.gsub( /:/, '_')}")
256
+ end
257
+ end
258
+
259
+ sclass = cl.superclass
260
+ next if sclass.nil? || sclass == 'Object'
261
+ sclass_full_name = find_full_name(sclass,cl)
262
+ unless @local_names.include?(sclass_full_name) or @global_names.include?(sclass_full_name)
263
+ path = sclass_full_name.split("::")
264
+ url = File.join('classes', *path) + ".html"
265
+ @global_graph << DOT::Node.new('name' => "#{sclass_full_name.gsub( /:/, '_' )}",
266
+ 'label' => sclass_full_name,
267
+ 'URL' => %{"#{url}"})
268
+ @global_names << sclass_full_name
269
+ end
270
+ @global_graph << DOT::Edge.new('from' => "#{sclass_full_name.gsub( /:/,'_' )}",
271
+ 'to' => "#{cl.full_name.gsub( /:/, '_')}")
272
+ end
273
+ end
274
+
275
+ container.modules.each do |submod|
276
+ draw_module(submod, graph)
277
+ end
278
+
279
+ end
280
+
281
+ def convert_to_png(file_base, graph)
282
+ str = graph.to_s
283
+ return @diagram_cache[str] if @diagram_cache[str]
284
+ op_type = @options.image_format
285
+ dotfile = File.join(DOT_PATH, file_base)
286
+ src = dotfile + ".dot"
287
+ dot = dotfile + "." + op_type
288
+
289
+ unless @options.quiet
290
+ $stderr.print "."
291
+ $stderr.flush
292
+ end
293
+
294
+ File.open(src, 'w+' ) do |f|
295
+ f << str << "\n"
296
+ end
297
+
298
+ system "dot", "-T#{op_type}", src, "-o", dot
299
+
300
+ # Now construct the imagemap wrapper around
301
+ # that png
302
+
303
+ ret = wrap_in_image_map(src, dot)
304
+ @diagram_cache[str] = ret
305
+ return ret
306
+ end
307
+
308
+ ##
309
+ # Extract the client-side image map from dot, and use it to generate the
310
+ # imagemap proper. Return the whole <map>..<img> combination, suitable for
311
+ # inclusion on the page
312
+
313
+ def wrap_in_image_map(src, dot)
314
+ res = %{<map id="map" name="map">\n}
315
+ dot_map = `dot -Tismap #{src}`
316
+ dot_map.split($/).each do |area|
317
+ unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
318
+ $stderr.puts "Unexpected output from dot:\n#{area}"
319
+ return nil
320
+ end
321
+
322
+ xs, ys = [$1.to_i, $3.to_i], [$2.to_i, $4.to_i]
323
+ url, area_name = $5, $6
324
+
325
+ res << %{ <area shape="rect" coords="#{xs.min},#{ys.min},#{xs.max},#{ys.max}" }
326
+ res << %{ href="#{url}" alt="#{area_name}" />\n}
327
+ end
328
+ res << "</map>\n"
329
+ # map_file = src.sub(/.dot/, '.map')
330
+ # system("dot -Timap #{src} -o #{map_file}")
331
+ res << %{<img src="#{dot}" usemap="#map" border="0" alt="#{dot}">}
332
+ return res
333
+ end
334
+
335
+ end
336
+
337
+ end
338
+
@@ -0,0 +1,249 @@
1
+ module RDoc; end
2
+
3
+ module RDoc::DOT
4
+
5
+ TAB = ' '
6
+ TAB2 = TAB * 2
7
+
8
+ # options for node declaration
9
+ NODE_OPTS = [
10
+ 'bgcolor',
11
+ 'color',
12
+ 'fontcolor',
13
+ 'fontname',
14
+ 'fontsize',
15
+ 'height',
16
+ 'width',
17
+ 'label',
18
+ 'layer',
19
+ 'rank',
20
+ 'shape',
21
+ 'shapefile',
22
+ 'style',
23
+ 'URL',
24
+ ]
25
+
26
+ # options for edge declaration
27
+ EDGE_OPTS = [
28
+ 'color',
29
+ 'decorate',
30
+ 'dir',
31
+ 'fontcolor',
32
+ 'fontname',
33
+ 'fontsize',
34
+ 'id',
35
+ 'label',
36
+ 'layer',
37
+ 'lhead',
38
+ 'ltail',
39
+ 'minlen',
40
+ 'style',
41
+ 'weight'
42
+ ]
43
+
44
+ # options for graph declaration
45
+ GRAPH_OPTS = [
46
+ 'bgcolor',
47
+ 'center',
48
+ 'clusterrank',
49
+ 'color',
50
+ 'compound',
51
+ 'concentrate',
52
+ 'fillcolor',
53
+ 'fontcolor',
54
+ 'fontname',
55
+ 'fontsize',
56
+ 'label',
57
+ 'layerseq',
58
+ 'margin',
59
+ 'mclimit',
60
+ 'nodesep',
61
+ 'nslimit',
62
+ 'ordering',
63
+ 'orientation',
64
+ 'page',
65
+ 'rank',
66
+ 'rankdir',
67
+ 'ranksep',
68
+ 'ratio',
69
+ 'size',
70
+ 'style',
71
+ 'URL'
72
+ ]
73
+
74
+ # a root class for any element in dot notation
75
+ class SimpleElement
76
+ attr_accessor :name
77
+
78
+ def initialize( params = {} )
79
+ @label = params['name'] ? params['name'] : ''
80
+ end
81
+
82
+ def to_s
83
+ @name
84
+ end
85
+ end
86
+
87
+ # an element that has options ( node, edge or graph )
88
+ class Element < SimpleElement
89
+ #attr_reader :parent
90
+ attr_accessor :name, :options
91
+
92
+ def initialize( params = {}, option_list = [] )
93
+ super( params )
94
+ @name = params['name'] ? params['name'] : nil
95
+ @parent = params['parent'] ? params['parent'] : nil
96
+ @options = {}
97
+ option_list.each{ |i|
98
+ @options[i] = params[i] if params[i]
99
+ }
100
+ @options['label'] ||= @name if @name != 'node'
101
+ end
102
+
103
+ def each_option
104
+ @options.each{ |i| yield i }
105
+ end
106
+
107
+ def each_option_pair
108
+ @options.each_pair{ |key, val| yield key, val }
109
+ end
110
+
111
+ #def parent=( thing )
112
+ # @parent.delete( self ) if defined?( @parent ) and @parent
113
+ # @parent = thing
114
+ #end
115
+ end
116
+
117
+
118
+ # this is used when we build nodes that have shape=record
119
+ # ports don't have options :)
120
+ class Port < SimpleElement
121
+ attr_accessor :label
122
+
123
+ def initialize( params = {} )
124
+ super( params )
125
+ @name = params['label'] ? params['label'] : ''
126
+ end
127
+ def to_s
128
+ ( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
129
+ end
130
+ end
131
+
132
+ # node element
133
+ class Node < Element
134
+
135
+ def initialize( params = {}, option_list = NODE_OPTS )
136
+ super( params, option_list )
137
+ @ports = params['ports'] ? params['ports'] : []
138
+ end
139
+
140
+ def each_port
141
+ @ports.each{ |i| yield i }
142
+ end
143
+
144
+ def << ( thing )
145
+ @ports << thing
146
+ end
147
+
148
+ def push ( thing )
149
+ @ports.push( thing )
150
+ end
151
+
152
+ def pop
153
+ @ports.pop
154
+ end
155
+
156
+ def to_s( t = '' )
157
+
158
+ label = @options['shape'] != 'record' && @ports.length == 0 ?
159
+ @options['label'] ?
160
+ t + TAB + "label = \"#{@options['label']}\"\n" :
161
+ '' :
162
+ t + TAB + 'label = "' + " \\\n" +
163
+ t + TAB2 + "#{@options['label']}| \\\n" +
164
+ @ports.collect{ |i|
165
+ t + TAB2 + i.to_s
166
+ }.join( "| \\\n" ) + " \\\n" +
167
+ t + TAB + '"' + "\n"
168
+
169
+ t + "#{@name} [\n" +
170
+ @options.to_a.collect{ |i|
171
+ i[1] && i[0] != 'label' ?
172
+ t + TAB + "#{i[0]} = #{i[1]}" : nil
173
+ }.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) +
174
+ label +
175
+ t + "]\n"
176
+ end
177
+ end
178
+
179
+ # subgraph element is the same to graph, but has another header in dot
180
+ # notation
181
+ class Subgraph < Element
182
+
183
+ def initialize( params = {}, option_list = GRAPH_OPTS )
184
+ super( params, option_list )
185
+ @nodes = params['nodes'] ? params['nodes'] : []
186
+ @dot_string = 'subgraph'
187
+ end
188
+
189
+ def each_node
190
+ @nodes.each{ |i| yield i }
191
+ end
192
+
193
+ def << ( thing )
194
+ @nodes << thing
195
+ end
196
+
197
+ def push( thing )
198
+ @nodes.push( thing )
199
+ end
200
+
201
+ def pop
202
+ @nodes.pop
203
+ end
204
+
205
+ def to_s( t = '' )
206
+ hdr = t + "#{@dot_string} #{@name} {\n"
207
+
208
+ options = @options.to_a.collect{ |name, val|
209
+ val && name != 'label' ?
210
+ t + TAB + "#{name} = #{val}" :
211
+ name ? t + TAB + "#{name} = \"#{val}\"" : nil
212
+ }.compact.join( "\n" ) + "\n"
213
+
214
+ nodes = @nodes.collect{ |i|
215
+ i.to_s( t + TAB )
216
+ }.join( "\n" ) + "\n"
217
+ hdr + options + nodes + t + "}\n"
218
+ end
219
+ end
220
+
221
+ # this is graph
222
+ class Digraph < Subgraph
223
+ def initialize( params = {}, option_list = GRAPH_OPTS )
224
+ super( params, option_list )
225
+ @dot_string = 'digraph'
226
+ end
227
+ end
228
+
229
+ # this is edge
230
+ class Edge < Element
231
+ attr_accessor :from, :to
232
+ def initialize( params = {}, option_list = EDGE_OPTS )
233
+ super( params, option_list )
234
+ @from = params['from'] ? params['from'] : nil
235
+ @to = params['to'] ? params['to'] : nil
236
+ end
237
+
238
+ def to_s( t = '' )
239
+ t + "#{@from} -> #{to} [\n" +
240
+ @options.to_a.collect{ |i|
241
+ i[1] && i[0] != 'label' ?
242
+ t + TAB + "#{i[0]} = #{i[1]}" :
243
+ i[1] ? t + TAB + "#{i[0]} = \"#{i[1]}\"" : nil
244
+ }.compact.join( "\n" ) + "\n" + t + "]\n"
245
+ end
246
+ end
247
+
248
+ end
249
+