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::Verbatim < RDoc::Markup::Raw
5
5
 
6
+ ##
7
+ # Calls #accept_verbatim on +visitor+
8
+
6
9
  def accept visitor
7
10
  visitor.accept_verbatim self
8
11
  end
@@ -17,16 +20,16 @@ class RDoc::Markup::Verbatim < RDoc::Markup::Raw
17
20
 
18
21
  @parts.each do |part|
19
22
  case part
20
- when /\n/ then
23
+ when /^\s*\n/ then
21
24
  newlines += 1
22
- parts << part if newlines <= 2
25
+ parts << part if newlines == 1
23
26
  else
24
27
  newlines = 0
25
28
  parts << part
26
29
  end
27
30
  end
28
31
 
29
- parts.slice!(-1) if parts[-2..-1] == ["\n", "\n"]
32
+ parts.pop if parts.last =~ /\A\r?\n\z/
30
33
 
31
34
  @parts = parts
32
35
  end
@@ -0,0 +1,353 @@
1
+ require 'rdoc/code_object'
2
+
3
+ ##
4
+ # Abstract class representing either a method or an attribute.
5
+
6
+ class RDoc::MethodAttr < RDoc::CodeObject
7
+
8
+ include Comparable
9
+
10
+ ##
11
+ # Name of this method/attribute.
12
+
13
+ attr_accessor :name
14
+
15
+ ##
16
+ # public, protected, private
17
+
18
+ attr_accessor :visibility
19
+
20
+ ##
21
+ # Is this a singleton method/attribute?
22
+
23
+ attr_accessor :singleton
24
+
25
+ ##
26
+ # Source file token stream
27
+
28
+ attr_reader :text
29
+
30
+ ##
31
+ # Array of other names for this method/attribute
32
+
33
+ attr_reader :aliases
34
+
35
+ ##
36
+ # The method/attribute we're aliasing
37
+
38
+ attr_accessor :is_alias_for
39
+
40
+ #--
41
+ # The attributes below are for AnyMethod only.
42
+ # They are left here for the time being to
43
+ # allow ri to operate.
44
+ # TODO modify ri to avoid calling these on attributes.
45
+ #++
46
+
47
+ ##
48
+ # Parameters yielded by the called block
49
+
50
+ attr_reader :block_params
51
+
52
+ ##
53
+ # Parameters for this method
54
+
55
+ attr_accessor :params
56
+
57
+ ##
58
+ # Different ways to call this method
59
+
60
+ attr_accessor :call_seq
61
+
62
+ ##
63
+ # The call_seq or the param_seq with method name, if there is no call_seq.
64
+
65
+ attr_reader :arglists
66
+
67
+ ##
68
+ # Pretty parameter list for this method
69
+
70
+ attr_reader :param_seq
71
+
72
+
73
+ ##
74
+ # Creates a new MethodAttr from token stream +text+ and method or attribute
75
+ # name +name+.
76
+ #
77
+ # Usually this is called by super from a subclass.
78
+
79
+ def initialize text, name
80
+ super()
81
+
82
+ @text = text
83
+ @name = name
84
+
85
+ @aliases = []
86
+ @is_alias_for = nil
87
+ @parent_name = nil
88
+ @singleton = nil
89
+ @visibility = :public
90
+ @see = false
91
+
92
+ @arglists = nil
93
+ @block_params = nil
94
+ @call_seq = nil
95
+ @param_seq = nil
96
+ @params = nil
97
+ end
98
+
99
+ ##
100
+ # Order by #singleton then #name
101
+
102
+ def <=>(other)
103
+ [@singleton ? 0 : 1, name] <=> [other.singleton ? 0 : 1, other.name]
104
+ end
105
+
106
+ ##
107
+ # A method/attribute is documented if any of the following is true:
108
+ # - it was marked with :nodoc:;
109
+ # - it has a comment;
110
+ # - it is an alias for a documented method;
111
+ # - it has a +#see+ method that is documented.
112
+
113
+ def documented?
114
+ super or
115
+ (is_alias_for and is_alias_for.documented?) or
116
+ (see and see.documented?)
117
+ end
118
+
119
+ ##
120
+ # A method/attribute to look at,
121
+ # in particular if this method/attribute has no documentation.
122
+ #
123
+ # It can be a method/attribute of the superclass or of an included module,
124
+ # including the Kernel module, which is always appended to the included
125
+ # modules.
126
+ #
127
+ # Returns +nil+ if there is no such method/attribute.
128
+ # The +#is_alias_for+ method/attribute, if any, is not included.
129
+ #
130
+ # Templates may generate a "see also ..." if this method/attribute
131
+ # has documentation, and "see ..." if it does not.
132
+
133
+ def see
134
+ @see = find_see if @see == false
135
+ @see
136
+ end
137
+
138
+ def find_see # :nodoc:
139
+ return nil if singleton || is_alias_for
140
+
141
+ # look for the method
142
+ other = find_method_or_attribute name
143
+ return other if other
144
+
145
+ # if it is a setter, look for a getter
146
+ return nil unless name =~ /[a-z_]=$/i # avoid == or ===
147
+ return find_method_or_attribute name[0..-2]
148
+ end
149
+
150
+ def find_method_or_attribute name # :nodoc:
151
+ return nil unless parent.respond_to? :ancestors
152
+
153
+ searched = parent.ancestors
154
+ kernel = RDoc::TopLevel.all_modules_hash['Kernel']
155
+
156
+ searched << kernel if kernel &&
157
+ parent != kernel && !searched.include?(kernel)
158
+
159
+ searched.each do |ancestor|
160
+ next if parent == ancestor
161
+ next if String === ancestor
162
+
163
+ other = ancestor.find_method_named('#' << name) ||
164
+ ancestor.find_attribute_named(name)
165
+
166
+ return other if other
167
+ end
168
+
169
+ nil
170
+ end
171
+
172
+ ##
173
+ # Abstract method. Contexts in their building phase call this
174
+ # to register a new alias for this known method/attribute.
175
+ #
176
+ # - creates a new AnyMethod/Attribute +newa+ named an_alias.new_name;
177
+ # - adds +self+ as +newa.is_alias_for+;
178
+ # - adds +newa+ to #aliases
179
+ # - adds +newa+ to the methods/attributes of +context+.
180
+
181
+ def add_alias(an_alias, context)
182
+ raise NotImplementedError
183
+ end
184
+
185
+ ##
186
+ # HTML fragment reference for this method
187
+
188
+ def aref
189
+ type = singleton ? 'c' : 'i'
190
+ # % characters are not allowed in html names => dash instead
191
+ "#{aref_prefix}-#{type}-#{html_name}"
192
+ end
193
+
194
+ ##
195
+ # Prefix for +aref+, defined by subclasses.
196
+
197
+ def aref_prefix
198
+ raise NotImplementedError
199
+ end
200
+
201
+ ##
202
+ # Attempts to sanitize the content passed by the ruby parser:
203
+ # remove outer parentheses, etc.
204
+
205
+ def block_params=(value)
206
+ # 'yield.to_s' or 'assert yield, msg'
207
+ return @block_params = '' if value =~ /^[\.,]/
208
+
209
+ # remove trailing 'if/unless ...'
210
+ return @block_params = '' if value =~ /^(if|unless)\s/
211
+
212
+ value = $1.strip if value =~ /^(.+)\s(if|unless)\s/
213
+
214
+ # outer parentheses
215
+ value = $1 if value =~ /^\s*\((.*)\)\s*$/
216
+ value = value.strip
217
+
218
+ # proc/lambda
219
+ return @block_params = $1 if value =~ /^(proc|lambda)(\s*\{|\sdo)/
220
+
221
+ # surrounding +...+ or [...]
222
+ value = $1.strip if value =~ /^\+(.*)\+$/
223
+ value = $1.strip if value =~ /^\[(.*)\]$/
224
+
225
+ return @block_params = '' if value.empty?
226
+
227
+ # global variable
228
+ return @block_params = 'str' if value =~ /^\$[&0-9]$/
229
+
230
+ # wipe out array/hash indices
231
+ value.gsub!(/(\w)\[[^\[]+\]/, '\1')
232
+
233
+ # remove @ from class/instance variables
234
+ value.gsub!(/@@?([a-z0-9_]+)/, '\1')
235
+
236
+ # method calls => method name
237
+ value.gsub!(/([A-Z:a-z0-9_]+)\.([a-z0-9_]+)(\s*\(\s*[a-z0-9_.,\s]*\s*\)\s*)?/) do
238
+ case $2
239
+ when 'to_s' then $1
240
+ when 'const_get' then 'const'
241
+ when 'new' then
242
+ $1.split('::').last. # ClassName => class_name
243
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
244
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
245
+ downcase
246
+ else
247
+ $2
248
+ end
249
+ end
250
+
251
+ # class prefixes
252
+ value.gsub!(/[A-Za-z0-9_:]+::/, '')
253
+
254
+ # simple expressions
255
+ value = $1 if value =~ /^([a-z0-9_]+)\s*[-*+\/]/
256
+
257
+ @block_params = value.strip
258
+ end
259
+
260
+ ##
261
+ # HTML id-friendly method/attribute name
262
+
263
+ def html_name
264
+ CGI.escape(@name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '')
265
+ end
266
+
267
+ ##
268
+ # Full method/attribute name including namespace
269
+
270
+ def full_name
271
+ @full_name || "#{parent_name}#{pretty_name}"
272
+ end
273
+
274
+ ##
275
+ # '::' for a class method/attribute, '#' for an instance method.
276
+
277
+ def name_prefix
278
+ singleton ? '::' : '#'
279
+ end
280
+
281
+ ##
282
+ # Method/attribute name with class/instance indicator
283
+
284
+ def pretty_name
285
+ "#{name_prefix}#{@name}"
286
+ end
287
+
288
+ ##
289
+ # Type of method/attribute (class or instance)
290
+
291
+ def type
292
+ singleton ? 'class' : 'instance'
293
+ end
294
+
295
+ ##
296
+ # Path to this method
297
+
298
+ def path
299
+ "#{@parent.path}##{aref}"
300
+ end
301
+
302
+ ##
303
+ # Name of our parent with special handling for un-marshaled methods
304
+
305
+ def parent_name
306
+ @parent_name || super
307
+ end
308
+
309
+ def pretty_print q # :nodoc:
310
+ alias_for = @is_alias_for ? "alias for #{@is_alias_for.name}" : nil
311
+
312
+ q.group 2, "[#{self.class.name} #{full_name} #{visibility}", "]" do
313
+ if alias_for then
314
+ q.breakable
315
+ q.text alias_for
316
+ end
317
+
318
+ if text then
319
+ q.breakable
320
+ q.text "text:"
321
+ q.breakable
322
+ q.pp @text
323
+ end
324
+
325
+ unless comment.empty? then
326
+ q.breakable
327
+ q.text "comment:"
328
+ q.breakable
329
+ q.pp @comment
330
+ end
331
+ end
332
+ end
333
+
334
+ def inspect # :nodoc:
335
+ alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
336
+ "#<%s:0x%x %s (%s)%s>" % [
337
+ self.class, object_id,
338
+ full_name,
339
+ visibility,
340
+ alias_for,
341
+ ]
342
+ end
343
+
344
+ def to_s # :nodoc:
345
+ if @is_alias_for
346
+ "#{self.class.name}: #{full_name} -> #{is_alias_for}"
347
+ else
348
+ "#{self.class.name}: #{full_name}"
349
+ end
350
+ end
351
+
352
+ end
353
+
@@ -6,10 +6,10 @@ require 'rdoc/class_module'
6
6
  class RDoc::NormalClass < RDoc::ClassModule
7
7
 
8
8
  ##
9
- # Ancestor ClassModules
9
+ # Appends the superclass, if any, to the included modules.
10
10
 
11
11
  def ancestors
12
- includes + [superclass]
12
+ superclass ? super + [superclass] : super
13
13
  end
14
14
 
15
15
  def inspect # :nodoc:
@@ -20,6 +20,15 @@ class RDoc::NormalClass < RDoc::ClassModule
20
20
  ]
21
21
  end
22
22
 
23
+ def to_s # :nodoc:
24
+ display = "#{self.class.name} #{self.full_name}"
25
+ if superclass
26
+ display << ' < ' << (superclass.is_a?(String) ? superclass : superclass.full_name)
27
+ end
28
+ display << ' -> ' << is_alias_for.to_s if is_alias_for
29
+ display
30
+ end
31
+
23
32
  def pretty_print q # :nodoc:
24
33
  superclass = @superclass ? " < #{@superclass}" : nil
25
34
 
@@ -5,11 +5,6 @@ require 'rdoc/class_module'
5
5
 
6
6
  class RDoc::NormalModule < RDoc::ClassModule
7
7
 
8
- ##
9
- # Included NormalModules
10
-
11
- alias ancestors includes
12
-
13
8
  def inspect # :nodoc:
14
9
  "#<%s:0x%x module %s includes: %p attributes: %p methods: %p aliases: %p>" % [
15
10
  self.class, object_id,
@@ -8,9 +8,41 @@ require 'rdoc/ri/paths'
8
8
  class RDoc::Options
9
9
 
10
10
  ##
11
- # Character-set
11
+ # The deprecated options.
12
+
13
+ DEPRECATED = {
14
+ '--accessor' => 'support discontinued',
15
+ '--diagram' => 'support discontinued',
16
+ '--help-output' => 'support discontinued',
17
+ '--image-format' => 'was an option for --diagram',
18
+ '--inline-source' => 'source code is now always inlined',
19
+ '--merge' => 'ri now always merges class information',
20
+ '--one-file' => 'support discontinued',
21
+ '--op-name' => 'support discontinued',
22
+ '--opname' => 'support discontinued',
23
+ '--promiscuous' => 'files always only document their content',
24
+ '--ri-system' => 'Ruby installers use other techniques',
25
+ }
12
26
 
13
- attr_reader :charset
27
+ ##
28
+ # Template option validator for OptionParser
29
+
30
+ Template = nil
31
+
32
+ ##
33
+ # Character-set for HTML output. #encoding is preferred over #charset
34
+
35
+ attr_accessor :charset
36
+
37
+ ##
38
+ # If true, RDoc will not write any files.
39
+
40
+ attr_accessor :dry_run
41
+
42
+ ##
43
+ # Encoding of output where. This is set via --encoding.
44
+
45
+ attr_accessor :encoding if Object.const_defined? :Encoding
14
46
 
15
47
  ##
16
48
  # Files matching this pattern will be excluded
@@ -22,10 +54,21 @@ class RDoc::Options
22
54
 
23
55
  attr_accessor :files
24
56
 
57
+ ##
58
+ # Create the output even if the output directory does not look
59
+ # like an rdoc output directory
60
+
61
+ attr_accessor :force_output
62
+
25
63
  ##
26
64
  # Scan newer sources than the flag file if true.
27
65
 
28
- attr_reader :force_update
66
+ attr_accessor :force_update
67
+
68
+ ##
69
+ # Formatter to mark up text with
70
+
71
+ attr_accessor :formatter
29
72
 
30
73
  ##
31
74
  # Description of the output generator (set with the <tt>-fmt</tt> option)
@@ -33,9 +76,21 @@ class RDoc::Options
33
76
  attr_accessor :generator
34
77
 
35
78
  ##
36
- # Formatter to mark up text with
79
+ # Loaded generator options. Used to prevent --help from loading the same
80
+ # options multiple times.
37
81
 
38
- attr_accessor :formatter
82
+ attr_accessor :generator_options
83
+
84
+ ##
85
+ # Old rdoc behavior: hyperlink all words that match a method name,
86
+ # even if not preceded by '#' or '::'
87
+
88
+ attr_accessor :hyperlink_all
89
+
90
+ ##
91
+ # Include line numbers in the source code
92
+
93
+ attr_accessor :line_numbers
39
94
 
40
95
  ##
41
96
  # Name of the file, class or module to display in the initial index page (if
@@ -43,11 +98,21 @@ class RDoc::Options
43
98
 
44
99
  attr_accessor :main_page
45
100
 
101
+ ##
102
+ # If true, only report on undocumented files
103
+
104
+ attr_accessor :coverage_report
105
+
46
106
  ##
47
107
  # The name of the output directory
48
108
 
49
109
  attr_accessor :op_dir
50
110
 
111
+ ##
112
+ # The OptionParser for this instance
113
+
114
+ attr_accessor :option_parser
115
+
51
116
  ##
52
117
  # Is RDoc in pipe mode?
53
118
 
@@ -56,27 +121,32 @@ class RDoc::Options
56
121
  ##
57
122
  # Array of directories to search for files to satisfy an :include:
58
123
 
59
- attr_reader :rdoc_include
124
+ attr_accessor :rdoc_include
60
125
 
61
126
  ##
62
127
  # Include the '#' at the front of hyperlinked instance method names
63
128
 
64
- attr_reader :show_hash
129
+ attr_accessor :show_hash
65
130
 
66
131
  ##
67
132
  # The number of columns in a tab
68
133
 
69
- attr_reader :tab_width
134
+ attr_accessor :tab_width
70
135
 
71
136
  ##
72
137
  # Template to be used when generating output
73
138
 
74
- attr_reader :template
139
+ attr_accessor :template
140
+
141
+ ##
142
+ # Directory the template lives in
143
+
144
+ attr_accessor :template_dir
75
145
 
76
146
  ##
77
147
  # Documentation title
78
148
 
79
- attr_reader :title
149
+ attr_accessor :title
80
150
 
81
151
  ##
82
152
  # Verbosity, zero means quiet
@@ -86,28 +156,88 @@ class RDoc::Options
86
156
  ##
87
157
  # URL of web cvs frontend
88
158
 
89
- attr_reader :webcvs
159
+ attr_accessor :webcvs
160
+
161
+ ##
162
+ # Minimum visibility of a documented method. One of +:public+,
163
+ # +:protected+, +:private+. May be overridden on a per-method
164
+ # basis with the :doc: directive.
165
+
166
+ attr_accessor :visibility
90
167
 
91
168
  def initialize # :nodoc:
92
169
  require 'rdoc/rdoc'
93
- @op_dir = nil
94
- @main_page = nil
170
+ @dry_run = false
95
171
  @exclude = []
96
- @generators = RDoc::RDoc::GENERATORS
97
- @generator = RDoc::Generator::Darkfish
172
+ @force_output = false
173
+ @force_update = true
174
+ @generator = nil
98
175
  @generator_name = nil
176
+ @generator_options = []
177
+ @generators = RDoc::RDoc::GENERATORS
178
+ @hyperlink_all = false
179
+ @line_numbers = false
180
+ @main_page = nil
181
+ @coverage_report = false
182
+ @op_dir = nil
183
+ @pipe = false
99
184
  @rdoc_include = []
100
- @title = nil
101
- @template = nil
102
185
  @show_hash = false
186
+ @stylesheet_url = nil
103
187
  @tab_width = 8
104
- @force_update = true
188
+ @template = nil
189
+ @template_dir = nil
190
+ @title = nil
105
191
  @verbosity = 1
106
- @pipe = false
107
-
192
+ @visibility = :protected
108
193
  @webcvs = nil
109
194
 
110
- @charset = 'utf-8'
195
+ if Object.const_defined? :Encoding then
196
+ @encoding = Encoding.default_external
197
+ @charset = @encoding.to_s
198
+ else
199
+ @charset = 'UTF-8'
200
+ end
201
+ end
202
+
203
+ ##
204
+ # Check that the files on the command line exist
205
+
206
+ def check_files
207
+ @files.delete_if do |file|
208
+ if File.exist? file then
209
+ if File.readable? file then
210
+ false
211
+ else
212
+ warn "file '#{file}' not readable"
213
+
214
+ true
215
+ end
216
+ else
217
+ warn "file '#{file}' not found"
218
+
219
+ true
220
+ end
221
+ end
222
+ end
223
+
224
+ ##
225
+ # Ensure only one generator is loaded
226
+
227
+ def check_generator
228
+ if @generator then
229
+ raise OptionParser::InvalidOption,
230
+ "generator already set to #{@generator_name}"
231
+ end
232
+ end
233
+
234
+ ##
235
+ # Set the title, but only if not already set. Used to set the title
236
+ # from a source file, so that a title set from the command line
237
+ # will have the priority.
238
+
239
+ def default_title=(string)
240
+ @title ||= string
111
241
  end
112
242
 
113
243
  ##
@@ -116,7 +246,10 @@ class RDoc::Options
116
246
  def parse(argv)
117
247
  ignore_invalid = true
118
248
 
249
+ argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT']
250
+
119
251
  opts = OptionParser.new do |opt|
252
+ @option_parser = opt
120
253
  opt.program_name = File.basename $0
121
254
  opt.version = RDoc::VERSION
122
255
  opt.release = nil
@@ -133,6 +266,14 @@ Usage: #{opt.program_name} [options] [names...]
133
266
  How RDoc generates output depends on the output formatter being used, and on
134
267
  the options you give.
135
268
 
269
+ Options can be specified via the RDOCOPT environment variable, which
270
+ functions similar to the RUBYOPT environment variable for ruby.
271
+
272
+ $ export RDOCOPT="--show-hash"
273
+
274
+ will make rdoc show hashes in method links by default. Command-line options
275
+ always will override those in RDOCOPT.
276
+
136
277
  - Darkfish creates frameless HTML output by Michael Granger.
137
278
  - ri creates ri data files
138
279
 
@@ -150,8 +291,46 @@ Usage: #{opt.program_name} [options] [names...]
150
291
  opt.banner << " - #{parser}: #{regexp.join ', '}\n"
151
292
  end
152
293
 
294
+ opt.banner << "\n The following options are deprecated:\n\n"
295
+
296
+ name_length = DEPRECATED.keys.sort_by { |k| k.length }.last.length
297
+
298
+ DEPRECATED.sort_by { |k,| k }.each do |name, reason|
299
+ opt.banner << " %*1$2$s %3$s\n" % [-name_length, name, reason]
300
+ end
301
+
302
+ opt.accept Template do |template|
303
+ template_dir = template_dir_for template
304
+
305
+ unless template_dir then
306
+ warn "could not find template #{template}"
307
+ nil
308
+ else
309
+ [template, template_dir]
310
+ end
311
+ end
312
+
153
313
  opt.separator nil
154
- opt.separator "Parsing Options:"
314
+ opt.separator "Parsing options:"
315
+ opt.separator nil
316
+
317
+ if Object.const_defined? :Encoding then
318
+ opt.on("--encoding=ENCODING", "-e", Encoding.list.map { |e| e.name },
319
+ "Specifies the output encoding. All files",
320
+ "read will be converted to this encoding.",
321
+ "Preferred over --charset") do |value|
322
+ @encoding = Encoding.find value
323
+ @charset = @encoding.to_s # may not be valid value
324
+ end
325
+
326
+ opt.separator nil
327
+ end
328
+
329
+ opt.on("--all", "-a",
330
+ "Synonym for --visibility=private.") do |value|
331
+ @visibility = :private
332
+ end
333
+
155
334
  opt.separator nil
156
335
 
157
336
  opt.on("--exclude=PATTERN", "-x", Regexp,
@@ -193,20 +372,41 @@ Usage: #{opt.program_name} [options] [names...]
193
372
  end
194
373
 
195
374
  opt.separator nil
196
- opt.separator "Generator Options:"
375
+
376
+ opt.on("--tab-width=WIDTH", "-w", OptionParser::DecimalInteger,
377
+ "Set the width of tab characters.") do |value|
378
+ @tab_width = value
379
+ end
380
+
197
381
  opt.separator nil
198
382
 
199
- opt.on("--charset=CHARSET", "-c",
200
- "Specifies the output HTML character-set.") do |value|
201
- @charset = value
383
+ opt.on("--visibility=VISIBILITY", "-V", RDoc::VISIBILITIES,
384
+ "Minimum visibility to document a method.",
385
+ "One of 'public', 'protected' (the default)",
386
+ "or 'private'. Can be abbreviated.") do |value|
387
+ @visibility = value
388
+ end
389
+
390
+ opt.separator nil
391
+ opt.separator "Common generator options:"
392
+ opt.separator nil
393
+
394
+ opt.on("--force-output", "-O",
395
+ "Forces rdoc to write the output files,",
396
+ "even if the output directory exists",
397
+ "and does not seem to have been created",
398
+ "by rdoc.") do |value|
399
+ @force_output = value
202
400
  end
203
401
 
204
402
  opt.separator nil
205
403
 
206
404
  generator_text = @generators.keys.map { |name| " #{name}" }.sort
207
405
 
208
- opt.on("--fmt=FORMAT", "--format=FORMAT", "-f", @generators.keys,
406
+ opt.on("-f", "--fmt=FORMAT", "--format=FORMAT", @generators.keys,
209
407
  "Set the output formatter. One of:", *generator_text) do |value|
408
+ check_generator
409
+
210
410
  @generator_name = value.downcase
211
411
  setup_generator
212
412
  end
@@ -222,9 +422,11 @@ Usage: #{opt.program_name} [options] [names...]
222
422
 
223
423
  opt.separator nil
224
424
 
225
- opt.on("--main=NAME", "-m",
226
- "NAME will be the initial page displayed.") do |value|
227
- @main_page = value
425
+ opt.on("--[no-]coverage-report", "--[no-]dcov", "-C",
426
+ "Prints a report on undocumented items.",
427
+ "Does not generate files.") do |value|
428
+ @coverage_report = value
429
+ @force_update = true if value
228
430
  end
229
431
 
230
432
  opt.separator nil
@@ -236,6 +438,51 @@ Usage: #{opt.program_name} [options] [names...]
236
438
 
237
439
  opt.separator nil
238
440
 
441
+ opt.on("-d",
442
+ "Deprecated --diagram option.",
443
+ "Prevents firing debug mode",
444
+ "with legacy invocation.") do |value|
445
+ end
446
+
447
+ opt.separator nil
448
+ opt.separator 'HTML generator options:'
449
+ opt.separator nil
450
+
451
+ opt.on("--charset=CHARSET", "-c",
452
+ "Specifies the output HTML character-set.",
453
+ "Use --encoding instead of --charset if",
454
+ "available.") do |value|
455
+ @charset = value
456
+ end
457
+
458
+ opt.separator nil
459
+
460
+ opt.on("--hyperlink-all", "-A",
461
+ "Generate hyperlinks for all words that",
462
+ "correspond to known methods, even if they",
463
+ "do not start with '#' or '::' (legacy",
464
+ "behavior).") do |value|
465
+ @hyperlink_all = value
466
+ end
467
+
468
+ opt.separator nil
469
+
470
+ opt.on("--main=NAME", "-m",
471
+ "NAME will be the initial page displayed.") do |value|
472
+ @main_page = value
473
+ end
474
+
475
+ opt.separator nil
476
+
477
+ opt.on("--[no-]line-numbers", "-N",
478
+ "Include line numbers in the source code.",
479
+ "By default, only the number of the first",
480
+ "line is displayed, in a leading comment.") do |value|
481
+ @line_numbers = value
482
+ end
483
+
484
+ opt.separator nil
485
+
239
486
  opt.on("--show-hash", "-H",
240
487
  "A name of the form #name in a comment is a",
241
488
  "possible hyperlink to an instance method",
@@ -246,17 +493,12 @@ Usage: #{opt.program_name} [options] [names...]
246
493
 
247
494
  opt.separator nil
248
495
 
249
- opt.on("--tab-width=WIDTH", "-w", OptionParser::DecimalInteger,
250
- "Set the width of tab characters.") do |value|
251
- @tab_width = value
252
- end
253
-
254
- opt.separator nil
255
-
256
- opt.on("--template=NAME", "-T",
496
+ opt.on("--template=NAME", "-T", Template,
257
497
  "Set the template used when generating",
258
- "output.") do |value|
259
- @template = value
498
+ "output. The default depends on the",
499
+ "formatter used.") do |(template, template_dir)|
500
+ @template = template
501
+ @template_dir = template_dir
260
502
  end
261
503
 
262
504
  opt.separator nil
@@ -278,11 +520,7 @@ Usage: #{opt.program_name} [options] [names...]
278
520
  end
279
521
 
280
522
  opt.separator nil
281
-
282
- opt.on("-d", "--diagram", "Prevents -d from tripping --debug")
283
-
284
- opt.separator nil
285
- opt.separator "ri Generator Options:"
523
+ opt.separator "ri generator options:"
286
524
  opt.separator nil
287
525
 
288
526
  opt.on("--ri", "-r",
@@ -291,6 +529,8 @@ Usage: #{opt.program_name} [options] [names...]
291
529
  "your home directory unless overridden by a",
292
530
  "subsequent --op parameter, so no special",
293
531
  "privileges are needed.") do |value|
532
+ check_generator
533
+
294
534
  @generator_name = "ri"
295
535
  @op_dir ||= RDoc::RI::Paths::HOMEDIR
296
536
  setup_generator
@@ -303,22 +543,30 @@ Usage: #{opt.program_name} [options] [names...]
303
543
  "are stored in a site-wide directory,",
304
544
  "making them accessible to others, so",
305
545
  "special privileges are needed.") do |value|
546
+ check_generator
547
+
306
548
  @generator_name = "ri"
307
549
  @op_dir = RDoc::RI::Paths::SITEDIR
308
550
  setup_generator
309
551
  end
310
552
 
311
553
  opt.separator nil
312
- opt.separator "Generic Options:"
554
+ opt.separator "Generic options:"
313
555
  opt.separator nil
314
556
 
557
+ opt.on("--[no-]dry-run",
558
+ "Don't write any files") do |value|
559
+ @dry_run = value
560
+ end
561
+
315
562
  opt.on("-D", "--[no-]debug",
316
563
  "Displays lots on internal stuff.") do |value|
317
564
  $DEBUG_RDOC = value
318
565
  end
319
566
 
320
567
  opt.on("--[no-]ignore-invalid",
321
- "Ignore invalid options and continue.") do |value|
568
+ "Ignore invalid options and continue",
569
+ "(default true).") do |value|
322
570
  ignore_invalid = value
323
571
  end
324
572
 
@@ -328,38 +576,70 @@ Usage: #{opt.program_name} [options] [names...]
328
576
  end
329
577
 
330
578
  opt.on("--verbose", "-v",
331
- "Display extra progress as we parse.") do |value|
579
+ "Display extra progress as RDoc parses") do |value|
332
580
  @verbosity = 2
333
581
  end
334
582
 
583
+ opt.on("--help",
584
+ "Display this help") do
585
+ RDoc::RDoc::GENERATORS.each_key do |generator|
586
+ setup_generator generator
587
+ end
588
+
589
+ puts opt.help
590
+ exit
591
+ end
592
+
335
593
  opt.separator nil
336
594
  end
337
595
 
338
- argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT']
339
- ignored = []
596
+ setup_generator 'darkfish' if
597
+ argv.grep(/\A(-f|--fmt|--format|-r|-R|--ri|--ri-site)\b/).empty?
598
+
599
+ deprecated = []
600
+ invalid = []
340
601
 
341
602
  begin
342
603
  opts.parse! argv
343
604
  rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
344
- if ignore_invalid then
345
- ignored << e.args.join(' ')
346
- retry
605
+ if DEPRECATED[e.args.first] then
606
+ deprecated << e.args.first
607
+ elsif %w[--format --ri -r --ri-site -R].include? e.args.first then
608
+ raise
347
609
  else
348
- $stderr.puts opts
349
- $stderr.puts
350
- $stderr.puts e
351
- exit 1
610
+ invalid << e.args.join(' ')
352
611
  end
612
+
613
+ retry
614
+ end
615
+
616
+ unless @generator then
617
+ @generator = RDoc::Generator::Darkfish
618
+ @generator_name = 'darkfish'
353
619
  end
354
620
 
355
621
  if @pipe and not argv.empty? then
356
622
  @pipe = false
357
- ignored << '-p (with files)'
623
+ invalid << '-p (with files)'
358
624
  end
359
625
 
360
- unless ignored.empty? or quiet then
361
- $stderr.puts "invalid options: #{ignored.join ', '}"
362
- $stderr.puts '(invalid options are ignored)'
626
+ unless quiet then
627
+ deprecated.each do |opt|
628
+ $stderr.puts 'option ' << opt << ' is deprecated: ' << DEPRECATED[opt]
629
+ end
630
+
631
+ unless invalid.empty? then
632
+ invalid = "invalid options: #{invalid.join ', '}"
633
+
634
+ if ignore_invalid then
635
+ $stderr.puts invalid
636
+ $stderr.puts '(invalid options are ignored)'
637
+ else
638
+ $stderr.puts opts
639
+ $stderr.puts invalid
640
+ exit 1
641
+ end
642
+ end
363
643
  end
364
644
 
365
645
  @op_dir ||= 'doc'
@@ -378,15 +658,10 @@ Usage: #{opt.program_name} [options] [names...]
378
658
  # If no template was specified, use the default template for the output
379
659
  # formatter
380
660
 
381
- @template ||= @generator_name
382
- end
383
-
384
- ##
385
- # Set the title, but only if not already set. This means that a title set
386
- # from the command line trumps one set in a source file
387
-
388
- def title=(string)
389
- @title ||= string
661
+ unless @template then
662
+ @template = @generator_name
663
+ @template_dir = template_dir_for @template
664
+ end
390
665
  end
391
666
 
392
667
  ##
@@ -396,30 +671,46 @@ Usage: #{opt.program_name} [options] [names...]
396
671
  @verbosity.zero?
397
672
  end
398
673
 
399
- def quiet=(bool)
674
+ ##
675
+ # Set quietness to +bool+
676
+
677
+ def quiet= bool
400
678
  @verbosity = bool ? 0 : 1
401
679
  end
402
680
 
403
- private
404
-
405
681
  ##
406
- # Set up an output generator for the format in @generator_name
682
+ # Set up an output generator for the named +generator_name+.
683
+ #
684
+ # If the found generator responds to :setup_options it will be called with
685
+ # the options instance. This allows generators to add custom options or set
686
+ # default options.
407
687
 
408
- def setup_generator
409
- @generator = @generators[@generator_name]
688
+ def setup_generator generator_name = @generator_name
689
+ @generator = @generators[generator_name]
410
690
 
411
691
  unless @generator then
412
- raise OptionParser::InvalidArgument, "Invalid output formatter"
692
+ raise OptionParser::InvalidArgument,
693
+ "Invalid output formatter #{generator_name}"
413
694
  end
695
+
696
+ return if @generator_options.include? @generator
697
+
698
+ @generator_name = generator_name
699
+ @generator_options << @generator
700
+
701
+ @generator.setup_options self if @generator.respond_to? :setup_options
414
702
  end
415
703
 
416
704
  ##
417
- # Check that the files on the command line exist
705
+ # Finds the template dir for +template+
418
706
 
419
- def check_files
420
- @files.each do |f|
421
- stat = File.stat f rescue next
422
- raise RDoc::Error, "file '#{f}' not readable" unless stat.readable?
707
+ def template_dir_for template
708
+ template_path = File.join 'rdoc', 'generator', 'template', template
709
+
710
+ $LOAD_PATH.map do |path|
711
+ File.join File.expand_path(path), template_path
712
+ end.find do |dir|
713
+ File.directory? dir
423
714
  end
424
715
  end
425
716