command_mapper-gen 0.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +27 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +1 -0
  6. data/ChangeLog.md +20 -0
  7. data/Gemfile +17 -0
  8. data/LICENSE.txt +20 -0
  9. data/README.md +145 -0
  10. data/Rakefile +15 -0
  11. data/bin/command_mapper-gen +7 -0
  12. data/commnad_mapper-gen.gemspec +61 -0
  13. data/examples/grep.rb +63 -0
  14. data/gemspec.yml +26 -0
  15. data/lib/command_mapper/gen/arg.rb +43 -0
  16. data/lib/command_mapper/gen/argument.rb +53 -0
  17. data/lib/command_mapper/gen/cli.rb +233 -0
  18. data/lib/command_mapper/gen/command.rb +202 -0
  19. data/lib/command_mapper/gen/exceptions.rb +9 -0
  20. data/lib/command_mapper/gen/option.rb +66 -0
  21. data/lib/command_mapper/gen/option_value.rb +23 -0
  22. data/lib/command_mapper/gen/parsers/common.rb +49 -0
  23. data/lib/command_mapper/gen/parsers/help.rb +351 -0
  24. data/lib/command_mapper/gen/parsers/man.rb +80 -0
  25. data/lib/command_mapper/gen/parsers/options.rb +127 -0
  26. data/lib/command_mapper/gen/parsers/usage.rb +141 -0
  27. data/lib/command_mapper/gen/parsers.rb +2 -0
  28. data/lib/command_mapper/gen/task.rb +90 -0
  29. data/lib/command_mapper/gen/types/enum.rb +30 -0
  30. data/lib/command_mapper/gen/types/key_value.rb +34 -0
  31. data/lib/command_mapper/gen/types/list.rb +34 -0
  32. data/lib/command_mapper/gen/types/map.rb +36 -0
  33. data/lib/command_mapper/gen/types/num.rb +18 -0
  34. data/lib/command_mapper/gen/types/str.rb +48 -0
  35. data/lib/command_mapper/gen/types.rb +6 -0
  36. data/lib/command_mapper/gen/version.rb +6 -0
  37. data/lib/command_mapper/gen.rb +2 -0
  38. data/spec/argument_spec.rb +92 -0
  39. data/spec/cli_spec.rb +269 -0
  40. data/spec/command_spec.rb +316 -0
  41. data/spec/option_spec.rb +85 -0
  42. data/spec/option_value_spec.rb +20 -0
  43. data/spec/parsers/common_spec.rb +616 -0
  44. data/spec/parsers/help_spec.rb +612 -0
  45. data/spec/parsers/man_spec.rb +158 -0
  46. data/spec/parsers/options_spec.rb +802 -0
  47. data/spec/parsers/usage_spec.rb +1175 -0
  48. data/spec/spec_helper.rb +6 -0
  49. data/spec/task_spec.rb +69 -0
  50. data/spec/types/enum_spec.rb +45 -0
  51. data/spec/types/key_value_spec.rb +36 -0
  52. data/spec/types/list_spec.rb +36 -0
  53. data/spec/types/map_spec.rb +48 -0
  54. data/spec/types/str_spec.rb +70 -0
  55. metadata +133 -0
