bahuvrihi-tap 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/History +69 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +119 -0
  4. data/bin/tap +114 -0
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +32 -0
  13. data/lib/tap/app.rb +720 -0
  14. data/lib/tap/constants.rb +8 -0
  15. data/lib/tap/env.rb +640 -0
  16. data/lib/tap/file_task.rb +547 -0
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +21 -0
  21. data/lib/tap/generator/generators/command/templates/command.erb +32 -0
  22. data/lib/tap/generator/generators/config/config_generator.rb +26 -0
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +27 -0
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -0
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +33 -0
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +29 -0
  30. data/lib/tap/generator/generators/root/root_generator.rb +55 -0
  31. data/lib/tap/generator/generators/root/templates/Rakefile +86 -0
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +3 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +5 -0
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +27 -0
  38. data/lib/tap/generator/generators/task/templates/task.erb +14 -0
  39. data/lib/tap/generator/generators/task/templates/test.erb +21 -0
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +8 -0
  42. data/lib/tap/patches/rake/testtask.rb +55 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +51 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +16 -0
  45. data/lib/tap/root.rb +581 -0
  46. data/lib/tap/support/aggregator.rb +55 -0
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +418 -0
  49. data/lib/tap/support/batchable.rb +47 -0
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +194 -0
  52. data/lib/tap/support/command_line.rb +98 -0
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +114 -0
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +111 -0
  61. data/lib/tap/support/executable_queue.rb +82 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +39 -0
  68. data/lib/tap/support/shell_utils.rb +71 -0
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +404 -0
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +38 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +42 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +410 -0
  75. data/lib/tap/support/versions.rb +97 -0
  76. data/lib/tap/task.rb +259 -0
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +37 -0
  80. data/lib/tap/test/env_vars.rb +29 -0
  81. data/lib/tap/test/file_methods.rb +377 -0
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +420 -0
  84. data/lib/tap/test/tap_methods.rb +237 -0
  85. data/lib/tap/workflow.rb +187 -0
  86. metadata +145 -0
