rdoc 2.5.11 → 3.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 (113) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.document +1 -0
  3. data/History.txt +95 -0
  4. data/Manifest.txt +13 -4
  5. data/README.txt +9 -3
  6. data/Rakefile +1 -1
  7. data/lib/rdoc.rb +15 -298
  8. data/lib/rdoc/alias.rb +65 -16
  9. data/lib/rdoc/any_method.rb +27 -150
  10. data/lib/rdoc/attr.rb +36 -115
  11. data/lib/rdoc/class_module.rb +236 -22
  12. data/lib/rdoc/code_object.rb +76 -31
  13. data/lib/rdoc/constant.rb +32 -4
  14. data/lib/rdoc/context.rb +494 -222
  15. data/lib/rdoc/encoding.rb +79 -0
  16. data/lib/rdoc/erbio.rb +37 -0
  17. data/lib/rdoc/gauntlet.rb +9 -5
  18. data/lib/rdoc/generator.rb +33 -1
  19. data/lib/rdoc/generator/darkfish.rb +284 -375
  20. data/lib/rdoc/generator/markup.rb +72 -36
  21. data/lib/rdoc/generator/ri.rb +4 -4
  22. data/lib/rdoc/generator/template/darkfish/classpage.rhtml +267 -274
  23. data/lib/rdoc/generator/template/darkfish/filepage.rhtml +91 -91
  24. data/lib/rdoc/generator/template/darkfish/index.rhtml +45 -45
  25. data/lib/rdoc/generator/template/darkfish/rdoc.css +298 -298
  26. data/lib/rdoc/include.rb +40 -1
  27. data/lib/rdoc/known_classes.rb +1 -0
  28. data/lib/rdoc/markup.rb +467 -2
  29. data/lib/rdoc/markup/attribute_manager.rb +24 -6
  30. data/lib/rdoc/markup/blank_line.rb +11 -3
  31. data/lib/rdoc/markup/document.rb +6 -0
  32. data/lib/rdoc/markup/formatter.rb +10 -0
  33. data/lib/rdoc/markup/formatter_test_case.rb +339 -3
  34. data/lib/rdoc/markup/heading.rb +3 -0
  35. data/lib/rdoc/markup/inline.rb +11 -1
  36. data/lib/rdoc/markup/list.rb +3 -0
  37. data/lib/rdoc/markup/list_item.rb +3 -0
  38. data/lib/rdoc/markup/paragraph.rb +3 -0
  39. data/lib/rdoc/markup/parser.rb +191 -237
  40. data/lib/rdoc/markup/{preprocess.rb → pre_process.rb} +50 -29
  41. data/lib/rdoc/markup/raw.rb +4 -0
  42. data/lib/rdoc/markup/rule.rb +3 -0
  43. data/lib/rdoc/markup/text_formatter_test_case.rb +116 -0
  44. data/lib/rdoc/markup/to_ansi.rb +14 -2
  45. data/lib/rdoc/markup/to_bs.rb +8 -2
  46. data/lib/rdoc/markup/to_html.rb +84 -91
  47. data/lib/rdoc/markup/to_html_crossref.rb +77 -26
  48. data/lib/rdoc/markup/to_rdoc.rb +94 -49
  49. data/lib/rdoc/markup/to_test.rb +9 -1
  50. data/lib/rdoc/markup/verbatim.rb +6 -3
  51. data/lib/rdoc/method_attr.rb +353 -0
  52. data/lib/rdoc/normal_class.rb +11 -2
  53. data/lib/rdoc/normal_module.rb +0 -5
  54. data/lib/rdoc/options.rb +373 -82
  55. data/lib/rdoc/parser.rb +59 -23
  56. data/lib/rdoc/parser/c.rb +224 -86
  57. data/lib/rdoc/parser/ruby.rb +219 -111
  58. data/lib/rdoc/parser/ruby_tools.rb +4 -1
  59. data/lib/rdoc/parser/simple.rb +9 -4
  60. data/lib/rdoc/rdoc.rb +68 -28
  61. data/lib/rdoc/require.rb +21 -0
  62. data/lib/rdoc/ri/driver.rb +20 -10
  63. data/lib/rdoc/ri/paths.rb +2 -2
  64. data/lib/rdoc/ri/store.rb +22 -5
  65. data/lib/rdoc/ruby_lex.rb +11 -12
  66. data/lib/rdoc/ruby_token.rb +2 -2
  67. data/lib/rdoc/single_class.rb +2 -1
  68. data/lib/rdoc/stats.rb +202 -162
  69. data/lib/rdoc/stats/normal.rb +51 -0
  70. data/lib/rdoc/stats/quiet.rb +59 -0
  71. data/lib/rdoc/stats/verbose.rb +45 -0
  72. data/lib/rdoc/text.rb +133 -4
  73. data/lib/rdoc/{tokenstream.rb → token_stream.rb} +0 -2
  74. data/lib/rdoc/top_level.rb +230 -39
  75. data/test/test_attribute_manager.rb +58 -7
  76. data/test/test_rdoc_alias.rb +13 -0
  77. data/test/test_rdoc_any_method.rb +43 -2
  78. data/test/test_rdoc_attr.rb +15 -8
  79. data/test/test_rdoc_class_module.rb +133 -0
  80. data/test/test_rdoc_code_object.rb +62 -5
  81. data/test/test_rdoc_context.rb +72 -26
  82. data/test/test_rdoc_encoding.rb +145 -0
  83. data/test/test_rdoc_generator_darkfish.rb +119 -0
  84. data/test/test_rdoc_generator_ri.rb +22 -2
  85. data/test/test_rdoc_include.rb +79 -0
  86. data/test/test_rdoc_markup_attribute_manager.rb +4 -4
  87. data/test/test_rdoc_markup_parser.rb +134 -95
  88. data/test/test_rdoc_markup_pre_process.rb +7 -2
  89. data/test/test_rdoc_markup_to_ansi.rb +43 -153
  90. data/test/test_rdoc_markup_to_bs.rb +42 -156
  91. data/test/test_rdoc_markup_to_html.rb +130 -58
  92. data/test/test_rdoc_markup_to_html_crossref.rb +10 -10
  93. data/test/test_rdoc_markup_to_rdoc.rb +40 -151
  94. data/test/test_rdoc_method_attr.rb +122 -0
  95. data/test/test_rdoc_normal_class.rb +1 -1
  96. data/test/test_rdoc_normal_module.rb +6 -1
  97. data/test/test_rdoc_options.rb +237 -12
  98. data/test/test_rdoc_parser.rb +3 -22
  99. data/test/test_rdoc_parser_c.rb +203 -2
  100. data/test/test_rdoc_parser_ruby.rb +403 -89
  101. data/test/test_rdoc_parser_simple.rb +25 -1
  102. data/test/test_rdoc_rdoc.rb +44 -32
  103. data/test/test_rdoc_ri_driver.rb +29 -24
  104. data/test/test_rdoc_ri_store.rb +46 -3
  105. data/test/test_rdoc_task.rb +1 -1
  106. data/test/test_rdoc_text.rb +102 -8
  107. data/test/test_rdoc_top_level.rb +13 -4
  108. data/test/xref_data.rb +8 -0
  109. data/test/xref_test_case.rb +6 -0
  110. metadata +29 -19
  111. metadata.gz.sig +0 -0
  112. data/lib/rdoc/parser/perl.rb +0 -165
  113. data/test/test_rdoc_parser_perl.rb +0 -73
