command_kit 0.1.0.pre2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +15 -0
  3. data/.rubocop.yml +141 -0
  4. data/ChangeLog.md +98 -2
  5. data/Gemfile +3 -0
  6. data/README.md +189 -117
  7. data/Rakefile +3 -2
  8. data/command_kit.gemspec +4 -4
  9. data/examples/command.rb +1 -1
  10. data/gemspec.yml +10 -2
  11. data/lib/command_kit/arguments/argument.rb +2 -0
  12. data/lib/command_kit/arguments/argument_value.rb +2 -0
  13. data/lib/command_kit/arguments.rb +23 -4
  14. data/lib/command_kit/colors.rb +253 -45
  15. data/lib/command_kit/command.rb +6 -1
  16. data/lib/command_kit/command_name.rb +9 -0
  17. data/lib/command_kit/commands/auto_load.rb +24 -1
  18. data/lib/command_kit/commands/auto_require.rb +16 -0
  19. data/lib/command_kit/commands/command.rb +3 -0
  20. data/lib/command_kit/commands/help.rb +5 -2
  21. data/lib/command_kit/commands/parent_command.rb +7 -0
  22. data/lib/command_kit/commands/subcommand.rb +13 -1
  23. data/lib/command_kit/commands.rb +54 -9
  24. data/lib/command_kit/description.rb +12 -1
  25. data/lib/command_kit/env/home.rb +9 -0
  26. data/lib/command_kit/env/path.rb +16 -1
  27. data/lib/command_kit/env.rb +4 -0
  28. data/lib/command_kit/examples.rb +12 -1
  29. data/lib/command_kit/exception_handler.rb +4 -0
  30. data/lib/command_kit/help/man.rb +26 -30
  31. data/lib/command_kit/help.rb +7 -1
  32. data/lib/command_kit/inflector.rb +49 -17
  33. data/lib/command_kit/interactive.rb +248 -0
  34. data/lib/command_kit/main.rb +18 -9
  35. data/lib/command_kit/man.rb +44 -0
  36. data/lib/command_kit/open_app.rb +69 -0
  37. data/lib/command_kit/options/option.rb +3 -6
  38. data/lib/command_kit/options/option_value.rb +5 -2
  39. data/lib/command_kit/options/parser.rb +46 -19
  40. data/lib/command_kit/options/quiet.rb +3 -0
  41. data/lib/command_kit/options/verbose.rb +5 -0
  42. data/lib/command_kit/options/version.rb +6 -0
  43. data/lib/command_kit/options.rb +32 -7
  44. data/lib/command_kit/os/linux.rb +157 -0
  45. data/lib/command_kit/os.rb +165 -11
  46. data/lib/command_kit/package_manager.rb +200 -0
  47. data/lib/command_kit/pager.rb +80 -11
  48. data/lib/command_kit/printing/indent.rb +27 -4
  49. data/lib/command_kit/printing.rb +35 -1
  50. data/lib/command_kit/program_name.rb +7 -0
  51. data/lib/command_kit/stdio.rb +24 -0
  52. data/lib/command_kit/sudo.rb +40 -0
  53. data/lib/command_kit/terminal.rb +159 -0
  54. data/lib/command_kit/usage.rb +14 -0
  55. data/lib/command_kit/version.rb +1 -1
  56. data/lib/command_kit/xdg.rb +13 -0
  57. data/lib/command_kit.rb +1 -0
  58. data/spec/arguments/argument_spec.rb +2 -2
  59. data/spec/arguments_spec.rb +53 -27
  60. data/spec/colors_spec.rb +277 -13
  61. data/spec/command_name_spec.rb +1 -1
  62. data/spec/command_spec.rb +79 -5
  63. data/spec/commands/auto_load/subcommand_spec.rb +1 -1
  64. data/spec/commands/auto_load_spec.rb +34 -3
  65. data/spec/commands/auto_require_spec.rb +2 -2
  66. data/spec/commands/help_spec.rb +1 -1
  67. data/spec/commands/parent_command_spec.rb +1 -1
  68. data/spec/commands/subcommand_spec.rb +1 -1
  69. data/spec/commands_spec.rb +103 -29
  70. data/spec/description_spec.rb +1 -25
  71. data/spec/env/home_spec.rb +1 -1
  72. data/spec/env/path_spec.rb +7 -1
  73. data/spec/examples_spec.rb +1 -25
  74. data/spec/exception_handler_spec.rb +1 -1
  75. data/spec/help/man_spec.rb +45 -58
  76. data/spec/help_spec.rb +0 -25
  77. data/spec/inflector_spec.rb +71 -9
  78. data/spec/interactive_spec.rb +415 -0
  79. data/spec/main_spec.rb +7 -7
  80. data/spec/man_spec.rb +46 -0
  81. data/spec/open_app_spec.rb +85 -0
  82. data/spec/options/option_spec.rb +5 -5
  83. data/spec/options/option_value_spec.rb +56 -1
  84. data/spec/options_spec.rb +283 -1
  85. data/spec/os/linux_spec.rb +164 -0
  86. data/spec/os_spec.rb +201 -14
  87. data/spec/package_manager_spec.rb +806 -0
  88. data/spec/pager_spec.rb +76 -11
  89. data/spec/printing/indent_spec.rb +8 -6
  90. data/spec/printing_spec.rb +33 -3
  91. data/spec/program_name_spec.rb +1 -1
  92. data/spec/spec_helper.rb +0 -3
  93. data/spec/sudo_spec.rb +51 -0
  94. data/spec/{console_spec.rb → terminal_spec.rb} +65 -35
  95. data/spec/usage_spec.rb +2 -2
  96. data/spec/xdg_spec.rb +1 -1
  97. metadata +26 -8
  98. data/lib/command_kit/console.rb +0 -141
