tap 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/History +35 -1
  2. data/MIT-LICENSE +1 -1
  3. data/README +16 -15
  4. data/bin/tap +1 -1
  5. data/cmd/console.rb +4 -3
  6. data/cmd/manifest.rb +2 -2
  7. data/cmd/run.rb +12 -15
  8. data/doc/Class Reference +120 -117
  9. data/doc/Command Reference +27 -27
  10. data/doc/Syntax Reference +55 -111
  11. data/doc/Tutorial +69 -26
  12. data/lib/tap.rb +3 -8
  13. data/lib/tap/app.rb +122 -146
  14. data/lib/tap/constants.rb +2 -2
  15. data/lib/tap/env.rb +178 -252
  16. data/lib/tap/exe.rb +67 -30
  17. data/lib/tap/file_task.rb +224 -411
  18. data/lib/tap/generator/arguments.rb +13 -0
  19. data/lib/tap/generator/base.rb +112 -30
  20. data/lib/tap/generator/destroy.rb +36 -13
  21. data/lib/tap/generator/generate.rb +69 -48
  22. data/lib/tap/generator/generators/command/templates/command.erb +3 -3
  23. data/lib/tap/generator/generators/config/config_generator.rb +82 -10
  24. data/lib/tap/generator/generators/generator/generator_generator.rb +16 -6
  25. data/lib/tap/generator/generators/generator/templates/task.erb +2 -2
  26. data/lib/tap/generator/generators/generator/templates/test.erb +26 -0
  27. data/lib/tap/generator/generators/root/root_generator.rb +24 -13
  28. data/lib/tap/generator/generators/root/templates/Rakefile +4 -4
  29. data/lib/tap/generator/generators/root/templates/{tapfile → Rapfile} +6 -6
  30. data/lib/tap/generator/generators/root/templates/gemspec +0 -1
  31. data/lib/tap/generator/generators/task/task_generator.rb +3 -3
  32. data/lib/tap/generator/generators/task/templates/test.erb +1 -1
  33. data/lib/tap/generator/manifest.rb +7 -1
  34. data/lib/tap/generator/preview.rb +76 -0
  35. data/lib/tap/root.rb +222 -156
  36. data/lib/tap/spec.rb +41 -0
  37. data/lib/tap/support/aggregator.rb +25 -28
  38. data/lib/tap/support/audit.rb +278 -357
  39. data/lib/tap/support/constant.rb +2 -1
  40. data/lib/tap/support/constant_manifest.rb +28 -25
  41. data/lib/tap/support/dependency.rb +1 -1
  42. data/lib/tap/support/executable.rb +52 -183
  43. data/lib/tap/support/executable_queue.rb +50 -20
  44. data/lib/tap/support/gems.rb +1 -1
  45. data/lib/tap/support/intern.rb +0 -6
  46. data/lib/tap/support/join.rb +49 -83
  47. data/lib/tap/support/joins.rb +0 -3
  48. data/lib/tap/support/joins/switch.rb +13 -11
  49. data/lib/tap/support/joins/sync_merge.rb +25 -50
  50. data/lib/tap/support/manifest.rb +1 -0
  51. data/lib/tap/support/node.rb +140 -20
  52. data/lib/tap/support/parser.rb +56 -42
  53. data/lib/tap/support/schema.rb +183 -157
  54. data/lib/tap/support/templater.rb +9 -1
  55. data/lib/tap/support/versions.rb +39 -0
  56. data/lib/tap/task.rb +150 -177
  57. data/lib/tap/tasks/dump.rb +4 -4
  58. data/lib/tap/tasks/load.rb +29 -29
  59. data/lib/tap/test.rb +66 -53
  60. data/lib/tap/test/env_vars.rb +3 -3
  61. data/lib/tap/test/extensions.rb +11 -17
  62. data/lib/tap/test/file_test.rb +74 -132
  63. data/lib/tap/test/file_test_class.rb +4 -1
  64. data/lib/tap/test/regexp_escape.rb +2 -2
  65. data/lib/tap/test/script_test.rb +2 -2
  66. data/lib/tap/test/subset_test.rb +6 -6
  67. data/lib/tap/test/tap_test.rb +28 -154
  68. metadata +30 -51
  69. data/bin/rap +0 -118
  70. data/cgi/run.rb +0 -97
  71. data/lib/tap/declarations.rb +0 -229
  72. data/lib/tap/generator/generators/config/templates/doc.erb +0 -12
  73. data/lib/tap/generator/generators/config/templates/nodoc.erb +0 -8
  74. data/lib/tap/generator/generators/file_task/file_task_generator.rb +0 -27
  75. data/lib/tap/generator/generators/file_task/templates/file.txt +0 -11
  76. data/lib/tap/generator/generators/file_task/templates/result.yml +0 -6
  77. data/lib/tap/generator/generators/file_task/templates/task.erb +0 -33
  78. data/lib/tap/generator/generators/file_task/templates/test.erb +0 -29
  79. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +0 -5
  80. data/lib/tap/patches/optparse/summarize.rb +0 -62
  81. data/lib/tap/support/assignments.rb +0 -173
  82. data/lib/tap/support/class_configuration.rb +0 -182
  83. data/lib/tap/support/combinator.rb +0 -125
  84. data/lib/tap/support/configurable.rb +0 -113
  85. data/lib/tap/support/configurable_class.rb +0 -271
  86. data/lib/tap/support/configuration.rb +0 -170
  87. data/lib/tap/support/gems/rake.rb +0 -111
  88. data/lib/tap/support/instance_configuration.rb +0 -173
  89. data/lib/tap/support/joins/fork.rb +0 -19
  90. data/lib/tap/support/joins/merge.rb +0 -22
  91. data/lib/tap/support/joins/sequence.rb +0 -21
  92. data/lib/tap/support/lazy_attributes.rb +0 -45
  93. data/lib/tap/support/lazydoc.rb +0 -386
  94. data/lib/tap/support/lazydoc/comment.rb +0 -503
  95. data/lib/tap/support/lazydoc/config.rb +0 -17
  96. data/lib/tap/support/lazydoc/definition.rb +0 -36
  97. data/lib/tap/support/lazydoc/document.rb +0 -152
  98. data/lib/tap/support/lazydoc/method.rb +0 -24
  99. data/lib/tap/support/tdoc.rb +0 -409
  100. data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -38
  101. data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -42
  102. data/lib/tap/support/validation.rb +0 -479
  103. data/lib/tap/tasks/rake.rb +0 -57
