rake-commander 0.4.0 → 0.4.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -1
- data/examples/01_basic_example.rb +3 -1
- data/examples/03_a_chainer_plus_example.rb +3 -2
- data/lib/rake-commander/base/class_auto_loader.rb +10 -1
- data/lib/rake-commander/base/class_inheritable.rb +9 -2
- data/lib/rake-commander/base/custom_error.rb +3 -3
- data/lib/rake-commander/base/object_helpers.rb +6 -1
- data/lib/rake-commander/base.rb +2 -1
- data/lib/rake-commander/option.rb +81 -36
- data/lib/rake-commander/options/arguments.rb +55 -29
- data/lib/rake-commander/options/description.rb +28 -1
- data/lib/rake-commander/options/error/base.rb +6 -2
- data/lib/rake-commander/options/error/handling.rb +12 -3
- data/lib/rake-commander/options/error/invalid_argument.rb +3 -2
- data/lib/rake-commander/options/error/invalid_option.rb +1 -1
- data/lib/rake-commander/options/error/missing_argument.rb +1 -1
- data/lib/rake-commander/options/error.rb +19 -7
- data/lib/rake-commander/options/name.rb +41 -18
- data/lib/rake-commander/options/result.rb +15 -4
- data/lib/rake-commander/options/set.rb +2 -0
- data/lib/rake-commander/options/type.rb +28 -0
- data/lib/rake-commander/options.rb +31 -12
- data/lib/rake-commander/patcher/application/top_level_resume.rb +2 -0
- data/lib/rake-commander/patcher/debug.rb +5 -0
- data/lib/rake-commander/rake_task.rb +13 -4
- data/lib/rake-commander/version.rb +1 -1
- metadata +4 -3
@@ -5,12 +5,39 @@ class RakeCommander
|
|
5
5
|
|
6
6
|
private
|
7
7
|
|
8
|
+
def fetch_desc!(args)
|
9
|
+
descs = args.dup.select do |arg|
|
10
|
+
arg.is_a?(String).tap do |is_string|
|
11
|
+
next unless is_string
|
12
|
+
|
13
|
+
args.delete(arg)
|
14
|
+
end
|
15
|
+
end.uniq
|
16
|
+
|
17
|
+
joined_lines(*descs)
|
18
|
+
end
|
19
|
+
|
8
20
|
def string_to_lines(str, max: DESC_MAX_LENGTH)
|
9
21
|
str.scan(liner_regex(max)).map(&:strip)
|
10
22
|
end
|
11
23
|
|
12
24
|
def liner_regex(len = DESC_MAX_LENGTH)
|
13
|
-
|
25
|
+
/[^\n\r]{0,#{len}}[^ ](?:\s|$)/mi
|
26
|
+
end
|
27
|
+
|
28
|
+
def joined_lines(*lines, join: "\n")
|
29
|
+
lines = lines.compact.map(&:strip).reject(&:empty?)
|
30
|
+
return unless lines.count.positive?
|
31
|
+
|
32
|
+
first = lines.first
|
33
|
+
first = "#{first}." unless first.end_with?('.')
|
34
|
+
|
35
|
+
(lines[1..] || []).reduce(first) do |mem, line|
|
36
|
+
mem = "#{mem}." unless mem.end_with?('.')
|
37
|
+
line = "#{line}." unless line.end_with?('.')
|
38
|
+
|
39
|
+
"#{mem}#{join}#{line}"
|
40
|
+
end
|
14
41
|
end
|
15
42
|
end
|
16
43
|
end
|
@@ -4,7 +4,7 @@ class RakeCommander
|
|
4
4
|
# Base error class that does a rely between OptionParser and RakeCommander errors
|
5
5
|
class Base < RakeCommander::Base::CustomError
|
6
6
|
extend RakeCommander::Options::Name
|
7
|
-
OPTION_REGEX = /(?:argument|option): (?<option>.+)/i
|
7
|
+
OPTION_REGEX = /(?:argument|option): (?<option>.+)/i
|
8
8
|
|
9
9
|
class << self
|
10
10
|
# Helper to check if `error` is this class or any children class
|
@@ -20,14 +20,17 @@ class RakeCommander
|
|
20
20
|
def option_regex(value = :not_used)
|
21
21
|
@option_regex ||= OPTION_REGEX
|
22
22
|
return @option_regex if value == :not_used
|
23
|
+
|
23
24
|
@option_regex = value
|
24
25
|
end
|
25
26
|
|
26
27
|
# Identifies the option `Symbol` (short or name) for a given message
|
27
28
|
def option_sym(message)
|
28
|
-
return
|
29
|
+
return unless (match = message.match(option_regex))
|
30
|
+
|
29
31
|
option = match[:option]
|
30
32
|
return name_word_sym(option) if option.length > 1
|
33
|
+
|
31
34
|
short_sym(option)
|
32
35
|
end
|
33
36
|
end
|
@@ -59,6 +62,7 @@ class RakeCommander
|
|
59
62
|
|
60
63
|
def from_desc
|
61
64
|
return '' unless from
|
65
|
+
|
62
66
|
if from.respond_to?(:name)
|
63
67
|
"(#{from.name}) "
|
64
68
|
elsif from.respond_to?(:to_s)
|
@@ -4,7 +4,8 @@ class RakeCommander
|
|
4
4
|
module Handling
|
5
5
|
class << self
|
6
6
|
def included(base)
|
7
|
-
super
|
7
|
+
super
|
8
|
+
|
8
9
|
base.extend RakeCommander::Base::ClassHelpers
|
9
10
|
base.extend RakeCommander::Base::ClassInheritable
|
10
11
|
base.extend ClassMethods
|
@@ -40,6 +41,7 @@ class RakeCommander
|
|
40
41
|
# @return [Boolean] whether this error is enabled.
|
41
42
|
def error_on_options(action = :not_used, error: RakeCommander::Options::Error::Base, &handler)
|
42
43
|
RakeCommander::Options::Error::Base.require_argument!(error, :error, accept_children: true)
|
44
|
+
|
43
45
|
@options_latest_error = nil
|
44
46
|
@error_on_options ||= {}
|
45
47
|
@error_on_options[error] = action if action != :not_used
|
@@ -82,9 +84,10 @@ class RakeCommander
|
|
82
84
|
action = error_on_options(error: eklass)
|
83
85
|
|
84
86
|
# here is where we ignore the handler (when !action == `true`)
|
85
|
-
raise unless !action || handler = error_on_options_handler(eklass)
|
87
|
+
raise unless !action || (handler = error_on_options_handler(eklass))
|
86
88
|
raise if handler&.call(e, argv, results, leftovers)
|
87
89
|
return leftovers if action == :continue
|
90
|
+
|
88
91
|
puts e.message
|
89
92
|
# https://stackoverflow.com/a/23340693/4352306
|
90
93
|
exit 1
|
@@ -95,7 +98,13 @@ class RakeCommander
|
|
95
98
|
def error_on_options_handler(error = :not_used, &handler)
|
96
99
|
@error_on_options_handler ||= {}
|
97
100
|
return @error_on_options_handler if error == :not_used
|
98
|
-
|
101
|
+
|
102
|
+
RakeCommander::Options::Error::Base.require_argument!(
|
103
|
+
error,
|
104
|
+
:error,
|
105
|
+
accept_children: true
|
106
|
+
)
|
107
|
+
|
99
108
|
@error_on_options_handler[error] = handler if block_given?
|
100
109
|
@error_on_options_handler[error]
|
101
110
|
end
|
@@ -2,12 +2,13 @@ class RakeCommander
|
|
2
2
|
module Options
|
3
3
|
module Error
|
4
4
|
class InvalidArgument < RakeCommander::Options::Error::Base
|
5
|
-
option_regex(/invalid argument: (?<option>.+)/i
|
5
|
+
option_regex(/invalid argument: (?<option>.+)/i)
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
9
|
def to_message(value)
|
10
|
-
return super unless opt = option
|
10
|
+
return super unless (opt = option)
|
11
|
+
|
11
12
|
case value
|
12
13
|
when OptionParser::InvalidArgument
|
13
14
|
super("invalid option argument: #{opt.name_hyphen} (#{opt.short_hyphen})")
|
@@ -3,7 +3,7 @@ class RakeCommander
|
|
3
3
|
module Error
|
4
4
|
# Relates to options with missing required argument (when there's no `default` value)
|
5
5
|
class MissingArgument < RakeCommander::Options::Error::Base
|
6
|
-
option_regex(/missing(?: required|) argument: (?<option>.+)/i
|
6
|
+
option_regex(/missing(?: required|) argument: (?<option>.+)/i)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -11,7 +11,7 @@ class RakeCommander
|
|
11
11
|
module Error
|
12
12
|
class << self
|
13
13
|
def included(base)
|
14
|
-
super
|
14
|
+
super
|
15
15
|
base.send :include, RakeCommander::Options::Error::Handling
|
16
16
|
base.extend ClassMethods
|
17
17
|
end
|
@@ -22,7 +22,7 @@ class RakeCommander
|
|
22
22
|
# @see RakeCommander::Options::Result
|
23
23
|
def parse_options(argv = ARGV, results: {}, leftovers: [], &block)
|
24
24
|
with_error_handling(argv, results, leftovers) do
|
25
|
-
super.tap do
|
25
|
+
super.tap do
|
26
26
|
check_on_leftovers(leftovers)
|
27
27
|
check_required_presence(results)
|
28
28
|
end
|
@@ -37,11 +37,21 @@ class RakeCommander
|
|
37
37
|
raise eklass.new(from: self, option: opt), msg, cause: nil
|
38
38
|
rescue OptionParser::InvalidArgument => e
|
39
39
|
eklass = RakeCommander::Options::Error::InvalidArgument
|
40
|
+
src_e = nil
|
41
|
+
msg = nil
|
40
42
|
opt = error_option(e, eklass)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
|
44
|
+
if opt&.enum?
|
45
|
+
msg = "argument in option #{opt.name_hyphen} (#{opt.short_hyphen}) "
|
46
|
+
msg << "should be any of [#{opt.enum_options.join(' | ')}]"
|
47
|
+
elsif opt&.argument_required?
|
48
|
+
eklass = RakeCommander::Options::Error::MissingArgument
|
49
|
+
msg = "missing required argument in option: #{opt.name_hyphen} (#{opt.short_hyphen})"
|
50
|
+
else
|
51
|
+
src_e = e
|
52
|
+
end
|
53
|
+
|
54
|
+
raise eklass.new(src_e, from: self, option: opt), msg, cause: nil
|
45
55
|
end
|
46
56
|
end
|
47
57
|
|
@@ -53,7 +63,8 @@ class RakeCommander
|
|
53
63
|
# @param eklass [RakeCommander::Options::Error:Base::Class] the error class to retrive the option key
|
54
64
|
# @return [RakeCommander::Option, NilClass]
|
55
65
|
def error_option(err, eklass)
|
56
|
-
return false unless option_sym = eklass.option_sym(err.message)
|
66
|
+
return false unless (option_sym = eklass.option_sym(err.message))
|
67
|
+
|
57
68
|
options_hash(with_implicit: true)[option_sym]
|
58
69
|
end
|
59
70
|
|
@@ -65,6 +76,7 @@ class RakeCommander
|
|
65
76
|
# @return [Hash] the results (same object)
|
66
77
|
def check_on_leftovers(leftovers)
|
67
78
|
return if leftovers.empty?
|
79
|
+
|
68
80
|
eklass = RakeCommander::Options::Error::UnknownArgument
|
69
81
|
raise eklass.new(leftovers, from: self)
|
70
82
|
end
|
@@ -3,31 +3,34 @@ class RakeCommander
|
|
3
3
|
module Name
|
4
4
|
BOOLEAN_TOKEN = '[no-]'.freeze
|
5
5
|
# Substitions
|
6
|
-
HYPHEN_START_REGEX =
|
7
|
-
HYPEN_REGEX =
|
8
|
-
UNDERSCORE_REGEX = /_
|
9
|
-
WORD_DELIMITER = /[\s=]
|
6
|
+
HYPHEN_START_REGEX = /^-+/
|
7
|
+
HYPEN_REGEX = /-+/
|
8
|
+
UNDERSCORE_REGEX = /_+/
|
9
|
+
WORD_DELIMITER = /[\s=]+/
|
10
10
|
# Checkers / Capturers
|
11
|
-
OPTIONAL_REGEX = /\[\w+\]
|
12
|
-
SINGLE_HYPHEN_REGEX = /^-(?<options>[^- ][^ ]*)
|
13
|
-
DOUBLE_HYPHEN_REGEX = /^(?:--\[?no-\]?|--)(?<option>[^- ][^ \r\n]*)
|
14
|
-
BOOLEAN_NAME_REGEX = /^[^ ]*#{Regexp.escape(BOOLEAN_TOKEN)}[^ ]{2,}
|
11
|
+
OPTIONAL_REGEX = /\[\w+\]$/
|
12
|
+
SINGLE_HYPHEN_REGEX = /^-(?<options>[^- ][^ ]*)/
|
13
|
+
DOUBLE_HYPHEN_REGEX = /^(?:--\[?no-\]?|--)(?<option>[^- ][^ \r\n]*).*$/
|
14
|
+
BOOLEAN_NAME_REGEX = /^[^ ]*#{Regexp.escape(BOOLEAN_TOKEN)}[^ ]{2,}/
|
15
15
|
|
16
16
|
# @return [Boolean]
|
17
17
|
def single_hyphen?(value)
|
18
18
|
return false unless value.respond_to?(:to_s)
|
19
|
+
|
19
20
|
!!value.to_s.match(SINGLE_HYPHEN_REGEX)
|
20
21
|
end
|
21
22
|
|
22
23
|
# @return [Boolean]
|
23
24
|
def double_hyphen?(value)
|
24
25
|
return false unless value.respond_to?(:to_s)
|
26
|
+
|
25
27
|
!!value.to_s.match(DOUBLE_HYPHEN_REGEX)
|
26
28
|
end
|
27
29
|
|
28
30
|
# @return [Boolean] whether the name has the boolean switch `[no-]`
|
29
31
|
def boolean_name?(value)
|
30
32
|
return false unless value.respond_to?(:to_s)
|
33
|
+
|
31
34
|
!!value.to_s.match(BOOLEAN_NAME_REGEX)
|
32
35
|
end
|
33
36
|
|
@@ -35,9 +38,11 @@ class RakeCommander
|
|
35
38
|
# @return [Boolean]
|
36
39
|
def valid_short?(value, strict: false)
|
37
40
|
return false unless value.respond_to?(:to_s)
|
41
|
+
|
38
42
|
value = value.to_s.strip
|
39
43
|
return false if value.empty?
|
40
44
|
return false if strict && !single_hyphen?(value)
|
45
|
+
|
41
46
|
value = value.gsub(HYPHEN_START_REGEX, '')
|
42
47
|
value.length == 1
|
43
48
|
end
|
@@ -46,9 +51,11 @@ class RakeCommander
|
|
46
51
|
# @return [Boolean]
|
47
52
|
def valid_name?(value, strict: false)
|
48
53
|
return false unless value.respond_to?(:to_s)
|
54
|
+
|
49
55
|
value = value.to_s.strip
|
50
56
|
return false if value.empty?
|
51
57
|
return false if strict && !double_hyphen?(value)
|
58
|
+
|
52
59
|
name_sym(value).to_s.length > 1
|
53
60
|
end
|
54
61
|
|
@@ -59,6 +66,7 @@ class RakeCommander
|
|
59
66
|
capture_argument_with!(args) do |arg|
|
60
67
|
next false unless arg.is_a?(String) || arg.is_a?(Symbol)
|
61
68
|
next false if symbol && !arg.is_a?(Symbol)
|
69
|
+
|
62
70
|
valid_short?(arg, strict: strict)
|
63
71
|
end
|
64
72
|
end
|
@@ -70,6 +78,7 @@ class RakeCommander
|
|
70
78
|
capture_argument_with!(args) do |arg|
|
71
79
|
next false unless arg.is_a?(String) || arg.is_a?(Symbol)
|
72
80
|
next false if symbol && !arg.is_a?(Symbol)
|
81
|
+
|
73
82
|
valid_name?(arg, strict: strict)
|
74
83
|
end
|
75
84
|
end
|
@@ -79,13 +88,16 @@ class RakeCommander
|
|
79
88
|
# @return [String, Symbol, NilClass] the arg candidate
|
80
89
|
def capture_argument_with!(args)
|
81
90
|
raise ArgumentError, "Expecting Array. Given: #{args.class}" unless args.is_a?(Array)
|
91
|
+
|
82
92
|
args.dup.find.with_index do |arg, i|
|
83
93
|
yield(arg).tap do |valid|
|
84
94
|
next unless valid
|
95
|
+
|
85
96
|
args.slice!(i)
|
86
97
|
return arg
|
87
98
|
end
|
88
99
|
end
|
100
|
+
|
89
101
|
nil
|
90
102
|
end
|
91
103
|
|
@@ -94,10 +106,12 @@ class RakeCommander
|
|
94
106
|
# * `"-d"` becomes `:d`
|
95
107
|
# @return [Symbol, NilClass]
|
96
108
|
def short_sym(value)
|
97
|
-
return
|
109
|
+
return unless value
|
110
|
+
|
98
111
|
value = value.to_s.gsub(BOOLEAN_TOKEN, '')
|
99
112
|
value = value.gsub(HYPHEN_START_REGEX, '')
|
100
|
-
return
|
113
|
+
return unless value = value.chars.first
|
114
|
+
|
101
115
|
value.to_sym
|
102
116
|
end
|
103
117
|
|
@@ -110,11 +124,13 @@ class RakeCommander
|
|
110
124
|
# 3. Replaces any multi-spacing by single space ` `
|
111
125
|
# @return [Symbol, NilClass]
|
112
126
|
def name_sym(value)
|
113
|
-
return
|
127
|
+
return unless value
|
128
|
+
|
114
129
|
value = value.to_s.gsub(HYPHEN_START_REGEX, '')
|
115
130
|
value = value.gsub(HYPEN_REGEX, '_')
|
116
131
|
value = value.gsub(WORD_DELIMITER, ' ')
|
117
|
-
return
|
132
|
+
return if value.empty?
|
133
|
+
|
118
134
|
value.to_sym
|
119
135
|
end
|
120
136
|
|
@@ -128,14 +144,16 @@ class RakeCommander
|
|
128
144
|
# @return [Symbol, NilClass]
|
129
145
|
def name_word_sym(value)
|
130
146
|
value = value.to_s.gsub(BOOLEAN_TOKEN, '')
|
131
|
-
return
|
132
|
-
return
|
147
|
+
return unless (value = name_sym(value))
|
148
|
+
return unless (value = name_words(value).first)
|
149
|
+
|
133
150
|
value.downcase.to_sym
|
134
151
|
end
|
135
152
|
|
136
153
|
# @return [String, NilClass] it returns the hyphened (`-`) version of a short `value`
|
137
154
|
def short_hyphen(value)
|
138
|
-
return
|
155
|
+
return unless (value = short_sym(value))
|
156
|
+
|
139
157
|
"-#{value}"
|
140
158
|
end
|
141
159
|
|
@@ -146,9 +164,11 @@ class RakeCommander
|
|
146
164
|
# * `:there_we_go` becomes `"--there-we-go"`
|
147
165
|
# @return [String, NilClass] option `name` alone double hypened (`--`)
|
148
166
|
def name_hyphen(value)
|
149
|
-
return
|
167
|
+
return unless value = name_sym(value)
|
168
|
+
|
150
169
|
value = value.to_s.gsub(UNDERSCORE_REGEX, '-')
|
151
|
-
return
|
170
|
+
return if value.empty?
|
171
|
+
|
152
172
|
"--#{value}"
|
153
173
|
end
|
154
174
|
|
@@ -174,6 +194,7 @@ class RakeCommander
|
|
174
194
|
# @return [Boolean] `true` if `value` does NOT end with `[String]`
|
175
195
|
def argument_required?(value)
|
176
196
|
return false unless value
|
197
|
+
|
177
198
|
!argument_optional?(value)
|
178
199
|
end
|
179
200
|
|
@@ -185,6 +206,7 @@ class RakeCommander
|
|
185
206
|
# @return [Boolean] `true` if `value` ends with `[String]`
|
186
207
|
def argument_optional?(value)
|
187
208
|
return true unless value
|
209
|
+
|
188
210
|
!!value.match(OPTIONAL_REGEX)
|
189
211
|
end
|
190
212
|
|
@@ -194,7 +216,8 @@ class RakeCommander
|
|
194
216
|
# * `"--there-we-go [ARGUMENT]"` returns `["there-we-go","[ARGUMENT]"]`
|
195
217
|
# @return [Array<String>] the words of `value` without hyphen start
|
196
218
|
def name_words(value)
|
197
|
-
return
|
219
|
+
return unless value
|
220
|
+
|
198
221
|
value = value.to_s.gsub(HYPHEN_START_REGEX, '')
|
199
222
|
value.to_s.split(WORD_DELIMITER)
|
200
223
|
end
|
@@ -3,7 +3,7 @@ class RakeCommander
|
|
3
3
|
module Result
|
4
4
|
class << self
|
5
5
|
def included(base)
|
6
|
-
super
|
6
|
+
super
|
7
7
|
base.extend ClassMethods
|
8
8
|
base.attr_inheritable :options_with_defaults
|
9
9
|
end
|
@@ -46,7 +46,7 @@ class RakeCommander
|
|
46
46
|
# 2. We use `task_context` to open up extensibility.
|
47
47
|
# @todo think if it should rather raise an `ArgumentError` when the task
|
48
48
|
# was not defined in an instance object of his class.
|
49
|
-
def install_task(&task_method)
|
49
|
+
def install_task(&task_method) # rubocop:disable Naming/BlockForwarding
|
50
50
|
super(&task_context(&task_method))
|
51
51
|
end
|
52
52
|
|
@@ -57,6 +57,7 @@ class RakeCommander
|
|
57
57
|
def task_context(&task_method)
|
58
58
|
instance = eval('self', task_method.binding, __FILE__, __LINE__)
|
59
59
|
return task_method unless instance.is_a?(self)
|
60
|
+
|
60
61
|
proc do |*task_args|
|
61
62
|
# launch `ARGV` parsing
|
62
63
|
instance.options
|
@@ -72,6 +73,7 @@ class RakeCommander
|
|
72
73
|
# @return [Proc] the results collector that wraps the middleware.
|
73
74
|
def results_collector(results, &middleware)
|
74
75
|
results = result_defaults(results)
|
76
|
+
|
75
77
|
proc do |value, default, short, name, opt|
|
76
78
|
middleware&.call(value, default, short, name, opt)
|
77
79
|
results[name] = results[short] = value.nil?? default : value
|
@@ -91,12 +93,21 @@ class RakeCommander
|
|
91
93
|
end
|
92
94
|
end
|
93
95
|
|
96
|
+
# INSTANCE METHODS
|
97
|
+
|
94
98
|
# Launches the options parsing of this class.
|
95
99
|
# @return [Hash] keyed by short.
|
96
|
-
def options(argv = ARGV, &block)
|
100
|
+
def options(argv = ARGV, &block) # rubocop:disable Naming/BlockForwarding
|
97
101
|
return @options if instance_variable_defined?(:@options)
|
102
|
+
|
98
103
|
@options = {}
|
99
|
-
self.class.parse_options(
|
104
|
+
self.class.parse_options(
|
105
|
+
argv,
|
106
|
+
results: @options,
|
107
|
+
leftovers: options_leftovers,
|
108
|
+
&block
|
109
|
+
)
|
110
|
+
|
100
111
|
@options
|
101
112
|
end
|
102
113
|
|
@@ -9,11 +9,13 @@ class RakeCommander
|
|
9
9
|
# Name of the `Options::Set`
|
10
10
|
def name(value = :not_used)
|
11
11
|
return @name if value == :not_used
|
12
|
+
|
12
13
|
@name = value.to_sym
|
13
14
|
end
|
14
15
|
|
15
16
|
def each(&block)
|
16
17
|
return to_enum(:each) unless block
|
18
|
+
|
17
19
|
options.each(&block)
|
18
20
|
end
|
19
21
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class RakeCommander
|
2
|
+
module Options
|
3
|
+
module Type
|
4
|
+
ALLOWED_TYPES = [
|
5
|
+
Class,
|
6
|
+
Array
|
7
|
+
].freeze
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def fetch_type!(args)
|
12
|
+
args.dup.select do |arg|
|
13
|
+
allowed_type?(arg).tap do |is_type|
|
14
|
+
next unless is_type
|
15
|
+
|
16
|
+
args.delete(arg)
|
17
|
+
end
|
18
|
+
end.first
|
19
|
+
end
|
20
|
+
|
21
|
+
def allowed_type?(value)
|
22
|
+
ALLOWED_TYPES.any? do |allowed|
|
23
|
+
value.is_a?(allowed)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative 'options/name'
|
2
2
|
require_relative 'options/description'
|
3
|
+
require_relative 'options/type'
|
3
4
|
require_relative 'options/arguments'
|
4
5
|
require_relative 'options/result'
|
5
6
|
require_relative 'options/error'
|
@@ -9,16 +10,20 @@ class RakeCommander
|
|
9
10
|
module Options
|
10
11
|
class << self
|
11
12
|
def included(base)
|
12
|
-
super
|
13
|
+
super
|
14
|
+
|
13
15
|
base.extend RakeCommander::Base::ClassHelpers
|
14
16
|
base.extend RakeCommander::Base::ClassInheritable
|
15
17
|
base.extend ClassMethods
|
16
18
|
base.attr_inheritable :banner
|
19
|
+
|
17
20
|
base.attr_inheritable(:options_hash) do |value, subclass|
|
18
|
-
next
|
21
|
+
next unless value
|
22
|
+
|
19
23
|
value.values.uniq.each {|opt| subclass.send :add_to_options, opt.dup}
|
20
24
|
subclass.send(:options_hash)
|
21
25
|
end
|
26
|
+
|
22
27
|
base.class_resolver :option_class, RakeCommander::Option
|
23
28
|
base.send :include, RakeCommander::Options::Result
|
24
29
|
base.send :include, RakeCommander::Options::Error
|
@@ -30,15 +35,17 @@ class RakeCommander
|
|
30
35
|
# Overrides the auto-generated banner
|
31
36
|
def banner(desc = :not_used)
|
32
37
|
return @banner = desc unless desc == :not_used
|
33
|
-
return @banner
|
34
|
-
|
38
|
+
return @banner if @banner
|
39
|
+
|
40
|
+
task_options_banner if respond_to?(:task_options_banner, true)
|
35
41
|
end
|
36
42
|
|
37
43
|
# Defines a new option or opens for edition an existing one if `reopen: true` is used.
|
38
44
|
# @note
|
39
45
|
# - If override is `true`, it will with a Warning when same `short` or `name` clashes.
|
40
|
-
def option(*args, override: true, reopen: false, **kargs, &block)
|
46
|
+
def option(*args, override: true, reopen: false, **kargs, &block) # rubocop:disable Naming/BlockForwarding, Style/ArgumentsForwarding
|
41
47
|
return option_reopen(*args, override: override, **kargs, &block) if reopen
|
48
|
+
|
42
49
|
opt = option_class.new(*args, **kargs, &block)
|
43
50
|
add_to_options(opt, override: override)
|
44
51
|
end
|
@@ -52,13 +59,15 @@ class RakeCommander
|
|
52
59
|
# 2. It will have the effect of overriding existing options
|
53
60
|
# @note when `short` and `name` are provided, `name` takes precedence over `short`
|
54
61
|
# in the lookup (to identify the existing option)
|
55
|
-
def option_reopen(*args, override: false, **kargs, &block)
|
56
|
-
aux = option_class.new(*args, **kargs, sample: true, &block)
|
62
|
+
def option_reopen(*args, override: false, **kargs, &block) # rubocop:disable Naming/BlockForwarding, Style/ArgumentsForwarding
|
63
|
+
aux = option_class.new(*args, **kargs, sample: true, &block) # rubocop:disable Naming/BlockForwarding, Style/ArgumentsForwarding
|
57
64
|
opt = options_hash.values_at(aux.name, aux.short).compact.first
|
58
65
|
return option(*args, **kargs, &block) unless opt
|
66
|
+
|
59
67
|
mod = {}.tap do |mkargs|
|
60
68
|
mkargs.merge!(name: opt.name_full) if aux.name_full.is_a?(Symbol)
|
61
69
|
end
|
70
|
+
|
62
71
|
replace_in_options(opt, opt.merge(aux, **mod), override: override)
|
63
72
|
end
|
64
73
|
|
@@ -77,10 +86,13 @@ class RakeCommander
|
|
77
86
|
# should be overriden, may they clash
|
78
87
|
# @param options [Enumerable<RakeCommander::Option>]
|
79
88
|
def options_use(opts, override: true)
|
80
|
-
|
89
|
+
msg = "Could not obtain list of RakeCommander::Option from #{opts.class}"
|
90
|
+
raise msg unless (opts = to_options(opts))
|
91
|
+
|
81
92
|
opts.each do |opt|
|
82
93
|
add_to_options(opt.deep_dup, override: override)
|
83
94
|
end
|
95
|
+
|
84
96
|
self
|
85
97
|
end
|
86
98
|
|
@@ -103,6 +115,7 @@ class RakeCommander
|
|
103
115
|
def options_hash(with_implicit: false)
|
104
116
|
@options_hash ||= {}
|
105
117
|
return @options_hash unless with_implicit
|
118
|
+
|
106
119
|
@options_hash.merge(implicit_shorts)
|
107
120
|
end
|
108
121
|
|
@@ -153,7 +166,7 @@ class RakeCommander
|
|
153
166
|
end
|
154
167
|
|
155
168
|
# @return [OptionParser]
|
156
|
-
def new_options_parser(&block)
|
169
|
+
def new_options_parser(&block) # rubocop:disable Naming/BlockForwarding
|
157
170
|
require 'optparse'
|
158
171
|
OptionParser.new(&block)
|
159
172
|
end
|
@@ -180,6 +193,7 @@ class RakeCommander
|
|
180
193
|
# @param opts [OptionParser] where the help will be added.
|
181
194
|
def option_help(opts)
|
182
195
|
return false if option?(:help) || option?(:h)
|
196
|
+
|
183
197
|
option(:h, :help, 'Prints this help') do
|
184
198
|
puts opts
|
185
199
|
exit(0)
|
@@ -212,16 +226,19 @@ class RakeCommander
|
|
212
226
|
# @return [RakeCommander::Option, NilClass] the option that was added, `nil` is returned otherwise.
|
213
227
|
def add_to_options(opt, override: true)
|
214
228
|
name_ref = respond_to?(:name)? " (#{name})" : ''
|
215
|
-
if sprev = option_get(opt.short)
|
229
|
+
if (sprev = option_get(opt.short))
|
216
230
|
return nil unless override
|
217
231
|
puts "Warning#{name_ref}: Overriding option '#{sprev.name}' with short '#{sprev.short}' ('#{opt.name}')"
|
218
232
|
delete_from_options(sprev)
|
219
233
|
end
|
220
|
-
|
221
|
-
|
234
|
+
|
235
|
+
if (nprev = option_get(opt.name))
|
236
|
+
return unless override
|
237
|
+
|
222
238
|
puts "Warning#{name_ref}: Overriding option '#{nprev.short}' with name '#{nprev.name}' ('#{opt.short}')"
|
223
239
|
delete_from_options(nprev)
|
224
240
|
end
|
241
|
+
|
225
242
|
options_hash[opt.name] = options_hash[opt.short] = opt
|
226
243
|
end
|
227
244
|
|
@@ -245,6 +262,7 @@ class RakeCommander
|
|
245
262
|
add_to_options(opt, override: override).tap do |added_opt|
|
246
263
|
# restore previous status
|
247
264
|
next options_hash[ref.short] = options_hash[ref.name] = ref unless added_opt
|
265
|
+
|
248
266
|
delete_empty_keys(options_hash)
|
249
267
|
end
|
250
268
|
end
|
@@ -254,6 +272,7 @@ class RakeCommander
|
|
254
272
|
hash.tap do |_h|
|
255
273
|
hash.dup.each do |k, v|
|
256
274
|
next unless v.nil?
|
275
|
+
|
257
276
|
hash.delete(k)
|
258
277
|
end
|
259
278
|
end
|
@@ -11,11 +11,13 @@ class RakeCommander
|
|
11
11
|
|
12
12
|
def patch_prepend(_invoked_by)
|
13
13
|
return unless target_defined?
|
14
|
+
|
14
15
|
Rake::Application.prepend Patch
|
15
16
|
end
|
16
17
|
|
17
18
|
def target_defined?
|
18
19
|
return true if defined?(target)
|
20
|
+
|
19
21
|
puts "Warning (#{self}): undefined target #{target}"
|
20
22
|
false
|
21
23
|
end
|