@@ -0,0 +1,1175 @@
1
+ require 'spec_helper'
2
+ require 'command_mapper/gen/parsers/usage'
3
+
4
+ describe CommandMapper::Gen::Parsers::Usage do
5
+ describe "#capitalized_word" do
6
+ subject { super().capitalized_word }
7
+
8
+ context "when given a single lowercase character" do
9
+ let(:string) { 'a' }
10
+
11
+ it "must not parse it" do
12
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
13
+ end
14
+ end
15
+
16
+ context "when given a '_' character" do
17
+ let(:string) { '_' }
18
+
19
+ it "must not parse it" do
20
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
21
+ end
22
+ end
23
+
24
+ context "when given one uppercase character" do
25
+ let(:string) { 'A' }
26
+
27
+ it "must not parse it" do
28
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
29
+ end
30
+ end
31
+
32
+ context "when given one uppercase character and a lowercase character" do
33
+ let(:string) { 'Ab' }
34
+
35
+ it "must parse it" do
36
+ expect(subject.parse(string)).to eq(string)
37
+ end
38
+ end
39
+
40
+ context "when given one uppercase character followed by multiple lowercase characters" do
41
+ let(:string) { 'Abbbb' }
42
+
43
+ it "must parse it" do
44
+ expect(subject.parse(string)).to eq(string)
45
+ end
46
+
47
+ context "and it contains a '_' character" do
48
+ let(:string) { 'Abb_bb' }
49
+
50
+ it "must not parse it" do
51
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
52
+ end
53
+ end
54
+
55
+ context "and it contains a '-' character" do
56
+ let(:string) { 'Abb-bb' }
57
+
58
+ it "must not parse it" do
59
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
60
+ end
61
+ end
62
+ end
63
+
64
+ context "when given two uppercase characters" do
65
+ let(:string) { 'AB' }
66
+
67
+ it "must not parse it" do
68
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "#lowercase_word" do
74
+ subject { super().lowercase_word }
75
+
76
+ context "when given a '_' character" do
77
+ let(:string) { '_' }
78
+
79
+ it "must not parse it" do
80
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
81
+ end
82
+ end
83
+
84
+ context "when given one lowercase character" do
85
+ let(:string) { 'a' }
86
+
87
+ it "must parse it" do
88
+ expect(subject.parse(string)).to eq(string)
89
+ end
90
+ end
91
+
92
+ context "when given multiple lowercase characters" do
93
+ let(:string) { 'ab' }
94
+
95
+ it "must parse it" do
96
+ expect(subject.parse(string)).to eq(string)
97
+ end
98
+
99
+ context "and it contains a '_' character" do
100
+ let(:string) { 'abb_bb' }
101
+
102
+ it "must not parse it" do
103
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
104
+ end
105
+ end
106
+
107
+ context "and it contains a '-' character" do
108
+ let(:string) { 'Abb-bb' }
109
+
110
+ it "must not parse it" do
111
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
112
+ end
113
+ end
114
+ end
115
+
116
+ context "when given a single uppercase characters" do
117
+ let(:string) { 'A' }
118
+
119
+ it "must not parse it" do
120
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
121
+ end
122
+ end
123
+
124
+ context "when it contains a uppercase character" do
125
+ let(:string) { 'aaaaBaaaa' }
126
+
127
+ it "must not parse it" do
128
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
129
+ end
130
+ end
131
+ end
132
+
133
+ describe "#word" do
134
+ subject { super().word }
135
+
136
+ context "when given a lowercase word" do
137
+ let(:string) { "foo" }
138
+
139
+ it "must parse it" do
140
+ expect(subject.parse(string)).to eq(string)
141
+ end
142
+ end
143
+
144
+ context "when given a capitalized word" do
145
+ let(:string) { "Foo" }
146
+
147
+ it "must parse it" do
148
+ expect(subject.parse(string)).to eq(string)
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "#words" do
154
+ subject { super().words }
155
+
156
+ context "when given one word" do
157
+ let(:word) { "foo" }
158
+ let(:string) { word }
159
+
160
+ it "must not parse it" do
161
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
162
+ end
163
+ end
164
+
165
+ context "when given two words" do
166
+ let(:words) { "foo bar" }
167
+ let(:string) { words }
168
+
169
+ it "must capture the word" do
170
+ expect(subject.parse(string)).to eq({words: words})
171
+ end
172
+ end
173
+
174
+ context "when given more than two words separated by a space" do
175
+ let(:words) { "foo Bar baz" }
176
+ let(:string) { words }
177
+
178
+ it "must capture the multiple words" do
179
+ expect(subject.parse(string)).to eq({words: words})
180
+ end
181
+ end
182
+
183
+ context "when the words end with '...'" do
184
+ let(:words) { "foo bar baz" }
185
+ let(:string) { "#{words} ..." }
186
+
187
+ it "must capture the words and the ellipsis" do
188
+ expect(subject.parse(string)).to eq({words: words, repeats: "..."})
189
+ end
190
+ end
191
+ end
192
+
193
+ describe "#argument_name" do
194
+ subject { super().argument_name }
195
+
196
+ context "when given a lowercase name" do
197
+ let(:name) { "foo" }
198
+ let(:string) { name }
199
+
200
+ it "must capture the name" do
201
+ expect(subject.parse(string)).to eq(
202
+ {
203
+ argument: {name: name}
204
+ }
205
+ )
206
+ end
207
+
208
+ context "and the string ends with a '...'" do
209
+ let(:string) { "#{name} ..." }
210
+
211
+ it "must capture the name and the ellipsis" do
212
+ expect(subject.parse(string)).to eq(
213
+ {
214
+ argument: {
215
+ name: name,
216
+ repeats: "..."
217
+ }
218
+ }
219
+ )
220
+ end
221
+ end
222
+ end
223
+
224
+ context "when given an uppercase name" do
225
+ let(:name) { "FOO" }
226
+ let(:string) { name }
227
+
228
+ it "must capture the name" do
229
+ expect(subject.parse(string)).to eq(
230
+ {
231
+ argument: {name: name}
232
+ }
233
+ )
234
+ end
235
+
236
+ context "and the string ends with a '...'" do
237
+ let(:string) { "#{name} ..." }
238
+
239
+ it "must capture the name and the ellipsis" do
240
+ expect(subject.parse(string)).to eq(
241
+ {
242
+ argument: {
243
+ name: name,
244
+ repeats: "..."
245
+ }
246
+ }
247
+ )
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ describe "#short_flags" do
254
+ subject { super().short_flags }
255
+
256
+ context "when given a short flag (ex: '-o')" do
257
+ let(:short_flag) { "-o" }
258
+ let(:string) { short_flag }
259
+
260
+ it "must not parse it" do
261
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
262
+ end
263
+ end
264
+
265
+ context "when given an amalgamation of short flags (ex: '-xyz')" do
266
+ let(:short_flags) { "-xyz" }
267
+ let(:string) { short_flags }
268
+
269
+ it "must capture the short flags" do
270
+ expect(subject.parse(string)).to eq({short_flags: short_flags})
271
+ end
272
+ end
273
+ end
274
+
275
+ describe "#flag" do
276
+ subject { super().flag }
277
+
278
+ context "when given a long flag (ex: '--opt')" do
279
+ let(:long_flag) { "--opt" }
280
+ let(:string) { long_flag }
281
+
282
+ it "must capture the long flag" do
283
+ expect(subject.parse(string)).to eq({long_flag: long_flag})
284
+ end
285
+ end
286
+
287
+ context "when given a short flag (ex: '-o')" do
288
+ let(:short_flag) { "-o" }
289
+ let(:string) { short_flag }
290
+
291
+ it "must capture the short flag" do
292
+ expect(subject.parse(string)).to eq({short_flag: short_flag})
293
+ end
294
+ end
295
+
296
+ context "when given an amalgamation of short flags (ex: '-xyz')" do
297
+ let(:short_flags) { "-xyz" }
298
+ let(:string) { short_flags }
299
+
300
+ it "must capture the short flags" do
301
+ expect(subject.parse(string)).to eq({short_flags: short_flags})
302
+ end
303
+ end
304
+ end
305
+
306
+ describe "#option_value_string" do
307
+ subject { super().option_value_string }
308
+
309
+ context "when given an empty string" do
310
+ let(:string) { "" }
311
+
312
+ it "must not parse it" do
313
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
314
+ end
315
+ end
316
+
317
+ context "when given one lowercase character" do
318
+ let(:string) { 'a' }
319
+
320
+ it "must capture the string" do
321
+ expect(subject.parse(string)).to eq({string: string})
322
+ end
323
+ end
324
+
325
+ context "when given multiple lowercase characters" do
326
+ let(:string) { 'ab' }
327
+
328
+ it "must capture the string" do
329
+ expect(subject.parse(string)).to eq({string: string})
330
+ end
331
+
332
+ context "and it contains a '_' character" do
333
+ let(:string) { 'a_b' }
334
+
335
+ it "must capture the string" do
336
+ expect(subject.parse(string)).to eq({string: string})
337
+ end
338
+ end
339
+
340
+ context "and it contains a '-' character" do
341
+ let(:string) { 'a-b' }
342
+
343
+ it "must capture the string" do
344
+ expect(subject.parse(string)).to eq({string: string})
345
+ end
346
+ end
347
+
348
+ context "and when it contains an uppercase character" do
349
+ let(:string) { 'aB' }
350
+
351
+ it "must capture the string" do
352
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
353
+ end
354
+ end
355
+ end
356
+ end
357
+
358
+ describe "#option_value_strings" do
359
+ subject { super().option_value_strings }
360
+
361
+ context "when given a single value string" do
362
+ let(:string) { "foo" }
363
+
364
+ it "must not parse it" do
365
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
366
+ end
367
+ end
368
+
369
+ let(:value_string1) { "foo" }
370
+ let(:value_string2) { "bar" }
371
+
372
+ context "when given two value strings" do
373
+ context "and it's separated by a ','" do
374
+ let(:string) { "#{value_string1},#{value_string2}" }
375
+
376
+ it "must capture the strings" do
377
+ expect(subject.parse(string)).to eq(
378
+ [
379
+ {string: value_string1},
380
+ {string: value_string2}
381
+ ]
382
+ )
383
+ end
384
+ end
385
+
386
+ context "and it's separated by a '|'" do
387
+ let(:string) { "#{value_string1}|#{value_string2}" }
388
+
389
+ it "must capture the strings" do
390
+ expect(subject.parse(string)).to eq(
391
+ [
392
+ {string: value_string1},
393
+ {string: value_string2}
394
+ ]
395
+ )
396
+ end
397
+ end
398
+ end
399
+
400
+ context "when given more than two value strings" do
401
+ let(:value_string3) { "baz" }
402
+
403
+ context "and it's separated by a ','" do
404
+ let(:string) { "#{value_string1},#{value_string2},#{value_string3}" }
405
+
406
+ it "must capture the strings" do
407
+ expect(subject.parse(string)).to eq(
408
+ [
409
+ {string: value_string1},
410
+ {string: value_string2},
411
+ {string: value_string3}
412
+ ]
413
+ )
414
+ end
415
+ end
416
+
417
+ context "and it's separated by a '|'" do
418
+ let(:string) { "#{value_string1}|#{value_string2}|#{value_string3}" }
419
+
420
+ it "must capture the strings" do
421
+ expect(subject.parse(string)).to eq(
422
+ [
423
+ {string: value_string1},
424
+ {string: value_string2},
425
+ {string: value_string3}
426
+ ]
427
+ )
428
+ end
429
+ end
430
+
431
+ context "but it's separated by a combination of ',' and '|'" do
432
+ let(:string) { "#{value_string1},#{value_string2}|#{value_string3}" }
433
+
434
+ it "must capture the strings" do
435
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
436
+ end
437
+ end
438
+ end
439
+ end
440
+
441
+ describe "#option_value_name" do
442
+ subject { super().option_value_name }
443
+
444
+ context "when given a lowercase name" do
445
+ let(:string) { 'foo' }
446
+
447
+ it "must capture it" do
448
+ expect(subject.parse(string)).to eq({name: string})
449
+ end
450
+ end
451
+
452
+ context "when given a capitalized name" do
453
+ let(:string) { 'Foo' }
454
+
455
+ it "must capture it" do
456
+ expect(subject.parse(string)).to eq({name: string})
457
+ end
458
+ end
459
+
460
+ context "when given a camelCase name" do
461
+ let(:string) { 'fooBar' }
462
+
463
+ it "must capture it" do
464
+ expect(subject.parse(string)).to eq({name: string})
465
+ end
466
+ end
467
+ end
468
+
469
+ describe "#option_value" do
470
+ subject { super().option_value }
471
+
472
+ context "when given multiple option value strings" do
473
+ let(:value_string1) { "foo" }
474
+ let(:value_string2) { "bar" }
475
+ let(:value_string3) { "baz" }
476
+
477
+ let(:string) { "#{value_string1},#{value_string2},#{value_string3}" }
478
+
479
+ it "must capture the option value strings" do
480
+ expect(subject.parse(string)).to eq(
481
+ [
482
+ {string: value_string1},
483
+ {string: value_string2},
484
+ {string: value_string3}
485
+ ]
486
+ )
487
+ end
488
+ end
489
+
490
+ context "when given a single option value name" do
491
+ let(:name) { "foo" }
492
+ let(:string) { name }
493
+
494
+ it "must capture the option value name" do
495
+ expect(subject.parse(string)).to eq({name: name})
496
+ end
497
+ end
498
+ end
499
+
500
+ describe "#optional_option_value" do
501
+ subject { super().optional_option_value }
502
+
503
+ context "and the contents is an option value name" do
504
+ let(:option_value_name) { "Foo" }
505
+ let(:string) { "[#{option_value_name}]" }
506
+
507
+ it "must parse the contents and mark it as optional" do
508
+ expect(subject.parse(string)).to eq(
509
+ {
510
+ optional: {
511
+ name: option_value_name
512
+ }
513
+ }
514
+ )
515
+ end
516
+ end
517
+
518
+ context "and the contents is an option value strings" do
519
+ let(:value_string1) { "foo" }
520
+ let(:value_string2) { "bar" }
521
+ let(:value_string3) { "baz" }
522
+
523
+ let(:option_value_strings) do
524
+ "#{value_string1},#{value_string2},#{value_string3}"
525
+ end
526
+
527
+ let(:string) { "[#{option_value_strings}]" }
528
+
529
+ it "must parse the contents and mark it as optional" do
530
+ expect(subject.parse(string)).to eq(
531
+ {
532
+ optional: [
533
+ {string: value_string1},
534
+ {string: value_string2},
535
+ {string: value_string3}
536
+ ]
537
+ }
538
+ )
539
+ end
540
+ end
541
+ end
542
+
543
+ describe "#option_value_container" do
544
+ subject { super().option_value_container }
545
+
546
+ let(:value_string1) { "foo" }
547
+ let(:value_string2) { "bar" }
548
+ let(:value_string3) { "baz" }
549
+
550
+ let(:option_value_strings) do
551
+ "#{value_string1},#{value_string2},#{value_string3}"
552
+ end
553
+
554
+ let(:option_value_name) { "Foo" }
555
+
556
+ context "when given a '{...}' string" do
557
+ context "and the contents is an option value name" do
558
+ let(:string) { "{#{option_value_name}}" }
559
+
560
+ it "must parse the contents" do
561
+ expect(subject.parse(string)).to eq({name: option_value_name})
562
+ end
563
+ end
564
+
565
+ context "and the contents is an option value strings" do
566
+ let(:string) { "{#{option_value_strings}}" }
567
+
568
+ it "must parse the contents" do
569
+ expect(subject.parse(string)).to eq(
570
+ [
571
+ {string: value_string1},
572
+ {string: value_string2},
573
+ {string: value_string3}
574
+ ]
575
+ )
576
+ end
577
+ end
578
+ end
579
+
580
+ context "when given a '<...>' string" do
581
+ context "and the contents is an option value name" do
582
+ let(:string) { "<#{option_value_name}>" }
583
+
584
+ it "must parse the contents" do
585
+ expect(subject.parse(string)).to eq({name: option_value_name})
586
+ end
587
+ end
588
+
589
+ context "and the contents is an option value strings" do
590
+ let(:string) { "<#{option_value_strings}>" }
591
+
592
+ it "must parse the contents" do
593
+ expect(subject.parse(string)).to eq(
594
+ [
595
+ {string: value_string1},
596
+ {string: value_string2},
597
+ {string: value_string3}
598
+ ]
599
+ )
600
+ end
601
+ end
602
+ end
603
+
604
+ context "when given a '[...]' string" do
605
+ context "and the contents is an option value name" do
606
+ let(:string) { "[#{option_value_name}]" }
607
+
608
+ it "must parse the contents and mark it as optional" do
609
+ expect(subject.parse(string)).to eq(
610
+ {
611
+ optional: {
612
+ name: option_value_name
613
+ }
614
+ }
615
+ )
616
+ end
617
+ end
618
+
619
+ context "and the contents is an option value strings" do
620
+ let(:string) { "[#{option_value_strings}]" }
621
+
622
+ it "must parse the contents" do
623
+ expect(subject.parse(string)).to eq(
624
+ {
625
+ optional: [
626
+ {string: value_string1},
627
+ {string: value_string2},
628
+ {string: value_string3}
629
+ ]
630
+ }
631
+ )
632
+ end
633
+ end
634
+ end
635
+
636
+ context "when given multiple option value strings" do
637
+ let(:value_string1) { "foo" }
638
+ let(:value_string2) { "bar" }
639
+ let(:value_string3) { "baz" }
640
+
641
+ let(:string) { "#{value_string1},#{value_string2},#{value_string3}" }
642
+
643
+ it "must capture the option value strings" do
644
+ expect(subject.parse(string)).to eq(
645
+ [
646
+ {string: value_string1},
647
+ {string: value_string2},
648
+ {string: value_string3}
649
+ ]
650
+ )
651
+ end
652
+ end
653
+
654
+ context "when given a single option value name" do
655
+ let(:name) { "foo" }
656
+ let(:string) { name }
657
+
658
+ it "must capture the option value name" do
659
+ expect(subject.parse(string)).to eq({name: name})
660
+ end
661
+ end
662
+ end
663
+
664
+ describe "#option" do
665
+ subject { super().option }
666
+
667
+ context "when given an option flag" do
668
+ let(:flag) { "--opt" }
669
+ let(:string) { flag }
670
+
671
+ it "must capture the option flag" do
672
+ expect(subject.parse(string)).to eq(
673
+ {
674
+ option: {long_flag: flag}
675
+ }
676
+ )
677
+ end
678
+
679
+ context "and a value name separated by a space" do
680
+ let(:name) { 'value' }
681
+ let(:string) { "#{flag} #{name}" }
682
+
683
+ it "must capture the option flag and option value name" do
684
+ expect(subject.parse(string)).to eq(
685
+ {
686
+ option: {
687
+ long_flag: flag,
688
+ value: {name: name}
689
+ }
690
+ }
691
+ )
692
+ end
693
+ end
694
+
695
+ context "and a value name separated by a '='" do
696
+ let(:name) { 'value' }
697
+ let(:string) { "#{flag}=#{name}" }
698
+
699
+ it "must capture the option flag, equals, and the option value name" do
700
+ expect(subject.parse(string)).to eq(
701
+ {
702
+ option: {
703
+ long_flag: flag,
704
+ value: {
705
+ equals: '=',
706
+ name: name
707
+ }
708
+ }
709
+ }
710
+ )
711
+ end
712
+
713
+ context "but the '=' and value are wrapped in '[' and ']'" do
714
+ let(:string) { "#{flag}[=#{name}]" }
715
+
716
+ it "must mark the option value name and equals as being optional" do
717
+ expect(subject.parse(string)).to eq(
718
+ {
719
+ option: {
720
+ long_flag: flag,
721
+ value: {
722
+ optional: {
723
+ equals: '=',
724
+ name: name
725
+ }
726
+ }
727
+ }
728
+ }
729
+ )
730
+ end
731
+ end
732
+ end
733
+
734
+ context "and an option value name wrapped in '[' ']'" do
735
+ let(:name) { 'value' }
736
+ let(:string) { "#{flag}[#{name}]" }
737
+
738
+ it "must mark the option value name and equals as being optional" do
739
+ expect(subject.parse(string)).to eq(
740
+ {
741
+ option: {
742
+ long_flag: flag,
743
+ value: {
744
+ optional: {name: name}
745
+ }
746
+ }
747
+ }
748
+ )
749
+ end
750
+ end
751
+ end
752
+ end
753
+
754
+ describe "#angle_brackets_group" do
755
+ subject { super().angle_brackets_group }
756
+
757
+ context "when given a string wrapped in '<' '>'" do
758
+ context "and it contains a list of more than one word" do
759
+ let(:words) { "foo bar baz" }
760
+ let(:string) { "<#{words}>" }
761
+
762
+ it "must capture the words as a single argument" do
763
+ expect(subject.parse(string)).to eq(
764
+ {
765
+ argument: {words: words}
766
+ }
767
+ )
768
+ end
769
+ end
770
+
771
+ context "and it contains more than one argument" do
772
+ let(:arg1) { "FOO" }
773
+ let(:arg2) { "BAR" }
774
+ let(:arg3) { "BAZ" }
775
+ let(:string) { "<#{arg1} #{arg2} #{arg3}>" }
776
+
777
+ it "must capture the arguments" do
778
+ expect(subject.parse(string)).to eq(
779
+ [
780
+ {argument: {name: arg1}},
781
+ {argument: {name: arg2}},
782
+ {argument: {name: arg3}},
783
+ ]
784
+ )
785
+ end
786
+ end
787
+ end
788
+
789
+ context "otherwise" do
790
+ let(:string) { "foo bar" }
791
+
792
+ it "must not parse it" do
793
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
794
+ end
795
+ end
796
+ end
797
+
798
+ describe "#curly_braces_group" do
799
+ subject { super().curly_braces_group }
800
+
801
+ context "when given a string wrapped in '{' '}'" do
802
+ context "and it contains a list of more than one word" do
803
+ let(:words) { "foo bar baz" }
804
+ let(:string) { "{#{words}}" }
805
+
806
+ it "must capture the words" do
807
+ expect(subject.parse(string)).to eq(
808
+ {
809
+ argument: {words: words}
810
+ }
811
+ )
812
+ end
813
+ end
814
+
815
+ context "and it contains more than one argument" do
816
+ let(:arg1) { "FOO" }
817
+ let(:arg2) { "BAR" }
818
+ let(:arg3) { "BAZ" }
819
+ let(:string) { "{#{arg1} #{arg2} #{arg3}}" }
820
+
821
+ it "must capture the arguments" do
822
+ expect(subject.parse(string)).to eq(
823
+ [
824
+ {argument: {name: arg1}},
825
+ {argument: {name: arg2}},
826
+ {argument: {name: arg3}},
827
+ ]
828
+ )
829
+ end
830
+ end
831
+ end
832
+
833
+ context "otherwise" do
834
+ let(:string) { "foo bar" }
835
+
836
+ it "must not parse it" do
837
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
838
+ end
839
+ end
840
+ end
841
+
842
+ describe "#optional_group" do
843
+ subject { super().optional_group }
844
+
845
+ context "when given a string wrapped in '[' ']'" do
846
+ context "and it contains more than one argument" do
847
+ let(:arg1) { "FOO" }
848
+ let(:arg2) { "BAR" }
849
+ let(:arg3) { "BAZ" }
850
+ let(:string) { "[#{arg1} #{arg2} #{arg3}]" }
851
+
852
+ it "must capture the arguments and mark them as optional" do
853
+ expect(subject.parse(string)).to eq(
854
+ {
855
+ optional: [
856
+ {argument: {name: arg1}},
857
+ {argument: {name: arg2}},
858
+ {argument: {name: arg3}}
859
+ ]
860
+ }
861
+ )
862
+ end
863
+
864
+ context "and ends with a '...'" do
865
+ let(:string) { "[#{arg1} #{arg2} #{arg3}]..." }
866
+
867
+ it "must capture the arguments and mark them as optional" do
868
+ expect(subject.parse(string)).to eq(
869
+ {
870
+ optional: [
871
+ {argument: {name: arg1}},
872
+ {argument: {name: arg2}},
873
+ {argument: {name: arg3}},
874
+ {repeats: '...'}
875
+ ]
876
+ }
877
+ )
878
+ end
879
+ end
880
+ end
881
+ end
882
+
883
+ context "otherwise" do
884
+ let(:string) { "foo bar" }
885
+
886
+ it "must not parse it" do
887
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
888
+ end
889
+ end
890
+ end
891
+
892
+ describe "#arg" do
893
+ subject { super().arg }
894
+
895
+ context "when given an --option" do
896
+ let(:flag) { '--opt' }
897
+ let(:string) { flag }
898
+
899
+ it "must capture the option" do
900
+ expect(subject.parse(string)).to eq(
901
+ {
902
+ option: {long_flag: flag}
903
+ }
904
+ )
905
+ end
906
+ end
907
+
908
+ context "when given an ARG name" do
909
+ let(:name) { 'ARG' }
910
+ let(:string) { name }
911
+
912
+ it "must capture the argument name" do
913
+ expect(subject.parse(string)).to eq(
914
+ {
915
+ argument: {name: name}
916
+ }
917
+ )
918
+ end
919
+ end
920
+
921
+ let(:arg1) { "FOO" }
922
+ let(:arg2) { "BAR" }
923
+ let(:arg3) { "BAZ" }
924
+
925
+ context "when given a <...> group of arguments" do
926
+ let(:string) { "<#{arg1} #{arg2} #{arg3}>" }
927
+
928
+ it "must capture the arguments" do
929
+ expect(subject.parse(string)).to eq(
930
+ [
931
+ {argument: {name: arg1}},
932
+ {argument: {name: arg2}},
933
+ {argument: {name: arg3}},
934
+ ]
935
+ )
936
+ end
937
+ end
938
+
939
+ context "when gvien a {...} group of arguments" do
940
+ let(:string) { "{#{arg1} #{arg2} #{arg3}}" }
941
+
942
+ it "must capture the arguments" do
943
+ expect(subject.parse(string)).to eq(
944
+ [
945
+ {argument: {name: arg1}},
946
+ {argument: {name: arg2}},
947
+ {argument: {name: arg3}},
948
+ ]
949
+ )
950
+ end
951
+ end
952
+
953
+ context "when given a [...] group of arguments" do
954
+ let(:string) { "[#{arg1} #{arg2} #{arg3}]" }
955
+
956
+ it "must parse the contents" do
957
+ expect(subject.parse(string)).to eq(
958
+ {
959
+ optional: [
960
+ {argument: {name: arg1}},
961
+ {argument: {name: arg2}},
962
+ {argument: {name: arg3}}
963
+ ]
964
+ }
965
+ )
966
+ end
967
+ end
968
+
969
+ context "when given a single '...'" do
970
+ let(:string) { "..." }
971
+
972
+ it "must parse the '...'" do
973
+ expect(subject.parse(string)).to eq(string)
974
+ end
975
+ end
976
+ end
977
+
978
+ describe "#arg_separator" do
979
+ subject { super().arg_separator }
980
+
981
+ context "when given a ' '" do
982
+ let(:string) { ' ' }
983
+
984
+ it "must parse it" do
985
+ expect(subject.parse(string)).to eq(string)
986
+ end
987
+ end
988
+
989
+ context "when given a ' | '" do
990
+ let(:string) { ' | ' }
991
+
992
+ it "must parse it" do
993
+ expect(subject.parse(string)).to eq(string)
994
+ end
995
+ end
996
+
997
+ context "when given a '|'" do
998
+ let(:string) { '|' }
999
+
1000
+ it "must parse it" do
1001
+ expect(subject.parse(string)).to eq(string)
1002
+ end
1003
+ end
1004
+ end
1005
+
1006
+ describe "#args" do
1007
+ subject { super().args }
1008
+
1009
+ context "when given one argument" do
1010
+ let(:arg) { "ARG" }
1011
+ let(:string) { arg }
1012
+
1013
+ it "must parse the argument" do
1014
+ expect(subject.parse(string)).to eq({argument: {name: arg}})
1015
+ end
1016
+ end
1017
+
1018
+ context "when given multiple arguments separated by a ' '" do
1019
+ let(:arg1) { "ARG1" }
1020
+ let(:arg2) { "ARG2" }
1021
+ let(:arg3) { "ARG3" }
1022
+ let(:string) { "#{arg1} #{arg2} #{arg3}" }
1023
+
1024
+ it "must parse the argument" do
1025
+ expect(subject.parse(string)).to eq(
1026
+ [
1027
+ {argument: {name: arg1}},
1028
+ {argument: {name: arg2}},
1029
+ {argument: {name: arg3}}
1030
+ ]
1031
+ )
1032
+ end
1033
+ end
1034
+
1035
+ context "when given multiple arguments separated by a ' | '" do
1036
+ let(:arg1) { "ARG1" }
1037
+ let(:arg2) { "ARG2" }
1038
+ let(:arg3) { "ARG3" }
1039
+ let(:string) { "#{arg1} | #{arg2} | #{arg3}" }
1040
+
1041
+ it "must parse the argument" do
1042
+ expect(subject.parse(string)).to eq(
1043
+ [
1044
+ {argument: {name: arg1}},
1045
+ {argument: {name: arg2}},
1046
+ {argument: {name: arg3}}
1047
+ ]
1048
+ )
1049
+ end
1050
+ end
1051
+ end
1052
+
1053
+ describe "#command_name" do
1054
+ subject { super().command_name }
1055
+
1056
+ context "when the command name starts with a '_'" do
1057
+ let(:string) { '_foo' }
1058
+
1059
+ it "must not parse it" do
1060
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
1061
+ end
1062
+ end
1063
+
1064
+ context "when the command name starts with a '-'" do
1065
+ let(:string) { '-foo' }
1066
+
1067
+ it "must not parse it" do
1068
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
1069
+ end
1070
+ end
1071
+
1072
+ context "when the command name starts with a digit" do
1073
+ let(:string) { '0foo' }
1074
+
1075
+ it "must not parse it" do
1076
+ expect { subject.parse(string) }.to raise_error(Parslet::ParseFailed)
1077
+ end
1078
+ end
1079
+
1080
+ context "when the command name starts with a lowercase letter" do
1081
+ let(:string) { 'foo' }
1082
+
1083
+ it "must capture the command name" do
1084
+ expect(subject.parse(string)).to eq(string)
1085
+ end
1086
+ end
1087
+
1088
+ context "when the command name starts with a uppercase letter" do
1089
+ let(:string) { 'Foo' }
1090
+
1091
+ it "must capture the command name" do
1092
+ expect(subject.parse(string)).to eq(string)
1093
+ end
1094
+ end
1095
+
1096
+ context "when the command name contains a '_'" do
1097
+ let(:string) { 'foo_bar' }
1098
+
1099
+ it "must capture the command name" do
1100
+ expect(subject.parse(string)).to eq(string)
1101
+ end
1102
+ end
1103
+
1104
+ context "when the command name contains a '-'" do
1105
+ let(:string) { 'foo-bar' }
1106
+
1107
+ it "must capture the command name" do
1108
+ expect(subject.parse(string)).to eq(string)
1109
+ end
1110
+ end
1111
+ end
1112
+
1113
+ describe "#usage" do
1114
+ subject { super().usage }
1115
+
1116
+ let(:command_name) { "foo" }
1117
+
1118
+ context "when given only a command name" do
1119
+ let(:string) { command_name }
1120
+
1121
+ it "must capture the command name" do
1122
+ expect(subject.parse(string)).to eq({command_name: command_name})
1123
+ end
1124
+ end
1125
+
1126
+ context "when given a command name and a sub-command name" do
1127
+ let(:subcommand_name) { "bar" }
1128
+
1129
+ let(:string) { "#{command_name} #{subcommand_name}" }
1130
+
1131
+ it "must capture both the command name and sub-command name" do
1132
+ expect(subject.parse(string)).to eq(
1133
+ {
1134
+ command_name: command_name,
1135
+ subcommand_name: subcommand_name
1136
+ }
1137
+ )
1138
+ end
1139
+ end
1140
+
1141
+ context "when given a command name and a single argument" do
1142
+ let(:arg1) { "ARG1" }
1143
+ let(:string) { "#{command_name} #{arg1}" }
1144
+
1145
+ it "must capture the command name and argument" do
1146
+ expect(subject.parse(string)).to eq(
1147
+ {
1148
+ command_name: command_name,
1149
+ arguments: {argument: {name: arg1}}
1150
+ }
1151
+ )
1152
+ end
1153
+ end
1154
+
1155
+ context "when given a command name and arguments" do
1156
+ let(:arg1) { "ARG1" }
1157
+ let(:arg2) { "ARG2" }
1158
+ let(:arg3) { "ARG3" }
1159
+ let(:string) { "#{command_name} #{arg1} #{arg2} #{arg3}" }
1160
+
1161
+ it "must capture the command name and arguments" do
1162
+ expect(subject.parse(string)).to eq(
1163
+ {
1164
+ command_name: command_name,
1165
+ arguments: [
1166
+ {argument: {name: arg1}},
1167
+ {argument: {name: arg2}},
1168
+ {argument: {name: arg3}}
1169
+ ]
1170
+ }
1171
+ )
1172
+ end
1173
+ end
1174
+ end
1175
+ end