@@ -0,0 +1,415 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/interactive'
3
+
4
+ describe CommandKit::Interactive do
5
+ module TestInteractive
6
+ class TestCommand
7
+ include CommandKit::Interactive
8
+ end
9
+ end
10
+
11
+ let(:command_class) { TestInteractive::TestCommand }
12
+
13
+ describe "#included" do
14
+ subject { command_class }
15
+
16
+ it { expect(subject).to include(CommandKit::Stdio) }
17
+ end
18
+
19
+ let(:stdout) { StringIO.new }
20
+ let(:stdin) { StringIO.new }
21
+ let(:stderr) { StringIO.new }
22
+
23
+ subject do
24
+ command_class.new(stdout: stdout, stdin: stdin, stderr: stderr)
25
+ end
26
+
27
+ let(:prompt) { 'Prompt' }
28
+
29
+ describe "#ask" do
30
+ let(:input) { 'foo' }
31
+
32
+ it "must print a prompt, read input, and return the input" do
33
+ expect(stdout).to receive(:print).with("#{prompt}: ")
34
+ expect(stdin).to receive(:gets).and_return(input)
35
+
36
+ expect(subject.ask(prompt)).to eq(input)
37
+ end
38
+
39
+ it "must accept empty user input by default" do
40
+ expect(stdin).to receive(:gets).and_return("")
41
+
42
+ expect(subject.ask(prompt)).to eq("")
43
+ end
44
+
45
+ context "when Ctrl^C is entered" do
46
+ it "must return \"\"" do
47
+ expect(stdin).to receive(:gets).and_return(nil) # simulate Ctrl^C
48
+
49
+ expect(subject.ask(prompt)).to eq("")
50
+ end
51
+ end
52
+
53
+ context "when default: is given" do
54
+ let(:default) { 'bar' }
55
+
56
+ it "must include the default: value in the prompt" do
57
+ expect(stdout).to receive(:print).with("#{prompt} [#{default}]: ")
58
+ expect(stdin).to receive(:gets).and_return(input)
59
+
60
+ expect(subject.ask(prompt, default: default)).to eq(input)
61
+ end
62
+
63
+ context "and non-empty user input is given" do
64
+ it "must return the non-empty user input" do
65
+ expect(stdin).to receive(:gets).and_return(input)
66
+
67
+ expect(subject.ask(prompt, default: default)).to eq(input)
68
+ end
69
+ end
70
+
71
+ context "and empty user input is given" do
72
+ it "must return the default value" do
73
+ expect(stdin).to receive(:gets).and_return("")
74
+
75
+ expect(subject.ask(prompt, default: default)).to eq(default)
76
+ end
77
+ end
78
+ end
79
+
80
+ context "when required: is given" do
81
+ context "and empty user input is given" do
82
+ it "must ask for input again, until non-empty input is given" do
83
+ expect(stdin).to receive(:gets).and_return("")
84
+ expect(stdin).to receive(:gets).and_return("")
85
+ expect(stdin).to receive(:gets).and_return(input)
86
+
87
+ expect(subject.ask(prompt, required: true)).to eq(input)
88
+ end
89
+ end
90
+
91
+ context "and non-empty user input is given" do
92
+ it "must return the non-empty user input" do
93
+ expect(stdin).to receive(:gets).and_return(input)
94
+
95
+ expect(subject.ask(prompt, required: true)).to eq(input)
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "#ask_yes_or_no" do
102
+ let(:input) { 'Y' }
103
+
104
+ it "must print a prompt indicating Y/N, and then accept input" do
105
+ expect(stdout).to receive(:print).with("#{prompt} (Y/N): ")
106
+ expect(stdin).to receive(:gets).and_return(input)
107
+
108
+ subject.ask_yes_or_no(prompt)
109
+ end
110
+
111
+ context "when 'Y' is entered" do
112
+ let(:input) { 'Y' }
113
+
114
+ it "must return true" do
115
+ expect(stdin).to receive(:gets).and_return(input)
116
+
117
+ expect(subject.ask_yes_or_no(prompt)).to eq(true)
118
+ end
119
+ end
120
+
121
+ context "when 'y' is entered" do
122
+ let(:input) { 'y' }
123
+
124
+ it "must return true" do
125
+ expect(stdin).to receive(:gets).and_return(input)
126
+
127
+ expect(subject.ask_yes_or_no(prompt)).to eq(true)
128
+ end
129
+ end
130
+
131
+ context "when 'YES' is entered" do
132
+ let(:input) { 'YES' }
133
+
134
+ it "must return true" do
135
+ expect(stdin).to receive(:gets).and_return(input)
136
+
137
+ expect(subject.ask_yes_or_no(prompt)).to eq(true)
138
+ end
139
+ end
140
+
141
+ context "when 'Yes' is entered" do
142
+ let(:input) { 'Yes' }
143
+
144
+ it "must return true" do
145
+ expect(stdin).to receive(:gets).and_return(input)
146
+
147
+ expect(subject.ask_yes_or_no(prompt)).to eq(true)
148
+ end
149
+ end
150
+
151
+ context "when 'yes' is entered" do
152
+ let(:input) { 'yes' }
153
+
154
+ it "must return true" do
155
+ expect(stdin).to receive(:gets).and_return(input)
156
+
157
+ expect(subject.ask_yes_or_no(prompt)).to eq(true)
158
+ end
159
+ end
160
+
161
+ context "when 'N' is entered" do
162
+ let(:input) { 'N' }
163
+
164
+ it "must return false" do
165
+ expect(stdin).to receive(:gets).and_return(input)
166
+
167
+ expect(subject.ask_yes_or_no(prompt)).to eq(false)
168
+ end
169
+ end
170
+
171
+ context "when 'n' is entered" do
172
+ let(:input) { 'n' }
173
+
174
+ it "must return false" do
175
+ expect(stdin).to receive(:gets).and_return(input)
176
+
177
+ expect(subject.ask_yes_or_no(prompt)).to eq(false)
178
+ end
179
+ end
180
+
181
+ context "when 'NO' is entered" do
182
+ let(:input) { 'NO' }
183
+
184
+ it "must return false" do
185
+ expect(stdin).to receive(:gets).and_return(input)
186
+
187
+ expect(subject.ask_yes_or_no(prompt)).to eq(false)
188
+ end
189
+ end
190
+
191
+ context "when 'No' is entered" do
192
+ let(:input) { 'No' }
193
+
194
+ it "must return false" do
195
+ expect(stdin).to receive(:gets).and_return(input)
196
+
197
+ expect(subject.ask_yes_or_no(prompt)).to eq(false)
198
+ end
199
+ end
200
+
201
+ context "when 'no' is entered" do
202
+ let(:input) { 'no' }
203
+
204
+ it "must return false" do
205
+ expect(stdin).to receive(:gets).and_return(input)
206
+
207
+ expect(subject.ask_yes_or_no(prompt)).to eq(false)
208
+ end
209
+ end
210
+
211
+ context "when input besides y/n/yes/no is entered" do
212
+ let(:input) { 'jflksjfls' }
213
+
214
+ it "must return false" do
215
+ expect(stdin).to receive(:gets).and_return(input)
216
+
217
+ expect(subject.ask_yes_or_no(prompt)).to eq(false)
218
+ end
219
+ end
220
+
221
+ context "when defualt: is given" do
222
+ context "and is true" do
223
+ let(:default) { true }
224
+
225
+ it "must include [Y] in the prompt" do
226
+ expect(stdout).to receive(:print).with("#{prompt} (Y/N) [Y]: ")
227
+ expect(stdin).to receive(:gets).and_return(input)
228
+
229
+ subject.ask_yes_or_no(prompt, default: default)
230
+ end
231
+
232
+ context "and empty user-input is given" do
233
+ let(:input) { "" }
234
+
235
+ it "must return true" do
236
+ expect(stdout).to receive(:print).with("#{prompt} (Y/N) [Y]: ")
237
+ expect(stdin).to receive(:gets).and_return(input)
238
+
239
+ expect(subject.ask_yes_or_no(prompt, default: default)).to eq(default)
240
+ end
241
+ end
242
+ end
243
+
244
+ context "and is false" do
245
+ let(:default) { false }
246
+
247
+ it "must include [N] in the prompt" do
248
+ expect(stdout).to receive(:print).with("#{prompt} (Y/N) [N]: ")
249
+ expect(stdin).to receive(:gets).and_return(input)
250
+
251
+ subject.ask_yes_or_no(prompt, default: default)
252
+ end
253
+
254
+ context "and empty user-input is given" do
255
+ let(:input) { "" }
256
+
257
+ it "must return false" do
258
+ expect(stdout).to receive(:print).with("#{prompt} (Y/N) [N]: ")
259
+ expect(stdin).to receive(:gets).and_return(input)
260
+
261
+ expect(subject.ask_yes_or_no(prompt, default: default)).to eq(default)
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end
267
+
268
+ describe "#ask_multiple_choice" do
269
+ context "when given an Array" do
270
+ let(:choices) do
271
+ [
272
+ "foo",
273
+ "bar",
274
+ "baz"
275
+ ]
276
+ end
277
+
278
+ let(:input) { "2" }
279
+
280
+ it "must print the numbered choices, a prompt with the choices, read input, and return the choice" do
281
+ expect(stdout).to receive(:puts).with(" 1) #{choices[0]}")
282
+ expect(stdout).to receive(:puts).with(" 2) #{choices[1]}")
283
+ expect(stdout).to receive(:puts).with(" 3) #{choices[2]}")
284
+ expect(stdout).to receive(:puts).with(no_args)
285
+ expect(stdout).to receive(:print).with("#{prompt} (1, 2, 3): ")
286
+ expect(stdin).to receive(:gets).and_return(input)
287
+
288
+ expect(subject.ask_multiple_choice(prompt,choices)).to eq(choices[input.to_i - 1])
289
+ end
290
+
291
+ context "when empty user-input is given" do
292
+ it "must ask for input again, until non-empty input is given" do
293
+ expect(stdin).to receive(:gets).and_return("")
294
+ expect(stdin).to receive(:gets).and_return("")
295
+ expect(stdin).to receive(:gets).and_return(input)
296
+
297
+ expect(subject.ask_multiple_choice(prompt,choices)).to eq(choices[input.to_i - 1])
298
+ end
299
+ end
300
+
301
+ context "and default: is given" do
302
+ let(:default) { '3' }
303
+
304
+ it "must include the default: choice in the prompt" do
305
+ expect(stdout).to receive(:print).with("#{prompt} (1, 2, 3) [#{default}]: ")
306
+ expect(stdin).to receive(:gets).and_return(input)
307
+
308
+ subject.ask_multiple_choice(prompt,choices, default: default)
309
+ end
310
+
311
+ context "and empty user-input is given" do
312
+ it "must return the value for the default choice" do
313
+ expect(stdin).to receive(:gets).and_return("")
314
+
315
+ expect(subject.ask_multiple_choice(prompt,choices, default: default)).to eq(choices[default.to_i - 1])
316
+ end
317
+ end
318
+ end
319
+ end
320
+
321
+ context "when given a Hash" do
322
+ let(:choices) do
323
+ {
324
+ "A" => "foo",
325
+ "B" => "bar",
326
+ "C" => "baz"
327
+ }
328
+ end
329
+
330
+ let(:input) { "B" }
331
+
332
+ it "must print the labeled choices, a prompt with the choices, read input, and return the choice" do
333
+ expect(stdout).to receive(:puts).with(" #{choices.keys[0]}) #{choices.values[0]}")
334
+ expect(stdout).to receive(:puts).with(" #{choices.keys[1]}) #{choices.values[1]}")
335
+ expect(stdout).to receive(:puts).with(" #{choices.keys[2]}) #{choices.values[2]}")
336
+ expect(stdout).to receive(:puts).with(no_args)
337
+ expect(stdout).to receive(:print).with("#{prompt} (#{choices.keys[0]}, #{choices.keys[1]}, #{choices.keys[2]}): ")
338
+ expect(stdin).to receive(:gets).and_return(input)
339
+
340
+ expect(subject.ask_multiple_choice(prompt,choices)).to eq(choices[input])
341
+ end
342
+
343
+ context "when empty user-input is given" do
344
+ it "must ask for input again, until non-empty input is given" do
345
+ expect(stdin).to receive(:gets).and_return("")
346
+ expect(stdin).to receive(:gets).and_return("")
347
+ expect(stdin).to receive(:gets).and_return(input)
348
+
349
+ expect(subject.ask_multiple_choice(prompt,choices)).to eq(choices[input])
350
+ end
351
+ end
352
+
353
+ context "and default: is given" do
354
+ let(:default) { 'C' }
355
+
356
+ it "must include the default: choice in the prompt" do
357
+ expect(stdout).to receive(:print).with("#{prompt} (#{choices.keys[0]}, #{choices.keys[1]}, #{choices.keys[2]}) [#{default}]: ")
358
+ expect(stdin).to receive(:gets).and_return(input)
359
+
360
+ subject.ask_multiple_choice(prompt,choices, default: default)
361
+ end
362
+
363
+ context "and empty user-input is given" do
364
+ it "must return the value for the default choice" do
365
+ expect(stdin).to receive(:gets).and_return("")
366
+
367
+ expect(subject.ask_multiple_choice(prompt,choices, default: default)).to eq(choices[default])
368
+ end
369
+ end
370
+ end
371
+ end
372
+ end
373
+
374
+ describe "#ask_secret" do
375
+ let(:input) { 's3cr3t' }
376
+
377
+ context "when stdin supports to #noecho" do
378
+ it "must call #noecho, read input, then return the input" do
379
+ allow(stdin).to receive(:noecho).and_yield
380
+ expect(stdin).to receive(:gets).and_return(input)
381
+
382
+ expect(subject.ask_secret(prompt)).to eq(input)
383
+ end
384
+ end
385
+
386
+ context "when stdin does not support #noecho" do
387
+ it "must fallback to reading input" do
388
+ expect(stdin).to receive(:gets).and_return(input)
389
+
390
+ expect(subject.ask_secret(prompt)).to eq(input)
391
+ end
392
+ end
393
+
394
+ context "when empty user-input is given" do
395
+ it "must ask for input again, until non-empty input is given" do
396
+ expect(stdin).to receive(:gets).and_return("")
397
+ expect(stdin).to receive(:gets).and_return("")
398
+ expect(stdin).to receive(:gets).and_return("")
399
+ expect(stdin).to receive(:gets).and_return(input)
400
+
401
+ expect(subject.ask_secret(prompt)).to eq(input)
402
+ end
403
+ end
404
+
405
+ context "when required: is false" do
406
+ context "and empty user-input is given" do
407
+ it "must return the empty user-input" do
408
+ expect(stdin).to receive(:gets).and_return("")
409
+
410
+ expect(subject.ask_secret(prompt, required: false)).to eq("")
411
+ end
412
+ end
413
+ end
414
+ end
415
+ end
data/spec/main_spec.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/main'
3
3
 
