tap 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (244) hide show
  1. data/History +37 -30
  2. data/MIT-LICENSE +1 -1
  3. data/README +92 -44
  4. data/bin/tap +62 -75
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +6 -45
  13. data/lib/tap/app.rb +126 -500
  14. data/lib/tap/constants.rb +2 -29
  15. data/lib/tap/env.rb +555 -250
  16. data/lib/tap/file_task.rb +60 -103
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +16 -12
  21. data/lib/tap/generator/generators/command/templates/command.erb +13 -19
  22. data/lib/tap/generator/generators/config/config_generator.rb +18 -27
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -11
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -2
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +24 -31
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +18 -22
  30. data/lib/tap/generator/generators/root/root_generator.rb +45 -31
  31. data/lib/tap/generator/generators/root/templates/Rakefile +64 -41
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +21 -28
  38. data/lib/tap/generator/generators/task/templates/task.erb +13 -23
  39. data/lib/tap/generator/generators/task/templates/test.erb +15 -18
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +0 -0
  42. data/lib/tap/patches/rake/testtask.rb +0 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +0 -0
  45. data/lib/tap/root.rb +260 -21
  46. data/lib/tap/support/aggregator.rb +11 -11
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +20 -18
  49. data/lib/tap/support/batchable.rb +21 -10
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +154 -239
  52. data/lib/tap/support/command_line.rb +97 -102
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +86 -65
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +30 -17
  61. data/lib/tap/support/executable_queue.rb +0 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +0 -0
  68. data/lib/tap/support/shell_utils.rb +33 -9
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +339 -134
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +409 -76
  75. data/lib/tap/support/versions.rb +5 -3
  76. data/lib/tap/task.rb +78 -174
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +3 -3
  80. data/lib/tap/test/env_vars.rb +2 -2
  81. data/lib/tap/test/file_methods.rb +19 -20
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +1 -1
  84. data/lib/tap/test/tap_methods.rb +28 -62
  85. data/lib/tap/workflow.rb +22 -39
  86. metadata +48 -179
  87. data/Basic Overview +0 -151
  88. data/Command Reference +0 -99
  89. data/Rakefile +0 -127
  90. data/Tutorial +0 -287
  91. data/lib/tap/cmd/console.rb +0 -31
  92. data/lib/tap/cmd/destroy.rb +0 -20
  93. data/lib/tap/cmd/generate.rb +0 -20
  94. data/lib/tap/cmd/run.rb +0 -151
  95. data/lib/tap/dump.rb +0 -57
  96. data/lib/tap/generator.rb +0 -91
  97. data/lib/tap/generator/generators/command/USAGE +0 -6
  98. data/lib/tap/generator/generators/config/USAGE +0 -21
  99. data/lib/tap/generator/generators/config/templates/config.erb +0 -1
  100. data/lib/tap/generator/generators/file_task/USAGE +0 -3
  101. data/lib/tap/generator/generators/file_task/templates/file.yml +0 -3
  102. data/lib/tap/generator/generators/generator/USAGE +0 -0
  103. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -21
  104. data/lib/tap/generator/generators/generator/templates/generator.erb +0 -32
  105. data/lib/tap/generator/generators/generator/templates/usage.erb +0 -1
  106. data/lib/tap/generator/generators/root/USAGE +0 -0
  107. data/lib/tap/generator/generators/root/templates/ReadMe.txt +0 -0
  108. data/lib/tap/generator/generators/root/templates/tap.yml +0 -80
  109. data/lib/tap/generator/generators/task/USAGE +0 -3
  110. data/lib/tap/generator/generators/workflow/USAGE +0 -0
  111. data/lib/tap/generator/generators/workflow/templates/task.erb +0 -16
  112. data/lib/tap/generator/generators/workflow/templates/test.erb +0 -7
  113. data/lib/tap/generator/generators/workflow/workflow_generator.rb +0 -6
  114. data/lib/tap/generator/options.rb +0 -26
  115. data/lib/tap/generator/usage.rb +0 -26
  116. data/lib/tap/support/batchable_methods.rb +0 -34
  117. data/lib/tap/support/command_line_methods.rb +0 -76
  118. data/lib/tap/support/configurable_methods.rb +0 -224
  119. data/lib/tap/support/logger.rb +0 -88
  120. data/lib/tap/support/rake.rb +0 -43
  121. data/lib/tap/support/tdoc/config_attr.rb +0 -362
  122. data/test/app/config/another/task.yml +0 -1
  123. data/test/app/config/batch.yml +0 -2
  124. data/test/app/config/empty.yml +0 -0
  125. data/test/app/config/erb.yml +0 -2
  126. data/test/app/config/some/task.yml +0 -1
  127. data/test/app/config/template.yml +0 -2
  128. data/test/app/config/version-0.1.yml +0 -1
  129. data/test/app/config/version.yml +0 -1
  130. data/test/app/lib/app_test_task.rb +0 -3
  131. data/test/app_test.rb +0 -1849
  132. data/test/env/test_configure/recurse_a.yml +0 -2
  133. data/test/env/test_configure/recurse_b.yml +0 -2
  134. data/test/env/test_configure/tap.yml +0 -23
  135. data/test/env/test_load_env_config/dir/tap.yml +0 -3
  136. data/test/env/test_load_env_config/recurse_a.yml +0 -2
  137. data/test/env/test_load_env_config/recurse_b.yml +0 -2
  138. data/test/env/test_load_env_config/tap.yml +0 -3
  139. data/test/env_test.rb +0 -198
  140. data/test/file_task/config/batch.yml +0 -2
  141. data/test/file_task/config/configured.yml +0 -1
  142. data/test/file_task/old_file_one.txt +0 -0
  143. data/test/file_task/old_file_two.txt +0 -0
  144. data/test/file_task_test.rb +0 -1291
  145. data/test/root/alt_lib/alt_module.rb +0 -4
  146. data/test/root/file.txt +0 -0
  147. data/test/root/glob/one.txt +0 -0
  148. data/test/root/glob/two.txt +0 -0
  149. data/test/root/lib/absolute_alt_filepath.rb +0 -2
  150. data/test/root/lib/alternative_filepath.rb +0 -2
  151. data/test/root/lib/another_module.rb +0 -2
  152. data/test/root/lib/nested/some_module.rb +0 -4
  153. data/test/root/lib/no_module_included.rb +0 -0
  154. data/test/root/lib/some/module.rb +0 -4
  155. data/test/root/lib/some_class.rb +0 -2
  156. data/test/root/lib/some_module.rb +0 -3
  157. data/test/root/load_path/load_path_module.rb +0 -2
  158. data/test/root/load_path/skip_module.rb +0 -2
  159. data/test/root/mtime/older.txt +0 -0
  160. data/test/root/unload/full_path.rb +0 -2
  161. data/test/root/unload/loaded_by_nested.rb +0 -2
  162. data/test/root/unload/nested/nested_load.rb +0 -6
  163. data/test/root/unload/nested/nested_with_ext.rb +0 -4
  164. data/test/root/unload/nested/relative_path.rb +0 -4
  165. data/test/root/unload/older.rb +0 -2
  166. data/test/root/unload/unload_base.rb +0 -9
  167. data/test/root/versions/another.yml +0 -0
  168. data/test/root/versions/file-0.1.2.yml +0 -0
  169. data/test/root/versions/file-0.1.yml +0 -0
  170. data/test/root/versions/file.yml +0 -0
  171. data/test/root_test.rb +0 -718
  172. data/test/support/aggregator_test.rb +0 -99
  173. data/test/support/audit_test.rb +0 -445
  174. data/test/support/batchable_test.rb +0 -74
  175. data/test/support/class_configuration_test.rb +0 -331
  176. data/test/support/command_line_test.rb +0 -58
  177. data/test/support/configurable/config/configured.yml +0 -2
  178. data/test/support/configurable_test.rb +0 -295
  179. data/test/support/executable_queue_test.rb +0 -103
  180. data/test/support/executable_test.rb +0 -38
  181. data/test/support/logger_test.rb +0 -31
  182. data/test/support/rake_test.rb +0 -37
  183. data/test/support/shell_utils_test.rb +0 -24
  184. data/test/support/tdoc_test.rb +0 -370
  185. data/test/support/validation_test.rb +0 -54
  186. data/test/support/versions_test.rb +0 -103
  187. data/test/tap_test_helper.rb +0 -57
  188. data/test/tap_test_suite.rb +0 -7
  189. data/test/task/config/batch.yml +0 -2
  190. data/test/task/config/batched.yml +0 -2
  191. data/test/task/config/configured.yml +0 -1
  192. data/test/task/config/example.yml +0 -1
  193. data/test/task_base_test.rb +0 -24
  194. data/test/task_syntax_test.rb +0 -300
  195. data/test/task_test.rb +0 -320
  196. data/test/test/env_vars_test.rb +0 -48
  197. data/test/test/file_methods/test_assert_files/expected/one.txt +0 -1
  198. data/test/test/file_methods/test_assert_files/expected/two.txt +0 -1
  199. data/test/test/file_methods/test_assert_files/input/one.txt +0 -1
  200. data/test/test/file_methods/test_assert_files/input/two.txt +0 -1
  201. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/one.txt +0 -1
  202. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/two.txt +0 -1
  203. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +0 -1
  204. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/two.txt +0 -1
  205. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +0 -1
  206. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +0 -1
  207. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/expected/one.txt +0 -1
  208. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +0 -1
  209. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +0 -1
  210. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +0 -1
  211. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +0 -1
  212. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +0 -1
  213. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +0 -1
  214. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +0 -1
  215. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +0 -1
  216. data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
  217. data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
  218. data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
  219. data/test/test/file_methods_doc/test_sub/expected/one.txt +0 -1
  220. data/test/test/file_methods_doc/test_sub/expected/two.txt +0 -1
  221. data/test/test/file_methods_doc/test_sub/input/one.txt +0 -1
  222. data/test/test/file_methods_doc/test_sub/input/two.txt +0 -1
  223. data/test/test/file_methods_doc_test.rb +0 -29
  224. data/test/test/file_methods_test.rb +0 -275
  225. data/test/test/subset_methods_test.rb +0 -171
  226. data/test/test/tap_methods/test_assert_files/expected/task/name/a.txt +0 -1
  227. data/test/test/tap_methods/test_assert_files/expected/task/name/b.txt +0 -1
  228. data/test/test/tap_methods/test_assert_files/input/a.txt +0 -1
  229. data/test/test/tap_methods/test_assert_files/input/b.txt +0 -1
  230. data/test/test/tap_methods_test.rb +0 -399
  231. data/test/workflow_test.rb +0 -120
  232. data/vendor/rails_generator.rb +0 -56
  233. data/vendor/rails_generator/base.rb +0 -263
  234. data/vendor/rails_generator/commands.rb +0 -581
  235. data/vendor/rails_generator/generated_attribute.rb +0 -42
  236. data/vendor/rails_generator/lookup.rb +0 -209
  237. data/vendor/rails_generator/manifest.rb +0 -53
  238. data/vendor/rails_generator/options.rb +0 -143
  239. data/vendor/rails_generator/scripts.rb +0 -83
  240. data/vendor/rails_generator/scripts/destroy.rb +0 -7
  241. data/vendor/rails_generator/scripts/generate.rb +0 -7
  242. data/vendor/rails_generator/scripts/update.rb +0 -12
  243. data/vendor/rails_generator/simple_logger.rb +0 -46
  244. data/vendor/rails_generator/spec.rb +0 -44
