command_kit 0.1.0.pre2 → 0.2.1

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 (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 }