@@ -3,6 +3,9 @@
3
3
 
4
4
  class RDoc::Markup::Heading < Struct.new :level, :text
5
5
 
6
+ ##
7
+ # Calls #accept_heading on +wisitor+
8
+
6
9
  def accept visitor
7
10
  visitor.accept_heading self
8
11
  end
@@ -1,3 +1,4 @@
1
+ require 'rdoc'
1
2
  class RDoc::Markup
2
3
 
3
4
  ##
@@ -14,6 +15,9 @@ class RDoc::Markup
14
15
  @@name_to_bitmap = { :_SPECIAL_ => SPECIAL }
15
16
  @@next_bitmap = 2
16
17
 
18
+ ##
19
+ # Returns a unique bit for +name+
20
+
17
21
  def self.bitmap_for(name)
18
22
  bitmap = @@name_to_bitmap[name]
19
23
  unless bitmap then
@@ -24,6 +28,9 @@ class RDoc::Markup
24
28
  bitmap
25
29
  end
26
30
 
31
+ ##
32
+ # Returns a string reperesentation of +bitmap+
33
+
27
34
  def self.as_string(bitmap)
28
35
  return "none" if bitmap.zero?
29
36
  res = []
@@ -33,6 +40,9 @@ class RDoc::Markup
33
40
  res.join(",")
