command_mapper-gen 0.1.0.pre1
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 +7 -0
- data/.github/workflows/ruby.yml +27 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +20 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +20 -0
- data/README.md +145 -0
- data/Rakefile +15 -0
- data/bin/command_mapper-gen +7 -0
- data/commnad_mapper-gen.gemspec +61 -0
- data/examples/grep.rb +63 -0
- data/gemspec.yml +26 -0
- data/lib/command_mapper/gen/arg.rb +43 -0
- data/lib/command_mapper/gen/argument.rb +53 -0
- data/lib/command_mapper/gen/cli.rb +233 -0
- data/lib/command_mapper/gen/command.rb +202 -0
- data/lib/command_mapper/gen/exceptions.rb +9 -0
- data/lib/command_mapper/gen/option.rb +66 -0
- data/lib/command_mapper/gen/option_value.rb +23 -0
- data/lib/command_mapper/gen/parsers/common.rb +49 -0
- data/lib/command_mapper/gen/parsers/help.rb +351 -0
- data/lib/command_mapper/gen/parsers/man.rb +80 -0
- data/lib/command_mapper/gen/parsers/options.rb +127 -0
- data/lib/command_mapper/gen/parsers/usage.rb +141 -0
- data/lib/command_mapper/gen/parsers.rb +2 -0
- data/lib/command_mapper/gen/task.rb +90 -0
- data/lib/command_mapper/gen/types/enum.rb +30 -0
- data/lib/command_mapper/gen/types/key_value.rb +34 -0
- data/lib/command_mapper/gen/types/list.rb +34 -0
- data/lib/command_mapper/gen/types/map.rb +36 -0
- data/lib/command_mapper/gen/types/num.rb +18 -0
- data/lib/command_mapper/gen/types/str.rb +48 -0
- data/lib/command_mapper/gen/types.rb +6 -0
- data/lib/command_mapper/gen/version.rb +6 -0
- data/lib/command_mapper/gen.rb +2 -0
- data/spec/argument_spec.rb +92 -0
- data/spec/cli_spec.rb +269 -0
- data/spec/command_spec.rb +316 -0
- data/spec/option_spec.rb +85 -0
- data/spec/option_value_spec.rb +20 -0
- data/spec/parsers/common_spec.rb +616 -0
- data/spec/parsers/help_spec.rb +612 -0
- data/spec/parsers/man_spec.rb +158 -0
- data/spec/parsers/options_spec.rb +802 -0
- data/spec/parsers/usage_spec.rb +1175 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/task_spec.rb +69 -0
- data/spec/types/enum_spec.rb +45 -0
- data/spec/types/key_value_spec.rb +36 -0
- data/spec/types/list_spec.rb +36 -0
- data/spec/types/map_spec.rb +48 -0
- data/spec/types/str_spec.rb +70 -0
- metadata +133 -0
@@ -0,0 +1,802 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/gen/parsers/options'
|
3
|
+
|
4
|
+
describe CommandMapper::Gen::Parsers::Options do
|
5
|
+
describe "#name" do
|
6
|
+
subject { super().name }
|
7
|
+
|
8
|
+
context "when given a uppercase name" do
|
9
|
+
context "and it's a single character" do
|
10
|
+
let(:string) { 'A' }
|
11
|
+
|
12
|
+
it "must parse it" do
|
13
|
+
expect(subject.parse(string)).to eq(string)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "and it's multiple characters" do
|
18
|
+
let(:string) { 'ABC' }
|
19
|
+
|
20
|
+
it "must parse it" do
|
21
|
+
expect(subject.parse(string)).to eq(string)
|
22
|
+
end
|
23
|
+
|
24
|
+
context "but it starts with a digit" do
|
25
|
+
let(:string) { '1FOO' }
|
26
|
+
|
27
|
+
it "must not parse it" do
|
28
|
+
expect {
|
29
|
+
subject.parse(string)
|
30
|
+
}.to raise_error(Parslet::ParseFailed)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "and it contains a digit" do
|
35
|
+
let(:string) { 'FOO1' }
|
36
|
+
|
37
|
+
it "must parse it" do
|
38
|
+
expect(subject.parse(string)).to eq(string)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "but it starts with a '_'" do
|
43
|
+
let(:string) { '_FOO' }
|
44
|
+
|
45
|
+
it "must not parse it" do
|
46
|
+
expect {
|
47
|
+
subject.parse(string)
|
48
|
+
}.to raise_error(Parslet::ParseFailed)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "and it contains a '_'" do
|
53
|
+
let(:string) { 'FOO_BAR' }
|
54
|
+
|
55
|
+
it "must parse it" do
|
56
|
+
expect(subject.parse(string)).to eq(string)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "but it contains a '-'" do
|
61
|
+
let(:string) { 'FOO-BAR' }
|
62
|
+
|
63
|
+
it "must parse it" do
|
64
|
+
expect(subject.parse(string)).to eq(string)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when given a lowercase name" do
|
71
|
+
context "and it's a single character" do
|
72
|
+
let(:string) { 'a' }
|
73
|
+
|
74
|
+
it "must parse it" do
|
75
|
+
expect(subject.parse(string)).to eq(string)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "and it's multiple characters" do
|
80
|
+
let(:string) { 'abc' }
|
81
|
+
|
82
|
+
it "must parse it" do
|
83
|
+
expect(subject.parse(string)).to eq(string)
|
84
|
+
end
|
85
|
+
|
86
|
+
context "but it starts with a digit" do
|
87
|
+
let(:string) { '1foo' }
|
88
|
+
|
89
|
+
it "must not parse it" do
|
90
|
+
expect {
|
91
|
+
subject.parse(string)
|
92
|
+
}.to raise_error(Parslet::ParseFailed)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "and it contains a digit" do
|
97
|
+
let(:string) { 'foo1' }
|
98
|
+
|
99
|
+
it "must parse it" do
|
100
|
+
expect(subject.parse(string)).to eq(string)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "but it starts with a '_'" do
|
105
|
+
let(:string) { '_foo' }
|
106
|
+
|
107
|
+
it "must not parse it" do
|
108
|
+
expect {
|
109
|
+
subject.parse(string)
|
110
|
+
}.to raise_error(Parslet::ParseFailed)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "and it contains a '_'" do
|
115
|
+
let(:string) { 'foo_bar' }
|
116
|
+
|
117
|
+
it "must parse it" do
|
118
|
+
expect(subject.parse(string)).to eq(string)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "and it contains a '-'" do
|
123
|
+
let(:string) { 'foo-bar' }
|
124
|
+
|
125
|
+
it "must parse it" do
|
126
|
+
expect(subject.parse(string)).to eq(string)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when given a capitalized name" do
|
133
|
+
context "and it's multiple characters" do
|
134
|
+
let(:string) { 'Abc' }
|
135
|
+
|
136
|
+
it "must parse it" do
|
137
|
+
expect(subject.parse(string)).to eq(string)
|
138
|
+
end
|
139
|
+
|
140
|
+
context "but it starts with a digit" do
|
141
|
+
let(:string) { '1Foo' }
|
142
|
+
|
143
|
+
it "must not parse it" do
|
144
|
+
expect {
|
145
|
+
subject.parse(string)
|
146
|
+
}.to raise_error(Parslet::ParseFailed)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "and it contains a digit" do
|
151
|
+
let(:string) { 'Foo1' }
|
152
|
+
|
153
|
+
it "must parse it" do
|
154
|
+
expect(subject.parse(string)).to eq(string)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "but it starts with a '_'" do
|
159
|
+
let(:string) { '_Foo' }
|
160
|
+
|
161
|
+
it "must not parse it" do
|
162
|
+
expect {
|
163
|
+
subject.parse(string)
|
164
|
+
}.to raise_error(Parslet::ParseFailed)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "and it contains a '_'" do
|
169
|
+
let(:string) { 'Foo_bar' }
|
170
|
+
|
171
|
+
it "must parse it" do
|
172
|
+
expect(subject.parse(string)).to eq(string)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "and it contains a '-'" do
|
177
|
+
let(:string) { 'Foo-bar' }
|
178
|
+
|
179
|
+
it "must parse it" do
|
180
|
+
expect(subject.parse(string)).to eq(string)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context "when given a camelCase name" do
|
187
|
+
context "and it's multiple characters" do
|
188
|
+
let(:string) { 'aaBcc' }
|
189
|
+
|
190
|
+
it "must parse it" do
|
191
|
+
expect(subject.parse(string)).to eq(string)
|
192
|
+
end
|
193
|
+
|
194
|
+
context "but it starts with a digit" do
|
195
|
+
let(:string) { '1aaBcc' }
|
196
|
+
|
197
|
+
it "must not parse it" do
|
198
|
+
expect {
|
199
|
+
subject.parse(string)
|
200
|
+
}.to raise_error(Parslet::ParseFailed)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context "and it contains a digit" do
|
205
|
+
let(:string) { 'aaB1cc' }
|
206
|
+
|
207
|
+
it "must parse it" do
|
208
|
+
expect(subject.parse(string)).to eq(string)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context "and it ends with a digit" do
|
213
|
+
let(:string) { 'aaBcc1' }
|
214
|
+
|
215
|
+
it "must parse it" do
|
216
|
+
expect(subject.parse(string)).to eq(string)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "but it starts with a '_'" do
|
221
|
+
let(:string) { '_aaBcc' }
|
222
|
+
|
223
|
+
it "must not parse it" do
|
224
|
+
expect {
|
225
|
+
subject.parse(string)
|
226
|
+
}.to raise_error(Parslet::ParseFailed)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
context "and it contains a '_'" do
|
231
|
+
let(:string) { 'aa_Bcc' }
|
232
|
+
|
233
|
+
it "must not parse it" do
|
234
|
+
expect {
|
235
|
+
subject.parse(string)
|
236
|
+
}.to raise_error(Parslet::ParseFailed)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
context "and it contains a '-'" do
|
241
|
+
let(:string) { 'aa-Bcc' }
|
242
|
+
|
243
|
+
it "must not parse it" do
|
244
|
+
expect {
|
245
|
+
subject.parse(string)
|
246
|
+
}.to raise_error(Parslet::ParseFailed)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "#literal_values" do
|
254
|
+
subject { super().literal_values }
|
255
|
+
|
256
|
+
context "when given 'foo'" do
|
257
|
+
let(:string) { "foo" }
|
258
|
+
|
259
|
+
it "must not parse the single name" do
|
260
|
+
expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context "when given 'foo|bar'" do
|
265
|
+
let(:literal1) { "foo" }
|
266
|
+
let(:literal2) { "bar" }
|
267
|
+
let(:string) { "#{literal1}|#{literal2}" }
|
268
|
+
|
269
|
+
it "must parse both literal string values" do
|
270
|
+
expect(subject.parse(string)).to eq(
|
271
|
+
{
|
272
|
+
literal_values: [
|
273
|
+
{string: literal1},
|
274
|
+
{string: literal2}
|
275
|
+
]
|
276
|
+
}
|
277
|
+
)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
context "when given 'foo|bar|baz'" do
|
282
|
+
let(:literal1) { "foo" }
|
283
|
+
let(:literal2) { "bar" }
|
284
|
+
let(:literal3) { "baz" }
|
285
|
+
let(:string) { "#{literal1}|#{literal2}|#{literal3}" }
|
286
|
+
|
287
|
+
it "must parse both literal string values" do
|
288
|
+
expect(subject.parse(string)).to eq(
|
289
|
+
{
|
290
|
+
literal_values: [
|
291
|
+
{string: literal1},
|
292
|
+
{string: literal2},
|
293
|
+
{string: literal3}
|
294
|
+
]
|
295
|
+
}
|
296
|
+
)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context "when given 'foo,bar'" do
|
301
|
+
let(:literal1) { "foo" }
|
302
|
+
let(:literal2) { "bar" }
|
303
|
+
let(:string) { "#{literal1},#{literal2}" }
|
304
|
+
|
305
|
+
it "must parse both literal string values" do
|
306
|
+
expect(subject.parse(string)).to eq(
|
307
|
+
{
|
308
|
+
literal_values: [
|
309
|
+
{string: literal1},
|
310
|
+
{string: literal2}
|
311
|
+
]
|
312
|
+
}
|
313
|
+
)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context "when given 'foo,bar,baz'" do
|
318
|
+
let(:literal1) { "foo" }
|
319
|
+
let(:literal2) { "bar" }
|
320
|
+
let(:literal3) { "baz" }
|
321
|
+
let(:string) { "#{literal1},#{literal2},#{literal3}" }
|
322
|
+
|
323
|
+
it "must parse both literal string values" do
|
324
|
+
expect(subject.parse(string)).to eq(
|
325
|
+
{
|
326
|
+
literal_values: [
|
327
|
+
{string: literal1},
|
328
|
+
{string: literal2},
|
329
|
+
{string: literal3}
|
330
|
+
]
|
331
|
+
}
|
332
|
+
)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
describe "#list" do
|
338
|
+
subject { super().list }
|
339
|
+
|
340
|
+
context "when given 'VALUE,...'" do
|
341
|
+
let(:separator) { ',' }
|
342
|
+
let(:name) { "ITEM" }
|
343
|
+
let(:string) { "#{name}#{separator}..." }
|
344
|
+
|
345
|
+
it "must parse the list item name and separator" do
|
346
|
+
expect(subject.parse(string)).to eq(
|
347
|
+
{
|
348
|
+
list: {
|
349
|
+
name: name,
|
350
|
+
separator: separator
|
351
|
+
}
|
352
|
+
}
|
353
|
+
)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
describe "#key_value" do
|
359
|
+
subject { super().key_value }
|
360
|
+
|
361
|
+
context "when given 'KEY:VALUE'" do
|
362
|
+
let(:separator) { ':' }
|
363
|
+
let(:string) { "key#{separator}value" }
|
364
|
+
|
365
|
+
it "must parse the key:value and separator" do
|
366
|
+
expect(subject.parse(string)).to eq(
|
367
|
+
{
|
368
|
+
key_value: {separator: separator}
|
369
|
+
}
|
370
|
+
)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
context "when given 'KEY=VALUE'" do
|
375
|
+
let(:separator) { '=' }
|
376
|
+
let(:string) { "key#{separator}value" }
|
377
|
+
|
378
|
+
it "must parse the key:value and separator" do
|
379
|
+
expect(subject.parse(string)).to eq(
|
380
|
+
{
|
381
|
+
key_value: {separator: separator}
|
382
|
+
}
|
383
|
+
)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
describe "#value" do
|
389
|
+
subject { super().value }
|
390
|
+
|
391
|
+
context "when given 'NAME,...'" do
|
392
|
+
let(:name) { "NAME" }
|
393
|
+
let(:string) { "#{name},..." }
|
394
|
+
|
395
|
+
it "must parse the value as a list" do
|
396
|
+
expect(subject.parse(string)).to eq(
|
397
|
+
{
|
398
|
+
value: {
|
399
|
+
list: {name: name, separator: ','}
|
400
|
+
}
|
401
|
+
}
|
402
|
+
)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context "when given 'KEY:VALUE'" do
|
407
|
+
let(:key) { "NAME" }
|
408
|
+
let(:value) { "VALUE" }
|
409
|
+
let(:separator) { ':' }
|
410
|
+
let(:string) { "#{key}#{separator}#{value}" }
|
411
|
+
|
412
|
+
it "must parse the value as a list" do
|
413
|
+
expect(subject.parse(string)).to eq(
|
414
|
+
{
|
415
|
+
value: {
|
416
|
+
key_value: {separator: separator}
|
417
|
+
}
|
418
|
+
}
|
419
|
+
)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
context "when given 'KEY=VALUE'" do
|
424
|
+
let(:key) { "NAME" }
|
425
|
+
let(:value) { "VALUE" }
|
426
|
+
let(:separator) { '=' }
|
427
|
+
let(:string) { "#{key}#{separator}#{value}" }
|
428
|
+
|
429
|
+
it "must parse the value as a list" do
|
430
|
+
expect(subject.parse(string)).to eq(
|
431
|
+
{
|
432
|
+
value: {
|
433
|
+
key_value: {separator: separator}
|
434
|
+
}
|
435
|
+
}
|
436
|
+
)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
context "when given 'str1|...'" do
|
441
|
+
let(:str1) { 'str1' }
|
442
|
+
let(:str2) { 'str2' }
|
443
|
+
let(:string) { "#{str1}|#{str2}" }
|
444
|
+
|
445
|
+
it "must parse the list of literal string values" do
|
446
|
+
expect(subject.parse(string)).to eq(
|
447
|
+
{
|
448
|
+
value: {
|
449
|
+
literal_values: [
|
450
|
+
{string: str1},
|
451
|
+
{string: str2}
|
452
|
+
]
|
453
|
+
}
|
454
|
+
}
|
455
|
+
)
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
context "when given 'name" do
|
460
|
+
let(:name) { 'name' }
|
461
|
+
let(:string) { name }
|
462
|
+
|
463
|
+
it "must parse the option's value name" do
|
464
|
+
expect(subject.parse(string)).to eq({value: {name: name}})
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
context "when given 'NAME" do
|
469
|
+
let(:name) { 'NAME' }
|
470
|
+
let(:string) { name }
|
471
|
+
|
472
|
+
it "must parse the option's value name" do
|
473
|
+
expect(subject.parse(string)).to eq({value: {name: name}})
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
describe "#value_container" do
|
479
|
+
subject { super().value_container }
|
480
|
+
|
481
|
+
context "when given '{NAME}'" do
|
482
|
+
let(:name) { "NAME" }
|
483
|
+
let(:string) { "{#{name}}" }
|
484
|
+
|
485
|
+
it "must parse the value within the { }" do
|
486
|
+
expect(subject.parse(string)).to eq(
|
487
|
+
{
|
488
|
+
value: {name: name}
|
489
|
+
}
|
490
|
+
)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
context "when given '<VALUE>'" do
|
495
|
+
let(:name) { "NAME" }
|
496
|
+
let(:string) { "<#{name}>" }
|
497
|
+
|
498
|
+
it "must parse the value within the < >" do
|
499
|
+
expect(subject.parse(string)).to eq(
|
500
|
+
{
|
501
|
+
value: {name: name}
|
502
|
+
}
|
503
|
+
)
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
context "when given '[VALUE]'" do
|
508
|
+
let(:name) { "NAME" }
|
509
|
+
let(:string) { "[#{name}]" }
|
510
|
+
|
511
|
+
it "must parse the optional value within the [ ]" do
|
512
|
+
expect(subject.parse(string)).to eq(
|
513
|
+
{
|
514
|
+
optional: {
|
515
|
+
value: {name: name}
|
516
|
+
}
|
517
|
+
}
|
518
|
+
)
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
context "when given 'VALUE'" do
|
523
|
+
let(:name) { "NAME" }
|
524
|
+
let(:string) { "#{name}" }
|
525
|
+
|
526
|
+
it "must return the value" do
|
527
|
+
expect(subject.parse(string)).to eq(
|
528
|
+
{
|
529
|
+
value: {name: name}
|
530
|
+
}
|
531
|
+
)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
describe "#option" do
|
537
|
+
let(:short_flag) { '-o' }
|
538
|
+
let(:long_flag) { '--opt' }
|
539
|
+
let(:value) { 'VALUE' }
|
540
|
+
|
541
|
+
subject { super().option }
|
542
|
+
|
543
|
+
context "when given '-o'" do
|
544
|
+
let(:string) { short_flag }
|
545
|
+
|
546
|
+
it "must capture the short flag" do
|
547
|
+
expect(subject.parse(string)).to eq({short_flag: short_flag})
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
context "when given '-o VALUE'" do
|
552
|
+
let(:string) { "#{short_flag} #{value}" }
|
553
|
+
|
554
|
+
it "must capture short flag and argument name" do
|
555
|
+
expect(subject.parse(string)).to eq(
|
556
|
+
{
|
557
|
+
short_flag: short_flag,
|
558
|
+
value: {name: value}
|
559
|
+
}
|
560
|
+
)
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
context "when given '-o=VALUE'" do
|
565
|
+
let(:string) { "#{short_flag}=#{value}" }
|
566
|
+
|
567
|
+
it "must capture the short flag, equals, and value" do
|
568
|
+
expect(subject.parse(string)).to eq(
|
569
|
+
{
|
570
|
+
short_flag: short_flag,
|
571
|
+
equals: '=',
|
572
|
+
value: {name: value}
|
573
|
+
}
|
574
|
+
)
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
context "when given '--opt'" do
|
579
|
+
let(:string) { long_flag }
|
580
|
+
|
581
|
+
it "must capture the long flag" do
|
582
|
+
expect(subject.parse(string)).to eq(
|
583
|
+
{
|
584
|
+
long_flag: long_flag
|
585
|
+
}
|
586
|
+
)
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
context "when given '--opt VALUE'" do
|
591
|
+
let(:string) { "#{long_flag} #{value}" }
|
592
|
+
|
593
|
+
it "must capture the long flag and value" do
|
594
|
+
expect(subject.parse(string)).to eq(
|
595
|
+
{
|
596
|
+
long_flag: long_flag,
|
597
|
+
value: {name: value}
|
598
|
+
}
|
599
|
+
)
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
context "when given '--opt=VALUE'" do
|
604
|
+
let(:string) { "#{long_flag}=#{value}" }
|
605
|
+
|
606
|
+
it "must capture the long flag, equals, and value" do
|
607
|
+
expect(subject.parse(string)).to eq(
|
608
|
+
{
|
609
|
+
long_flag: long_flag,
|
610
|
+
equals: '=',
|
611
|
+
value: {name: value}
|
612
|
+
}
|
613
|
+
)
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
context "when given '-o, --opt'" do
|
618
|
+
let(:string) { "#{short_flag}, #{long_flag}" }
|
619
|
+
|
620
|
+
it "must capture the short flag and long flag" do
|
621
|
+
expect(subject.parse(string)).to eq(
|
622
|
+
{
|
623
|
+
short_flag: short_flag,
|
624
|
+
long_flag: long_flag
|
625
|
+
}
|
626
|
+
)
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
context "when given '-o, --opt1, --opt2, --opt3'" do
|
631
|
+
let(:long_Flag) { "--opt1" }
|
632
|
+
let(:string) { "#{short_flag}, #{long_flag}, --opt2, --opt3" }
|
633
|
+
|
634
|
+
it "must only capture the short flag and first long flag" do
|
635
|
+
expect(subject.parse(string)).to eq(
|
636
|
+
{
|
637
|
+
short_flag: short_flag,
|
638
|
+
long_flag: long_flag
|
639
|
+
}
|
640
|
+
)
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
context "when given '-o, --opt VALUE'" do
|
645
|
+
let(:string) { "#{short_flag}, #{long_flag} #{value}" }
|
646
|
+
|
647
|
+
it "must capture the short flag, long flag, and value" do
|
648
|
+
expect(subject.parse(string)).to eq(
|
649
|
+
{
|
650
|
+
short_flag: short_flag,
|
651
|
+
long_flag: long_flag,
|
652
|
+
value: {name: value}
|
653
|
+
}
|
654
|
+
)
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
658
|
+
context "when given '-o, --opt=VALUE'" do
|
659
|
+
let(:string) { "#{short_flag}, #{long_flag}=#{value}" }
|
660
|
+
|
661
|
+
it "must capture the short flag, long flag, equals, and value" do
|
662
|
+
expect(subject.parse(string)).to eq(
|
663
|
+
{
|
664
|
+
short_flag: short_flag,
|
665
|
+
long_flag: long_flag,
|
666
|
+
equals: '=',
|
667
|
+
value: {name: value}
|
668
|
+
}
|
669
|
+
)
|
670
|
+
end
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
describe "#option_line" do
|
675
|
+
subject { super().option_line }
|
676
|
+
|
677
|
+
let(:short_flag) { '-o' }
|
678
|
+
let(:long_flag) { '--opt' }
|
679
|
+
let(:value) { 'VALUE' }
|
680
|
+
|
681
|
+
context "when given a line only containing options" do
|
682
|
+
let(:line) { " #{short_flag}, #{long_flag}=#{value}" }
|
683
|
+
|
684
|
+
it "must parse the options" do
|
685
|
+
expect(subject.parse(line)).to eq(
|
686
|
+
{
|
687
|
+
short_flag: short_flag,
|
688
|
+
long_flag: long_flag,
|
689
|
+
equals: '=',
|
690
|
+
value: {name: value}
|
691
|
+
}
|
692
|
+
)
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
context "when the line begins with a single space" do
|
697
|
+
let(:line) { " #{short_flag}, #{long_flag}=#{value}" }
|
698
|
+
|
699
|
+
it "must parse the options" do
|
700
|
+
expect(subject.parse(line)).to eq(
|
701
|
+
{
|
702
|
+
short_flag: short_flag,
|
703
|
+
long_flag: long_flag,
|
704
|
+
equals: '=',
|
705
|
+
value: {name: value}
|
706
|
+
}
|
707
|
+
)
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
context "when the line begins with multiple spaces" do
|
712
|
+
let(:line) { " #{short_flag}, #{long_flag}=#{value}" }
|
713
|
+
|
714
|
+
it "must parse the options" do
|
715
|
+
expect(subject.parse(line)).to eq(
|
716
|
+
{
|
717
|
+
short_flag: short_flag,
|
718
|
+
long_flag: long_flag,
|
719
|
+
equals: '=',
|
720
|
+
value: {name: value}
|
721
|
+
}
|
722
|
+
)
|
723
|
+
end
|
724
|
+
end
|
725
|
+
|
726
|
+
context "when the line begins with a single tab" do
|
727
|
+
let(:line) { "\t#{short_flag}, #{long_flag}=#{value}" }
|
728
|
+
|
729
|
+
it "must parse the options" do
|
730
|
+
expect(subject.parse(line)).to eq(
|
731
|
+
{
|
732
|
+
short_flag: short_flag,
|
733
|
+
long_flag: long_flag,
|
734
|
+
equals: '=',
|
735
|
+
value: {name: value}
|
736
|
+
}
|
737
|
+
)
|
738
|
+
end
|
739
|
+
end
|
740
|
+
|
741
|
+
context "when given a line with trailing option summary text" do
|
742
|
+
let(:summary) { 'Does stuff and stuff.' }
|
743
|
+
let(:line) { " #{short_flag}, #{long_flag}=#{value}\t#{summary}" }
|
744
|
+
|
745
|
+
it "must parse the options and ignore the summary text" do
|
746
|
+
expect(subject.parse(line)).to eq(
|
747
|
+
{
|
748
|
+
short_flag: short_flag,
|
749
|
+
long_flag: long_flag,
|
750
|
+
equals: '=',
|
751
|
+
value: {name: value}
|
752
|
+
}
|
753
|
+
)
|
754
|
+
end
|
755
|
+
|
756
|
+
context "and the summary is indented with multiple spaces" do
|
757
|
+
let(:line) { " #{short_flag}, #{long_flag}=#{value} #{summary}" }
|
758
|
+
|
759
|
+
it "must parse the options and ignore the summary text" do
|
760
|
+
expect(subject.parse(line)).to eq(
|
761
|
+
{
|
762
|
+
short_flag: short_flag,
|
763
|
+
long_flag: long_flag,
|
764
|
+
equals: '=',
|
765
|
+
value: {name: value}
|
766
|
+
}
|
767
|
+
)
|
768
|
+
end
|
769
|
+
end
|
770
|
+
|
771
|
+
context "and the summary is indented with a single tab" do
|
772
|
+
let(:line) { " #{short_flag}, #{long_flag}=#{value}\t#{summary}" }
|
773
|
+
|
774
|
+
it "must parse the options and ignore the summary text" do
|
775
|
+
expect(subject.parse(line)).to eq(
|
776
|
+
{
|
777
|
+
short_flag: short_flag,
|
778
|
+
long_flag: long_flag,
|
779
|
+
equals: '=',
|
780
|
+
value: {name: value}
|
781
|
+
}
|
782
|
+
)
|
783
|
+
end
|
784
|
+
end
|
785
|
+
|
786
|
+
context "and the summary is indented with a both tabs and spaces" do
|
787
|
+
let(:line) { " #{short_flag}, #{long_flag}=#{value}\t #{summary}" }
|
788
|
+
|
789
|
+
it "must parse the options and ignore the summary text" do
|
790
|
+
expect(subject.parse(line)).to eq(
|
791
|
+
{
|
792
|
+
short_flag: short_flag,
|
793
|
+
long_flag: long_flag,
|
794
|
+
equals: '=',
|
795
|
+
value: {name: value}
|
796
|
+
}
|
797
|
+
)
|
798
|
+
end
|
799
|
+
end
|
800
|
+
end
|
801
|
+
end
|
802
|
+
end
|