consoler 1.0.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/tests.yml +34 -0
- data/.rubocop.yml +45 -0
- data/README.md +50 -37
- data/consoler.gemspec +4 -3
- data/lib/consoler/application.rb +73 -29
- data/lib/consoler/arguments.rb +0 -1
- data/lib/consoler/command.rb +0 -1
- data/lib/consoler/matcher.rb +73 -49
- data/lib/consoler/option.rb +75 -27
- data/lib/consoler/options.rb +34 -17
- data/lib/consoler/version.rb +1 -2
- metadata +23 -23
- data/.travis.yml +0 -11
data/lib/consoler/matcher.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Consoler
|
4
|
-
|
5
4
|
# Argument/Options matcher
|
6
5
|
#
|
7
6
|
# Given a list of arguments and a list option try to match them
|
8
7
|
class Matcher
|
9
|
-
|
10
8
|
# Create a matcher
|
11
9
|
#
|
12
10
|
# @param [Consoler::Arguments] arguments List of arguments
|
@@ -27,14 +25,14 @@ module Consoler
|
|
27
25
|
parse_options = true
|
28
26
|
|
29
27
|
_loop_args do |arg|
|
30
|
-
unless parse_options
|
28
|
+
unless parse_options
|
31
29
|
@argument_values.push arg
|
32
30
|
next
|
33
31
|
end
|
34
32
|
|
35
33
|
# when "argument" is --, then stop parsing the rest of the arguments
|
36
34
|
# and treat the rest as regular arguments
|
37
|
-
if arg == '--'
|
35
|
+
if arg == '--'
|
38
36
|
parse_options = false
|
39
37
|
next
|
40
38
|
end
|
@@ -49,12 +47,20 @@ module Consoler
|
|
49
47
|
remaining = _match_arguments
|
50
48
|
_fill_defaults
|
51
49
|
|
52
|
-
if @matched_options.size == @options.size
|
50
|
+
if @matched_options.size == @options.size
|
53
51
|
@matched_options['remaining'] = remaining
|
52
|
+
|
53
|
+
# make sure all aliases are also filled
|
54
|
+
@options.each do |option|
|
55
|
+
option.aliases.each do |alias_|
|
56
|
+
@matched_options[alias_.name] = @matched_options[option.name]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
54
60
|
return @matched_options
|
55
61
|
end
|
56
62
|
|
57
|
-
|
63
|
+
nil
|
58
64
|
end
|
59
65
|
|
60
66
|
private
|
@@ -68,59 +74,58 @@ module Consoler
|
|
68
74
|
is_short = false
|
69
75
|
name = nil
|
70
76
|
|
71
|
-
if arg[0..1] == '--'
|
77
|
+
if arg[0..1] == '--'
|
72
78
|
is_long = true
|
73
79
|
name = arg[2..-1]
|
74
|
-
elsif arg[0] == '-'
|
80
|
+
elsif arg[0] == '-'
|
75
81
|
is_short = true
|
76
82
|
name = arg[1..-1]
|
77
83
|
end
|
78
84
|
|
79
85
|
# arg is not a long/short option, add to arguments values
|
80
|
-
unless is_long
|
86
|
+
unless is_long || is_short
|
81
87
|
@argument_values.push arg
|
82
88
|
return true
|
83
89
|
end
|
84
90
|
|
85
|
-
unless name.nil?
|
91
|
+
unless name.nil?
|
86
92
|
# get the name of the option, short options use the first character
|
87
|
-
option_name = if is_short
|
93
|
+
option_name = if is_short
|
88
94
|
name[0]
|
89
95
|
else
|
90
96
|
name
|
91
97
|
end
|
92
98
|
|
93
|
-
option = @options.
|
99
|
+
option, matched = @options.get_with_alias option_name
|
94
100
|
|
95
101
|
# no option by this name in options
|
96
102
|
return nil if option.nil?
|
97
103
|
|
98
|
-
needs_short = option.is_short
|
99
|
-
needs_long = option.is_long
|
100
|
-
|
101
104
|
# see if the type if right, short or long
|
102
|
-
if
|
105
|
+
if matched.is_long && !is_long
|
103
106
|
return nil
|
104
|
-
elsif
|
107
|
+
elsif matched.is_short && !is_short
|
105
108
|
return nil
|
106
109
|
end
|
107
110
|
|
108
|
-
if is_long
|
109
|
-
if option.is_value
|
111
|
+
if is_long
|
112
|
+
if option.is_value
|
110
113
|
# is_value needs a next argument for its value
|
111
114
|
return nil if _peek_next.nil?
|
112
|
-
|
115
|
+
|
116
|
+
@matched_options[option.name] = _peek_next
|
113
117
|
_skip_next
|
114
118
|
else
|
115
|
-
|
119
|
+
option_value! option
|
116
120
|
end
|
117
121
|
end
|
118
122
|
|
119
|
-
if is_short
|
120
|
-
if name.size == 1
|
123
|
+
if is_short
|
124
|
+
if name.size == 1 && option.is_value
|
121
125
|
# is_value needs a next argument for its value
|
122
126
|
return nil if _peek_next.nil?
|
123
|
-
|
127
|
+
|
128
|
+
@matched_options[option.name] = _peek_next
|
124
129
|
_skip_next
|
125
130
|
else
|
126
131
|
# for every character (short option) increment the option value
|
@@ -128,17 +133,30 @@ module Consoler
|
|
128
133
|
short_option = @options.get n
|
129
134
|
return nil if short_option.nil?
|
130
135
|
|
131
|
-
|
132
|
-
@matched_options[n] = 0
|
133
|
-
end
|
134
|
-
|
135
|
-
@matched_options[n] += 1
|
136
|
+
option_value! short_option
|
136
137
|
end
|
137
138
|
end
|
138
139
|
end
|
139
140
|
end
|
140
141
|
|
141
|
-
|
142
|
+
true
|
143
|
+
end
|
144
|
+
|
145
|
+
# Set the value of an option
|
146
|
+
#
|
147
|
+
# Long or short option needed
|
148
|
+
#
|
149
|
+
# @param [Consoler::Option]
|
150
|
+
def option_value!(option)
|
151
|
+
if option.is_short
|
152
|
+
if @matched_options[option.name].nil?
|
153
|
+
@matched_options[option.name] = 0
|
154
|
+
end
|
155
|
+
|
156
|
+
@matched_options[option.name] += 1
|
157
|
+
else
|
158
|
+
@matched_options[option.name] = true
|
159
|
+
end
|
142
160
|
end
|
143
161
|
|
144
162
|
# Loop through the arguments
|
@@ -151,7 +169,7 @@ module Consoler
|
|
151
169
|
|
152
170
|
# use an incrementing index, to be able to peek to the next in the list
|
153
171
|
# and to skip an item
|
154
|
-
while @index < size
|
172
|
+
while @index < size
|
155
173
|
yield @arguments.args[@index]
|
156
174
|
|
157
175
|
_skip_next
|
@@ -183,11 +201,13 @@ module Consoler
|
|
183
201
|
|
184
202
|
# Match arguments to defined option arguments
|
185
203
|
#
|
186
|
-
# @return [Array<String
|
204
|
+
# @return [Array<String>, nil] The remaining args,
|
205
|
+
# or <tt>nil</tt> if there are not enough arguments
|
187
206
|
def _match_arguments
|
188
207
|
@optionals_before = {}
|
189
208
|
@optionals_before_has_remaining = false
|
190
209
|
|
210
|
+
total_argument_values = @argument_values.size
|
191
211
|
argument_values_index = 0
|
192
212
|
|
193
213
|
_match_arguments_optionals_before
|
@@ -197,7 +217,9 @@ module Consoler
|
|
197
217
|
# arguments supplied (info available from optionals map)
|
198
218
|
optionals.each do |_, optional|
|
199
219
|
optional.each do |before|
|
200
|
-
if before[:included]
|
220
|
+
if before[:included]
|
221
|
+
return nil if argument_values_index >= total_argument_values
|
222
|
+
|
201
223
|
@matched_options[before[:name]] = @argument_values[argument_values_index]
|
202
224
|
argument_values_index += 1
|
203
225
|
end
|
@@ -205,7 +227,9 @@ module Consoler
|
|
205
227
|
end
|
206
228
|
|
207
229
|
# only fill mandatory argument if its not the :REMAINING key
|
208
|
-
if mandatory_arg_name != :REMAINING
|
230
|
+
if mandatory_arg_name != :REMAINING
|
231
|
+
return nil if argument_values_index >= total_argument_values
|
232
|
+
|
209
233
|
@matched_options[mandatory_arg_name] = @argument_values[argument_values_index]
|
210
234
|
argument_values_index += 1
|
211
235
|
end
|
@@ -214,7 +238,7 @@ module Consoler
|
|
214
238
|
remaining = []
|
215
239
|
|
216
240
|
# left over arguments
|
217
|
-
while argument_values_index < @argument_values.size
|
241
|
+
while argument_values_index < @argument_values.size
|
218
242
|
remaining.push @argument_values[argument_values_index]
|
219
243
|
argument_values_index += 1
|
220
244
|
end
|
@@ -229,18 +253,18 @@ module Consoler
|
|
229
253
|
@optionals_before = {}
|
230
254
|
tracker = {}
|
231
255
|
|
232
|
-
@options.each do |option,
|
256
|
+
@options.each do |option, _key|
|
233
257
|
next unless option.is_argument
|
234
258
|
|
235
|
-
if option.is_optional
|
259
|
+
if option.is_optional
|
236
260
|
# setup tracker for optional group
|
237
261
|
tracker[option.is_optional] = [] if tracker[option.is_optional].nil?
|
238
262
|
|
239
263
|
# mark all optionals as not-included
|
240
|
-
tracker[option.is_optional].push(
|
264
|
+
tracker[option.is_optional].push(
|
241
265
|
included: false,
|
242
266
|
name: option.name,
|
243
|
-
|
267
|
+
)
|
244
268
|
else
|
245
269
|
@optionals_before[option.name] = tracker
|
246
270
|
tracker = {}
|
@@ -248,7 +272,7 @@ module Consoler
|
|
248
272
|
end
|
249
273
|
|
250
274
|
# make sure all optionals are accounted for in the map
|
251
|
-
if tracker != {}
|
275
|
+
if tracker != {}
|
252
276
|
# use a special key so we can handle it differently in the filling process
|
253
277
|
@optionals_before[:REMAINING] = tracker
|
254
278
|
@optionals_before_has_remaining = true
|
@@ -267,7 +291,7 @@ module Consoler
|
|
267
291
|
mandatories_matched = @optionals_before.size
|
268
292
|
|
269
293
|
# there are optionals at the end of the options, don't match the void
|
270
|
-
if @optionals_before_has_remaining
|
294
|
+
if @optionals_before_has_remaining
|
271
295
|
mandatories_matched -= 1
|
272
296
|
end
|
273
297
|
|
@@ -276,11 +300,11 @@ module Consoler
|
|
276
300
|
# loop through optional map
|
277
301
|
_each_optional_before_sorted do |before|
|
278
302
|
# are there enough arguments left to fill this optional group
|
279
|
-
if (total + before.size + mandatories_matched) <= @argument_values.size
|
303
|
+
if (total + before.size + mandatories_matched) <= @argument_values.size
|
280
304
|
total += before.size
|
281
305
|
|
282
306
|
before.each do |val|
|
283
|
-
val[:included] = true
|
307
|
+
val[:included] = true
|
284
308
|
end
|
285
309
|
end
|
286
310
|
end
|
@@ -293,10 +317,10 @@ module Consoler
|
|
293
317
|
# @return [Consoler::Matcher]
|
294
318
|
def _fill_defaults
|
295
319
|
@options.each do |option|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
320
|
+
next unless option.is_optional
|
321
|
+
|
322
|
+
unless @matched_options.key? option.name
|
323
|
+
@matched_options[option.name] = option.default_value
|
300
324
|
end
|
301
325
|
end
|
302
326
|
|
@@ -312,10 +336,10 @@ module Consoler
|
|
312
336
|
@optionals_before.each do |_, optionals|
|
313
337
|
tmp = []
|
314
338
|
optionals.each do |optional_index, before|
|
315
|
-
tmp.push(
|
339
|
+
tmp.push(
|
316
340
|
count: before.size,
|
317
341
|
index: optional_index,
|
318
|
-
|
342
|
+
)
|
319
343
|
end
|
320
344
|
|
321
345
|
tmp.sort! { |a, b| b[:count] - a[:count] }.each do |item|
|
data/lib/consoler/option.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Consoler
|
4
|
-
|
5
4
|
# Represents an option
|
6
5
|
#
|
7
6
|
# @attr_reader [String] name Name of the options
|
@@ -10,6 +9,7 @@ module Consoler
|
|
10
9
|
# @attr_reader [Boolean] is_argument Is the option an argument
|
11
10
|
# @attr_reader [Boolean] is_value Does the option need a value (<tt>--option=</tt>)
|
12
11
|
# @attr_reader [Integer] is_optional Is the option optional (> 0) (<tt>[option]</tt>)
|
12
|
+
# @attr_reader [Array] aliases List of aliases of option (<tt>-v|--verbose</tt>)
|
13
13
|
class Option
|
14
14
|
attr_reader :name
|
15
15
|
attr_reader :is_long
|
@@ -17,6 +17,7 @@ module Consoler
|
|
17
17
|
attr_reader :is_argument
|
18
18
|
attr_reader :is_value
|
19
19
|
attr_reader :is_optional
|
20
|
+
attr_reader :aliases
|
20
21
|
|
21
22
|
# Create a option
|
22
23
|
#
|
@@ -28,13 +29,13 @@ module Consoler
|
|
28
29
|
option = Option.new option_def, tracker
|
29
30
|
|
30
31
|
# split short options with more than 1 char in multiple options
|
31
|
-
if option.is_short
|
32
|
+
if option.is_short && option.name.size > 1
|
32
33
|
# remember state
|
33
34
|
old_tracking = tracker.is_tracking
|
34
35
|
old_is_value = option.is_value
|
35
36
|
|
36
37
|
# if the complete option is optional, fake the tracker
|
37
|
-
if option.is_optional
|
38
|
+
if option.is_optional
|
38
39
|
tracker.is_tracking = true
|
39
40
|
end
|
40
41
|
|
@@ -44,7 +45,7 @@ module Consoler
|
|
44
45
|
new_name = "-#{name}"
|
45
46
|
|
46
47
|
# if the short option should have a value, this only counts for the last option
|
47
|
-
if old_is_value
|
48
|
+
if old_is_value && i == names.count - 1
|
48
49
|
new_name = "#{new_name}="
|
49
50
|
end
|
50
51
|
|
@@ -67,14 +68,20 @@ module Consoler
|
|
67
68
|
def to_definition
|
68
69
|
definition = name
|
69
70
|
|
70
|
-
if is_long
|
71
|
+
if is_long
|
71
72
|
definition = "--#{definition}"
|
72
|
-
elsif is_short
|
73
|
+
elsif is_short
|
73
74
|
definition = "-#{definition}"
|
74
75
|
end
|
75
76
|
|
76
|
-
if is_value
|
77
|
+
if is_value
|
77
78
|
definition = "#{definition}="
|
79
|
+
elsif is_argument
|
80
|
+
definition = "<#{definition}>"
|
81
|
+
end
|
82
|
+
|
83
|
+
aliases.each do |alias_|
|
84
|
+
definition = "#{definition}|#{alias_.to_definition}"
|
78
85
|
end
|
79
86
|
|
80
87
|
definition
|
@@ -88,7 +95,7 @@ module Consoler
|
|
88
95
|
return 0 if is_short
|
89
96
|
return false if is_long
|
90
97
|
|
91
|
-
|
98
|
+
nil
|
92
99
|
end
|
93
100
|
|
94
101
|
protected
|
@@ -103,19 +110,33 @@ module Consoler
|
|
103
110
|
# Check for multiple attributes in the option definition till we got the
|
104
111
|
# final name and all of its attributes
|
105
112
|
|
106
|
-
|
113
|
+
# make sure we don't wrongly process any alias
|
114
|
+
alias_defs = option_def.split '|'
|
115
|
+
option = alias_defs.shift || ''
|
116
|
+
|
117
|
+
option, @is_optional = _is_optional option, tracker
|
107
118
|
option, @is_long = _is_long option
|
108
119
|
option, @is_short = _is_short option
|
109
|
-
@is_argument = (
|
120
|
+
@is_argument = (!@is_long && !@is_short)
|
110
121
|
option, @is_value = _value option, @is_argument
|
122
|
+
option, @aliases = _aliases option, alias_defs, tracker
|
123
|
+
|
124
|
+
if option[0] == '<'
|
125
|
+
raise 'Invalid <, missing >' if option[-1] != '>'
|
126
|
+
raise 'Only arguments support <, > around name' unless @is_argument
|
127
|
+
|
128
|
+
option = option[1..-2]
|
129
|
+
end
|
130
|
+
|
131
|
+
raise 'Missing starting <' if option[-1] == '>'
|
111
132
|
|
112
133
|
@name = option
|
113
134
|
|
114
|
-
if @name.empty?
|
135
|
+
if @name.empty?
|
115
136
|
raise 'Option must have a name'
|
116
137
|
end
|
117
138
|
|
118
|
-
if @is_long
|
139
|
+
if @is_long && @is_short
|
119
140
|
raise 'Option can not be a long and a short option'
|
120
141
|
end
|
121
142
|
end
|
@@ -135,8 +156,8 @@ module Consoler
|
|
135
156
|
# @raise [RuntimeError] if you try to close an unopened optional
|
136
157
|
# @return [(String, Integer|nil)] Remaining option definition, and, optional group if available
|
137
158
|
def _is_optional(option, tracker)
|
138
|
-
if option[0] == '['
|
139
|
-
if !tracker.is_tracking
|
159
|
+
if option[0] == '['
|
160
|
+
if !tracker.is_tracking
|
140
161
|
# mark tracker as tracking
|
141
162
|
tracker.is_tracking = true
|
142
163
|
tracker.index += 1
|
@@ -147,14 +168,12 @@ module Consoler
|
|
147
168
|
end
|
148
169
|
|
149
170
|
# get optional group index from tracking, if tracking
|
150
|
-
optional = if tracker.is_tracking
|
171
|
+
optional = if tracker.is_tracking
|
151
172
|
tracker.index
|
152
|
-
else
|
153
|
-
nil
|
154
173
|
end
|
155
174
|
|
156
|
-
if option[-1] == ']'
|
157
|
-
if tracker.is_tracking
|
175
|
+
if option[-1] == ']'
|
176
|
+
if tracker.is_tracking
|
158
177
|
# mark tracker as non-tracking
|
159
178
|
tracker.is_tracking = false
|
160
179
|
option = option[0..-2]
|
@@ -163,7 +182,7 @@ module Consoler
|
|
163
182
|
end
|
164
183
|
end
|
165
184
|
|
166
|
-
|
185
|
+
[option, optional]
|
167
186
|
end
|
168
187
|
|
169
188
|
# Check long definition
|
@@ -171,14 +190,14 @@ module Consoler
|
|
171
190
|
# @param [String] option Option definition
|
172
191
|
# @return [(String, Boolean)]
|
173
192
|
def _is_long(option)
|
174
|
-
if option[0..1] == '--'
|
193
|
+
if option[0..1] == '--'
|
175
194
|
long = true
|
176
195
|
option = option[2..-1]
|
177
196
|
else
|
178
197
|
long = false
|
179
198
|
end
|
180
199
|
|
181
|
-
|
200
|
+
[option, long]
|
182
201
|
end
|
183
202
|
|
184
203
|
# Check short definition
|
@@ -186,14 +205,14 @@ module Consoler
|
|
186
205
|
# @param [String] option Option definition
|
187
206
|
# @return [(String, Boolean)]
|
188
207
|
def _is_short(option)
|
189
|
-
if option[0] == '-'
|
208
|
+
if option[0] == '-'
|
190
209
|
short = true
|
191
210
|
option = option[1..-1]
|
192
211
|
else
|
193
212
|
short = false
|
194
213
|
end
|
195
214
|
|
196
|
-
|
215
|
+
[option, short]
|
197
216
|
end
|
198
217
|
|
199
218
|
# Check value definition
|
@@ -202,8 +221,8 @@ module Consoler
|
|
202
221
|
# @raise [RuntimeError] if you try to assign a value to an argument
|
203
222
|
# @return [(String, Boolean)]
|
204
223
|
def _value(option, argument)
|
205
|
-
if option[-1] == '='
|
206
|
-
if argument
|
224
|
+
if option[-1] == '='
|
225
|
+
if argument
|
207
226
|
raise 'Arguments can\'t have a value'
|
208
227
|
end
|
209
228
|
|
@@ -213,7 +232,36 @@ module Consoler
|
|
213
232
|
value = false
|
214
233
|
end
|
215
234
|
|
216
|
-
|
235
|
+
[option, value]
|
236
|
+
end
|
237
|
+
|
238
|
+
# Parse all possible aliases
|
239
|
+
#
|
240
|
+
# @param [String] option Option definition
|
241
|
+
# @param [Consoler::Tracker] tracker Optional tracker
|
242
|
+
# @raise [RuntimeError] On all kinds of occasions
|
243
|
+
# @return [(String, Array)] Remaining option definition, and, aliases if available
|
244
|
+
def _aliases(option, alias_defs, tracker)
|
245
|
+
return option, [] if alias_defs.empty?
|
246
|
+
|
247
|
+
raise 'Argument can\'t have aliases' if is_argument
|
248
|
+
raise 'Aliases are not allowed for multiple short options' if is_short && option.size > 1
|
249
|
+
|
250
|
+
aliases_ = []
|
251
|
+
alias_names = []
|
252
|
+
|
253
|
+
while (alias_def = alias_defs.shift)
|
254
|
+
Consoler::Option.create alias_def, tracker do |alias_|
|
255
|
+
raise "Duplicate alias name: #{alias_.name}" if alias_names.include? alias_.name
|
256
|
+
raise "Alias must have a value: #{alias_.name}" if is_value && !alias_.is_value
|
257
|
+
raise "Alias can't have a value: #{alias_.name}" if !is_value && alias_.is_value
|
258
|
+
|
259
|
+
aliases_.push alias_
|
260
|
+
alias_names.push alias_.name
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
[option, aliases_]
|
217
265
|
end
|
218
266
|
end
|
219
267
|
end
|
data/lib/consoler/options.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require_relative 'option'
|
4
4
|
|
5
5
|
module Consoler
|
6
|
-
|
7
6
|
# List of options
|
8
7
|
#
|
9
8
|
# @attr_reader [String] description Description of the options
|
@@ -21,7 +20,7 @@ module Consoler
|
|
21
20
|
return if options_def.nil?
|
22
21
|
|
23
22
|
# strip the description
|
24
|
-
if match = /(^|\s+)-- (?<description>.*)$/.match(options_def)
|
23
|
+
if (match = /(^|\s+)-- (?<description>.*)$/.match(options_def))
|
25
24
|
@description = match[:description]
|
26
25
|
options_def = options_def[0...-match[0].size]
|
27
26
|
end
|
@@ -31,28 +30,50 @@ module Consoler
|
|
31
30
|
|
32
31
|
option_names = []
|
33
32
|
|
34
|
-
while option_def = options.shift
|
33
|
+
while (option_def = options.shift)
|
35
34
|
Consoler::Option.create option_def, tracker do |option|
|
36
35
|
raise "Duplicate option name: #{option.name}" if option_names.include? option.name
|
37
36
|
|
38
|
-
@options.push option
|
39
37
|
option_names.push option.name
|
38
|
+
|
39
|
+
option.aliases.each do |alias_|
|
40
|
+
raise "Duplicate alias name: #{alias_.name}" if option_names.include? alias_.name
|
41
|
+
|
42
|
+
option_names.push alias_.name
|
43
|
+
end
|
44
|
+
|
45
|
+
@options.push option
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
44
|
-
# Get a
|
50
|
+
# Get a option by its name
|
51
|
+
#
|
52
|
+
# May be matched by one of its aliases
|
45
53
|
#
|
46
54
|
# @param name [String] Name of the option
|
47
55
|
# @return [Consoler::Option, nil]
|
48
56
|
def get(name)
|
57
|
+
option, = get_with_alias name
|
58
|
+
option
|
59
|
+
end
|
60
|
+
|
61
|
+
# Get a option by its name, with matched alias
|
62
|
+
#
|
63
|
+
# @param name [String] Name of the option
|
64
|
+
# @return [[(Consoler::Option, nil), (Consoler::Option, nil)]]
|
65
|
+
def get_with_alias(name)
|
49
66
|
each do |option, _|
|
50
|
-
if option.name == name
|
51
|
-
return option
|
67
|
+
if option.name == name
|
68
|
+
return option, option
|
69
|
+
end
|
70
|
+
|
71
|
+
option.aliases.each do |alias_|
|
72
|
+
return option, alias_ if alias_.name == name
|
52
73
|
end
|
53
74
|
end
|
54
75
|
|
55
|
-
|
76
|
+
[nil, nil]
|
56
77
|
end
|
57
78
|
|
58
79
|
# Loop through all options
|
@@ -84,19 +105,17 @@ module Consoler
|
|
84
105
|
each do |option, i|
|
85
106
|
definition += ' '
|
86
107
|
|
87
|
-
if optional.nil?
|
108
|
+
if optional.nil? && option.is_optional
|
88
109
|
definition += '['
|
89
110
|
optional = option.is_optional
|
90
111
|
end
|
91
112
|
|
92
113
|
definition += option.to_definition
|
93
114
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
optional = nil
|
99
|
-
end
|
115
|
+
# only close when the next option is not optional, or another optional group
|
116
|
+
if option.is_optional && (@options[i + 1].nil? || optional != @options[i + 1].is_optional)
|
117
|
+
definition += ']'
|
118
|
+
optional = nil
|
100
119
|
end
|
101
120
|
end
|
102
121
|
|
@@ -104,8 +123,6 @@ module Consoler
|
|
104
123
|
end
|
105
124
|
end
|
106
125
|
|
107
|
-
private
|
108
|
-
|
109
126
|
# Optionals tracker
|
110
127
|
#
|
111
128
|
# @attr [Boolean] is_tracking Is inside optional options
|