34
41
  end
35
42
 
43
+ ##
44
+ # yields each attribute name in +bitmap+
45
+
36
46
  def self.each_name_of(bitmap)
37
47
  @@name_to_bitmap.each do |name, bit|
38
48
  next if bit == SPECIAL
@@ -75,7 +85,7 @@ class RDoc::Markup
75
85
  end
76
86
 
77
87
  ##
78
- # Acccesses flags for character +n+
88
+ # Accesses flags for character +n+
79
89
 
80
90
  def [](n)
81
91
  @attrs[n]
@@ -35,6 +35,9 @@ class RDoc::Markup::List
35
35
  @items == other.items
36
36
  end
37
37
 
38
+ ##
39
+ # Runs this list and all its #items through +visitor+
40
+
38
41
  def accept visitor
39
42
  visitor.accept_list_start self
40
43
 
@@ -35,6 +35,9 @@ class RDoc::Markup::ListItem
35
35
  @parts == other.parts
36
36
  end
37
37
 
38
+ ##
39
+ # Runs this list item and all its #parts through +visitor+
40
+
38
41
  def accept visitor
39
42
  visitor.accept_list_item_start self
40
43
 
@@ -3,6 +3,9 @@
3
3
 
4
4
  class RDoc::Markup::Paragraph < RDoc::Markup::Raw
5
5
 
6
+ ##
7
+ # Calls #accept_paragraph on +visitor+
8
+
6
9
  def accept visitor
7
10
  visitor.accept_paragraph self
8
11
  end
@@ -52,13 +52,13 @@ class RDoc::Markup::Parser
52
52
  attr_reader :tokens
53
53
 
54
54
  ##
55
- # Parsers +str+ into a Document
55
+ # Parses +str+ into a Document
56
56
 
57
57
  def self.parse str
58
58
  parser = new
59
- #parser.debug = true
60
59
  parser.tokenize str
61
- RDoc::Markup::Document.new(*parser.parse)
60
+ doc = RDoc::Markup::Document.new
61
+ parser.parse doc
62
62
  end
63
63
 
64
64
  ##
@@ -86,6 +86,7 @@ class RDoc::Markup::Parser
86
86
  # Builds a Heading of +level+
87
87
 
88
88
  def build_heading level
89
+ _, text, = get # TEXT
89
90
  heading = RDoc::Markup::Heading.new level, text
90
91
  skip :NEWLINE
91
92
 
@@ -105,38 +106,69 @@ class RDoc::Markup::Parser
105
106
 
106
107
  case type
107
108
  when :BULLET, :LABEL, :LALPHA, :NOTE, :NUMBER, :UALPHA then
108
- list_type = type
109
109
 
110
- if column < margin then
110
+ if column < margin || (list.type && list.type != type) then
111
111
  unget
112
112
  break
113
113
  end
114
114
 
115
- if list.type and list.type != list_type then
116
- unget
117
- break
118
- end
119
-
120
- list.type = list_type
115
+ list.type = type
116
+ peek_type, _, column, = peek_token
121
117
 
122
118
  case type
123
119
  when :NOTE, :LABEL then
124
- _, indent, = get # SPACE
125
- if :NEWLINE == peek_token.first then
126
- get
127
- peek_type, new_indent, peek_column, = peek_token
128
- indent = new_indent if
129
- peek_type == :INDENT and peek_column >= column
130
- unget
120
+ if peek_type == :NEWLINE then
121
+ # description not on the same line as LABEL/NOTE
122
+ # skip the trailing newline & any blank lines below
123
+ while peek_type == :NEWLINE
124
+ get
125
+ peek_type, _, column, = peek_token
126
+ end
127
+
128
+ # we may be:
129
+ # - at end of stream
130
+ # - at a column < margin:
131
+ # [text]
132
+ # blah blah blah
133
+ # - at the same column, but with a different type of list item
134
+ # [text]
135
+ # * blah blah
136
+ # - at the same column, with the same type of list item
137
+ # [one]
138
+ # [two]
139
+ # In all cases, we have an empty description.
140
+ # In the last case only, we continue.
141
+ if peek_type.nil? || column < margin then
142
+ empty = 1
143
+ elsif column == margin then
144
+ case peek_type
145
+ when type
146
+ empty = 2 # continue
147
+ when *LIST_TOKENS
148
+ empty = 1
149
+ else
150
+ empty = 0
151
+ end
152
+ else
153
+ empty = 0
154
+ end
155
+
156
+ if empty > 0 then
157
+ item = RDoc::Markup::ListItem.new(data)
158
+ item << RDoc::Markup::BlankLine.new
159
+ list << item
160
+ break if empty == 1
161
+ next
162
+ end
131
163
  end
