tap 0.8.0 → 0.9.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/Basic Overview +151 -0
- data/Command Reference +99 -0
- data/History +24 -0
- data/MIT-LICENSE +1 -1
- data/README +29 -57
- data/Rakefile +30 -37
- data/Tutorial +243 -191
- data/bin/tap +66 -35
- data/lib/tap.rb +47 -29
- data/lib/tap/app.rb +700 -342
- data/lib/tap/{script → cmd}/console.rb +0 -0
- data/lib/tap/{script → cmd}/destroy.rb +0 -0
- data/lib/tap/{script → cmd}/generate.rb +0 -0
- data/lib/tap/cmd/run.rb +156 -0
- data/lib/tap/constants.rb +4 -0
- data/lib/tap/dump.rb +57 -0
- data/lib/tap/env.rb +316 -0
- data/lib/tap/file_task.rb +106 -109
- data/lib/tap/generator.rb +4 -1
- data/lib/tap/generator/generators/command/USAGE +6 -0
- data/lib/tap/generator/generators/command/command_generator.rb +17 -0
- data/lib/tap/generator/generators/{script/templates/script.erb → command/templates/command.erb} +10 -10
- data/lib/tap/generator/generators/config/USAGE +21 -0
- data/lib/tap/generator/generators/config/config_generator.rb +17 -7
- data/lib/tap/generator/generators/file_task/USAGE +3 -0
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -0
- data/lib/tap/generator/generators/file_task/templates/file.txt +2 -0
- data/lib/tap/generator/generators/file_task/templates/file.yml +3 -0
- data/lib/tap/generator/generators/file_task/templates/task.erb +26 -20
- data/lib/tap/generator/generators/file_task/templates/test.erb +20 -10
- data/lib/tap/generator/generators/generator/generator_generator.rb +1 -1
- data/lib/tap/generator/generators/generator/templates/generator.erb +21 -12
- data/lib/tap/generator/generators/root/templates/Rakefile +33 -24
- data/lib/tap/generator/generators/root/templates/tap.yml +28 -31
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +1 -0
- data/lib/tap/generator/generators/task/USAGE +3 -0
- data/lib/tap/generator/generators/task/task_generator.rb +18 -5
- data/lib/tap/generator/generators/task/templates/task.erb +7 -12
- data/lib/tap/generator/generators/task/templates/test.erb +10 -11
- data/lib/tap/generator/generators/workflow/templates/task.erb +1 -1
- data/lib/tap/generator/generators/workflow/templates/test.erb +1 -1
- data/lib/tap/patches/rake/rake_test_loader.rb +8 -0
- data/lib/tap/patches/rake/testtask.rb +55 -0
- data/lib/tap/patches/ruby19/backtrace_filter.rb +51 -0
- data/lib/tap/patches/ruby19/parsedate.rb +16 -0
- data/lib/tap/root.rb +172 -67
- data/lib/tap/script.rb +70 -336
- data/lib/tap/support/aggregator.rb +55 -0
- data/lib/tap/support/audit.rb +281 -280
- data/lib/tap/support/batchable.rb +59 -0
- data/lib/tap/support/class_configuration.rb +279 -0
- data/lib/tap/support/configurable.rb +92 -0
- data/lib/tap/support/configurable_methods.rb +296 -0
- data/lib/tap/support/executable.rb +98 -0
- data/lib/tap/support/executable_queue.rb +82 -0
- data/lib/tap/support/logger.rb +9 -15
- data/lib/tap/support/rake.rb +43 -54
- data/lib/tap/support/run_error.rb +32 -13
- data/lib/tap/support/shell_utils.rb +47 -0
- data/lib/tap/support/tdoc.rb +9 -8
- data/lib/tap/support/tdoc/config_attr.rb +40 -16
- data/lib/tap/support/validation.rb +77 -0
- data/lib/tap/support/versions.rb +36 -36
- data/lib/tap/task.rb +276 -482
- data/lib/tap/test.rb +20 -261
- data/lib/tap/test/env_vars.rb +7 -5
- data/lib/tap/test/file_methods.rb +126 -121
- data/lib/tap/test/subset_methods.rb +86 -45
- data/lib/tap/test/tap_methods.rb +271 -0
- data/lib/tap/workflow.rb +174 -46
- data/test/app/config/another/task.yml +1 -0
- data/test/app/config/erb.yml +2 -1
- data/test/app/config/some/task.yml +1 -0
- data/test/app/config/template.yml +2 -6
- data/test/app_test.rb +1241 -1008
- data/test/env/test_configure/recurse_a.yml +2 -0
- data/test/env/test_configure/recurse_b.yml +2 -0
- data/test/env/test_configure/tap.yml +23 -0
- data/test/env/test_load_env_config/dir/tap.yml +3 -0
- data/test/env/test_load_env_config/recurse_a.yml +2 -0
- data/test/env/test_load_env_config/recurse_b.yml +2 -0
- data/test/env/test_load_env_config/tap.yml +3 -0
- data/test/env_test.rb +198 -0
- data/test/file_task_test.rb +70 -53
- data/{lib/tap/generator/generators/package/USAGE → test/root/file.txt} +0 -0
- data/test/root_test.rb +621 -454
- data/test/script_test.rb +38 -174
- data/test/support/aggregator_test.rb +99 -0
- data/test/support/audit_test.rb +409 -416
- data/test/support/batchable_test.rb +74 -0
- data/test/support/{task_configuration_test.rb → class_configuration_test.rb} +106 -47
- data/test/{task/config/overriding.yml → support/configurable/config/configured.yml} +0 -0
- data/test/support/configurable_test.rb +295 -0
- data/test/support/executable_queue_test.rb +103 -0
- data/test/support/executable_test.rb +38 -0
- data/test/support/logger_test.rb +17 -17
- data/test/support/rake_test.rb +4 -2
- data/test/support/shell_utils_test.rb +24 -0
- data/test/support/tdoc_test.rb +265 -258
- data/test/support/validation_test.rb +54 -0
- data/test/support/versions_test.rb +38 -38
- data/test/tap_test_helper.rb +19 -5
- data/test/tap_test_suite.rb +5 -2
- data/test/task_base_test.rb +13 -104
- data/test/task_syntax_test.rb +300 -0
- data/test/task_test.rb +258 -381
- data/test/test/env_vars_test.rb +40 -40
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/one.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/two.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/one.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/two.txt +0 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/one.txt +0 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/two.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +1 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_different_content}/expected/two.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +1 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_missing_expected_file}/expected/one.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +1 -0
- data/test/test/file_methods_doc/test_sub/expected/one.txt +1 -0
- data/test/test/file_methods_doc/test_sub/expected/two.txt +1 -0
- data/test/test/file_methods_doc/test_sub/input/one.txt +1 -0
- data/test/test/file_methods_doc/test_sub/input/two.txt +1 -0
- data/test/test/file_methods_doc_test.rb +29 -0
- data/test/test/file_methods_test.rb +214 -143
- data/test/test/subset_methods_test.rb +111 -115
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/a.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/b.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/a.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/b.txt +0 -0
- data/test/test/tap_methods_test.rb +399 -0
- data/test/workflow_test.rb +101 -91
- metadata +86 -70
- data/lib/tap/generator/generators/package/package_generator.rb +0 -38
- data/lib/tap/generator/generators/package/templates/package.erb +0 -186
- data/lib/tap/generator/generators/script/USAGE +0 -0
- data/lib/tap/generator/generators/script/script_generator.rb +0 -17
- data/lib/tap/script/run.rb +0 -154
- data/lib/tap/support/batch_queue.rb +0 -162
- data/lib/tap/support/combinator.rb +0 -114
- data/lib/tap/support/task_configuration.rb +0 -169
- data/lib/tap/support/template.rb +0 -81
- data/lib/tap/support/templater.rb +0 -155
- data/lib/tap/version.rb +0 -4
- data/test/app/config/addition_template.yml +0 -6
- data/test/app_class_test.rb +0 -33
- data/test/check/binding_eval.rb +0 -23
- data/test/check/define_method_check.rb +0 -22
- data/test/check/dependencies_check.rb +0 -175
- data/test/check/inheritance_check.rb +0 -22
- data/test/support/batch_queue_test.rb +0 -320
- data/test/support/combinator_test.rb +0 -249
- data/test/support/template_test.rb +0 -122
- data/test/support/templater/erb.txt +0 -2
- data/test/support/templater/erb.yml +0 -2
- data/test/support/templater/somefile.txt +0 -2
- data/test/support/templater_test.rb +0 -192
- data/test/task/config/template.yml +0 -4
- data/test/task_class_test.rb +0 -170
- data/test/task_execute_test.rb +0 -262
- data/test/test/file_methods/test_assert_expected/expected/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/expected/folder/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/input/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/input/folder/file.txt +0 -1
- data/test/test/file_methods/test_assert_files_exist/input/input_1.txt +0 -0
- data/test/test/file_methods/test_assert_files_exist/input/input_2.txt +0 -0
- data/test/test/file_methods/test_file_compare/expected/output_1.txt +0 -3
- data/test/test/file_methods/test_file_compare/expected/output_2.txt +0 -1
- data/test/test/file_methods/test_file_compare/input/input_1.txt +0 -3
- data/test/test/file_methods/test_file_compare/input/input_2.txt +0 -3
- data/test/test/file_methods/test_infer_glob/expected/file.yml +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_1.txt +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_2.txt +0 -0
- data/test/test/file_methods/test_yml_compare/expected/output_1.yml +0 -6
- data/test/test/file_methods/test_yml_compare/expected/output_2.yml +0 -6
- data/test/test/file_methods/test_yml_compare/input/input_1.yml +0 -4
- data/test/test/file_methods/test_yml_compare/input/input_2.yml +0 -4
- data/test/test_test.rb +0 -373
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
require 'enumerator'
|
|
2
|
-
|
|
3
|
-
module Tap
|
|
4
|
-
module Support
|
|
5
|
-
|
|
6
|
-
# Combinator provides a method for iterating over all possible combinations
|
|
7
|
-
# of items in the input sets.
|
|
8
|
-
#
|
|
9
|
-
# c = Combinator.new [1,2], [3,4]
|
|
10
|
-
# c.collect # => [[1,3], [1,4], [2,3], [2,4]]
|
|
11
|
-
#
|
|
12
|
-
# Combinator works by iteratively combining each element from the first set (a)
|
|
13
|
-
# with each element from the second set (b). When more than two sets are given,
|
|
14
|
-
# a Combinator will bundle all but the first set into a new Combinator which
|
|
15
|
-
# then acts as the second set.
|
|
16
|
-
#
|
|
17
|
-
# # Note: each element in a set is arrayified
|
|
18
|
-
# # to simplify creation of the combination.
|
|
19
|
-
#
|
|
20
|
-
# c = Combinator.new [1,2], [3,4], [5,6]
|
|
21
|
-
# c.a # => [[1],[2]]
|
|
22
|
-
# c.b.class # => Combinator
|
|
23
|
-
# c.b.a # => [[3],[4]]
|
|
24
|
-
# c.b.b # => [[5],[6]]
|
|
25
|
-
#
|
|
26
|
-
# Thus when iterating, each Combinator makes it's pairwise combinations and
|
|
27
|
-
# works outwards to the final multi-set combinations.
|
|
28
|
-
class Combinator
|
|
29
|
-
include Enumerable
|
|
30
|
-
|
|
31
|
-
attr_reader :a, :b
|
|
32
|
-
|
|
33
|
-
# Creates a new Combinator. Input sets must be an Array, or nil.
|
|
34
|
-
# Within the Array any objects are allowed for combination.
|
|
35
|
-
def initialize(*sets)
|
|
36
|
-
@a = make_set(sets.shift)
|
|
37
|
-
@b = make_set(*sets)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Returns the sets used to initialize the Combinator, minus any
|
|
41
|
-
# nil or empty sets.
|
|
42
|
-
def sets
|
|
43
|
-
sets_in(a) + sets_in(b)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# True if the Combinator has no combinations.
|
|
47
|
-
def empty?
|
|
48
|
-
a.empty? && b.empty?
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Returns the number of combinations in the Combinator.
|
|
52
|
-
def length
|
|
53
|
-
if a.empty? || b.empty?
|
|
54
|
-
if !a.empty?
|
|
55
|
-
a.length
|
|
56
|
-
elsif !b.empty?
|
|
57
|
-
b.length
|
|
58
|
-
else
|
|
59
|
-
0
|
|
60
|
-
end
|
|
61
|
-
else
|
|
62
|
-
a.length * b.length
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Passes each combination as an array to the input block.
|
|
67
|
-
def each(&block)
|
|
68
|
-
# if either set is empty, iterate only the non-empty set
|
|
69
|
-
# note, the two-step check on each ensures that if both
|
|
70
|
-
# sets are empty, then neither is iterated.
|
|
71
|
-
if a.empty? || b.empty?
|
|
72
|
-
if !a.empty?
|
|
73
|
-
a.each {|aa| yield aa }
|
|
74
|
-
elsif !b.empty?
|
|
75
|
-
b.each {|bb| yield bb }
|
|
76
|
-
end
|
|
77
|
-
else
|
|
78
|
-
# otherwise, iterate all combinations of both
|
|
79
|
-
a.each do |aa|
|
|
80
|
-
b.each do |bb|
|
|
81
|
-
yield aa + bb
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
private
|
|
88
|
-
|
|
89
|
-
def sets_in(set)
|
|
90
|
-
# recursively de-arrayifies each element in the array
|
|
91
|
-
case set
|
|
92
|
-
when Combinator then set.sets
|
|
93
|
-
when Array then set.empty? ? [] : [set.collect {|s| s.first}]
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def make_set(*sets)
|
|
98
|
-
# recieves an array of arrays or combinators
|
|
99
|
-
return Combinator.new(*sets) if sets.length > 1
|
|
100
|
-
return [] if sets.empty?
|
|
101
|
-
|
|
102
|
-
# recursively arrayifies each element in an array
|
|
103
|
-
set = sets.first
|
|
104
|
-
case set
|
|
105
|
-
when Array then set.collect {|s| [s]}
|
|
106
|
-
when nil then []
|
|
107
|
-
else
|
|
108
|
-
raise ArgumentError.new("sets must be arrays or nil")
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
module Tap
|
|
2
|
-
module Support
|
|
3
|
-
# == UNDER CONSTRUCTION
|
|
4
|
-
#
|
|
5
|
-
# TaskConfiguration holds the class configurations defined in a Tap::Task.
|
|
6
|
-
# The configurations are stored as an array of declarations like:
|
|
7
|
-
# [name, default, msg, declaration_class]. In addition, TaskConfiguration
|
|
8
|
-
# collapse the array of declarations into a hash, which acts as the default
|
|
9
|
-
# task configuration.
|
|
10
|
-
#
|
|
11
|
-
# Storing metadata about the configurations, such as the declaration_class,
|
|
12
|
-
# allows the creation of more user-friendly configuration files and facilitates
|
|
13
|
-
# incorporation into command-line applications.
|
|
14
|
-
#
|
|
15
|
-
# In general, users will not have to interact with TaskConfigurations directly.
|
|
16
|
-
#
|
|
17
|
-
# == Example
|
|
18
|
-
#
|
|
19
|
-
# class BaseTask < Tap::Task
|
|
20
|
-
# class_configurations [:one, 1]
|
|
21
|
-
# end
|
|
22
|
-
#
|
|
23
|
-
# BaseTask.configurations.hash # => {:one => 1}
|
|
24
|
-
#
|
|
25
|
-
# class SubTask < BaseTask
|
|
26
|
-
# class_configurations(
|
|
27
|
-
# [:one, 'one', "the first configuration"],
|
|
28
|
-
# [:two, 'two', "the second configuration"])
|
|
29
|
-
# end
|
|
30
|
-
#
|
|
31
|
-
# SubTask.configurations.hash # => {:one => 'one', :two => 'two'}
|
|
32
|
-
#
|
|
33
|
-
# Now you can see how the comments and declaring classes get used in the
|
|
34
|
-
# configuration files. Note that configuration keys are stringified
|
|
35
|
-
# for clarity (this is ok -- they will be symbolized when loaded by a
|
|
36
|
-
# task).
|
|
37
|
-
#
|
|
38
|
-
# [BaseTask.configurations.format_yaml]
|
|
39
|
-
# # BaseTask configuration
|
|
40
|
-
# one: 1
|
|
41
|
-
#
|
|
42
|
-
# [SubTask.configurations.format_yaml]
|
|
43
|
-
# # BaseTask configuration
|
|
44
|
-
# one: one # the first configuration
|
|
45
|
-
#
|
|
46
|
-
# # SubTask configuration
|
|
47
|
-
# two: two # the second configuration
|
|
48
|
-
#
|
|
49
|
-
class TaskConfiguration
|
|
50
|
-
attr_reader :declarations, :default, :attributes
|
|
51
|
-
|
|
52
|
-
include Enumerable
|
|
53
|
-
|
|
54
|
-
def initialize
|
|
55
|
-
@declarations = {}
|
|
56
|
-
@default = {}
|
|
57
|
-
@attributes = {}
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def dup
|
|
61
|
-
# ensure the duplication does not pass along
|
|
62
|
-
# new references to the same objects
|
|
63
|
-
another = TaskConfiguration.new
|
|
64
|
-
another.declarations = self.declarations.dup
|
|
65
|
-
another.default = self.default.dup
|
|
66
|
-
another.attributes = self.attributes.dup
|
|
67
|
-
another
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def empty?
|
|
71
|
-
@declaration.empty?
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def declared?(key)
|
|
75
|
-
default.has_key?(key.to_sym)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def declare(key, declaration_class)
|
|
79
|
-
key = key.to_sym
|
|
80
|
-
|
|
81
|
-
# Check if the key is already declared...
|
|
82
|
-
return if declared?(key)
|
|
83
|
-
|
|
84
|
-
# Add a declaration array if no declaration have been
|
|
85
|
-
# created for the class and append the key
|
|
86
|
-
(declarations[declaration_class] ||= [declarations.length]) << key
|
|
87
|
-
default[key] = nil
|
|
88
|
-
attributes[key] = {}
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def set(key, value, attributes={})
|
|
92
|
-
key = key.to_sym
|
|
93
|
-
raise "configurations cannot be set until they are declared" unless declared?(key)
|
|
94
|
-
|
|
95
|
-
default[key] = value
|
|
96
|
-
self.attributes[key].merge!(attributes)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def each # :yields: declaration_class, key, default, attributes
|
|
100
|
-
declarations.each_pair do |declaration_class, keys|
|
|
101
|
-
keys[1..-1].each do |key|
|
|
102
|
-
yield(declaration_class, key, default[key], attributes[key])
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# Nicely formats the configurations into yaml with messages and
|
|
108
|
-
# declaration class divisions.
|
|
109
|
-
def format_yaml
|
|
110
|
-
lines = []
|
|
111
|
-
declarations.each_pair do |declaration_class, keys|
|
|
112
|
-
lines << "# #{declaration_class} configuration#{keys.length > 2 ? 's' : ''}"
|
|
113
|
-
|
|
114
|
-
class_name = declaration_class.to_s
|
|
115
|
-
class_path = class_name.underscore
|
|
116
|
-
source_file = Dependencies.search_for_file(class_path)
|
|
117
|
-
|
|
118
|
-
Tap::Support::TDoc.document(source_file)
|
|
119
|
-
class_doc = Tap::Support::TDoc[declaration_class]
|
|
120
|
-
configurations = (class_doc == nil ? [] : class_doc.configurations)
|
|
121
|
-
|
|
122
|
-
keys[1..-1].each do |key|
|
|
123
|
-
value = default[key]
|
|
124
|
-
attribs = attributes[key]
|
|
125
|
-
message = ""
|
|
126
|
-
configurations.each do |config|
|
|
127
|
-
if config.name == key.to_s
|
|
128
|
-
message = config.comment
|
|
129
|
-
break
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# yaml adds a header and a final newline which should be removed:
|
|
134
|
-
# {'key' => 'value'}.to_yaml # => "--- \nkey: value\n"
|
|
135
|
-
# {'key' => 'value'}.to_yaml[5...-1] # => "key: value"
|
|
136
|
-
yaml = {key.to_s => value}.to_yaml[5...-1]
|
|
137
|
-
#yaml = "##{yaml}" if value.nil?
|
|
138
|
-
|
|
139
|
-
lines << case
|
|
140
|
-
when message == nil || message.empty?
|
|
141
|
-
# if there is no message, simply add the yaml
|
|
142
|
-
yaml
|
|
143
|
-
when yaml !~ /\r?\n/ && message !~ /\r?\n/ && yaml.length < 20 && message.length < 30
|
|
144
|
-
# shorthand ONLY if the config and message can be expressed in a single line
|
|
145
|
-
message = message.gsub(/^#\s*/, "")
|
|
146
|
-
"%-20s # %s" % [yaml, message]
|
|
147
|
-
else
|
|
148
|
-
# comment out new lines and add the message
|
|
149
|
-
message = message.gsub(/\n#\s*/, "\n# ")
|
|
150
|
-
lines << "# #{message}"
|
|
151
|
-
yaml
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# add a spacer line
|
|
156
|
-
lines << ""
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
lines.join("\n")
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
protected
|
|
164
|
-
|
|
165
|
-
attr_writer :declarations, :default, :attributes
|
|
166
|
-
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
data/lib/tap/support/template.rb
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
require 'tap/support/combinator'
|
|
2
|
-
|
|
3
|
-
module Tap
|
|
4
|
-
module Support
|
|
5
|
-
|
|
6
|
-
# Template provides the default methods for making hash templates using Templater.
|
|
7
|
-
# Methods are provided to make variations of the template, as well as to pattern
|
|
8
|
-
# templates based on combinations of possible values.
|
|
9
|
-
#
|
|
10
|
-
module Template
|
|
11
|
-
attr_accessor :templater
|
|
12
|
-
|
|
13
|
-
# Provides a standard way of creating a variations of a template and takes an
|
|
14
|
-
# array of hashes with the specified variations. The template is treated as the
|
|
15
|
-
# default and variations are pushed (<<) to the templater. The template is
|
|
16
|
-
# cleared upon complete, so that it will be removed if used in the context of
|
|
17
|
-
# a Templater.
|
|
18
|
-
#
|
|
19
|
-
# t = {"default" => "default value"}.extend Template
|
|
20
|
-
# t.templater = []
|
|
21
|
-
# t.variations([
|
|
22
|
-
# {"default" => "non-default value"},
|
|
23
|
-
# {"another" => "value"}])
|
|
24
|
-
#
|
|
25
|
-
# t.templater
|
|
26
|
-
# # => [{"default" => "non-default value"},
|
|
27
|
-
# {"default" => "default value", "another" => "value"}]
|
|
28
|
-
#
|
|
29
|
-
def variations(array)
|
|
30
|
-
variations!(array)
|
|
31
|
-
self.clear
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Same as variations but does NOT clear the template (ie the template will
|
|
35
|
-
# be kept as specified, effectively acting as another variant). Note that
|
|
36
|
-
# variations! is called by the 'variations!!' key.
|
|
37
|
-
def variations!(array)
|
|
38
|
-
array.each { |var| templater << self.merge(var) }
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Provides a standard way of creating variations of a template based on all
|
|
42
|
-
# combinations of the keys in the input hash. The template itself is treated
|
|
43
|
-
# as the default and variations are pushed (<<) to the templater. The template
|
|
44
|
-
# is cleared upon complete, so that it will be removed if used in the context of
|
|
45
|
-
# a Templater.
|
|
46
|
-
#
|
|
47
|
-
# t = {"default" => "default value"}.extend Template
|
|
48
|
-
# t.templater = []
|
|
49
|
-
# t.combinations(
|
|
50
|
-
# "letter" => ["a", "b"],
|
|
51
|
-
# "number" => [1, 2])
|
|
52
|
-
#
|
|
53
|
-
# t.templater
|
|
54
|
-
# # => [{"default" => "default value", "letter" => "a", "number" => 1},
|
|
55
|
-
# {"default" => "default value", "letter" => "a", "number" => 2},
|
|
56
|
-
# {"default" => "default value", "letter" => "b", "number" => 1},
|
|
57
|
-
# {"default" => "default value", "letter" => "b", "number" => 2}]
|
|
58
|
-
def combinations(hash)
|
|
59
|
-
combinations!(hash)
|
|
60
|
-
self.clear
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Same as combinations but does NOT clear the template (ie the template will
|
|
64
|
-
# be kept as specified, effectively acting as another variant). Note that
|
|
65
|
-
# combinations! is called by the 'combinations!!' key.
|
|
66
|
-
def combinations!(hash)
|
|
67
|
-
keys, values = hash.to_a.transpose
|
|
68
|
-
values.collect! do |value|
|
|
69
|
-
value.kind_of?(Array) ? value : [value]
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
Combinator.new(*values).each do |c|
|
|
73
|
-
template = {}
|
|
74
|
-
keys.each_with_index {|key,i| template[key] = c[i] }
|
|
75
|
-
|
|
76
|
-
templater << self.merge(template)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
require 'tap/support/template'
|
|
2
|
-
|
|
3
|
-
module Tap
|
|
4
|
-
module Support
|
|
5
|
-
|
|
6
|
-
# Templater generates permutations of a hash, treating it as a template for other
|
|
7
|
-
# hashes. Templater looks for various flags on the end of keys to signify operations
|
|
8
|
-
# like method execution ('!') and replacement ('=').
|
|
9
|
-
#
|
|
10
|
-
# module TemplateMethods
|
|
11
|
-
# def method_call(input)
|
|
12
|
-
# self["result"] = "#{input} was processed"
|
|
13
|
-
# end
|
|
14
|
-
# end
|
|
15
|
-
#
|
|
16
|
-
# t = Templater.new(
|
|
17
|
-
# "key"=> "value",
|
|
18
|
-
# "method_call!" => "method input",
|
|
19
|
-
# "replacement=" => "replacement input")
|
|
20
|
-
# t.run_methods(TemplateMethods)
|
|
21
|
-
# t.run_replace do |input|
|
|
22
|
-
# "#{input} was replaced"
|
|
23
|
-
# end
|
|
24
|
-
#
|
|
25
|
-
# t.templates
|
|
26
|
-
# # => [{"key" => "value",
|
|
27
|
-
# "result" => "method input was processed",
|
|
28
|
-
# "replacement" => "replacement input was replaced"}]
|
|
29
|
-
#
|
|
30
|
-
# == Creating Template Methods
|
|
31
|
-
#
|
|
32
|
-
# The default Template methods may not be sufficient for your needs, but making new
|
|
33
|
-
# methods (as above) is easy. Some simple rules apply:
|
|
34
|
-
#
|
|
35
|
-
# - Any method can be called from run_methods provided it has a single input.
|
|
36
|
-
# - Modules with the methods will extend the hash templates so 'self' indicates the
|
|
37
|
-
# template itself.
|
|
38
|
-
# - New templates should be added by pushing the template to the templater, which
|
|
39
|
-
# will already be set by the time the method executes
|
|
40
|
-
# (ex: self.templater << new_template).
|
|
41
|
-
#
|
|
42
|
-
# Also, it's important to note that ANY empty templates at the end of run_methods
|
|
43
|
-
# are cleared from the templates array. Thus, if you want to remove a template from
|
|
44
|
-
# within a method, simply clear self.
|
|
45
|
-
#
|
|
46
|
-
# See the Template code for examples.
|
|
47
|
-
class Templater
|
|
48
|
-
|
|
49
|
-
# Convenience method for making a new Templater, running methods
|
|
50
|
-
# with the input modules, and making replacements using the input
|
|
51
|
-
# block. Returns the resulting templates.
|
|
52
|
-
def self.make_templates(hash, *modules, &block)
|
|
53
|
-
t = Templater.new(hash)
|
|
54
|
-
t.run_methods(*modules)
|
|
55
|
-
t.run_replace(&block)
|
|
56
|
-
t.templates
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
attr_reader :templates
|
|
60
|
-
|
|
61
|
-
# Creates a new Templater with the input hash as the initial template.
|
|
62
|
-
def initialize(hash)
|
|
63
|
-
@templates = []
|
|
64
|
-
self << hash
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Shortcut to add a template to the templater, unless the template is empty.
|
|
68
|
-
def <<(template)
|
|
69
|
-
self.templates << template unless template.empty?
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Iterates through the pairs in each template looking for keys matching the
|
|
73
|
-
# regexp (using =~). When a matching key is found, it is removed from the
|
|
74
|
-
# template and then the template, the key, and the corresponding value are
|
|
75
|
-
# passed to the block for further processing. Iteration restarts after each
|
|
76
|
-
# match and empty templates are removed upon completion. All templates are
|
|
77
|
-
# extended with Template before iteration.
|
|
78
|
-
#
|
|
79
|
-
# Notes:
|
|
80
|
-
# - run_templater is the foundation of the other run_* methods and may be used
|
|
81
|
-
# for custom template processing.
|
|
82
|
-
# - since =~ is used for comparison, only String keys will be selected
|
|
83
|
-
# under normal circumstances.
|
|
84
|
-
def run_templater(regexp) # :yields: template, key, value
|
|
85
|
-
templates.each do |template|
|
|
86
|
-
unless template.respond_to?(:templater)
|
|
87
|
-
template.extend Template
|
|
88
|
-
template.templater = self
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
template.each_pair do |key, value|
|
|
92
|
-
next unless key =~ regexp
|
|
93
|
-
|
|
94
|
-
# remove the key
|
|
95
|
-
template.delete(key)
|
|
96
|
-
yield(template, key, value)
|
|
97
|
-
|
|
98
|
-
# restart the loop as key/value pairs may have changed
|
|
99
|
-
retry
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
templates.delete_if {|t| t.empty?}
|
|
104
|
-
|
|
105
|
-
self
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
# Iterates through the pairs in each template looking for and executing method calls
|
|
109
|
-
# as per run_templater. Method calls are indicated by an exclamation attached to the
|
|
110
|
-
# key, like 'do_something!'.
|
|
111
|
-
#
|
|
112
|
-
# Templates are extended with the input modules before the method call. The modules
|
|
113
|
-
# should provide the methods (an error will be raised if the specified method is not
|
|
114
|
-
# defined). Note, templates will by default be extended with the Template module.
|
|
115
|
-
#
|
|
116
|
-
# module MethodModule
|
|
117
|
-
# def method_call(input)
|
|
118
|
-
# self["result"] = "#{input} was processed"
|
|
119
|
-
# end
|
|
120
|
-
# end
|
|
121
|
-
#
|
|
122
|
-
# t = Templater.new('method_call!' => 'input')
|
|
123
|
-
# t.run_methods(MethodModule) # calls 'do_something' with the input 'some value',
|
|
124
|
-
# # after removing the key-value pair
|
|
125
|
-
# t.templates # => [{"result" => "input was processed"}]
|
|
126
|
-
#
|
|
127
|
-
# Notes:
|
|
128
|
-
# - The method called is the method minus the exclamation, so 'do_something!' calls
|
|
129
|
-
# 'do_something' within the template and 'do_something!!' calls 'do_something!'
|
|
130
|
-
# - Iteration restarts after each method call; inserted method calls will be executed
|
|
131
|
-
def run_methods(*modules)
|
|
132
|
-
run_templater(/!$/) do |template, key, value|
|
|
133
|
-
modules.each {|mod| template.extend mod}
|
|
134
|
-
template.send(key.chop, value)
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Iterates through the pairs in each template looking for replacement keys and
|
|
139
|
-
# executing the block to make the appropriate replacement value, as per
|
|
140
|
-
# run_templater. Replacement keys are indicated by an equals sign attached to
|
|
141
|
-
# the key, like 'key='. The equals sign will be chopped off for these keys, and
|
|
142
|
-
# the value replaced with the return value of the block.
|
|
143
|
-
#
|
|
144
|
-
# t = Templater.new('replacement=' => 'some value')
|
|
145
|
-
# t.run_replace {|value| "#{value} was replaced"}
|
|
146
|
-
# t.templates # => [{"replacement" => "some value was replaced"}]
|
|
147
|
-
#
|
|
148
|
-
def run_replace # :yields: value
|
|
149
|
-
run_templater(/=$/) do |template, key, value|
|
|
150
|
-
template[key.chop] = yield(value)
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|