cliqr 1.2.0 → 2.0.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +95 -0
  3. data/README.md +9 -71
  4. data/examples/numbers +1 -2
  5. data/examples/vagrant +0 -3
  6. data/lib/cliqr.rb +52 -11
  7. data/lib/cliqr/argument_validation/argument_type_validator.rb +2 -2
  8. data/lib/cliqr/argument_validation/validator.rb +3 -3
  9. data/lib/cliqr/{cli → command}/argument_operator.rb +2 -2
  10. data/lib/cliqr/{cli → command}/argument_operator_context.rb +1 -1
  11. data/lib/cliqr/{cli/command.rb → command/base_command.rb} +2 -2
  12. data/lib/cliqr/command/color.rb +174 -0
  13. data/lib/cliqr/{cli → command}/command_context.rb +68 -20
  14. data/lib/cliqr/command/shell_banner_builder.rb +17 -0
  15. data/lib/cliqr/command/shell_command.rb +125 -0
  16. data/lib/cliqr/command/shell_prompt_builder.rb +26 -0
  17. data/lib/cliqr/config/action.rb +226 -0
  18. data/lib/cliqr/config/base.rb +84 -0
  19. data/lib/cliqr/config/command.rb +137 -0
  20. data/lib/cliqr/config/dsl.rb +81 -0
  21. data/lib/cliqr/config/event.rb +43 -0
  22. data/lib/cliqr/config/event_based.rb +78 -0
  23. data/lib/cliqr/config/named.rb +55 -0
  24. data/lib/cliqr/config/option.rb +95 -0
  25. data/lib/cliqr/config/option_based.rb +130 -0
  26. data/lib/cliqr/config/shell.rb +87 -0
  27. data/lib/cliqr/config/validation/validation_set.rb +66 -0
  28. data/lib/cliqr/config/validation/validator_factory.rb +403 -0
  29. data/lib/cliqr/config/validation/verifiable.rb +91 -0
  30. data/lib/cliqr/error.rb +20 -4
  31. data/lib/cliqr/events/event.rb +56 -0
  32. data/lib/cliqr/events/event_context.rb +31 -0
  33. data/lib/cliqr/events/handler.rb +32 -0
  34. data/lib/cliqr/events/invoker.rb +70 -0
  35. data/lib/cliqr/{cli → executor}/command_runner_factory.rb +3 -3
  36. data/lib/cliqr/{cli → executor}/router.rb +4 -4
  37. data/lib/cliqr/{cli/executor.rb → executor/runner.rb} +25 -10
  38. data/lib/cliqr/interface.rb +98 -0
  39. data/lib/cliqr/parser/token_factory.rb +1 -1
  40. data/lib/cliqr/usage/command_usage_context.rb +94 -0
  41. data/lib/cliqr/usage/option_usage_context.rb +86 -0
  42. data/lib/cliqr/usage/templates/partial/action_list.erb +10 -0
  43. data/lib/cliqr/usage/templates/partial/command_name.erb +3 -0
  44. data/lib/cliqr/usage/templates/partial/option_list.erb +18 -0
  45. data/lib/cliqr/usage/templates/partial/usage_info.erb +5 -0
  46. data/lib/cliqr/usage/templates/usage/cli.erb +4 -0
  47. data/lib/cliqr/usage/templates/usage/shell.erb +2 -0
  48. data/lib/cliqr/usage/usage_builder.rb +59 -0
  49. data/lib/cliqr/util.rb +81 -34
  50. data/lib/cliqr/version.rb +1 -1
  51. data/spec/config/action_config_validator_spec.rb +127 -5
  52. data/spec/config/config_finalize_spec.rb +3 -3
  53. data/spec/config/config_validator_spec.rb +120 -17
  54. data/spec/config/option_config_validator_spec.rb +1 -1
  55. data/spec/dsl/interface_spec.rb +2 -2
  56. data/spec/dsl/usage_spec.rb +461 -465
  57. data/spec/executor/action_executor_spec.rb +1 -1
  58. data/spec/executor/color_executor_spec.rb +125 -0
  59. data/spec/executor/command_runner_spec.rb +6 -8
  60. data/spec/executor/event_executor_spec.rb +365 -0
  61. data/spec/executor/executor_spec.rb +49 -11
  62. data/spec/executor/help_executor_spec.rb +107 -103
  63. data/spec/fixtures/action_reader_command.rb +1 -1
  64. data/spec/fixtures/test_arg_printer_event_handler.rb +9 -0
  65. data/spec/fixtures/test_color_shell_prompt.rb +13 -0
  66. data/spec/fixtures/test_empty_event_handler.rb +5 -0
  67. data/spec/fixtures/test_invoker_event_handler.rb +9 -0
  68. data/spec/fixtures/test_shell_banner.rb +8 -0
  69. data/spec/fixtures/test_shell_prompt.rb +13 -0
  70. data/spec/shell/shell_executor_spec.rb +700 -0
  71. data/spec/validation/validation_spec.rb +2 -2
  72. metadata +65 -27
  73. data/lib/cliqr/cli/config.rb +0 -554
  74. data/lib/cliqr/cli/interface.rb +0 -107
  75. data/lib/cliqr/cli/shell_command.rb +0 -69
  76. data/lib/cliqr/cli/usage_builder.rb +0 -185
  77. data/lib/cliqr/config_validation/validation_set.rb +0 -48
  78. data/lib/cliqr/config_validation/validator_factory.rb +0 -319
  79. data/lib/cliqr/config_validation/verifiable.rb +0 -89
  80. data/lib/cliqr/dsl.rb +0 -59
  81. data/spec/executor/shell_executor_spec.rb +0 -233
  82. data/templates/usage.erb +0 -39