4
- describe Main do
4
+ describe CommandKit::Main do
5
5
  module TestMain
6
6
  class TestCommand
7
7
  include CommandKit::Main
@@ -156,16 +156,16 @@ describe Main do
156
156
  describe "#main" do
157
157
  subject { command_class.new }
158
158
 
159
- it "must provide a default #main" do
160
- expect(subject).to respond_to(:main)
161
- end
162
-
163
159
  it "must return 0 by default" do
164
160
  expect(subject.main).to eq(0)
165
161
  end
166
162
 
167
- it "must accept arbitrary argv" do
168
- expect { subject.main([1,2,3]) }.to_not raise_error
163
+ it "must call #run with the given argv" do
164
+ argv = ["foo", "bar", "baz"]
165
+
166
+ expect(subject).to receive(:run).with(*argv)
167
+
168
+ subject.main(argv)
169
169
  end
170
170
 
171
171
  context "when #run raises SystemExit" do
data/spec/man_spec.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/man'
3
+
4
+ describe CommandKit::Man do
5
+ module TestMan
6
+ class TestCommand
7
+ include CommandKit::Man
8
+ end
9
+ end
10
+
11
+ let(:command_class) { TestMan::TestCommand }
12
+
13
+ subject { command_class.new }
14
+
15
+ describe "#man" do
16
+ let(:man_page) { 'foo' }
17
+
18
+ it "must call system() with the given man page" do
19
+ expect(subject).to receive(:system).with('man',man_page)
20
+
21
+ subject.man(man_page)
22
+ end
23
+
24
+ context "when given a non-String man-page argument" do
25
+ let(:man_page_arg) { double(:non_string_arg) }
26
+
27
+ it "must call #to_s on the man-page argument" do
28
+ expect(man_page_arg).to receive(:to_s).and_return(man_page)
29
+
30
+ expect(subject).to receive(:system).with('man',man_page)
31
+
32
+ subject.man(man_page_arg)
33
+ end
34
+ end
35
+
36
+ context "when given the section: keyword argument" do
37
+ let(:section) { 7 }
38
+
39
+ it "must call system() with the given section number and man page" do
40
+ expect(subject).to receive(:system).with('man',section.to_s,man_page)
41
+
42
+ subject.man(man_page, section: section)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/open_app'
3
+
4
+ describe CommandKit::OpenApp do
5
+ module TestOpenApp
6
+ class TestCommand
7
+ include CommandKit::OpenApp
8
+ end
9
+ end
10
+
11
+ let(:command_class) { TestOpenApp::TestCommand }
12
+
13
+ subject { command_class.new }
14
+
15
+ describe "#initialize" do
16
+ context "when the OS is macOS" do
17
+ subject { command_class.new(os: :macos) }
18
+
19
+ it "must set @open_command to \"open\"" do
20
+ expect(subject.instance_variable_get("@open_command")).to eq("open")
21
+ end
22
+ end
23
+
24
+ context "when the OS is Linux" do
25
+ subject { command_class.new(os: :linux) }
26
+
27
+ it "must set @open_command to \"xdg-open\"" do
28
+ expect(subject.instance_variable_get("@open_command")).to eq("xdg-open")
29
+ end
30
+ end
31
+
32
+ context "when the OS is FreeBSD" do
33
+ subject { command_class.new(os: :freebsd) }
34
+
35
+ it "must set @open_command to \"xdg-open\"" do
36
+ expect(subject.instance_variable_get("@open_command")).to eq("xdg-open")
37
+ end
38
+ end
39
+
40
+ context "when the OS is OpenBSD" do
41
+ subject { command_class.new(os: :openbsd) }
42
+
43
+ it "must set @open_command to \"xdg-open\"" do
44
+ expect(subject.instance_variable_get("@open_command")).to eq("xdg-open")
45
+ end
46
+ end
47
+
48
+ context "when the OS is NetBSD" do
49
+ subject { command_class.new(os: :openbsd) }
50
+
51
+ it "must set @open_command to \"xdg-open\"" do
52
+ expect(subject.instance_variable_get("@open_command")).to eq("xdg-open")
53
+ end
54
+ end
55
+
56
+ context "when the OS is Windows" do
57
+ subject { command_class.new(os: :windows) }
58
+
59
+ it "must set @open_command to \"start\"" do
60
+ expect(subject.instance_variable_get("@open_command")).to eq("start")
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "#open_app_for" do
66
+ context "when @open_command is set" do
67
+ let(:file_or_uri) { "foo" }
68
+ let(:status) { true }
69
+
70
+ it "must execute the @open_command with the given URI or file" do
71
+ expect(subject).to receive(:system).with(subject.instance_variable_get("@open_command"),file_or_uri).and_return(status)
72
+
73
+ expect(subject.open_app_for(file_or_uri)).to be(status)
74
+ end
75
+ end
76
+
77
+ context "when @open_command is not set" do
78
+ before do
79
+ subject.instance_variable_set("@open_command",nil)
80
+ end
81
+
82
+ it { expect(subject.open_app_for("foo")).to be(nil) }
83
+ end
84
+ end
85
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/options/option'
3
3
 
