gli_aziz_light 2.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +17 -0
  6. data/CONTRIBUTING.md +23 -0
  7. data/Gemfile +8 -0
  8. data/LICENSE.txt +201 -0
  9. data/ObjectModel.graffle +1191 -0
  10. data/README.rdoc +109 -0
  11. data/Rakefile +126 -0
  12. data/bin/gli +59 -0
  13. data/bin/report_on_rake_results +10 -0
  14. data/bin/test_all_rubies.sh +6 -0
  15. data/features/gli_executable.feature +90 -0
  16. data/features/gli_init.feature +232 -0
  17. data/features/step_definitions/gli_executable_steps.rb +18 -0
  18. data/features/step_definitions/gli_init_steps.rb +11 -0
  19. data/features/step_definitions/todo_steps.rb +88 -0
  20. data/features/support/env.rb +53 -0
  21. data/features/todo.feature +413 -0
  22. data/features/todo_legacy.feature +128 -0
  23. data/gli.cheat +95 -0
  24. data/gli.gemspec +34 -0
  25. data/gli.rdoc +73 -0
  26. data/lib/gli.rb +35 -0
  27. data/lib/gli/app.rb +286 -0
  28. data/lib/gli/app_support.rb +341 -0
  29. data/lib/gli/command.rb +171 -0
  30. data/lib/gli/command_finder.rb +41 -0
  31. data/lib/gli/command_line_option.rb +34 -0
  32. data/lib/gli/command_line_token.rb +63 -0
  33. data/lib/gli/command_support.rb +181 -0
  34. data/lib/gli/commands/compound_command.rb +42 -0
  35. data/lib/gli/commands/doc.rb +231 -0
  36. data/lib/gli/commands/help.rb +95 -0
  37. data/lib/gli/commands/help_modules/arg_name_formatter.rb +20 -0
  38. data/lib/gli/commands/help_modules/command_finder.rb +60 -0
  39. data/lib/gli/commands/help_modules/command_help_format.rb +156 -0
  40. data/lib/gli/commands/help_modules/global_help_format.rb +70 -0
  41. data/lib/gli/commands/help_modules/help_completion_format.rb +31 -0
  42. data/lib/gli/commands/help_modules/list_formatter.rb +23 -0
  43. data/lib/gli/commands/help_modules/one_line_wrapper.rb +18 -0
  44. data/lib/gli/commands/help_modules/options_formatter.rb +49 -0
  45. data/lib/gli/commands/help_modules/text_wrapper.rb +53 -0
  46. data/lib/gli/commands/help_modules/tty_only_wrapper.rb +23 -0
  47. data/lib/gli/commands/help_modules/verbatim_wrapper.rb +16 -0
  48. data/lib/gli/commands/initconfig.rb +74 -0
  49. data/lib/gli/commands/rdoc_document_listener.rb +116 -0
  50. data/lib/gli/commands/scaffold.rb +401 -0
  51. data/lib/gli/dsl.rb +226 -0
  52. data/lib/gli/exceptions.rb +71 -0
  53. data/lib/gli/flag.rb +68 -0
  54. data/lib/gli/gli_option_block_parser.rb +84 -0
  55. data/lib/gli/gli_option_parser.rb +156 -0
  56. data/lib/gli/option_parser_factory.rb +81 -0
  57. data/lib/gli/option_parsing_result.rb +21 -0
  58. data/lib/gli/options.rb +23 -0
  59. data/lib/gli/switch.rb +35 -0
  60. data/lib/gli/terminal.rb +101 -0
  61. data/lib/gli/version.rb +5 -0
  62. data/test/apps/README.md +2 -0
  63. data/test/apps/todo/Gemfile +2 -0
  64. data/test/apps/todo/README.rdoc +6 -0
  65. data/test/apps/todo/Rakefile +23 -0
  66. data/test/apps/todo/bin/todo +63 -0
  67. data/test/apps/todo/lib/todo/commands/create.rb +24 -0
  68. data/test/apps/todo/lib/todo/commands/list.rb +63 -0
  69. data/test/apps/todo/lib/todo/commands/ls.rb +47 -0
  70. data/test/apps/todo/lib/todo/commands/make.rb +52 -0
  71. data/test/apps/todo/lib/todo/version.rb +3 -0
  72. data/test/apps/todo/test/tc_nothing.rb +14 -0
  73. data/test/apps/todo/todo.gemspec +23 -0
  74. data/test/apps/todo/todo.rdoc +5 -0
  75. data/test/apps/todo_legacy/Gemfile +2 -0
  76. data/test/apps/todo_legacy/README.rdoc +6 -0
  77. data/test/apps/todo_legacy/Rakefile +23 -0
  78. data/test/apps/todo_legacy/bin/todo +61 -0
  79. data/test/apps/todo_legacy/lib/todo/commands/create.rb +24 -0
  80. data/test/apps/todo_legacy/lib/todo/commands/list.rb +63 -0
  81. data/test/apps/todo_legacy/lib/todo/commands/ls.rb +47 -0
  82. data/test/apps/todo_legacy/lib/todo/version.rb +3 -0
  83. data/test/apps/todo_legacy/test/tc_nothing.rb +14 -0
  84. data/test/apps/todo_legacy/todo.gemspec +23 -0
  85. data/test/apps/todo_legacy/todo.rdoc +5 -0
  86. data/test/apps/todo_plugins/commands/third.rb +1 -0
  87. data/test/config.yaml +10 -0
  88. data/test/fake_std_out.rb +30 -0
  89. data/test/init_simplecov.rb +8 -0
  90. data/test/option_test_helper.rb +13 -0
  91. data/test/tc_command.rb +508 -0
  92. data/test/tc_compound_command.rb +22 -0
  93. data/test/tc_doc.rb +325 -0
  94. data/test/tc_flag.rb +62 -0
  95. data/test/tc_gli.rb +773 -0
  96. data/test/tc_help.rb +387 -0
  97. data/test/tc_options.rb +43 -0
  98. data/test/tc_subcommand_parsing.rb +104 -0
  99. data/test/tc_subcommands.rb +260 -0
  100. data/test/tc_switch.rb +55 -0
  101. data/test/tc_terminal.rb +100 -0
  102. data/test/tc_verbatim_wrapper.rb +36 -0
  103. data/test/test_helper.rb +20 -0
  104. metadata +330 -0
