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.
- data/History.txt +13 -0
- data/Manifest.txt +61 -0
- data/README.txt +34 -0
- data/Rakefile +10 -0
- data/bin/rdoc +22 -0
- data/bin/ri +6 -0
- data/lib/rdoc.rb +277 -0
- data/lib/rdoc/code_objects.rb +776 -0
- data/lib/rdoc/diagram.rb +338 -0
- data/lib/rdoc/dot.rb +249 -0
- data/lib/rdoc/generator.rb +1048 -0
- data/lib/rdoc/generator/chm.rb +113 -0
- data/lib/rdoc/generator/chm/chm.rb +98 -0
- data/lib/rdoc/generator/html.rb +370 -0
- data/lib/rdoc/generator/html/hefss.rb +414 -0
- data/lib/rdoc/generator/html/html.rb +704 -0
- data/lib/rdoc/generator/html/kilmer.rb +418 -0
- data/lib/rdoc/generator/html/one_page_html.rb +121 -0
- data/lib/rdoc/generator/ri.rb +229 -0
- data/lib/rdoc/generator/xml.rb +120 -0
- data/lib/rdoc/generator/xml/rdf.rb +113 -0
- data/lib/rdoc/generator/xml/xml.rb +111 -0
- data/lib/rdoc/markup.rb +473 -0
- data/lib/rdoc/markup/attribute_manager.rb +274 -0
- data/lib/rdoc/markup/formatter.rb +14 -0
- data/lib/rdoc/markup/fragments.rb +337 -0
- data/lib/rdoc/markup/inline.rb +101 -0
- data/lib/rdoc/markup/lines.rb +152 -0
- data/lib/rdoc/markup/preprocess.rb +71 -0
- data/lib/rdoc/markup/to_flow.rb +185 -0
- data/lib/rdoc/markup/to_html.rb +353 -0
- data/lib/rdoc/markup/to_html_crossref.rb +86 -0
- data/lib/rdoc/markup/to_latex.rb +328 -0
- data/lib/rdoc/markup/to_test.rb +50 -0
- data/lib/rdoc/options.rb +616 -0
- data/lib/rdoc/parsers/parse_c.rb +775 -0
- data/lib/rdoc/parsers/parse_f95.rb +1841 -0
- data/lib/rdoc/parsers/parse_rb.rb +2584 -0
- data/lib/rdoc/parsers/parse_simple.rb +40 -0
- data/lib/rdoc/parsers/parserfactory.rb +99 -0
- data/lib/rdoc/rdoc.rb +277 -0
- data/lib/rdoc/ri.rb +4 -0
- data/lib/rdoc/ri/cache.rb +188 -0
- data/lib/rdoc/ri/descriptions.rb +150 -0
- data/lib/rdoc/ri/display.rb +274 -0
- data/lib/rdoc/ri/driver.rb +452 -0
- data/lib/rdoc/ri/formatter.rb +616 -0
- data/lib/rdoc/ri/paths.rb +102 -0
- data/lib/rdoc/ri/reader.rb +106 -0
- data/lib/rdoc/ri/util.rb +81 -0
- data/lib/rdoc/ri/writer.rb +68 -0
- data/lib/rdoc/stats.rb +25 -0
- data/lib/rdoc/template.rb +64 -0
- data/lib/rdoc/tokenstream.rb +33 -0
- data/test/test_rdoc_c_parser.rb +261 -0
- data/test/test_rdoc_markup.rb +613 -0
- data/test/test_rdoc_markup_attribute_manager.rb +224 -0
- data/test/test_rdoc_ri_attribute_formatter.rb +42 -0
- data/test/test_rdoc_ri_default_display.rb +295 -0
- data/test/test_rdoc_ri_formatter.rb +318 -0
- data/test/test_rdoc_ri_overstrike_formatter.rb +69 -0
- metadata +134 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'rdoc/markup'
|
2
|
+
|
3
|
+
class RDoc::Markup
|
4
|
+
|
5
|
+
##
|
6
|
+
# We manage a set of attributes. Each attribute has a symbol name and a bit
|
7
|
+
# value.
|
8
|
+
|
9
|
+
class Attribute
|
10
|
+
SPECIAL = 1
|
11
|
+
|
12
|
+
@@name_to_bitmap = { :_SPECIAL_ => SPECIAL }
|
13
|
+
@@next_bitmap = 2
|
14
|
+
|
15
|
+
def self.bitmap_for(name)
|
16
|
+
bitmap = @@name_to_bitmap[name]
|
17
|
+
unless bitmap then
|
18
|
+
bitmap = @@next_bitmap
|
19
|
+
@@next_bitmap <<= 1
|
20
|
+
@@name_to_bitmap[name] = bitmap
|
21
|
+
end
|
22
|
+
bitmap
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.as_string(bitmap)
|
26
|
+
return "none" if bitmap.zero?
|
27
|
+
res = []
|
28
|
+
@@name_to_bitmap.each do |name, bit|
|
29
|
+
res << name if (bitmap & bit) != 0
|
30
|
+
end
|
31
|
+
res.join(",")
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.each_name_of(bitmap)
|
35
|
+
@@name_to_bitmap.each do |name, bit|
|
36
|
+
next if bit == SPECIAL
|
37
|
+
yield name.to_s if (bitmap & bit) != 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
AttrChanger = Struct.new(:turn_on, :turn_off)
|
43
|
+
|
44
|
+
##
|
45
|
+
# An AttrChanger records a change in attributes. It contains a bitmap of the
|
46
|
+
# attributes to turn on, and a bitmap of those to turn off.
|
47
|
+
|
48
|
+
class AttrChanger
|
49
|
+
def to_s
|
50
|
+
"Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# An array of attributes which parallels the characters in a string.
|
56
|
+
|
57
|
+
class AttrSpan
|
58
|
+
def initialize(length)
|
59
|
+
@attrs = Array.new(length, 0)
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_attrs(start, length, bits)
|
63
|
+
for i in start ... (start+length)
|
64
|
+
@attrs[i] |= bits
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def [](n)
|
69
|
+
@attrs[n]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Hold details of a special sequence
|
75
|
+
|
76
|
+
class Special
|
77
|
+
attr_reader :type
|
78
|
+
attr_accessor :text
|
79
|
+
|
80
|
+
def initialize(type, text)
|
81
|
+
@type, @text = type, text
|
82
|
+
end
|
83
|
+
|
84
|
+
def ==(o)
|
85
|
+
self.text == o.text && self.type == o.type
|
86
|
+
end
|
87
|
+
|
88
|
+
def inspect
|
89
|
+
"#<RDoc::Markup::Special:0x%x @type=%p, name=%p @text=%p>" % [
|
90
|
+
object_id, @type, RDoc::Markup::Attribute.as_string(type), text.dump]
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_s
|
94
|
+
"Special: type=#{type}, name=#{RDoc::Markup::Attribute.as_string type}, text=#{text.dump}"
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
require 'rdoc/markup/attribute_manager'
|
@@ -0,0 +1,152 @@
|
|
1
|
+
class RDoc::Markup
|
2
|
+
|
3
|
+
##
|
4
|
+
# We store the lines we're working on as objects of class Line. These
|
5
|
+
# contain the text of the line, along with a flag indicating the line type,
|
6
|
+
# and an indentation level.
|
7
|
+
|
8
|
+
class Line
|
9
|
+
INFINITY = 9999
|
10
|
+
|
11
|
+
LINE_TYPES = [
|
12
|
+
:BLANK,
|
13
|
+
:HEADING,
|
14
|
+
:LIST,
|
15
|
+
:PARAGRAPH,
|
16
|
+
:RULE,
|
17
|
+
:VERBATIM,
|
18
|
+
]
|
19
|
+
|
20
|
+
# line type
|
21
|
+
attr_accessor :type
|
22
|
+
|
23
|
+
# The indentation nesting level
|
24
|
+
attr_accessor :level
|
25
|
+
|
26
|
+
# The contents
|
27
|
+
attr_accessor :text
|
28
|
+
|
29
|
+
# A prefix or parameter. For LIST lines, this is
|
30
|
+
# the text that introduced the list item (the label)
|
31
|
+
attr_accessor :param
|
32
|
+
|
33
|
+
# A flag. For list lines, this is the type of the list
|
34
|
+
attr_accessor :flag
|
35
|
+
|
36
|
+
# the number of leading spaces
|
37
|
+
attr_accessor :leading_spaces
|
38
|
+
|
39
|
+
# true if this line has been deleted from the list of lines
|
40
|
+
attr_accessor :deleted
|
41
|
+
|
42
|
+
def initialize(text)
|
43
|
+
@text = text.dup
|
44
|
+
@deleted = false
|
45
|
+
|
46
|
+
# expand tabs
|
47
|
+
1 while @text.gsub!(/\t+/) { ' ' * (8*$&.length - $`.length % 8)} && $~ #`
|
48
|
+
|
49
|
+
# Strip trailing whitespace
|
50
|
+
@text.sub!(/\s+$/, '')
|
51
|
+
|
52
|
+
# and look for leading whitespace
|
53
|
+
if @text.length > 0
|
54
|
+
@text =~ /^(\s*)/
|
55
|
+
@leading_spaces = $1.length
|
56
|
+
else
|
57
|
+
@leading_spaces = INFINITY
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return true if this line is blank
|
62
|
+
def blank?
|
63
|
+
@text.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
# stamp a line with a type, a level, a prefix, and a flag
|
67
|
+
def stamp(type, level, param="", flag=nil)
|
68
|
+
@type, @level, @param, @flag = type, level, param, flag
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Strip off the leading margin
|
73
|
+
|
74
|
+
def strip_leading(size)
|
75
|
+
if @text.size > size
|
76
|
+
@text[0,size] = ""
|
77
|
+
else
|
78
|
+
@text = ""
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_s
|
83
|
+
"#@type#@level: #@text"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# A container for all the lines.
|
89
|
+
|
90
|
+
class Lines
|
91
|
+
|
92
|
+
include Enumerable
|
93
|
+
|
94
|
+
attr_reader :lines # :nodoc:
|
95
|
+
|
96
|
+
def initialize(lines)
|
97
|
+
@lines = lines
|
98
|
+
rewind
|
99
|
+
end
|
100
|
+
|
101
|
+
def empty?
|
102
|
+
@lines.size.zero?
|
103
|
+
end
|
104
|
+
|
105
|
+
def each
|
106
|
+
@lines.each do |line|
|
107
|
+
yield line unless line.deleted
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# def [](index)
|
112
|
+
# @lines[index]
|
113
|
+
# end
|
114
|
+
|
115
|
+
def rewind
|
116
|
+
@nextline = 0
|
117
|
+
end
|
118
|
+
|
119
|
+
def next
|
120
|
+
begin
|
121
|
+
res = @lines[@nextline]
|
122
|
+
@nextline += 1 if @nextline < @lines.size
|
123
|
+
end while res and res.deleted and @nextline < @lines.size
|
124
|
+
res
|
125
|
+
end
|
126
|
+
|
127
|
+
def unget
|
128
|
+
@nextline -= 1
|
129
|
+
end
|
130
|
+
|
131
|
+
def delete(a_line)
|
132
|
+
a_line.deleted = true
|
133
|
+
end
|
134
|
+
|
135
|
+
def normalize
|
136
|
+
margin = @lines.collect{|l| l.leading_spaces}.min
|
137
|
+
margin = 0 if margin == :INFINITY
|
138
|
+
@lines.each {|line| line.strip_leading(margin) } if margin > 0
|
139
|
+
end
|
140
|
+
|
141
|
+
def as_text
|
142
|
+
@lines.map {|l| l.text}.join("\n")
|
143
|
+
end
|
144
|
+
|
145
|
+
def line_types
|
146
|
+
@lines.map {|l| l.type }
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rdoc/markup'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Handle common directives that can occur in a block of text:
|
5
|
+
#
|
6
|
+
# : include : filename
|
7
|
+
|
8
|
+
class RDoc::Markup::PreProcess
|
9
|
+
|
10
|
+
def initialize(input_file_name, include_path)
|
11
|
+
@input_file_name = input_file_name
|
12
|
+
@include_path = include_path
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Look for common options in a chunk of text. Options that we don't handle
|
17
|
+
# are passed back to our caller as |directive, param|
|
18
|
+
|
19
|
+
def handle(text)
|
20
|
+
text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do
|
21
|
+
prefix = $1
|
22
|
+
directive = $2.downcase
|
23
|
+
param = $3
|
24
|
+
|
25
|
+
case directive
|
26
|
+
when "include"
|
27
|
+
filename = param.split[0]
|
28
|
+
include_file(filename, prefix)
|
29
|
+
|
30
|
+
else
|
31
|
+
yield(directive, param)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
##
|
39
|
+
# Include a file, indenting it correctly.
|
40
|
+
|
41
|
+
def include_file(name, indent)
|
42
|
+
if full_name = find_include_file(name) then
|
43
|
+
content = File.open(full_name) {|f| f.read}
|
44
|
+
# strip leading '#'s, but only if all lines start with them
|
45
|
+
if content =~ /^[^#]/
|
46
|
+
content.gsub(/^/, indent)
|
47
|
+
else
|
48
|
+
content.gsub(/^#?/, indent)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
$stderr.puts "Couldn't find file to include: '#{name}'"
|
52
|
+
''
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Look for the given file in the directory containing the current file,
|
58
|
+
# and then in each of the directories specified in the RDOC_INCLUDE path
|
59
|
+
|
60
|
+
def find_include_file(name)
|
61
|
+
to_search = [ File.dirname(@input_file_name) ].concat @include_path
|
62
|
+
to_search.each do |dir|
|
63
|
+
full_name = File.join(dir, name)
|
64
|
+
stat = File.stat(full_name) rescue next
|
65
|
+
return full_name if stat.readable?
|
66
|
+
end
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'rdoc/markup/formatter'
|
2
|
+
require 'rdoc/markup/fragments'
|
3
|
+
require 'rdoc/markup/inline'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
class RDoc::Markup
|
7
|
+
|
8
|
+
module Flow
|
9
|
+
P = Struct.new(:body)
|
10
|
+
VERB = Struct.new(:body)
|
11
|
+
RULE = Struct.new(:width)
|
12
|
+
class LIST
|
13
|
+
attr_reader :type, :contents
|
14
|
+
def initialize(type)
|
15
|
+
@type = type
|
16
|
+
@contents = []
|
17
|
+
end
|
18
|
+
def <<(stuff)
|
19
|
+
@contents << stuff
|
20
|
+
end
|
21
|
+
end
|
22
|
+
LI = Struct.new(:label, :body)
|
23
|
+
H = Struct.new(:level, :text)
|
24
|
+
end
|
25
|
+
|
26
|
+
class ToFlow < RDoc::Markup::Formatter
|
27
|
+
LIST_TYPE_TO_HTML = {
|
28
|
+
:BULLET => [ "<ul>", "</ul>" ],
|
29
|
+
:NUMBER => [ "<ol>", "</ol>" ],
|
30
|
+
:UPPERALPHA => [ "<ol>", "</ol>" ],
|
31
|
+
:LOWERALPHA => [ "<ol>", "</ol>" ],
|
32
|
+
:LABELED => [ "<dl>", "</dl>" ],
|
33
|
+
:NOTE => [ "<table>", "</table>" ],
|
34
|
+
}
|
35
|
+
|
36
|
+
InlineTag = Struct.new(:bit, :on, :off)
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
super
|
40
|
+
|
41
|
+
init_tags
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Set up the standard mapping of attributes to HTML tags
|
46
|
+
|
47
|
+
def init_tags
|
48
|
+
@attr_tags = [
|
49
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
|
50
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
|
51
|
+
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:EM), "<em>", "</em>"),
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Add a new set of HTML tags for an attribute. We allow separate start and
|
57
|
+
# end tags for flexibility
|
58
|
+
|
59
|
+
def add_tag(name, start, stop)
|
60
|
+
@attr_tags << InlineTag.new(RDoc::Markup::Attribute.bitmap_for(name), start, stop)
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Given an HTML tag, decorate it with class information and the like if
|
65
|
+
# required. This is a no-op in the base class, but is overridden in HTML
|
66
|
+
# output classes that implement style sheets
|
67
|
+
|
68
|
+
def annotate(tag)
|
69
|
+
tag
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Here's the client side of the visitor pattern
|
74
|
+
|
75
|
+
def start_accepting
|
76
|
+
@res = []
|
77
|
+
@list_stack = []
|
78
|
+
end
|
79
|
+
|
80
|
+
def end_accepting
|
81
|
+
@res
|
82
|
+
end
|
83
|
+
|
84
|
+
def accept_paragraph(am, fragment)
|
85
|
+
@res << Flow::P.new((convert_flow(am.flow(fragment.txt))))
|
86
|
+
end
|
87
|
+
|
88
|
+
def accept_verbatim(am, fragment)
|
89
|
+
@res << Flow::VERB.new((convert_flow(am.flow(fragment.txt))))
|
90
|
+
end
|
91
|
+
|
92
|
+
def accept_rule(am, fragment)
|
93
|
+
size = fragment.param
|
94
|
+
size = 10 if size > 10
|
95
|
+
@res << Flow::RULE.new(size)
|
96
|
+
end
|
97
|
+
|
98
|
+
def accept_list_start(am, fragment)
|
99
|
+
@list_stack.push(@res)
|
100
|
+
list = Flow::LIST.new(fragment.type)
|
101
|
+
@res << list
|
102
|
+
@res = list
|
103
|
+
end
|
104
|
+
|
105
|
+
def accept_list_end(am, fragment)
|
106
|
+
@res = @list_stack.pop
|
107
|
+
end
|
108
|
+
|
109
|
+
def accept_list_item(am, fragment)
|
110
|
+
@res << Flow::LI.new(fragment.param, convert_flow(am.flow(fragment.txt)))
|
111
|
+
end
|
112
|
+
|
113
|
+
def accept_blank_line(am, fragment)
|
114
|
+
# @res << annotate("<p />") << "\n"
|
115
|
+
end
|
116
|
+
|
117
|
+
def accept_heading(am, fragment)
|
118
|
+
@res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def on_tags(res, item)
|
124
|
+
attr_mask = item.turn_on
|
125
|
+
return if attr_mask.zero?
|
126
|
+
|
127
|
+
@attr_tags.each do |tag|
|
128
|
+
if attr_mask & tag.bit != 0
|
129
|
+
res << annotate(tag.on)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def off_tags(res, item)
|
135
|
+
attr_mask = item.turn_off
|
136
|
+
return if attr_mask.zero?
|
137
|
+
|
138
|
+
@attr_tags.reverse_each do |tag|
|
139
|
+
if attr_mask & tag.bit != 0
|
140
|
+
res << annotate(tag.off)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def convert_flow(flow)
|
146
|
+
res = ""
|
147
|
+
flow.each do |item|
|
148
|
+
case item
|
149
|
+
when String
|
150
|
+
res << convert_string(item)
|
151
|
+
when AttrChanger
|
152
|
+
off_tags(res, item)
|
153
|
+
on_tags(res, item)
|
154
|
+
when Special
|
155
|
+
res << convert_special(item)
|
156
|
+
else
|
157
|
+
raise "Unknown flow element: #{item.inspect}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
res
|
161
|
+
end
|
162
|
+
|
163
|
+
def convert_string(item)
|
164
|
+
CGI.escapeHTML(item)
|
165
|
+
end
|
166
|
+
|
167
|
+
def convert_special(special)
|
168
|
+
handled = false
|
169
|
+
Attribute.each_name_of(special.type) do |name|
|
170
|
+
method_name = "handle_special_#{name}"
|
171
|
+
if self.respond_to? method_name
|
172
|
+
special.text = send(method_name, special)
|
173
|
+
handled = true
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
raise "Unhandled special: #{special}" unless handled
|
178
|
+
|
179
|
+
special.text
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|