132
164
  else
133
165
  data = nil
134
- _, indent, = get
135
166
  end
136
167
 
137
- list_item = build_list_item(margin + indent, data)
168
+ list_item = RDoc::Markup::ListItem.new data
169
+ parse list_item, column
170
+ list << list_item
138
171
 
139
- list << list_item if list_item
140
172
  else
141
173
  unget
142
174
  break
@@ -150,54 +182,6 @@ class RDoc::Markup::Parser
150
182
  list
151
183
  end
152
184
 
153
- ##
154
- # Builds a ListItem that is flush to +indent+ with type +item_type+
155
-
156
- def build_list_item indent, item_type = nil
157
- p :list_item_start => [indent, item_type] if @debug
158
-
159
- list_item = RDoc::Markup::ListItem.new item_type
160
-
161
- until @tokens.empty? do
162
- type, data, column = get
163
-
164
- if column < indent and
165
- not type == :NEWLINE and
166
- (type != :INDENT or data < indent) then
167
- unget
168
- break
169
- end
170
-
171
- case type
172
- when :INDENT then
173
- unget
174
- list_item.push(*parse(indent))
175
- when :TEXT then
176
- unget
177
- list_item << build_paragraph(indent)
178
- when :HEADER then
179
- list_item << build_heading(data)
180
- when :NEWLINE then
181
- list_item << RDoc::Markup::BlankLine.new
182
- when *LIST_TOKENS then
183
- unget
184
- list_item << build_list(column)
185
- else
186
- raise ParseError, "Unhandled token #{@current_token.inspect}"
187
- end
188
- end
189
-
190
- p :list_item_end => [indent, item_type] if @debug
191
-
192
- return nil if list_item.empty?
193
-
194
- list_item.parts.shift if
195
- RDoc::Markup::BlankLine === list_item.parts.first and
196
- list_item.length > 1
197
-
198
- list_item
199
- end
200
-
201
185
  ##
202
186
  # Builds a Paragraph that is flush to +margin+
203
187
 
@@ -209,18 +193,7 @@ class RDoc::Markup::Parser
209
193
  until @tokens.empty? do
210
194
  type, data, column, = get
211
195
 
212
- case type
213
- when :INDENT then
214
- next if data == margin and peek_token[0] == :TEXT
215
-
216
- unget
217
- break
218
- when :TEXT then
219
- if column != margin then
220
- unget
221
- break
222
- end
223
-
196
+ if type == :TEXT && column == margin then
224
197
  paragraph << data
225
198
  skip :NEWLINE
226
199
  else
@@ -235,67 +208,81 @@ class RDoc::Markup::Parser
235
208
  end
236
209
 
237
210
  ##
238
- # Builds a Verbatim that is flush to +margin+
211
+ # Builds a Verbatim that is indented from +margin+.
212
+ #
213
+ # The verbatim block is shifted left (the least indented lines start in
214
+ # column 0). Each part of the verbatim is one line of text, always
215
+ # terminated by a newline. Blank lines always consist of a single newline
216
+ # character, and there is never a single newline at the end of the verbatim.
239
217
 
240
218
  def build_verbatim margin
241
219
  p :verbatim_begin => margin if @debug
242
220
  verbatim = RDoc::Markup::Verbatim.new
243
221
 
222
+ min_indent = nil
223
+ generate_leading_spaces = true
224
+ line = ''
225
+
244
226
  until @tokens.empty? do
245
227
  type, data, column, = get
246
228
 
247
- case type
248
- when :INDENT then
249
- if margin >= data then
250
- unget
251
- break
252
- end
229
+ if type == :NEWLINE then
230
+ line << data
231
+ verbatim << line
232
+ line = ''
233
+ generate_leading_spaces = true
234
+ next
235
+ end
253
236
 
