tap 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History +37 -30
- data/MIT-LICENSE +1 -1
- data/README +92 -44
- data/bin/tap +62 -75
- data/cmd/console.rb +42 -0
- data/cmd/destroy.rb +16 -0
- data/cmd/generate.rb +16 -0
- data/cmd/run.rb +126 -0
- data/doc/Class Reference +362 -0
- data/doc/Command Reference +153 -0
- data/doc/Tutorial +237 -0
- data/lib/tap.rb +6 -45
- data/lib/tap/app.rb +126 -500
- data/lib/tap/constants.rb +2 -29
- data/lib/tap/env.rb +555 -250
- data/lib/tap/file_task.rb +60 -103
- data/lib/tap/generator/base.rb +109 -0
- data/lib/tap/generator/destroy.rb +37 -0
- data/lib/tap/generator/generate.rb +61 -0
- data/lib/tap/generator/generators/command/command_generator.rb +16 -12
- data/lib/tap/generator/generators/command/templates/command.erb +13 -19
- data/lib/tap/generator/generators/config/config_generator.rb +18 -27
- data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
- data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -11
- data/lib/tap/generator/generators/file_task/templates/file.txt +11 -2
- data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
- data/lib/tap/generator/generators/file_task/templates/task.erb +24 -31
- data/lib/tap/generator/generators/file_task/templates/test.erb +18 -22
- data/lib/tap/generator/generators/root/root_generator.rb +45 -31
- data/lib/tap/generator/generators/root/templates/Rakefile +64 -41
- data/lib/tap/generator/generators/root/templates/gemspec +27 -0
- data/lib/tap/generator/generators/root/templates/tapfile +8 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
- data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
- data/lib/tap/generator/generators/task/task_generator.rb +21 -28
- data/lib/tap/generator/generators/task/templates/task.erb +13 -23
- data/lib/tap/generator/generators/task/templates/test.erb +15 -18
- data/lib/tap/generator/manifest.rb +14 -0
- data/lib/tap/patches/rake/rake_test_loader.rb +0 -0
- data/lib/tap/patches/rake/testtask.rb +0 -0
- data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -0
- data/lib/tap/patches/ruby19/parsedate.rb +0 -0
- data/lib/tap/root.rb +260 -21
- data/lib/tap/support/aggregator.rb +11 -11
- data/lib/tap/support/assignments.rb +172 -0
- data/lib/tap/support/audit.rb +20 -18
- data/lib/tap/support/batchable.rb +21 -10
- data/lib/tap/support/batchable_class.rb +107 -0
- data/lib/tap/support/class_configuration.rb +154 -239
- data/lib/tap/support/command_line.rb +97 -102
- data/lib/tap/support/comment.rb +270 -0
- data/lib/tap/support/configurable.rb +86 -65
- data/lib/tap/support/configurable_class.rb +296 -0
- data/lib/tap/support/configuration.rb +122 -0
- data/lib/tap/support/constant.rb +70 -0
- data/lib/tap/support/constant_utils.rb +127 -0
- data/lib/tap/support/declarations.rb +111 -0
- data/lib/tap/support/executable.rb +30 -17
- data/lib/tap/support/executable_queue.rb +0 -0
- data/lib/tap/support/framework.rb +71 -0
- data/lib/tap/support/framework_class.rb +199 -0
- data/lib/tap/support/instance_configuration.rb +147 -0
- data/lib/tap/support/lazydoc.rb +428 -0
- data/lib/tap/support/manifest.rb +89 -0
- data/lib/tap/support/run_error.rb +0 -0
- data/lib/tap/support/shell_utils.rb +33 -9
- data/lib/tap/support/summary.rb +30 -0
- data/lib/tap/support/tdoc.rb +339 -134
- data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -0
- data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -0
- data/lib/tap/support/templater.rb +180 -0
- data/lib/tap/support/validation.rb +409 -76
- data/lib/tap/support/versions.rb +5 -3
- data/lib/tap/task.rb +78 -174
- data/lib/tap/tasks/dump.rb +56 -0
- data/lib/tap/tasks/rake.rb +93 -0
- data/lib/tap/test.rb +3 -3
- data/lib/tap/test/env_vars.rb +2 -2
- data/lib/tap/test/file_methods.rb +19 -20
- data/lib/tap/test/script_methods.rb +144 -0
- data/lib/tap/test/subset_methods.rb +1 -1
- data/lib/tap/test/tap_methods.rb +28 -62
- data/lib/tap/workflow.rb +22 -39
- metadata +48 -179
- data/Basic Overview +0 -151
- data/Command Reference +0 -99
- data/Rakefile +0 -127
- data/Tutorial +0 -287
- data/lib/tap/cmd/console.rb +0 -31
- data/lib/tap/cmd/destroy.rb +0 -20
- data/lib/tap/cmd/generate.rb +0 -20
- data/lib/tap/cmd/run.rb +0 -151
- data/lib/tap/dump.rb +0 -57
- data/lib/tap/generator.rb +0 -91
- data/lib/tap/generator/generators/command/USAGE +0 -6
- data/lib/tap/generator/generators/config/USAGE +0 -21
- data/lib/tap/generator/generators/config/templates/config.erb +0 -1
- data/lib/tap/generator/generators/file_task/USAGE +0 -3
- data/lib/tap/generator/generators/file_task/templates/file.yml +0 -3
- data/lib/tap/generator/generators/generator/USAGE +0 -0
- data/lib/tap/generator/generators/generator/generator_generator.rb +0 -21
- data/lib/tap/generator/generators/generator/templates/generator.erb +0 -32
- data/lib/tap/generator/generators/generator/templates/usage.erb +0 -1
- data/lib/tap/generator/generators/root/USAGE +0 -0
- data/lib/tap/generator/generators/root/templates/ReadMe.txt +0 -0
- data/lib/tap/generator/generators/root/templates/tap.yml +0 -80
- data/lib/tap/generator/generators/task/USAGE +0 -3
- data/lib/tap/generator/generators/workflow/USAGE +0 -0
- data/lib/tap/generator/generators/workflow/templates/task.erb +0 -16
- data/lib/tap/generator/generators/workflow/templates/test.erb +0 -7
- data/lib/tap/generator/generators/workflow/workflow_generator.rb +0 -6
- data/lib/tap/generator/options.rb +0 -26
- data/lib/tap/generator/usage.rb +0 -26
- data/lib/tap/support/batchable_methods.rb +0 -34
- data/lib/tap/support/command_line_methods.rb +0 -76
- data/lib/tap/support/configurable_methods.rb +0 -224
- data/lib/tap/support/logger.rb +0 -88
- data/lib/tap/support/rake.rb +0 -43
- data/lib/tap/support/tdoc/config_attr.rb +0 -362
- data/test/app/config/another/task.yml +0 -1
- data/test/app/config/batch.yml +0 -2
- data/test/app/config/empty.yml +0 -0
- data/test/app/config/erb.yml +0 -2
- data/test/app/config/some/task.yml +0 -1
- data/test/app/config/template.yml +0 -2
- data/test/app/config/version-0.1.yml +0 -1
- data/test/app/config/version.yml +0 -1
- data/test/app/lib/app_test_task.rb +0 -3
- data/test/app_test.rb +0 -1849
- data/test/env/test_configure/recurse_a.yml +0 -2
- data/test/env/test_configure/recurse_b.yml +0 -2
- data/test/env/test_configure/tap.yml +0 -23
- data/test/env/test_load_env_config/dir/tap.yml +0 -3
- data/test/env/test_load_env_config/recurse_a.yml +0 -2
- data/test/env/test_load_env_config/recurse_b.yml +0 -2
- data/test/env/test_load_env_config/tap.yml +0 -3
- data/test/env_test.rb +0 -198
- data/test/file_task/config/batch.yml +0 -2
- data/test/file_task/config/configured.yml +0 -1
- data/test/file_task/old_file_one.txt +0 -0
- data/test/file_task/old_file_two.txt +0 -0
- data/test/file_task_test.rb +0 -1291
- data/test/root/alt_lib/alt_module.rb +0 -4
- data/test/root/file.txt +0 -0
- data/test/root/glob/one.txt +0 -0
- data/test/root/glob/two.txt +0 -0
- data/test/root/lib/absolute_alt_filepath.rb +0 -2
- data/test/root/lib/alternative_filepath.rb +0 -2
- data/test/root/lib/another_module.rb +0 -2
- data/test/root/lib/nested/some_module.rb +0 -4
- data/test/root/lib/no_module_included.rb +0 -0
- data/test/root/lib/some/module.rb +0 -4
- data/test/root/lib/some_class.rb +0 -2
- data/test/root/lib/some_module.rb +0 -3
- data/test/root/load_path/load_path_module.rb +0 -2
- data/test/root/load_path/skip_module.rb +0 -2
- data/test/root/mtime/older.txt +0 -0
- data/test/root/unload/full_path.rb +0 -2
- data/test/root/unload/loaded_by_nested.rb +0 -2
- data/test/root/unload/nested/nested_load.rb +0 -6
- data/test/root/unload/nested/nested_with_ext.rb +0 -4
- data/test/root/unload/nested/relative_path.rb +0 -4
- data/test/root/unload/older.rb +0 -2
- data/test/root/unload/unload_base.rb +0 -9
- data/test/root/versions/another.yml +0 -0
- data/test/root/versions/file-0.1.2.yml +0 -0
- data/test/root/versions/file-0.1.yml +0 -0
- data/test/root/versions/file.yml +0 -0
- data/test/root_test.rb +0 -718
- data/test/support/aggregator_test.rb +0 -99
- data/test/support/audit_test.rb +0 -445
- data/test/support/batchable_test.rb +0 -74
- data/test/support/class_configuration_test.rb +0 -331
- data/test/support/command_line_test.rb +0 -58
- data/test/support/configurable/config/configured.yml +0 -2
- data/test/support/configurable_test.rb +0 -295
- data/test/support/executable_queue_test.rb +0 -103
- data/test/support/executable_test.rb +0 -38
- data/test/support/logger_test.rb +0 -31
- data/test/support/rake_test.rb +0 -37
- data/test/support/shell_utils_test.rb +0 -24
- data/test/support/tdoc_test.rb +0 -370
- data/test/support/validation_test.rb +0 -54
- data/test/support/versions_test.rb +0 -103
- data/test/tap_test_helper.rb +0 -57
- data/test/tap_test_suite.rb +0 -7
- data/test/task/config/batch.yml +0 -2
- data/test/task/config/batched.yml +0 -2
- data/test/task/config/configured.yml +0 -1
- data/test/task/config/example.yml +0 -1
- data/test/task_base_test.rb +0 -24
- data/test/task_syntax_test.rb +0 -300
- data/test/task_test.rb +0 -320
- data/test/test/env_vars_test.rb +0 -48
- data/test/test/file_methods/test_assert_files/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files/expected/two.txt +0 -1
- data/test/test/file_methods/test_assert_files/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +0 -1
- data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
- data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
- data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
- data/test/test/file_methods_doc/test_sub/expected/one.txt +0 -1
- data/test/test/file_methods_doc/test_sub/expected/two.txt +0 -1
- data/test/test/file_methods_doc/test_sub/input/one.txt +0 -1
- data/test/test/file_methods_doc/test_sub/input/two.txt +0 -1
- data/test/test/file_methods_doc_test.rb +0 -29
- data/test/test/file_methods_test.rb +0 -275
- data/test/test/subset_methods_test.rb +0 -171
- data/test/test/tap_methods/test_assert_files/expected/task/name/a.txt +0 -1
- data/test/test/tap_methods/test_assert_files/expected/task/name/b.txt +0 -1
- data/test/test/tap_methods/test_assert_files/input/a.txt +0 -1
- data/test/test/tap_methods/test_assert_files/input/b.txt +0 -1
- data/test/test/tap_methods_test.rb +0 -399
- data/test/workflow_test.rb +0 -120
- data/vendor/rails_generator.rb +0 -56
- data/vendor/rails_generator/base.rb +0 -263
- data/vendor/rails_generator/commands.rb +0 -581
- data/vendor/rails_generator/generated_attribute.rb +0 -42
- data/vendor/rails_generator/lookup.rb +0 -209
- data/vendor/rails_generator/manifest.rb +0 -53
- data/vendor/rails_generator/options.rb +0 -143
- data/vendor/rails_generator/scripts.rb +0 -83
- data/vendor/rails_generator/scripts/destroy.rb +0 -7
- data/vendor/rails_generator/scripts/generate.rb +0 -7
- data/vendor/rails_generator/scripts/update.rb +0 -12
- data/vendor/rails_generator/simple_logger.rb +0 -46
- data/vendor/rails_generator/spec.rb +0 -44
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
require 'strscan'
|
|
2
|
+
|
|
3
|
+
module Tap
|
|
4
|
+
module Support
|
|
5
|
+
# Comment represents a comment parsed by Lazydoc.
|
|
6
|
+
class Comment
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
|
|
10
|
+
# Parses the input string into a comment, stopping at end_regexp
|
|
11
|
+
# or the first non-comment line. Also parses the next non-comment
|
|
12
|
+
# lines as the comment subject. Takes a string or a StringScanner
|
|
13
|
+
# and returns the new comment.
|
|
14
|
+
#
|
|
15
|
+
# comment_string = %Q{
|
|
16
|
+
# # comments spanning multiple
|
|
17
|
+
# # lines are collected
|
|
18
|
+
# #
|
|
19
|
+
# # while indented lines
|
|
20
|
+
# # are preserved individually
|
|
21
|
+
# #
|
|
22
|
+
# this is the subject line
|
|
23
|
+
#
|
|
24
|
+
# # this line is not parsed as it
|
|
25
|
+
# # is after a non-comment line
|
|
26
|
+
# }
|
|
27
|
+
#
|
|
28
|
+
# c = Comment.parse(comment_string)
|
|
29
|
+
# c.lines
|
|
30
|
+
# # => [
|
|
31
|
+
# # ['comments spanning multiple', 'lines are collected'],
|
|
32
|
+
# # [''],
|
|
33
|
+
# # [' while indented lines'],
|
|
34
|
+
# # [' are preserved individually'],
|
|
35
|
+
# # [''],
|
|
36
|
+
# # []]
|
|
37
|
+
# c.subject # => "this is the subject line"
|
|
38
|
+
#
|
|
39
|
+
def parse(str, parse_subject=true) # :yields: fragment
|
|
40
|
+
scanner = case str
|
|
41
|
+
when StringScanner then str
|
|
42
|
+
when String then StringScanner.new(str)
|
|
43
|
+
else raise TypeError, "can't convert #{str.class} into StringScanner or String"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
comment = Comment.new
|
|
47
|
+
while scanner.scan(/\r?\n?[ \t]*#[ \t]?(([ \t]*).*?)\r?$/)
|
|
48
|
+
fragment = scanner[1]
|
|
49
|
+
indent = scanner[2]
|
|
50
|
+
|
|
51
|
+
# collect continuous description line
|
|
52
|
+
# fragments and join into a single line
|
|
53
|
+
if block_given? && yield(fragment)
|
|
54
|
+
# break on comment if the description end is reached
|
|
55
|
+
parse_subject = false
|
|
56
|
+
break
|
|
57
|
+
else
|
|
58
|
+
categorize(fragment, indent) {|f| comment.push(f) }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if parse_subject
|
|
63
|
+
scanner.skip(/\s+/)
|
|
64
|
+
unless scanner.peek(1) == '#'
|
|
65
|
+
comment.subject = scanner.scan(/.+?$/)
|
|
66
|
+
comment.subject.strip! unless comment.subject == nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
comment
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Scans the line checking if it is a comment. If so, scan
|
|
74
|
+
# yields the parse fragments to the block which correspond
|
|
75
|
+
# to the type of comment input (continuation, indent, etc).
|
|
76
|
+
# Returns true if the line is a comment, false otherwise.
|
|
77
|
+
#
|
|
78
|
+
# Scan may be used to build a comment from an array of lines:
|
|
79
|
+
#
|
|
80
|
+
# lines = [
|
|
81
|
+
# "# comments spanning multiple",
|
|
82
|
+
# "# lines are collected",
|
|
83
|
+
# "#",
|
|
84
|
+
# "# while indented lines",
|
|
85
|
+
# "# are preserved individually",
|
|
86
|
+
# "# ",
|
|
87
|
+
# "not a comment line",
|
|
88
|
+
# "# skipped since the loop breaks",
|
|
89
|
+
# "# at the first non-comment line"]
|
|
90
|
+
#
|
|
91
|
+
# c = Comment.new
|
|
92
|
+
# lines.each do |line|
|
|
93
|
+
# break unless Comment.scan(line) do |fragment|
|
|
94
|
+
# # c.unshift will also work if building in reverse
|
|
95
|
+
# c.push(fragment)
|
|
96
|
+
# end
|
|
97
|
+
# end
|
|
98
|
+
#
|
|
99
|
+
# c.lines
|
|
100
|
+
# # => [
|
|
101
|
+
# # ['comments spanning multiple', 'lines are collected'],
|
|
102
|
+
# # [''],
|
|
103
|
+
# # [' while indented lines'],
|
|
104
|
+
# # [' are preserved individually'],
|
|
105
|
+
# # [''],
|
|
106
|
+
# # []]
|
|
107
|
+
#
|
|
108
|
+
def scan(line) # :yields: fragment
|
|
109
|
+
return false unless line =~ /^[ \t]*#[ \t]?(([ \t]*).*?)\r?$/
|
|
110
|
+
categorize($1, $2) do |fragment|
|
|
111
|
+
yield(fragment)
|
|
112
|
+
end
|
|
113
|
+
true
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def wrap(lines, cols=80, tabsize=2)
|
|
117
|
+
lines = lines.split(/\r?\n/) unless lines.kind_of?(Array)
|
|
118
|
+
|
|
119
|
+
lines.collect do |line|
|
|
120
|
+
line = line.gsub(/\t/, " " * tabsize) unless tabsize == nil
|
|
121
|
+
|
|
122
|
+
if line.strip.empty?
|
|
123
|
+
line
|
|
124
|
+
else
|
|
125
|
+
# wrapping algorithm is slightly modified from
|
|
126
|
+
# http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
|
|
127
|
+
line.gsub(/(.{1,#{cols}})( +|$\r?\n?)|(.{1,#{cols}})/, "\\1\\3\n").split(/\s*\n/)
|
|
128
|
+
end
|
|
129
|
+
end.flatten
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
private
|
|
133
|
+
|
|
134
|
+
def categorize(fragment, indent)
|
|
135
|
+
case
|
|
136
|
+
when fragment == indent
|
|
137
|
+
# empty comment line
|
|
138
|
+
yield [""]
|
|
139
|
+
yield []
|
|
140
|
+
when indent.empty?
|
|
141
|
+
# continuation line
|
|
142
|
+
yield fragment.rstrip
|
|
143
|
+
else
|
|
144
|
+
# indented line
|
|
145
|
+
yield [fragment.rstrip]
|
|
146
|
+
yield []
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# An array of line fragment arrays.
|
|
152
|
+
attr_reader :lines
|
|
153
|
+
|
|
154
|
+
# The next non-comment line after the comment ends.
|
|
155
|
+
# This is the line that would receive the comment
|
|
156
|
+
# in RDoc documentation.
|
|
157
|
+
attr_accessor :subject
|
|
158
|
+
|
|
159
|
+
# Returns the line number for the subject line, if known.
|
|
160
|
+
attr_accessor :line_number
|
|
161
|
+
|
|
162
|
+
def initialize(line_number=nil)
|
|
163
|
+
@lines = []
|
|
164
|
+
@subject = nil
|
|
165
|
+
@line_number = line_number
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Pushes the fragment onto the last line array. If fragment is an
|
|
169
|
+
# array itself, then fragment will be pushed onto lines.
|
|
170
|
+
#
|
|
171
|
+
# c = Comment.new
|
|
172
|
+
# c.push "some line"
|
|
173
|
+
# c.push "fragments"
|
|
174
|
+
# c.push ["a", "whole", "new line"]
|
|
175
|
+
# c.lines # => [["some line", "fragments"], ["a", "whole", "new line"]]
|
|
176
|
+
#
|
|
177
|
+
def push(fragment)
|
|
178
|
+
lines << [] if lines.empty?
|
|
179
|
+
|
|
180
|
+
case fragment
|
|
181
|
+
when Array
|
|
182
|
+
if lines[-1].empty?
|
|
183
|
+
lines[-1] = fragment
|
|
184
|
+
else
|
|
185
|
+
lines.push fragment
|
|
186
|
+
end
|
|
187
|
+
else
|
|
188
|
+
lines[-1].push fragment
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Alias for push.
|
|
193
|
+
def <<(fragment)
|
|
194
|
+
push(fragment)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Unshifts the fragment to the first line array. If fragment is an
|
|
198
|
+
# array itself, then fragment will be unshifted onto lines.
|
|
199
|
+
#
|
|
200
|
+
# c = Comment.new
|
|
201
|
+
# c.unshift "some line"
|
|
202
|
+
# c.unshift "fragments"
|
|
203
|
+
# c.unshift ["a", "whole", "new line"]
|
|
204
|
+
# c.lines # => [["a", "whole", "new line"], ["fragments", "some line"]]
|
|
205
|
+
#
|
|
206
|
+
def unshift(fragment)
|
|
207
|
+
lines << [] if lines.empty?
|
|
208
|
+
|
|
209
|
+
case fragment
|
|
210
|
+
when Array
|
|
211
|
+
if lines[0].empty?
|
|
212
|
+
lines[0] = fragment
|
|
213
|
+
else
|
|
214
|
+
lines.unshift fragment
|
|
215
|
+
end
|
|
216
|
+
else
|
|
217
|
+
lines[0].unshift fragment
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def prepend(comment_line)
|
|
222
|
+
Comment.scan(comment_line) {|f| unshift(f) }
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def append(comment_line)
|
|
226
|
+
Comment.scan(comment_line) {|f| push(f) }
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Removes leading and trailing lines that are empty ([])
|
|
230
|
+
# or whitespace (['']). Returns self.
|
|
231
|
+
def trim
|
|
232
|
+
lines.shift while !lines.empty? && (lines[0].empty? || lines[0].join.strip.empty?)
|
|
233
|
+
lines.pop while !lines.empty? && (lines[-1].empty? || lines[-1].join.strip.empty?)
|
|
234
|
+
self
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# True if there are no fragments in self.
|
|
238
|
+
def empty?
|
|
239
|
+
!lines.find {|array| !array.empty?}
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def wrap(cols=80, tabsize=2, line_sep="\n", fragment_sep=" ", strip=true)
|
|
243
|
+
resolved_lines = Comment.wrap(to_s(fragment_sep, nil, strip), cols, tabsize)
|
|
244
|
+
line_sep ? resolved_lines.join(line_sep) : resolved_lines
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Returns lines as a string where line fragments are joined by
|
|
248
|
+
# fragment_sep and lines are joined by line_sep.
|
|
249
|
+
def to_s(fragment_sep=" ", line_sep="\n", strip=true)
|
|
250
|
+
resolved_lines = lines.collect {|line| line.join(fragment_sep)}
|
|
251
|
+
|
|
252
|
+
# strip leading an trailing whitespace lines
|
|
253
|
+
if strip
|
|
254
|
+
resolved_lines.shift while !resolved_lines.empty? && resolved_lines[0].empty?
|
|
255
|
+
resolved_lines.pop while !resolved_lines.empty? && resolved_lines[-1].empty?
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
line_sep ? resolved_lines.join(line_sep) : resolved_lines
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def ==(another)
|
|
262
|
+
another.kind_of?(Comment) &&
|
|
263
|
+
self.line_number == another.line_number &&
|
|
264
|
+
self.subject == another.subject &&
|
|
265
|
+
self.lines == another.lines
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
@@ -1,92 +1,113 @@
|
|
|
1
|
+
require 'tap/support/configurable_class'
|
|
2
|
+
|
|
1
3
|
module Tap
|
|
2
4
|
module Support
|
|
3
5
|
|
|
4
|
-
# Configurable
|
|
5
|
-
# by Tasks. When Configurable is included in a class, the class itself
|
|
6
|
-
# is extended with Tap::Support::ConfigurableMethods, such that configs
|
|
7
|
-
# can be declared within the class definition.
|
|
6
|
+
# Configurable enables the specification of configurations within a class definition.
|
|
8
7
|
#
|
|
9
|
-
# class
|
|
8
|
+
# class ConfigClass
|
|
10
9
|
# include Configurable
|
|
11
10
|
#
|
|
12
11
|
# config :one, 'one'
|
|
13
12
|
# config :two, 'two'
|
|
14
13
|
# config :three, 'three'
|
|
14
|
+
#
|
|
15
|
+
# def initialize(overrides={})
|
|
16
|
+
# initialize_config(overrides)
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# c = ConfigClass.new
|
|
21
|
+
# c.config.class # => InstanceConfiguration
|
|
22
|
+
# c.config # => {:one => 'one', :two => 'two', :three => 'three'}
|
|
23
|
+
#
|
|
24
|
+
# The <tt>config</tt> object acts as a kind of forwarding hash; declared configurations
|
|
25
|
+
# map to accessors while undeclared configurations are stored internally:
|
|
26
|
+
#
|
|
27
|
+
# c.config[:one] = 'ONE'
|
|
28
|
+
# c.one # => 'ONE'
|
|
29
|
+
#
|
|
30
|
+
# c.one = 1
|
|
31
|
+
# c.config # => {:one => 1, :two => 'two', :three => 'three'}
|
|
32
|
+
#
|
|
33
|
+
# c.config[:undeclared] = 'value'
|
|
34
|
+
# c.config.store # => {:undeclared => 'value'}
|
|
35
|
+
#
|
|
36
|
+
# The writer method for a configuration can be modified by providing a block to config.
|
|
37
|
+
# The Validation module provides a number of common validation and string-transform
|
|
38
|
+
# blocks which can be accessed through the class method 'c':
|
|
39
|
+
#
|
|
40
|
+
# class SubClass < ConfigClass
|
|
41
|
+
# config(:one, 'one') {|v| v.upcase }
|
|
42
|
+
# config :two, 2, &c.integer
|
|
15
43
|
# end
|
|
16
44
|
#
|
|
17
|
-
#
|
|
45
|
+
# s = SubClass.new
|
|
46
|
+
# s.config # => {:one => 'ONE', :two => 2, :three => 'three'}
|
|
47
|
+
#
|
|
48
|
+
# s.one = 'aNothER'
|
|
49
|
+
# s.one # => 'ANOTHER'
|
|
50
|
+
#
|
|
51
|
+
# s.two = -2
|
|
52
|
+
# s.two # => -2
|
|
53
|
+
# s.two = "3"
|
|
54
|
+
# s.two # => 3
|
|
55
|
+
# s.two = nil # !> ValidationError
|
|
56
|
+
# s.two = 'str' # !> ValidationError
|
|
57
|
+
#
|
|
58
|
+
# As shown above, configurations are inherited from the parent and can be
|
|
59
|
+
# overridden in subclasses. See ConfigurableClass for more details.
|
|
18
60
|
#
|
|
19
|
-
# See the 'Configuration' section in the Tap::Task documentation for
|
|
20
|
-
# more details on how Configurable works in practice.
|
|
21
61
|
module Configurable
|
|
22
|
-
|
|
23
|
-
|
|
62
|
+
|
|
63
|
+
# Extends including classes with ConfigurableClass
|
|
24
64
|
def self.included(mod)
|
|
25
|
-
mod.extend Support::
|
|
26
|
-
mod.extend Support::ConfigurableMethods
|
|
27
|
-
mod.instance_variable_set(:@configurations, Support::ClassConfiguration.new(mod))
|
|
28
|
-
mod.instance_variable_set(:@source_files, [])
|
|
65
|
+
mod.extend Support::ConfigurableClass if mod.kind_of?(Class)
|
|
29
66
|
end
|
|
30
|
-
|
|
31
|
-
# The application used to load config_file templates
|
|
32
|
-
# (and hence, to initialize batched objects).
|
|
33
|
-
attr_reader :app
|
|
34
67
|
|
|
35
|
-
# The
|
|
36
|
-
# app.config_filepath(name).
|
|
37
|
-
attr_reader :name
|
|
38
|
-
|
|
39
|
-
# The config file used to load config templates.
|
|
40
|
-
attr_reader :config_file
|
|
41
|
-
|
|
42
|
-
# A configuration hash.
|
|
68
|
+
# The instance configurations for self
|
|
43
69
|
attr_reader :config
|
|
44
70
|
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
config.symbolize_keys! unless config.empty?
|
|
54
|
-
app.each_config_template(config_file) do |template|
|
|
55
|
-
template_config = template.empty? ? config : template.symbolize_keys.merge(config)
|
|
56
|
-
initialize_batch_obj(name, template_config)
|
|
71
|
+
# Reconfigures self with the given configuration overrides. Only
|
|
72
|
+
# the specified configs are modified. Override keys are symbolized.
|
|
73
|
+
#
|
|
74
|
+
# Returns self.
|
|
75
|
+
def reconfigure(overrides={})
|
|
76
|
+
keys = (config.class_config.ordered_keys + overrides.keys) & overrides.keys
|
|
77
|
+
keys.each do |key|
|
|
78
|
+
config[key.to_sym] = overrides[key]
|
|
57
79
|
end
|
|
80
|
+
|
|
81
|
+
self
|
|
58
82
|
end
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
self.config
|
|
83
|
+
|
|
84
|
+
# Reinitializes config with a copy of orig.config (this assures
|
|
85
|
+
# that duplicates have their own copy of configurations,
|
|
86
|
+
# separate from the original object).
|
|
87
|
+
def initialize_copy(orig)
|
|
88
|
+
super
|
|
89
|
+
initialize_config(orig.config)
|
|
67
90
|
end
|
|
68
91
|
|
|
69
|
-
|
|
70
|
-
# will be a duplicate of the current object but with a new name and/or
|
|
71
|
-
# configurations.
|
|
72
|
-
def initialize_batch_obj(name=nil, config={})
|
|
73
|
-
obj = super()
|
|
92
|
+
protected
|
|
74
93
|
|
|
75
|
-
|
|
76
|
-
|
|
94
|
+
# Initializes config to an InstanceConfiguration specific for self.
|
|
95
|
+
# Default config values are assigned or overridden if specified in
|
|
96
|
+
# overrides. Override keys are symbolized.
|
|
97
|
+
def initialize_config(overrides={})
|
|
98
|
+
class_config = self.class.configurations
|
|
99
|
+
@config = class_config.instance_config
|
|
100
|
+
|
|
101
|
+
overrides.each_pair do |key, value|
|
|
102
|
+
config[key.to_sym] = value
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class_config.each_pair do |key, value|
|
|
106
|
+
next if config.has_key?(key)
|
|
107
|
+
config[key] = value.default
|
|
108
|
+
end
|
|
77
109
|
|
|
78
|
-
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
protected
|
|
82
|
-
|
|
83
|
-
attr_writer :name
|
|
84
|
-
|
|
85
|
-
# Sets the specified configuration, processing the input value using
|
|
86
|
-
# the block specified in the config declaration. The input key should
|
|
87
|
-
# be symbolized.
|
|
88
|
-
def set_config(key, value)
|
|
89
|
-
config[key] = self.class.configurations.process(key, value)
|
|
110
|
+
config.bind(self)
|
|
90
111
|
end
|
|
91
112
|
end
|
|
92
113
|
end
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
require 'tap/support/class_configuration'
|
|
2
|
+
require 'tap/support/validation'
|
|
3
|
+
require 'tap/support/lazydoc'
|
|
4
|
+
|
|
5
|
+
module Tap
|
|
6
|
+
module Support
|
|
7
|
+
autoload(:Templater, 'tap/support/templater')
|
|
8
|
+
|
|
9
|
+
# ConfigurableClass encapsulates class methods used to declare class configurations.
|
|
10
|
+
# When configurations are declared using the config method, ConfigurableClass
|
|
11
|
+
# generates accessors in the class, much like attr_accessor.
|
|
12
|
+
#
|
|
13
|
+
# class ConfigurableClass
|
|
14
|
+
# extend ConfigurableClass
|
|
15
|
+
# config :one, 'one'
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# ConfigurableClass.configurations.to_hash # => {:one => 'one'}
|
|
19
|
+
#
|
|
20
|
+
# c = ConfigurableClass.new
|
|
21
|
+
# c.respond_to?('one') # => true
|
|
22
|
+
# c.respond_to?('one=') # => true
|
|
23
|
+
#
|
|
24
|
+
# If a block is given, the block will be used to create the writer method
|
|
25
|
+
# for the config. Used in this manner, config defines a <tt>config_key=</tt> method
|
|
26
|
+
# wherein <tt>@config_key</tt> will be set to the return value of the block.
|
|
27
|
+
#
|
|
28
|
+
# class AnotherConfigurableClass
|
|
29
|
+
# extend ConfigurableClass
|
|
30
|
+
# config(:one, 'one') {|value| value.upcase }
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# ac = AnotherConfigurableClass.new
|
|
34
|
+
# ac.one = 'value'
|
|
35
|
+
# ac.one # => 'VALUE'
|
|
36
|
+
#
|
|
37
|
+
# The block has class-context in this case. To have instance-context, use the
|
|
38
|
+
# config_attr method which defines the writer method using the block directly.
|
|
39
|
+
#
|
|
40
|
+
# class YetAnotherConfigurableClass
|
|
41
|
+
# extend ConfigurableClass
|
|
42
|
+
# config_attr(:one, 'one') {|value| @one = value.reverse }
|
|
43
|
+
# end
|
|
44
|
+
#
|
|
45
|
+
# ac = YetAnotherConfigurableClass.new
|
|
46
|
+
# ac.one = 'value'
|
|
47
|
+
# ac.one # => 'eulav'
|
|
48
|
+
#
|
|
49
|
+
module ConfigurableClass
|
|
50
|
+
|
|
51
|
+
# A ClassConfiguration holding the class configurations.
|
|
52
|
+
attr_reader :configurations
|
|
53
|
+
|
|
54
|
+
# The source_file for self. By default the first file
|
|
55
|
+
# to define the class inheriting ConfigurableClass.
|
|
56
|
+
attr_accessor :source_file
|
|
57
|
+
|
|
58
|
+
# Sets the source_file for base and initializes base.configurations.
|
|
59
|
+
def self.extended(base)
|
|
60
|
+
caller.each_with_index do |line, index|
|
|
61
|
+
case line
|
|
62
|
+
when /\/configurable.rb/ then next
|
|
63
|
+
when /^(([A-z]:)?[^:]+):(\d+)/
|
|
64
|
+
base.instance_variable_set(:@source_file, File.expand_path($1))
|
|
65
|
+
break
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
base.instance_variable_set(:@configurations, ClassConfiguration.new(base))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# When subclassed, the parent.configurations are duplicated and passed to
|
|
73
|
+
# the child class where they can be extended/modified without affecting
|
|
74
|
+
# the configurations of the parent class.
|
|
75
|
+
def inherited(child)
|
|
76
|
+
unless child.instance_variable_defined?(:@source_file)
|
|
77
|
+
caller.first =~ /^(([A-z]:)?[^:]+):(\d+)/
|
|
78
|
+
child.instance_variable_set(:@source_file, File.expand_path($1))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
child.instance_variable_set(:@configurations, ClassConfiguration.new(child, @configurations))
|
|
82
|
+
super
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Returns the lazydoc for source_file
|
|
86
|
+
def lazydoc(resolve=false)
|
|
87
|
+
Lazydoc.resolve(configurations.code_comments) if resolve
|
|
88
|
+
Lazydoc[source_file]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Loads the contents of path as YAML. Returns an empty hash if the path
|
|
92
|
+
# is empty, does not exist, or is not a file.
|
|
93
|
+
def load_config(path)
|
|
94
|
+
return {} if path == nil || !File.exists?(path) || File.directory?(path)
|
|
95
|
+
|
|
96
|
+
YAML.load_file(path) || {}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
protected
|
|
100
|
+
|
|
101
|
+
# Declares a class configuration and generates the associated accessors.
|
|
102
|
+
# If a block is given, the <tt>key=</tt> method will set <tt>@key</tt>
|
|
103
|
+
# to the return of the block, which executes in class-context.
|
|
104
|
+
# Configurations are inherited, and can be overridden in subclasses.
|
|
105
|
+
#
|
|
106
|
+
# class SampleClass
|
|
107
|
+
# include Tap::Support::Configurable
|
|
108
|
+
#
|
|
109
|
+
# config :str, 'value'
|
|
110
|
+
# config(:upcase, 'value') {|input| input.upcase }
|
|
111
|
+
# end
|
|
112
|
+
#
|
|
113
|
+
# # An equivalent class to illustrate class-context
|
|
114
|
+
# class EquivalentClass
|
|
115
|
+
# attr_accessor :str
|
|
116
|
+
# attr_reader :upcase
|
|
117
|
+
#
|
|
118
|
+
# UPCASE_BLOCK = lambda {|input| input.upcase }
|
|
119
|
+
#
|
|
120
|
+
# def upcase=(input)
|
|
121
|
+
# @upcase = UPCASE_BLOCK.call(input)
|
|
122
|
+
# end
|
|
123
|
+
# end
|
|
124
|
+
#
|
|
125
|
+
def config(key, value=nil, options={}, &block)
|
|
126
|
+
if block_given?
|
|
127
|
+
# add arg_type implied by block, if necessary
|
|
128
|
+
options[:arg_type] = arg_type(block) if options[:arg_type] == nil
|
|
129
|
+
options[:arg_name] = arg_name(block) if options[:arg_name] == nil
|
|
130
|
+
|
|
131
|
+
instance_variable = "@#{key}".to_sym
|
|
132
|
+
config_attr(key, value, options) do |input|
|
|
133
|
+
instance_variable_set(instance_variable, block.call(input))
|
|
134
|
+
end
|
|
135
|
+
else
|
|
136
|
+
config_attr(key, value, options)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Declares a class configuration and generates the associated accessors.
|
|
141
|
+
# If a block is given, the <tt>key=</tt> method will perform the block with
|
|
142
|
+
# instance-context. Configurations are inherited, and can be overridden
|
|
143
|
+
# in subclasses.
|
|
144
|
+
#
|
|
145
|
+
# class SampleClass
|
|
146
|
+
# include Tap::Support::Configurable
|
|
147
|
+
#
|
|
148
|
+
# def initialize
|
|
149
|
+
# initialize_config
|
|
150
|
+
# end
|
|
151
|
+
#
|
|
152
|
+
# config_attr :str, 'value'
|
|
153
|
+
# config_attr(:upcase, 'value') {|input| @upcase = input.upcase }
|
|
154
|
+
# end
|
|
155
|
+
#
|
|
156
|
+
# # An equivalent class to illustrate instance-context
|
|
157
|
+
# class EquivalentClass
|
|
158
|
+
# attr_accessor :str
|
|
159
|
+
# attr_reader :upcase
|
|
160
|
+
#
|
|
161
|
+
# def upcase=(input)
|
|
162
|
+
# @upcase = input.upcase
|
|
163
|
+
# end
|
|
164
|
+
# end
|
|
165
|
+
#
|
|
166
|
+
# Instances of a Configurable class may set configurations through config.
|
|
167
|
+
# The config object is an InstanceConfiguration which forwards read/write
|
|
168
|
+
# operations to the configuration accessors. For example:
|
|
169
|
+
#
|
|
170
|
+
# s = SampleClass.new
|
|
171
|
+
# s.config.class # => Tap::Support::InstanceConfiguration
|
|
172
|
+
# s.str # => 'value'
|
|
173
|
+
# s.config[:str] # => 'value'
|
|
174
|
+
#
|
|
175
|
+
# s.str = 'one'
|
|
176
|
+
# s.config[:str] # => 'one'
|
|
177
|
+
#
|
|
178
|
+
# s.config[:str] = 'two'
|
|
179
|
+
# s.str # => 'two'
|
|
180
|
+
#
|
|
181
|
+
# Alternative reader and writer methods may be specified as an option;
|
|
182
|
+
# in this case config_attr assumes the methods are declared elsewhere
|
|
183
|
+
# and will not define the associated accessors.
|
|
184
|
+
#
|
|
185
|
+
# class AlternativeClass
|
|
186
|
+
# include Tap::Support::Configurable
|
|
187
|
+
#
|
|
188
|
+
# config_attr :sym, 'value', :reader => :get_sym, :writer => :set_sym
|
|
189
|
+
#
|
|
190
|
+
# def initialize
|
|
191
|
+
# initialize_config
|
|
192
|
+
# end
|
|
193
|
+
#
|
|
194
|
+
# def get_sym
|
|
195
|
+
# @sym
|
|
196
|
+
# end
|
|
197
|
+
#
|
|
198
|
+
# def set_sym(input)
|
|
199
|
+
# @sym = input.to_sym
|
|
200
|
+
# end
|
|
201
|
+
# end
|
|
202
|
+
#
|
|
203
|
+
# alt = AlternativeClass.new
|
|
204
|
+
# alt.respond_to?(:sym) # => false
|
|
205
|
+
# alt.respond_to?(:sym=) # => false
|
|
206
|
+
#
|
|
207
|
+
# alt.config[:sym] = 'one'
|
|
208
|
+
# alt.get_sym # => :one
|
|
209
|
+
#
|
|
210
|
+
# alt.set_sym('two')
|
|
211
|
+
# alt.config[:sym] # => :two
|
|
212
|
+
#
|
|
213
|
+
# Idiosyncratically, true, false, and nil may also be provided as
|
|
214
|
+
# reader/writer options. Specifying true is the same as using the
|
|
215
|
+
# default. Specifying false or nil prevents config_attr from
|
|
216
|
+
# defining accessors, but the configuration still expects to use
|
|
217
|
+
# the default reader/writer methods (ie <tt>key</tt> and <tt>key=</tt>)
|
|
218
|
+
# which must be defined elsewhere.
|
|
219
|
+
def config_attr(key, value=nil, options={}, &block)
|
|
220
|
+
|
|
221
|
+
# add arg_type implied by block, if necessary
|
|
222
|
+
options[:arg_type] = arg_type(block) if block_given? && options[:arg_type] == nil
|
|
223
|
+
options[:arg_name] = arg_name(block) if block_given? && options[:arg_name] == nil
|
|
224
|
+
|
|
225
|
+
# define the default public reader method
|
|
226
|
+
if !options.has_key?(:reader) || options[:reader] == true
|
|
227
|
+
attr_reader(key)
|
|
228
|
+
public key
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# define the public writer method
|
|
232
|
+
case
|
|
233
|
+
when options.has_key?(:writer) && options[:writer] != true
|
|
234
|
+
raise ArgumentError.new("block may not be specified with writer") if block_given?
|
|
235
|
+
when block_given?
|
|
236
|
+
define_method("#{key}=", &block)
|
|
237
|
+
public "#{key}="
|
|
238
|
+
else
|
|
239
|
+
attr_writer(key)
|
|
240
|
+
public "#{key}="
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# remove any true, false, nil reader/writer declarations...
|
|
244
|
+
# implicitly reverting the option to the default reader
|
|
245
|
+
# and writer methods
|
|
246
|
+
[:reader, :writer].each do |option|
|
|
247
|
+
case options[option]
|
|
248
|
+
when true, false, nil then options.delete(option)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# register with TDoc so that all extra documentation can be extracted
|
|
253
|
+
caller.each_with_index do |line, index|
|
|
254
|
+
case line
|
|
255
|
+
when /in .config.$/ then next
|
|
256
|
+
when /^(([A-z]:)?[^:]+):(\d+)/
|
|
257
|
+
options[:desc] = Lazydoc.register($1, $3.to_i - 1)
|
|
258
|
+
break
|
|
259
|
+
end
|
|
260
|
+
end if options[:desc] == nil
|
|
261
|
+
|
|
262
|
+
configurations.add(key, value, options)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Alias for Tap::Support::Validation
|
|
266
|
+
def c
|
|
267
|
+
Validation
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
private
|
|
271
|
+
|
|
272
|
+
# Returns special argument types for standard validation
|
|
273
|
+
# blocks, such as switch (Validation::SWITCH) and list
|
|
274
|
+
# (Validation::LIST).
|
|
275
|
+
def arg_type(block) # :nodoc:
|
|
276
|
+
case block
|
|
277
|
+
when Validation::SWITCH then :switch
|
|
278
|
+
when Validation::FLAG then :flag
|
|
279
|
+
when Validation::LIST then :list
|
|
280
|
+
else nil
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Returns special argument names for standard validation
|
|
285
|
+
# blocks, such as switch (Validation::ARRAY) and list
|
|
286
|
+
# (Validation::HASH).
|
|
287
|
+
def arg_name(block) # :nodoc:
|
|
288
|
+
case block
|
|
289
|
+
when Validation::ARRAY then "'[a, b, c]'"
|
|
290
|
+
when Validation::HASH then "'{one: 1, two: 2}'"
|
|
291
|
+
else nil
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|