@@ -4,7 +4,7 @@
4
4
  class ActionReaderCommand < Cliqr.command
5
5
  def execute(context)
6
6
  puts "command = #{context.command}\n\n"
7
- puts "executing action = #{context.action_name}" if context.action?
7
+ puts "executing action = #{context.action_name}" if context.action_type?
8
8
  context.options.each do |option|
9
9
  puts "[option] #{option.name} => #{option.value}"
10
10
  end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ # Event handler that prints arguments
4
+ class TestArgPrinterEventHandler < Cliqr.event_handler
5
+ def handle(event, ch, num)
6
+ puts event.name
7
+ puts "#{ch} => #{num}"
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ # A custom colored test command prompt
4
+ class TestColorShellPrompt < Cliqr.shell_prompt
5
+ def initialize
6
+ @count = 0
7
+ end
8
+
9
+ def build(_context)
10
+ @count += 1
11
+ red("test-prompt [#{@count}] > ")
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ # Empty event handler
4
+ class TestEmptyEventHandler < Cliqr.event_handler
5
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ # Event handler that invokes another event
4
+ class TestInvokerEventHandler < Cliqr.event_handler
5
+ def handle(event, ch, num)
6
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
7
+ invoke :foo, 'b', 2, :t => 1
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ # A custom test command banner
4
+ class TestShellBanner < Cliqr.shell_banner
5
+ def build(context)
6
+ "welcome to the command #{context.command}"
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ # A custom test command prompt
4
+ class TestShellPrompt < Cliqr.shell_prompt
5
+ def initialize
6
+ @count = 0
7
+ end
8
+
9
+ def build(_context)
10
+ @count += 1
11
+ "test-prompt [#{@count}] > "
12
+ end
13
+ end
@@ -0,0 +1,700 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'fixtures/test_command'
6
+ require 'fixtures/test_shell_prompt'
7
+ require 'fixtures/test_color_shell_prompt'
8
+ require 'fixtures/test_shell_banner'
9
+
10
+ describe Cliqr::Command::ShellCommand do
11
+ it 'can execute help in command shell' do
12
+ cli = Cliqr.interface do
13
+ name 'my-command'
14
+ description 'this is a test command'
15
+ color :disable
16
+
17
+ action :foo do
18
+ description 'the foo action'
19
+ end
20
+
21
+ action :bar do
22
+ description 'bar command'
23
+
24
+ action :baz
25
+ end
26
+ end
27
+
28
+ with_input(%w(help -h)) do
29
+ result = cli.execute_internal %w(my-command shell), output: :buffer
30
+ expect(result[:stdout]).to eq <<-EOS
31
+ Starting shell for command "my-command"
32
+ [my-command][1] $ help.
33
+ my-command -- this is a test command
34
+
35
+ Available actions:
36
+ [ Type "help [action-name]" to get more information about that action ]
37
+
38
+ foo -- the foo action
39
+ bar -- bar command
40
+ help -- The help action for command "my-command" which provides details and usage information on how to use the command.
41
+ [my-command][2] $ -h.
42
+ unknown action "-h"
43
+ [my-command][3] $ exit.
44
+ shell exited with code 0
45
+ EOS
46
+ end
47
+
48
+ with_input(['help bar']) do
49
+ result = cli.execute_internal %w(my-command shell), output: :buffer
50
+ expect(result[:stdout]).to eq <<-EOS
51
+ Starting shell for command "my-command"
52
+ [my-command][4] $ help bar.
53
+ my-command bar -- bar command
54
+
55
+ Available actions:
56
+ [ Type "help [action-name]" to get more information about that action ]
57
+
58
+ baz
59
+ help -- The help action for command "my-command bar" which provides details and usage information on how to use the command.
60
+ [my-command][5] $ exit.
61
+ shell exited with code 0
62
+ EOS
63
+ end
64
+ end
65
+
66
+ it 'can execute help in shell with a different name' do
67
+ cli = Cliqr.interface do
68
+ name 'my-command'
69
+ description 'this is a test command'
70
+ color :disable
71
+
72
+ shell do
73
+ name 'custom-shell'
74
+ description 'this is a custom shell'
75
+ end
76
+ end
77
+
78
+ with_input(%w(help)) do
79
+ result = cli.execute_internal %w(my-command custom-shell), output: :buffer
80
+ expect(result[:stdout]).to eq <<-EOS
81
+ Starting shell for command "my-command"
82
+ [my-command][1] $ help.
83
+ my-command -- this is a test command
84
+
85
+ Available actions:
86
+ [ Type "help [action-name]" to get more information about that action ]
87
+
88
+ help -- The help action for command "my-command" which provides details and usage information on how to use the command.
89
+ custom-shell -- this is a custom shell
90
+ [my-command][2] $ exit.
91
+ shell exited with code 0
92
+ EOS
93
+ end
94
+ end
95
+
96
+ it 'can execute a sub action from shell' do
97
+ cli = Cliqr.interface do
98
+ name 'my-command'
99
+ color :disable
100
+
101
+ handler do
102
+ puts 'base command executed'
103
+ end
104
+
105
+ action :foo do
106
+ handler do
107
+ puts 'foo executed'
108
+ end
109
+
110
+ action :bar do
111
+ handler do
112
+ puts 'bar executed'
113
+ puts "option: #{opt}" if opt?
114
+ end
115
+
116
+ option :opt
117
+ end
118
+ end
119
+ end
120
+
121
+ with_input(['', 'my-command', 'foo', 'foo bar', 'foo bar --opt yes', 'foo bar help']) do
122
+ result = cli.execute_internal %w(my-command shell), output: :buffer
123
+ expect(result[:stdout]).to eq <<-EOS
124
+ Starting shell for command "my-command"
125
+ [my-command][1] $ .
126
+ [my-command][2] $ my-command.
127
+ unknown action "my-command"
128
+ [my-command][3] $ foo.
129
+ foo executed
130
+ [my-command][4] $ foo bar.
131
+ bar executed
132
+ [my-command][5] $ foo bar --opt yes.
133
+ bar executed
134
+ option: yes
135
+ [my-command][6] $ foo bar help.
136
+ my-command foo bar
137
+
138
+ Available actions:
139
+ [ Type "help [action-name]" to get more information about that action ]
140
+
141
+ help -- The help action for command "my-command foo bar" which provides details and usage information on how to use the command.
142
+ [my-command][7] $ exit.
143
+ shell exited with code 0
144
+ EOS
145
+ end
146
+ end
147
+
148
+ it 'does not allow shell action if shell config is disabled' do
149
+ cli = Cliqr.interface do
150
+ name 'my-command'
151
+ shell :disable
152
+ arguments :disable
153
+ end
154
+ expect { cli.execute_internal %w(my-command shell) }.to(
155
+ raise_error(Cliqr::Error::IllegalArgumentError, 'invalid command argument "shell"'))
156
+ end
157
+
158
+ it 'can handle errors in shell' do
159
+ cli = Cliqr.interface do
160
+ name 'my-command'
161
+ arguments :disable
162
+ color :disable
163
+
164
+ action :foo do
165
+ handler do
166
+ fail StandardError, 'I failed!'
167
+ end
168
+
169
+ action :bar
170
+ end
171
+ end
172
+
173
+ with_input(['unknown', '--opt-1 val', 'foo']) do
174
+ result = cli.execute_internal %w(my-command shell), output: :buffer
175
+ expect(result[:stdout]).to eq <<-EOS
176
+ Starting shell for command "my-command"
177
+ [my-command][1] $ unknown.
178
+ unknown action "unknown"
179
+ [my-command][2] $ --opt-1 val.
180
+ unknown action "--opt-1"
181
+ [my-command][3] $ foo.
182
+ command 'my-command foo' failed
183
+
184
+ Cause: StandardError - I failed!
185
+ [my-command][4] $ exit.
186
+ shell exited with code 0
187
+ EOS
188
+ end
189
+ end
190
+
191
+ it 'can pass options to shell command' do
192
+ cli = Cliqr.interface do
193
+ name 'my-command'
194
+ color :disable
195
+
196
+ on :shell_start do
197
+ puts 'base: shell started'
198
+ puts foo?
199
+ puts foo
200
+ puts bar?
201
+ puts bar
202
+ puts baz?
203
+ puts baz
204
+ end
205
+
206
+ on :shell_stop do
207
+ puts 'base: shell stopped'
208
+ puts foo?
209
+ puts foo
210
+ puts bar?
211
+ puts bar
212
+ puts baz?
213
+ puts baz
214
+ end
215
+
216
+ shell :enable do
217
+ on :shell_start do
218
+ puts 'shell started'
219
+ puts foo?
220
+ puts foo
221
+ puts bar?
222
+ puts bar
223
+ puts baz?
224
+ puts baz
225
+ end
226
+
227
+ on :shell_stop do
228
+ puts 'shell stopped'
229
+ puts foo?
230
+ puts foo
231
+ puts bar?
232
+ puts bar
233
+ puts baz?
234
+ puts baz
235
+ end
236
+
237
+ option :foo do
238
+ short 'f'
239
+ end
240
+
241
+ option :bar do
242
+ type :boolean
243
+ end
244
+
245
+ option :baz do
246
+ type :numeric
247
+ default 10
248
+ end
249
+ end
250
+ end
251
+
252
+ with_input(['']) do
253
+ result = cli.execute_internal %w(my-command shell -f qwerty --no-bar), output: :buffer
254
+ expect(result[:stdout]).to eq <<-EOS
255
+ Starting shell for command "my-command"
256
+ shell started
257
+ true
258
+ qwerty
259
+ true
260
+ false
261
+ false
262
+ 10
263
+ base: shell started
264
+ true
265
+ qwerty
266
+ true
267
+ false
268
+ false
269
+ 10
270
+ [my-command][1] $ .
271
+ [my-command][2] $ exit.
272
+ shell stopped
273
+ true
274
+ qwerty
275
+ true
276
+ false
277
+ false
278
+ 10
279
+ base: shell stopped
280
+ true
281
+ qwerty
282
+ true
283
+ false
284
+ false
285
+ 10
286
+ shell exited with code 0
287
+ EOS
288
+ end
289
+ end
290
+
291
+ describe 'illegal shell operations' do
292
+ it 'does not allow shell action if there are no sub-actions' do
293
+ cli = Cliqr.interface do
294
+ name 'my-command'
295
+ help :disable
296
+ handler TestCommand
297
+ arguments :disable
298
+ end
299
+ expect { cli.execute_internal %w(my-command shell) }.to(
300
+ raise_error(Cliqr::Error::IllegalArgumentError, 'invalid command argument "shell"'))
301
+ end
302
+
303
+ it 'does not allow shell in shell for base command' do
304
+ cli = Cliqr.interface do
305
+ name 'my-command'
306
+ color :disable
307
+
308
+ action :foo do
309
+ action :bar
310
+ end
311
+ end
312
+
313
+ with_input(['shell']) do
314
+ result = cli.execute_internal %w(my-command shell), output: :buffer
315
+ expect(result[:stdout]).to eq <<-EOS
316
+ Starting shell for command "my-command"
317
+ [my-command][1] $ shell.
318
+ command 'my-command shell' failed
319
+
320
+ Cause: Cliqr::Error::IllegalCommandError - Cannot run another shell within an already running shell
321
+ [my-command][2] $ exit.
322
+ shell exited with code 0
323
+ EOS
324
+ end
325
+ end
326
+
327
+ it 'does not allow shell in shell for sub action' do
328
+ cli = Cliqr.interface do
329
+ name 'my-command'
330
+ color :disable
331
+
332
+ action :foo do
333
+ action :bar
334
+ end
335
+ end
336
+
337
+ expect { cli.execute_internal %w(my-command foo shell) }.to(
338
+ raise_error(Cliqr::Error::CommandRuntimeError,
339
+ "command 'my-command foo' failed\n\nCause: Cliqr::Error::IllegalArgumentError - no arguments allowed for default help action\n"))
340
+
341
+ with_input(['foo shell']) do
342
+ result = cli.execute_internal %w(my-command shell), output: :buffer
343
+ expect(result[:stdout]).to eq <<-EOS
344
+ Starting shell for command "my-command"
345
+ [my-command][1] $ foo shell.
346
+ command 'my-command foo' failed
347
+
348
+ Cause: Cliqr::Error::IllegalArgumentError - no arguments allowed for default help action
349
+ [my-command][2] $ exit.
350
+ shell exited with code 0
351
+ EOS
352
+ end
353
+ end
354
+ end
355
+
356
+ describe Cliqr::Command::ShellPromptBuilder do
357
+ it 'allows a custom prompt string for shell prompt' do
358
+ cli = Cliqr.interface do
359
+ name 'my-command'
360
+ color :disable
361
+ shell :enable do
362
+ prompt 'test-prompt $ '
363
+ end
364
+
365
+ action :foo do
366
+ handler do
367
+ puts 'foo executed'
368
+ end
369
+ end
370
+ end
371
+
372
+ with_input(['', '', 'foo']) do
373
+ result = cli.execute_internal %w(my-command shell), output: :buffer
374
+ expect(result[:stdout]).to eq <<-EOS
375
+ Starting shell for command "my-command"
376
+ test-prompt $ .
377
+ test-prompt $ .
378
+ test-prompt $ foo.
379
+ foo executed
380
+ test-prompt $ exit.
381
+ shell exited with code 0
382
+ EOS
383
+ end
384
+ end
385
+
386
+ it 'allows a custom prompt function for shell prompt' do
387
+ cli = Cliqr.interface do
388
+ name 'my-command'
389
+ color :disable
390
+ shell :enable do
391
+ count = 0
392
+ prompt do
393
+ count += 1
394
+ "my-command [#{count}]$ "
395
+ end
396
+ end
397
+
398
+ action :foo do
399
+ handler do
400
+ puts 'foo executed'
401
+ end
402
+ end
403
+ end
404
+
405
+ with_input(['', '', 'foo', '']) do
406
+ result = cli.execute_internal %w(my-command shell), output: :buffer
407
+ expect(result[:stdout]).to eq <<-EOS
408
+ Starting shell for command "my-command"
409
+ my-command [1]$ .
410
+ my-command [2]$ .
411
+ my-command [3]$ foo.
412
+ foo executed
413
+ my-command [4]$ .
414
+ my-command [5]$ exit.
415
+ shell exited with code 0
416
+ EOS
417
+ end
418
+ end
419
+
420
+ it 'allows a custom prompt class for shell prompt' do
421
+ cli = Cliqr.interface do
422
+ name 'my-command'
423
+ color :disable
424
+ shell :enable do
425
+ prompt TestShellPrompt
426
+ end
427
+
428
+ action :foo do
429
+ handler do
430
+ puts 'foo executed'
431
+ end
432
+ end
433
+ end
434
+
435
+ with_input(['', '', 'foo', '']) do
436
+ result = cli.execute_internal %w(my-command shell), output: :buffer
437
+ expect(result[:stdout]).to eq <<-EOS
438
+ Starting shell for command "my-command"
439
+ test-prompt [1] > .
440
+ test-prompt [2] > .
441
+ test-prompt [3] > foo.
442
+ foo executed
443
+ test-prompt [4] > .
444
+ test-prompt [5] > exit.
445
+ shell exited with code 0
446
+ EOS
447
+ end
448
+ end
449
+
450
+ it 'allows a default prompt' do
451
+ cli = Cliqr.interface do
452
+ name 'my-command'
453
+ color :disable
454
+ shell :enable
455
+
456
+ action :foo do
457
+ handler do
458
+ puts 'foo executed'
459
+ end
460
+ end
461
+ end
462
+
463
+ with_input(['', '', 'foo', '']) do
464
+ result = cli.execute_internal %w(my-command shell), output: :buffer
465
+ expect(result[:stdout]).to eq <<-EOS
466
+ Starting shell for command "my-command"
467
+ [my-command][1] $ .
468
+ [my-command][2] $ .
469
+ [my-command][3] $ foo.
470
+ foo executed
471
+ [my-command][4] $ .
472
+ [my-command][5] $ exit.
473
+ shell exited with code 0
474
+ EOS
475
+ end
476
+ end
477
+
478
+ describe 'prompt colors' do
479
+ it 'can show colors using default prompt builder' do
480
+ cli = Cliqr.interface do
481
+ name 'my-command'
482
+ arguments :disable
483
+
484
+ action :foo do
485
+ handler do
486
+ fail StandardError, 'I failed!'
487
+ end
488
+
489
+ action :bar
490
+ end
491
+ end
492
+
493
+ with_input(['unknown', '--opt-1 val', 'foo']) do
494
+ result = cli.execute_internal %w(my-command shell), output: :buffer
495
+ expect(result[:stdout]).to eq <<-EOS
496
+ Starting shell for command "my-command"
497
+ [my-command][1] $ unknown.
498
+ unknown action "unknown"
499
+ [my-command][2] $ --opt-1 val.
500
+ unknown action "--opt-1"
501
+ [my-command][3] $ foo.
502
+ command 'my-command foo' failed
503
+
504
+ Cause: StandardError - I failed!
505
+ [my-command][4] $ exit.
506
+ shell exited with code 0
507
+ EOS
508
+ end
509
+ end
510
+
511
+ it 'can show colors using custom prompt builder' do
512
+ cli = Cliqr.interface do
513
+ name 'my-command'
514
+ arguments :disable
515
+
516
+ shell do
517
+ prompt TestColorShellPrompt
518
+ end
519
+
520
+ action :foo do
521
+ handler do
522
+ fail StandardError, 'I failed!'
523
+ end
524
+
525
+ action :bar
526
+ end
527
+ end
528
+
529
+ with_input(['unknown', '--opt-1 val', 'foo']) do
530
+ result = cli.execute_internal %w(my-command shell), output: :buffer
531
+ expect(result[:stdout]).to eq <<-EOS
532
+ Starting shell for command "my-command"
533
+ test-prompt [1] > unknown.
534
+ unknown action "unknown"
535
+ test-prompt [2] > --opt-1 val.
536
+ unknown action "--opt-1"
537
+ test-prompt [3] > foo.
538
+ command 'my-command foo' failed
539
+
540
+ Cause: StandardError - I failed!
541
+ test-prompt [4] > exit.
542
+ shell exited with code 0
543
+ EOS
544
+ end
545
+ end
546
+
547
+ it 'can show colors using custom prompt builder' do
548
+ cli = Cliqr.interface do
549
+ name 'my-command'
550
+ arguments :disable
551
+
552
+ shell do
553
+ prompt do
554
+ green('green prompt > ')
555
+ end
556
+ end
557
+
558
+ action :foo do
559
+ handler do
560
+ fail StandardError, 'I failed!'
561
+ end
562
+
563
+ action :bar
564
+ end
565
+ end
566
+
567
+ with_input(['unknown', '--opt-1 val', 'foo']) do
568
+ result = cli.execute_internal %w(my-command shell), output: :buffer
569
+ expect(result[:stdout]).to eq <<-EOS
570
+ Starting shell for command "my-command"
571
+ green prompt > unknown.
572
+ unknown action "unknown"
573
+ green prompt > --opt-1 val.
574
+ unknown action "--opt-1"
575
+ green prompt > foo.
576
+ command 'my-command foo' failed
577
+
578
+ Cause: StandardError - I failed!
579
+ green prompt > exit.
580
+ shell exited with code 0
581
+ EOS
582
+ end
583
+ end
584
+ end
585
+ end
586
+
587
+ describe Cliqr::Command::ShellBannerBuilder do
588
+ it 'allows a custom prompt string for shell banner' do
589
+ cli = Cliqr.interface do
590
+ name 'my-command'
591
+ color :disable
592
+ shell :enable do
593
+ banner 'Welcome to my-command!!!'
594
+ end
595
+
596
+ action :foo do
597
+ handler do
598
+ puts 'foo executed'
599
+ end
600
+ end
601
+ end
602
+
603
+ with_input(['', '', 'foo']) do
604
+ result = cli.execute_internal %w(my-command shell), output: :buffer
605
+ expect(result[:stdout]).to eq <<-EOS
606
+ Welcome to my-command!!!
607
+ [my-command][1] $ .
608
+ [my-command][2] $ .
609
+ [my-command][3] $ foo.
610
+ foo executed
611
+ [my-command][4] $ exit.
612
+ shell exited with code 0
613
+ EOS
614
+ end
615
+ end
616
+
617
+ it 'allows a custom prompt function for shell banner' do
618
+ cli = Cliqr.interface do
619
+ name 'my-command'
620
+ color :disable
621
+ shell :enable do
622
+ banner do
623
+ "welcome to #{command}"
624
+ end
625
+ end
626
+
627
+ action :foo do
628
+ handler do
629
+ puts 'foo executed'
630
+ end
631
+ end
632
+ end
633
+
634
+ with_input(['', '', 'foo', '']) do
635
+ result = cli.execute_internal %w(my-command shell), output: :buffer
636
+ expect(result[:stdout]).to eq <<-EOS
637
+ welcome to my-command
638
+ [my-command][1] $ .
639
+ [my-command][2] $ .
640
+ [my-command][3] $ foo.
641
+ foo executed
642
+ [my-command][4] $ .
643
+ [my-command][5] $ exit.
644
+ shell exited with code 0
645
+ EOS
646
+ end
647
+ end
648
+
649
+ it 'allows a custom prompt class for shell banner' do
650
+ cli = Cliqr.interface do
651
+ name 'my-command'
652
+ color :disable
653
+ shell :enable do
654
+ banner TestShellBanner
655
+ end
656
+
657
+ action :foo do
658
+ handler do
659
+ puts 'foo executed'
660
+ end
661
+ end
662
+ end
663
+
664
+ with_input(['', '', 'foo', '']) do
665
+ result = cli.execute_internal %w(my-command shell), output: :buffer
666
+ expect(result[:stdout]).to eq <<-EOS
667
+ welcome to the command my-command
668
+ [my-command][1] $ .
669
+ [my-command][2] $ .
670
+ [my-command][3] $ foo.
671
+ foo executed
672
+ [my-command][4] $ .
673
+ [my-command][5] $ exit.
674
+ shell exited with code 0
675
+ EOS
676
+ end
677
+ end
678
+ end
679
+ end
680
+
681
+ def with_input(lines, &block)
682
+ old_stdin = $stdin
683
+ $stdin = TestIO.new(lines)
684
+ block.call
685
+ ensure
686
+ $stdin = old_stdin
687
+ end
688
+
689
+ # A test class for wrapping stdin
690
+ class TestIO
691
+ def initialize(lines)
692
+ @lines = lines.reverse
693
+ end
694
+
695
+ def gets
696
+ input = "#{@lines.length > 0 ? @lines.pop : 'exit'}"
697
+ puts "#{input}."
698
+ "#{input}\n"
699
+ end
700
+ end