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,274 @@
1
+ require 'rdoc/markup/inline'
2
+
3
+ class RDoc::Markup::AttributeManager
4
+
5
+ NULL = "\000".freeze
6
+
7
+ ##
8
+ # We work by substituting non-printing characters in to the text. For now
9
+ # I'm assuming that I can substitute a character in the range 0..8 for a 7
10
+ # bit character without damaging the encoded string, but this might be
11
+ # optimistic
12
+
13
+ A_PROTECT = 004
14
+ PROTECT_ATTR = A_PROTECT.chr
15
+
16
+ ##
17
+ # This maps delimiters that occur around words (such as *bold* or +tt+)
18
+ # where the start and end delimiters and the same. This lets us optimize
19
+ # the regexp
20
+
21
+ MATCHING_WORD_PAIRS = {}
22
+
23
+ ##
24
+ # And this is used when the delimiters aren't the same. In this case the
25
+ # hash maps a pattern to the attribute character
26
+
27
+ WORD_PAIR_MAP = {}
28
+
29
+ ##
30
+ # This maps HTML tags to the corresponding attribute char
31
+
32
+ HTML_TAGS = {}
33
+
34
+ ##
35
+ # And this maps _special_ sequences to a name. A special sequence is
36
+ # something like a WikiWord
37
+
38
+ SPECIAL = {}
39
+
40
+ ##
41
+ # Return an attribute object with the given turn_on and turn_off bits set
42
+
43
+ def attribute(turn_on, turn_off)
44
+ RDoc::Markup::AttrChanger.new turn_on, turn_off
45
+ end
46
+
47
+ def change_attribute(current, new)
48
+ diff = current ^ new
49
+ attribute(new & diff, current & diff)
50
+ end
51
+
52
+ def changed_attribute_by_name(current_set, new_set)
53
+ current = new = 0
54
+ current_set.each do |name|
55
+ current |= RDoc::Markup::Attribute.bitmap_for(name)
56
+ end
57
+
58
+ new_set.each do |name|
59
+ new |= RDoc::Markup::Attribute.bitmap_for(name)
60
+ end
61
+
62
+ change_attribute(current, new)
63
+ end
64
+
65
+ def copy_string(start_pos, end_pos)
66
+ res = @str[start_pos...end_pos]
67
+ res.gsub!(/\000/, '')
68
+ res
69
+ end
70
+
71
+ ##
72
+ # Map attributes like <b>text</b>to the sequence
73
+ # \001\002<char>\001\003<char>, where <char> is a per-attribute specific
74
+ # character
75
+
76
+ def convert_attrs(str, attrs)
77
+ # first do matching ones
78
+ tags = MATCHING_WORD_PAIRS.keys.join("")
79
+
80
+ re = /(^|\W)([#{tags}])([#:\\]?[\w.\/-]+?\S?)\2(\W|$)/
81
+
82
+ 1 while str.gsub!(re) do
83
+ attr = MATCHING_WORD_PAIRS[$2]
84
+ attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr)
85
+ $1 + NULL * $2.length + $3 + NULL * $2.length + $4
86
+ end
87
+
88
+ # then non-matching
89
+ unless WORD_PAIR_MAP.empty? then
90
+ WORD_PAIR_MAP.each do |regexp, attr|
91
+ str.gsub!(regexp) {
92
+ attrs.set_attrs($`.length + $1.length, $2.length, attr)
93
+ NULL * $1.length + $2 + NULL * $3.length
94
+ }
95
+ end
96
+ end
97
+ end
98
+
99
+ def convert_html(str, attrs)
100
+ tags = HTML_TAGS.keys.join '|'
101
+
102
+ 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) {
103
+ attr = HTML_TAGS[$1.downcase]
104
+ html_length = $1.length + 2
105
+ seq = NULL * html_length
106
+ attrs.set_attrs($`.length + html_length, $2.length, attr)
107
+ seq + $2 + seq + NULL
108
+ }
109
+ end
110
+
111
+ def convert_specials(str, attrs)
112
+ unless SPECIAL.empty?
113
+ SPECIAL.each do |regexp, attr|
114
+ str.scan(regexp) do
115
+ attrs.set_attrs($`.length, $&.length,
116
+ attr | RDoc::Markup::Attribute::SPECIAL)
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ ##
123
+ # A \ in front of a character that would normally be processed turns off
124
+ # processing. We do this by turning \< into <#{PROTECT}
125
+
126
+ PROTECTABLE = %w[<\\]
127
+
128
+ def mask_protected_sequences
129
+ protect_pattern = Regexp.new("\\\\([#{Regexp.escape(PROTECTABLE.join(''))}])")
130
+ @str.gsub!(protect_pattern, "\\1#{PROTECT_ATTR}")
131
+ end
132
+
133
+ def unmask_protected_sequences
134
+ @str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000")
135
+ end
136
+
137
+ def initialize
138
+ add_word_pair("*", "*", :BOLD)
139
+ add_word_pair("_", "_", :EM)
140
+ add_word_pair("+", "+", :TT)
141
+
142
+ add_html("em", :EM)
143
+ add_html("i", :EM)
144
+ add_html("b", :BOLD)
145
+ add_html("tt", :TT)
146
+ add_html("code", :TT)
147
+
148
+ add_special(/<!--(.*?)-->/, :COMMENT)
149
+ end
150
+
151
+ def add_word_pair(start, stop, name)
152
+ raise ArgumentError, "Word flags may not start with '<'" if
153
+ start[0,1] == '<'
154
+
155
+ bitmap = RDoc::Markup::Attribute.bitmap_for name
156
+
157
+ if start == stop then
158
+ MATCHING_WORD_PAIRS[start] = bitmap
159
+ else
160
+ pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/
161
+ WORD_PAIR_MAP[pattern] = bitmap
162
+ end
163
+
164
+ PROTECTABLE << start[0,1]
165
+ PROTECTABLE.uniq!
166
+ end
167
+
168
+ def add_html(tag, name)
169
+ HTML_TAGS[tag.downcase] = RDoc::Markup::Attribute.bitmap_for name
170
+ end
171
+
172
+ def add_special(pattern, name)
173
+ SPECIAL[pattern] = RDoc::Markup::Attribute.bitmap_for name
174
+ end
175
+
176
+ def flow(str)
177
+ @str = str
178
+
179
+ puts("Before flow, str='#{@str.dump}'") if $DEBUG_RDOC
180
+ mask_protected_sequences
181
+
182
+ @attrs = RDoc::Markup::AttrSpan.new @str.length
183
+
184
+ puts("After protecting, str='#{@str.dump}'") if $DEBUG_RDOC
185
+
186
+ convert_attrs(@str, @attrs)
187
+ convert_html(@str, @attrs)
188
+ convert_specials(str, @attrs)
189
+
190
+ unmask_protected_sequences
191
+
192
+ puts("After flow, str='#{@str.dump}'") if $DEBUG_RDOC
193
+
194
+ return split_into_flow
195
+ end
196
+
197
+ def display_attributes
198
+ puts
199
+ puts @str.tr(NULL, "!")
200
+ bit = 1
201
+ 16.times do |bno|
202
+ line = ""
203
+ @str.length.times do |i|
204
+ if (@attrs[i] & bit) == 0
205
+ line << " "
206
+ else
207
+ if bno.zero?
208
+ line << "S"
209
+ else
210
+ line << ("%d" % (bno+1))
211
+ end
212
+ end
213
+ end
214
+ puts(line) unless line =~ /^ *$/
215
+ bit <<= 1
216
+ end
217
+ end
218
+
219
+ def split_into_flow
220
+ display_attributes if $DEBUG_RDOC
221
+
222
+ res = []
223
+ current_attr = 0
224
+ str = ""
225
+
226
+ str_len = @str.length
227
+
228
+ # skip leading invisible text
229
+ i = 0
230
+ i += 1 while i < str_len and @str[i].chr == "\0"
231
+ start_pos = i
232
+
233
+ # then scan the string, chunking it on attribute changes
234
+ while i < str_len
235
+ new_attr = @attrs[i]
236
+ if new_attr != current_attr
237
+ if i > start_pos
238
+ res << copy_string(start_pos, i)
239
+ start_pos = i
240
+ end
241
+
242
+ res << change_attribute(current_attr, new_attr)
243
+ current_attr = new_attr
244
+
245
+ if (current_attr & RDoc::Markup::Attribute::SPECIAL) != 0 then
246
+ i += 1 while
247
+ i < str_len and (@attrs[i] & RDoc::Markup::Attribute::SPECIAL) != 0
248
+
249
+ res << RDoc::Markup::Special.new(current_attr,
250
+ copy_string(start_pos, i))
251
+ start_pos = i
252
+ next
253
+ end
254
+ end
255
+
256
+ # move on, skipping any invisible characters
257
+ begin
258
+ i += 1
259
+ end while i < str_len and @str[i].chr == "\0"
260
+ end
261
+
262
+ # tidy up trailing text
263
+ if start_pos < str_len
264
+ res << copy_string(start_pos, str_len)
265
+ end
266
+
267
+ # and reset to all attributes off
268
+ res << change_attribute(current_attr, 0) if current_attr != 0
269
+
270
+ return res
271
+ end
272
+
273
+ end
274
+
@@ -0,0 +1,14 @@
1
+ require 'rdoc/markup'
2
+
3
+ class RDoc::Markup::Formatter
4
+
5
+ def initialize
6
+ @markup = RDoc::Markup.new
7
+ end
8
+
9
+ def convert(content)
10
+ @markup.convert content, self
11
+ end
12
+
13
+ end
14
+
@@ -0,0 +1,337 @@
1
+ require 'rdoc/markup'
2
+ require 'rdoc/markup/lines'
3
+
4
+ class RDoc::Markup
5
+
6
+ ##
7
+ # A Fragment is a chunk of text, subclassed as a paragraph, a list
8
+ # entry, or verbatim text.
9
+
10
+ class Fragment
11
+ attr_reader :level, :param, :txt
12
+ attr_accessor :type
13
+
14
+ ######
15
+ # This is a simple factory system that lets us associate fragement
16
+ # types (a string) with a subclass of fragment
17
+
18
+ TYPE_MAP = {}
19
+
20
+ def self.type_name(name)
21
+ TYPE_MAP[name] = self
22
+ end
23
+
24
+ def self.for(line)
25
+ klass = TYPE_MAP[line.type] ||
26
+ raise("Unknown line type: '#{line.type.inspect}:' '#{line.text}'")
27
+ return klass.new(line.level, line.param, line.flag, line.text)
28
+ end
29
+
30
+ def initialize(level, param, type, txt)
31
+ @level = level
32
+ @param = param
33
+ @type = type
34
+ @txt = ""
35
+ add_text(txt) if txt
36
+ end
37
+
38
+ def add_text(txt)
39
+ @txt << " " if @txt.length > 0
40
+ @txt << txt.tr_s("\n ", " ").strip
41
+ end
42
+
43
+ def to_s
44
+ "L#@level: #{self.class.name.split('::')[-1]}\n#@txt"
45
+ end
46
+
47
+ end
48
+
49
+ ##
50
+ # A paragraph is a fragment which gets wrapped to fit. We remove all
51
+ # newlines when we're created, and have them put back on output.
52
+
53
+ class Paragraph < Fragment
54
+ type_name :PARAGRAPH
55
+ end
56
+
57
+ class BlankLine < Paragraph
58
+ type_name :BLANK
59
+ end
60
+
61
+ class Heading < Paragraph
62
+ type_name :HEADING
63
+
64
+ def head_level
65
+ @param.to_i
66
+ end
67
+ end
68
+
69
+ ##
70
+ # A List is a fragment with some kind of label
71
+
72
+ class ListBase < Paragraph
73
+ LIST_TYPES = [
74
+ :BULLET,
75
+ :NUMBER,
76
+ :UPPERALPHA,
77
+ :LOWERALPHA,
78
+ :LABELED,
79
+ :NOTE,
80
+ ]
81
+ end
82
+
83
+ class ListItem < ListBase
84
+ type_name :LIST
85
+
86
+ def to_s
87
+ text = if [:NOTE, :LABELED].include? type then
88
+ "#{@param}: #{@txt}"
89
+ else
90
+ @txt
91
+ end
92
+
93
+ "L#@level: #{type} #{self.class.name.split('::')[-1]}\n#{text}"
94
+ end
95
+
96
+ end
97
+
98
+ class ListStart < ListBase
99
+ def initialize(level, param, type)
100
+ super(level, param, type, nil)
101
+ end
102
+ end
103
+
104
+ class ListEnd < ListBase
105
+ def initialize(level, type)
106
+ super(level, "", type, nil)
107
+ end
108
+ end
109
+
110
+ ##
111
+ # Verbatim code contains lines that don't get wrapped.
112
+
113
+ class Verbatim < Fragment
114
+ type_name :VERBATIM
115
+
116
+ def add_text(txt)
117
+ @txt << txt.chomp << "\n"
118
+ end
119
+
120
+ end
121
+
122
+ ##
123
+ # A horizontal rule
124
+
125
+ class Rule < Fragment
126
+ type_name :RULE
127
+ end
128
+
129
+ ##
130
+ # Collect groups of lines together. Each group will end up containing a flow
131
+ # of text.
132
+
133
+ class LineCollection
134
+
135
+ def initialize
136
+ @fragments = []
137
+ end
138
+
139
+ def add(fragment)
140
+ @fragments << fragment
141
+ end
142
+
143
+ def each(&b)
144
+ @fragments.each(&b)
145
+ end
146
+
147
+ def to_a # :nodoc:
148
+ @fragments.map {|fragment| fragment.to_s}
149
+ end
150
+
151
+ ##
152
+ # Factory for different fragment types
153
+
154
+ def fragment_for(*args)
155
+ Fragment.for(*args)
156
+ end
157
+
158
+ ##
159
+ # Tidy up at the end
160
+
161
+ def normalize
162
+ change_verbatim_blank_lines
163
+ add_list_start_and_ends
164
+ add_list_breaks
165
+ tidy_blank_lines
166
+ end
167
+
168
+ def to_s
169
+ @fragments.join("\n----\n")
170
+ end
171
+
172
+ def accept(am, visitor)
173
+ visitor.start_accepting
174
+
175
+ @fragments.each do |fragment|
176
+ case fragment
177
+ when Verbatim
178
+ visitor.accept_verbatim(am, fragment)
179
+ when Rule
180
+ visitor.accept_rule(am, fragment)
181
+ when ListStart
182
+ visitor.accept_list_start(am, fragment)
183
+ when ListEnd
184
+ visitor.accept_list_end(am, fragment)
185
+ when ListItem
186
+ visitor.accept_list_item(am, fragment)
187
+ when BlankLine
188
+ visitor.accept_blank_line(am, fragment)
189
+ when Heading
190
+ visitor.accept_heading(am, fragment)
191
+ when Paragraph
192
+ visitor.accept_paragraph(am, fragment)
193
+ end
194
+ end
195
+
196
+ visitor.end_accepting
197
+ end
198
+
199
+ private
200
+
201
+ # If you have:
202
+ #
203
+ # normal paragraph text.
204
+ #
205
+ # this is code
206
+ #
207
+ # and more code
208
+ #
209
+ # You'll end up with the fragments Paragraph, BlankLine, Verbatim,
210
+ # BlankLine, Verbatim, BlankLine, etc.
211
+ #
212
+ # The BlankLine in the middle of the verbatim chunk needs to be changed to
213
+ # a real verbatim newline, and the two verbatim blocks merged
214
+
215
+ def change_verbatim_blank_lines
216
+ frag_block = nil
217
+ blank_count = 0
218
+ @fragments.each_with_index do |frag, i|
219
+ if frag_block.nil?
220
+ frag_block = frag if Verbatim === frag
221
+ else
222
+ case frag
223
+ when Verbatim
224
+ blank_count.times { frag_block.add_text("\n") }
225
+ blank_count = 0
226
+ frag_block.add_text(frag.txt)
227
+ @fragments[i] = nil # remove out current fragment
228
+ when BlankLine
229
+ if frag_block
230
+ blank_count += 1
231
+ @fragments[i] = nil
232
+ end
233
+ else
234
+ frag_block = nil
235
+ blank_count = 0
236
+ end
237
+ end
238
+ end
239
+ @fragments.compact!
240
+ end
241
+
242
+ ##
243
+ # List nesting is implicit given the level of indentation. Make it
244
+ # explicit, just to make life a tad easier for the output processors
245
+
246
+ def add_list_start_and_ends
247
+ level = 0
248
+ res = []
249
+ type_stack = []
250
+
251
+ @fragments.each do |fragment|
252
+ # $stderr.puts "#{level} : #{fragment.class.name} : #{fragment.level}"
253
+ new_level = fragment.level
254
+ while (level < new_level)
255
+ level += 1
256
+ type = fragment.type
257
+ res << ListStart.new(level, fragment.param, type) if type
258
+ type_stack.push type
259
+ # $stderr.puts "Start: #{level}"
260
+ end
261
+
262
+ while level > new_level
263
+ type = type_stack.pop
264
+ res << ListEnd.new(level, type) if type
265
+ level -= 1
266
+ # $stderr.puts "End: #{level}, #{type}"
267
+ end
268
+
269
+ res << fragment
270
+ level = fragment.level
271
+ end
272
+ level.downto(1) do |i|
273
+ type = type_stack.pop
274
+ res << ListEnd.new(i, type) if type
275
+ end
276
+
277
+ @fragments = res
278
+ end
279
+
280
+ ##
281
+ # Inserts start/ends between list entries at the same level that have
282
+ # different element types
283
+
284
+ def add_list_breaks
285
+ res = @fragments
286
+
287
+ @fragments = []
288
+ list_stack = []
289
+
290
+ res.each do |fragment|
291
+ case fragment
292
+ when ListStart
293
+ list_stack.push fragment
294
+ when ListEnd
295
+ start = list_stack.pop
296
+ fragment.type = start.type
297
+ when ListItem
298
+ l = list_stack.last
299
+ if fragment.type != l.type
300
+ @fragments << ListEnd.new(l.level, l.type)
301
+ start = ListStart.new(l.level, fragment.param, fragment.type)
302
+ @fragments << start
303
+ list_stack.pop
304
+ list_stack.push start
305
+ end
306
+ else
307
+ ;
308
+ end
309
+ @fragments << fragment
310
+ end
311
+ end
312
+
313
+ ##
314
+ # Tidy up the blank lines:
315
+ # * change Blank/ListEnd into ListEnd/Blank
316
+ # * remove blank lines at the front
317
+
318
+ def tidy_blank_lines
319
+ (@fragments.size - 1).times do |i|
320
+ if BlankLine === @fragments[i] and ListEnd === @fragments[i+1] then
321
+ @fragments[i], @fragments[i+1] = @fragments[i+1], @fragments[i]
322
+ end
323
+ end
324
+
325
+ # remove leading blanks
326
+ @fragments.each_with_index do |f, i|
327
+ break unless f.kind_of? BlankLine
328
+ @fragments[i] = nil
329
+ end
330
+
331
+ @fragments.compact!
332
+ end
333
+
334
+ end
335
+
336
+ end
337
+