254
- indent = data - margin
237
+ if column <= margin
238
+ unget
239
+ break
240
+ end
255
241
 
256
- verbatim << ' ' * indent
257
- when :HEADER then
258
- verbatim << '=' * data
242
+ if generate_leading_spaces then
243
+ indent = column - margin
244
+ line << ' ' * indent
245
+ min_indent = indent if min_indent.nil? || indent < min_indent
246
+ generate_leading_spaces = false
247
+ end
259
248
 
249
+ case type
250
+ when :HEADER then
251
+ line << '=' * data
260
252
  _, _, peek_column, = peek_token
261
253
  peek_column ||= column + data
262
- verbatim << ' ' * (peek_column - column - data)
254
+ indent = peek_column - column - data
255
+ line << ' ' * indent
263
256
  when :RULE then
264
257
  width = 2 + data
265
- verbatim << '-' * width
266
-
258
+ line << '-' * width
267
259
  _, _, peek_column, = peek_token
268
- peek_column ||= column + data + 2
269
- verbatim << ' ' * (peek_column - column - width)
260
+ peek_column ||= column + width
261
+ indent = peek_column - column - width
262
+ line << ' ' * indent
270
263
  when :TEXT then
271
- verbatim << data
272
- when *LIST_TOKENS then
273
- if column <= margin then
274
- unget
275
- break
276
- end
277
-
264
+ line << data
265
+ else # *LIST_TOKENS
278
266
  list_marker = case type
279
- when :BULLET then data
280
- when :LABEL then "[#{data}]"
281
- when :LALPHA, :NUMBER, :UALPHA then "#{data}."
282
- when :NOTE then "#{data}::"
267
+ when :BULLET then data
268
+ when :LABEL then "[#{data}]"
269
+ when :NOTE then "#{data}::"
270
+ else # :LALPHA, :NUMBER, :UALPHA
271
+ "#{data}."
283
272
  end
284
-
285
- verbatim << list_marker
286
-
287
- _, data, = get
288
-
289
- verbatim << ' ' * (data - list_marker.length)
290
- when :NEWLINE then
291
- verbatim << data
292
- break unless [:INDENT, :NEWLINE].include? peek_token[0]
293
- else
294
- unget
295
- break
273
+ line << list_marker
274
+ peek_type, _, peek_column = peek_token
275
+ unless peek_type == :NEWLINE then
276
+ peek_column ||= column + list_marker.length
277
+ indent = peek_column - column - list_marker.length
278
+ line << ' ' * indent
279
+ end
296
280
  end
281
+
297
282
  end
298
283
 
284
+ verbatim << line << "\n" unless line.empty?
285
+ verbatim.parts.each { |p| p.slice!(0, min_indent) unless p == "\n" } if min_indent > 0
299
286
  verbatim.normalize
300
287
 
301
288
  p :verbatim_end => margin if @debug
@@ -313,65 +300,60 @@ class RDoc::Markup::Parser
313
300
  end
314
301
 
315
302
  ##
316
- # Parses the tokens into a Document
317
-
318
- def parse indent = 0
303
+ # Parses the tokens into an array of RDoc::Markup::XXX objects,
304
+ # and appends them to the passed +parent+ RDoc::Markup::YYY object.
305
+ #
306
+ # Exits at the end of the token stream, or when it encounters a token
307
+ # in a column less than +indent+ (unless it is a NEWLINE).
308
+ #
309
+ # Returns +parent+.
310
+
311
+ def parse parent, indent = 0
319
312
  p :parse_start => indent if @debug
320
313
 
321
- document = []
322
-
323
314
  until @tokens.empty? do
324
315
  type, data, column, = get
325
316
 
326
- if type != :INDENT and column < indent then
317
+ if type == :NEWLINE then
318
+ # trailing newlines are skipped below, so this is a blank line
319
+ parent << RDoc::Markup::BlankLine.new
320
+ skip :NEWLINE, false
321
+ next
322
+ end
323
+
324
+ # indentation change: break or verbattim
325
+ if column < indent then
327
326
  unget
328
327
  break
328
+ elsif column > indent then
329
+ unget
330
+ parent << build_verbatim(indent)
331
+ next
329
332
  end
330
333
 
334
+ # indentation is the same
331
335
  case type