4
- describe Options::Option do
4
+ describe CommandKit::Options::Option do
5
5
  let(:name) { :foo }
6
6
  let(:short) { nil }
7
7
  let(:long) { '--foo' }
@@ -18,12 +18,12 @@ describe Options::Option do
18
18
  end
19
19
 
20
20
  subject do
21
- described_class.new name, short: short,
21
+ described_class.new(name, short: short,
22
22
  long: long,
23
23
  equals: equals,
24
24
  desc: desc,
25
25
  value: value,
26
- &block
26
+ &block)
27
27
  end
28
28
 
29
29
  describe "#initialize" do
@@ -82,7 +82,7 @@ describe Options::Option do
82
82
  subject { described_class.new(name, value: {type: type}, desc: desc) }
83
83
 
84
84
  it "must initialize #value" do
85
- expect(subject.value).to be_kind_of(Options::OptionValue)
85
+ expect(subject.value).to be_kind_of(CommandKit::Options::OptionValue)
86
86
  expect(subject.value.type).to eq(type)
87
87
  end
88
88
  end
@@ -91,7 +91,7 @@ describe Options::Option do
91
91
  subject { described_class.new(name, value: true, desc: desc) }
92
92
 
93
93
  it "must initialize #value with defaults" do
94
- expect(subject.value).to be_kind_of(Options::OptionValue)
94
+ expect(subject.value).to be_kind_of(CommandKit::Options::OptionValue)
95
95
  expect(subject.value.type).to eq(String)