@@ -0,0 +1,39 @@
1
+ module Tap
2
+ module Support
3
+ # Raised when an exception is raised during App#run. All errors generated during
4
+ # termination are collected into the RunError.
5
+ class RunError < RuntimeError
6
+ attr_reader :errors
7
+
8
+ def initialize(errors)
9
+ @errors = errors
10
+ @backtrace = nil
11
+ end
12
+
13
+ #The join of all the error messages.
14
+ def message
15
+ lines = []
16
+ errors.each_with_index do |error, i|
17
+ lines << "\nRunError [#{i}] #{error.class} #{error.message}"
18
+ end
19
+ lines.join + "\n"
20
+ end
21
+
22
+ #The join of all the error backtraces.
23
+ def backtrace
24
+ # backtrace gets called every time RunError is re-raised, leading to multiple
25
+ # repeats of the error backtraces. This ensures the additional backtrace
26
+ # information is only added once.
27
+ return @backtrace unless @backtrace == nil
28
+ return nil unless @backtrace = super
29
+
30
+ errors.each_with_index do |error, i|
31
+ @backtrace [-1] += "\n\n---------------------- RunError [#{i}] ----------------------\n#{error.class} #{error.message}"
32
+ @backtrace.concat(error.backtrace || ["missing backtrace"])
33
+ end
34
+ @backtrace
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,71 @@
1
+ autoload(:Tempfile, 'tempfile')
2
+
3
+ module Tap
4
+ module Support
5
+ # Provides several shell utility methods for calling programs.
6
+ #
7
+ # == Windows
8
+ # A couple warnings when running shell commands in the MSDOS prompt on Windows.
9
+ # MSDOS has command line length limits specific to the version of Windows being
10
+ # run (from http://www.ss64.com/nt/cmd.html):
11
+ #
12
+ # Windows NT:: 256 characters
13
+ # Windows 2000:: 2046 characters
14
+ # Windows XP:: 8190 characters
15
+ #
16
+ # No word on more recent versions of Windows. Commands longer than these limits
17
+ # fail, usually with something like: 'the input line is too long'
18
+ #
19
+ module ShellUtils
20
+
21
+ module_function
22
+
23
+ # Run the system command +cmd+, passing the result to the block, if given.
24
+ # Raises an error if the command fails. Uses the same semantics as
25
+ # Kernel::exec and Kernel::system.
26
+ #
27
+ # Based on FileUtils#sh from Rake.
28
+ def sh(*cmd) # :yields: ok, status
29
+ ok = system(*cmd)
30
+
31
+ if block_given?
32
+ yield(ok, $?)
33
+ else
34
+ ok or raise "Command failed with status (#{$?.exitstatus}): [#{ cmd.join(' ')}]"
35
+ end
36
+ end
37
+
38
+ # Runs the system command +cmd+ using sh, redirecting the output to the
39
+ # specified file path. Uses the redirection command:
40
+ #
41
+ # "> \"#{path}\" 2>&1 #{cmd}"
42
+ #
43
+ # This redirection has been tested on Windows, OS X, and Fedora. See
44
+ # http://www.robvanderwoude.com/redirection.html for pointers on
45
+ # redirection. The website notes that this style of redirection SHOULD
46
+ # NOT be used with commands that contain other redirections.
47
+ def redirect_sh(cmd, path, &block) # :yields: ok, status
48
+ sh( "> \"#{path}\" 2>&1 #{cmd}", &block)
49
+ end
50
+
51
+ # Runs the system command +cmd+ and returns the output as a string.
52
+ def capture_sh(cmd, quiet=false, &block) # :yields: ok, status, tempfile_path
53
+ tempfile = Tempfile.new('shell_utils')
54
+ tempfile.close
55
+ redirect_sh(cmd, tempfile.path) do |ok, status|
56
+ if block_given?
57
+ yield(ok, $?, tempfile.path)
58
+ else
59
+ ok or raise %Q{Command failed with status (#{$?.exitstatus}): [#{cmd}]
60
+ -------------- command output -------------------
61
+ #{File.read(tempfile.path)}
62
+ -------------------------------------------------
63
+ }
64
+ end
65
+ end
66
+
67
+ quiet == true ? "" : File.read(tempfile.path)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,30 @@
1
+ module Tap
2
+ module Support
3
+ class Summary
4
+ def initialize
5
+ @map = []
6
+ @width = 10
7
+ end
8
+
9
+ def add(env_key, env, map)
10
+ unless map.empty?
11
+ @map << [env_key, env, map]
12
+ map.each {|(key, path)| @width = key.length if @width < key.length }
13
+ end
14
+ end
15
+
16
+ def lines
17
+ lines = []
18
+ @map.each do |(env_lookup, env, map)|
19
+ lines << "#{env_lookup}:" if @map.length > 1
20
+ map.each do |(key, path)|
21
+ desc = block_given? ? (yield(path) || '') : ''
22
+ desc = " # #{desc}" unless desc.empty?
23
+ lines << (" %-#{@width}s%s" % [key, desc])
24
+ end
25
+ end
26
+ lines
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,404 @@
1
+ # RDoc creates a namespace conflict with IRB within 'rdoc/parsers/parse_rb'
2
+ # In that file, RubyToken and RubyLex get defined in the Object namespace,
3
+ # which will conflict with prior definitions from, for instance, IRB.
4
+ #
5
+ # This code redefines the RDoc RubyToken and RubyLex within the RDoc
6
+ # namespace. RDoc is not affected because all includes and uses of
7
+ # RubyToken and RubyLex are set when RDoc is loaded. The single exception
8
+ # I know of are several calls to class methods of RubyLex (ex RubyLex.debug?).
9
+ # These calls will be routed to the existing RubyLex.
10
+ #
11
+ # Uses of the existing RubyToken and RubyLex (as by irb) should be
12
+ # unaffected as the constants are reset after RDoc loads.
13
+ #
14
+ if Object.const_defined?(:RubyToken) || Object.const_defined?(:RubyLex)
15
+ class Object
16
+ old_ruby_token = const_defined?(:RubyToken) ? remove_const(:RubyToken) : nil
17
+ old_ruby_lex = const_defined?(:RubyLex) ? remove_const(:RubyLex) : nil
18
+
19
+ require 'rdoc/rdoc'
20
+
21
+ # if by chance rdoc has ALREADY been loaded then requiring
22
+ # rdoc will not reset RubyToken and RubyLex... in this case
23
+ # the old constants are what you want.
24
+ new_ruby_token = const_defined?(:RubyToken) ? remove_const(:RubyToken) : old_ruby_token
25
+ new_ruby_lex = const_defined?(:RubyLex) ? remove_const(:RubyLex) : old_ruby_lex
26
+
27
+ RDoc.const_set(:RubyToken, new_ruby_token)
28
+ RDoc.const_set(:RubyLex, new_ruby_lex)
29
+
30
+ const_set(:RubyToken, old_ruby_token) unless old_ruby_token == nil
31
+ const_set(:RubyLex, old_ruby_lex) unless old_ruby_lex == nil
32
+ end
33
+ else
34
+ require 'rdoc/rdoc'
35
+
36
+ if Object.const_defined?(:RubyToken) && !RDoc.const_defined?(:RubyToken)
37
+ class Object
38
+ RDoc.const_set(:RubyToken, remove_const(:RubyToken))
39
+ end
40
+ end
41
+
42
+ if Object.const_defined?(:RubyLex) && !RDoc.const_defined?(:RubyLex)
43
+ class Object
44
+ RDoc.const_set(:RubyLex, remove_const(:RubyLex))
45
+ RDoc::RubyLex.const_set(:RubyLex, RDoc::RubyLex)
46
+ end
47
+ end
48
+ end
49
+
50
+ module Tap
51
+ module Support
52
+
53
+ # TDoc hooks into and extends RDoc to make configuration documentation available as
54
+ # attributes. TDoc provides an extension to the standard RDoc HTMLGenerator and template.
55
+ #
56
+ # === Usage
57
+ # To generate task documentation with configuration information, TDoc must be loaded and
58
+ # the appropriate flags passed to rdoc . Essentially what you want is:
59
+ #
60
+ # % rdoc --fmt tdoc --template tap/support/tdoc/tdoc_html_template [file_names....]
61
+ #
62
+ # Unfortunately, there is no way to load or require a file into the rdoc utility directly; the
63
+ # above code causes an 'Invalid output formatter' error. However, TDoc is easy to utilize
64
+ # from a Rake::RDocTask:
65
+ #
66
+ # require 'rake'
67
+ # require 'rake/rdoctask'
68
+ #
69
+ # desc 'Generate documentation.'
70
+ # Rake::RDocTask.new(:rdoc) do |rdoc|
71
+ # require 'tap/support/tdoc'
72
+ # rdoc.template = 'tap/support/tdoc/tdoc_html_template'
73
+ # rdoc.options << '--fmt' << 'tdoc'
74
+ #
75
+ # # specify whatever else you need
76
+ # # rdoc.rdoc_files.include(...)
77
+ # end
78
+ #
79
+ # Now execute the rake task like:
80
+ #
81
+ # % rake rdoc
82
+ #
83
+ # === Implementation
84
+ # RDoc is a beast to utilize in a non-standard way. One way to make RDoc parse unexpected
85
+ # flags like 'config' or 'config_attr' is to use the '--accessor' option (see 'rdoc --help' or
86
+ # the RDoc documentation for more details).
87
+ #
88
+ # TDoc hooks into the '--accessor' parsing process to pull out configuration attributes and
89
+ # format them into their own Configuration section on an RDoc html page. When 'tdoc' is
90
+ # specified as an rdoc option, TDoc in effect sets accessor flags for all the standard Task
91
+ # configuration methods, and then extends the RDoc::RubyParser handle these specially.
92
+ #
93
+ # If tdoc is not specified as the rdoc format, TDoc does not affect the RDoc output.
94
+ # Similarly, the configuration attributes will not appear in the output unless you specify a
95
+ # template that utilizes them.
96
+ #
97
+ # === Namespace conflicts
98
+ # RDoc creates a namespace conflict with other libraries that define RubyToken and RubyLex
99
+ # in the Object namespace (the prime example being IRB). TDoc checks for such a conflict
100
+ # and redfines the RDoc versions of RubyToken and RubyLex within the RDoc namespace.
101
+ # Essentially:
102
+ #
103
+ # original constant redefined constant
104
+ # RubyToken RDoc::RubyToken
105
+ # RubyLex RDoc::RubyLex
106
+ #
107
+ # The redefinition should not affect the existing (non RDoc) RubyToken and RubyLex constants,
108
+ # but if you directly use the RDoc versions after loading TDoc, you should be aware that they must
109
+ # be accessed through the new constants. Unfortunatley the trick is not seamless. The RDoc
110
+ # RubyLex makes a few calls to the RubyLex class method 'debug?'... these will be issued to
111
+ # the existing (non RDoc) RubyLex method and not the redefined RDoc::RubyLex.debug?
112
+ #
113
+ # In addition, because of the RubyLex calls, the RDoc::RubyLex cannot be fully hidden when
114
+ # TDoc is loaded before the conflicting RubyLex; you cannot load TDoc before loading IRB
115
+ # without raising warnings.
116
+ #
117
+ # Luckily all these troubles can be avoided very easily by not loading TDoc or RDoc when
118
+ # you're in irb. On the plus side, going against what I just said, you can now access/use
119
+ # RDoc within irb by requiring <tt>'tap/support/tdoc'</tt>.
120
+ #
121
+ #--
122
+ # Note that tap-0.10.0 heavily refactored TDoc functionality out of the old TDoc and into
123
+ # Lazydoc, and changed the declaration syntax for configurations. These changes also
124
+ # affected the implementation of TDoc. Mostly the changes are hacks to get the old
125
+ # system to work in the new system... as hacky as the old TDoc was, now this TDoc is hacky
126
+ # AND may have cruft. Until it breaks completely, I leave it as is... ugly and hard to fathom.
127
+ #
128
+ module TDoc
129
+
130
+ # Encasulates information about the configuration. Designed to be utilized
131
+ # by the TDocHTMLGenerator as similarly as possible to standard attributes.
132
+ class ConfigAttr < RDoc::Attr
133
+ # Contains the actual declaration for the config attribute. ex: "c [:key, 'value'] # comment"
134
+ attr_accessor :config_declaration, :default
135
+
136
+ def initialize(*args)
137
+ @comment = nil # suppress a warning in Ruby 1.9
138
+ super
139
+ end
140
+
141
+ alias original_comment comment
142
+
143
+ def desc
144
+ case text.to_s
145
+ when /^#--(.*)/ then $1.strip
146
+ when /^#(.*)/ then $1.strip
147
+ else
148
+ nil
149
+ end
150
+ end
151
+
152
+ # The description for the config. Comment is formed from the standard
153
+ # attribute comment and the text following the attribute, which is slightly
154
+ # different than normal:
155
+ #
156
+ # # standard comment
157
+ # attr_accessor :attribute
158
+ #
159
+ # # standard comment
160
+ # config_accessor :config # ...added to standard comment
161
+ #
162
+ # c [:key, 'value'] # hence you can comment inline like this.
163
+ #
164
+ # The comments for each of these will be:
165
+ # attribute:: standard comment
166
+ # config:: standard comment ...added to standard comment
167
+ # key:: hence you can comment inline like this.
168
+ #
169
+ def comment(add_default=true)
170
+ # this would include the trailing comment...
171
+ # text_comment = text.to_s.sub(/^#--.*/m, '')
172
+ #original_comment.to_s + text_comment + (default && add_default ? " (#{default})" : "")
173
+ comment = original_comment.to_s.strip
174
+ comment = desc.to_s if comment.empty?
175
+ comment + (default && add_default ? " (<tt>#{default}</tt>)" : "")
176
+ end
177
+ end
178
+
179
+ module CodeObjectAccess # :nodoc:
180
+ def comment_sections(section_regexp=//, normalize_comments=false)
181
+ res = {}
182
+
183
+ section = nil
184
+ lines = []
185
+ comment_lines = comment.split(/\r?\n/)
186
+ comment_lines << nil
187
+ comment_lines.each do |line|
188
+ case line
189
+ when nil, /^\s*#\s*=+(.*)/
190
+ next_section = (line == nil ? nil : $1.to_s.strip)
191
+
192
+ if section =~ section_regexp
193
+ lines << "" unless normalize_comments
194
+ res[section] = lines.join("\n") unless section == nil
195
+ end
196
+
197
+ section = next_section
198
+ lines = []
199
+ else
200
+ if normalize_comments
201
+ line =~ /^\s*#\s?(.*)/
202
+ line = $1.to_s
203
+ end
204
+
205
+ lines << line
206
+ end
207
+ end
208
+
209
+ res
210
+ end
211
+ end
212
+
213
+ module ClassModuleAccess # :nodoc:
214
+ def find_class_or_module_named(name)
215
+ return self if full_name == name
216
+ (@classes.values + @modules.values).each do |c|
217
+ res = c.find_class_or_module_named(name)
218
+ return res if res
219
+ end
220
+ nil
221
+ end
222
+
223
+ def configurations
224
+ @attributes.select do |attribute|
225
+ attribute.kind_of?(TDoc::ConfigAttr)
226
+ end
227
+ end
228
+
229
+ def find_configuration_named(name)
230
+ @attributes.each do |attribute|
231
+ next unless attribute.kind_of?(TDoc::ConfigAttr)
232
+ return attribute if attribute.name == name
233
+ end
234
+ nil
235
+ end
236
+ end
237
+
238
+ # Overrides the new method automatically extend the new object with
239
+ # ConfigParser. Intended to be used like:
240
+ # RDoc::RubyParser.extend InitializeConfigParser
241
+ module InitializeConfigParser # :nodoc:
242
+ def new(*args)
243
+ parser = super
244
+ parser.extend ConfigParser
245
+ #parser.config_mode = 'config_accessor'
246
+ parser
247
+ end
248
+ end
249
+
250
+ # Provides methods extending an RDoc::RubyParser such that the parser will produce
251
+ # TDoc::ConfigAttr instances in the place of RDoc::Attr instances during attribute
252
+ # parsing.
253
+ module ConfigParser # :nodoc:
254
+ include RDoc::RubyToken
255
+ include TokenStream
256
+
257
+ CONFIG_ACCESSORS = ['config', 'config_attr']
258
+
259
+ # Gets tokens until the next TkNL
260
+ def get_tk_to_nl
261
+ tokens = []
262
+ while !(tk = get_tk).kind_of?(TkNL)
263
+ tokens.push tk
264
+ end
265
+ unget_tk(tk)
266
+ tokens
267
+ end
268
+
269
+ # Works like the original parse_attr_accessor, except that the arg
270
+ # name is parsed from the config syntax and added attribute will
271
+ # be a TDoc::ConfigAttr. For example:
272
+ #
273
+ # class TaskDoc < Tap::Task
274
+ # config [:key, 'value'] # comment
275
+ # end
276
+ #
277
+ # produces an attribute named :key in the current config_rw mode.
278
+ #
279
+ # (see 'rdoc/parsers/parse_rb' line 2509)
280
+ def parse_config(context, single, tk, comment)
281
+ tks = get_tk_to_nl
282
+
283
+ key_tk = nil
284
+ value_tk = nil
285
+
286
+ tks.each do |token|
287
+ next if token.kind_of?(TkSPACE)
288
+
289
+ if key_tk == nil
290
+ case token
291
+ when TkSYMBOL then key_tk = token
292
+ when TkLPAREN then next
293
+ else break
294
+ end
295
+ else
296
+ case token
297
+ when TkCOMMA then value_tk = token
298
+ else
299
+ value_tk = token if value_tk.kind_of?(TkCOMMA)
300
+ break
301
+ end
302
+ end
303
+ end
304
+
305
+ text = ""
306
+ if tks.last.kind_of?(TkCOMMENT)
307
+ text = tks.last.text.chomp("\n").chomp("\r")
308
+ unget_tk(tks.last)
309
+
310
+ # If nodoc is given, don't document
311
+
312
+ tmp = RDoc::CodeObject.new
313
+ read_documentation_modifiers(tmp, RDoc::ATTR_MODIFIERS)
314
+ text = nil unless tmp.document_self
315
+ end
316
+
317
+ tks.reverse_each {|token| unget_tk(token) }
318
+ return if key_tk == nil || text == nil
319
+
320
+ arg = key_tk.text[1..-1]
321
+ default = nil
322
+ if value_tk
323
+ if text =~ /(.*):no_default:(.*)/
324
+ text = $1 + $2
325
+ else
326
+ default = value_tk.text
327
+ end
328
+ end
329
+ att = TDoc::ConfigAttr.new(text, arg, "RW", comment)
330
+ att.config_declaration = get_tkread
331
+ att.default = default
332
+
333
+ context.add_attribute(att)
334
+ end
335
+
336
+ # Overrides the standard parse_attr_accessor method to hook in parsing
337
+ # of the config accessors. If the input token is not named as one of the
338
+ # CONFIG_ACCESSORS, it will be processed normally.
339
+ def parse_attr_accessor(context, single, tk, comment)
340
+ case tk.name
341
+ when 'config', 'config_attr'
342
+ parse_config(context, single, tk, comment)
343
+ else
344
+ super
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+ end
351
+
352
+ # Register the TDoc generator (in case you want to actually use it).
353
+ # method echos RDoc generator registration (see 'rdoc/rdoc' line 76)
354
+ Generator = Struct.new(:file_name, :class_name, :key)
355
+ RDoc::RDoc::GENERATORS['tdoc'] = Generator.new(
356
+ "tap/support/tdoc/tdoc_html_generator.rb",
357
+ "TDocHTMLGenerator".intern,
358
+ "tdoc")
359
+
360
+ # Add the extended accessors to context classes.
361
+ module RDoc # :nodoc:
362
+ class CodeObject # :nodoc:
363
+ include Tap::Support::TDoc::CodeObjectAccess
364
+ end
365
+
366
+ class ClassModule # :nodoc:
367
+ include Tap::Support::TDoc::ClassModuleAccess
368
+ end
369
+ end
370
+
371
+ # Override methods in Options to in effect incorporate the accessor
372
+ # flags for TDoc parsing. (see 'rdoc/options') Raise an error if an
373
+ # accessor flag has already been specified.
374
+ class Options # :nodoc:
375
+ alias tdoc_original_parse parse
376
+
377
+ def parse(argv, generators)
378
+ tdoc_original_parse(argv, generators)
379
+ return unless @generator_name == 'tdoc'
380
+
381
+ accessors = Tap::Support::TDoc::ConfigParser::CONFIG_ACCESSORS
382
+
383
+ # check the config_accessor_flags for accessor conflicts
384
+ extra_accessor_flags.each_pair do |accessor, flag|
385
+ if accessors.include?(accessor)
386
+ raise OptionList.error("tdoc format already handles the accessor '#{accessor}'")
387
+ end
388
+ end
389
+
390
+ # extra_accessors will be nil if no extra accessors were
391
+ # specifed, otherwise it'll be a regexp like /^(...)$/
392
+ # the string subset assumes
393
+ # regexp.to_s # => /(?-mix:^(...)$)/
394
+ @extra_accessors ||= /^()$/
395
+ current_accessors_str = @extra_accessors.to_s[9..-4]
396
+
397
+ # echos the Regexp production code in rdoc/options.rb
398
+ # (see the parse method, line 501)
399
+ re = '^(' + current_accessors_str + accessors.map{|a| Regexp.quote(a)}.join('|') + ')$'
400
+ @extra_accessors = Regexp.new(re)
401
+
402
+ RDoc::RubyParser.extend Tap::Support::TDoc::InitializeConfigParser
403
+ end
404
+ end