cliqr 1.1.0 → 1.2.0

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -1
  3. data/README.md +97 -71
  4. data/examples/README.md +12 -0
  5. data/examples/hbase +58 -0
  6. data/examples/my-command +63 -0
  7. data/examples/numbers +55 -0
  8. data/examples/vagrant +90 -0
  9. data/lib/cliqr.rb +17 -2
  10. data/lib/cliqr/argument_validation/argument_type_validator.rb +2 -2
  11. data/lib/cliqr/argument_validation/validator.rb +1 -1
  12. data/lib/cliqr/cli/argument_operator.rb +44 -0
  13. data/lib/cliqr/cli/argument_operator_context.rb +20 -0
  14. data/lib/cliqr/cli/command.rb +1 -1
  15. data/lib/cliqr/cli/command_context.rb +93 -12
  16. data/lib/cliqr/cli/command_runner_factory.rb +2 -2
  17. data/lib/cliqr/cli/config.rb +301 -33
  18. data/lib/cliqr/cli/executor.rb +14 -9
  19. data/lib/cliqr/cli/interface.rb +22 -7
  20. data/lib/cliqr/cli/router.rb +6 -2
  21. data/lib/cliqr/cli/shell_command.rb +69 -0
  22. data/lib/cliqr/cli/usage_builder.rb +185 -0
  23. data/lib/cliqr/config_validation/validator_factory.rb +59 -5
  24. data/lib/cliqr/error.rb +10 -4
  25. data/lib/cliqr/parser/action_token.rb +23 -0
  26. data/lib/cliqr/parser/argument_parser.rb +1 -1
  27. data/lib/cliqr/parser/argument_token.rb +1 -4
  28. data/lib/cliqr/parser/argument_tree_walker.rb +40 -8
  29. data/lib/cliqr/parser/option_token.rb +2 -1
  30. data/lib/cliqr/parser/parsed_input.rb +21 -2
  31. data/lib/cliqr/parser/parsed_input_builder.rb +11 -7
  32. data/lib/cliqr/parser/token.rb +3 -9
  33. data/lib/cliqr/parser/token_factory.rb +1 -1
  34. data/lib/cliqr/util.rb +135 -0
  35. data/lib/cliqr/version.rb +1 -1
  36. data/spec/argument_parser_spec_helper.rb +15 -0
  37. data/spec/config/action_config_validator_spec.rb +146 -0
  38. data/spec/config/config_finalize_spec.rb +1 -1
  39. data/spec/config/config_validator_spec.rb +29 -19
  40. data/spec/config/option_config_validator_spec.rb +13 -13
  41. data/spec/dsl/interface_spec.rb +1 -168
  42. data/spec/dsl/usage_spec.rb +705 -0
  43. data/spec/executor/action_executor_spec.rb +205 -0
  44. data/spec/executor/executor_spec.rb +405 -17
  45. data/spec/executor/help_executor_spec.rb +424 -0
  46. data/spec/executor/shell_executor_spec.rb +233 -0
  47. data/spec/fixtures/action_reader_command.rb +12 -0
  48. data/spec/fixtures/csv_argument_operator.rb +8 -0
  49. data/spec/fixtures/test_option_type_checker_command.rb +8 -0
  50. data/spec/parser/action_argument_parser_spec.rb +113 -0
  51. data/spec/parser/argument_parser_spec.rb +37 -44
  52. data/spec/spec_helper.rb +1 -0
  53. data/spec/validation/action_argument_validator_spec.rb +50 -0
  54. data/spec/validation/{argument_validation_spec.rb → command_argument_validation_spec.rb} +36 -18
  55. data/spec/validation/error_spec.rb +1 -1
  56. data/tasks/rdoc.rake +16 -0
  57. data/tasks/rubucop.rake +14 -0
  58. data/tasks/yard.rake +21 -0
  59. data/templates/usage.erb +39 -0
  60. metadata +48 -11