@@ -0,0 +1,122 @@
1
+ module Tap
2
+ module Support
3
+ class Configuration
4
+ class << self
5
+ SHORT_REGEXP = /^-[A-z]$/
6
+
7
+ # Turns the input string into a short-format option. Raises
8
+ # an error if the option does not match SHORT_REGEXP.
9
+ #
10
+ # Configuration.shortify("-o") # => '-o'
11
+ # Configuration.shortify(:o) # => '-o'
12
+ #
13
+ def shortify(str)
14
+ str = str.to_s
15
+ str = "-#{str}" unless str[0] == ?-
16
+ raise "invalid short option: #{str}" unless str =~ SHORT_REGEXP
17
+ str
18
+ end
19
+
20
+ LONG_REGEXP = /^--(\[no-\])?([A-z][\w-]*)$/
21
+
22
+ # Turns the input string into a long-format option. Raises
23
+ # an error if the option does not match LONG_REGEXP.
24
+ #
25
+ # Configuration.longify("--opt") # => '--opt'
26
+ # Configuration.longify(:opt) # => '--opt'
27
+ # Configuration.longify(:opt, true) # => '--[no-]opt'
28
+ # Configuration.longify(:opt_ion) # => '--opt-ion'
29
+ # Configuration.longify(:opt_ion, false, false) # => '--opt_ion'
30
+ #
31
+ def longify(str, switch_notation=false, hyphenize=true)
32
+ str = str.to_s
33
+ str = "--#{str}" unless str.index("--")
34
+ str.gsub!(/_/, '-') if hyphenize
35
+
36
+ raise "invalid long option: #{str}" unless str =~ LONG_REGEXP
37
+
38
+ if switch_notation && $1.nil?
39
+ str = "--[no-]#{$2}"
40
+ end
41
+
42
+ str
43
+ end
44
+ end
45
+
46
+ attr_reader :name
47
+ attr_reader :reader
48
+ attr_reader :writer
49
+ attr_reader :duplicable
50
+ attr_reader :attributes
51
+
52
+ def initialize(name, default=nil, options={})
53
+ @name = name
54
+ self.default = default
55
+
56
+ self.reader = options.delete(:reader) || name
57
+ self.writer = options.delete(:writer) || "#{name}="
58
+ @attributes = options
59
+ end
60
+
61
+ # Sets the default value for self and determines if the
62
+ # default is duplicable (ie not nil, true, false, Symbol,
63
+ # Numeric, and responds_to?(:dup)).
64
+ def default=(value)
65
+ @duplicable = case value
66
+ when nil, true, false, Symbol, Numeric then false
67
+ else value.respond_to?(:dup)
68
+ end
69
+
70
+ @default = value.freeze
71
+ end
72
+
73
+ # Returns the default value, or a duplicate of the default
74
+ # value if specified and the default value is duplicable.
75
+ def default(duplicate=true)
76
+ duplicate && duplicable ? @default.dup : @default
77
+ end
78
+
79
+ # Sets the reader for self. The reader is symbolized.
80
+ def reader=(value)
81
+ @reader = value.to_sym
82
+ end
83
+
84
+ # Sets the writer for self. The writer is symbolized.
85
+ def writer=(value)
86
+ @writer = value.to_sym
87
+ end
88
+
89
+ def arg_name
90
+ attributes[:arg_name] || name.to_s.upcase
91
+ end
92
+
93
+ def arg_type
94
+ attributes[:arg_type] || :mandatory
95
+ end
96
+
97
+ def long(switch_notation=false, hyphenize=true)
98
+ Configuration.longify(attributes[:long] || name.to_s, switch_notation, hyphenize)
99
+ end
100
+
101
+ def short
102
+ attributes[:short] ? Configuration.shortify(attributes[:short]) : nil
103
+ end
104
+
105
+ def desc
106
+ attributes[:desc]
107
+ end
108
+
109
+ # True if another is a kind of Configuration with the same name,
110
+ # default value, reader and writer; other attributes are NOT
111
+ # taken into account.
112
+ def ==(another)
113
+ another.kind_of?(Configuration) &&
114
+ self.name == another.name &&
115
+ self.reader == another.reader &&
116
+ self.writer == another.writer &&
117
+ self.default(false) == another.default(false)
118
+ end
119
+
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,70 @@
1
+ require 'tap/support/constant_utils'
2
+ class String # :nodoc:
3
+ include Tap::Support::ConstantUtils
4
+ end
5
+
6
+ module Tap
7
+ module Support
8
+ class Constant
9
+
10
+ # The camelized name for self.
11
+ attr_reader :name
12
+
13
+ # The path to load to initialize the constant name.
14
+ attr_reader :require_path
15
+
16
+ def initialize(name, require_path=nil)
17
+ @name = name
18
+ @require_path = require_path
19
+ end
20
+
21
+ # Returns the underscored name.
22
+ def path
23
+ @path ||= name.underscore
24
+ end
25
+
26
+ # Returns the basename of path.
27
+ def basename
28
+ @basename ||= File.basename(path)
29
+ end
30
+
31
+ # Returns the path, minus the basename of path.
32
+ def dirname
33
+ @dirname ||= (dirname = File.dirname(path)) == "." ? "" : dirname
34
+ end
35
+
36
+ # Returns the name of the constant, minus nesting.
37
+ def const_name
38
+ @const_name ||= (name =~ /.*::(.*)$/ ? $1 : name)
39
+ end
40
+
41
+ # Returns an array of the nesting constants of name.
42
+ def nesting
43
+ @nesting ||= (name =~ /(.*)::.*$/ ? $1 : '')
44
+ end
45
+
46
+ # Returns the number of constants in nesting.
47
+ def nesting_depth
48
+ @nesting_depth ||= nesting.split(/::/).length
49
+ end
50
+
51
+ # Returns the document for require_path, if set, or nil otherwise.
52
+ def document
53
+ require_path ? Support::Lazydoc[require_path] : nil
54
+ end
55
+
56
+ def ==(another)
57
+ another.kind_of?(Constant) &&
58
+ another.name == self.name &&
59
+ another.require_path == self.require_path
60
+ end
61
+
62
+ def constantize
63
+ name.try_constantize do |const_name|
64
+ require require_path
65
+ name.constantize
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,127 @@
1
+ module Tap
2
+ module Support
3
+
4
+ # ConstantUtils provides methods for transforming strings into constants.
5
+ # Several methods are directly taken from or based heavily on the
6
+ # ActiveSupport {Inflections}[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
7
+ # module and should not cause conflicts if ActiveSupport is loaded
8
+ # alongside Tap.
9
+ #
10
+ # ActiveSupport is distributed with an MIT-LICENSE:
11
+ #
12
+ # Copyright (c) 2004-2008 David Heinemeier Hansson
13
+ #
14
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
15
+ # associated documentation files (the "Software"), to deal in the Software without restriction,
16
+ # including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
17
+ # and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
18
+ # subject to the following conditions:
19
+ #
20
+ # The above copyright notice and this permission notice shall be included in all copies or substantial
21
+ # portions of the Software.
22
+ #
23
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24
+ # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
25
+ # NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ #
29
+ module ConstantUtils
30
+
31
+ # camelize converts self to UpperCamelCase. If the argument to
32
+ # camelize is set to :lower then camelize produces lowerCamelCase.
33
+ # camelize will also convert '/' to '::' which is useful for
34
+ # converting paths to namespaces.
35
+ def camelize(first_letter = :upper)
36
+ case first_letter
37
+ when :upper then self.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
38
+ when :lower then self.first + camelize[1..-1]
39
+ end
40
+ end
41
+
42
+ # The reverse of camelize. Makes an underscored, lowercase form
43
+ # from self. underscore will also change '::' to '/' to convert
44
+ # namespaces to paths.
45
+ def underscore
46
+ self.gsub(/::/, '/').
47
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
48
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
49
+ tr("-", "_").
50
+ downcase
51
+ end
52
+
53
+ # constantize tries to find a declared constant with the name specified
54
+ # by self. It raises a NameError when the name is not in CamelCase
55
+ # or is not initialized.
56
+ def constantize
57
+ case RUBY_VERSION
58
+ when /^1.9/
59
+
60
+ # a check is necessary to maintain the 1.8 behavior
61
+ # in 1.9, where ancestor constants may be returned
62
+ # by a direct evaluation
63
+ const_name.split("::").inject(Object) do |current, const|
64
+ const = const.to_sym
65
+
66
+ current.const_get(const).tap do |c|
67
+ unless current.const_defined?(const, false)
68
+ raise NameError.new("uninitialized constant #{const_name}")
69
+ end
70
+ end
71
+ end
72
+
73
+ else
74
+ Object.module_eval("::#{const_name}", __FILE__, __LINE__)
75
+ end
76
+ end
77
+
78
+ # Tries to constantize self; if a NameError is raised, try_constantize
79
+ # passes control to the block. Control is only passed if the NameError
80
+ # is for one of the constants in self.
81
+ def try_constantize
82
+ begin
83
+ constantize
84
+ rescue(NameError)
85
+ error_name = $!.name.to_s
86
+ missing_const = const_name.split(/::/).inject(Object) do |current, const|
87
+ if current.const_defined?(const)
88
+ current.const_get(const)
89
+ else
90
+ break(const)
91
+ end
92
+ end
93
+
94
+ # check that the error_name is the first missing constant
95
+ raise $! unless missing_const == error_name
96
+ yield(const_name)
97
+ end
98
+ end
99
+
100
+ def constants_split
101
+ camel_cased_word = camelize
102
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
103
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
104
+ end
105
+
106
+ constants = $1.split(/::/)
107
+ current = Object
108
+ while !constants.empty?
109
+ break unless current.const_defined?(constants[0])
110
+ current = current.const_get(constants.shift)
111
+ end
112
+
113
+ [current, constants]
114
+ end
115
+
116
+ protected
117
+
118
+ def const_name
119
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
120
+ raise NameError, "#{inspect} is not a valid constant name!"
121
+ end
122
+ $1
123
+ end
124
+
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,111 @@
1
+ module Tap
2
+ module Support
3
+ module Declarations
4
+ def self.set_declaration_base(base)
5
+ # TODO -- warn if base is Object -- conflict with Rake
6
+ declaration_base = base.to_s
7
+ declaration_base = "" if ["Object", "Tap"].include?(declaration_base)
8
+
9
+ base.instance_variable_set(:@tap_declaration_base, declaration_base.underscore)
10
+ end
11
+
12
+ def self.included(base)
13
+ set_declaration_base(base)
14
+ end
15
+
16
+ def self.extended(base)
17
+ set_declaration_base(base)
18
+ end
19
+
20
+ def tasc(name, configs={}, options={}, &block)
21
+ Tap::Task.subclass(nest(name), configs, options, &block)
22
+ end
23
+
24
+ def task(name, configs={}, options={}, &block)
25
+ options[:arity] = arity(block)
26
+ tasc(name, configs, options, &task_block(block)).new
27
+ end
28
+
29
+ def file_tasc(name, configs={}, options={}, &block)
30
+ Tap::FileTask.subclass(nest(name), configs, options, &block)
31
+ end
32
+
33
+ def file_task(name, configs={}, options={}, &block)
34
+ options[:arity] = arity(block)
35
+ file_tasc(nest(name), configs, options, &task_block(block)).new
36
+ end
37
+
38
+ def worcflow(name, configs={}, options={}, &block)
39
+ Tap::Workflow.subclass(nest(name), configs, options, &block)
40
+ end
41
+
42
+ def workflow(name, configs={}, options={}, &block)
43
+ options[:arity] = arity(block)
44
+ worcflow(name, configs, options, &task_block(block)).new
45
+ end
46
+
47
+ protected
48
+
49
+ def config(key, value=nil, options={}, &block)
50
+ caller.each_with_index do |line, index|
51
+ case line
52
+ when /^(([A-z]:)?[^:]+):(\d+)/
53
+ options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
54
+ break
55
+ end
56
+ end if options[:desc] == nil
57
+
58
+ [:config, key, value, options, block]
59
+ end
60
+
61
+ def config_attr(key, value=nil, options={}, &block)
62
+ caller.each_with_index do |line, index|
63
+ case line
64
+ when /^(([A-z]:)?[^:]+):(\d+)/
65
+ options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
66
+ break
67
+ end
68
+ end if options[:desc] == nil
69
+
70
+ [:config_attr, key, value, options, block]
71
+ end
72
+
73
+ def c
74
+ Support::Validation
75
+ end
76
+
77
+ private
78
+
79
+ def nest(name)
80
+ # use self if self is a Module or Class,
81
+ # or self.class if self is an instance.
82
+ File.join((self.kind_of?(Module) ? self : self.class).instance_variable_get(:@tap_declaration_base), name.to_s)
83
+ end
84
+
85
+ def arity(block)
86
+ arity = block.arity
87
+
88
+ case
89
+ when arity > 0 then arity -= 1
90
+ when arity < 0 then arity += 1
91
+ end
92
+
93
+ arity
94
+ end
95
+
96
+ def task_block(block)
97
+ lambda do |*inputs|
98
+ inputs.unshift(self)
99
+
100
+ arity = block.arity
101
+ n = inputs.length
102
+ unless n == arity || (arity < 0 && (-1-n) <= arity)
103
+ raise ArgumentError.new("wrong number of arguments (#{n} for #{arity})")
104
+ end
105
+
106
+ block.call(*inputs)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,23 +1,25 @@
1
+ require 'tap/support/audit'
2
+
1
3
  module Tap