@@ -1,17 +0,0 @@
1
- module Tap
2
- module Support
3
- module Lazydoc
4
- class Config < Comment
5
- def empty?
6
- to_str.empty?
7
- end
8
-
9
- def to_str
10
- # currently removes the :no_default: document modifier
11
- # which is used during generation of TDoc
12
- subject.to_s =~ /#\s*(:no_default:)?\s*(.*)$/ ? $2.strip : ""
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,36 +0,0 @@
1
- module Tap
2
- module Support
3
- module Lazydoc
4
- class Definition < Comment
5
- attr_accessor :subclass
6
-
7
- def configurations(fragment_sep=" ", line_sep="\n", strip=true)
8
- lines = []
9
- subclass.configurations.each do |receiver, key, config|
10
- desc = config.desc
11
- case desc
12
- when Definition
13
- lines << "# #{desc.subclass}"
14
- lines.concat desc.original_to_s(fragment_sep, nil, strip).collect {|line| "# #{line}"}
15
- lines << "#{key}:"
16
- lines.concat desc.configurations(fragment_sep).collect {|line| " #{line}"}
17
- else
18
- lines << "# #{desc}"
19
- lines << "#{key}: #{config.default}"
20
- lines << ""
21
- end
22
- end
23
-
24
- lines
25
- end
26
-
27
- alias original_to_s to_s
28
-
29
- def to_s(fragment_sep=" ", line_sep="\n", strip=true)
30
- lines = [original_to_s(fragment_sep, line_sep, strip)] + configurations(fragment_sep)
31
- line_sep ? lines.join(line_sep) : lines
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,152 +0,0 @@
1
- require 'tap/support/lazydoc/comment'
2
-
3
- module Tap
4
- module Support
5
- module Lazydoc
6
-
7
- # A Document tracks constant attributes and code comments for a particular
8
- # source file. Documents may be assigned a default_const_name to be used
9
- # when a constant attribute does not specify a constant.
10
- #
11
- # # KeyWithConst::key value a
12
- # # ::key value b
13
- #
14
- # doc = Document.new(__FILE__, 'DefaultConst')
15
- # doc.resolve
16
- # doc['KeyWithConst']['key'].value # => 'value a'
17
- # doc['DefaultConst']['key'].value # => 'value b'
18
- #
19
- class Document
20
-
21
- # The source file for self, used during resolve
22
- attr_reader :source_file
23
-
24
- # An array of Comment objects identifying lines
25
- # resolved or to-be-resolved
26
- attr_reader :comments
27
-
28
- # A hash of [const_name, attributes] pairs tracking the constant
29
- # attributes resolved or to-be-resolved for self. Attributes
30
- # are hashes of [key, comment] pairs.
31
- attr_reader :const_attrs
32
-
33
- # The default constant name used when no constant name
34
- # is specified for a constant attribute
35
- attr_reader :default_const_name
36
-
37
- # Flag indicating whether or not self has been resolved
38
- attr_accessor :resolved
39
-
40
- def initialize(source_file=nil, default_const_name='')
41
- self.source_file = source_file
42
- @default_const_name = default_const_name
43
- @comments = []
44
- @const_attrs = {}
45
- @resolved = false
46
- self.reset
47
- end
48
-
49
- # Resets self by clearing const_attrs, comments, and setting
50
- # resolved to false. Generally NOT recommended as this
51
- # clears any work you've done registering lines; to simply
52
- # allow resolve to re-scan a document, manually set
53
- # resolved to false.
54
- def reset
55
- @const_attrs.clear
56
- @comments.clear
57
- @resolved = false
58
- self
59
- end
60
-
61
- # Sets the source file for self. Expands the source file path if necessary.
62
- def source_file=(source_file)
63
- @source_file = source_file == nil ? nil : File.expand_path(source_file)
64
- end
65
-
66
- # Sets the default_const_name for self. Any const_attrs assigned to
67
- # the previous default will be removed and merged with those already
68
- # assigned to the new default.
69
- def default_const_name=(const_name)
70
- self[const_name].merge!(const_attrs.delete(@default_const_name) || {})
71
- @default_const_name = const_name
72
- end
73
-
74
- # Returns the attributes for the specified const_name.
75
- def [](const_name)
76
- const_attrs[const_name] ||= {}
77
- end
78
-
79
- # Returns an array of the const_names in self with at
80
- # least one attribute.
81
- def const_names
82
- names = []
83
- const_attrs.each_pair do |const_name, attrs|
84
- names << const_name unless attrs.empty?
85
- end
86
- names
87
- end
88
-
89
- # Register the specified line number to self. Register
90
- # may take an integer or a regexp for late-evaluation.
91
- # See Comment#resolve for more details.
92
- #
93
- # Returns a comment_class instance corresponding to the line.
94
- def register(line_number, comment_class=Comment)
95
- comment = comments.find {|c| c.class == comment_class && c.line_number == line_number }
96
-
97
- if comment == nil
98
- comment = comment_class.new(line_number)
99
- comments << comment
100
- end
101
-
102
- comment
103
- end
104
-
105
- # Registers a regexp matching methods by the specified
106
- # name.
107
- def register_method(method, comment_class=Comment)
108
- register(/^\s*def\s+#{method}(\W|$)/, comment_class)
109
- end
110
-
111
- # Scans str for constant attributes and adds them to to self. Code
112
- # comments are also resolved against str. If no str is specified,
113
- # the contents of source_file are used instead.
114
- #
115
- # Resolve does nothing if resolved == true. Returns true if str
116
- # was resolved, or false otherwise.
117
- def resolve(str=nil)
118
- return(false) if resolved
119
-
120
- str = File.read(source_file) if str == nil
121
- Lazydoc.parse(str) do |const_name, key, comment|
122
- const_name = default_const_name if const_name.empty?
123
- self[const_name][key] = comment
124
- end
125
-
126
- unless comments.empty?
127
- lines = str.split(/\r?\n/)
128
- comments.each do |comment|
129
- comment.resolve(lines)
130
- end
131
- end
132
-
133
- @resolved = true
134
- end
135
-
136
- def to_hash
137
- const_hash = {}
138
- const_attrs.each_pair do |const_name, attributes|
139
- next if attributes.empty?
140
-
141
- attr_hash = {}
142
- attributes.each_pair do |key, comment|
143
- attr_hash[key] = (block_given? ? yield(comment) : comment)
144
- end
145
- const_hash[const_name] = attr_hash
146
- end
147
- const_hash
148
- end
149
- end
150
- end
151
- end
152
- end
@@ -1,24 +0,0 @@
1
- module Tap
2
- module Support
3
- module Lazydoc
4
- class Method < Comment
5
- def resolve(lines)
6
- super
7
- @subject =~ /def \w+(\((.*?)\))?/
8
-
9
- args = $2.to_s.split(',').collect do |arg|
10
- arg = arg.strip.upcase
11
- case arg
12
- when /^&/ then nil
13
- when /^\*/ then arg[1..-1] + "..."
14
- else arg
15
- end
16
- end
17
-
18
- @subject = args.join(' ')
19
- self
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,409 +0,0 @@
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
- unless Object.const_defined?(:TokenStream)
51
- TokenStream = RDoc::TokenStream
52
- Options = RDoc::Options
53
- end
54
-
55
- module Tap
56
- module Support
57
-
58
- # TDoc hooks into and extends RDoc to make configuration documentation available as
59
- # attributes. TDoc provides an extension to the standard RDoc HTMLGenerator and template.
60
- #
61
- # === Usage
62
- # To generate task documentation with configuration information, TDoc must be loaded and
63
- # the appropriate flags passed to rdoc . Essentially what you want is:
64
- #
65
- # % rdoc --fmt tdoc --template tap/support/tdoc/tdoc_html_template [file_names....]
66
- #
67
- # Unfortunately, there is no way to load or require a file into the rdoc utility directly; the
68
- # above code causes an 'Invalid output formatter' error. However, TDoc is easy to utilize
69
- # from a Rake::RDocTask:
70
- #
71
- # require 'rake'
72
- # require 'rake/rdoctask'
73
- #
74
- # desc 'Generate documentation.'
75
- # Rake::RDocTask.new(:rdoc) do |rdoc|
76
- # require 'tap/support/tdoc'
77
- # rdoc.template = 'tap/support/tdoc/tdoc_html_template'
78
- # rdoc.options << '--fmt' << 'tdoc'
79
- #
80
- # # specify whatever else you need
81
- # # rdoc.rdoc_files.include(...)
82
- # end
83
- #
84
- # Now execute the rake task like:
85
- #
86
- # % rake rdoc
87
- #--
88
- # === Implementation
89
- # RDoc is a beast to utilize in a non-standard way. One way to make RDoc parse unexpected
90
- # flags like 'config' or 'config_attr' is to use the '--accessor' option (see 'rdoc --help' or
91
- # the RDoc documentation for more details).
92
- #
93
- # TDoc hooks into the '--accessor' parsing process to pull out configuration attributes and
94
- # format them into their own Configuration section on an RDoc html page. When 'tdoc' is
95
- # specified as an rdoc option, TDoc in effect sets accessor flags for all the standard Task
96
- # configuration methods, and then extends the RDoc::RubyParser handle these specially.
97
- #
98
- # If tdoc is not specified as the rdoc format, TDoc does not affect the RDoc output.
99
- # Similarly, the configuration attributes will not appear in the output unless you specify a
100
- # template that utilizes them.
101
- #
102
- # === Namespace conflicts
103
- # RDoc creates a namespace conflict with other libraries that define RubyToken and RubyLex
104
- # in the Object namespace (the prime example being IRB). TDoc checks for such a conflict
105
- # and redfines the RDoc versions of RubyToken and RubyLex within the RDoc namespace.
106
- # Essentially:
107
- #
108
- # original constant redefined constant
109
- # RubyToken RDoc::RubyToken
110
- # RubyLex RDoc::RubyLex
111
- #
112
- # The redefinition should not affect the existing (non RDoc) RubyToken and RubyLex constants,
113
- # but if you directly use the RDoc versions after loading TDoc, you should be aware that they must
114
- # be accessed through the new constants. Unfortunatley the trick is not seamless. The RDoc
115
- # RubyLex makes a few calls to the RubyLex class method 'debug?'... these will be issued to
116
- # the existing (non RDoc) RubyLex method and not the redefined RDoc::RubyLex.debug?
117
- #
118
- # In addition, because of the RubyLex calls, the RDoc::RubyLex cannot be fully hidden when
119
- # TDoc is loaded before the conflicting RubyLex; you cannot load TDoc before loading IRB
120
- # without raising warnings.
121
- #
122
- # Luckily all these troubles can be avoided very easily by not loading TDoc or RDoc when
123
- # you're in irb. On the plus side, going against what I just said, you can now access/use
124
- # RDoc within irb by requiring <tt>'tap/support/tdoc'</tt>.
125
- #
126
- #--
127
- # Note that tap-0.10.0 heavily refactored TDoc functionality out of the old TDoc and into
128
- # Lazydoc, and changed the declaration syntax for configurations. These changes also
129
- # affected the implementation of TDoc. Mostly the changes are hacks to get the old
130
- # system to work in the new system... as hacky as the old TDoc was, now this TDoc is hacky
131
- # AND may have cruft. Until it breaks completely, I leave it as is... ugly and hard to fathom.
132
- #
133
- module TDoc
134
-
135
- # Encasulates information about the configuration. Designed to be utilized
136
- # by the TDocHTMLGenerator as similarly as possible to standard attributes.
137
- class ConfigAttr < RDoc::Attr # :nodoc:
138
- # Contains the actual declaration for the config attribute. ex: "c [:key, 'value'] # comment"
139
- attr_accessor :config_declaration, :default
140
-
141
- def initialize(*args)
142
- @comment = nil # suppress a warning in Ruby 1.9
143
- super
144
- end
145
-
146
- alias original_comment comment
147
-
148
- def desc
149
- case text.to_s
150
- when /^#--(.*)/ then $1.strip
151
- when /^#(.*)/ then $1.strip
152
- else
153
- nil
154
- end
155
- end
156
-
157
- # The description for the config. Comment is formed from the standard
158
- # attribute comment and the text following the attribute, which is slightly
159
- # different than normal:
160
- #
161
- # # standard comment
162
- # attr_accessor :attribute
163
- #
164
- # # standard comment
165
- # config_accessor :config # ...added to standard comment
166
- #
167
- # c [:key, 'value'] # hence you can comment inline like this.
168
- #
169
- # The comments for each of these will be:
170
- # attribute:: standard comment
171
- # config:: standard comment ...added to standard comment
172
- # key:: hence you can comment inline like this.
173
- #
174
- def comment(add_default=true)
175
- # this would include the trailing comment...
176
- # text_comment = text.to_s.sub(/^#--.*/m, '')
177
- #original_comment.to_s + text_comment + (default && add_default ? " (#{default})" : "")
178
- comment = original_comment.to_s.strip
179
- comment = desc.to_s if comment.empty?
180
- comment + (default && add_default ? " (<tt>#{default}</tt>)" : "")
181
- end
182
- end
183
-
184
- module CodeObjectAccess # :nodoc:
185
- def comment_sections(section_regexp=//, normalize_comments=false)
186
- res = {}
187
-
188
- section = nil
189
- lines = []
190
- comment_lines = comment.split(/\r?\n/)
191
- comment_lines << nil
192
- comment_lines.each do |line|
193
- case line
194
- when nil, /^\s*#\s*=+(.*)/
195
- next_section = (line == nil ? nil : $1.to_s.strip)
196
-
197
- if section =~ section_regexp
198
- lines << "" unless normalize_comments
199
- res[section] = lines.join("\n") unless section == nil
200
- end
201
-
202
- section = next_section
203
- lines = []
204
- else
205
- if normalize_comments
206
- line =~ /^\s*#\s?(.*)/
207
- line = $1.to_s
208
- end
209
-
210
- lines << line
211
- end
212
- end
213
-
214
- res
215
- end
216
- end
217
-
218
- module ClassModuleAccess # :nodoc:
219
- def find_class_or_module_named(name)
220
- return self if full_name == name
221
- (@classes.values + @modules.values).each do |c|
222
- res = c.find_class_or_module_named(name)
223
- return res if res
224
- end
225
- nil
226
- end
227
-
228
- def configurations
229
- @attributes.select do |attribute|
230
- attribute.kind_of?(TDoc::ConfigAttr)
231
- end
232
- end
233
-
234
- def find_configuration_named(name)
235
- @attributes.each do |attribute|
236
- next unless attribute.kind_of?(TDoc::ConfigAttr)
237
- return attribute if attribute.name == name
238
- end
239
- nil
240
- end
241
- end
242
-
243
- # Overrides the new method automatically extend the new object with
244
- # ConfigParser. Intended to be used like:
245
- # RDoc::RubyParser.extend InitializeConfigParser
246
- module InitializeConfigParser # :nodoc:
247
- def new(*args)
248
- parser = super
249
- parser.extend ConfigParser
250
- #parser.config_mode = 'config_accessor'
251
- parser
252
- end
253
- end
254
-
255
- # Provides methods extending an RDoc::RubyParser such that the parser will produce
256
- # TDoc::ConfigAttr instances in the place of RDoc::Attr instances during attribute
257
- # parsing.
258
- module ConfigParser # :nodoc:
259
- include RDoc::RubyToken
260
- include TokenStream
261
-
262
- CONFIG_ACCESSORS = ['config', 'config_attr']
263
-
264
- # Gets tokens until the next TkNL
265
- def get_tk_to_nl
266
- tokens = []
267
- while !(tk = get_tk).kind_of?(TkNL)
268
- tokens.push tk
269
- end
270
- unget_tk(tk)
271
- tokens
272
- end
273
-
274
- # Works like the original parse_attr_accessor, except that the arg
275
- # name is parsed from the config syntax and added attribute will
276
- # be a TDoc::ConfigAttr. For example:
277
- #
278
- # class TaskDoc < Tap::Task
279
- # config [:key, 'value'] # comment
280
- # end
281
- #
282
- # produces an attribute named :key in the current config_rw mode.
283
- #
284
- # (see 'rdoc/parsers/parse_rb' line 2509)
285
- def parse_config(context, single, tk, comment)
286
- tks = get_tk_to_nl
287
-
288
- key_tk = nil
289
- value_tk = nil
290
-
291
- tks.each do |token|
292
- next if token.kind_of?(TkSPACE)
293
-
294
- if key_tk == nil
295
- case token
296
- when TkSYMBOL then key_tk = token
297
- when TkLPAREN then next
298
- else break
299
- end
300
- else
301
- case token
302
- when TkCOMMA then value_tk = token
303
- else
304
- value_tk = token if value_tk.kind_of?(TkCOMMA)
305
- break
306
- end
307
- end
308
- end
309
-
310
- text = ""
311
- if tks.last.kind_of?(TkCOMMENT)
312
- text = tks.last.text.chomp("\n").chomp("\r")
313
- unget_tk(tks.last)
314
-
315
- # If nodoc is given, don't document
316
-
317
- tmp = RDoc::CodeObject.new
318
- read_documentation_modifiers(tmp, RDoc::ATTR_MODIFIERS)
319
- text = nil unless tmp.document_self
320
- end
321
-
322
- tks.reverse_each {|token| unget_tk(token) }
323
- return if key_tk == nil || text == nil
324
-
325
- arg = key_tk.text[1..-1]
326
- default = nil
327
- if value_tk
328
- if text =~ /(.*):no_default:(.*)/
329
- text = $1 + $2
330
- else
331
- default = value_tk.text
332
- end
333
- end
334
- att = TDoc::ConfigAttr.new(text, arg, "RW", comment)
335
- att.config_declaration = get_tkread
336
- att.default = default
337
-
338
- context.add_attribute(att)
339
- end
340
-
341
- # Overrides the standard parse_attr_accessor method to hook in parsing
342
- # of the config accessors. If the input token is not named as one of the
343
- # CONFIG_ACCESSORS, it will be processed normally.
344
- def parse_attr_accessor(context, single, tk, comment)
345
- case tk.name
346
- when 'config', 'config_attr'
347
- parse_config(context, single, tk, comment)
348
- else
349
- super
350
- end
351
- end
352
- end
353
- end
354
- end
355
- end
356
-
357
- # Register the TDoc generator (in case you want to actually use it).
358
- # method echos RDoc generator registration (see 'rdoc/rdoc' line 76)
359
- Generator = Struct.new(:file_name, :class_name, :key)
360
- RDoc::RDoc::GENERATORS['tdoc'] = Generator.new(
361
- "tap/support/tdoc/tdoc_html_generator.rb",
362
- "TDocHTMLGenerator".intern,
363
- "tdoc")
364
-
365
- # Add the extended accessors to context classes.
366
- module RDoc # :nodoc:
367
- class CodeObject # :nodoc:
368
- include Tap::Support::TDoc::CodeObjectAccess
369
- end
370
-
371
- class ClassModule # :nodoc:
372
- include Tap::Support::TDoc::ClassModuleAccess
373
- end
374
- end
375
-
376
- # Override methods in Options to in effect incorporate the accessor
377
- # flags for TDoc parsing. (see 'rdoc/options') Raise an error if an
378
- # accessor flag has already been specified.
379
- class Options # :nodoc:
380
- alias tdoc_original_parse parse
381
-
382
- def parse(argv, generators)
383
- tdoc_original_parse(argv, generators)
384
- return unless @generator_name == 'tdoc'
385
-
386
- accessors = Tap::Support::TDoc::ConfigParser::CONFIG_ACCESSORS
387
-
388
- # check the config_accessor_flags for accessor conflicts
389
- extra_accessor_flags.each_pair do |accessor, flag|
390
- if accessors.include?(accessor)
391
- raise OptionList.error("tdoc format already handles the accessor '#{accessor}'")
392
- end
393
- end
394
-
395
- # extra_accessors will be nil if no extra accessors were
396
- # specifed, otherwise it'll be a regexp like /^(...)$/
397
- # the string subset assumes
398
- # regexp.to_s # => /(?-mix:^(...)$)/
399
- @extra_accessors ||= /^()$/
400
- current_accessors_str = @extra_accessors.to_s[9..-4]
401
-
402
- # echos the Regexp production code in rdoc/options.rb
403
- # (see the parse method, line 501)
404
- re = '^(' + current_accessors_str + accessors.map{|a| Regexp.quote(a)}.join('|') + ')$'
405
- @extra_accessors = Regexp.new(re)
406
-
407
- RDoc::RubyParser.extend Tap::Support::TDoc::InitializeConfigParser
408
- end
409
- end