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
@@ -9,7 +9,7 @@ require 'fixtures/test_option_reader_command'
9
9
  require 'fixtures/test_option_checker_command'
10
10
  require 'fixtures/argument_reader_command'
11
11
 
12
- describe Cliqr::CLI::Executor do
12
+ describe Cliqr::Executor do
13
13
  it 'routes to action command with no arguments' do
14
14
  cli = Cliqr.interface do
15
15
  name 'my-command'
@@ -0,0 +1,125 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'fixtures/test_command'
6
+
7
+ describe Cliqr::Command::Color do
8
+ it 'allows use of several colors in the command handler' do
9
+ cli = Cliqr.interface do
10
+ name 'my-command'
11
+ handler do
12
+ [
13
+ :black,
14
+ :red,
15
+ :green,
16
+ :yellow,
17
+ :blue,
18
+ :magenta,
19
+ :cyan,
20
+ :gray,
21
+ :bg_black,
22
+ :bg_red,
23
+ :bg_green,
24
+ :bg_yellow,
25
+ :bg_blue,
26
+ :bg_magenta,
27
+ :bg_cyan,
28
+ :bg_gray,
29
+ :bold,
30
+ :reverse_color
31
+ ].each do |color|
32
+ puts method(color).call("this should be #{color}")
33
+ end
34
+ end
35
+ end
36
+ result = cli.execute_internal ['my-command'], output: :buffer
37
+ expect(result[:stdout]).to eq <<-EOS
38
+ this should be black
39
+ this should be red
40
+ this should be green
41
+ this should be yellow
42
+ this should be blue
43
+ this should be magenta
44
+ this should be cyan
45
+ this should be gray
46
+ this should be bg_black
47
+ this should be bg_red
48
+ this should be bg_green
49
+ this should be bg_yellow
50
+ this should be bg_blue
51
+ this should be bg_magenta
52
+ this should be bg_cyan
53
+ this should be bg_gray
54
+ this should be bold
55
+ this should be reverse_color
56
+ EOS
57
+ end
58
+
59
+ it 'allows use of color in action' do
60
+ cli = Cliqr.interface do
61
+ name 'my-command'
62
+ handler TestCommand
63
+
64
+ action :foo do
65
+ handler do
66
+ puts red('this should be colorized in red')
67
+ end
68
+ end
69
+ end
70
+ result = cli.execute_internal ['my-command foo'], output: :buffer
71
+ expect(result[:stdout]).to eq <<-EOS
72
+ \e[31mthis should be colorized in red\e[0m
73
+ EOS
74
+ end
75
+
76
+ it 'allows disabling colors in command' do
77
+ cli = Cliqr.interface do
78
+ name 'my-command'
79
+ color :disable
80
+ handler do
81
+ puts red('this should not be colorized')
82
+ end
83
+ end
84
+ result = cli.execute_internal ['my-command'], output: :buffer
85
+ expect(result[:stdout]).to eq <<-EOS
86
+ this should not be colorized
87
+ EOS
88
+ end
89
+
90
+ it 'allows disabling colors in action' do
91
+ cli = Cliqr.interface do
92
+ name 'my-command'
93
+ color :disable
94
+
95
+ action :foo do
96
+ handler do
97
+ puts red('this should not be colorized')
98
+ end
99
+ end
100
+ end
101
+ result = cli.execute_internal ['my-command foo'], output: :buffer
102
+ expect(result[:stdout]).to eq <<-EOS
103
+ this should not be colorized
104
+ EOS
105
+ end
106
+
107
+ it 'allows disabling colors in deeply nested action' do
108
+ cli = Cliqr.interface do
109
+ name 'my-command'
110
+ color :disable
111
+
112
+ action :foo do
113
+ action :bar do
114
+ handler do
115
+ puts red('this should not be colorized')
116
+ end
117
+ end
118
+ end
119
+ end
120
+ result = cli.execute_internal ['my-command foo bar'], output: :buffer
121
+ expect(result[:stdout]).to eq <<-EOS
122
+ this should not be colorized
123
+ EOS
124
+ end
125
+ end
@@ -2,21 +2,19 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- require 'cliqr/cli/command_runner_factory'
6
-
7
- describe Cliqr::CLI::CommandRunnerFactory do
5
+ describe Cliqr::Executor::CommandRunnerFactory do
8
6
  it 'returns standard runner for default output' do
9
- runner = Cliqr::CLI::CommandRunnerFactory.get(output: :default)
10
- expect(runner).to be_kind_of(Cliqr::CLI::StandardCommandRunner)
7
+ runner = Cliqr::Executor::CommandRunnerFactory.get(output: :default)
8
+ expect(runner).to be_kind_of(Cliqr::Executor::StandardCommandRunner)
11
9
  end
12
10
 
13
11
  it 'returns buffered runner for buffer output' do
14
- runner = Cliqr::CLI::CommandRunnerFactory.get(output: :buffer)
15
- expect(runner).to be_kind_of(Cliqr::CLI::BufferedCommandRunner)
12
+ runner = Cliqr::Executor::CommandRunnerFactory.get(output: :buffer)
13
+ expect(runner).to be_kind_of(Cliqr::Executor::BufferedCommandRunner)
16
14
  end
17
15
 
18
16
  it 'throws error for default output type' do
19
- expect { Cliqr::CLI::CommandRunnerFactory.get(output: :unknown) }.to(
17
+ expect { Cliqr::Executor::CommandRunnerFactory.get(output: :unknown) }.to(
20
18
  raise_error(be_kind_of(Cliqr::Error::UnknownCommandRunnerException))
21
19
  )
22
20
  end
@@ -0,0 +1,365 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'cliqr/events/handler'
6
+
7
+ require 'fixtures/test_arg_printer_event_handler'
8
+ require 'fixtures/test_empty_event_handler'
9
+ require 'fixtures/test_invoker_event_handler'
10
+
11
+ describe Cliqr::Events::Handler do
12
+ it 'allows invoking event that does not have a handler' do
13
+ cli = Cliqr.interface do
14
+ name 'my-command'
15
+ handler do
16
+ puts invoke :base, 'a', 1
17
+ end
18
+ end
19
+ result = cli.execute_internal ['my-command'], output: :buffer
20
+ expect(result[:stdout]).to eq <<-EOS
21
+ false
22
+ EOS
23
+ end
24
+
25
+ it 'allows a custom class as event handler' do
26
+ cli = Cliqr.interface do
27
+ name 'my-command'
28
+ on :base, TestArgPrinterEventHandler
29
+ handler do
30
+ puts invoke :base, 'a', 1
31
+ end
32
+ end
33
+ result = cli.execute_internal ['my-command'], output: :buffer
34
+ expect(result[:stdout]).to eq <<-EOS
35
+ base
36
+ a => 1
37
+ true
38
+ EOS
39
+ end
40
+
41
+ it 'does not allow missing handle method in handler' do
42
+ cli = Cliqr.interface do
43
+ name 'my-command'
44
+ on :base, TestEmptyEventHandler
45
+ handler do
46
+ puts invoke :base, 'a', 1
47
+ end
48
+ end
49
+ expect { cli.execute_internal ['my-command'] }.to(
50
+ raise_error(Cliqr::Error::CommandRuntimeError,
51
+ "command 'my-command' failed\n\n" \
52
+ "Cause: Cliqr::Error::InvocationError - failed invocation for base\n\n" \
53
+ "Cause: Cliqr::Error::InvocationError - handle method not implemented by handler class\n\n"))
54
+ end
55
+
56
+ it 'handles errors in invocation handlers' do
57
+ cli = Cliqr.interface do
58
+ name 'my-command'
59
+ on :base do
60
+ fail StandardError, 'kaboom!'
61
+ end
62
+ handler do
63
+ puts invoke :base
64
+ end
65
+ end
66
+ expect { cli.execute_internal ['my-command'] }.to(
67
+ raise_error(Cliqr::Error::CommandRuntimeError,
68
+ "command 'my-command' failed\n\n" \
69
+ "Cause: Cliqr::Error::InvocationError - failed invocation for base\n\n" \
70
+ "Cause: StandardError - kaboom!\n\n"))
71
+ end
72
+
73
+ it 'allows a proc as event handler' do
74
+ cli = Cliqr.interface do
75
+ name 'my-command'
76
+ on :base do |_event, ch, num|
77
+ puts "invoked : #{ch} : #{num}"
78
+ end
79
+ handler do
80
+ puts invoke :base, 'a', 1
81
+ end
82
+ end
83
+ result = cli.execute_internal ['my-command'], output: :buffer
84
+ expect(result[:stdout]).to eq <<-EOS
85
+ invoked : a : 1
86
+ true
87
+ EOS
88
+ end
89
+
90
+ it 'allows a string as event name' do
91
+ cli = Cliqr.interface do
92
+ name 'my-command'
93
+ on 'my-event-name' do |_event, ch, num|
94
+ puts "invoked : #{ch} : #{num}"
95
+ end
96
+ handler do
97
+ puts invoke 'my-event-name', 'a', 1
98
+ end
99
+ end
100
+ result = cli.execute_internal ['my-command'], output: :buffer
101
+ expect(result[:stdout]).to eq <<-EOS
102
+ invoked : a : 1
103
+ true
104
+ EOS
105
+ end
106
+
107
+ it 'allows access to event properties in event handler' do
108
+ cli = Cliqr.interface do
109
+ name 'my-command'
110
+ on :base do |event, ch, num|
111
+ puts "invoked : #{ch} : #{num}"
112
+ puts event.name
113
+ puts event.command
114
+ puts event.timestamp.class
115
+ end
116
+ handler do
117
+ invoke :base, 'a', 1
118
+ end
119
+ end
120
+ result = cli.execute_internal ['my-command'], output: :buffer
121
+ expect(result[:stdout]).to eq <<-EOS
122
+ invoked : a : 1
123
+ base
124
+ my-command
125
+ Time
126
+ EOS
127
+ end
128
+
129
+ it 'allows invoking a event handler from other event handler' do
130
+ cli = Cliqr.interface do
131
+ name 'my-command'
132
+ on :foo do |event, ch, num, hash|
133
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num} : #{hash}"
134
+ puts "#{event.name} #{(event.parent? ? "has parent => #{event.parent.name}" : 'does not have parent')}"
135
+ puts "parent: #{event.parent.name} : #{event.parent.command}"
136
+ puts "diff => #{event.timestamp.to_i - event.parent.timestamp.to_i}"
137
+ puts "diff => #{event.parent.timestamp.to_i - event.parent.parent.timestamp.to_i}"
138
+ puts "#{event.name} ending"
139
+ end
140
+
141
+ action :my_action do
142
+ on :bar do |event, ch, num|
143
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
144
+ puts "#{event.name} #{(event.parent? ? "has parent => #{event.parent.name}" : 'does not have parent')}"
145
+ sleep 1
146
+ invoke :baz, 'b', 2, :t => 1
147
+ puts "#{event.name} ending"
148
+ end
149
+ on :baz do |event, ch, num, hash|
150
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num} : #{hash}"
151
+ puts "#{event.name} #{(event.parent? ? "has parent => #{event.parent.name}" : 'does not have parent')}"
152
+ puts "parent: #{event.parent.name} : #{event.parent.command}"
153
+ puts "diff => #{event.timestamp.to_i - event.parent.timestamp.to_i}"
154
+ sleep 1
155
+ invoke :foo, 'c', 3, :s => 2
156
+ puts "#{event.name} ending"
157
+ end
158
+ handler do
159
+ puts 'invoked action'
160
+ invoke :bar, 'a', 1
161
+ puts 'action ending'
162
+ end
163
+ end
164
+ end
165
+ result = cli.execute_internal ['my-command my_action'], output: :buffer
166
+ expect(result[:stdout]).to eq <<-EOS
167
+ invoked action
168
+ invoked bar : my-command my_action : a : 1
169
+ bar does not have parent
170
+ invoked baz : my-command my_action : b : 2 : {:t=>1}
171
+ baz has parent => bar
172
+ parent: bar : my-command my_action
173
+ diff => 1
174
+ invoked foo : my-command my_action : c : 3 : {:s=>2}
175
+ foo has parent => baz
176
+ parent: baz : my-command my_action
177
+ diff => 1
178
+ diff => 1
179
+ foo ending
180
+ baz ending
181
+ bar ending
182
+ action ending
183
+ EOS
184
+ end
185
+
186
+ it 'allows invoking a event handler from custom event handler class' do
187
+ cli = Cliqr.interface do
188
+ name 'my-command'
189
+ on :foo do |event, ch, num, hash|
190
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num} : #{hash}"
191
+ puts event.parent.name
192
+ end
193
+
194
+ action :my_action do
195
+ on :bar, TestInvokerEventHandler
196
+ handler do
197
+ invoke :bar, 'a', 1
198
+ end
199
+ end
200
+ end
201
+ result = cli.execute_internal ['my-command my_action'], output: :buffer
202
+ expect(result[:stdout]).to eq <<-EOS
203
+ invoked bar : my-command my_action : a : 1
204
+ invoked foo : my-command my_action : b : 2 : {:t=>1}
205
+ bar
206
+ EOS
207
+ end
208
+
209
+ it 'invokes event handler by propogating up the action chain' do
210
+ cli = Cliqr.interface do
211
+ name 'my-command'
212
+ on :first do |event, ch, num|
213
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
214
+ end
215
+ on :second do |event, ch, num|
216
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
217
+ end
218
+ on :third do |event, ch, num|
219
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
220
+ end
221
+ handler do
222
+ invoke :first, 'a', 1 # should only call one of base command
223
+ end
224
+
225
+ action :foo do
226
+ on :first do |event, ch, num|
227
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
228
+ end
229
+ on :second do |event, ch, num|
230
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
231
+ end
232
+ handler do
233
+ invoke :second, 'b', 2 # invokes this and base
234
+ end
235
+
236
+ action :bar do
237
+ on :first do |event, ch, num|
238
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
239
+ end
240
+ on :third do |event, ch, num|
241
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
242
+ end
243
+ handler do
244
+ invoke :first, 'b', 2 # invokes all the way to base
245
+ invoke :third, 'd', 4 # invokes this and base (skips parent)
246
+ end
247
+ end
248
+
249
+ action :baz do
250
+ on :second do |event, ch, num|
251
+ puts "invoked #{event.name} : #{event.command} : #{ch} : #{num}"
252
+ end
253
+ handler do
254
+ invoke :second, 'e', 5 # invokes all the way to base (skips sibling)
255
+ end
256
+ end
257
+ end
258
+ end
259
+ result = cli.execute_internal ['my-command'], output: :buffer
260
+ expect(result[:stdout]).to eq <<-EOS
261
+ invoked first : my-command : a : 1
262
+ EOS
263
+ result = cli.execute_internal ['my-command foo'], output: :buffer
264
+ expect(result[:stdout]).to eq <<-EOS
265
+ invoked second : my-command foo : b : 2
266
+ invoked second : my-command foo : b : 2
267
+ EOS
268
+ result = cli.execute_internal ['my-command foo bar'], output: :buffer
269
+ expect(result[:stdout]).to eq <<-EOS
270
+ invoked first : my-command foo bar : b : 2
271
+ invoked first : my-command foo bar : b : 2
272
+ invoked first : my-command foo bar : b : 2
273
+ invoked third : my-command foo bar : d : 4
274
+ invoked third : my-command foo bar : d : 4
275
+ EOS
276
+ result = cli.execute_internal ['my-command foo baz'], output: :buffer
277
+ expect(result[:stdout]).to eq <<-EOS
278
+ invoked second : my-command foo baz : e : 5
279
+ invoked second : my-command foo baz : e : 5
280
+ invoked second : my-command foo baz : e : 5
281
+ EOS
282
+ end
283
+
284
+ it 'can terminate event chain' do
285
+ cli = Cliqr.interface do
286
+ name 'my-command'
287
+ on :base do
288
+ puts 'should not be invoked'
289
+ end
290
+
291
+ action :foo do
292
+ on :base do |event|
293
+ puts 'should be invoked'
294
+ event.stop_propagation
295
+ end
296
+ handler do
297
+ invoke :base
298
+ end
299
+ end
300
+ end
301
+ result = cli.execute_internal ['my-command foo'], output: :buffer
302
+ expect(result[:stdout]).to eq <<-EOS
303
+ should be invoked
304
+ EOS
305
+ end
306
+
307
+ it 'can access options in event handler' do
308
+ cli = Cliqr.interface do
309
+ name 'my-command'
310
+ on :foo do
311
+ puts 'invoked foo'
312
+ puts opt?
313
+ puts abc?
314
+ puts xyz?
315
+ puts opt
316
+ end
317
+
318
+ action :my_action do
319
+ on :bar do
320
+ puts 'invoked bar'
321
+ puts opt?
322
+ puts abc?
323
+ puts xyz?
324
+ puts opt
325
+ end
326
+
327
+ handler do
328
+ invoke :bar, 'a', 1
329
+ end
330
+
331
+ option :opt
332
+ option :abc
333
+ end
334
+ end
335
+ result = cli.execute_internal ['my-command my_action --opt val'], output: :buffer
336
+ expect(result[:stdout]).to eq <<-EOS
337
+ invoked bar
338
+ true
339
+ false
340
+
341
+ val
342
+ EOS
343
+ end
344
+
345
+ it 'cannot get option value for non-configured option' do
346
+ cli = Cliqr.interface do
347
+ name 'my-command'
348
+
349
+ on :foo do
350
+ puts 'invoked foo'
351
+ puts opt
352
+ end
353
+
354
+ handler do
355
+ invoke :foo
356
+ end
357
+ end
358
+
359
+ result = cli.execute_internal ['my-command'], output: :buffer
360
+ expect(result[:stdout]).to eq <<-EOS
361
+ invoked foo
362
+
363
+ EOS
364
+ end
365
+ end