atli 0.1.4 → 0.1.5
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/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
|