bahuvrihi-tap 0.10.4 → 0.10.5
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rap +112 -0
- data/bin/tap +21 -10
- data/cmd/destroy.rb +1 -1
- data/cmd/generate.rb +1 -1
- data/cmd/run.rb +4 -48
- data/cmd/server.rb +3 -1
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/env.rb +37 -39
- data/lib/tap/exe.rb +59 -29
- data/lib/tap/generator/base.rb +1 -1
- data/lib/tap/generator/generators/config/templates/doc.erb +1 -1
- data/lib/tap/generator/generators/file_task/templates/test.erb +1 -1
- data/lib/tap/generator/generators/root/templates/README +0 -0
- data/lib/tap/generator/generators/root/templates/gemspec +3 -4
- data/lib/tap/generator/generators/root/templates/tapfile +3 -3
- data/lib/tap/parser.rb +35 -0
- data/lib/tap/patches/optparse/summarize.rb +62 -0
- data/lib/tap/root.rb +24 -18
- data/lib/tap/support/class_configuration.rb +1 -1
- data/lib/tap/support/configurable_class.rb +3 -1
- data/lib/tap/support/configuration.rb +19 -0
- data/lib/tap/support/constant.rb +14 -2
- data/lib/tap/support/declarations.rb +33 -39
- data/lib/tap/support/dependable.rb +21 -2
- data/lib/tap/support/gems.rb +4 -30
- data/lib/tap/support/gems/rack.rb +14 -11
- data/lib/tap/support/lazy_attributes.rb +1 -1
- data/lib/tap/support/lazydoc.rb +257 -340
- data/lib/tap/support/lazydoc/comment.rb +499 -0
- data/lib/tap/support/lazydoc/config.rb +17 -0
- data/lib/tap/support/lazydoc/declaration.rb +20 -0
- data/lib/tap/support/lazydoc/document.rb +118 -0
- data/lib/tap/support/lazydoc/method.rb +24 -0
- data/lib/tap/support/manifest.rb +33 -4
- data/lib/tap/support/validation.rb +56 -0
- data/lib/tap/task.rb +46 -44
- data/lib/tap/tasks/dump.rb +15 -10
- data/lib/tap/tasks/load.rb +25 -0
- data/lib/tap/tasks/rake.rb +2 -2
- data/lib/tap/test.rb +55 -36
- data/lib/tap/test/file_methods.rb +204 -178
- data/lib/tap/test/file_methods_class.rb +4 -18
- data/lib/tap/test/script_methods.rb +76 -90
- data/lib/tap/test/script_methods/regexp_escape.rb +92 -0
- data/lib/tap/test/script_methods/script_test.rb +4 -2
- data/lib/tap/test/subset_methods.rb +46 -49
- data/lib/tap/test/subset_methods_class.rb +17 -54
- data/lib/tap/test/tap_methods.rb +1 -5
- data/lib/tap/test/utils.rb +142 -32
- metadata +12 -3
- data/lib/tap/support/command_line.rb +0 -55
- data/lib/tap/support/comment.rb +0 -270
@@ -0,0 +1,17 @@
|
|
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
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Tap
|
2
|
+
module Support
|
3
|
+
module Lazydoc
|
4
|
+
class Declaration < Comment
|
5
|
+
def resolve(lines)
|
6
|
+
super
|
7
|
+
|
8
|
+
@subject = case
|
9
|
+
when content.empty? || content[0][0].to_s !~ /^::desc(.*)/ then ""
|
10
|
+
else
|
11
|
+
content[0].shift
|
12
|
+
$1.strip
|
13
|
+
end
|
14
|
+
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'tap/support/lazydoc/comment'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Support
|
5
|
+
module Lazydoc
|
6
|
+
class Document
|
7
|
+
# The source file for self, used during resolve.
|
8
|
+
attr_reader :source_file
|
9
|
+
|
10
|
+
# An array of Comment objects identifying lines
|
11
|
+
# resolved or to-be-resolved for self.
|
12
|
+
attr_reader :comments
|
13
|
+
|
14
|
+
# A hash of (const_name, attributes) pairs tracking the constant
|
15
|
+
# attributes resolved or to-be-resolved for self. Attributes
|
16
|
+
# are hashes of (key, comment) pairs.
|
17
|
+
attr_reader :const_attrs
|
18
|
+
|
19
|
+
# The default constant name used when no constant name
|
20
|
+
# is specified for a constant attribute.
|
21
|
+
attr_reader :default_const_name
|
22
|
+
|
23
|
+
# Flag indicating whether or not self has been resolved.
|
24
|
+
attr_accessor :resolved
|
25
|
+
|
26
|
+
def initialize(source_file=nil, default_const_name='')
|
27
|
+
self.source_file = source_file
|
28
|
+
@default_const_name = default_const_name
|
29
|
+
@comments = []
|
30
|
+
@const_attrs = {}
|
31
|
+
@resolved = false
|
32
|
+
self.reset
|
33
|
+
end
|
34
|
+
|
35
|
+
# Resets self by clearing const_attrs, comments, and setting
|
36
|
+
# resolved to false. Generally NOT recommended as this
|
37
|
+
# clears any work you've done registering lines; to simply
|
38
|
+
# allow resolve to re-scan a document, manually set
|
39
|
+
# resolved to false.
|
40
|
+
def reset
|
41
|
+
@const_attrs.clear
|
42
|
+
@comments.clear
|
43
|
+
@resolved = false
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sets the source file for self. Expands the source file path if necessary.
|
48
|
+
def source_file=(source_file)
|
49
|
+
@source_file = source_file == nil ? nil : File.expand_path(source_file)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Sets the default_const_name for self. Any const_attrs assigned to
|
53
|
+
# the previous default_const_name will be removed from const_attrs
|
54
|
+
# and merged with any const_attrs already assigned to the new
|
55
|
+
# default_const_name.
|
56
|
+
def default_const_name=(const_name)
|
57
|
+
self[const_name].merge!(const_attrs.delete(@default_const_name) || {})
|
58
|
+
@default_const_name = const_name
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns the attributes for the specified const_name.
|
62
|
+
def [](const_name)
|
63
|
+
const_attrs[const_name] ||= {}
|
64
|
+
end
|
65
|
+
|
66
|
+
# Register the specified line number to self. Returns a
|
67
|
+
# comment_class instance corresponding to the line.
|
68
|
+
def register(line_number, comment_class=Comment)
|
69
|
+
comment = comments.find {|c| c.class == comment_class && c.line_number == line_number }
|
70
|
+
|
71
|
+
if comment == nil
|
72
|
+
comment = comment_class.new(line_number)
|
73
|
+
comments << comment
|
74
|
+
end
|
75
|
+
|
76
|
+
comment
|
77
|
+
end
|
78
|
+
|
79
|
+
def register_method(method, comment_class=Comment)
|
80
|
+
register(/^\s*def\s+#{method}(\W|$)/, comment_class)
|
81
|
+
end
|
82
|
+
|
83
|
+
def resolve(str=nil)
|
84
|
+
return(false) if resolved
|
85
|
+
|
86
|
+
str = File.read(source_file) if str == nil
|
87
|
+
Lazydoc.parse(str) do |const_name, key, comment|
|
88
|
+
const_name = default_const_name if const_name.empty?
|
89
|
+
self[const_name][key] = comment
|
90
|
+
end
|
91
|
+
|
92
|
+
unless comments.empty?
|
93
|
+
lines = str.split(/\r?\n/)
|
94
|
+
comments.each do |comment|
|
95
|
+
comment.resolve(lines)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
@resolved = true
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_hash
|
103
|
+
const_hash = {}
|
104
|
+
const_attrs.each_pair do |const_name, attributes|
|
105
|
+
next if attributes.empty?
|
106
|
+
|
107
|
+
attr_hash = {}
|
108
|
+
attributes.each_pair do |key, comment|
|
109
|
+
attr_hash[key] = (block_given? ? yield(comment) : comment)
|
110
|
+
end
|
111
|
+
const_hash[const_name] = attr_hash
|
112
|
+
end
|
113
|
+
const_hash
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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
|
data/lib/tap/support/manifest.rb
CHANGED
@@ -40,6 +40,8 @@ module Tap
|
|
40
40
|
entries.empty?
|
41
41
|
end
|
42
42
|
|
43
|
+
# Sets the search_paths for self. Setting search_paths
|
44
|
+
# clears all entries and puts search_path_index to zero.
|
43
45
|
def search_paths=(search_paths)
|
44
46
|
@entries = []
|
45
47
|
@search_paths = search_paths
|
@@ -94,9 +96,9 @@ module Tap
|
|
94
96
|
new_entry
|
95
97
|
end
|
96
98
|
|
97
|
-
# Iterates over each (key, value) entry in self, dynamically
|
98
|
-
# from search_paths if necessary. New
|
99
|
-
# method.
|
99
|
+
# Iterates over each (key, value) entry in self, dynamically
|
100
|
+
# identifying entries from search_paths if necessary. New
|
101
|
+
# entries are identifed using the each_for method.
|
100
102
|
def each
|
101
103
|
entries.each do |key, path|
|
102
104
|
yield(key, path)
|
@@ -134,7 +136,34 @@ module Tap
|
|
134
136
|
entries.collect {|path, value| [hash[path], value] }
|
135
137
|
end
|
136
138
|
|
137
|
-
|
139
|
+
# Returns the first [key, value] entry where the key mini-matches
|
140
|
+
# the input pattern, or nil if no matching entry is found. This
|
141
|
+
# method identifies new entries as in each, as needed.
|
142
|
+
#
|
143
|
+
# See Tap::Root.minimal_match? for details on mini-matching.
|
144
|
+
def [](pattern)
|
145
|
+
each do |key, value|
|
146
|
+
return [key, value] if Root.minimal_match?(key, pattern)
|
147
|
+
end
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
|
151
|
+
def inspect
|
152
|
+
lines = ["", "search paths:"]
|
153
|
+
search_paths.each_with_index do |path, index|
|
154
|
+
indent = (index == search_path_index ? "* " : " ")
|
155
|
+
lines << (indent + path.inspect)
|
156
|
+
end
|
157
|
+
|
158
|
+
lines << ""
|
159
|
+
lines << "mini-entries:"
|
160
|
+
minimize.each do |mini, value|
|
161
|
+
lines << " #{mini}: #{value.inspect}"
|
162
|
+
end
|
163
|
+
lines << ""
|
164
|
+
|
165
|
+
"#{self.class}:#{object_id} #{lines.join("\n")}"
|
166
|
+
end
|
138
167
|
|
139
168
|
# Raised when multiple paths are assigned to the same manifest key.
|
140
169
|
class ManifestConflict < StandardError
|
@@ -405,6 +405,62 @@ module Tap
|
|
405
405
|
end
|
406
406
|
RANGE_OR_NIL = range_or_nil_block
|
407
407
|
|
408
|
+
# Returns a block that checks the input is a Time. String inputs are
|
409
|
+
# loaded using Time.parse and then converted into times. Parsed times
|
410
|
+
# are local unless specified otherwise.
|
411
|
+
#
|
412
|
+
# time.class # => Proc
|
413
|
+
#
|
414
|
+
# now = Time.now
|
415
|
+
# time.call(now) # => now
|
416
|
+
#
|
417
|
+
# time.call('2008-08-08 20:00:00.00 +08:00').getutc.strftime('%Y/%m/%d %H:%M:%S')
|
418
|
+
# # => '2008/08/08 12:00:00'
|
419
|
+
#
|
420
|
+
# time.call('2008-08-08').strftime('%Y/%m/%d %H:%M:%S')
|
421
|
+
# # => '2008/08/08 00:00:00'
|
422
|
+
#
|
423
|
+
# time.call(1) # => ValidationError
|
424
|
+
# time.call(nil) # => ValidationError
|
425
|
+
#
|
426
|
+
# Warning: Time.parse will parse a valid time (Time.now)
|
427
|
+
# even when no time is specified:
|
428
|
+
#
|
429
|
+
# time.call('str').strftime('%Y/%m/%d %H:%M:%S')
|
430
|
+
# # => Time.now.strftime('%Y/%m/%d %H:%M:%S')
|
431
|
+
#
|
432
|
+
def time()
|
433
|
+
# adding this here is a compromise to lazy-load the parse
|
434
|
+
# method (autoload doesn't work since Time already exists)
|
435
|
+
require 'time' unless Time.respond_to?(:parse)
|
436
|
+
TIME
|
437
|
+
end
|
438
|
+
|
439
|
+
TIME = lambda do |input|
|
440
|
+
input = Time.parse(input) if input.kind_of?(String)
|
441
|
+
validate(input, [Time])
|
442
|
+
end
|
443
|
+
|
444
|
+
# Same as time but allows nil:
|
445
|
+
#
|
446
|
+
# time_or_nil.call('~') # => nil
|
447
|
+
# time_or_nil.call(nil) # => nil
|
448
|
+
def time_or_nil()
|
449
|
+
# adding this check is a compromise to autoload the parse
|
450
|
+
# method (autoload doesn't work since Time already exists)
|
451
|
+
require 'time' unless Time.respond_to?(:parse)
|
452
|
+
TIME_OR_NIL
|
453
|
+
end
|
454
|
+
|
455
|
+
TIME_OR_NIL = lambda do |input|
|
456
|
+
input = case input
|
457
|
+
when nil, '~' then nil
|
458
|
+
when String then Time.parse(input)
|
459
|
+
else input
|
460
|
+
end
|
461
|
+
|
462
|
+
validate(input, [Time, nil])
|
463
|
+
end
|
408
464
|
end
|
409
465
|
end
|
410
466
|
end
|
data/lib/tap/task.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'tap/support/batchable'
|
2
2
|
require 'tap/support/executable'
|
3
|
-
require 'tap/support/
|
3
|
+
require 'tap/support/lazydoc/method'
|
4
|
+
autoload(:OptionParser, 'optparse')
|
4
5
|
|
5
6
|
module Tap
|
6
7
|
|
@@ -214,52 +215,32 @@ module Tap
|
|
214
215
|
subclass.define_configurations(configs)
|
215
216
|
subclass.define_dependencies(dependencies)
|
216
217
|
subclass.define_process(block) if block_given?
|
217
|
-
|
218
|
-
#
|
219
|
-
# Register documentation
|
220
|
-
#
|
221
|
-
const_name = subclass.to_s
|
222
|
-
caller.each_with_index do |line, index|
|
223
|
-
case line
|
224
|
-
when /\/tap\/support\/declarations.rb/ then next
|
225
|
-
when Support::Lazydoc::CALLER_REGEXP
|
226
|
-
subclass.source_file = File.expand_path($1)
|
227
|
-
lzd = subclass.lazydoc(false)
|
228
|
-
lzd[const_name, false]['manifest'] = lzd.register($3.to_i - 1)
|
229
|
-
break
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
arity = options[:arity] || (block_given? ? block.arity : -1)
|
234
|
-
comment = Support::Comment.new
|
235
|
-
comment.subject = case
|
236
|
-
when arity > 0
|
237
|
-
Array.new(arity, "INPUT").join(' ')
|
238
|
-
when arity < 0
|
239
|
-
array = Array.new(-1 * arity - 1, "INPUT")
|
240
|
-
array << "INPUTS..."
|
241
|
-
array.join(' ')
|
242
|
-
else ""
|
243
|
-
end
|
244
|
-
subclass.lazydoc(false)[const_name, false]['args'] ||= comment
|
245
|
-
|
246
|
-
subclass.default_name = const_name.underscore
|
218
|
+
subclass.default_name = subclass.to_s.underscore
|
247
219
|
subclass
|
248
220
|
end
|
249
221
|
|
250
|
-
|
222
|
+
# Parses the argv into an instance of self and an array of arguments (implicitly
|
223
|
+
# to be enqued to the instance and run by app). Yields a help string to the
|
224
|
+
# block when the argv indicates 'help'.
|
225
|
+
#
|
226
|
+
def parse(argv=ARGV, app=Tap::App.instance, &block) # :yields: help_str
|
227
|
+
parse!(argv.dup, &block)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Same as parse, but removes switches destructively.
|
231
|
+
def parse!(argv=ARGV, app=Tap::App.instance) # :yields: help_str
|
251
232
|
opts = OptionParser.new
|
252
233
|
|
253
234
|
# Add configurations
|
254
|
-
|
235
|
+
argv_config = {}
|
255
236
|
unless configurations.empty?
|
256
237
|
opts.separator ""
|
257
238
|
opts.separator "configurations:"
|
258
239
|
end
|
259
240
|
|
260
|
-
configurations.each do |receiver, key,
|
261
|
-
opts.on(*
|
262
|
-
|
241
|
+
configurations.each do |receiver, key, config|
|
242
|
+
opts.on(*config.to_optparse_argv) do |value|
|
243
|
+
argv_config[key] = value
|
263
244
|
end
|
264
245
|
end
|
265
246
|
|
@@ -269,8 +250,12 @@ module Tap
|
|
269
250
|
|
270
251
|
opts.on_tail("-h", "--help", "Print this help") do
|
271
252
|
opts.banner = "#{help}usage: tap run -- #{to_s.underscore} #{args.subject}"
|
272
|
-
|
273
|
-
|
253
|
+
if block_given?
|
254
|
+
yield(opts.to_s)
|
255
|
+
else
|
256
|
+
puts opts
|
257
|
+
exit
|
258
|
+
end
|
274
259
|
end
|
275
260
|
|
276
261
|
# Add option for name
|
@@ -295,26 +280,42 @@ module Tap
|
|
295
280
|
use_args << obj
|
296
281
|
end
|
297
282
|
end
|
298
|
-
|
283
|
+
|
284
|
+
# parse the argv
|
299
285
|
opts.parse!(argv)
|
286
|
+
|
287
|
+
# build and reconfigure the instance and any associated
|
288
|
+
# batch objects as specified in the file configurations
|
300
289
|
obj = new({}, name, app)
|
301
|
-
|
302
290
|
path_configs = load_config(app.config_filepath(name))
|
303
291
|
if path_configs.kind_of?(Array)
|
304
292
|
path_configs.each_with_index do |path_config, i|
|
305
|
-
|
293
|
+
next if i == 0
|
294
|
+
batch_obj = obj.initialize_batch_obj(path_config, "#{name}_#{i}")
|
295
|
+
batch_obj.reconfigure(argv_config)
|
306
296
|
end
|
307
297
|
path_configs = path_configs[0]
|
308
298
|
end
|
309
|
-
|
299
|
+
obj.reconfigure(path_configs).reconfigure(argv_config)
|
300
|
+
|
301
|
+
# recollect arguments
|
310
302
|
argv = (argv + use_args).collect {|str| str =~ /\A---\s*\n/ ? YAML.load(str) : str }
|
311
303
|
|
312
|
-
[obj
|
304
|
+
[obj, argv]
|
305
|
+
end
|
306
|
+
|
307
|
+
def execute(argv=ARGV)
|
308
|
+
instance, args = parse(ARGV) do |help|
|
309
|
+
puts help
|
310
|
+
exit
|
311
|
+
end
|
312
|
+
|
313
|
+
instance.execute(*args)
|
313
314
|
end
|
314
315
|
|
315
316
|
def lazydoc(resolve=true)
|
316
317
|
lazydoc = super(false)
|
317
|
-
lazydoc.
|
318
|
+
lazydoc[self.to_s]['args'] ||= lazydoc.register_method(:process, Support::Lazydoc::Method)
|
318
319
|
super
|
319
320
|
end
|
320
321
|
|
@@ -615,5 +616,6 @@ module Tap
|
|
615
616
|
raise ArgumentError, "config '#{name}' is not a hash" unless configs.kind_of?(Hash)
|
616
617
|
klass.new(configs, name, &block)
|
617
618
|
end
|
619
|
+
|
618
620
|
end
|
619
621
|
end
|