rdoc 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rdoc might be problematic. Click here for more details.

Files changed (62) hide show
  1. data/History.txt +13 -0
  2. data/Manifest.txt +61 -0
  3. data/README.txt +34 -0
  4. data/Rakefile +10 -0
  5. data/bin/rdoc +22 -0
  6. data/bin/ri +6 -0
  7. data/lib/rdoc.rb +277 -0
  8. data/lib/rdoc/code_objects.rb +776 -0
  9. data/lib/rdoc/diagram.rb +338 -0
  10. data/lib/rdoc/dot.rb +249 -0
  11. data/lib/rdoc/generator.rb +1048 -0
  12. data/lib/rdoc/generator/chm.rb +113 -0
  13. data/lib/rdoc/generator/chm/chm.rb +98 -0
  14. data/lib/rdoc/generator/html.rb +370 -0
  15. data/lib/rdoc/generator/html/hefss.rb +414 -0
  16. data/lib/rdoc/generator/html/html.rb +704 -0
  17. data/lib/rdoc/generator/html/kilmer.rb +418 -0
  18. data/lib/rdoc/generator/html/one_page_html.rb +121 -0
  19. data/lib/rdoc/generator/ri.rb +229 -0
  20. data/lib/rdoc/generator/xml.rb +120 -0
  21. data/lib/rdoc/generator/xml/rdf.rb +113 -0
  22. data/lib/rdoc/generator/xml/xml.rb +111 -0
  23. data/lib/rdoc/markup.rb +473 -0
  24. data/lib/rdoc/markup/attribute_manager.rb +274 -0
  25. data/lib/rdoc/markup/formatter.rb +14 -0
  26. data/lib/rdoc/markup/fragments.rb +337 -0
  27. data/lib/rdoc/markup/inline.rb +101 -0
  28. data/lib/rdoc/markup/lines.rb +152 -0
  29. data/lib/rdoc/markup/preprocess.rb +71 -0
  30. data/lib/rdoc/markup/to_flow.rb +185 -0
  31. data/lib/rdoc/markup/to_html.rb +353 -0
  32. data/lib/rdoc/markup/to_html_crossref.rb +86 -0
  33. data/lib/rdoc/markup/to_latex.rb +328 -0
  34. data/lib/rdoc/markup/to_test.rb +50 -0
  35. data/lib/rdoc/options.rb +616 -0
  36. data/lib/rdoc/parsers/parse_c.rb +775 -0
  37. data/lib/rdoc/parsers/parse_f95.rb +1841 -0
  38. data/lib/rdoc/parsers/parse_rb.rb +2584 -0
  39. data/lib/rdoc/parsers/parse_simple.rb +40 -0
  40. data/lib/rdoc/parsers/parserfactory.rb +99 -0
  41. data/lib/rdoc/rdoc.rb +277 -0
  42. data/lib/rdoc/ri.rb +4 -0
  43. data/lib/rdoc/ri/cache.rb +188 -0
  44. data/lib/rdoc/ri/descriptions.rb +150 -0
  45. data/lib/rdoc/ri/display.rb +274 -0
  46. data/lib/rdoc/ri/driver.rb +452 -0
  47. data/lib/rdoc/ri/formatter.rb +616 -0
  48. data/lib/rdoc/ri/paths.rb +102 -0
  49. data/lib/rdoc/ri/reader.rb +106 -0
  50. data/lib/rdoc/ri/util.rb +81 -0
  51. data/lib/rdoc/ri/writer.rb +68 -0
  52. data/lib/rdoc/stats.rb +25 -0
  53. data/lib/rdoc/template.rb +64 -0
  54. data/lib/rdoc/tokenstream.rb +33 -0
  55. data/test/test_rdoc_c_parser.rb +261 -0
  56. data/test/test_rdoc_markup.rb +613 -0
  57. data/test/test_rdoc_markup_attribute_manager.rb +224 -0
  58. data/test/test_rdoc_ri_attribute_formatter.rb +42 -0
  59. data/test/test_rdoc_ri_default_display.rb +295 -0
  60. data/test/test_rdoc_ri_formatter.rb +318 -0
  61. data/test/test_rdoc_ri_overstrike_formatter.rb +69 -0
  62. metadata +134 -0
