getopt 1.6.0 → 1.7.1
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +9 -2
- data/Gemfile +2 -3
- data/MANIFEST.md +2 -2
- data/README.md +5 -2
- data/Rakefile +12 -2
- data/getopt.gemspec +12 -7
- data/lib/getopt/long.rb +246 -224
- data/lib/getopt/std.rb +91 -91
- data/lib/getopt/version.rb +3 -1
- data/spec/getopt_long_spec.rb +213 -121
- data/spec/getopt_std_spec.rb +79 -71
- data.tar.gz.sig +0 -0
- metadata +36 -8
- metadata.gz.sig +0 -0
data/spec/getopt_long_spec.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
#####################################################################
|
|
2
4
|
# getopt_long_spec.rb
|
|
3
5
|
#
|
|
@@ -12,57 +14,63 @@ RSpec.describe Getopt::Long do
|
|
|
12
14
|
@opts = nil
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
after do
|
|
18
|
+
@opts = nil
|
|
19
|
+
ARGV.clear
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
example 'version' do
|
|
23
|
+
expect(Getopt::Long::VERSION).to eq('1.7.1')
|
|
17
24
|
expect(Getopt::Long::VERSION).to be_frozen
|
|
18
25
|
end
|
|
19
26
|
|
|
20
|
-
example
|
|
27
|
+
example 'constants' do
|
|
21
28
|
expect(Getopt::BOOLEAN).not_to be_nil
|
|
22
29
|
expect(Getopt::OPTIONAL).not_to be_nil
|
|
23
30
|
expect(Getopt::REQUIRED).not_to be_nil
|
|
24
31
|
expect(Getopt::INCREMENT).not_to be_nil
|
|
32
|
+
expect(Getopt::NEGATABLE).not_to be_nil
|
|
25
33
|
end
|
|
26
34
|
|
|
27
|
-
example
|
|
28
|
-
expect(
|
|
35
|
+
example 'getopts long basic functionality' do
|
|
36
|
+
expect(described_class).to respond_to(:getopts)
|
|
29
37
|
|
|
30
|
-
expect{
|
|
31
|
-
expect{
|
|
38
|
+
expect{ described_class.getopts(['--test'], ['--help'], ['--foo']) }.not_to raise_error
|
|
39
|
+
expect{ described_class.getopts(['--test', '-x'], ['--help', '-y'], ['--foo', '-z']) }.not_to raise_error
|
|
32
40
|
|
|
33
41
|
expect{
|
|
34
|
-
|
|
35
|
-
[
|
|
36
|
-
[
|
|
37
|
-
[
|
|
38
|
-
[
|
|
42
|
+
described_class.getopts(
|
|
43
|
+
['--test', '-x', Getopt::BOOLEAN],
|
|
44
|
+
['--help', '-y', Getopt::REQUIRED],
|
|
45
|
+
['--foo', '-z', Getopt::OPTIONAL],
|
|
46
|
+
['--more', '-m', Getopt::INCREMENT]
|
|
39
47
|
)
|
|
40
48
|
}.not_to raise_error
|
|
41
49
|
|
|
42
|
-
expect(
|
|
50
|
+
expect(described_class.getopts('--test')).to be_a(Hash)
|
|
43
51
|
end
|
|
44
52
|
|
|
45
|
-
example
|
|
46
|
-
ARGV.push(
|
|
53
|
+
example 'getopts long using equals sign works as expected' do
|
|
54
|
+
ARGV.push('--foo=hello', '-b', 'world')
|
|
47
55
|
|
|
48
56
|
expect{
|
|
49
|
-
@opts =
|
|
50
|
-
[
|
|
51
|
-
[
|
|
57
|
+
@opts = described_class.getopts(
|
|
58
|
+
['--foo', '-f', Getopt::REQUIRED],
|
|
59
|
+
['--bar', '-b', Getopt::OPTIONAL]
|
|
52
60
|
)
|
|
53
61
|
}.not_to raise_error
|
|
54
62
|
|
|
55
|
-
expect(@opts[
|
|
56
|
-
expect(@opts[
|
|
57
|
-
expect(@opts[
|
|
58
|
-
expect(@opts[
|
|
63
|
+
expect(@opts['foo']).to eq('hello')
|
|
64
|
+
expect(@opts['f']).to eq('hello')
|
|
65
|
+
expect(@opts['bar']).to eq('world')
|
|
66
|
+
expect(@opts['b']).to eq('world')
|
|
59
67
|
end
|
|
60
68
|
|
|
61
|
-
example
|
|
69
|
+
example 'getopts long with embedded hyphens works as expected' do
|
|
62
70
|
ARGV.push('--foo-bar', 'hello', '--test1-test2-test3', 'world')
|
|
63
71
|
|
|
64
72
|
expect{
|
|
65
|
-
@opts =
|
|
73
|
+
@opts = described_class.getopts(
|
|
66
74
|
['--foo-bar', '-f', Getopt::REQUIRED],
|
|
67
75
|
['--test1-test2-test3', '-t', Getopt::REQUIRED]
|
|
68
76
|
)
|
|
@@ -74,11 +82,11 @@ RSpec.describe Getopt::Long do
|
|
|
74
82
|
expect(@opts['t']).to eq('world')
|
|
75
83
|
end
|
|
76
84
|
|
|
77
|
-
example
|
|
85
|
+
example 'getopts long embedded hyphens using equals sign works as expected' do
|
|
78
86
|
ARGV.push('--foo-bar=hello', '--test1-test2-test3=world')
|
|
79
87
|
|
|
80
88
|
expect{
|
|
81
|
-
@opts =
|
|
89
|
+
@opts = described_class.getopts(
|
|
82
90
|
['--foo-bar', '-f', Getopt::REQUIRED],
|
|
83
91
|
['--test1-test2-test3', '-t', Getopt::REQUIRED]
|
|
84
92
|
)
|
|
@@ -90,180 +98,204 @@ RSpec.describe Getopt::Long do
|
|
|
90
98
|
expect(@opts['t']).to eq('world')
|
|
91
99
|
end
|
|
92
100
|
|
|
93
|
-
example
|
|
94
|
-
ARGV.push(
|
|
101
|
+
example 'getopts long with short switch squished works as expected' do
|
|
102
|
+
ARGV.push('-f', 'hello', '-bworld')
|
|
95
103
|
|
|
96
104
|
expect{
|
|
97
|
-
@opts =
|
|
98
|
-
[
|
|
99
|
-
[
|
|
105
|
+
@opts = described_class.getopts(
|
|
106
|
+
['--foo', '-f', Getopt::REQUIRED],
|
|
107
|
+
['--bar', '-b', Getopt::OPTIONAL]
|
|
100
108
|
)
|
|
101
109
|
}.not_to raise_error
|
|
102
110
|
|
|
103
|
-
expect(@opts[
|
|
104
|
-
expect(@opts[
|
|
111
|
+
expect(@opts['f']).to eq('hello')
|
|
112
|
+
expect(@opts['b']).to eq('world')
|
|
105
113
|
end
|
|
106
114
|
|
|
107
|
-
example
|
|
108
|
-
ARGV.push(
|
|
115
|
+
example 'getopts long accepts question mark as a short switch' do
|
|
116
|
+
ARGV.push('-?')
|
|
109
117
|
|
|
110
|
-
expect{
|
|
118
|
+
expect{
|
|
119
|
+
@opts = described_class.getopts(
|
|
120
|
+
['--help', '-?', Getopt::BOOLEAN]
|
|
121
|
+
)
|
|
122
|
+
}.not_to raise_error
|
|
111
123
|
|
|
112
|
-
expect(@opts[
|
|
113
|
-
expect(@opts[
|
|
124
|
+
expect(@opts['help']).to be(true)
|
|
125
|
+
expect(@opts['?']).to be(true)
|
|
114
126
|
end
|
|
115
127
|
|
|
116
|
-
example
|
|
117
|
-
ARGV.push(
|
|
118
|
-
|
|
119
|
-
expect
|
|
120
|
-
|
|
121
|
-
expect(
|
|
128
|
+
example 'getopts long increment type works as expected' do
|
|
129
|
+
ARGV.push('-m', '-m')
|
|
130
|
+
|
|
131
|
+
expect{ @opts = described_class.getopts(['--more', '-m', Getopt::INCREMENT]) }.not_to raise_error
|
|
132
|
+
|
|
133
|
+
expect(@opts['more']).to eq(2)
|
|
134
|
+
expect(@opts['m']).to eq(2)
|
|
122
135
|
end
|
|
123
136
|
|
|
124
|
-
example
|
|
125
|
-
ARGV.push(
|
|
126
|
-
expect{ @opts =
|
|
127
|
-
expect(@opts.
|
|
128
|
-
expect(@opts.
|
|
129
|
-
expect(@opts.
|
|
137
|
+
example 'switches are set as expected' do
|
|
138
|
+
ARGV.push('--verbose', '--test', '--foo')
|
|
139
|
+
expect{ @opts = described_class.getopts('--verbose --test --foo') }.not_to raise_error
|
|
140
|
+
expect(@opts.key?('verbose')).to be(true)
|
|
141
|
+
expect(@opts.key?('test')).to be(true)
|
|
142
|
+
expect(@opts.key?('foo')).to be(true)
|
|
130
143
|
end
|
|
131
144
|
|
|
132
|
-
example
|
|
133
|
-
ARGV.push(
|
|
145
|
+
example 'short switch synonyms work as expected' do
|
|
146
|
+
ARGV.push('--verbose', '--test', '--foo')
|
|
147
|
+
expect{ @opts = described_class.getopts('--verbose --test --foo') }.not_to raise_error
|
|
148
|
+
expect(@opts.key?('v')).to be(true)
|
|
149
|
+
expect(@opts.key?('t')).to be(true)
|
|
150
|
+
expect(@opts.key?('f')).to be(true)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
example 'short_switch_synonyms_with_explicit_types' do
|
|
154
|
+
ARGV.push('--verbose', '--test', 'hello', '--foo')
|
|
134
155
|
|
|
135
156
|
expect{
|
|
136
|
-
@opts =
|
|
137
|
-
[
|
|
138
|
-
[
|
|
139
|
-
[
|
|
157
|
+
@opts = described_class.getopts(
|
|
158
|
+
['--verbose', Getopt::BOOLEAN],
|
|
159
|
+
['--test', Getopt::REQUIRED],
|
|
160
|
+
['--foo', Getopt::BOOLEAN]
|
|
140
161
|
)
|
|
141
162
|
}.not_to raise_error
|
|
142
163
|
|
|
143
|
-
expect(@opts.
|
|
144
|
-
expect(@opts.
|
|
145
|
-
expect(@opts.
|
|
164
|
+
expect(@opts.key?('v')).to be(true)
|
|
165
|
+
expect(@opts.key?('t')).to be(true)
|
|
166
|
+
expect(@opts.key?('f')).to be(true)
|
|
146
167
|
end
|
|
147
168
|
|
|
148
|
-
example
|
|
149
|
-
ARGV.push(
|
|
169
|
+
example 'switches with required arguments when present' do
|
|
170
|
+
ARGV.push('--foo', '1', '--bar', 'hello')
|
|
150
171
|
|
|
151
172
|
expect{
|
|
152
|
-
@opts =
|
|
153
|
-
[
|
|
154
|
-
[
|
|
173
|
+
@opts = described_class.getopts(
|
|
174
|
+
['--foo', '-f', Getopt::REQUIRED],
|
|
175
|
+
['--bar', '-b', Getopt::REQUIRED]
|
|
155
176
|
)
|
|
156
177
|
}.not_to raise_error
|
|
157
178
|
|
|
158
|
-
expect(@opts).to eq({
|
|
179
|
+
expect(@opts).to eq({'foo' => '1', 'bar' => 'hello', 'f' => '1', 'b' => 'hello'})
|
|
159
180
|
end
|
|
160
181
|
|
|
161
|
-
example "
|
|
162
|
-
ARGV.push(
|
|
182
|
+
example "error is raised if argument isn't provided for switch that requires it" do
|
|
183
|
+
ARGV.push('-f', '1', '-b')
|
|
163
184
|
|
|
164
185
|
expect{
|
|
165
|
-
@opts =
|
|
166
|
-
[
|
|
167
|
-
[
|
|
186
|
+
@opts = described_class.getopts(
|
|
187
|
+
['--foo', '-f', Getopt::REQUIRED],
|
|
188
|
+
['--bar', '-b', Getopt::REQUIRED]
|
|
189
|
+
)
|
|
190
|
+
}.to raise_error(Getopt::Long::Error)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
example 'compressed switches work as expected' do
|
|
194
|
+
ARGV.push('-fb')
|
|
195
|
+
|
|
196
|
+
expect{
|
|
197
|
+
@opts = described_class.getopts(
|
|
198
|
+
['--foo', '-f', Getopt::BOOLEAN],
|
|
199
|
+
['--bar', '-b', Getopt::BOOLEAN]
|
|
168
200
|
)
|
|
169
201
|
}.not_to raise_error
|
|
170
202
|
|
|
171
|
-
expect(@opts).to eq({
|
|
203
|
+
expect(@opts).to eq({'foo' => true, 'f' => true, 'b' => true, 'bar' => true})
|
|
172
204
|
end
|
|
173
205
|
|
|
174
|
-
example
|
|
175
|
-
ARGV.push(
|
|
206
|
+
example 'compress switches with required argument works as expected' do
|
|
207
|
+
ARGV.push('-xf', 'foo.txt')
|
|
176
208
|
|
|
177
209
|
expect{
|
|
178
|
-
@opts =
|
|
179
|
-
[
|
|
180
|
-
[
|
|
210
|
+
@opts = described_class.getopts(
|
|
211
|
+
['--expand', '-x', Getopt::BOOLEAN],
|
|
212
|
+
['--file', '-f', Getopt::REQUIRED]
|
|
181
213
|
)
|
|
182
214
|
}.not_to raise_error
|
|
183
215
|
|
|
184
|
-
expect(@opts).to eq({
|
|
216
|
+
expect(@opts).to eq({'x' => true, 'expand' => true, 'f' => 'foo.txt', 'file' => 'foo.txt'})
|
|
185
217
|
end
|
|
186
218
|
|
|
187
|
-
example
|
|
188
|
-
ARGV.push(
|
|
219
|
+
example 'compress switches with argument that is compressed works as expected' do
|
|
220
|
+
ARGV.push('-xffoo.txt')
|
|
189
221
|
|
|
190
222
|
expect{
|
|
191
|
-
@opts =
|
|
192
|
-
[
|
|
193
|
-
[
|
|
223
|
+
@opts = described_class.getopts(
|
|
224
|
+
['--expand', '-x', Getopt::BOOLEAN],
|
|
225
|
+
['--file', '-f', Getopt::REQUIRED]
|
|
194
226
|
)
|
|
195
227
|
}.not_to raise_error
|
|
196
228
|
|
|
197
|
-
expect(@opts).to eq({
|
|
229
|
+
expect(@opts).to eq({'x' => true, 'expand' => true, 'f' => 'foo.txt', 'file' => 'foo.txt'})
|
|
198
230
|
end
|
|
199
231
|
|
|
200
|
-
example
|
|
201
|
-
ARGV.push(
|
|
232
|
+
example 'compress switches with optional argument not defined works as expected' do
|
|
233
|
+
ARGV.push('-xf')
|
|
202
234
|
|
|
203
235
|
expect{
|
|
204
|
-
@opts =
|
|
205
|
-
[
|
|
206
|
-
[
|
|
236
|
+
@opts = described_class.getopts(
|
|
237
|
+
['--expand', '-x', Getopt::BOOLEAN],
|
|
238
|
+
['--file', '-f', Getopt::OPTIONAL]
|
|
207
239
|
)
|
|
208
240
|
}.not_to raise_error
|
|
209
241
|
|
|
210
|
-
expect(@opts).to eq({
|
|
242
|
+
expect(@opts).to eq({'x' => true, 'expand' => true, 'f' => nil, 'file' => nil})
|
|
211
243
|
end
|
|
212
244
|
|
|
213
|
-
example
|
|
214
|
-
ARGV.push(
|
|
245
|
+
example 'compress switches with optional argument works as expected' do
|
|
246
|
+
ARGV.push('-xf', 'boo.txt')
|
|
215
247
|
|
|
216
248
|
expect{
|
|
217
|
-
@opts =
|
|
218
|
-
[
|
|
219
|
-
[
|
|
249
|
+
@opts = described_class.getopts(
|
|
250
|
+
['--expand', '-x', Getopt::BOOLEAN],
|
|
251
|
+
['--file', '-f', Getopt::OPTIONAL]
|
|
220
252
|
)
|
|
221
253
|
}.not_to raise_error
|
|
222
254
|
|
|
223
|
-
expect(@opts).to eq({
|
|
255
|
+
expect(@opts).to eq({'x' => true, 'expand' => true, 'f' => 'boo.txt', 'file' => 'boo.txt'})
|
|
224
256
|
end
|
|
225
257
|
|
|
226
|
-
example
|
|
227
|
-
ARGV.push(
|
|
258
|
+
example 'compress switches with compressed optional argument works as expected' do
|
|
259
|
+
ARGV.push('-xfboo.txt')
|
|
228
260
|
|
|
229
261
|
expect{
|
|
230
|
-
@opts =
|
|
231
|
-
[
|
|
232
|
-
[
|
|
262
|
+
@opts = described_class.getopts(
|
|
263
|
+
['--expand', '-x', Getopt::BOOLEAN],
|
|
264
|
+
['--file', '-f', Getopt::OPTIONAL]
|
|
233
265
|
)
|
|
234
266
|
}.not_to raise_error
|
|
235
267
|
|
|
236
|
-
expect(@opts).to eq({
|
|
268
|
+
expect(@opts).to eq({'x' => true, 'expand' => true, 'f' => 'boo.txt', 'file' => 'boo.txt'})
|
|
237
269
|
end
|
|
238
270
|
|
|
239
|
-
example
|
|
240
|
-
ARGV.push(
|
|
271
|
+
example 'compressed_short_and_long_mixed' do
|
|
272
|
+
ARGV.push('-xb', '--file', 'boo.txt', '-v')
|
|
241
273
|
|
|
242
274
|
expect{
|
|
243
|
-
@opts =
|
|
244
|
-
[
|
|
245
|
-
[
|
|
246
|
-
[
|
|
247
|
-
[
|
|
275
|
+
@opts = described_class.getopts(
|
|
276
|
+
['--expand', '-x', Getopt::BOOLEAN],
|
|
277
|
+
['--verbose', '-v', Getopt::BOOLEAN],
|
|
278
|
+
['--file', '-f', Getopt::REQUIRED],
|
|
279
|
+
['--bar', '-b', Getopt::OPTIONAL]
|
|
248
280
|
)
|
|
249
281
|
}.not_to raise_error
|
|
250
282
|
|
|
251
283
|
expect(@opts).to eq({
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
284
|
+
'x' => true, 'expand' => true,
|
|
285
|
+
'v' => true, 'verbose' => true,
|
|
286
|
+
'f' => 'boo.txt', 'file' => 'boo.txt',
|
|
287
|
+
'b' => nil, 'bar' => nil
|
|
256
288
|
})
|
|
257
289
|
end
|
|
258
290
|
|
|
259
|
-
example
|
|
260
|
-
ARGV.push('--to','1','--too','2','--tooo','3')
|
|
291
|
+
example 'multiple similar long switches with no short switches works as expected' do
|
|
292
|
+
ARGV.push('--to', '1', '--too', '2', '--tooo', '3')
|
|
261
293
|
|
|
262
294
|
expect{
|
|
263
|
-
@opts =
|
|
264
|
-
[
|
|
265
|
-
[
|
|
266
|
-
[
|
|
295
|
+
@opts = described_class.getopts(
|
|
296
|
+
['--to', Getopt::REQUIRED],
|
|
297
|
+
['--too', Getopt::REQUIRED],
|
|
298
|
+
['--tooo', Getopt::REQUIRED]
|
|
267
299
|
)
|
|
268
300
|
}.not_to raise_error
|
|
269
301
|
|
|
@@ -272,8 +304,68 @@ RSpec.describe Getopt::Long do
|
|
|
272
304
|
expect(@opts['tooo']).to eq('3')
|
|
273
305
|
end
|
|
274
306
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
307
|
+
example 'negatable switch set to true when positive form used' do
|
|
308
|
+
ARGV.push('--verbose')
|
|
309
|
+
|
|
310
|
+
expect{
|
|
311
|
+
@opts = described_class.getopts(
|
|
312
|
+
['--verbose', '-v', Getopt::NEGATABLE]
|
|
313
|
+
)
|
|
314
|
+
}.not_to raise_error
|
|
315
|
+
|
|
316
|
+
expect(@opts['verbose']).to be(true)
|
|
317
|
+
expect(@opts['v']).to be(true)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
example 'negatable switch set to false when --no- form used' do
|
|
321
|
+
ARGV.push('--no-verbose')
|
|
322
|
+
|
|
323
|
+
expect{
|
|
324
|
+
@opts = described_class.getopts(
|
|
325
|
+
['--verbose', '-v', Getopt::NEGATABLE]
|
|
326
|
+
)
|
|
327
|
+
}.not_to raise_error
|
|
328
|
+
|
|
329
|
+
expect(@opts['verbose']).to be(false)
|
|
330
|
+
expect(@opts['v']).to be(false)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
example 'negatable switch works with multiple switches' do
|
|
334
|
+
ARGV.push('--color', '--no-debug')
|
|
335
|
+
|
|
336
|
+
expect{
|
|
337
|
+
@opts = described_class.getopts(
|
|
338
|
+
['--color', '-c', Getopt::NEGATABLE],
|
|
339
|
+
['--debug', '-d', Getopt::NEGATABLE]
|
|
340
|
+
)
|
|
341
|
+
}.not_to raise_error
|
|
342
|
+
|
|
343
|
+
expect(@opts['color']).to be(true)
|
|
344
|
+
expect(@opts['c']).to be(true)
|
|
345
|
+
expect(@opts['debug']).to be(false)
|
|
346
|
+
expect(@opts['d']).to be(false)
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
example 'negatable switch raises error if set more than once' do
|
|
350
|
+
ARGV.push('--verbose', '--no-verbose')
|
|
351
|
+
|
|
352
|
+
expect{
|
|
353
|
+
@opts = described_class.getopts(
|
|
354
|
+
['--verbose', '-v', Getopt::NEGATABLE]
|
|
355
|
+
)
|
|
356
|
+
}.to raise_error(Getopt::Long::Error, /negatable switch already set/)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
example 'negatable switch with hyphenated name works as expected' do
|
|
360
|
+
ARGV.push('--no-dry-run')
|
|
361
|
+
|
|
362
|
+
expect{
|
|
363
|
+
@opts = described_class.getopts(
|
|
364
|
+
['--dry-run', '-n', Getopt::NEGATABLE]
|
|
365
|
+
)
|
|
366
|
+
}.not_to raise_error
|
|
367
|
+
|
|
368
|
+
expect(@opts['dry-run']).to be(false)
|
|
369
|
+
expect(@opts['n']).to be(false)
|
|
278
370
|
end
|
|
279
371
|
end
|