atli 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/thor.rb +23 -3
- data/lib/thor/base.rb +15 -611
- data/lib/thor/base/class_methods.rb +730 -0
- data/lib/thor/command.rb +146 -28
- data/lib/thor/group.rb +61 -54
- data/lib/thor/parser/argument.rb +9 -2
- data/lib/thor/parser/arguments.rb +142 -110
- data/lib/thor/parser/options.rb +218 -102
- data/lib/thor/version.rb +2 -2
- metadata +3 -2
data/lib/thor/parser/options.rb
CHANGED
@@ -1,12 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Thor
|
2
|
-
class Options < Arguments
|
4
|
+
class Options < Arguments # rubocop:disable ClassLength
|
5
|
+
|
6
|
+
# Constants
|
7
|
+
# ========================================================================
|
8
|
+
|
3
9
|
LONG_RE = /^(--\w+(?:-\w+)*)$/
|
4
10
|
SHORT_RE = /^(-[a-z])$/i
|
5
11
|
EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
12
|
+
|
13
|
+
# Matches "multiple short switches", like `-xv`.
|
14
|
+
#
|
15
|
+
# @return [Regexp]
|
16
|
+
#
|
17
|
+
SHORT_SQ_RE = /^-([a-z]{2,})$/i
|
18
|
+
|
19
|
+
|
20
|
+
# Matches things like `'-x123'`.
|
21
|
+
#
|
22
|
+
# @return [Regexp]
|
23
|
+
#
|
24
|
+
SHORT_NUM = /^(-[a-z])#{ Thor::Arguments::NUMERIC }$/i
|
25
|
+
|
26
|
+
|
27
|
+
# The "bare double-dash" used to indicate that following arguments
|
28
|
+
# should not be parsed for options.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
#
|
32
|
+
OPTS_END = "--"
|
33
|
+
|
34
|
+
|
35
|
+
# Class Methods
|
36
|
+
# ========================================================================
|
37
|
+
|
10
38
|
# Receives a hash and makes it switches.
|
11
39
|
def self.to_switches(options)
|
12
40
|
options.map do |key, value|
|
@@ -24,12 +52,23 @@ class Thor
|
|
24
52
|
end
|
25
53
|
end.compact.join(" ")
|
26
54
|
end
|
27
|
-
|
55
|
+
|
56
|
+
|
57
|
+
# Constructor
|
58
|
+
# ========================================================================
|
59
|
+
|
28
60
|
# Takes a hash of Thor::Option and a hash with defaults.
|
29
61
|
#
|
30
62
|
# If +stop_on_unknown+ is true, #parse will stop as soon as it encounters
|
31
63
|
# an unknown option or a regular argument.
|
32
|
-
|
64
|
+
#
|
65
|
+
# @param [Hash<Symbol, Thor::Option>] hash_options
|
66
|
+
#
|
67
|
+
#
|
68
|
+
def initialize hash_options = {},
|
69
|
+
defaults = {},
|
70
|
+
stop_on_unknown = false,
|
71
|
+
disable_required_check = false
|
33
72
|
@stop_on_unknown = stop_on_unknown
|
34
73
|
@disable_required_check = disable_required_check
|
35
74
|
options = hash_options.values
|
@@ -54,25 +93,56 @@ class Thor
|
|
54
93
|
end
|
55
94
|
end
|
56
95
|
end
|
57
|
-
|
96
|
+
|
97
|
+
|
98
|
+
# Instance Methods
|
99
|
+
# ========================================================================
|
100
|
+
|
58
101
|
def remaining
|
59
102
|
@extra
|
60
103
|
end
|
61
|
-
|
104
|
+
|
105
|
+
|
106
|
+
# What's next?! I think.
|
107
|
+
#
|
108
|
+
# @note
|
109
|
+
# This *used to* remove `--` separators (what {OPTS_END} is),
|
110
|
+
# but that was problematic with multiple nested subcommands
|
111
|
+
# 'cause Thor classes further down the chain wouldn't know that
|
112
|
+
# it was there and would parse options that had been after it.
|
113
|
+
#
|
114
|
+
# Maybe that's how Thor was supposed to work (???), but it didn't really
|
115
|
+
# jive with me... I've always felt like stuff after `--` meant
|
116
|
+
# **_stop parsing options - these are always args_** since I usually
|
117
|
+
# see it used when passing shell commands to other shell commands -
|
118
|
+
# which is how I was using it when I came across the issues.
|
119
|
+
#
|
120
|
+
# And it ain't like Thor has any documentation to straiten it out. Hell,
|
121
|
+
# this method had no doc when I showed up. The line that dropped the `--`
|
122
|
+
# has no comment. The {Thor::Options} class itself had no doc.
|
123
|
+
#
|
124
|
+
# So, now it *does* mean that... `--` means "no option parsing after
|
125
|
+
# here". For real.
|
126
|
+
#
|
62
127
|
def peek
|
63
128
|
return super unless @parsing_options
|
64
129
|
|
65
130
|
result = super
|
66
131
|
if result == OPTS_END
|
67
|
-
|
132
|
+
# Removed, see note above:
|
133
|
+
# shift
|
68
134
|
@parsing_options = false
|
69
135
|
super
|
70
136
|
else
|
71
137
|
result
|
72
138
|
end
|
73
139
|
end
|
74
|
-
|
75
|
-
|
140
|
+
|
141
|
+
|
142
|
+
def parse args # rubocop:disable MethodLength
|
143
|
+
logger.debug __method__.to_s,
|
144
|
+
args: args
|
145
|
+
|
76
146
|
@pile = args.dup
|
77
147
|
@parsing_options = true
|
78
148
|
|
@@ -87,15 +157,15 @@ class Thor
|
|
87
157
|
unshift($1.split("").map { |f| "-#{f}" })
|
88
158
|
next
|
89
159
|
when EQ_RE, SHORT_NUM
|
90
|
-
unshift
|
91
|
-
|
160
|
+
unshift $2
|
161
|
+
raw_switch_arg = $1
|
92
162
|
when LONG_RE, SHORT_RE
|
93
|
-
|
163
|
+
raw_switch_arg = $1
|
94
164
|
end
|
95
165
|
|
96
|
-
switch = normalize_switch
|
97
|
-
option = switch_option
|
98
|
-
@assigns[option.human_name] = parse_peek
|
166
|
+
switch = normalize_switch raw_switch_arg
|
167
|
+
option = switch_option switch
|
168
|
+
@assigns[option.human_name] = parse_peek switch, option
|
99
169
|
elsif @stop_on_unknown
|
100
170
|
@parsing_options = false
|
101
171
|
@extra << shifted
|
@@ -116,106 +186,152 @@ class Thor
|
|
116
186
|
|
117
187
|
assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
|
118
188
|
assigns.freeze
|
189
|
+
|
190
|
+
logger.debug "#{ __method__ } done",
|
191
|
+
assigns: assigns,
|
192
|
+
remaining: remaining
|
193
|
+
|
119
194
|
assigns
|
120
195
|
end
|
121
|
-
|
196
|
+
|
197
|
+
|
122
198
|
def check_unknown!
|
123
199
|
# an unknown option starts with - or -- and has no more --'s afterward.
|
124
200
|
unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ }
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
protected
|
129
|
-
|
130
|
-
# Check if the current value in peek is a registered switch.
|
131
|
-
#
|
132
|
-
# Two booleans are returned. The first is true if the current value
|
133
|
-
# starts with a hyphen; the second is true if it is a registered switch.
|
134
|
-
def current_is_switch?
|
135
|
-
case peek
|
136
|
-
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
|
137
|
-
[true, switch?($1)]
|
138
|
-
when SHORT_SQ_RE
|
139
|
-
[true, $1.split("").any? { |f| switch?("-#{f}") }]
|
140
|
-
else
|
141
|
-
[false, false]
|
201
|
+
unless unknown.empty?
|
202
|
+
raise UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'"
|
142
203
|
end
|
143
204
|
end
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
205
|
+
|
206
|
+
|
207
|
+
protected # Instance Methods
|
208
|
+
# ==========================================================================
|
209
|
+
|
210
|
+
def last?
|
211
|
+
super() || peek == OPTS_END
|
151
212
|
end
|
152
|
-
end
|
153
213
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
214
|
+
# Check if the current value in peek is a registered switch.
|
215
|
+
#
|
216
|
+
# Two booleans are returned. The first is true if the current value
|
217
|
+
# starts with a hyphen; the second is true if it is a registered switch.
|
218
|
+
def current_is_switch?
|
219
|
+
case peek
|
220
|
+
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
|
221
|
+
[true, switch?($1)]
|
222
|
+
when SHORT_SQ_RE
|
223
|
+
[true, $1.split("").any? { |f| switch?("-#{f}") }]
|
224
|
+
else
|
225
|
+
[false, false]
|
226
|
+
end
|
167
227
|
end
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
(@shorts[arg] || arg).tr("_", "-")
|
174
|
-
end
|
175
|
-
|
176
|
-
def parsing_options?
|
177
|
-
peek
|
178
|
-
@parsing_options
|
179
|
-
end
|
180
|
-
|
181
|
-
# Parse boolean values which can be given as --foo=true, --foo or --no-foo.
|
182
|
-
#
|
183
|
-
def parse_boolean(switch)
|
184
|
-
if current_is_value?
|
185
|
-
if ["true", "TRUE", "t", "T", true].include?(peek)
|
186
|
-
shift
|
228
|
+
|
229
|
+
|
230
|
+
def current_is_switch_formatted?
|
231
|
+
case peek
|
232
|
+
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE
|
187
233
|
true
|
188
|
-
|
189
|
-
shift
|
234
|
+
else
|
190
235
|
false
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
def switch?(arg)
|
241
|
+
switch_option(normalize_switch(arg))
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
# Get the option for a switch arg.
|
246
|
+
#
|
247
|
+
# Handles parsing `--no-<option>` and `--skip-<option>` styles as well.
|
248
|
+
#
|
249
|
+
# @param [String] arg
|
250
|
+
# The switch part of the CLI arg, like `--blah`.
|
251
|
+
#
|
252
|
+
# @return [Thor::Option]
|
253
|
+
# If we have an option for the switch.
|
254
|
+
#
|
255
|
+
# @return [nil]
|
256
|
+
# If we don't have an option for the switch.
|
257
|
+
#
|
258
|
+
def switch_option(arg)
|
259
|
+
if match = no_or_skip?(arg) # rubocop:disable AssignmentInCondition
|
260
|
+
@switches[arg] || @switches["--#{match}"]
|
191
261
|
else
|
192
|
-
|
262
|
+
@switches[arg]
|
193
263
|
end
|
194
|
-
else
|
195
|
-
@switches.key?(switch) || !no_or_skip?(switch)
|
196
264
|
end
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
265
|
+
|
266
|
+
|
267
|
+
# Check if the given argument is actually a shortcut.
|
268
|
+
#
|
269
|
+
# Also normalizes '_' to '-'.
|
270
|
+
#
|
271
|
+
# @param [String] raw_switch_arg
|
272
|
+
# The raw switch arg that we received (essentially, what was passed
|
273
|
+
# on the CLI).
|
274
|
+
#
|
275
|
+
# @return [String]
|
276
|
+
# Normalized, de-aliased switch string.
|
277
|
+
#
|
278
|
+
def normalize_switch raw_switch_arg
|
279
|
+
(@shorts[raw_switch_arg] || raw_switch_arg).tr("_", "-")
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
def parsing_options?
|
284
|
+
peek
|
285
|
+
@parsing_options
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
# Parse boolean values which can be given as --foo=true, --foo or --no-foo.
|
290
|
+
#
|
291
|
+
def parse_boolean(switch)
|
292
|
+
if current_is_value?
|
293
|
+
if ["true", "TRUE", "t", "T", true].include?(peek)
|
294
|
+
shift
|
295
|
+
true
|
296
|
+
elsif ["false", "FALSE", "f", "F", false].include?(peek)
|
297
|
+
shift
|
298
|
+
false
|
299
|
+
else
|
300
|
+
!no_or_skip?(switch)
|
301
|
+
end
|
212
302
|
else
|
213
|
-
|
303
|
+
@switches.key?(switch) || !no_or_skip?(switch)
|
214
304
|
end
|
215
305
|
end
|
306
|
+
|
307
|
+
|
308
|
+
# Parse the value at the peek analyzing if it requires an input or not.
|
309
|
+
#
|
310
|
+
# @param [String] switch
|
311
|
+
# The normalized option switch, as returned from {#normalize_switch}.
|
312
|
+
#
|
313
|
+
def parse_peek switch, option
|
314
|
+
if current_is_switch_formatted? || last?
|
315
|
+
if option.boolean?
|
316
|
+
# No problem for boolean types
|
317
|
+
elsif no_or_skip?(switch)
|
318
|
+
return nil # User set value to nil
|
319
|
+
elsif option.string? && !option.required?
|
320
|
+
# Return the default if there is one, else the human name
|
321
|
+
return option.lazy_default || option.default || option.human_name
|
322
|
+
elsif option.lazy_default
|
323
|
+
return option.lazy_default
|
324
|
+
else
|
325
|
+
raise MalformattedArgumentError,
|
326
|
+
"No value provided for option '#{switch}'"
|
327
|
+
end
|
328
|
+
end
|
216
329
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
end
|
330
|
+
@non_assigned_required.delete(option)
|
331
|
+
send(:"parse_#{option.type}", switch)
|
332
|
+
end # #parse_peek
|
333
|
+
|
334
|
+
public # end protected Instance Methods **********************************
|
335
|
+
|
336
|
+
end # class Options
|
337
|
+
end # class Thor
|
data/lib/thor/version.rb
CHANGED
@@ -14,7 +14,7 @@ class Thor
|
|
14
14
|
#
|
15
15
|
# @return [String]
|
16
16
|
#
|
17
|
-
VERSION = '0.1.
|
17
|
+
VERSION = '0.1.5'
|
18
18
|
|
19
19
|
|
20
20
|
# The version of Thor that Atli is up to date with.
|
@@ -27,5 +27,5 @@ class Thor
|
|
27
27
|
#
|
28
28
|
# @return [String]
|
29
29
|
#
|
30
|
-
THOR_VERSION = '0.1.
|
30
|
+
THOR_VERSION = '0.1.5'
|
31
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil Souza (Atli)
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-
|
13
|
+
date: 2018-03-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- lib/thor/actions/file_manipulation.rb
|
92
92
|
- lib/thor/actions/inject_into_file.rb
|
93
93
|
- lib/thor/base.rb
|
94
|
+
- lib/thor/base/class_methods.rb
|
94
95
|
- lib/thor/base/common_class_options.rb
|
95
96
|
- lib/thor/command.rb
|
96
97
|
- lib/thor/core_ext/hash_with_indifferent_access.rb
|