2
4
  module Support
3
- # Executable wraps methods to make them executable by App.
5
+ # Executable wraps methods to make them executable by App. Methods are
6
+ # wrapped by extending the object that receives them; the easiest way
7
+ # to make an object executable is to use Object#_method.
4
8
  module Executable
5
9
 
6
10
  # The method called when an Executable is executed via _execute
7
11
  attr_reader :_method_name
8
12
 
9
- # Indicates whether or not to call in multithread mode. Default false.
13
+ # Indicates whether or not to execute in multithread mode.
10
14
  attr_accessor :multithread
11
15
 
12
- # Stores the on complete block. Default is Executable.default_on_complete_block.
16
+ # Stores the on complete block.
13
17
  attr_reader :on_complete_block
14
18
 
15
- protected
16
-
17
- attr_writer :_method_name
18
-
19
19
  public
20
-
20
+
21
+ # Extends obj with Executable and sets up all required variables. The
22
+ # specified method will be called on _execute.
21
23
  def self.initialize(obj, method_name, multithread=false, &on_complete_block)
22
24
  obj.extend Executable
23
25
  obj.instance_variable_set(:@_method_name, method_name)
@@ -26,8 +28,9 @@ module Tap
26
28
  obj
27
29
  end
28
30
 
29
- # Sets a block to receive the results of _call. Raises an error
30
- # if on_complete_block is already set, unless override = true.
31
+ # Sets a block to receive the results of _execute. Raises an error
32
+ # if an on_complete block is already set. Override an existing
33
+ # on_complete block by specifying override = true.
31
34
  #