@@ -0,0 +1,616 @@
1
+ require 'rdoc/ri'
2
+ require 'rdoc/markup'
3
+
4
+ class RDoc::RI::Formatter
5
+
6
+ attr_writer :indent
7
+ attr_accessor :output
8
+
9
+ FORMATTERS = { }
10
+
11
+ def self.for(name)
12
+ FORMATTERS[name.downcase]
13
+ end
14
+
15
+ def self.list
16
+ FORMATTERS.keys.sort.join ", "
17
+ end
18
+
19
+ def initialize(output, width, indent)
20
+ @output = output
21
+ @width = width
22
+ @indent = indent
23
+ @original_indent = indent.dup
24
+ end
25
+
26
+ def draw_line(label=nil)
27
+ len = @width
28
+ len -= (label.size + 1) if label
29
+
30
+ if len > 0 then
31
+ @output.print '-' * len
32
+ if label
33
+ @output.print ' '
34
+ bold_print label
35
+ end
36
+
37
+ @output.puts
38
+ else
39
+ @output.print '-' * @width
40
+ @output.puts
41
+
42
+ @output.puts label
43
+ end
44
+ end
45
+
46
+ def indent
47
+ return @indent unless block_given?
48
+
49
+ begin
50
+ indent = @indent.dup
51
+ @indent += @original_indent
52
+ yield
53
+ ensure
54
+ @indent = indent
55
+ end
56
+ end
57
+
58
+ def wrap(txt, prefix=@indent, linelen=@width)
59
+ return unless txt && !txt.empty?
60
+
61
+ work = conv_markup(txt)
62
+ textLen = linelen - prefix.length
63
+ patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
64
+ next_prefix = prefix.tr("^ ", " ")
65
+
66
+ res = []
67
+
68
+ while work.length > textLen
69
+ if work =~ patt
70
+ res << $1
71
+ work.slice!(0, $&.length)
72
+ else
73
+ res << work.slice!(0, textLen)
74
+ end
75
+ end
76
+ res << work if work.length.nonzero?
77
+ @output.puts(prefix + res.join("\n" + next_prefix))
78
+ end
79
+
80
+ def blankline
81
+ @output.puts
82
+ end
83
+
84
+ ##
85
+ # Called when we want to ensure a new 'wrap' starts on a newline. Only
86
+ # needed for HtmlFormatter, because the rest do their own line breaking.
87
+
88
+ def break_to_newline
89
+ end
90
+
91
+ def bold_print(txt)
92
+ @output.print txt
93
+ end
94
+
95
+ def raw_print_line(txt)
96
+ @output.puts txt
97
+ end
98
+
99
+ ##
100
+ # Convert HTML entities back to ASCII
101
+
102
+ def conv_html(txt)
103
+ txt = txt.gsub(/&gt;/, '>')
104
+ txt.gsub!(/&lt;/, '<')
105
+ txt.gsub!(/&quot;/, '"')
106
+ txt.gsub!(/&amp;/, '&')
107
+ txt
108
+ end
109
+
110
+ ##
111
+ # Convert markup into display form
112
+
113
+ def conv_markup(txt)
114
+ txt = txt.gsub(%r{<tt>(.*?)</tt>}, '+\1+')
115
+ txt.gsub!(%r{<code>(.*?)</code>}, '+\1+')
116
+ txt.gsub!(%r{<b>(.*?)</b>}, '*\1*')
117
+ txt.gsub!(%r{<em>(.*?)</em>}, '_\1_')
118
+ txt
119
+ end
120
+
121
+ def display_list(list)
122
+ case list.type
123
+ when :BULLET
124
+ prefixer = proc { |ignored| @indent + "* " }
125
+
126
+ when :NUMBER, :UPPERALPHA, :LOWERALPHA then
127
+ start = case list.type
128
+ when :NUMBER then 1
129
+ when :UPPERALPHA then 'A'
130
+ when :LOWERALPHA then 'a'
131
+ end
132
+
133
+ prefixer = proc do |ignored|
134
+ res = @indent + "#{start}.".ljust(4)
135
+ start = start.succ
136
+ res
137
+ end
138
+
139
+ when :LABELED, :NOTE then
140
+ longest = 0
141
+
142
+ list.contents.each do |item|
143
+ if RDoc::Markup::Flow::LI === item and item.label.length > longest then
144
+ longest = item.label.length
145
+ end
146
+ end
147
+
148
+ longest += 1
149
+
150
+ prefixer = proc { |li| @indent + li.label.ljust(longest) }
151
+
152
+ else
153
+ raise ArgumentError, "unknown list type #{list.type}"
154
+ end
155
+
156
+ list.contents.each do |item|
157
+ if RDoc::Markup::Flow::LI === item then
158
+ prefix = prefixer.call item
159
+ display_flow_item item, prefix
160
+ else
161
+ display_flow_item item
162
+ end
163
+ end
164
+ end
165
+
166
+ def display_flow_item(item, prefix = @indent)
167
+ case item
168
+ when RDoc::Markup::Flow::P, RDoc::Markup::Flow::LI
169
+ wrap(conv_html(item.body), prefix)
170
+ blankline
171
+
172
+ when RDoc::Markup::Flow::LIST
173
+ display_list(item)
174
+
175
+ when RDoc::Markup::Flow::VERB
176
+ display_verbatim_flow_item(item, @indent)
177
+
178
+ when RDoc::Markup::Flow::H
179
+ display_heading(conv_html(item.text), item.level, @indent)
180
+
181
+ when RDoc::Markup::Flow::RULE
182
+ draw_line
183
+
184
+ else
185
+ raise RDoc::Error, "Unknown flow element: #{item.class}"
186
+ end
187
+ end
188
+
189
+ def display_verbatim_flow_item(item, prefix=@indent)
190
+ item.body.split(/\n/).each do |line|
191
+ @output.print @indent, conv_html(line), "\n"
192
+ end
193
+ blankline
194
+ end
195
+
196
+ def display_heading(text, level, indent)
197
+ text = strip_attributes text
198
+
199
+ case level
200
+ when 1 then
201
+ ul = "=" * text.length
202
+ @output.puts
203
+ @output.puts text.upcase
204
+ @output.puts ul
205
+
206
+ when 2 then
207
+ ul = "-" * text.length
208
+ @output.puts
209
+ @output.puts text
210
+ @output.puts ul
211
+ else
212
+ @output.print indent, text, "\n"
213
+ end
214
+
215
+ @output.puts
216
+ end
217
+
218
+ def display_flow(flow)
219
+ flow.each do |f|
220
+ display_flow_item(f)
221
+ end
222
+ end
223
+
224
+ def strip_attributes(text)
225
+ text.gsub(/(<\/?(?:b|code|em|i|tt)>)/, '')
226
+ end
227
+
228
+ end
229
+
230
+ ##
231
+ # Handle text with attributes. We're a base class: there are different
232
+ # presentation classes (one, for example, uses overstrikes to handle bold and
233
+ # underlining, while another using ANSI escape sequences.
234
+
235
+ class RDoc::RI::AttributeFormatter < RDoc::RI::Formatter
236
+
237
+ BOLD = 1
238
+ ITALIC = 2
239
+ CODE = 4
240
+
241
+ ATTR_MAP = {
242
+ "b" => BOLD,
243
+ "code" => CODE,
244
+ "em" => ITALIC,
245
+ "i" => ITALIC,
246
+ "tt" => CODE
247
+ }
248
+
249
+ AttrChar = Struct.new :char, :attr
250
+
251
+ class AttributeString
252
+ attr_reader :txt
253
+
254
+ def initialize
255
+ @txt = []
256
+ @optr = 0
257
+ end
258
+
259
+ def <<(char)
260
+ @txt << char
261
+ end
262
+
263
+ def empty?
264
+ @optr >= @txt.length
265
+ end
266
+
267
+ # accept non space, then all following spaces
268
+ def next_word
269
+ start = @optr
270
+ len = @txt.length
271
+
272
+ while @optr < len && @txt[@optr].char != " "
273
+ @optr += 1
274
+ end
275
+
276
+ while @optr < len && @txt[@optr].char == " "
277
+ @optr += 1
278
+ end
279
+
280
+ @txt[start...@optr]
281
+ end
282
+ end
283
+
284
+ ##
285
+ # Overrides base class. Looks for <tt>...</tt> etc sequences and generates
286
+ # an array of AttrChars. This array is then used as the basis for the
287
+ # split.
288
+
289
+ def wrap(txt, prefix=@indent, linelen=@width)
290
+ return unless txt && !txt.empty?
291
+
292
+ txt = add_attributes_to(txt)
293
+ next_prefix = prefix.tr("^ ", " ")
294
+ linelen -= prefix.size
295
+
296
+ line = []
297
+
298
+ until txt.empty?
299
+ word = txt.next_word
300
+ if word.size + line.size > linelen
301
+ write_attribute_text(prefix, line)
302
+ prefix = next_prefix
303
+ line = []
304
+ end
305
+ line.concat(word)
306
+ end
307
+
308
+ write_attribute_text(prefix, line) if line.length > 0
309
+ end
310
+
311
+ protected
312
+
313
+ def write_attribute_text(prefix, line)
314
+ @output.print prefix
315
+ line.each do |achar|
316
+ @output.print achar.char
317
+ end
318
+ @output.puts
319
+ end
320
+
321
+ def bold_print(txt)
322
+ @output.print txt
323
+ end
324
+
325
+ private
326
+
327
+ def add_attributes_to(txt)
328
+ tokens = txt.split(%r{(</?(?:b|code|em|i|tt)>)})
329
+ text = AttributeString.new
330
+ attributes = 0
331
+ tokens.each do |tok|
332
+ case tok
333
+ when %r{^</(\w+)>$} then attributes &= ~(ATTR_MAP[$1]||0)
334
+ when %r{^<(\w+)>$} then attributes |= (ATTR_MAP[$1]||0)
335
+ else
336
+ tok.split(//).each {|ch| text << AttrChar.new(ch, attributes)}
337
+ end
338
+ end
339
+ text
340
+ end
341
+
342
+ end
343
+
344
+ ##
345
+ # This formatter generates overstrike-style formatting, which works with
346
+ # pagers such as man and less.
347
+
348
+ class RDoc::RI::OverstrikeFormatter < RDoc::RI::AttributeFormatter
349
+
350
+ BS = "\C-h"
351
+
352
+ def write_attribute_text(prefix, line)
353
+ @output.print prefix
354
+
355
+ line.each do |achar|
356
+ attr = achar.attr
357
+ @output.print "_", BS if (attr & (ITALIC + CODE)) != 0
358
+ @output.print achar.char, BS if (attr & BOLD) != 0
359
+ @output.print achar.char
360
+ end
361
+
362
+ @output.puts
363
+ end
364
+
365
+ ##
366
+ # Draw a string in bold
367
+
368
+ def bold_print(text)
369
+ text.split(//).each do |ch|
370
+ @output.print ch, BS, ch
371
+ end
372
+ end
373
+
374
+ end
375
+
376
+ ##
377
+ # This formatter uses ANSI escape sequences to colorize stuff works with
378
+ # pagers such as man and less.
379
+
380
+ class RDoc::RI::AnsiFormatter < RDoc::RI::AttributeFormatter
381
+
382
+ def initialize(*args)
383
+ super
384
+ @output.print "\033[0m"
385
+ end
386
+
387
+ def write_attribute_text(prefix, line)
388
+ @output.print prefix
389
+ curr_attr = 0
390
+ line.each do |achar|
391
+ attr = achar.attr
392
+ if achar.attr != curr_attr
393
+ update_attributes(achar.attr)
394
+ curr_attr = achar.attr
395
+ end
396
+ @output.print achar.char
397
+ end
398
+ update_attributes(0) unless curr_attr.zero?
399
+ @output.puts
400
+ end
401
+
402
+ def bold_print(txt)
403
+ @output.print "\033[1m#{txt}\033[m"
404
+ end
405
+
406
+ HEADINGS = {
407
+ 1 => ["\033[1;32m", "\033[m"],
408
+ 2 => ["\033[4;32m", "\033[m"],
409
+ 3 => ["\033[32m", "\033[m"],
410
+ }
411
+
412
+ def display_heading(text, level, indent)
413
+ level = 3 if level > 3
414
+ heading = HEADINGS[level]
415
+ @output.print indent
416
+ @output.print heading[0]
417
+ @output.print strip_attributes(text)
418
+ @output.puts heading[1]
419
+ end
420
+
421
+ private
422
+
423
+ ATTR_MAP = {
424
+ BOLD => "1",
425
+ ITALIC => "33",
426
+ CODE => "36"
427
+ }
428
+
429
+ def update_attributes(attr)
430
+ str = "\033["
431
+ for quality in [ BOLD, ITALIC, CODE]
432
+ unless (attr & quality).zero?
433
+ str << ATTR_MAP[quality]
434
+ end
435
+ end
436
+ @output.print str, "m"
437
+ end
438
+
439
+ end
440
+
441
+ ##
442
+ # This formatter uses HTML.
443
+
444
+ class RDoc::RI::HtmlFormatter < RDoc::RI::AttributeFormatter
445
+
446
+ def write_attribute_text(prefix, line)
447
+ curr_attr = 0
448
+ line.each do |achar|
449
+ attr = achar.attr
450
+ if achar.attr != curr_attr
451
+ update_attributes(curr_attr, achar.attr)
452
+ curr_attr = achar.attr
453
+ end
454
+ @output.print(escape(achar.char))
455
+ end
456
+ update_attributes(curr_attr, 0) unless curr_attr.zero?
457
+ end
458
+
459
+ def draw_line(label=nil)
460
+ if label != nil
461
+ bold_print(label)
462
+ end
463
+ @output.puts("<hr>")
464
+ end
465
+
466
+ def bold_print(txt)
467
+ tag("b") { txt }
468
+ end
469
+
470
+ def blankline()
471
+ @output.puts("<p>")
472
+ end
473
+
474
+ def break_to_newline
475
+ @output.puts("<br>")
476
+ end
477
+
478
+ def display_heading(text, level, indent)
479
+ level = 4 if level > 4
480
+ tag("h#{level}") { text }
481
+ @output.puts
482
+ end
483
+
484
+ def display_list(list)
485
+ case list.type
486
+ when :BULLET then
487
+ list_type = "ul"
488
+ prefixer = proc { |ignored| "<li>" }
489
+
490
+ when :NUMBER, :UPPERALPHA, :LOWERALPHA then
491
+ list_type = "ol"
492
+ prefixer = proc { |ignored| "<li>" }
493
+
494
+ when :LABELED then
495
+ list_type = "dl"
496
+ prefixer = proc do |li|
497
+ "<dt><b>" + escape(li.label) + "</b><dd>"
498
+ end
499
+
500
+ when :NOTE then
501
+ list_type = "table"
502
+ prefixer = proc do |li|
503
+ %{<tr valign="top"><td>#{li.label.gsub(/ /, '&nbsp;')}</td><td>}
504
+ end
505
+ else
506
+ fail "unknown list type"
507
+ end
508
+
509
+ @output.print "<#{list_type}>"
510
+ list.contents.each do |item|
511
+ if item.kind_of? RDoc::Markup::Flow::LI
512
+ prefix = prefixer.call(item)
513
+ @output.print prefix
514
+ display_flow_item(item, prefix)
515
+ else
516
+ display_flow_item(item)
517
+ end
518
+ end
519
+ @output.print "</#{list_type}>"
520
+ end
521
+
522
+ def display_verbatim_flow_item(item, prefix=@indent)
523
+ @output.print("<pre>")
524
+ item.body.split(/\n/).each do |line|
525
+ @output.puts conv_html(line)
526
+ end
527
+ @output.puts("</pre>")
528
+ end
529
+
530
+ private
531
+
532
+ ATTR_MAP = {
533
+ BOLD => "b>",
534
+ ITALIC => "i>",
535
+ CODE => "tt>"
536
+ }
537
+
538
+ def update_attributes(current, wanted)
539
+ str = ""
540
+ # first turn off unwanted ones
541
+ off = current & ~wanted
542
+ for quality in [ BOLD, ITALIC, CODE]
543
+ if (off & quality) > 0
544
+ str << "</" + ATTR_MAP[quality]
545
+ end
546
+ end
547
+
548
+ # now turn on wanted
549
+ for quality in [ BOLD, ITALIC, CODE]
550
+ unless (wanted & quality).zero?
551
+ str << "<" << ATTR_MAP[quality]
552
+ end
553
+ end
554
+ @output.print str
555
+ end
556
+
557
+ def tag(code)
558
+ @output.print("<#{code}>")
559
+ @output.print(yield)
560
+ @output.print("</#{code}>")
561
+ end
562
+
563
+ def escape(str)
564
+ str = str.gsub(/&/n, '&amp;')
565
+ str.gsub!(/\"/n, '&quot;')
566
+ str.gsub!(/>/n, '&gt;')
567
+ str.gsub!(/</n, '&lt;')
568
+ str
569
+ end
570
+
571
+ end
572
+
573
+ ##
574
+ # This formatter reduces extra lines for a simpler output. It improves way
575
+ # output looks for tools like IRC bots.
576
+
577
+ class RDoc::RI::SimpleFormatter < RDoc::RI::Formatter
578
+
579
+ ##
580
+ # No extra blank lines
581
+
582
+ def blankline
583
+ end
584
+
585
+ ##
586
+ # Display labels only, no lines
587
+
588
+ def draw_line(label=nil)
589
+ unless label.nil? then
590
+ bold_print(label)
591
+ @output.puts
592
+ end
593
+ end
594
+
595
+ ##
596
+ # Place heading level indicators inline with heading.
597
+
598
+ def display_heading(text, level, indent)
599
+ text = strip_attributes(text)
600
+ case level
601
+ when 1
602
+ @output.puts "= " + text.upcase
603
+ when 2
604
+ @output.puts "-- " + text
605
+ else
606
+ @output.print indent, text, "\n"
607
+ end
608
+ end
609
+
610
+ end
611
+
612
+ RDoc::RI::Formatter::FORMATTERS['plain'] = RDoc::RI::Formatter
613
+ RDoc::RI::Formatter::FORMATTERS['simple'] = RDoc::RI::SimpleFormatter
614
+ RDoc::RI::Formatter::FORMATTERS['bs'] = RDoc::RI::OverstrikeFormatter
615
+ RDoc::RI::Formatter::FORMATTERS['ansi'] = RDoc::RI::AnsiFormatter
616
+ RDoc::RI::Formatter::FORMATTERS['html'] = RDoc::RI::HtmlFormatter