332
336
  when :HEADER then
333
- document << build_heading(data)
334
- when :INDENT then
335
- if indent > data then
336
- unget
337
- break
338
- elsif indent == data then
339
- next
340
- end
341
-
342
- unget
343
- document << build_verbatim(indent)
344
- when :NEWLINE then
345
- document << RDoc::Markup::BlankLine.new
346
- skip :NEWLINE, false
337
+ parent << build_heading(data)
347
338
  when :RULE then
348
- document << RDoc::Markup::Rule.new(data)
339
+ parent << RDoc::Markup::Rule.new(data)
349
340
  skip :NEWLINE
350
341
  when :TEXT then
351
342
  unget
352
- document << build_paragraph(indent)
353
-
354
- # we're done with this paragraph (indent mismatch)
355
- break if peek_token[0] == :TEXT
343
+ parent << build_paragraph(indent)
356
344
  when *LIST_TOKENS then
357
345
  unget
358
-
359
- list = build_list(indent)
360
-
361
- document << list if list
362
-
363
- # we're done with this list (indent mismatch)
364
- break if LIST_TOKENS.include? peek_token.first and indent > 0
346
+ parent << build_list(indent)
365
347
  else
366
348
  type, data, column, line = @current_token
367
- raise ParseError,
368
- "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
349
+ raise ParseError, "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
369
350
  end
370
351
  end
371
352
 
372
353
  p :parse_end => indent if @debug
373
354
 
374
- document
355
+ parent
356
+
375
357
  end
376
358
 
377
359
  ##
@@ -384,63 +366,16 @@ class RDoc::Markup::Parser
384
366
  end
385
367
 
386
368
  ##
387
- # Skips a token of +token_type+, optionally raising an error.
369
+ # Skips the next token if its type is +token_type+.
370
+ #
371
+ # Optionally raises an error if the next token is not of the expected type.
388
372
 
389
373
  def skip token_type, error = true
390
- type, data, = get
391
-
374
+ type, = get
392
375
  return unless type # end of stream
393
-
394
376
  return @current_token if token_type == type
395
-
396
377
  unget
397
-
398
- raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if
399
- error
400
- end
401
-
402
- ##
403
- # Consumes tokens until NEWLINE and turns them back into text
404
-
405
- def text
406
- text = ''
407
-
408
- loop do
409
- type, data, = get
410
-
411
- text << case type
412
- when :BULLET then
413
- _, space, = get # SPACE
414
- "*#{' ' * (space - 1)}"
415
- when :LABEL then
416
- _, space, = get # SPACE
417
- "[#{data}]#{' ' * (space - data.length - 2)}"
418
- when :LALPHA, :NUMBER, :UALPHA then
419
- _, space, = get # SPACE
420
- "#{data}.#{' ' * (space - 2)}"
421
- when :NOTE then
422
- _, space = get # SPACE
423
- "#{data}::#{' ' * (space - data.length - 2)}"
424
- when :TEXT then
425
- data
426
- when :NEWLINE then
427
- unget
428
- break
429
- when nil then
430
- break
431
- else
432
- raise ParseError, "unhandled token #{@current_token.inspect}"
433
- end
434
- end
435
-
436
- text
437
- end
438
-
439
- ##
440
- # Calculates the column and line of the current token based on +offset+.
441
-
442
- def token_pos offset
443
- [offset - @line_pos, @line]
378
+ raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if error
444
379
  end
445
380
 
446
381
  ##
@@ -455,51 +390,62 @@ class RDoc::Markup::Parser
455
390
  until s.eos? do
456
391
  pos = s.pos
457
392
 
393
+ # leading spaces will be reflected by the column of the next token
394
+ # the only thing we loose are trailing spaces at the end of the file
395
+ next if s.scan(/ +/)
396
+
397
+ # note: after BULLET, LABEL, etc.,
398
+ # indent will be the column of the next non-newline token
399
+
458
400
  @tokens << case
401
+ # [CR]LF => :NEWLINE
459
402
  when s.scan(/\r?\n/) then
460
403
  token = [:NEWLINE, s.matched, *token_pos(pos)]
461
404
  @line_pos = s.pos
462
405
  @line += 1
463
406
  token
464
- when s.scan(/ +/) then
465
- [:INDENT, s.matched_size, *token_pos(pos)]
407
+ # === text => :HEADER then :TEXT
466
408
  when s.scan(/(=+)\s*/) then