96
96
  expect(subject.value.required?).to be(true)
97
97
  expect(subject.value.usage).to eq('STR')
@@ -1,12 +1,67 @@
1
1
  require 'spec_helper'
2
2
  require 'command_kit/options/option_value'
3
3
 
4
- describe Options::OptionValue do
4
+ describe CommandKit::Options::OptionValue do
5
5
  let(:type) { Integer }
6
6
  let(:usage) { 'COUNT' }
7
7
  let(:required) { true }
8
8
  let(:default) { 1 }
9
9
 
10
+ describe ".default_usage" do
11
+ subject { described_class }
12
+
13
+ context "when given a Hash" do
14
+ let(:type) do
15
+ {'foo' => :foo, "bar" => :bar}
16
+ end
17
+
18
+ it "must join the Hash's keys with a '|' character" do
19
+ expect(subject.default_usage(type)).to eq(type.keys.join('|'))
20
+ end
21
+ end
22
+
23
+ context "when given an Array" do
24
+ let(:type) do
25
+ ['foo', 'bar', 'baz']
26
+ end
27
+
28
+ it "must join the Array's elements with a '|' character" do
29
+ expect(subject.default_usage(type)).to eq(type.join('|'))
30
+ end
31
+ end
32
+
33
+ context "when given a Regexp" do
34
+ let(:type) { /[0-9a-f]+/ }
35
+
36
+ it "must return the Regexp's source" do
37
+ expect(subject.default_usage(type)).to eq(type.source)
38
+ end
39
+ end
40
+
41
+ context "when given a Class" do
42
+ module TestOptionValue
43
+ class FooBarBaz
44
+ end
45
+ end
46
+
47
+ let(:type) { TestOptionValue::FooBarBaz }
48
+
49
+ it "must return the uppercase and underscored version of it's name" do
50
+ expect(subject.default_usage(type)).to eq("FOO_BAR_BAZ")
51
+ end
52
+ end
53
+
54
+ context "when given another kind of Object" do
55
+ let(:type) { Object.new }
56
+
57
+ it do
58
+ expect {
59
+ subject.default_usage(type)
60
+ }.to raise_error(TypeError,"unsupported option type: #{type.inspect}")
61
+ end
62
+ end
63
+ end
64
+
10
65
  describe "#initialize" do
11
66
  context "when the type: keyword is given" do
12
67
  let(:type) { Integer }