32
35
  # Note the block recieves an audited result and not
33
36
  # the result itself (see Audit for more information).
@@ -82,15 +85,25 @@ module Tap
82
85
  end
83
86
  end
84
87
 
85
- # Tap extends Object with a convenience method to generate methods
86
- # that can be enqued by App and incorporated into workflows.
88
+ # Tap extends Object with <tt>_method</tt> to generate executable methods
89
+ # that can be enqued by Tap::App and incorporated into workflows.
90
+ #
91
+ # array = []
92
+ # push_to_array = array._method(:push)
93
+ #
94
+ # task = Tap::Task.new
95
+ # task.app.sequence(task, push_to_array)
96
+ #
97
+ # task.enq(1).enq(2,3)
98
+ # task.app.run
99
+ #
100
+ # array # => [[1],[2,3]]
101
+ #
87
102
  class Object
88
103
 
89
- # Makes a Tap::Support::Executable for the Method returned by
90
- # Object#method, setting multithread and the on_complete block
91
- # as specified. The method will be called on _execute.
92
- #
93
- # Returns nil if Object#method returns nil.
104
+ # Initializes a Tap::Support::Executable using the Method returned by
105
+ # Object#method(method_name), setting multithread and the on_complete
106
+ # block as specified. Returns nil if Object#method returns nil.
94
107
  def _method(method_name, multithread=false, &on_complete_block) # :yields: _result
95
108
  return nil unless m = method(method_name)
96
109
  Tap::Support::Executable.initialize(m, :call, multithread, &on_complete_block)