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,19 +0,0 @@
1
- module Tap
2
- module Support
3
- module Joins
4
-
5
- # A Fork join passes the results of source to each of the targets.
6
- class Fork < Join
7
- def join(source, targets)
8
- complete(source) do |_result|
9
- targets.each do |target|
10
- yield(_result) if block_given?
11
- enq(target, _result)
12
- end
13
- end
14
- end
15
- end
16
-
17
- end
18
- end
19
- end
@@ -1,22 +0,0 @@
1
- module Tap
2
- module Support
3
- module Joins
4
-
5
- # Merge (or simple merge) passes the results of each source to the
6
- # target without synchronization.
7
- class Merge < ReverseJoin
8
- def join(target, sources)
9
- sources.each do |source|
10
- # merging can use the existing audit trails... each distinct
11
- # input is getting sent to one place (the target)
12
- complete(source) do |_result|
13
- yield(_result) if block_given?
14
- enq(target, _result)
15
- end
16
- end
17
- end
18
- end
19
-
20
- end
21
- end
22
- end
@@ -1,21 +0,0 @@
1
- module Tap
2
- module Support
3
- module Joins
4
-
5
- # A Sequence join simply pass results from one task to the next.
6
- class Sequence < Join
7
- def join(source, targets)
8
- current_task = source
9
- targets.each do |next_task|
10
- complete(current_task) do |_result|
11
- yield(_result) if block_given?
12
- enq(next_task, _result)
13
- end
14
- current_task = next_task
15
- end
16
- end
17
- end
18
-
19
- end
20
- end
21
- end
@@ -1,45 +0,0 @@
1
- require 'tap/support/lazydoc'
2
-
3
- module Tap
4
- module Support
5
-
6
- # LazyAttributes adds methods to declare class-level accessors
7
- # for Lazydoc attributes. The source_file for the class must
8
- # be set manually.
9
- #
10
- # # ConstName::key value
11
- # class ConstName
12
- # extend LazyAttributes
13
- #
14
- # self.source_file = __FILE__
15
- # lazy_attr :key
16
- # end
17
- #
18
- # ConstName::key.subject # => 'value'
19
- #
20
- module LazyAttributes
21
-
22
- # The source_file for self. Must be set independently.
23
- attr_accessor :source_file
24
-
25
- # Returns the lazydoc for source_file
26
- def lazydoc(resolve=true)
27
- lazydoc = Lazydoc[source_file]
28
- lazydoc.resolve if resolve
29
- lazydoc
30
- end
31
-
32
- # Creates a lazy attribute accessor for the specified attribute.
33
- def lazy_attr(key, attribute=key)
34
- instance_eval %Q{
35
- def #{key}
36
- lazydoc[to_s]['#{attribute}'] ||= Lazydoc::Comment.new
37
- end
38
-
39
- def #{key}=(comment)
40
- Lazydoc[source_file][to_s]['#{attribute}'] = comment
41
- end}
42
- end
43
- end
44
- end
45
- end
@@ -1,386 +0,0 @@
1
- require 'tap/support/lazydoc/document'
2
-
3
- module Tap
4
- module Support
5
-
6
- # Lazydoc lazily pulls documentation out of source files and makes it
7
- # available through LazyAttributes. Lazydoc can find two types of
8
- # documentation, constant attributes and code comments. To illustrate,
9
- # consider the following:
10
- #
11
- # # Sample::key <value>
12
- # # This is the comment content. A content
13
- # # string can span multiple lines...
14
- # #
15
- # # code.is_allowed
16
- # # much.as_in RDoc
17
- # #
18
- # # and stops at the next non-comment
19
- # # line, the next constant attribute,
20
- # # or an end key
21
- # class Sample
22
- # extend Tap::Support::LazyAttributes
23
- # self.source_file = __FILE__
24
- #
25
- # lazy_attr :key
26
- #
27
- # # comment content for a code comment
28
- # # may similarly span multiple lines
29
- # def method_one
30
- # end
31
- # end
32
- #
33
- # When a lazy attribute is called, Lazydoc scans <tt>source_file</tt> for
34
- # the corresponding constant attribute and makes it available as a
35
- # Lazydoc::Comment.
36
- #
37
- # comment = Sample::key
38
- # comment.value
39
- # # => "<value>"
40
- #
41
- # comment.content
42
- # # => [
43
- # # ["This is the comment content. A content", "string can span multiple lines..."],
44
- # # [""],
45
- # # [" code.is_allowed"],
46
- # # [" much.as_in RDoc"],
47
- # # [""],
48
- # # ["and stops at the next non-comment", "line, the next constant attribute,", "or an end key"]]
49
- #
50
- # "\n#{'.' * 30}\n" + comment.wrap(30) + "\n#{'.' * 30}\n"
51
- # # => %q{
52
- # # ..............................
53
- # # This is the comment content.
54
- # # A content string can span
55
- # # multiple lines...
56
- # #
57
- # # code.is_allowed
58
- # # much.as_in RDoc
59
- # #
60
- # # and stops at the next
61
- # # non-comment line, the next
62
- # # constant attribute, or an end
63
- # # key
64
- # # ..............................
65
- # #}
66
- #
67
- # In addition, individual lines of code may be registered and resolved by Lazydoc:
68
- #
69
- # doc = Sample.lazydoc.reset
70
- # comment = doc.register(/method_one/)
71
- #
72
- # doc.resolve
73
- # comment.subject # => " def method_one"
74
- # comment.content # => [["comment content for a code comment", "may similarly span multiple lines"]]
75
- #
76
- # With these basics in mind, here are some details...
77
- #
78
- # === Constant Attributes
79
- # Constant attributes are like constants in Ruby, but with an extra 'key'
80
- # that must consist of only lowercase letters and/or underscores. For
81
- # example, these are constant attributes:
82
- #
83
- # # Const::Name::key
84
- # # Const::Name::key_with_underscores
85
- # # ::key
86
- #
87
- # While these are not:
88
- #
89
- # # Const::Name::Key
90
- # # Const::Name::key2
91
- # # Const::Name::k@y
92
- #
93
- # Lazydoc parses a Lazydoc::Comment for each constant attribute by using the
94
- # remainder of the line as a value (ie subject) and scanning down for content.
95
- # Scanning continues until a non-comment line, an end key, or a new attribute
96
- # is reached; the comment is then stored by constant name and key.
97
- #
98
- # str = %Q{
99
- # # Const::Name::key value for key
100
- # # comment for key
101
- # # parsed until a
102
- # # non-comment line
103
- #
104
- # # Const::Name::another value for another
105
- # # comment for another
106
- # # parsed to an end key
107
- # # Const::Name::another-
108
- # #
109
- # # ignored comment
110
- # }
111
- #
112
- # doc = Lazydoc::Document.new
113
- # doc.resolve(str)
114
- #
115
- # doc.to_hash {|comment| [comment.value, comment.to_s] }
116
- # # => {
117
- # # 'Const::Name' => {
118
- # # 'key' => ['value for key', 'comment for key parsed until a non-comment line'],
119
- # # 'another' => ['value for another', 'comment for another parsed to an end key']}
120
- # # }
121
- #
122
- # Constant attributes are only parsed from commented lines. To turn off
123
- # attribute parsing for a section of documentation, use start/stop keys:
124
- #
125
- # str = %Q{
126
- # Const::Name::not_parsed
127
- #
128
- # # :::-
129
- # # Const::Name::not_parsed
130
- # # :::+
131
- # # Const::Name::parsed value
132
- # }
133
- #
134
- # doc = Lazydoc::Document.new
135
- # doc.resolve(str)
136
- # doc.to_hash {|comment| comment.value } # => {'Const::Name' => {'parsed' => 'value'}}
137
- #
138
- # To hide attributes from RDoc, make use of the RDoc <tt>:startdoc:</tt>
139
- # document modifier like this (note that spaces are added to prevent RDoc
140
- # from hiding the example):
141
- #
142
- # # :start doc::Const::Name::one hidden in RDoc
143
- # # * This line is visible in RDoc.
144
- # # :start doc::Const::Name::one-
145
- # #
146
- # #--
147
- # # Const::Name::two
148
- # # You can hide attribute comments like this.
149
- # # Const::Name::two-
150
- # #++
151
- # #
152
- # # * This line is also visible in RDoc.
153
- #
154
- # Here is the same text, for comparison if you are reading this as RDoc:
155
- #
156
- # :startdoc::Const::Name::one hidden in RDoc
157
- # * This line is visible in RDoc.
158
- # :startdoc::Const::Name::one-
159
- #
160
- #--
161
- # Const::Name::two
162
- # You can hide attribute comments like this.
163
- # Const::Name::two-
164
- #++
165
- #
166
- # * This line is also visible in RDoc.
167
- #
168
- # As a side note, <tt>Const::Name::key</tt> is not a reference to the 'key'
169
- # constant (as that would be invalid). In *very* idiomatic ruby
170
- # <tt>Const::Name::key</tt> is equivalent to the method call
171
- # <tt>Const::Name.key</tt>.
172
- #
173
- # === Code Comments
174
- # Code comments are lines registered for parsing if and when a Lazydoc gets
175
- # resolved. Unlike constant attributes, the registered line is the comment
176
- # subject (ie value) and contents are parsed up from it (basically mimicking
177
- # the behavior of RDoc).
178
- #
179
- # str = %Q{
180
- # # comment lines for
181
- # # the method
182
- # def method
183
- # end
184
- #
185
- # # as in RDoc, the comment can be
186
- # # separated from the method
187
- #
188
- # def another_method
189
- # end
190
- # }
191
- #
192
- # doc = Lazydoc::Document.new
193
- # doc.register(3)
194
- # doc.register(9)
195
- # doc.resolve(str)
196
- #
197
- # doc.comments.collect {|comment| [comment.subject, comment.to_s] }
198
- # # => [
199
- # # ['def method', 'comment lines for the method'],
200
- # # ['def another_method', 'as in RDoc, the comment can be separated from the method']]
201
- #
202
- # Comments may be registered to specific line numbers, or with a Proc or
203
- # Regexp that will determine the line number during resolution. In the case
204
- # of a Regexp, the first matching line is used; Procs receive an array of
205
- # lines and should return the line number that should be used. See
206
- # Lazydoc::Comment#resolve for more details.
207
- #
208
- module Lazydoc
209
-
210
- # A regexp matching an attribute start or end. After a match:
211
- #
212
- # $1:: const_name
213
- # $3:: key
214
- # $4:: end flag
215
- #
216
- ATTRIBUTE_REGEXP = /([A-Z][A-z]*(::[A-Z][A-z]*)*)?::([a-z_]+)(-?)/
217
-
218
- # A regexp matching constants from the ATTRIBUTE_REGEXP leader
219
- CONSTANT_REGEXP = /#.*?([A-Z][A-z]*(::[A-Z][A-z]*)*)?$/
220
-
221
- # A regexp matching a caller line, to extract the calling file
222
- # and line number. After a match:
223
- #
224
- # $1:: file
225
- # $3:: line number (as a string, obviously)
226
- #
227
- # Note that line numbers in caller start at 1, not 0.
228
- CALLER_REGEXP = /^(([A-z]:)?[^:]+):(\d+)/
229
-
230
- module_function
231
-
232
- # A hash of (source_file, lazydoc) pairs tracking the
233
- # Lazydoc instance for the given source file.
234
- def registry
235
- @registry ||= []
236
- end
237
-
238
- # Returns the lazydoc in registry for the specified source file.
239
- # If no such lazydoc exists, one will be created for it.
240
- def [](source_file)
241
- source_file = File.expand_path(source_file.to_s)
242
- lazydoc = registry.find {|doc| doc.source_file == source_file }
243
- if lazydoc == nil
244
- lazydoc = Document.new(source_file)
245
- registry << lazydoc
246
- end
247
- lazydoc
248
- end
249
-
250
- # Register the specified line numbers to the lazydoc for source_file.
251
- # Returns a comment_class instance corresponding to the line.
252
- def register(source_file, line_number, comment_class=Comment)
253
- Lazydoc[source_file].register(line_number, comment_class)
254
- end
255
-
256
- # Resolves all lazydocs which include the specified code comments.
257
- def resolve_comments(comments)
258
- registry.each do |doc|
259
- next if (comments & doc.comments).empty?
260
- doc.resolve
261
- end
262
- end
263
-
264
- # Scans the specified file for attributes keyed by key and stores
265
- # the resulting comments in the source_file lazydoc. Returns the
266
- # lazydoc.
267
- def scan_doc(source_file, key)
268
- lazydoc = nil
269
- scan(File.read(source_file), key) do |const_name, attr_key, comment|
270
- lazydoc = self[source_file] unless lazydoc
271
- lazydoc[const_name][attr_key] = comment
272
- end
273
- lazydoc
274
- end
275
-
276
- # Scans the string or StringScanner for attributes matching the key
277
- # (keys may be patterns, they are incorporated into a regexp). Yields
278
- # each (const_name, key, value) triplet to the mandatory block and
279
- # skips regions delimited by the stop and start keys <tt>:-</tt>
280
- # and <tt>:+</tt>.
281
- #
282
- # str = %Q{
283
- # # Const::Name::key value
284
- # # ::alt alt_value
285
- # #
286
- # # Ignored::Attribute::not_matched value
287
- # # :::-
288
- # # Also::Ignored::key value
289
- # # :::+
290
- # # Another::key another value
291
- #
292
- # Ignored::key value
293
- # }
294
- #
295
- # results = []
296
- # Lazydoc.scan(str, 'key|alt') do |const_name, key, value|
297
- # results << [const_name, key, value]
298
- # end
299
- #
300
- # results
301
- # # => [
302
- # # ['Const::Name', 'key', 'value'],
303
- # # ['', 'alt', 'alt_value'],
304
- # # ['Another', 'key', 'another value']]
305
- #
306
- # Returns the StringScanner used during scanning.
307
- def scan(str, key) # :yields: const_name, key, value
308
- scanner = case str
309
- when StringScanner then str
310
- when String then StringScanner.new(str)
311
- else raise TypeError, "can't convert #{str.class} into StringScanner or String"
312
- end
313
-
314
- regexp = /^(.*?)::(:-|#{key})/
315
- while !scanner.eos?
316
- break if scanner.skip_until(regexp) == nil
317
-
318
- if scanner[2] == ":-"
319
- scanner.skip_until(/:::\+/)
320
- else
321
- next unless scanner[1] =~ CONSTANT_REGEXP
322
- key = scanner[2]
323
- yield($1.to_s, key, scanner.matched.strip) if scanner.scan(/[ \r\t].*$|$/)
324
- end
325
- end
326
-
327
- scanner
328
- end
329
-
330
- # Parses constant attributes from the string or StringScanner. Yields
331
- # each (const_name, key, comment) triplet to the mandatory block
332
- # and skips regions delimited by the stop and start keys <tt>:-</tt>
333
- # and <tt>:+</tt>.
334
- #
335
- # str = %Q{
336
- # # Const::Name::key subject for key
337
- # # comment for key
338
- #
339
- # # :::-
340
- # # Ignored::key value
341
- # # :::+
342
- #
343
- # # Ignored text before attribute ::another subject for another
344
- # # comment for another
345
- # }
346
- #
347
- # results = []
348
- # Lazydoc.parse(str) do |const_name, key, comment|
349
- # results << [const_name, key, comment.subject, comment.to_s]
350
- # end
351
- #
352
- # results
353
- # # => [
354
- # # ['Const::Name', 'key', 'subject for key', 'comment for key'],
355
- # # ['', 'another', 'subject for another', 'comment for another']]
356
- #
357
- # Returns the StringScanner used during scanning.
358
- def parse(str) # :yields: const_name, key, comment
359
- scanner = case str
360
- when StringScanner then str
361
- when String then StringScanner.new(str)
362
- else raise TypeError, "can't convert #{str.class} into StringScanner or String"
363
- end
364
-
365
- scan(scanner, '[a-z_]+') do |const_name, key, value|
366
- comment = Comment.parse(scanner, false) do |line|
367
- if line =~ ATTRIBUTE_REGEXP
368
- # rewind to capture the next attribute unless an end is specified.
369
- scanner.unscan unless $4 == '-' && $3 == key && $1.to_s == const_name
370
- true
371
- else false
372
- end
373
- end
374
- comment.subject = value
375
- yield(const_name, key, comment)
376
- end
377
- end
378
-
379
- def usage(path, cols=80)
380
- scanner = StringScanner.new(File.read(path))
381
- scanner.scan(/^#!.*?$/)
382
- Comment.parse(scanner, false).wrap(cols, 2).strip
383
- end
384
- end
385
- end
386
- end