@@ -0,0 +1,705 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'fixtures/test_command'
6
+ require 'fixtures/action_reader_command'
7
+ require 'fixtures/csv_argument_operator'
8
+
9
+ describe Cliqr::CLI::UsageBuilder do
10
+ ################ BASE COMMAND ################
11
+
12
+ it 'builds a base command with name' do
13
+ cli = Cliqr.interface do
14
+ name 'my-command'
15
+ description 'a command used to test cliqr'
16
+ handler TestCommand
17
+ arguments :disable
18
+ help :disable
19
+ end
20
+
21
+ expect(cli.usage).to eq <<-EOS
22
+ my-command -- a command used to test cliqr
23
+
24
+ USAGE:
25
+ my-command
26
+ EOS
27
+ end
28
+
29
+ it 'only makes name and handler to be required' do
30
+ cli = Cliqr.interface do
31
+ name 'my-command'
32
+ handler TestCommand
33
+ arguments :disable
34
+ help :disable
35
+ end
36
+
37
+ expect(cli.usage).to eq <<-EOS
38
+ my-command
39
+
40
+ USAGE:
41
+ my-command
42
+ EOS
43
+ end
44
+
45
+ ################ OPTION ################
46
+
47
+ it 'allows options for a command' do
48
+ cli = Cliqr.interface do
49
+ name 'my-command'
50
+ description 'a command used to test cliqr'
51
+ handler TestCommand
52
+ arguments :disable
53
+ help :disable
54
+
55
+ option 'option-1' do
56
+ short 'p'
57
+ description 'a nice option to have'
58
+ end
59
+ end
60
+
61
+ expect(cli.usage).to eq <<-EOS
62
+ my-command -- a command used to test cliqr
63
+
64
+ USAGE:
65
+ my-command [options]
66
+
67
+ Available options:
68
+
69
+ --option-1, -p : a nice option to have
70
+ EOS
71
+ end
72
+
73
+ it 'allows command options to optionally have description, type and short name' do
74
+ cli = Cliqr.interface do
75
+ name 'my-command'
76
+ description 'a command used to test cliqr'
77
+ handler TestCommand
78
+ arguments :disable
79
+ help :disable
80
+
81
+ option 'option-1'
82
+ end
83
+
84
+ expect(cli.usage).to eq <<-EOS
85
+ my-command -- a command used to test cliqr
86
+
87
+ USAGE:
88
+ my-command [options]
89
+
90
+ Available options:
91
+
92
+ --option-1
93
+ EOS
94
+ end
95
+
96
+ it 'has options if added during build phase' do
97
+ cli = Cliqr.interface do
98
+ name 'my-command'
99
+ description 'a command used to test cliqr'
100
+ handler TestCommand
101
+
102
+ option 'option-1' do
103
+ short 'p'
104
+ description 'a nice option to have'
105
+ end
106
+ end
107
+ expect(cli.config.options?).to be_truthy
108
+ end
109
+
110
+ ################ OPTION TYPES ################
111
+
112
+ it 'allows command options to have a numeric value type' do
113
+ cli = Cliqr.interface do
114
+ name 'my-command'
115
+ description 'a command used to test cliqr'
116
+ handler TestCommand
117
+ arguments :disable
118
+ help :disable
119
+
120
+ option 'option-1' do
121
+ description 'a numeric option'
122
+ short 'p'
123
+ type :numeric
124
+ end
125
+ end
126
+
127
+ expect(cli.usage).to eq <<-EOS
128
+ my-command -- a command used to test cliqr
129
+
130
+ USAGE:
131
+ my-command [options]
132
+
133
+ Available options:
134
+
135
+ --option-1, -p : <numeric> a numeric option (default => 0)
136
+ EOS
137
+ end
138
+
139
+ it 'allows command options to have a boolean value type' do
140
+ cli = Cliqr.interface do
141
+ name 'my-command'
142
+ description 'a command used to test cliqr'
143
+ handler TestCommand
144
+ arguments :disable
145
+ help :disable
146
+
147
+ option 'option-1' do
148
+ description 'a boolean option'
149
+ short 'p'
150
+ type :boolean
151
+ end
152
+ end
153
+
154
+ expect(cli.usage).to eq <<-EOS
155
+ my-command -- a command used to test cliqr
156
+
157
+ USAGE:
158
+ my-command [options]
159
+
160
+ Available options:
161
+
162
+ --[no-]option-1, -p : <boolean> a boolean option (default => false)
163
+ EOS
164
+ end
165
+
166
+ it 'allows command options to have a boolean value type and no description' do
167
+ cli = Cliqr.interface do
168
+ name 'my-command'
169
+ description 'a command used to test cliqr'
170
+ handler TestCommand
171
+ arguments :disable
172
+ help :disable
173
+
174
+ option 'option-1' do
175
+ short 'p'
176
+ type :boolean
177
+ end
178
+ end
179
+
180
+ expect(cli.usage).to eq <<-EOS
181
+ my-command -- a command used to test cliqr
182
+
183
+ USAGE:
184
+ my-command [options]
185
+
186
+ Available options:
187
+
188
+ --[no-]option-1, -p : <boolean> (default => false)
189
+ EOS
190
+ end
191
+
192
+ ################ ARGUMENTS ################
193
+
194
+ it 'allows interface to enable arbitrary argument list parsing without options' do
195
+ cli = Cliqr.interface do
196
+ name 'my-command'
197
+ handler TestCommand
198
+ arguments :enable
199
+ help :disable
200
+ end
201
+
202
+ expect(cli.usage).to eq <<-EOS
203
+ my-command
204
+
205
+ USAGE:
206
+ my-command [arguments]
207
+ EOS
208
+ end
209
+
210
+ it 'allows interface to enable arbitrary argument list parsing' do
211
+ cli = Cliqr.interface do
212
+ name 'my-command'
213
+ handler TestCommand
214
+ arguments :enable
215
+ help :disable
216
+
217
+ option 'option-1'
218
+ end
219
+
220
+ expect(cli.usage).to eq <<-EOS
221
+ my-command
222
+
223
+ USAGE:
224
+ my-command [options] [arguments]
225
+
226
+ Available options:
227
+
228
+ --option-1
229
+ EOS
230
+ end
231
+
232
+ ################ ACTIONS ################
233
+
234
+ it 'allows command to have an action' do
235
+ cli = Cliqr.interface do
236
+ name 'my-command'
237
+ handler TestCommand
238
+ help :disable
239
+ shell :disable
240
+
241
+ action 'my-action' do
242
+ handler TestCommand
243
+ arguments :disable
244
+ end
245
+ end
246
+
247
+ expect(cli.usage).to eq <<-EOS
248
+ my-command
249
+
250
+ USAGE:
251
+ my-command [actions] [arguments]
252
+
253
+ Available actions:
254
+
255
+ my-action
256
+ EOS
257
+ end
258
+
259
+ it 'allows command to have an action with description' do
260
+ cli = Cliqr.interface do
261
+ name 'my-command'
262
+ handler TestCommand
263
+ help :disable
264
+ shell :disable
265
+
266
+ action 'my-action' do
267
+ handler TestCommand
268
+ description 'this is a test action'
269
+ arguments :disable
270
+ end
271
+ end
272
+
273
+ expect(cli.usage).to eq <<-EOS
274
+ my-command
275
+
276
+ USAGE:
277
+ my-command [actions] [arguments]
278
+
279
+ Available actions:
280
+
281
+ my-action -- this is a test action
282
+ EOS
283
+ end
284
+
285
+ it 'allows command to have an action and an option' do
286
+ cli = Cliqr.interface do
287
+ name 'my-command'
288
+ handler TestCommand
289
+ help :disable
290
+ shell :disable
291
+
292
+ action 'my-action' do
293
+ handler TestCommand
294
+ description 'this is a test action'
295
+ arguments :disable
296
+ end
297
+
298
+ option 'option-1'
299
+ end
300
+
301
+ expect(cli.usage).to eq <<-EOS
302
+ my-command
303
+
304
+ USAGE:
305
+ my-command [actions] [options] [arguments]
306
+
307
+ Available options:
308
+
309
+ --option-1
310
+
311
+ Available actions:
312
+
313
+ my-action -- this is a test action
314
+ EOS
315
+ end
316
+
317
+ it 'allows command to have an action with options' do
318
+ cli = Cliqr.interface do
319
+ name 'my-command'
320
+ handler TestCommand
321
+ help :disable
322
+ shell :disable
323
+
324
+ action 'my-action' do
325
+ handler TestCommand
326
+ description 'this is a test action'
327
+
328
+ option 'action-option'
329
+ end
330
+
331
+ option 'option-1'
332
+ end
333
+
334
+ expect(cli.usage).to eq <<-EOS
335
+ my-command
336
+
337
+ USAGE:
338
+ my-command [actions] [options] [arguments]
339
+
340
+ Available options:
341
+
342
+ --option-1
343
+
344
+ Available actions:
345
+
346
+ my-action -- this is a test action
347
+ EOS
348
+ end
349
+
350
+ it 'allows command to have multiple actions and multiple options' do
351
+ cli = Cliqr.interface do
352
+ name 'my-command'
353
+ handler TestCommand
354
+ help :disable
355
+ shell :disable
356
+
357
+ option 'option-1'
358
+
359
+ action 'my-action' do
360
+ handler TestCommand
361
+ description 'this is a test action'
362
+
363
+ option 'action-option'
364
+ end
365
+
366
+ option 'option-2'
367
+
368
+ action 'another-action' do
369
+ handler TestCommand
370
+ description 'this is another test action'
371
+ arguments :disable
372
+ end
373
+
374
+ option 'option-3'
375
+ end
376
+
377
+ expect(cli.usage).to eq <<-EOS
378
+ my-command
379
+
380
+ USAGE:
381
+ my-command [actions] [options] [arguments]
382
+
383
+ Available options:
384
+
385
+ --option-1
386
+ --option-2
387
+ --option-3
388
+
389
+ Available actions:
390
+
391
+ my-action -- this is a test action
392
+
393
+ another-action -- this is another test action
394
+ EOS
395
+ end
396
+
397
+ it 'allows nested actions with a mix of same options and same names' do
398
+ def define_interface
399
+ Cliqr.interface do
400
+ name 'my-command'
401
+ handler TestCommand
402
+ help :disable
403
+ shell :disable
404
+
405
+ option 'test-option-1'
406
+ option 'test-option-2'
407
+
408
+ action 'my-action-1' do
409
+ handler ActionReaderCommand
410
+
411
+ action 'my-action-1' do
412
+ handler ActionReaderCommand
413
+
414
+ option 'test-option-1'
415
+ option 'test-option-2'
416
+
417
+ action 'my-action-1' do
418
+ handler ActionReaderCommand
419
+
420
+ option 'test-option-1'
421
+ option 'test-option-2'
422
+ end
423
+ end
424
+ end
425
+
426
+ action 'another-action' do
427
+ handler ActionReaderCommand
428
+ arguments :disable
429
+ end
430
+ end
431
+ end
432
+ expect(define_interface.usage).to eq <<-EOS
433
+ my-command
434
+
435
+ USAGE:
436
+ my-command [actions] [options] [arguments]
437
+
438
+ Available options:
439
+
440
+ --test-option-1
441
+ --test-option-2
442
+
443
+ Available actions:
444
+
445
+ my-action-1
446
+
447
+ another-action
448
+ EOS
449
+ end
450
+
451
+ ################ DEFAULT OPTION VALUES ################
452
+
453
+ it 'allows options to have default value' do
454
+ cli = Cliqr.interface do
455
+ name 'my-command'
456
+ handler TestCommand
457
+ help :disable
458
+
459
+ option 'test-option' do
460
+ default :a_symbol
461
+ end
462
+
463
+ option :another do
464
+ short 'a'
465
+ description 'another option'
466
+ type :numeric
467
+ default %w(test array default)
468
+
469
+ operator CSVArgumentOperator
470
+ end
471
+
472
+ option 'nil-option' do
473
+ default nil
474
+ end
475
+
476
+ option 'string-option' do
477
+ default 'string'
478
+ end
479
+
480
+ option 'hash-option' do
481
+ default(:key => 'val')
482
+ end
483
+ end
484
+
485
+ expect(cli.usage).to eq <<-EOS
486
+ my-command
487
+
488
+ USAGE:
489
+ my-command [options] [arguments]
490
+
491
+ Available options:
492
+
493
+ --test-option : (default => :a_symbol)
494
+ --another, -a : <numeric> another option (default => [\"test\", \"array\", \"default\"])
495
+ --nil-option
496
+ --string-option : (default => "string")
497
+ --hash-option : (default => {:key=>"val"})
498
+ EOS
499
+ end
500
+
501
+ it 'boolean option is false by default' do
502
+ cli = Cliqr.interface do
503
+ name 'my-command'
504
+ handler TestCommand
505
+ help :disable
506
+
507
+ option :another do
508
+ short 'a'
509
+ description 'another option'
510
+ type :boolean
511
+
512
+ operator CSVArgumentOperator
513
+ end
514
+ end
515
+
516
+ expect(cli.usage).to eq <<-EOS
517
+ my-command
518
+
519
+ USAGE:
520
+ my-command [options] [arguments]
521
+
522
+ Available options:
523
+
524
+ --[no-]another, -a : <boolean> another option (default => false)
525
+ EOS
526
+ end
527
+
528
+ it 'numeric option is 0 by default' do
529
+ cli = Cliqr.interface do
530
+ name 'my-command'
531
+ handler TestCommand
532
+ help :disable
533
+
534
+ option :another do
535
+ short 'a'
536
+ description 'another option'
537
+ type :numeric
538
+
539
+ operator CSVArgumentOperator
540
+ end
541
+ end
542
+
543
+ expect(cli.usage).to eq <<-EOS
544
+ my-command
545
+
546
+ USAGE:
547
+ my-command [options] [arguments]
548
+
549
+ Available options:
550
+
551
+ --another, -a : <numeric> another option (default => 0)
552
+ EOS
553
+ end
554
+
555
+ it 'boolean option can be made default true' do
556
+ cli = Cliqr.interface do
557
+ name 'my-command'
558
+ handler TestCommand
559
+ help :disable
560
+
561
+ option :another do
562
+ short 'a'
563
+ description 'another option'
564
+ type :boolean
565
+ default true
566
+
567
+ operator CSVArgumentOperator
568
+ end
569
+ end
570
+
571
+ expect(cli.usage).to eq <<-EOS
572
+ my-command
573
+
574
+ USAGE:
575
+ my-command [options] [arguments]
576
+
577
+ Available options:
578
+
579
+ --[no-]another, -a : <boolean> another option (default => true)
580
+ EOS
581
+ end
582
+
583
+ ################ SHELL ACTION ################
584
+
585
+ it 'adds shell action to the base command only when there are sub actions' do
586
+ cli = Cliqr.interface do
587
+ name 'my-command'
588
+ handler TestCommand
589
+ help :disable
590
+
591
+ action :bla
592
+ end
593
+
594
+ expect(cli.usage).to eq <<-EOS
595
+ my-command
596
+
597
+ USAGE:
598
+ my-command [actions] [arguments]
599
+
600
+ Available actions:
601
+
602
+ bla
603
+
604
+ shell -- Execute a shell in the context of "my-command" command.
605
+ EOS
606
+ end
607
+
608
+ it 'does not add shell action to the base command if it does not have actions' do
609
+ cli = Cliqr.interface do
610
+ name 'my-command'
611
+ handler TestCommand
612
+ help :disable
613
+ end
614
+
615
+ expect(cli.usage).to eq <<-EOS
616
+ my-command
617
+
618
+ USAGE:
619
+ my-command [arguments]
620
+ EOS
621
+ end
622
+
623
+ it 'can add shell action to a sub-action which does not have actions' do
624
+ cli = Cliqr.interface do
625
+ name 'my-command'
626
+
627
+ action :bla do
628
+ shell :enable
629
+ end
630
+ end
631
+ result = cli.execute_internal %w(my-command bla), output: :buffer
632
+ expect(result[:stdout]).to eq <<-EOS
633
+ my-command bla
634
+
635
+ USAGE:
636
+ my-command bla [actions] [options] [arguments]
637
+
638
+ Available options:
639
+
640
+ --help, -h : Get helpful information for action "my-command bla" along with its usage information.
641
+
642
+ Available actions:
643
+ [ Type "my-command bla help [action-name]" to get more information about that action ]
644
+
645
+ shell -- Execute a shell in the context of "my-command bla" command.
646
+
647
+ help -- The help action for command "my-command bla" which provides details and usage information on how to use the command.
648
+ EOS
649
+ end
650
+
651
+ it 'can add version to base command' do
652
+ cli = Cliqr.interface do
653
+ name 'my-command'
654
+ version '1234'
655
+ end
656
+ result = cli.execute_internal %w(help), output: :buffer
657
+ expect(result[:stdout]).to eq <<-EOS
658
+ my-command
659
+
660
+ USAGE:
661
+ my-command [actions] [options] [arguments]
662
+
663
+ Available options:
664
+
665
+ --version, -v : Get version information for command "my-command".
666
+ --help, -h : Get helpful information for action "my-command" along with its usage information.
667
+
668
+ Available actions:
669
+ [ Type "my-command help [action-name]" to get more information about that action ]
670
+
671
+ version -- Get version information for command "my-command".
672
+
673
+ help -- The help action for command "my-command" which provides details and usage information on how to use the command.
674
+ EOS
675
+ end
676
+
677
+ it 'can add version to any action' do
678
+ cli = Cliqr.interface do
679
+ name 'my-command'
680
+
681
+ action :bla do
682
+ version '1234'
683
+ end
684
+ end
685
+ result = cli.execute_internal %w(bla help), output: :buffer
686
+ expect(result[:stdout]).to eq <<-EOS
687
+ my-command bla
688
+
689
+ USAGE:
690
+ my-command bla [actions] [options] [arguments]
691
+
692
+ Available options:
693
+
694
+ --version, -v : Get version information for command "my-command bla".
695
+ --help, -h : Get helpful information for action "my-command bla" along with its usage information.
696
+
697
+ Available actions:
698
+ [ Type "my-command bla help [action-name]" to get more information about that action ]
699
+
700
+ version -- Get version information for command "my-command bla".
701
+
702
+ help -- The help action for command "my-command bla" which provides details and usage information on how to use the command.
703
+ EOS
704
+ end
705
+ end