rdoc-f95 0.0.1

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 (71) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +79 -0
  3. data/PostInstall.txt +7 -0
  4. data/README.rdoc +147 -0
  5. data/Rakefile +28 -0
  6. data/bin/rdoc-f95 +70 -0
  7. data/lib/rdoc-f95.rb +306 -0
  8. data/lib/rdoc-f95/code_objects.rb +776 -0
  9. data/lib/rdoc-f95/diagram.rb +342 -0
  10. data/lib/rdoc-f95/dot.rb +249 -0
  11. data/lib/rdoc-f95/generator.rb +1088 -0
  12. data/lib/rdoc-f95/generator/chm.rb +113 -0
  13. data/lib/rdoc-f95/generator/chm/chm.rb +98 -0
  14. data/lib/rdoc-f95/generator/html.rb +370 -0
  15. data/lib/rdoc-f95/generator/html/hefss.rb +414 -0
  16. data/lib/rdoc-f95/generator/html/html.rb +708 -0
  17. data/lib/rdoc-f95/generator/html/kilmer.rb +418 -0
  18. data/lib/rdoc-f95/generator/html/one_page_html.rb +121 -0
  19. data/lib/rdoc-f95/generator/ri.rb +229 -0
  20. data/lib/rdoc-f95/generator/xhtml.rb +106 -0
  21. data/lib/rdoc-f95/generator/xhtml/ctop.xsl +1318 -0
  22. data/lib/rdoc-f95/generator/xhtml/mathml.xsl +42 -0
  23. data/lib/rdoc-f95/generator/xhtml/pmathml.xsl +612 -0
  24. data/lib/rdoc-f95/generator/xhtml/pmathmlcss.xsl +872 -0
  25. data/lib/rdoc-f95/generator/xhtml/xhtml.rb +732 -0
  26. data/lib/rdoc-f95/generator/xml.rb +120 -0
  27. data/lib/rdoc-f95/generator/xml/rdf.rb +113 -0
  28. data/lib/rdoc-f95/generator/xml/xml.rb +111 -0
  29. data/lib/rdoc-f95/install.rb +166 -0
  30. data/lib/rdoc-f95/markup.rb +506 -0
  31. data/lib/rdoc-f95/markup/formatter.rb +14 -0
  32. data/lib/rdoc-f95/markup/fragments.rb +337 -0
  33. data/lib/rdoc-f95/markup/inline.rb +361 -0
  34. data/lib/rdoc-f95/markup/install.rb +57 -0
  35. data/lib/rdoc-f95/markup/lines.rb +152 -0
  36. data/lib/rdoc-f95/markup/mathml_wrapper.rb +91 -0
  37. data/lib/rdoc-f95/markup/preprocess.rb +71 -0
  38. data/lib/rdoc-f95/markup/sample/rdoc2latex.rb +16 -0
  39. data/lib/rdoc-f95/markup/sample/sample.rb +42 -0
  40. data/lib/rdoc-f95/markup/to_flow.rb +185 -0
  41. data/lib/rdoc-f95/markup/to_html.rb +357 -0
  42. data/lib/rdoc-f95/markup/to_html_crossref.rb +123 -0
  43. data/lib/rdoc-f95/markup/to_latex.rb +328 -0
  44. data/lib/rdoc-f95/markup/to_test.rb +50 -0
  45. data/lib/rdoc-f95/markup/to_xhtml_texparser.rb +234 -0
  46. data/lib/rdoc-f95/options.rb +745 -0
  47. data/lib/rdoc-f95/parsers/parse_c.rb +775 -0
  48. data/lib/rdoc-f95/parsers/parse_f95.rb +2499 -0
  49. data/lib/rdoc-f95/parsers/parse_rb.rb +2587 -0
  50. data/lib/rdoc-f95/parsers/parse_simple.rb +39 -0
  51. data/lib/rdoc-f95/parsers/parserfactory.rb +99 -0
  52. data/lib/rdoc-f95/ri.rb +2 -0
  53. data/lib/rdoc-f95/ri/cache.rb +188 -0
  54. data/lib/rdoc-f95/ri/descriptions.rb +147 -0
  55. data/lib/rdoc-f95/ri/display.rb +244 -0
  56. data/lib/rdoc-f95/ri/driver.rb +435 -0
  57. data/lib/rdoc-f95/ri/formatter.rb +603 -0
  58. data/lib/rdoc-f95/ri/paths.rb +105 -0
  59. data/lib/rdoc-f95/ri/reader.rb +106 -0
  60. data/lib/rdoc-f95/ri/util.rb +81 -0
  61. data/lib/rdoc-f95/ri/writer.rb +64 -0
  62. data/lib/rdoc-f95/stats.rb +23 -0
  63. data/lib/rdoc-f95/template.rb +64 -0
  64. data/lib/rdoc-f95/tokenstream.rb +33 -0
  65. data/lib/rdoc-f95/usage.rb +210 -0
  66. data/script/console +10 -0
  67. data/script/destroy +14 -0
  68. data/script/generate +14 -0
  69. data/test/test_helper.rb +3 -0
  70. data/test/test_rdoc-f95.rb +11 -0
  71. metadata +156 -0