@@ -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
@@ -0,0 +1,325 @@
1
+ require 'test_helper'
2
+ require 'pp'
3
+
4
+ class String
5
+ def blank?
6
+ self.strip.length == 0
7
+ end
8
+ end
9
+
10
+ class NilClass
11
+ def blank?
12
+ true
13
+ end
14
+ end
15
+
16
+ class Object
17
+ def blank?
18
+ false
19
+ end
20
+ end
21
+
22
+ class TC_testDoc < Clean::Test::TestCase
23
+ include TestHelper
24
+
25
+ class TestApp
26
+ include GLI::App
27
+ end
28
+
29
+ class TestListener
30
+ @@last = nil
31
+ def self.last
32
+ @@last
33
+ end
34
+ def initialize(*ignored)
35
+ @stringio = StringIO.new
36
+ @indent = ''
37
+ @@last = self
38
+ end
39
+ def options
40
+ end
41
+ def end_options
42
+ end
43
+ def commands
44
+ end
45
+ def end_commands
46
+ end
47
+ def beginning
48
+ @stringio << 'BEGIN' << "\n"
49
+ end
50
+
51
+ def ending
52
+ @stringio << 'END' << "\n"
53
+ end
54
+
55
+ def program_desc(desc)
56
+ @stringio << desc << "\n"
57
+ end
58
+
59
+ def program_long_desc(desc)
60
+ @stringio << desc << "\n"
61
+ end
62
+
63
+ def version(version)
64
+ @stringio << version << "\n"
65
+ end
66
+
67
+ def default_command(name)
68
+ @stringio << @indent << "default_command: " << name << "\n"
69
+ end
70
+
71
+ def flag(name,aliases,desc,long_desc,default_value,arg_name,must_match,type)
72
+ @stringio << @indent << "flag: " << name << "\n"
73
+ @indent += ' '
74
+ @stringio << @indent << "aliases: " << aliases.join(',') << "\n" unless aliases.empty?
75
+ @stringio << @indent << "desc: " << desc << "\n" unless desc.blank?
76
+ @stringio << @indent << "long_desc: " << long_desc << "\n" unless long_desc.blank?
77
+ @stringio << @indent << "default_value: " << default_value << "\n" unless default_value.blank?
78
+ @stringio << @indent << "arg_name: " << arg_name << "\n" unless arg_name.blank?
79
+ @indent.gsub!(/ $/,'')
80
+ end
81
+
82
+ def switch(name,aliases,desc,long_desc,negatable)
83
+ @stringio << @indent << "switch: " << name << "\n"
84
+ @indent += ' '
85
+ @stringio << @indent << "aliases: " << aliases.join(',') << "\n" unless aliases.empty?
86
+ @stringio << @indent << "desc: " << desc << "\n" unless desc.blank?
87
+ @stringio << @indent << "long_desc: " << long_desc << "\n" unless long_desc.blank?
88
+ @stringio << @indent << "negatable: " << negatable << "\n" unless negatable.blank?
89
+ @indent.gsub!(/ $/,'')
90
+ end
91
+
92
+ def command(name,aliases,desc,long_desc,arg_name)
93
+ @stringio << @indent << "command: " << name << "\n"
94
+ @indent += ' '
95
+ @stringio << @indent << "aliases: " << aliases.join(',') << "\n" unless aliases.empty?
96
+ @stringio << @indent << "desc: " << desc << "\n" unless desc.blank?
97
+ @stringio << @indent << "long_desc: " << long_desc << "\n" unless long_desc.blank?
98
+ @stringio << @indent << "arg_name: " << arg_name << "\n" unless arg_name.blank?
99
+ end
100
+
101
+ def end_command(name)
102
+ @indent.gsub!(/ $/,'')
103
+ @stringio << @indent << "end #{name}" << "\n"
104
+ end
105
+
106
+ def to_s
107
+ @stringio.string
108
+ end
109
+ end
110
+
111
+ def setup
112
+ @@counter = -1 # we pre-increment so this makes 0 first
113
+ end
114
+
115
+ test_that "a GLI app with documentation gets the callbacks for each element" do
116
+ Given :the_test_app
117
+ And :the_expected_output
118
+ And {
119
+ @documenter = GLI::Commands::Doc.new(@app)
120
+ @listener = TestListener.new
121
+ }
122
+ When {
123
+ @documenter.document(@listener)
124
+ }
125
+ Then {
126
+ lines_expected = @string.split(/\n/)
127
+ lines_got = @listener.to_s.split(/\n/)
128
+ lines_expected.zip(lines_got).each_with_index do |(expected,got),index|
129
+ assert_equal expected,got,"At index #{index}"
130
+ end
131
+ }
132
+ end
133
+
134
+ test_that "the doc command works as a GLI command" do
135
+ Given :the_test_app
136
+ And :the_expected_output
137
+ And {
138
+ @documenter = GLI::Commands::Doc.new(@app)
139
+ @listener = TestListener.new
140
+ }
141
+ When {
142
+ @documenter.execute({},{:format => "TC_testDoc::TestListener"},[])
143
+ }
144
+ Then {
145
+ lines_expected = @string.split(/\n/)
146
+ lines_got = TestListener.last.to_s.split(/\n/)
147
+ lines_expected.zip(lines_got).each_with_index do |(expected,got),index|
148
+ assert_equal expected,got,"At index #{index}"
149
+ end
150
+ }
151
+ end
152
+
153
+ private
154
+
155
+ @@counter = 1
156
+ def self.counter
157
+ @@counter += 1
158
+ @@counter
159
+ end
160
+
161
+ def the_test_app
162
+ @app = TestApp.new
163
+ @app.instance_eval do
164
+ program_desc "program desc"
165
+ program_long_desc "program long desc"
166
+ version "1.3.4"
167
+
168
+ TC_testDoc.flag_with_everything_specified(self)
169
+ TC_testDoc.flag_with_everything_omitted(self)
170
+ TC_testDoc.switch_with_everything_specified(self)
171
+ TC_testDoc.switch_with_everything_omitted(self)
172
+
173
+ desc "command desc"
174
+ long_desc "command long desc"
175
+ arg_name "cmd_arg_name"
176
+ command [:command1,:com1] do |c|
177
+ TC_testDoc.flag_with_everything_specified(c)
178
+ TC_testDoc.flag_with_everything_omitted(c)
179
+ TC_testDoc.switch_with_everything_specified(c)
180
+ TC_testDoc.switch_with_everything_omitted(c)
181
+
182
+ c.desc "subcommand desc"
183
+ c.long_desc "subcommand long desc"
184
+ c.arg_name "subcmd_arg_name"
185
+ c.action { |g,o,a| }
186
+ c.command [:sub,:subcommand] do |sub|
187
+ TC_testDoc.flag_with_everything_specified(sub,:subflag)
188
+ TC_testDoc.flag_with_everything_omitted(sub,:subflag2)
189
+ TC_testDoc.switch_with_everything_specified(sub,:subswitch)
190
+ TC_testDoc.switch_with_everything_omitted(sub,:subswitch2)
191
+ sub.action { |g,o,a| }
192
+ end
193
+ c.command [:default] do |sub|
194
+ sub.action { |g,o,a| }
195
+ end
196
+ c.default_command :default
197
+ end
198
+
199
+ command [:command2,:com2] do |c|
200
+ c.action { |g,o,a| }
201
+ c.command [:sub2,:subcommand2] do |sub|
202
+ sub.action { |g,o,a| }
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def self.flag_with_everything_specified(on,name=[:f,:flag])
209
+ on.flag name,:desc => "flag desc #{counter}",
210
+ :long_desc => "flag long_desc #{counter}",
211
+ :default_value => "flag default_value #{counter}",
212
+ :arg_name => "flag_arg_name_#{counter}",
213
+ :must_match => /foo.*bar/,
214
+ :type => Array
215
+ end
216
+
217
+ def self.flag_with_everything_omitted(on,name=[:F,:flag2])
218
+ on.flag name
219
+ end
220
+
221
+ def self.switch_with_everything_specified(on,name=[:s,:switch])
222
+ on.switch name, :desc => "switch desc #{counter}",
223
+ :long_desc => "switch long_desc #{counter}",
224
+ :negatable => false
225
+ end
226
+
227
+ def self.switch_with_everything_omitted(on,name=[:S,:switch2])
228
+ on.switch name
229
+ end
230
+ def the_expected_output
231
+ # Oh yeah. Creating a string representing the structure of the calls.
232
+ @string =<<EOS
233
+ BEGIN
234
+ program desc
235
+ program long desc
236
+ 1.3.4
237
+ flag: F
238
+ aliases: flag2
239
+ arg_name: arg
240
+ flag: f
241
+ aliases: flag
242
+ desc: flag desc 0
243
+ long_desc: flag long_desc 1
244
+ default_value: flag default_value 2
245
+ arg_name: flag_arg_name_3
246
+ switch: S
247
+ aliases: switch2
248
+ negatable: true
249
+ switch: s
250
+ aliases: switch
251
+ desc: switch desc 4
252
+ long_desc: switch long_desc 5
253
+ negatable: false
254
+ switch: version
255
+ desc: Display the program version
256
+ negatable: false
257
+ command: command1
258
+ aliases: com1
259
+ desc: command desc
260
+ long_desc: command long desc
261
+ arg_name: cmd_arg_name
262
+ flag: F
263
+ aliases: flag2
264
+ arg_name: arg
265
+ flag: f
266
+ aliases: flag
267
+ desc: flag desc 6
268
+ long_desc: flag long_desc 7
269
+ default_value: flag default_value 8
270
+ arg_name: flag_arg_name_9
271
+ switch: S
272
+ aliases: switch2
273
+ negatable: true
274
+ switch: s
275
+ aliases: switch
276
+ desc: switch desc 10
277
+ long_desc: switch long_desc 11
278
+ negatable: false
279
+ command: default
280
+ default_command:
281
+ end default
282
+ command: sub
283
+ aliases: subcommand
284
+ desc: subcommand desc
285
+ long_desc: subcommand long desc
286
+ arg_name: subcmd_arg_name
287
+ flag: subflag
288
+ desc: flag desc 12
289
+ long_desc: flag long_desc 13
290
+ default_value: flag default_value 14
291
+ arg_name: flag_arg_name_15
292
+ flag: subflag2
293
+ arg_name: arg
294
+ switch: subswitch
295
+ desc: switch desc 16
296
+ long_desc: switch long_desc 17
297
+ negatable: false
298
+ switch: subswitch2
299
+ negatable: true
300
+ default_command:
301
+ end sub
302
+ default_command: default
303
+ end command1
304
+ command: command2
305
+ aliases: com2
306
+ command: sub2
307
+ aliases: subcommand2
308
+ default_command:
309
+ end sub2
310
+ default_command:
311
+ end command2
312
+ command: help
313
+ desc: Shows a list of commands or help for one command
314
+ long_desc: Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function
315
+ arg_name: command
316
+ switch: c
317
+ desc: List commands one per line, to assist with shell completion
318
+ negatable: true
319
+ default_command:
320
+ end help
321
+ default_command:
322
+ END
323
+ EOS
324
+ end
325
+ end
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+
3
+ class TC_testFlag < Clean::Test::TestCase
4
+ include TestHelper
5
+
6
+ def test_basics_simple
7
+ Given flag_with_names(:f)
8
+ Then attributes_should_be_set
9
+ And name_should_be(:f)
10
+ And aliases_should_be(nil)
11
+ end
12
+
13
+ def test_basics_kinda_complex
14
+ Given flag_with_names([:f])
15
+ Then attributes_should_be_set
16
+ And name_should_be(:f)
17
+ And aliases_should_be(nil)
18
+ end
19
+
20
+ def test_basics_complex
21
+ Given flag_with_names([:f,:file,:filename])
22
+ Then attributes_should_be_set
23
+ And name_should_be(:f)
24
+ And aliases_should_be([:file,:filename])
25
+ And {
26
+ assert_equal ["-f VAL","--file VAL","--filename VAL",/foobar/,Float],@flag.arguments_for_option_parser
27
+ }
28
+ end
29
+
30
+ def test_flag_can_mask_its_value
31
+ Given flag_with_names(:password, :mask => true)
32
+ Then attributes_should_be_set(:safe_default_value => "********")
33
+ end
34
+
35
+ def flag_with_names(names,options = {})
36
+ lambda do
37
+ @options = {
38
+ :desc => 'Filename',
39
+ :long_desc => 'The Filename',
40
+ :arg_name => 'file',
41
+ :default_value => '~/.blah.rc',
42
+ :safe_default_value => '~/.blah.rc',
43
+ :must_match => /foobar/,
44
+ :type => Float,
45
+ }.merge(options)
46
+ @flag = GLI::Flag.new(names,@options)
47
+ @cli_option = @flag
48
+ end
49
+ end
50
+
51
+ def attributes_should_be_set(override={})
52
+ lambda {
53
+ expected = @options.merge(override)
54
+ assert_equal(expected[:desc],@flag.description)
55
+ assert_equal(expected[:long_desc],@flag.long_description)
56
+ assert_equal(expected[:default_value],@flag.default_value)
57
+ assert_equal(expected[:safe_default_value],@flag.safe_default_value)
58
+ assert_equal(expected[:must_match],@flag.must_match)
59
+ assert_equal(expected[:type],@flag.type)
60
+ }
61
+ end
62
+ end
@@ -0,0 +1,773 @@
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
+
18
+ def setup
19
+ @fake_stdout = FakeStdOut.new
20
+ @fake_stderr = FakeStdOut.new
21
+ @original_stdout = $stdout
22
+ $stdout = @fake_stdout
23
+ @original_stderr = $stderr
24
+ $stderr = @fake_stderr
25
+ @app = CLIApp.new
26
+
27
+ @config_file = File.expand_path(File.dirname(File.realpath(__FILE__)) + '/new_config.yaml')
28
+ @gli_debug = ENV['GLI_DEBUG']
29
+ @app.error_device=@fake_stderr
30
+ ENV.delete('GLI_DEBUG')
31
+ end
32
+
33
+ def teardown
34
+ File.delete(@config_file) if File.exist?(@config_file)
35
+ ENV['GLI_DEBUG'] = @gli_debug
36
+ @app.error_device=$stderr
37
+ $stdout = @original_stdout
38
+ $stderr = @original_stderr
39
+ end
40
+
41
+ def test_flag_create
42
+ @app.reset
43
+ do_test_flag_create(@app)
44
+ do_test_flag_create(GLI::Command.new(:names => :f))
45
+ end
46
+
47
+ def test_create_commands_using_strings
48
+ @app.reset
49
+ @app.flag ['f','flag']
50
+ @app.switch ['s','some-switch']
51
+ @app.command 'command','command-with-dash' do |c|
52
+ end
53
+ assert @app.commands.include? :command
54
+ assert @app.flags.include? :f
55
+ assert @app.switches.include? :s
56
+ assert @app.commands[:command].aliases.include? :'command-with-dash'
57
+ assert @app.flags[:f].aliases.include? :flag
58
+ assert @app.switches[:s].aliases.include? :'some-switch'
59
+ end
60
+
61
+ def test_default_command
62
+ @app.reset
63
+ @called = false
64
+ @app.command :foo do |c|
65
+ c.action do |global, options, arguments|
66
+ @called = true
67
+ end
68
+ end
69
+ @app.default_command(:foo)
70
+ assert_equal 0, @app.run([]), "Expected exit status to be 0"
71
+ assert @called, "Expected default command to be executed"
72
+ end
73
+
74
+ def test_flag_with_space_barfs
75
+ @app.reset
76
+ assert_raises(ArgumentError) { @app.flag ['some flag'] }
77
+ assert_raises(ArgumentError) { @app.flag ['f','some flag'] }
78
+ assert_raises(ArgumentError) { @app.switch ['some switch'] }
79
+ assert_raises(ArgumentError) { @app.switch ['f','some switch'] }
80
+ assert_raises(ArgumentError) { @app.command ['some command'] }
81
+ assert_raises(ArgumentError) { @app.command ['f','some command'] }
82
+ end
83
+
84
+ def test_command_line_stored_separately
85
+ failure = nil
86
+ @app.reset
87
+ @app.flag :f
88
+ @app.switch :s
89
+ @app.flag :g
90
+ @app.switch :bleorgh
91
+ called = false
92
+ @app.command :command do |c|
93
+ c.flag :f
94
+ c.switch :s
95
+ c.flag :g
96
+ c.action do |g,o,a|
97
+ begin
98
+ called = true
99
+ assert_equal "bar",g[:cli][:f]
100
+ assert !g[:cli][:bleorgh]
101
+ assert_equal "baaz",o[:cli][:g]
102
+ rescue Exception => ex
103
+ failure = ex
104
+ end
105
+ end
106
+ end
107
+ assert_equal 0,@app.run(%w(-f bar --no-bleorgh command -g baaz)),@fake_stderr.to_s
108
+ assert_equal "bar",@app.options[:global][:f]
109
+ assert !@app.options[:global][:bleorgh]
110
+ assert called
111
+ raise failure if !failure.nil?
112
+ end
113
+
114
+ def test_init_from_config
115
+ failure = nil
116
+ @app.reset
117
+ @app.config_file(File.expand_path(File.dirname(File.realpath(__FILE__)) + '/config.yaml'))
118
+ @app.flag :f
119
+ @app.switch :s
120
+ @app.flag :g
121
+ called = false
122
+ @app.command :command do |c|
123
+ c.flag :f
124
+ c.switch :s
125
+ c.flag :g
126
+ c.action do |g,o,a|
127
+ begin
128
+ called = true
129
+ assert_equal "foo",g[:f]
130
+ assert_equal "bar",o[:g]
131
+ assert !g[:g]
132
+ assert !o[:f]
133
+ assert !g[:s]
134
+ assert o[:s]
135
+ rescue Exception => ex
136
+ failure = ex
137
+ end
138
+ end
139
+ end
140
+ @app.run(['command'])
141
+ assert called
142
+ raise failure if !failure.nil?
143
+ end
144
+
145
+ def test_command_line_overrides_config
146
+ failure = nil
147
+ @app.reset
148
+ @app.config_file(File.expand_path(File.dirname(File.realpath(__FILE__)) + '/config.yaml'))
149
+ @app.flag :f
150
+ @app.switch :s
151
+ @app.flag :g
152
+ @app.switch :bleorgh
153
+ called = false
154
+ @app.command :command do |c|
155
+ c.flag :f
156
+ c.switch :s
157
+ c.flag :g
158
+ c.action do |g,o,a|
159
+ begin
160
+ called = true
161
+ assert_equal "baaz",o[:g]
162
+ assert_equal "bar",g[:f]
163
+ assert !g[:g],o.inspect
164
+ assert !o[:f],o.inspect
165
+ assert !g[:s],o.inspect
166
+ assert o[:s],o.inspect
167
+ assert g[:bleorgh] != nil,"Expected :bleorgh to have a value"
168
+ assert g[:bleorgh] == false,"Expected :bleorgh to be false"
169
+ rescue Exception => ex
170
+ failure = ex
171
+ end
172
+ end
173
+ end
174
+ assert_equal 0,@app.run(%w(-f bar --no-bleorgh command -g baaz)),@fake_stderr.to_s
175
+ assert called
176
+ raise failure if !failure.nil?
177
+ end
178
+
179
+ def test_no_overwrite_config
180
+ config_file = File.expand_path(File.dirname(File.realpath(__FILE__)) + '/config.yaml')
181
+ config_file_contents = File.read(config_file)
182
+ @app.reset
183
+ @app.config_file(config_file)
184
+ assert_equal 1,@app.run(['initconfig'])
185
+ assert @fake_stderr.strings.grep(/--force/),@fake_stderr.strings.inspect
186
+ assert !@fake_stdout.contained?(/written/), @fake_stdout.strings.inspect
187
+ config_file_contents_after = File.read(config_file)
188
+ assert_equal(config_file_contents,config_file_contents_after)
189
+ end
190
+
191
+ def test_config_file_name
192
+ @app.reset
193
+ file = @app.config_file("foo")
194
+ assert_equal(Etc.getpwuid.dir + "/foo",file)
195
+ file = @app.config_file("/foo")
196
+ assert_equal "/foo",file
197
+ init_command = @app.commands[:initconfig]
198
+ assert init_command
199
+ end
200
+
201
+ def test_initconfig_command
202
+ @app.reset
203
+ @app.config_file(@config_file)
204
+ @app.flag :f
205
+ @app.switch :s
206
+ @app.switch :w
207
+ @app.flag :bigflag
208
+ @app.flag :biggestflag
209
+ @app.command :foo do |c|
210
+ end
211
+ @app.command :bar do |c|
212
+ end
213
+ @app.command :blah do |c|
214
+ end
215
+ @app.on_error do |ex|
216
+ raise ex
217
+ end
218
+ @app.run(['-f','foo','-s','--bigflag=bleorgh','initconfig'])
219
+ assert @fake_stdout.contained?(/written/), @fake_stdout.strings.inspect
220
+
221
+ written_config = File.open(@config_file) { |f| YAML::load(f) }
222
+
223
+ assert_equal 'foo',written_config[:f]
224
+ assert_equal 'bleorgh',written_config[:bigflag]
225
+ assert written_config[:s]
226
+ assert !written_config[:w]
227
+ assert_nil written_config[:biggestflag]
228
+ assert written_config[GLI::InitConfig::COMMANDS_KEY]
229
+ assert written_config[GLI::InitConfig::COMMANDS_KEY][:foo]
230
+ assert written_config[GLI::InitConfig::COMMANDS_KEY][:bar]
231
+ assert written_config[GLI::InitConfig::COMMANDS_KEY][:blah]
232
+
233
+ end
234
+
235
+ def test_initconfig_permissions
236
+ @app.reset
237
+ @app.config_file(@config_file)
238
+ @app.run(['initconfig'])
239
+ oct_mode = "%o" % File.stat(@config_file).mode
240
+ assert_match /0600$/, oct_mode
241
+ end
242
+
243
+ def do_test_flag_create(object)
244
+ description = 'this is a description'
245
+ long_desc = 'this is a very long description'
246
+ object.desc description
247
+ object.long_desc long_desc
248
+ object.arg_name 'filename'
249
+ object.default_value '~/.blah.rc'
250
+ object.flag :f
251
+ assert (object.flags[:f] )
252
+ assert_equal(description,object.flags[:f].description)
253
+ assert_equal(long_desc,object.flags[:f].long_description)
254
+ assert(nil != object.flags[:f].usage)
255
+ assert(object.usage != nil) if object.respond_to? :usage;
256
+ end
257
+
258
+ def test_switch_create
259
+ @app.reset
260
+ do_test_switch_create(@app)
261
+ do_test_switch_create(GLI::Command.new(:names => :f))
262
+ end
263
+
264
+ def test_switch_create_twice
265
+ @app.reset
266
+ do_test_switch_create_twice(@app)
267
+ do_test_switch_create_twice(GLI::Command.new(:names => :f))
268
+ end
269
+
270
+ def test_all_aliases_in_options
271
+ @app.reset
272
+ @app.on_error { |ex| raise ex }
273
+ @app.flag [:f,:flag,:'big-flag-name']
274
+ @app.switch [:s,:switch,:'big-switch-name']
275
+ @app.command [:com,:command] do |c|
276
+ c.flag [:g,:gflag]
277
+ c.switch [:h,:hswitch]
278
+ c.action do |global,options,args|
279
+ assert_equal 'foo',global[:f]
280
+ assert_equal global[:f],global[:flag]
281
+ assert_equal global[:f],global['f']
282
+ assert_equal global[:f],global['flag']
283
+ assert_equal global[:f],global['big-flag-name']
284
+ assert_equal global[:f],global[:'big-flag-name']
285
+
286
+ assert global[:s]
287
+ assert global[:switch]
288
+ assert global[:'big-switch-name']
289
+ assert global['s']
290
+ assert global['switch']
291
+ assert global['big-switch-name']
292
+
293
+ assert_equal 'bar',options[:g]
294
+ assert_equal options[:g],options['g']
295
+ assert_equal options[:g],options['gflag']
296
+ assert_equal options[:g],options[:gflag]
297
+
298
+ assert options[:h]
299
+ assert options['h']
300
+ assert options[:hswitch]
301
+ assert options['hswitch']
302
+ end
303
+ end
304
+ @app.run(%w(-f foo -s command -g bar -h some_arg))
305
+ end
306
+
307
+ def test_use_hash_by_default
308
+ @app.reset
309
+ @app.switch :g
310
+ @app.command :command do |c|
311
+ c.switch :f
312
+ c.action do |global,options,args|
313
+ assert_equal Hash,global.class
314
+ assert_equal Hash,options.class
315
+ end
316
+ end
317
+ @app.run(%w(-g command -f))
318
+ end
319
+
320
+ def test_flag_array_of_options_global
321
+ @app.reset
322
+ @app.flag :foo, :must_match => ['bar','blah','baz']
323
+ @app.command :command do |c|
324
+ c.action do
325
+ end
326
+ end
327
+ assert_equal 64,@app.run(%w(--foo=cruddo command)),@fake_stderr.to_s
328
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
329
+ assert_equal 0,@app.run(%w(--foo=blah command)),@fake_stderr.to_s
330
+ end
331
+
332
+ def test_flag_hash_of_options_global
333
+ @app.reset
334
+ @app.flag :foo, :must_match => { 'bar' => "BAR", 'blah' => "BLAH" }
335
+ @foo_arg_value = nil
336
+ @app.command :command do |c|
337
+ c.action do |g,o,a|
338
+ @foo_arg_value = g[:foo]
339
+ end
340
+ end
341
+ assert_equal 64,@app.run(%w(--foo=cruddo command)),@fake_stderr.to_s
342
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
343
+ assert_equal 0,@app.run(%w(--foo=blah command)),@fake_stderr.to_s
344
+ assert_equal 'BLAH',@foo_arg_value
345
+ end
346
+
347
+ def test_flag_regexp_global
348
+ @app.reset
349
+ @app.flag :foo, :must_match => /bar/
350
+ @app.command :command do |c|
351
+ c.action do
352
+ end
353
+ end
354
+ assert_equal 64,@app.run(%w(--foo=cruddo command)),@fake_stderr.to_s
355
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
356
+ end
357
+
358
+ def test_flag_regexp_global_short_form
359
+ @app.reset
360
+ @app.flag :f, :must_match => /bar/
361
+ @app.command :command do |c|
362
+ c.action do
363
+ end
364
+ end
365
+ assert_equal 64,@app.run(%w(-f cruddo command)),@fake_stderr.to_s
366
+ assert @fake_stderr.contained?(/error: invalid argument: -f cruddo/),"STDERR was:\n" + @fake_stderr.to_s
367
+ end
368
+
369
+ def test_flag_regexp_command
370
+ @app.reset
371
+ @app.command :command do |c|
372
+ c.flag :foo, :must_match => /bar/
373
+ c.action do
374
+ end
375
+ end
376
+ assert_equal 64,@app.run(%w(command --foo=cruddo)),@fake_stderr.to_s
377
+ assert @fake_stderr.contained?(/error: invalid argument: --foo=cruddo/),"STDERR was:\n" + @fake_stderr.to_s
378
+ end
379
+
380
+ def test_use_openstruct
381
+ @app.reset
382
+ @app.switch :g
383
+ @app.use_openstruct true
384
+ @app.command :command do |c|
385
+ c.switch :f
386
+ c.action do |global,options,args|
387
+ assert_equal GLI::Options,global.class
388
+ assert_equal GLI::Options,options.class
389
+ end
390
+ end
391
+ @app.run(%w(-g command -f))
392
+ end
393
+
394
+ def test_repeated_option_names
395
+ @app.reset
396
+ @app.on_error { |ex| raise ex }
397
+ @app.flag [:f,:flag]
398
+ assert_raises(ArgumentError) { @app.switch [:foo,:flag] }
399
+ assert_raises(ArgumentError) { @app.switch [:f] }
400
+
401
+ @app.switch [:x,:y]
402
+ assert_raises(ArgumentError) { @app.flag [:x] }
403
+ assert_raises(ArgumentError) { @app.flag [:y] }
404
+
405
+ # This shouldn't raise; :help is special
406
+ @app.switch :help
407
+ end
408
+
409
+ def test_repeated_option_names_on_command
410
+ @app.reset
411
+ @app.on_error { |ex| raise ex }
412
+ @app.command :command do |c|
413
+ c.flag [:f,:flag]
414
+ assert_raises(ArgumentError) { c.switch [:foo,:flag] }
415
+ assert_raises(ArgumentError) { c.switch [:f] }
416
+ assert_raises(ArgumentError) { c.flag [:foo,:flag] }
417
+ assert_raises(ArgumentError) { c.flag [:f] }
418
+ end
419
+ @app.command :command3 do |c|
420
+ c.switch [:s,:switch]
421
+ assert_raises(ArgumentError) { c.switch [:switch] }
422
+ assert_raises(ArgumentError) { c.switch [:s] }
423
+ assert_raises(ArgumentError) { c.flag [:switch] }
424
+ assert_raises(ArgumentError) { c.flag [:s] }
425
+ end
426
+ end
427
+
428
+ def test_two_flags
429
+ @app.reset
430
+ @app.on_error do |ex|
431
+ raise ex
432
+ end
433
+ @app.command [:foo] do |c|
434
+ c.flag :i
435
+ c.flag :s
436
+ c.action do |g,o,a|
437
+ assert_equal "5", o[:i]
438
+ assert_equal "a", o[:s]
439
+ end
440
+ end
441
+ @app.run(['foo', '-i','5','-s','a'])
442
+ end
443
+
444
+ def test_two_flags_with_a_default
445
+ @app.reset
446
+ @app.on_error do |ex|
447
+ raise ex
448
+ end
449
+ @app.command [:foo] do |c|
450
+ c.default_value "1"
451
+ c.flag :i
452
+ c.flag :s
453
+ c.action do |g,o,a|
454
+ assert_equal "1", o[:i]
455
+ assert_equal nil, o[:s]
456
+ end
457
+ end
458
+ @app.run(['foo','a'])
459
+ end
460
+
461
+ def test_switch_with_default_of_true
462
+ @app.reset
463
+ @app.on_error do |ex|
464
+ raise ex
465
+ end
466
+ @switch_value = nil
467
+
468
+ @app.command [:foo] do |c|
469
+ c.default_value true
470
+ c.switch :switch
471
+ c.action do |g,o,a|
472
+ @switch_value = o[:switch]
473
+ end
474
+ end
475
+ @app.run(['foo'])
476
+
477
+ assert @switch_value == true,"Got: '#{@switch_value}', but expected true"
478
+
479
+ @app.run(['foo','--no-switch'])
480
+
481
+ assert @switch_value == false,"Got: '#{@switch_value}', but expected false"
482
+ end
483
+
484
+ def test_switch_with_default_true_and_not_negatable_causes_exception
485
+ @app.reset
486
+ @app.on_error do |ex|
487
+ raise ex
488
+ end
489
+ @switch_value = nil
490
+
491
+ assert_raises(RuntimeError) do
492
+ @app.command [:foo] do |c|
493
+ c.switch :switch, :default_value => true, :negatable => false
494
+ end
495
+ end
496
+ end
497
+
498
+ def test_two_flags_using_equals_with_a_default
499
+ @app.reset
500
+ @app.on_error do |ex|
501
+ raise ex
502
+ end
503
+ @app.command [:foo] do |c|
504
+ c.default_value "1"
505
+ c.flag :i
506
+ c.flag :s
507
+ c.action do |g,o,a|
508
+ assert_equal "5", o[:i],o.inspect
509
+ assert_equal "a", o[:s],o.inspect
510
+ end
511
+ end
512
+ @app.run(['foo', '-i5','-sa'])
513
+ end
514
+
515
+ def test_default_values_are_available_on_all_aliases
516
+ @app.reset
517
+ @app.on_error { |e| raise e }
518
+
519
+ @app.default_value "global_default"
520
+ @app.flag [ :f, :flag ]
521
+
522
+ @global_options = {}
523
+ @command_options = {}
524
+
525
+ @app.command [:foo] do |c|
526
+ c.default_value "command_default"
527
+ c.flag [ :c,:commandflag]
528
+
529
+ c.action do |g,o,a|
530
+ @global_options = g
531
+ @command_options = o
532
+ end
533
+ end
534
+
535
+ @app.run(["foo"])
536
+
537
+ assert_equal "global_default", @global_options[:f]
538
+ assert_equal "global_default", @global_options[:flag]
539
+ assert_equal "global_default", @global_options["f"]
540
+ assert_equal "global_default", @global_options["flag"]
541
+
542
+ assert_equal "command_default", @command_options[:c]
543
+ assert_equal "command_default", @command_options[:commandflag]
544
+ assert_equal "command_default", @command_options["c"]
545
+ assert_equal "command_default", @command_options["commandflag"]
546
+ end
547
+
548
+ def test_exits_zero_on_success
549
+ @app.reset
550
+ assert_equal 0,@app.run([]),@fake_stderr.to_s
551
+ end
552
+
553
+ def test_exits_nonzero_on_bad_command_line
554
+ @app.reset
555
+ @app.on_error { true }
556
+ assert_equal 64,@app.run(['asdfasdfasdf'])
557
+ end
558
+
559
+ def test_exists_nonzero_on_raise_from_command
560
+ @app.reset
561
+ @app.on_error { true }
562
+ @app.command(:foo) do |c|
563
+ c.action do |g,o,a|
564
+ raise "Problem"
565
+ end
566
+ end
567
+ assert_equal 1,@app.run(['foo'])
568
+ end
569
+
570
+ def test_exits_nonzero_with_custom_exception
571
+ @app.reset
572
+ @app.on_error { true }
573
+ @app.command(:foo) do |c|
574
+ c.action do |g,o,a|
575
+ raise GLI::CustomExit.new("Problem",45)
576
+ end
577
+ end
578
+ assert_equal 45,@app.run(['foo'])
579
+ end
580
+
581
+ def test_exits_nonzero_with_exit_method
582
+ @app.reset
583
+ @app.on_error { true }
584
+ @app.command(:foo) do |c|
585
+ c.action do |g,o,a|
586
+ @app.exit_now!("Problem",45)
587
+ end
588
+ end
589
+ assert_equal 45,@app.run(['foo'])
590
+ end
591
+
592
+ def test_exits_nonzero_with_exit_method_by_default
593
+ @app.reset
594
+ @app.on_error { true }
595
+ @app.command(:foo) do |c|
596
+ c.action do |g,o,a|
597
+ @app.exit_now!("Problem")
598
+ end
599
+ end
600
+ assert_equal 1,@app.run(['foo'])
601
+ end
602
+
603
+ def test_help_now_exits_and_shows_help
604
+ @app.reset
605
+ @app.on_error { true }
606
+ @app.command(:foo) do |c|
607
+ c.action do |g,o,a|
608
+ @app.help_now!("Problem")
609
+ end
610
+ end
611
+ assert_equal 64,@app.run(['foo']),@fake_stderr.strings.join("\n")
612
+ end
613
+
614
+ def test_custom_exception_causes_error_to_be_printed_to_stderr
615
+ @app.reset
616
+ @app.on_error { true }
617
+ error_message = "Something went wrong"
618
+ @app.command(:foo) do |c|
619
+ c.action do |g,o,a|
620
+ raise error_message
621
+ end
622
+ end
623
+ @app.run(['foo'])
624
+ assert @fake_stderr.strings.include?("error: #{error_message}"),"STDERR was:\n" + @fake_stderr.to_s
625
+ end
626
+
627
+ def test_gli_debug_overrides_error_hiding
628
+ ENV['GLI_DEBUG'] = 'true'
629
+
630
+ @app.reset
631
+ @app.on_error { true }
632
+ @app.command(:foo) do |c|
633
+ c.action do |g,o,a|
634
+ @app.exit_now!("Problem",45)
635
+ end
636
+ end
637
+
638
+ assert_raises(GLI::CustomExit) { @app.run(['foo']) }
639
+ end
640
+
641
+ class ConvertMe
642
+ attr_reader :value
643
+ def initialize(value)
644
+ @value = value
645
+ end
646
+ end
647
+
648
+ def test_that_we_can_add_new_casts_for_flags
649
+ @app.reset
650
+ @app.accept(ConvertMe) do |value|
651
+ ConvertMe.new(value)
652
+ end
653
+ @app.flag :foo, :type => ConvertMe
654
+
655
+ @foo = nil
656
+ @baz = nil
657
+
658
+ @app.command(:bar) do |c|
659
+ c.flag :baz, :type => ConvertMe
660
+ c.action do |g,o,a|
661
+ @foo = g[:foo]
662
+ @baz = o[:baz]
663
+ end
664
+ end
665
+
666
+ assert_equal 0,@app.run(['--foo','blah','bar','--baz=crud']),@fake_stderr.to_s
667
+
668
+ assert @foo.kind_of?(ConvertMe),"Expected a ConvertMe, but get a #{@foo.class}"
669
+ assert_equal 'blah',@foo.value
670
+
671
+ assert @baz.kind_of?(ConvertMe),"Expected a ConvertMe, but get a #{@foo.class}"
672
+ assert_equal 'crud',@baz.value
673
+ end
674
+
675
+ def test_that_we_mutate_ARGV_by_default
676
+ @app.reset
677
+ @app.flag :f
678
+ @app.command :foo do |c|
679
+ c.action do |*args|
680
+ end
681
+ end
682
+
683
+ argv = %w(-f some_flag foo bar blah)
684
+
685
+ @app.run(argv)
686
+
687
+ assert_equal %w(bar blah),argv
688
+ end
689
+
690
+ def test_that_we_can_avoid_mutating_ARGV
691
+ @app.reset
692
+ @app.flag :f
693
+ @app.command :foo do |c|
694
+ c.action do |*args|
695
+ end
696
+ end
697
+ @app.preserve_argv
698
+
699
+ argv = %w(-f some_flag foo bar blah)
700
+
701
+ @app.run(argv)
702
+
703
+ assert_equal %w(-f some_flag foo bar blah),argv
704
+ end
705
+
706
+ private
707
+
708
+ def do_test_flag_create(object)
709
+ description = 'this is a description'
710
+ long_desc = 'this is a very long description'
711
+ object.desc description
712
+ object.long_desc long_desc
713
+ object.arg_name 'filename'
714
+ object.default_value '~/.blah.rc'
715
+ object.flag :f
716
+ assert (object.flags[:f] )
717
+ assert_equal(description,object.flags[:f].description)
718
+ assert_equal(long_desc,object.flags[:f].long_description)
719
+ end
720
+
721
+ def do_test_switch_create(object)
722
+ do_test_switch_create_classic(object)
723
+ do_test_switch_create_compact(object)
724
+ end
725
+
726
+ def some_descriptions
727
+ lambda {
728
+ @description = 'this is a description'
729
+ @long_description = 'this is a very long description'
730
+ }
731
+ end
732
+
733
+ def assert_switch_was_made(object,switch)
734
+ lambda {
735
+ assert object.switches[switch]
736
+ assert_equal @description,object.switches[switch].description,"For switch #{switch}"
737
+ assert_equal @long_description,object.switches[switch].long_description,"For switch #{switch}"
738
+ assert(object.usage != nil) if object.respond_to? :usage
739
+ }
740
+ end
741
+
742
+ def do_test_switch_create_classic(object)
743
+ Given some_descriptions
744
+ When {
745
+ object.desc @description
746
+ object.long_desc @long_description
747
+ object.switch :f
748
+ }
749
+ Then assert_switch_was_made(object,:f)
750
+ end
751
+
752
+ def do_test_switch_create_compact(object)
753
+ Given some_descriptions
754
+ When {
755
+ object.switch :g, :desc => @description, :long_desc => @long_description
756
+ }
757
+ Then assert_switch_was_made(object,:g)
758
+ end
759
+
760
+ def do_test_switch_create_twice(object)
761
+ description = 'this is a description'
762
+ object.desc description
763
+ object.switch :f
764
+ assert (object.switches[:f] )
765
+ assert_equal(description,object.switches[:f].description)
766
+ object.switch :g
767
+ assert (object.switches[:g])
768
+ assert_equal(nil,object.switches[:g].description)
769
+ assert(object.usage != nil) if object.respond_to? :usage
770
+ end
771
+
772
+
773
+ end