gli 1.6.0 → 2.0.0.rc3

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 (78) hide show
  1. data/.gitignore +11 -0
  2. data/.rvmrc +1 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +8 -0
  5. data/LICENSE.txt +201 -0
  6. data/ObjectModel.graffle +1191 -0
  7. data/README.rdoc +60 -10
  8. data/Rakefile +145 -0
  9. data/bin/gli +12 -30
  10. data/bin/report_on_rake_results +10 -0
  11. data/bin/test_all_rubies.sh +6 -0
  12. data/features/gli_executable.feature +84 -0
  13. data/features/gli_init.feature +219 -0
  14. data/features/step_definitions/gli_executable_steps.rb +12 -0
  15. data/features/step_definitions/gli_init_steps.rb +11 -0
  16. data/features/step_definitions/todo_steps.rb +69 -0
  17. data/features/support/env.rb +49 -0
  18. data/features/todo.feature +182 -0
  19. data/gli.cheat +95 -0
  20. data/gli.gemspec +34 -0
  21. data/lib/gli.rb +11 -571
  22. data/lib/gli/app.rb +184 -0
  23. data/lib/gli/app_support.rb +226 -0
  24. data/lib/gli/command.rb +107 -95
  25. data/lib/gli/command_line_option.rb +34 -0
  26. data/lib/gli/command_line_token.rb +13 -9
  27. data/lib/gli/command_support.rb +200 -0
  28. data/lib/gli/commands/compound_command.rb +42 -0
  29. data/lib/gli/commands/help.rb +63 -0
  30. data/lib/gli/commands/help_modules/command_help_format.rb +134 -0
  31. data/lib/gli/commands/help_modules/global_help_format.rb +61 -0
  32. data/lib/gli/commands/help_modules/list_formatter.rb +22 -0
  33. data/lib/gli/commands/help_modules/options_formatter.rb +50 -0
  34. data/lib/gli/commands/help_modules/text_wrapper.rb +53 -0
  35. data/lib/gli/commands/initconfig.rb +67 -0
  36. data/lib/{support → gli/commands}/scaffold.rb +150 -34
  37. data/lib/gli/dsl.rb +194 -0
  38. data/lib/gli/exceptions.rb +13 -4
  39. data/lib/gli/flag.rb +30 -41
  40. data/lib/gli/gli_option_parser.rb +98 -0
  41. data/lib/gli/option_parser_factory.rb +44 -0
  42. data/lib/gli/options.rb +2 -1
  43. data/lib/gli/switch.rb +19 -51
  44. data/lib/gli/terminal.rb +30 -20
  45. data/lib/gli/version.rb +5 -0
  46. data/test/apps/README.md +2 -0
  47. data/test/apps/todo/Gemfile +2 -0
  48. data/test/apps/todo/README.rdoc +6 -0
  49. data/test/apps/todo/Rakefile +23 -0
  50. data/test/apps/todo/bin/todo +52 -0
  51. data/test/apps/todo/lib/todo/commands/create.rb +22 -0
  52. data/test/apps/todo/lib/todo/commands/list.rb +53 -0
  53. data/test/apps/todo/lib/todo/commands/ls.rb +47 -0
  54. data/test/apps/todo/lib/todo/version.rb +3 -0
  55. data/test/apps/todo/test/tc_nothing.rb +14 -0
  56. data/test/apps/todo/todo.gemspec +23 -0
  57. data/test/apps/todo/todo.rdoc +5 -0
  58. data/test/config.yaml +10 -0
  59. data/test/fake_std_out.rb +30 -0
  60. data/test/gli.reek +122 -0
  61. data/test/init_simplecov.rb +8 -0
  62. data/test/option_test_helper.rb +13 -0
  63. data/test/roodi.yaml +18 -0
  64. data/test/tc_command.rb +260 -0
  65. data/test/tc_compount_command.rb +22 -0
  66. data/test/tc_flag.rb +56 -0
  67. data/test/tc_gli.rb +611 -0
  68. data/test/tc_help.rb +223 -0
  69. data/test/tc_options.rb +31 -0
  70. data/test/tc_subcommands.rb +162 -0
  71. data/test/tc_switch.rb +57 -0
  72. data/test/tc_terminal.rb +97 -0
  73. data/test/test_helper.rb +13 -0
  74. metadata +318 -49
  75. data/lib/gli_version.rb +0 -3
  76. data/lib/support/help.rb +0 -179
  77. data/lib/support/initconfig.rb +0 -34
  78. data/lib/support/rdoc.rb +0 -119
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+ require 'tempfile'
3
+
4
+ class TC_testCompounCommand < Clean::Test::TestCase
5
+ include TestHelper
6
+
7
+ test_that "when we create a CompoundCommand where some commands are missing, we get an exception" do
8
+ Given {
9
+ @name = any_string
10
+ @unknown_name = any_string
11
+ @existing_command = OpenStruct.new(:name => @name)
12
+ @base = OpenStruct.new( :commands => { @name => @existing_command })
13
+ }
14
+ When {
15
+ @code = lambda { GLI::Commands::CompoundCommand.new(@base,{:foo => [@name,@unknown_name]}) }
16
+ }
17
+ Then {
18
+ ex = assert_raises(RuntimeError,&@code)
19
+ assert_match /#{@unknown_name}/,ex.message
20
+ }
21
+ end
22
+ end
data/test/tc_flag.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'test_helper'
2
+
3
+ class TC_testFlag < Clean::Test::TestCase
4
+ include TestHelper
5
+ include GLI
6
+
7
+ def test_basics_simple
8
+ Given flag_with_names(:f)
9
+ Then attributes_should_be_set
10
+ And name_should_be(:f)
11
+ And aliases_should_be(nil)
12
+ end
13
+
14
+ def test_basics_kinda_complex
15
+ Given flag_with_names([:f])
16
+ Then attributes_should_be_set
17
+ And name_should_be(:f)
18
+ And aliases_should_be(nil)
19
+ end
20
+
21
+ def test_basics_complex
22
+ Given flag_with_names([:f,:file,:filename])
23
+ Then attributes_should_be_set
24
+ And name_should_be(:f)
25
+ And aliases_should_be([:file,:filename])
26
+ And {
27
+ assert_equal ["-f VAL","--file VAL","--filename VAL",/foobar/,Float],@flag.arguments_for_option_parser
28
+ }
29
+ end
30
+
31
+ def flag_with_names(names)
32
+ lambda do
33
+ @options = {
34
+ :desc => 'Filename',
35
+ :long_desc => 'The Filename',
36
+ :arg_name => 'file',
37
+ :default_value => '~/.blah.rc',
38
+ :must_match => /foobar/,
39
+ :type => Float,
40
+ }
41
+ @flag = Flag.new(names,@options)
42
+ @cli_option = @flag
43
+ end
44
+ end
45
+
46
+ def attributes_should_be_set
47
+ lambda {
48
+ assert_equal(@options[:desc],@flag.description)
49
+ assert_equal(@options[:long_desc],@flag.long_description)
50
+ assert_equal(@options[:default_value],@flag.default_value)
51
+ assert_equal(@options[:must_match],@flag.must_match)
52
+ assert_equal(@options[:type],@flag.type)
53
+ assert(@flag.usage != nil)
54
+ }
55
+ end
56
+ end
data/test/tc_gli.rb ADDED
@@ -0,0 +1,611 @@
1
+ # 1.9 adds realpath to resolve symlinks; 1.8 doesn't
2
+ # have this method, so we add it so we get resolved symlinks
3
+ # and compatibility
4
+ unless File.respond_to? :realpath
5
+ class File
6
+ def self.realpath path
7
+ return realpath(File.readlink(path)) if symlink?(path)
8
+ path
9
+ end
10
+ end
11
+ end
12
+
13
+ require 'test_helper'
14
+
15
+ class TC_testGLI < Clean::Test::TestCase
16
+ include TestHelper
17
+ include GLI
18
+
19
+ def setup
20
+ @app = CLIApp.new
21
+ @config_file = File.expand_path(File.dirname(File.realpath(__FILE__)) + '/new_config.yaml')
22
+ @gli_debug = ENV['GLI_DEBUG']
23
+ @fake_stderr = FakeStdOut.new
24
+ @app.error_device=@fake_stderr
25
+ ENV.delete('GLI_DEBUG')
26
+ end
27
+
28
+ def teardown
29
+ File.delete(@config_file) if File.exist?(@config_file)
30
+ ENV['GLI_DEBUG'] = @gli_debug
31
+ @app.error_device=$stderr
32
+ end
33
+
34
+ def test_flag_create
35
+ @app.reset
36
+ do_test_flag_create(@app)
37
+ do_test_flag_create(Command.new(:names => :f))
38
+ end
39
+
40
+ def test_create_commands_using_strings
41
+ @app.reset
42
+ @app.flag ['f','flag']
43
+ @app.switch ['s','some-switch']
44
+ @app.command 'command','command-with-dash' do |c|
45
+ end
46
+ assert @app.commands.include? :command
47
+ assert @app.flags.include? :f
48
+ assert @app.switches.include? :s
49
+ assert @app.commands[:command].aliases.include? :'command-with-dash'
50
+ assert @app.flags[:f].aliases.include? :flag
51
+ assert @app.switches[:s].aliases.include? :'some-switch'
52
+ end
53
+
54
+ def test_flag_with_space_barfs
55
+ @app.reset
56
+ assert_raises(ArgumentError) { @app.flag ['some flag'] }
57
+ assert_raises(ArgumentError) { @app.flag ['f','some flag'] }
58
+ assert_raises(ArgumentError) { @app.switch ['some switch'] }
59
+ assert_raises(ArgumentError) { @app.switch ['f','some switch'] }
60
+ assert_raises(ArgumentError) { @app.command ['some command'] }
61
+ assert_raises(ArgumentError) { @app.command ['f','some command'] }
62
+ end
63
+
64
+ def test_init_from_config
65
+ failure = nil
66
+ @app.reset
67
+ @app.config_file(File.expand_path(File.dirname(File.realpath(__FILE__)) + '/config.yaml'))
68
+ @app.flag :f
69
+ @app.switch :s
70
+ @app.flag :g
71
+ called = false
72
+ @app.command :command do |c|
73
+ c.flag :f
74
+ c.switch :s
75
+ c.flag :g
76
+ c.action do |g,o,a|
77
+ begin
78
+ called = true
79
+ assert_equal "foo",g[:f]
80
+ assert_equal "bar",o[:g]
81
+ assert !g[:g]
82
+ assert !o[:f]
83
+ assert !g[:s]
84
+ assert o[:s]
85
+ rescue Exception => ex
86
+ failure = ex
87
+ end
88
+ end
89
+ end
90
+ @app.run(['command'])
91
+ assert called
92
+ raise failure if !failure.nil?
93
+ end
94
+
95
+ def test_command_line_overrides_config
96
+ failure = nil
97
+ @app.reset
98
+ @app.config_file(File.expand_path(File.dirname(File.realpath(__FILE__)) + '/config.yaml'))
99
+ @app.flag :f
100
+ @app.switch :s
101
+ @app.flag :g
102
+ @app.switch :bleorgh
103
+ called = false
104
+ @app.command :command do |c|
105
+ c.flag :f
106
+ c.switch :s
107
+ c.flag :g
108
+ c.action do |g,o,a|
109
+ begin
110
+ called = true
111
+ assert_equal "baaz",o[:g]
112
+ assert_equal "bar",g[:f]
113
+ assert !g[:g],o.inspect
114
+ assert !o[:f],o.inspect
115
+ assert !g[:s],o.inspect
116
+ assert o[:s],o.inspect
117
+ assert g[:bleorgh] != nil,"Expected :bleorgh to have a value"
118
+ assert g[:bleorgh] == false,"Expected :bleorgh to be false"
119
+ rescue Exception => ex
120
+ failure = ex
121
+ end
122
+ end
123
+ end
124
+ assert_equal 0,@app.run(%w(-f bar --no-bleorgh command -g baaz)),@fake_stderr.to_s
125
+ assert called
126
+ raise failure if !failure.nil?
127
+ end
128
+
129
+ def test_no_overwrite_config
130
+ config_file = File.expand_path(File.dirname(File.realpath(__FILE__)) + '/config.yaml')
131
+ config_file_contents = File.read(config_file)
132
+ @app.reset
133
+ @app.config_file(config_file)
134
+ assert_equal 1,@app.run(['initconfig'])
135
+ assert @fake_stderr.strings.grep(/--force/),@fake_stderr.strings.inspect
136
+ config_file_contents_after = File.read(config_file)
137
+ assert_equal(config_file_contents,config_file_contents_after)
138
+ end
139
+
140
+ def test_config_file_name
141
+ @app.reset
142
+ file = @app.config_file("foo")
143
+ assert_equal(Etc.getpwuid.dir + "/foo",file)
144
+ file = @app.config_file("/foo")
145
+ assert_equal "/foo",file
146
+ init_command = @app.commands[:initconfig]
147
+ assert init_command
148
+ end
149
+
150
+ def test_initconfig_command
151
+ @app.reset
152
+ @app.config_file(@config_file)
153
+ @app.flag :f
154
+ @app.switch :s
155
+ @app.switch :w
156
+ @app.flag :bigflag
157
+ @app.flag :biggestflag
158
+ @app.command :foo do |c|
159
+ end
160
+ @app.command :bar do |c|
161
+ end
162
+ @app.command :blah do |c|
163
+ end
164
+ @app.on_error do |ex|
165
+ raise ex
166
+ end
167
+ @app.run(['-f','foo','-s','--bigflag=bleorgh','initconfig'])
168
+
169
+ written_config = File.open(@config_file) { |f| YAML::load(f) }
170
+
171
+ assert_equal 'foo',written_config[:f]
172
+ assert_equal 'bleorgh',written_config[:bigflag]
173
+ assert written_config[:s]
174
+ assert !written_config[:w]
175
+ assert_nil written_config[:biggestflag]
176
+ assert written_config[GLI::InitConfig::COMMANDS_KEY]
177
+ assert written_config[GLI::InitConfig::COMMANDS_KEY][:foo]
178
+ assert written_config[GLI::InitConfig::COMMANDS_KEY][:bar]
179
+ assert written_config[GLI::InitConfig::COMMANDS_KEY][:blah]
180
+
181
+ end
182
+
183
+ def test_initconfig_permissions
184
+ @app.reset
185
+ @app.config_file(@config_file)
186
+ @app.run(['initconfig'])
187
+ oct_mode = "%o" % File.stat(@config_file).mode
188
+ assert_match /0600$/, oct_mode
189
+ end
190
+
191
+ def do_test_flag_create(object)
192
+ description = 'this is a description'
193
+ long_desc = 'this is a very long description'
194
+ object.desc description
195
+ object.long_desc long_desc
196
+ object.arg_name 'filename'
197
+ object.default_value '~/.blah.rc'
198
+ object.flag :f
199
+ assert (object.flags[:f] )
200
+ assert_equal(description,object.flags[:f].description)
201
+ assert_equal(long_desc,object.flags[:f].long_description)
202
+ assert(nil != object.flags[:f].usage)
203
+ assert(object.usage != nil) if object.respond_to? :usage;
204
+ end
205
+
206
+ def test_switch_create
207
+ @app.reset
208
+ do_test_switch_create(@app)
209
+ do_test_switch_create(Command.new(:names => :f))
210
+ end
211
+
212
+ def test_switch_create_twice
213
+ @app.reset
214
+ do_test_switch_create_twice(@app)
215
+ do_test_switch_create_twice(Command.new(:names => :f))
216
+ end
217
+
218
+ def test_all_aliases_in_options
219
+ @app.reset
220
+ @app.on_error { |ex| raise ex }
221
+ @app.flag [:f,:flag,:'big-flag-name']
222
+ @app.switch [:s,:switch,:'big-switch-name']
223
+ @app.command [:com,:command] do |c|
224
+ c.flag [:g,:gflag]
225
+ c.switch [:h,:hswitch]
226
+ c.action do |global,options,args|
227
+ assert_equal 'foo',global[:f]
228
+ assert_equal global[:f],global[:flag]
229
+ assert_equal global[:f],global[:'big-flag-name']
230
+
231
+ assert global[:s]
232
+ assert global[:switch]
233
+ assert global[:'big-switch-name']
234
+
235
+ assert_equal 'bar',options[:g]
236
+ assert_equal options[:g],options[:gflag]
237
+
238
+ assert options[:h]
239
+ assert options[:hswitch]
240
+ end
241
+ end
242
+ @app.run(%w(-f foo -s command -g bar -h some_arg))
243
+ end
244
+
245
+ def test_use_hash_by_default
246
+ @app.reset
247
+ @app.switch :g
248
+ @app.command :command do |c|
249
+ c.switch :f
250
+ c.action do |global,options,args|
251
+ assert_equal Hash,global.class
252
+ assert_equal Hash,options.class
253
+ end
254
+ end
255
+ @app.run(%w(-g command -f))
256
+ end
257
+
258
+ def test_flag_array_of_options_global
259
+ @app.reset
260
+ @app.flag :foo, :must_match => ['bar','blah','baz']
261
+ @app.command :command do |c|
262
+ c.action do
263
+ end
264
+ end
265
+ assert_equal 64,@app.run(%w(--foo=cruddo command)),@fake_stderr.to_s
266
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
267
+ assert_equal 0,@app.run(%w(--foo=blah command)),@fake_stderr.to_s
268
+ end
269
+
270
+ def test_flag_hash_of_options_global
271
+ @app.reset
272
+ @app.flag :foo, :must_match => { 'bar' => "BAR", 'blah' => "BLAH" }
273
+ @foo_arg_value = nil
274
+ @app.command :command do |c|
275
+ c.action do |g,o,a|
276
+ @foo_arg_value = g[:foo]
277
+ end
278
+ end
279
+ assert_equal 64,@app.run(%w(--foo=cruddo command)),@fake_stderr.to_s
280
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
281
+ assert_equal 0,@app.run(%w(--foo=blah command)),@fake_stderr.to_s
282
+ assert_equal 'BLAH',@foo_arg_value
283
+ end
284
+
285
+ def test_flag_regexp_global
286
+ @app.reset
287
+ @app.flag :foo, :must_match => /bar/
288
+ @app.command :command do |c|
289
+ c.action do
290
+ end
291
+ end
292
+ assert_equal 64,@app.run(%w(--foo=cruddo command)),@fake_stderr.to_s
293
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
294
+ end
295
+
296
+ def test_flag_regexp_global_short_form
297
+ @app.reset
298
+ @app.flag :f, :must_match => /bar/
299
+ @app.command :command do |c|
300
+ c.action do
301
+ end
302
+ end
303
+ assert_equal 64,@app.run(%w(-f cruddo command)),@fake_stderr.to_s
304
+ assert @fake_stderr.contained?(/error: invalid argument: -f cruddo/),"STDERR was:\n" + @fake_stderr.to_s
305
+ end
306
+
307
+ def test_flag_regexp_command
308
+ @app.reset
309
+ @app.command :command do |c|
310
+ c.flag :foo, :must_match => /bar/
311
+ c.action do
312
+ end
313
+ end
314
+ assert_equal 64,@app.run(%w(command --foo=cruddo)),@fake_stderr.to_s
315
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
316
+ end
317
+
318
+ def test_use_openstruct
319
+ @app.reset
320
+ @app.switch :g
321
+ @app.use_openstruct true
322
+ @app.command :command do |c|
323
+ c.switch :f
324
+ c.action do |global,options,args|
325
+ assert_equal GLI::Options,global.class
326
+ assert_equal GLI::Options,options.class
327
+ end
328
+ end
329
+ @app.run(%w(-g command -f))
330
+ end
331
+
332
+ def test_repeated_option_names
333
+ @app.reset
334
+ @app.on_error { |ex| raise ex }
335
+ @app.flag [:f,:flag]
336
+ assert_raises(ArgumentError) { @app.switch [:foo,:flag] }
337
+ assert_raises(ArgumentError) { @app.switch [:f] }
338
+
339
+ @app.switch [:x,:y]
340
+ assert_raises(ArgumentError) { @app.flag [:x] }
341
+ assert_raises(ArgumentError) { @app.flag [:y] }
342
+
343
+ # This shouldn't raise; :help is special
344
+ @app.switch :help
345
+ end
346
+
347
+ def test_repeated_option_names_on_command
348
+ @app.reset
349
+ @app.on_error { |ex| raise ex }
350
+ @app.command :command do |c|
351
+ c.flag [:f,:flag]
352
+ assert_raises(ArgumentError) { c.switch [:foo,:flag] }
353
+ assert_raises(ArgumentError) { c.switch [:f] }
354
+ assert_raises(ArgumentError) { c.flag [:foo,:flag] }
355
+ assert_raises(ArgumentError) { c.flag [:f] }
356
+ end
357
+ @app.command :command3 do |c|
358
+ c.switch [:s,:switch]
359
+ assert_raises(ArgumentError) { c.switch [:switch] }
360
+ assert_raises(ArgumentError) { c.switch [:s] }
361
+ assert_raises(ArgumentError) { c.flag [:switch] }
362
+ assert_raises(ArgumentError) { c.flag [:s] }
363
+ end
364
+ end
365
+
366
+ def test_two_flags
367
+ @app.reset
368
+ @app.on_error do |ex|
369
+ raise ex
370
+ end
371
+ @app.command [:foo] do |c|
372
+ c.flag :i
373
+ c.flag :s
374
+ c.action do |g,o,a|
375
+ assert_equal "5", o[:i]
376
+ assert_equal "a", o[:s]
377
+ end
378
+ end
379
+ @app.run(['foo', '-i','5','-s','a'])
380
+ end
381
+
382
+ def test_two_flags_with_a_default
383
+ @app.reset
384
+ @app.on_error do |ex|
385
+ raise ex
386
+ end
387
+ @app.command [:foo] do |c|
388
+ c.default_value "1"
389
+ c.flag :i
390
+ c.flag :s
391
+ c.action do |g,o,a|
392
+ assert_equal "5", o[:i]
393
+ assert_equal "a", o[:s]
394
+ end
395
+ end
396
+ @app.run(['foo', '-i','5','-s','a'])
397
+ end
398
+
399
+ def test_two_flags_using_equals_with_a_default
400
+ @app.reset
401
+ @app.on_error do |ex|
402
+ raise ex
403
+ end
404
+ @app.command [:foo] do |c|
405
+ c.default_value "1"
406
+ c.flag :i
407
+ c.flag :s
408
+ c.action do |g,o,a|
409
+ assert_equal "5", o[:i],o.inspect
410
+ assert_equal "a", o[:s],o.inspect
411
+ end
412
+ end
413
+ @app.run(['foo', '-i5','-sa'])
414
+ end
415
+
416
+ def test_exits_zero_on_success
417
+ assert_equal 0,@app.run([]),@fake_stderr.to_s
418
+ end
419
+
420
+ def test_exits_nonzero_on_bad_command_line
421
+ @app.reset
422
+ @app.on_error { true }
423
+ assert_equal 64,@app.run(['asdfasdfasdf'])
424
+ end
425
+
426
+ def test_exists_nonzero_on_raise_from_command
427
+ @app.reset
428
+ @app.on_error { true }
429
+ @app.command(:foo) do |c|
430
+ c.action do |g,o,a|
431
+ raise "Problem"
432
+ end
433
+ end
434
+ assert_equal 1,@app.run(['foo'])
435
+ end
436
+
437
+ def test_exits_nonzero_with_custom_exception
438
+ @app.reset
439
+ @app.on_error { true }
440
+ @app.command(:foo) do |c|
441
+ c.action do |g,o,a|
442
+ raise CustomExit.new("Problem",45)
443
+ end
444
+ end
445
+ assert_equal 45,@app.run(['foo'])
446
+ end
447
+
448
+ def test_exits_nonzero_with_exit_method
449
+ @app.reset
450
+ @app.on_error { true }
451
+ @app.command(:foo) do |c|
452
+ c.action do |g,o,a|
453
+ @app.exit_now!("Problem",45)
454
+ end
455
+ end
456
+ assert_equal 45,@app.run(['foo'])
457
+ end
458
+
459
+ def test_exits_nonzero_with_exit_method_by_default
460
+ @app.reset
461
+ @app.on_error { true }
462
+ @app.command(:foo) do |c|
463
+ c.action do |g,o,a|
464
+ @app.exit_now!("Problem")
465
+ end
466
+ end
467
+ assert_equal 1,@app.run(['foo'])
468
+ end
469
+
470
+ def test_help_now_exits_and_shows_help
471
+ @app.reset
472
+ @app.on_error { true }
473
+ @app.command(:foo) do |c|
474
+ c.action do |g,o,a|
475
+ @app.help_now!("Problem")
476
+ end
477
+ end
478
+ assert_equal 64,@app.run(['foo']),@fake_stderr.strings.join("\n")
479
+ end
480
+
481
+ def test_custom_exception_causes_error_to_be_printed_to_stderr
482
+ @app.reset
483
+ @app.on_error { true }
484
+ error_message = "Something went wrong"
485
+ @app.command(:foo) do |c|
486
+ c.action do |g,o,a|
487
+ raise error_message
488
+ end
489
+ end
490
+ @app.run(['foo'])
491
+ assert @fake_stderr.strings.include?("error: #{error_message}"),"STDERR was:\n" + @fake_stderr.to_s
492
+ end
493
+
494
+ def test_gli_debug_overrides_error_hiding
495
+ ENV['GLI_DEBUG'] = 'true'
496
+
497
+ @app.reset
498
+ @app.on_error { true }
499
+ @app.command(:foo) do |c|
500
+ c.action do |g,o,a|
501
+ @app.exit_now!("Problem",45)
502
+ end
503
+ end
504
+
505
+ assert_raises(CustomExit) { @app.run(['foo']) }
506
+ end
507
+
508
+ class ConvertMe
509
+ attr_reader :value
510
+ def initialize(value)
511
+ @value = value
512
+ end
513
+ end
514
+
515
+ def test_that_we_can_add_new_casts_for_flags
516
+ @app.reset
517
+ @app.accept(ConvertMe) do |value|
518
+ ConvertMe.new(value)
519
+ end
520
+ @app.flag :foo, :type => ConvertMe
521
+
522
+ @foo = nil
523
+ @baz = nil
524
+
525
+ @app.command(:bar) do |c|
526
+ c.flag :baz, :type => ConvertMe
527
+ c.action do |g,o,a|
528
+ @foo = g[:foo]
529
+ @baz = o[:baz]
530
+ end
531
+ end
532
+
533
+ assert_equal 0,@app.run(['--foo','blah','bar','--baz=crud']),@fake_stderr.to_s
534
+
535
+ assert @foo.kind_of?(ConvertMe),"Expected a ConvertMe, but get a #{@foo.class}"
536
+ assert_equal 'blah',@foo.value
537
+
538
+ assert @baz.kind_of?(ConvertMe),"Expected a ConvertMe, but get a #{@foo.class}"
539
+ assert_equal 'crud',@baz.value
540
+ end
541
+
542
+ private
543
+
544
+ def do_test_flag_create(object)
545
+ description = 'this is a description'
546
+ long_desc = 'this is a very long description'
547
+ object.desc description
548
+ object.long_desc long_desc
549
+ object.arg_name 'filename'
550
+ object.default_value '~/.blah.rc'
551
+ object.flag :f
552
+ assert (object.flags[:f] )
553
+ assert_equal(description,object.flags[:f].description)
554
+ assert_equal(long_desc,object.flags[:f].long_description)
555
+ assert(nil != object.flags[:f].usage)
556
+ assert(object.usage != nil) if object.respond_to? :usage
557
+ end
558
+
559
+ def do_test_switch_create(object)
560
+ do_test_switch_create_classic(object)
561
+ do_test_switch_create_compact(object)
562
+ end
563
+
564
+ def some_descriptions
565
+ lambda {
566
+ @description = 'this is a description'
567
+ @long_description = 'this is a very long description'
568
+ }
569
+ end
570
+
571
+ def assert_switch_was_made(object,switch)
572
+ lambda {
573
+ assert object.switches[switch]
574
+ assert_equal @description,object.switches[switch].description,"For switch #{switch}"
575
+ assert_equal @long_description,object.switches[switch].long_description,"For switch #{switch}"
576
+ assert(object.usage != nil) if object.respond_to? :usage
577
+ }
578
+ end
579
+
580
+ def do_test_switch_create_classic(object)
581
+ Given some_descriptions
582
+ When {
583
+ object.desc @description
584
+ object.long_desc @long_description
585
+ object.switch :f
586
+ }
587
+ Then assert_switch_was_made(object,:f)
588
+ end
589
+
590
+ def do_test_switch_create_compact(object)
591
+ Given some_descriptions
592
+ When {
593
+ object.switch :g, :desc => @description, :long_desc => @long_description
594
+ }
595
+ Then assert_switch_was_made(object,:g)
596
+ end
597
+
598
+ def do_test_switch_create_twice(object)
599
+ description = 'this is a description'
600
+ object.desc description
601
+ object.switch :f
602
+ assert (object.switches[:f] )
603
+ assert_equal(description,object.switches[:f].description)
604
+ object.switch :g
605
+ assert (object.switches[:g])
606
+ assert_equal(nil,object.switches[:g].description)
607
+ assert(object.usage != nil) if object.respond_to? :usage
608
+ end
609
+
610
+
611
+ end