gli 1.6.0 → 2.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
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