467
409
  level = s[1].length
468
410
  level = 6 if level > 6
469
411
  @tokens << [:HEADER, level, *token_pos(pos)]
470
-
471
412
  pos = s.pos
472
413
  s.scan(/.*/)
473
- [:TEXT, s.matched, *token_pos(pos)]
474
- when s.scan(/^(-{3,}) *$/) then
414
+ [:TEXT, s.matched.sub(/\r$/, ''), *token_pos(pos)]
415
+ # --- (at least 3) and nothing else on the line => :RULE
416
+ when s.scan(/(-{3,}) *$/) then
475
417
  [:RULE, s[1].length - 2, *token_pos(pos)]
476
- when s.scan(/([*-])\s+/) then
477
- @tokens << [:BULLET, s[1], *token_pos(pos)]
478
- [:SPACE, s.matched_size, *token_pos(pos)]
479
- when s.scan(/([a-z]|\d+)\.[ \t]+\S/i) then
418
+ # * or - followed by white space and text => :BULLET
419
+ when s.scan(/([*-]) +(\S)/) then
420
+ s.pos -= s[2].bytesize # unget \S
421
+ [:BULLET, s[1], *token_pos(pos)]
422
+ # A. text, a. text, 12. text => :UALPHA, :LALPHA, :NUMBER
423
+ when s.scan(/([a-z]|\d+)\. +(\S)/i) then
424
+ # FIXME if tab(s), the column will be wrong
425
+ # either support tabs everywhere by first expanding them to
426
+ # spaces, or assume that they will have been replaced
427
+ # before (and provide a check for that at least in debug
428
+ # mode)
480
429
  list_label = s[1]
481
- width = s.matched_size - 1
482
-
483
- s.pos -= 1 # unget \S
484
-
485
- list_type = case list_label
486
- when /[a-z]/ then :LALPHA
487
- when /[A-Z]/ then :UALPHA
488
- when /\d/ then :NUMBER
489
- else
490
- raise ParseError, "BUG token #{list_label}"
491
- end
492
-
493
- @tokens << [list_type, list_label, *token_pos(pos)]
494
- [:SPACE, width, *token_pos(pos)]
430
+ s.pos -= s[2].bytesize # unget \S
431
+ list_type =
432
+ case list_label
433
+ when /[a-z]/ then :LALPHA
434
+ when /[A-Z]/ then :UALPHA
435
+ when /\d/ then :NUMBER
436
+ else
437
+ raise ParseError, "BUG token #{list_label}"
438
+ end
439
+ [list_type, list_label, *token_pos(pos)]
440
+ # [text] followed by spaces or end of line => :LABEL
495
441
  when s.scan(/\[(.*?)\]( +|$)/) then
496
- @tokens << [:LABEL, s[1], *token_pos(pos)]
497
- [:SPACE, s.matched_size, *token_pos(pos)]
442
+ [:LABEL, s[1], *token_pos(pos)]
443
+ # text:: followed by spaces or end of line => :NOTE
498
444
  when s.scan(/(.*?)::( +|$)/) then
499
- @tokens << [:NOTE, s[1], *token_pos(pos)]
500
- [:SPACE, s.matched_size, *token_pos(pos)]
445
+ [:NOTE, s[1], *token_pos(pos)]
446
+ # anything else: :TEXT
501
447
  else s.scan(/.*/)
502
- [:TEXT, s.matched, *token_pos(pos)]
448
+ [:TEXT, s.matched.sub(/\r$/, ''), *token_pos(pos)]
503
449
  end
504
450
  end
505
451
 
@@ -507,9 +453,17 @@ class RDoc::Markup::Parser
507
453
  end
508
454
 
509
455
  ##
510
- # Returns the current token or +token+ to the token stream
456
+ # Calculates the column and line of the current token based on +offset+.
457
+
458
+ def token_pos offset
459
+ [offset - @line_pos, @line]
460
+ end
461
+
462
+ ##
463
+ # Returns the current token to the token stream
511
464
 
512
- def unget token = @current_token
465
+ def unget
466
+ token = @current_token
513
467
  p :unget => token if @debug
514
468
  raise Error, 'too many #ungets' if token == @tokens.first
515
469
  @tokens.unshift token if token