@@ -0,0 +1,1088 @@
1
+ require 'cgi'
2
+ require 'rdoc-f95/options'
3
+ require 'rdoc-f95/markup/to_html_crossref'
4
+ require 'rdoc-f95/markup/to_xhtml_texparser'
5
+ require 'rdoc-f95/template'
6
+
7
+ module RDocF95::Generator
8
+
9
+ ##
10
+ # Name of sub-direcory that holds file descriptions
11
+
12
+ FILE_DIR = "files"
13
+
14
+ ##
15
+ # Name of sub-direcory that holds class descriptions
16
+
17
+ CLASS_DIR = "classes"
18
+
19
+ ##
20
+ # Name of the RDoc CSS file
21
+
22
+ CSS_NAME = "rdoc-style.css"
23
+
24
+ ##
25
+ # Converts a target url to one that is relative to a given path
26
+
27
+ def self.gen_url(path, target)
28
+ from = ::File.dirname path
29
+ to, to_file = ::File.split target
30
+
31
+ from = from.split "/"
32
+ to = to.split "/"
33
+
34
+ while from.size > 0 and to.size > 0 and from[0] == to[0] do
35
+ from.shift
36
+ to.shift
37
+ end
38
+
39
+ from.delete_if{|f| f =~ /^\.$/}
40
+ from.fill ".."
41
+ from.concat to
42
+ from << to_file
43
+ ::File.join(*from)
44
+ end
45
+
46
+ ##
47
+ # Build a hash of all items that can be cross-referenced. This is used when
48
+ # we output required and included names: if the names appear in this hash,
49
+ # we can generate an html cross reference to the appropriate description.
50
+ # We also use this when parsing comment blocks: any decorated words matching
51
+ # an entry in this list are hyperlinked.
52
+
53
+ class AllReferences
54
+ @@refs = {}
55
+
56
+ def AllReferences::reset
57
+ @@refs = {}
58
+ end
59
+
60
+ def AllReferences.add(name, html_class)
61
+ @@refs[name] = html_class
62
+ end
63
+
64
+ def AllReferences.[](name)
65
+ @@refs[name]
66
+ end
67
+
68
+ def AllReferences.keys
69
+ @@refs.keys
70
+ end
71
+ end
72
+
73
+ ##
74
+ # Handle common markup tasks for the various Context subclasses
75
+
76
+ module MarkUp
77
+
78
+ ##
79
+ # Convert a string in markup format into HTML.
80
+
81
+ def markup(str, remove_para = false)
82
+ return '' unless str
83
+
84
+ unless defined? @formatter then
85
+ unless @options.mathml
86
+ @formatter = RDocF95::Markup::ToHtmlCrossref.new(path, self,
87
+ @options.show_hash)
88
+ else
89
+ @formatter = RDocF95::Markup::ToXHtmlTexParser.new(path, self,
90
+ @options.show_hash,
91
+ @options.mathml)
92
+ end
93
+ end
94
+
95
+ # Convert leading comment markers to spaces, but only if all non-blank
96
+ # lines have them
97
+ if str =~ /^(?>\s*)[^\#]/ then
98
+ content = str
99
+ else
100
+ content = str.gsub(/^\s*(#+)/) { $1.tr '#', ' ' }
101
+ end
102
+
103
+ unless @options.mathml
104
+ res = @formatter.convert content
105
+ else
106
+ res = @formatter.convert content, @formatter.block_exceptions
107
+ end
108
+
109
+ if remove_para then
110
+ res.sub!(/^<p>/, '')
111
+ res.sub!(/<\/p>$/, '')
112
+ end
113
+
114
+ res
115
+ end
116
+
117
+ ##
118
+ # Qualify a stylesheet URL; if if +css_name+ does not begin with '/' or
119
+ # 'http[s]://', prepend a prefix relative to +path+. Otherwise, return it
120
+ # unmodified.
121
+
122
+ def style_url(path, css_name=nil)
123
+ # $stderr.puts "style_url( #{path.inspect}, #{css_name.inspect} )"
124
+ css_name ||= CSS_NAME
125
+ if %r{^(https?:/)?/} =~ css_name
126
+ css_name
127
+ else
128
+ RDocF95::Generator.gen_url path, css_name
129
+ end
130
+ end
131
+
132
+ ##
133
+ # Build a webcvs URL with the given 'url' argument. URLs with a '%s' in them
134
+ # get the file's path sprintfed into them; otherwise they're just catenated
135
+ # together.
136
+
137
+ def cvs_url(url, full_path)
138
+ if /%s/ =~ url
139
+ return sprintf( url, full_path )
140
+ else
141
+ return url + full_path
142
+ end
143
+ end
144
+
145
+ end
146
+
147
+ ##
148
+ # A Context is built by the parser to represent a container: contexts hold
149
+ # classes, modules, methods, require lists and include lists. ClassModule
150
+ # and TopLevel are the context objects we process here
151
+
152
+ class Context
153
+
154
+ include MarkUp
155
+
156
+ attr_reader :context
157
+
158
+ ##
159
+ # Generate:
160
+ #
161
+ # * a list of RDocF95::Generator::File objects for each TopLevel object
162
+ # * a list of RDocF95::Generator::Class objects for each first level class or
163
+ # module in the TopLevel objects
164
+ # * a complete list of all hyperlinkable terms (file, class, module, and
165
+ # method names)
166
+
167
+ def self.build_indicies(toplevels, options)
168
+ files = []
169
+ classes = []
170
+
171
+ toplevels.each do |toplevel|
172
+ files << RDocF95::Generator::File.new(toplevel, options,
173
+ RDocF95::Generator::FILE_DIR)
174
+ end
175
+
176
+ RDocF95::TopLevel.all_classes_and_modules.each do |cls|
177
+ build_class_list(classes, options, cls, files[0],
178
+ RDocF95::Generator::CLASS_DIR)
179
+ end
180
+
181
+ return files, classes
182
+ end
183
+
184
+ def self.build_class_list(classes, options, from, html_file, class_dir)
185
+ classes << RDocF95::Generator::Class.new(from, html_file, class_dir, options)
186
+
187
+ from.each_classmodule do |mod|
188
+ build_class_list(classes, options, mod, html_file, class_dir)
189
+ end
190
+ end
191
+
192
+ def initialize(context, options)
193
+ @context = context
194
+ @options = options
195
+
196
+ # HACK ugly
197
+ @template = options.template_class
198
+ end
199
+
200
+ ##
201
+ # convenience method to build a hyperlink
202
+
203
+ def href(link, cls, name)
204
+ %{<a href="#{link}" class="#{cls}">#{name}</a>} #"
205
+ end
206
+
207
+ ##
208
+ # Returns a reference to outselves to be used as an href= the form depends
209
+ # on whether we're all in one file or in multiple files
210
+
211
+ def as_href(from_path)
212
+ if @options.all_one_file
213
+ "#" + path
214
+ else
215
+ RDocF95::Generator.gen_url from_path, path
216
+ end
217
+ end
218
+
219
+ ##
220
+ # Create a list of Method objects for each method in the corresponding
221
+ # context object. If the @options.show_all variable is set (corresponding
222
+ # to the <tt>--all</tt> option, we include all methods, otherwise just the
223
+ # public ones.
224
+
225
+ def collect_methods
226
+ list = @context.method_list
227
+
228
+ unless @options.show_all then
229
+ list = list.find_all do |m|
230
+ m.visibility == :public or
231
+ m.visibility == :protected or
232
+ m.force_documentation
233
+ end
234
+ end
235
+
236
+ @methods = list.collect do |m|
237
+ RDocF95::Generator::Method.new m, self, @options
238
+ end
239
+ end
240
+
241
+ ##
242
+ # Build a summary list of all the methods in this context
243
+
244
+ def build_method_summary_list(path_prefix="")
245
+ collect_methods unless @methods
246
+ meths = @methods.sort
247
+ res = []
248
+ meths.each do |meth|
249
+ res << {
250
+ "name" => CGI.escapeHTML(meth.name),
251
+ "aref" => "#{path_prefix}\##{meth.aref}"
252
+ }
253
+ end
254
+ res
255
+ end
256
+
257
+ ##
258
+ # Build a list of aliases for which we couldn't find a
259
+ # corresponding method
260
+
261
+ def build_alias_summary_list(section)
262
+ values = []
263
+ @context.aliases.each do |al|
264
+ next unless al.section == section
265
+ res = {
266
+ 'old_name' => al.old_name,
267
+ 'new_name' => al.new_name,
268
+ }
269
+ if al.comment && !al.comment.empty?
270
+ res['desc'] = markup(al.comment, true)
271
+ end
272
+ values << res
273
+ end
274
+ values
275
+ end
276
+
277
+ ##
278
+ # Build a list of constants
279
+
280
+ def build_constants_summary_list(section)
281
+ values = []
282
+ @context.constants.each do |co|
283
+ next unless co.section == section
284
+ res = {
285
+ 'name' => co.name,
286
+ 'value' => CGI.escapeHTML(co.value)
287
+ }
288
+ res['desc'] = markup(co.comment, true) if co.comment && !co.comment.empty?
289
+ values << res
290
+ end
291
+ values
292
+ end
293
+
294
+ def build_requires_list(context)
295
+ potentially_referenced_list(context.requires) {|fn| [fn + ".rb"] }
296
+ end
297
+
298
+ def build_include_list(context)
299
+ potentially_referenced_list(context.includes)
300
+ end
301
+
302
+ ##
303
+ # Build a list from an array of Context items. Look up each in the
304
+ # AllReferences hash: if we find a corresponding entry, we generate a
305
+ # hyperlink to it, otherwise just output the name. However, some names
306
+ # potentially need massaging. For example, you may require a Ruby file
307
+ # without the .rb extension, but the file names we know about may have it.
308
+ # To deal with this, we pass in a block which performs the massaging,
309
+ # returning an array of alternative names to match
310
+
311
+ def potentially_referenced_list(array)
312
+ res = []
313
+ array.each do |i|
314
+ ref = AllReferences[i.name]
315
+ # if !ref
316
+ # container = @context.parent
317
+ # while !ref && container
318
+ # name = container.name + "::" + i.name
319
+ # ref = AllReferences[name]
320
+ # container = container.parent
321
+ # end
322
+ # end
323
+
324
+ ref = @context.find_symbol(i.name, nil, @options.ignore_case) || \
325
+ @context.find_file(i.name)
326
+ ref = ref.viewer if ref
327
+
328
+ if !ref && block_given?
329
+ possibles = yield(i.name)
330
+ while !ref and !possibles.empty?
331
+ ref = AllReferences[possibles.shift]
332
+ end
333
+ end
334
+ h_name = CGI.escapeHTML(i.name)
335
+ if ref and ref.document_self
336
+ path = url(ref.path)
337
+ res << { "name" => h_name, "aref" => path }
338
+ else
339
+ res << { "name" => h_name }
340
+ end
341
+ end
342
+ res
343
+ end
344
+
345
+ ##
346
+ # Build an array of arrays of method details. The outer array has up
347
+ # to six entries, public, private, and protected for both class
348
+ # methods, the other for instance methods. The inner arrays contain
349
+ # a hash for each method
350
+
351
+ def build_method_detail_list(section)
352
+ outer = []
353
+
354
+ methods = @methods.sort
355
+ for singleton in [true, false]
356
+ for vis in [ :public, :protected, :private ]
357
+ res = []
358
+ methods.each do |m|
359
+ if m.section == section and
360
+ m.document_self and
361
+ m.visibility == vis and
362
+ m.singleton == singleton
363
+ row = {}
364
+ if m.call_seq
365
+ row["callseq"] = m.call_seq.gsub(/->/, '&rarr;')
366
+ else
367
+ row["name"] = CGI.escapeHTML(m.name)
368
+ row["params"] = m.params
369
+ end
370
+ desc = m.description.strip
371
+ row["m_desc"] = desc unless desc.empty?
372
+ row["aref"] = m.aref
373
+ row["visibility"] = m.visibility.to_s
374
+
375
+ alias_names = []
376
+ m.aliases.each do |other|
377
+ if other.viewer # won't be if the alias is private
378
+ alias_names << {
379
+ 'name' => other.name,
380
+ 'aref' => other.viewer.as_href(path)
381
+ }
382
+ end
383
+ end
384
+ unless alias_names.empty?
385
+ row["aka"] = alias_names
386
+ end
387
+
388
+ if @options.inline_source
389
+ code = m.source_code
390
+ row["sourcecode"] = code if code
391
+ else
392
+ code = m.src_url
393
+ if code
394
+ row["codeurl"] = code
395
+ row["imgurl"] = m.img_url
396
+ end
397
+ end
398
+ res << row
399
+ end
400
+ end
401
+ if res.size > 0
402
+ outer << {
403
+ "type" => vis.to_s.capitalize,
404
+ "category" => singleton ? "Class" : "Instance",
405
+ "methods" => res
406
+ }
407
+ end
408
+ end
409
+ end
410
+ outer
411
+ end
412
+
413
+ ##
414
+ # Build the structured list of classes and modules contained
415
+ # in this context.
416
+
417
+ def build_class_list(level, from, section, infile=nil)
418
+ res = ""
419
+ prefix = "&nbsp;&nbsp;::" * level;
420
+
421
+ from.modules.sort.each do |mod|
422
+ next unless mod.section == section
423
+ next if infile && !mod.defined_in?(infile)
424
+ if mod.document_self
425
+ res <<
426
+ prefix <<
427
+ "Module " <<
428
+ href(url(mod.viewer.path), "link", mod.full_name) <<
429
+ "<br />\n" <<
430
+ build_class_list(level + 1, mod, section, infile)
431
+ end
432
+ end
433
+
434
+ from.classes.sort.each do |cls|
435
+ next unless cls.section == section
436
+ next if infile && !cls.defined_in?(infile)
437
+ if cls.document_self
438
+ res <<
439
+ prefix <<
440
+ "Class " <<
441
+ href(url(cls.viewer.path), "link", cls.full_name) <<
442
+ "<br />\n" <<
443
+ build_class_list(level + 1, cls, section, infile)
444
+ end
445
+ end
446
+
447
+ res
448
+ end
449
+
450
+ def url(target)
451
+ RDocF95::Generator.gen_url path, target
452
+ end
453
+
454
+ def aref_to(target)
455
+ if @options.all_one_file
456
+ "#" + target
457
+ else
458
+ url(target)
459
+ end
460
+ end
461
+
462
+ def document_self
463
+ @context.document_self
464
+ end
465
+
466
+ def diagram_reference(diagram)
467
+ res = diagram.gsub(/((?:src|href)=")(.*?)"/) {
468
+ $1 + url($2) + '"'
469
+ }
470
+ res
471
+ end
472
+
473
+ ##
474
+ # Find a symbol in ourselves or our parent
475
+
476
+ def find_symbol(symbol, method=nil)
477
+ res = @context.find_symbol(symbol, method, @options.ignore_case)
478
+ if res
479
+ res = res.viewer
480
+ end
481
+ res
482
+ end
483
+
484
+ # Find a filenames in ourselves or our parent
485
+ def find_file(file, method=nil)
486
+ res = @context.find_file(file, method, @options.ignore_case)
487
+ if res
488
+ res = res.viewer
489
+ end
490
+ res
491
+ end
492
+
493
+ ##
494
+ # create table of contents if we contain sections
495
+
496
+ def add_table_of_sections
497
+ toc = []
498
+ @context.sections.each do |section|
499
+ if section.title
500
+ toc << {
501
+ 'secname' => section.title,
502
+ 'href' => section.sequence
503
+ }
504
+ end
505
+ end
506
+
507
+ @values['toc'] = toc unless toc.empty?
508
+ end
509
+
510
+ end
511
+
512
+ ##
513
+ # Wrap a ClassModule context
514
+
515
+ class Class < Context
516
+
517
+ attr_reader :methods
518
+ attr_reader :path
519
+
520
+ def initialize(context, html_file, prefix, options)
521
+ super(context, options)
522
+
523
+ @html_file = html_file
524
+ @is_module = context.is_module?
525
+ @values = {}
526
+
527
+ context.viewer = self
528
+
529
+ if options.all_one_file
530
+ @path = context.full_name
531
+ else
532
+ @path = http_url(context.full_name, prefix)
533
+ end
534
+
535
+ collect_methods
536
+
537
+ AllReferences.add(name, self)
538
+ end
539
+
540
+ ##
541
+ # Returns the relative file name to store this class in, which is also its
542
+ # url
543
+
544
+ def http_url(full_name, prefix)
545
+ path = full_name.dup
546
+
547
+ path.gsub!(/<<\s*(\w*)/, 'from-\1') if path['<<']
548
+ suffix = ".html"
549
+ suffix = ".xhtml" if @options.template == "xhtml"
550
+
551
+ ::File.join(prefix, path.split("::")) + suffix
552
+ end
553
+
554
+ def name
555
+ @context.full_name
556
+ end
557
+
558
+ def parent_name
559
+ @context.parent.full_name
560
+ end
561
+
562
+ def index_name
563
+ name
564
+ end
565
+
566
+ def write_on(f)
567
+ value_hash
568
+ template = RDocF95::TemplatePage.new(@template::BODY,
569
+ @template::CLASS_PAGE,
570
+ @template::METHOD_LIST)
571
+ template.write_html_on(f, @values)
572
+ end
573
+
574
+ def value_hash
575
+ class_attribute_values
576
+ add_table_of_sections
577
+
578
+ @values["charset"] = @options.charset
579
+ @values["style_url"] = style_url(path, @options.css)
580
+ @values["mathml_xsl_url"] = style_url(path, "mathml.xsl")
581
+
582
+ d = markup(@context.comment)
583
+ @values["description"] = d unless d.empty?
584
+
585
+ ml = build_method_summary_list
586
+ @values["methods"] = ml unless ml.empty?
587
+
588
+ il = build_include_list(@context)
589
+ @values["includes"] = il unless il.empty?
590
+
591
+ @values["sections"] = @context.sections.map do |section|
592
+
593
+ secdata = {
594
+ "sectitle" => section.title,
595
+ "secsequence" => section.sequence,
596
+ "seccomment" => markup(section.comment)
597
+ }
598
+
599
+ al = build_alias_summary_list(section)
600
+ secdata["aliases"] = al unless al.empty?
601
+
602
+ co = build_constants_summary_list(section)
603
+ secdata["constants"] = co unless co.empty?
604
+
605
+ al = build_attribute_list(section)
606
+ secdata["attributes"] = al unless al.empty?
607
+
608
+ cl = build_class_list(0, @context, section)
609
+ secdata["classlist"] = cl unless cl.empty?
610
+
611
+ mdl = build_method_detail_list(section)
612
+ secdata["method_list"] = mdl unless mdl.empty?
613
+
614
+ secdata
615
+ end
616
+
617
+ @values
618
+ end
619
+
620
+ def build_attribute_list(section)
621
+ atts = @context.attributes.sort
622
+ res = []
623
+ atts.each do |att|
624
+ next unless att.section == section
625
+ if att.visibility == :public || att.visibility == :protected || @options.show_all
626
+ entry = {
627
+ "name" => CGI.escapeHTML(att.name),
628
+ "rw" => att.rw,
629
+ "a_desc" => markup(att.comment, true)
630
+ }
631
+ unless att.visibility == :public || att.visibility == :protected
632
+ entry["rw"] << "-"
633
+ end
634
+ res << entry
635
+ end
636
+ end
637
+ res
638
+ end
639
+
640
+ def class_attribute_values
641
+ h_name = CGI.escapeHTML(name)
642
+
643
+ @values["path"] = @path
644
+ @values["classmod"] = @is_module ? "Module" : "Class"
645
+ @values["title"] = "#{@values['classmod']}: #{h_name}"
646
+
647
+ c = @context
648
+ c = c.parent while c and !c.diagram
649
+ if c && c.diagram
650
+ @values["diagram"] = diagram_reference(c.diagram)
651
+ end
652
+
653
+ @values["full_name"] = h_name
654
+
655
+ parent_class = @context.superclass
656
+
657
+ if parent_class
658
+ @values["parent"] = CGI.escapeHTML(parent_class)
659
+
660
+ if parent_name
661
+ lookup = parent_name + "::" + parent_class
662
+ else
663
+ lookup = parent_class
664
+ end
665
+
666
+ parent_url = AllReferences[lookup] || AllReferences[parent_class]
667
+
668
+ if parent_url and parent_url.document_self
669
+ @values["par_url"] = aref_to(parent_url.path)
670
+ end
671
+ end
672
+
673
+ files = []
674
+ @context.in_files.each do |f|
675
+ res = {}
676
+ full_path = CGI.escapeHTML(f.file_absolute_name)
677
+
678
+ res["full_path"] = full_path
679
+ res["full_path_url"] = aref_to(f.viewer.path) if f.document_self
680
+
681
+ if @options.webcvs
682
+ res["cvsurl"] = cvs_url( @options.webcvs, full_path )
683
+ end
684
+
685
+ files << res
686
+ end
687
+
688
+ @values['infiles'] = files
689
+ end
690
+
691
+ def <=>(other)
692
+ self.name <=> other.name
693
+ end
694
+
695
+ end
696
+
697
+ ##
698
+ # Handles the mapping of a file's information to HTML. In reality, a file
699
+ # corresponds to a +TopLevel+ object, containing modules, classes, and
700
+ # top-level methods. In theory it _could_ contain attributes and aliases,
701
+ # but we ignore these for now.
702
+
703
+ class File < Context
704
+
705
+ attr_reader :path
706
+ attr_reader :name
707
+
708
+ def initialize(context, options, file_dir)
709
+ super(context, options)
710
+
711
+ @values = {}
712
+
713
+ if options.all_one_file
714
+ @path = filename_to_label
715
+ else
716
+ @path = http_url(file_dir)
717
+ end
718
+
719
+ @name = @context.file_relative_name
720
+
721
+ collect_methods
722
+ AllReferences.add(name, self)
723
+ context.viewer = self
724
+ end
725
+
726
+ def http_url(file_dir)
727
+ suffix = ".html"
728
+ suffix = ".xhtml" if @options.template == "xhtml"
729
+
730
+ ::File.join file_dir, "#{@context.file_relative_name.tr '.', '_'}" + suffix
731
+ end
732
+
733
+ def filename_to_label
734
+ @context.file_relative_name.gsub(/%|\/|\?|\#/) do
735
+ '%%%x' % $&[0].unpack('C')
736
+ end
737
+ end
738
+
739
+ def index_name
740
+ name
741
+ end
742
+
743
+ def parent_name
744
+ nil
745
+ end
746
+
747
+ def value_hash
748
+ file_attribute_values
749
+ add_table_of_sections
750
+
751
+ @values["charset"] = @options.charset
752
+ @values["href"] = path
753
+ @values["style_url"] = style_url(path, @options.css)
754
+ @values["mathml_xsl_url"] = style_url(path, "mathml.xsl")
755
+
756
+ if @context.comment
757
+ d = markup(@context.comment)
758
+ @values["description"] = d if d.size > 0
759
+ end
760
+
761
+ ml = build_method_summary_list
762
+ @values["methods"] = ml unless ml.empty?
763
+
764
+ il = build_include_list(@context)
765
+ @values["includes"] = il unless il.empty?
766
+
767
+ rl = build_requires_list(@context)
768
+ @values["requires"] = rl unless rl.empty?
769
+
770
+ if @options.promiscuous
771
+ file_context = nil
772
+ else
773
+ file_context = @context
774
+ end
775
+
776
+
777
+ @values["sections"] = @context.sections.map do |section|
778
+
779
+ secdata = {
780
+ "sectitle" => section.title,
781
+ "secsequence" => section.sequence,
782
+ "seccomment" => markup(section.comment)
783
+ }
784
+
785
+ cl = build_class_list(0, @context, section, file_context)
786
+ @values["classlist"] = cl unless cl.empty?
787
+
788
+ mdl = build_method_detail_list(section)
789
+ secdata["method_list"] = mdl unless mdl.empty?
790
+
791
+ al = build_alias_summary_list(section)
792
+ secdata["aliases"] = al unless al.empty?
793
+
794
+ co = build_constants_summary_list(section)
795
+ @values["constants"] = co unless co.empty?
796
+
797
+ secdata
798
+ end
799
+
800
+ @values
801
+ end
802
+
803
+ def write_on(f)
804
+ value_hash
805
+
806
+ template = RDocF95::TemplatePage.new(@template::BODY,
807
+ @template::FILE_PAGE,
808
+ @template::METHOD_LIST)
809
+
810
+ template.write_html_on(f, @values)
811
+ end
812
+
813
+ def file_attribute_values
814
+ full_path = @context.file_absolute_name
815
+ short_name = ::File.basename full_path
816
+
817
+ @values["title"] = CGI.escapeHTML("File: #{short_name}")
818
+
819
+ if @context.diagram then
820
+ @values["diagram"] = diagram_reference(@context.diagram)
821
+ end
822
+
823
+ @values["short_name"] = CGI.escapeHTML(short_name)
824
+ @values["full_path"] = CGI.escapeHTML(full_path)
825
+ @values["dtm_modified"] = @context.file_stat.mtime.to_s
826
+
827
+ if @options.webcvs then
828
+ @values["cvsurl"] = cvs_url @options.webcvs, @values["full_path"]
829
+ end
830
+ end
831
+
832
+ def <=>(other)
833
+ self.name <=> other.name
834
+ end
835
+
836
+ end
837
+
838
+ class Method
839
+
840
+ include MarkUp
841
+
842
+ attr_reader :context
843
+ attr_reader :src_url
844
+ attr_reader :img_url
845
+ attr_reader :source_code
846
+
847
+ @@seq = "M000000"
848
+
849
+ @@all_methods = []
850
+
851
+ def self.all_methods
852
+ @@all_methods
853
+ end
854
+
855
+ def self.reset
856
+ @@all_methods = []
857
+ end
858
+
859
+ def initialize(context, html_class, options)
860
+ @context = context
861
+ @html_class = html_class
862
+ @options = options
863
+
864
+ # HACK ugly
865
+ @template = options.template_class
866
+
867
+ @@seq = @@seq.succ
868
+ @seq = @@seq
869
+ @@all_methods << self
870
+
871
+ context.viewer = self
872
+
873
+ if (ts = @context.token_stream)
874
+ @source_code = markup_code(ts)
875
+ unless @options.inline_source
876
+ @src_url = create_source_code_file(@source_code)
877
+ @img_url = RDocF95::Generator.gen_url path, 'source.png'
878
+ end
879
+ end
880
+
881
+ AllReferences.add(name, self)
882
+ end
883
+
884
+ ##
885
+ # Returns a reference to outselves to be used as an href= the form depends
886
+ # on whether we're all in one file or in multiple files
887
+
888
+ def as_href(from_path)
889
+ if @options.all_one_file
890
+ "#" + path
891
+ else
892
+ RDocF95::Generator.gen_url from_path, path
893
+ end
894
+ end
895
+
896
+ def name
897
+ @context.name
898
+ end
899
+
900
+ def section
901
+ @context.section
902
+ end
903
+
904
+ def index_name
905
+ "#{@context.name} (#{@html_class.name})"
906
+ end
907
+
908
+ def parent_name
909
+ if @context.parent.parent
910
+ @context.parent.parent.full_name
911
+ else
912
+ nil
913
+ end
914
+ end
915
+
916
+ def aref
917
+ @seq
918
+ end
919
+
920
+ def path
921
+ if @options.all_one_file
922
+ aref
923
+ else
924
+ @html_class.path + "#" + aref
925
+ end
926
+ end
927
+
928
+ def description
929
+ markup(@context.comment)
930
+ end
931
+
932
+ def visibility
933
+ @context.visibility
934
+ end
935
+
936
+ def singleton
937
+ @context.singleton
938
+ end
939
+
940
+ def call_seq
941
+ cs = @context.call_seq
942
+ if cs
943
+ cs.gsub(/\n/, "<br />\n")
944
+ else
945
+ nil
946
+ end
947
+ end
948
+
949
+ def params
950
+ # params coming from a call-seq in 'C' will start with the
951
+ # method name
952
+ if p !~ /^\w/
953
+ p = @context.params.gsub(/\s*\#.*/, '')
954
+ p = p.tr("\n", " ").squeeze(" ")
955
+ p = "(" + p + ")" unless p[0] == ?( || p == ''
956
+
957
+ if (block = @context.block_params)
958
+ # If this method has explicit block parameters, remove any
959
+ # explicit &block
960
+
961
+ p.sub!(/,?\s*&\w+/, '')
962
+
963
+ block.gsub!(/\s*\#.*/, '')
964
+ block = block.tr("\n", " ").squeeze(" ")
965
+ if block[0] == ?(
966
+ block.sub!(/^\(/, '').sub!(/\)/, '')
967
+ end
968
+ p << " {|#{block.strip}| ...}"
969
+ end
970
+ end
971
+ CGI.escapeHTML(p)
972
+ end
973
+
974
+ def create_source_code_file(code_body)
975
+ suffix = "html"
976
+ suffix = "xhtml" if @options.template == "xhtml"
977
+ template_regexp = Regexp.new("\\." + suffix + "$")
978
+ meth_path = @html_class.path.sub(template_regexp, '.src')
979
+ FileUtils.mkdir_p(meth_path)
980
+ file_path = ::File.join(meth_path, @seq) + '.' + suffix
981
+
982
+ template = RDocF95::TemplatePage.new(@template::SRC_PAGE)
983
+
984
+ open file_path, 'w' do |f|
985
+ values = {
986
+ 'title' => CGI.escapeHTML(index_name),
987
+ 'code' => code_body,
988
+ 'style_url' => style_url(file_path, @options.css),
989
+ 'mathml_xsl_url' => style_url(file_path, "mathml.xsl"),
990
+ 'charset' => @options.charset
991
+ }
992
+ template.write_html_on(f, values)
993
+ end
994
+
995
+ RDocF95::Generator.gen_url path, file_path
996
+ end
997
+
998
+ def <=>(other)
999
+ @context <=> other.context
1000
+ end
1001
+
1002
+ ##
1003
+ # Given a sequence of source tokens, mark up the source code
1004
+ # to make it look purty.
1005
+
1006
+ def markup_code(tokens)
1007
+ src = ""
1008
+ tokens.each do |t|
1009
+ next unless t
1010
+ # p t.class
1011
+ # style = STYLE_MAP[t.class]
1012
+ style = case t
1013
+ when RubyToken::TkCONSTANT then "ruby-constant"
1014
+ when RubyToken::TkKW then "ruby-keyword kw"
1015
+ when RubyToken::TkIVAR then "ruby-ivar"
1016
+ when RubyToken::TkOp then "ruby-operator"
1017
+ when RubyToken::TkId then "ruby-identifier"
1018
+ when RubyToken::TkNode then "ruby-node"
1019
+ when RubyToken::TkCOMMENT then "ruby-comment cmt"
1020
+ when RubyToken::TkREGEXP then "ruby-regexp re"
1021
+ when RubyToken::TkSTRING then "ruby-value str"
1022
+ when RubyToken::TkVal then "ruby-value"
1023
+ else
1024
+ nil
1025
+ end
1026
+
1027
+ text = CGI.escapeHTML(t.text)
1028
+
1029
+ if style
1030
+ src << "<span class=\"#{style}\">#{text}</span>"
1031
+ else
1032
+ src << text
1033
+ end
1034
+ end
1035
+
1036
+ add_line_numbers(src) if @options.include_line_numbers
1037
+ src
1038
+ end
1039
+
1040
+ ##
1041
+ # We rely on the fact that the first line of a source code listing has
1042
+ # # File xxxxx, line dddd
1043
+
1044
+ def add_line_numbers(src)
1045
+ if src =~ /\A.*, line (\d+)/
1046
+ first = $1.to_i - 1
1047
+ last = first + src.count("\n")
1048
+ size = last.to_s.length
1049
+ real_fmt = "%#{size}d: "
1050
+ fmt = " " * (size+2)
1051
+ src.gsub!(/^/) do
1052
+ res = sprintf(fmt, first)
1053
+ first += 1
1054
+ fmt = real_fmt
1055
+ res
1056
+ end
1057
+ end
1058
+ end
1059
+
1060
+ def document_self
1061
+ @context.document_self
1062
+ end
1063
+
1064
+ def aliases
1065
+ @context.aliases
1066
+ end
1067
+
1068
+ def find_symbol(symbol, method=nil)
1069
+ res = @context.parent.find_symbol(symbol, method, @options.ignore_case)
1070
+ if res
1071
+ res = res.viewer
1072
+ end
1073
+ res
1074
+ end
1075
+
1076
+ # Find a filenames in ourselves or our parent
1077
+ def find_file(file, method=nil)
1078
+ res = @context.parent.find_file(file, method, @options.ignore_case)
1079
+ if res
1080
+ res = res.viewer
1081
+ end
1082
+ res
1083
+ end
1084
+
1085
+ end
1086
+
1087
+ end
1088
+