optimist_xl 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ require 'chronic'
2
+
3
+
4
+ module OptimistXL
5
+
6
+ # Option for dates using Chronic gem.
7
+ # Mainly for compatibility with Optimist.
8
+ # Use of Chronic switches to United States formatted
9
+ # dates (MM/DD/YYYY) as opposed to DD/MM/YYYY
10
+
11
+ class ChronicDateOption < Option
12
+ register_alias :chronic_date
13
+ register_alias :'chronic::date'
14
+ def type_format ; "=<date>" ; end
15
+ def parse(paramlist, _neg_given)
16
+ paramlist.map do |pg|
17
+ pg.map do |param|
18
+ parse_date_param(param)
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+ def parse_date_param(param)
25
+ if param.respond_to?(:year) and param.respond_to?(:month) and param.respond_to(:day)
26
+ return Date.new(param.year, param.month, param.day)
27
+ end
28
+ time = Chronic.parse(param)
29
+ time ? Date.new(time.year, time.month, time.day) : Date.parse(param)
30
+ rescue ArgumentError
31
+ raise CommandlineError, "option '#{self.name}' needs a valid date"
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'optimist_xl'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "optimist_xl"
9
+ spec.version = OptimistXL::VERSION
10
+ spec.authors = ["William Morgan", "Keenan Brock", "Jason Frey", "Ben Bowers"]
11
+ spec.email = "nanobowers@gmail.com"
12
+ spec.summary = "OptimistXL is a commandline option parser for Ruby that just gets out of your way."
13
+ spec.description = "OptimistXL is a commandline option parser for Ruby that just
14
+ gets out of your way. One line of code per option is all you need to write.
15
+ For that, you get a nice automatically-generated help page, robust option
16
+ parsing, command subcompletion, and sensible defaults for everything you don't
17
+ specify. This gem is an enhanced-feature fork of the Optimist gem."
18
+ spec.homepage = "https://github.com/nanobowers/optimist_xl/"
19
+ spec.license = "MIT"
20
+
21
+ spec.files = `git ls-files -z`.split("\x0")
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.metadata = {
25
+ "changelog_uri" => "https://github.com/nanobowers/optimist_xl/blob/master/History.txt",
26
+ "source_code_uri" => "https://github.com/nanobowers/optimist_xl/",
27
+ "bug_tracker_uri" => "https://github.com/nanobowers/optimist_xl/issues",
28
+ }
29
+
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency "minitest", "~> 5.4.3"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "chronic"
35
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ module OptimistXL
4
+ class CommandlineErrorTest < ::MiniTest::Test
5
+ def test_class
6
+ assert_kind_of Exception, cle("message")
7
+ end
8
+
9
+ def test_message
10
+ assert "message", cle("message").message
11
+ end
12
+
13
+ def test_error_code_default
14
+ assert_nil cle("message").error_code
15
+ end
16
+
17
+ def test_error_code_custom
18
+ assert_equal(-3, cle("message", -3).error_code)
19
+ end
20
+
21
+ private
22
+
23
+ def cle(*args)
24
+ CommandlineError.new(*args)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ module OptimistXL
4
+ class HelpNeededTest < ::MiniTest::Test
5
+ def test_class
6
+ assert_kind_of Exception, hn("message")
7
+ end
8
+
9
+ def test_message
10
+ assert "message", hn("message").message
11
+ end
12
+
13
+ private
14
+
15
+ def hn(*args)
16
+ HelpNeeded.new(*args)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,177 @@
1
+ require 'stringio'
2
+ require 'test_helper'
3
+
4
+ module OptimistXL
5
+ class ParserEduateTest < ::MiniTest::Test
6
+ def setup
7
+ end
8
+
9
+ def test_no_arguments_to_stdout
10
+ assert_stdout(/Options:/) do
11
+ parser.educate
12
+ end
13
+ end
14
+
15
+ def test_argument_to_stringio
16
+ assert_educates(/Options:/)
17
+ end
18
+
19
+ def test_no_headers
20
+ assert_educates(/^Options:/)
21
+ end
22
+
23
+ def test_usage
24
+ parser.usage("usage string")
25
+ assert_educates(/^Usage: \w* usage string\n\nOptions:/)
26
+ end
27
+
28
+ def test_usage_synopsis_version
29
+ end
30
+
31
+ # def test_banner
32
+ # def test_text
33
+
34
+ # width, legacy_width
35
+ # wrap
36
+ # wrap_lines
37
+
38
+ ############
39
+ # convert these into multiple tests
40
+ # pulled out of optimist_test for now
41
+ def test_help_has_default_banner
42
+ @p = Parser.new
43
+ sio = StringIO.new "w"
44
+ @p.parse []
45
+ @p.educate sio
46
+ help = sio.string.split "\n"
47
+ assert help[0] =~ /options/i
48
+ assert_equal 2, help.length # options, then -h
49
+
50
+ @p = Parser.new
51
+ @p.version "my version"
52
+ sio = StringIO.new "w"
53
+ @p.parse []
54
+ @p.educate sio
55
+ help = sio.string.split "\n"
56
+ assert help[0] =~ /my version/i
57
+ assert_equal 4, help.length # version, options, -h, -v
58
+
59
+ @p = Parser.new
60
+ @p.banner "my own banner"
61
+ sio = StringIO.new "w"
62
+ @p.parse []
63
+ @p.educate sio
64
+ help = sio.string.split "\n"
65
+ assert help[0] =~ /my own banner/i
66
+ assert_equal 2, help.length # banner, -h
67
+
68
+ @p = Parser.new
69
+ @p.text "my own text banner"
70
+ sio = StringIO.new "w"
71
+ @p.parse []
72
+ @p.educate sio
73
+ help = sio.string.split "\n"
74
+ assert help[0] =~ /my own text banner/i
75
+ assert_equal 2, help.length # banner, -h
76
+ end
77
+
78
+ def test_help_has_optional_usage
79
+ @p = Parser.new
80
+ @p.usage "OPTIONS FILES"
81
+ sio = StringIO.new "w"
82
+ @p.parse []
83
+ @p.educate sio
84
+ help = sio.string.split "\n"
85
+ assert help[0] =~ /OPTIONS FILES/i
86
+ assert_equal 4, help.length # line break, options, then -h
87
+ end
88
+
89
+ def test_help_has_optional_synopsis
90
+ @p = Parser.new
91
+ @p.synopsis "About this program"
92
+ sio = StringIO.new "w"
93
+ @p.parse []
94
+ @p.educate sio
95
+ help = sio.string.split "\n"
96
+ assert help[0] =~ /About this program/i
97
+ assert_equal 4, help.length # line break, options, then -h
98
+ end
99
+
100
+ def test_help_has_specific_order_for_usage_and_synopsis
101
+ @p = Parser.new
102
+ @p.usage "OPTIONS FILES"
103
+ @p.synopsis "About this program"
104
+ sio = StringIO.new "w"
105
+ @p.parse []
106
+ @p.educate sio
107
+ help = sio.string.split "\n"
108
+ assert help[0] =~ /OPTIONS FILES/i
109
+ assert help[1] =~ /About this program/i
110
+ assert_equal 5, help.length # line break, options, then -h
111
+ end
112
+
113
+ def test_help_preserves_positions
114
+ parser.opt :zzz, "zzz"
115
+ parser.opt :aaa, "aaa"
116
+ sio = StringIO.new "w"
117
+ parser.educate sio
118
+
119
+ help = sio.string.split "\n"
120
+ assert help[1] =~ /zzz/
121
+ assert help[2] =~ /aaa/
122
+ end
123
+
124
+ def test_help_includes_option_types
125
+ parser.opt :arg1, 'arg', :type => :int
126
+ parser.opt :arg2, 'arg', :type => :ints
127
+ parser.opt :arg3, 'arg', :type => :string
128
+ parser.opt :arg4, 'arg', :type => :strings
129
+ parser.opt :arg5, 'arg', :type => :float
130
+ parser.opt :arg6, 'arg', :type => :floats
131
+ parser.opt :arg7, 'arg', :type => :io
132
+ parser.opt :arg8, 'arg', :type => :ios
133
+ parser.opt :arg9, 'arg', :type => :date
134
+ parser.opt :arg10, 'arg', :type => :dates
135
+ sio = StringIO.new "w"
136
+ parser.educate sio
137
+
138
+ help = sio.string.split "\n"
139
+ assert help[1] =~ /<i>/
140
+ assert help[2] =~ /<i\+>/
141
+ assert help[3] =~ /<s>/
142
+ assert help[4] =~ /<s\+>/
143
+ assert help[5] =~ /<f>/
144
+ assert help[6] =~ /<f\+>/
145
+ assert help[7] =~ /<filename\/uri>/
146
+ assert help[8] =~ /<filename\/uri\+>/
147
+ assert help[9] =~ /<date>/
148
+ assert help[10] =~ /<date\+>/
149
+ end
150
+
151
+ # changing behavior from optimist to simplify code.
152
+ # no longer write 'default' vs. 'Default' for descriptions ending with '.'
153
+ def test_help_has_default_text
154
+ parser.opt :arg1, 'description with period.', :default => 'hello'
155
+ parser.opt :arg2, 'description without period', :default => 'world'
156
+ sio = StringIO.new 'w'
157
+ parser.educate sio
158
+
159
+ help = sio.string.split "\n"
160
+ assert help[1] =~ /Default/
161
+ assert help[2] =~ /Default/
162
+ end
163
+ ############
164
+
165
+ private
166
+
167
+ def parser
168
+ @p ||= Parser.new
169
+ end
170
+
171
+ def assert_educates(output)
172
+ str = StringIO.new
173
+ parser.educate str
174
+ assert_match output, str.string
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,14 @@
1
+ require 'stringio'
2
+ require 'test_helper'
3
+
4
+ module OptimistXL
5
+
6
+ class ParserOptTest < ::MiniTest::Test
7
+
8
+ private
9
+
10
+ def parser
11
+ @p ||= Parser.new
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,79 @@
1
+ require 'stringio'
2
+ require 'test_helper'
3
+
4
+ module OptimistXL
5
+ class ParserParseTest < ::MiniTest::Test
6
+
7
+ # TODO: parse
8
+ # resolve_default_short_options!
9
+ # parse_date_parameter
10
+ # parse_integer_parameter(param, arg)
11
+ # parse_float_parameter(param, arg)
12
+ # parse_io_parameter(param, arg)
13
+ # each_arg
14
+ # collect_argument_parameters
15
+
16
+ def test_help_needed
17
+ parser.opt "arg"
18
+ assert_raises(HelpNeeded) { parser.parse %w(-h) }
19
+ assert_raises(HelpNeeded) { parser.parse %w(--help) }
20
+ end
21
+
22
+ def test_help_overridden
23
+ parser.opt :arg1, "desc", :long => "help"
24
+ assert parser.parse(%w(-h))[:arg1]
25
+ assert parser.parse(%w(--help))[:arg1]
26
+ end
27
+
28
+ def test_help_with_other_args
29
+ parser.opt :arg1
30
+ assert_raises(HelpNeeded) { @p.parse %w(--arg1 --help) }
31
+ end
32
+
33
+ def test_help_with_arg_error
34
+ parser.opt :arg1, :type => String
35
+ assert_raises(HelpNeeded) { @p.parse %w(--arg1 --help) }
36
+ end
37
+
38
+ def test_version_needed_unset
39
+ parser.opt "arg"
40
+ assert_raises(CommandlineError) { parser.parse %w(-v) }
41
+ end
42
+
43
+ def test_version_needed
44
+ parser.version "optimist 5.2.3"
45
+ assert_raises(VersionNeeded) { parser.parse %w(-v) }
46
+ assert_raises(VersionNeeded) { parser.parse %w(--version) }
47
+ end
48
+
49
+ def test_version_overridden
50
+ parser.opt "version"
51
+ assert parser.parse(%w(-v))["version"]
52
+ assert parser.parse(%w(-v))[:version_given]
53
+ end
54
+
55
+ def test_version_only_appears_if_set
56
+ parser.opt "arg"
57
+ assert_raises(CommandlineError) { parser.parse %w(-v) }
58
+ end
59
+
60
+ def test_version_with_other_args
61
+ parser.opt :arg1
62
+ parser.version "1.1"
63
+ assert_raises(VersionNeeded) { parser.parse %w(--arg1 --version) }
64
+ end
65
+
66
+ def test_version_with_arg_error
67
+ parser.opt :arg1, :type => String
68
+ parser.version "1.1"
69
+ assert_raises(VersionNeeded) { parser.parse %w(--arg1 --version) }
70
+ end
71
+
72
+
73
+ private
74
+
75
+ def parser
76
+ @p ||= Parser.new
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,1404 @@
1
+ require 'stringio'
2
+ require 'test_helper'
3
+
4
+ module OptimistXL
5
+
6
+ class ParserTest < ::MiniTest::Test
7
+ def setup
8
+ @p = Parser.new
9
+ end
10
+
11
+ def parser
12
+ @p ||= Parser.new
13
+ end
14
+
15
+ # initialize
16
+ # cloaker
17
+
18
+ def test_version
19
+ assert_nil parser.version
20
+ assert_equal "optimist 5.2.3", parser.version("optimist 5.2.3")
21
+ assert_equal "optimist 5.2.3", parser.version
22
+ end
23
+
24
+ def test_usage
25
+ assert_nil parser.usage
26
+
27
+ assert_equal "usage string", parser.usage("usage string")
28
+ assert_equal "usage string", parser.usage
29
+ end
30
+
31
+ def test_synopsis
32
+ assert_nil parser.synopsis
33
+
34
+ assert_equal "synopsis string", parser.synopsis("synopsis string")
35
+ assert_equal "synopsis string", parser.synopsis
36
+ end
37
+
38
+ # def test_depends
39
+ # def test_conflicts
40
+ # def test_stop_on
41
+ # def test_stop_on_unknown
42
+
43
+ # die
44
+ # def test_die_educate_on_error
45
+
46
+
47
+ def test_unknown_arguments
48
+ err = assert_raises(CommandlineError) { @p.parse(%w(--arg)) }
49
+ assert_match(/unknown argument '--arg'/, err.message)
50
+ @p.opt "arg"
51
+ @p.parse(%w(--arg))
52
+ err = assert_raises(CommandlineError) { @p.parse(%w(--arg2)) }
53
+ assert_match(/unknown argument '--arg2'/, err.message)
54
+ end
55
+
56
+ def test_unknown_arguments_with_suggestions
57
+ sugp = Parser.new(:suggestions => true)
58
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--bone)) }
59
+ assert_match(/unknown argument '--bone'$/, err.message)
60
+
61
+ if (Module::const_defined?("DidYouMean") &&
62
+ Module::const_defined?("DidYouMean::JaroWinkler") &&
63
+ Module::const_defined?("DidYouMean::Levenshtein"))
64
+ sugp.opt "cone"
65
+ sugp.parse(%w(--cone))
66
+
67
+ # single letter mismatch
68
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--bone)) }
69
+ assert_match(/unknown argument '--bone'. Did you mean: \[--cone\] \?$/, err.message)
70
+
71
+ # transposition
72
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--ocne)) }
73
+ assert_match(/unknown argument '--ocne'. Did you mean: \[--cone\] \?$/, err.message)
74
+
75
+ # extra letter at end
76
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--cones)) }
77
+ assert_match(/unknown argument '--cones'. Did you mean: \[--cone\] \?$/, err.message)
78
+
79
+ # too big of a mismatch to suggest (extra letters in front)
80
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--snowcone)) }
81
+ assert_match(/unknown argument '--snowcone'$/, err.message)
82
+
83
+ # too big of a mismatch to suggest (nothing close)
84
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--clown-nose)) }
85
+ assert_match(/unknown argument '--clown-nose'$/, err.message)
86
+
87
+ sugp.opt "zippy"
88
+ sugp.opt "zapzy"
89
+ # single letter mismatch, matches two
90
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--zipzy)) }
91
+ assert_match(/unknown argument '--zipzy'. Did you mean: \[--zippy, --zapzy\] \?$/, err.message)
92
+
93
+ sugp.opt "big_bug"
94
+ # suggest common case of dash versus underscore in argnames
95
+ err = assert_raises(CommandlineError) { sugp.parse(%w(--big_bug)) }
96
+ assert_match(/unknown argument '--big_bug'. Did you mean: \[--big-bug\] \?$/, err.message)
97
+ end
98
+
99
+ end
100
+
101
+ def test_syntax_check
102
+ @p.opt "arg"
103
+
104
+ @p.parse(%w(--arg))
105
+ @p.parse(%w(arg))
106
+ assert_raises(CommandlineError) { @p.parse(%w(---arg)) }
107
+ assert_raises(CommandlineError) { @p.parse(%w(-arg)) }
108
+ end
109
+
110
+ def test_required_flags_are_required
111
+ @p.opt "arg", "desc", :required => true
112
+ @p.opt "arg2", "desc", :required => false
113
+ @p.opt "arg3", "desc", :required => false
114
+
115
+ @p.parse(%w(--arg))
116
+ @p.parse(%w(--arg --arg2))
117
+ assert_raises(CommandlineError) { @p.parse(%w(--arg2)) }
118
+ assert_raises(CommandlineError) { @p.parse(%w(--arg2 --arg3)) }
119
+ end
120
+
121
+ ## flags that take an argument error unless given one
122
+ def test_argflags_demand_args
123
+ @p.opt "goodarg", "desc", :type => String
124
+ @p.opt "goodarg2", "desc", :type => String
125
+
126
+ @p.parse(%w(--goodarg goat))
127
+ assert_raises(CommandlineError) { @p.parse(%w(--goodarg --goodarg2 goat)) }
128
+ assert_raises(CommandlineError) { @p.parse(%w(--goodarg)) }
129
+ end
130
+
131
+ ## flags that don't take arguments ignore them
132
+ def test_arglessflags_refuse_args
133
+ @p.opt "goodarg"
134
+ @p.opt "goodarg2"
135
+ @p.parse(%w(--goodarg))
136
+ @p.parse(%w(--goodarg --goodarg2))
137
+ opts = @p.parse %w(--goodarg a)
138
+ assert_equal true, opts["goodarg"]
139
+ assert_equal ["a"], @p.leftovers
140
+ end
141
+
142
+ ## flags that require args of a specific type refuse args of other
143
+ ## types
144
+ def test_typed_args_refuse_args_of_other_types
145
+ @p.opt "goodarg", "desc", :type => :int
146
+ assert_raises(ArgumentError) { @p.opt "badarg", "desc", :type => :asdf }
147
+
148
+ @p.parse(%w(--goodarg 3))
149
+ assert_raises(CommandlineError) { @p.parse(%w(--goodarg 4.2)) }
150
+ assert_raises(CommandlineError) { @p.parse(%w(--goodarg hello)) }
151
+ end
152
+
153
+ ## type is correctly derived from :default
154
+ def test_type_correctly_derived_from_default
155
+ assert_raises(ArgumentError) { @p.opt "badarg", "desc", :default => [] }
156
+ assert_raises(ArgumentError) { @p.opt "badarg3", "desc", :default => [{1 => 2}] }
157
+ assert_raises(ArgumentError) { @p.opt "badarg4", "desc", :default => Hash.new }
158
+
159
+ # single arg: int
160
+ @p.opt "argsi", "desc", :default => 0
161
+ opts = @p.parse(%w(--))
162
+ assert_equal 0, opts["argsi"]
163
+ opts = @p.parse(%w(--argsi 4))
164
+ assert_equal 4, opts["argsi"]
165
+ opts = @p.parse(%w(--argsi=4))
166
+ assert_equal 4, opts["argsi"]
167
+ opts = @p.parse(%w(--argsi=-4))
168
+ assert_equal( -4, opts["argsi"])
169
+
170
+ assert_raises(CommandlineError) { @p.parse(%w(--argsi 4.2)) }
171
+ assert_raises(CommandlineError) { @p.parse(%w(--argsi hello)) }
172
+
173
+ # single arg: float
174
+ @p.opt "argsf", "desc", :default => 3.14
175
+ opts = @p.parse(%w(--))
176
+ assert_equal 3.14, opts["argsf"]
177
+ opts = @p.parse(%w(--argsf 2.41))
178
+ assert_equal 2.41, opts["argsf"]
179
+ opts = @p.parse(%w(--argsf 2))
180
+ assert_equal 2, opts["argsf"]
181
+ opts = @p.parse(%w(--argsf 1.0e-2))
182
+ assert_equal 1.0e-2, opts["argsf"]
183
+ assert_raises(CommandlineError) { @p.parse(%w(--argsf hello)) }
184
+
185
+ # single arg: date
186
+ date = Date.today
187
+ @p.opt "argsd", "desc", :default => date
188
+ opts = @p.parse(%w(--))
189
+ assert_equal Date.today, opts["argsd"]
190
+ opts = @p.parse(['--argsd', 'Jan 4, 2007'])
191
+ assert_equal Date.civil(2007, 1, 4), opts["argsd"]
192
+ assert_raises(CommandlineError) { @p.parse(%w(--argsd hello)) }
193
+
194
+ # single arg: string
195
+ @p.opt "argss", "desc", :default => "foobar"
196
+ opts = @p.parse(%w(--))
197
+ assert_equal "foobar", opts["argss"]
198
+ opts = @p.parse(%w(--argss 2.41))
199
+ assert_equal "2.41", opts["argss"]
200
+ opts = @p.parse(%w(--argss hello))
201
+ assert_equal "hello", opts["argss"]
202
+
203
+ # multi args: ints
204
+ @p.opt "argmi", "desc", :default => [3, 5]
205
+ opts = @p.parse(%w(--))
206
+ assert_equal [3, 5], opts["argmi"]
207
+ opts = @p.parse(%w(--argmi 4))
208
+ assert_equal [4], opts["argmi"]
209
+ assert_raises(CommandlineError) { @p.parse(%w(--argmi 4.2)) }
210
+ assert_raises(CommandlineError) { @p.parse(%w(--argmi hello)) }
211
+
212
+ # multi args: floats
213
+ @p.opt "argmf", "desc", :default => [3.34, 5.21]
214
+ opts = @p.parse(%w(--))
215
+ assert_equal [3.34, 5.21], opts["argmf"]
216
+ opts = @p.parse(%w(--argmf 2))
217
+ assert_equal [2], opts["argmf"]
218
+ opts = @p.parse(%w(--argmf 4.0))
219
+ assert_equal [4.0], opts["argmf"]
220
+ assert_raises(CommandlineError) { @p.parse(%w(--argmf hello)) }
221
+
222
+ # multi args: dates
223
+ dates = [Date.today, Date.civil(2007, 1, 4)]
224
+ @p.opt "argmd", "desc", :default => dates
225
+ opts = @p.parse(%w(--))
226
+ assert_equal dates, opts["argmd"]
227
+ opts = @p.parse(['--argmd', 'Jan 4, 2007'])
228
+ assert_equal [Date.civil(2007, 1, 4)], opts["argmd"]
229
+ assert_raises(CommandlineError) { @p.parse(%w(--argmd hello)) }
230
+
231
+ # multi args: strings
232
+ @p.opt "argmst", "desc", :default => %w(hello world)
233
+ opts = @p.parse(%w(--))
234
+ assert_equal %w(hello world), opts["argmst"]
235
+ opts = @p.parse(%w(--argmst 3.4))
236
+ assert_equal ["3.4"], opts["argmst"]
237
+ opts = @p.parse(%w(--argmst goodbye))
238
+ assert_equal ["goodbye"], opts["argmst"]
239
+ end
240
+
241
+ ## :type and :default must match if both are specified
242
+ def test_type_and_default_must_match
243
+ assert_raises(ArgumentError) { @p.opt "badarg", "desc", :type => :int, :default => "hello" }
244
+ assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :type => :String, :default => 4 }
245
+ assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :type => :String, :default => ["hi"] }
246
+ assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :type => :ints, :default => [3.14] }
247
+
248
+ @p.opt "argsi", "desc", :type => :int, :default => 4
249
+ @p.opt "argsf", "desc", :type => :float, :default => 3.14
250
+ @p.opt "argsd", "desc", :type => :date, :default => Date.today
251
+ @p.opt "argss", "desc", :type => :string, :default => "yo"
252
+ @p.opt "argmi", "desc", :type => :ints, :default => [4]
253
+ @p.opt "argmf", "desc", :type => :floats, :default => [3.14]
254
+ @p.opt "argmd", "desc", :type => :dates, :default => [Date.today]
255
+ @p.opt "argmst", "desc", :type => :strings, :default => ["yo"]
256
+ end
257
+
258
+ ##
259
+ def test_flags_with_defaults_and_no_args_act_as_switches
260
+ @p.opt :argd, "desc", :default => "default_string"
261
+
262
+ opts = @p.parse(%w(--))
263
+ assert !opts[:argd_given]
264
+ assert_equal "default_string", opts[:argd]
265
+
266
+ opts = @p.parse(%w( --argd ))
267
+ assert opts[:argd_given]
268
+ assert_equal "default_string", opts[:argd]
269
+
270
+ opts = @p.parse(%w(--argd different_string))
271
+ assert opts[:argd_given]
272
+ assert_equal "different_string", opts[:argd]
273
+ end
274
+
275
+ def test_flag_with_no_defaults_and_no_args_act_as_switches_array
276
+ opts = nil
277
+
278
+ @p.opt :argd, "desc", :type => :strings, :default => ["default_string"]
279
+
280
+ opts = @p.parse(%w(--argd))
281
+ assert_equal ["default_string"], opts[:argd]
282
+ end
283
+
284
+ def test_type_and_empty_array
285
+ @p.opt "argmi", "desc", :type => :ints, :default => []
286
+ @p.opt "argmf", "desc", :type => :floats, :default => []
287
+ @p.opt "argmd", "desc", :type => :dates, :default => []
288
+ @p.opt "argms", "desc", :type => :strings, :default => []
289
+ assert_raises(ArgumentError) { @p.opt "badi", "desc", :type => :int, :default => [] }
290
+ assert_raises(ArgumentError) { @p.opt "badf", "desc", :type => :float, :default => [] }
291
+ assert_raises(ArgumentError) { @p.opt "badd", "desc", :type => :date, :default => [] }
292
+ assert_raises(ArgumentError) { @p.opt "bads", "desc", :type => :string, :default => [] }
293
+ opts = @p.parse([])
294
+ assert_equal(opts["argmi"], [])
295
+ assert_equal(opts["argmf"], [])
296
+ assert_equal(opts["argmd"], [])
297
+ assert_equal(opts["argms"], [])
298
+ end
299
+
300
+ def test_long_detects_bad_names
301
+ @p.opt "goodarg", "desc", :long => "none"
302
+ @p.opt "goodarg2", "desc", :long => "--two"
303
+ assert_raises(ArgumentError) { @p.opt "badarg", "desc", :long => "" }
304
+ assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :long => "--" }
305
+ assert_raises(ArgumentError) { @p.opt "badarg3", "desc", :long => "-one" }
306
+ assert_raises(ArgumentError) { @p.opt "badarg4", "desc", :long => "---toomany" }
307
+ end
308
+
309
+ def test_short_detects_bad_names
310
+ @p.opt "goodarg", "desc", :short => "a"
311
+ @p.opt "goodarg2", "desc", :short => "-b"
312
+ assert_raises(ArgumentError) { @p.opt "badarg", "desc", :short => "" }
313
+ assert_raises(ArgumentError) { @p.opt "badarg2", "desc", :short => "-ab" }
314
+ assert_raises(ArgumentError) { @p.opt "badarg3", "desc", :short => "--t" }
315
+ end
316
+
317
+ def test_short_names_created_automatically
318
+ @p.opt "arg"
319
+ @p.opt "arg2"
320
+ @p.opt "arg3"
321
+ opts = @p.parse %w(-a -g)
322
+ assert_equal true, opts["arg"]
323
+ assert_equal false, opts["arg2"]
324
+ assert_equal true, opts["arg3"]
325
+ end
326
+
327
+ def test_short_autocreation_skips_dashes_and_numbers
328
+ @p.opt :arg # auto: a
329
+ @p.opt :arg_potato # auto: r
330
+ @p.opt :arg_muffin # auto: g
331
+ @p.opt :arg_daisy # auto: d (not _)!
332
+ @p.opt :arg_r2d2f # auto: f (not 2)!
333
+
334
+ opts = @p.parse %w(-f -d)
335
+ assert_equal true, opts[:arg_daisy]
336
+ assert_equal true, opts[:arg_r2d2f]
337
+ assert_equal false, opts[:arg]
338
+ assert_equal false, opts[:arg_potato]
339
+ assert_equal false, opts[:arg_muffin]
340
+ end
341
+
342
+ def test_short_autocreation_is_ok_with_running_out_of_chars
343
+ @p.opt :arg1 # auto: a
344
+ @p.opt :arg2 # auto: r
345
+ @p.opt :arg3 # auto: g
346
+ @p.opt :arg4 # auto: uh oh!
347
+ @p.parse []
348
+ end
349
+
350
+ def test_short_can_be_nothing
351
+ @p.opt "arg", "desc", :short => :none
352
+ @p.parse []
353
+
354
+ sio = StringIO.new "w"
355
+ @p.educate sio
356
+ assert sio.string =~ /--arg\s+desc/
357
+
358
+ assert_raises(CommandlineError) { @p.parse %w(-a) }
359
+ end
360
+
361
+ ## two args can't have the same name
362
+ def test_conflicting_names_are_detected
363
+ @p.opt "goodarg"
364
+ assert_raises(ArgumentError) { @p.opt "goodarg" }
365
+ end
366
+
367
+ ## two args can't have the same :long
368
+ def test_conflicting_longs_detected
369
+ @p.opt "goodarg", "desc", :long => "--goodarg"
370
+ assert_raises(ArgumentError) { @p.opt "badarg", "desc", :long => "--goodarg" }
371
+ end
372
+
373
+ ## two args can't have the same :short
374
+ def test_conflicting_shorts_detected
375
+ @p.opt "goodarg", "desc", :short => "-g"
376
+ assert_raises(ArgumentError) { @p.opt "badarg", "desc", :short => "-g" }
377
+ end
378
+
379
+ ## note: this behavior has changed in optimist 2.0!
380
+ def test_flag_parameters
381
+ @p.opt :defaultnone, "desc"
382
+ @p.opt :defaultfalse, "desc", :default => false
383
+ @p.opt :defaulttrue, "desc", :default => true
384
+
385
+ ## default state
386
+ opts = @p.parse []
387
+ assert_equal false, opts[:defaultnone]
388
+ assert_equal false, opts[:defaultfalse]
389
+ assert_equal true, opts[:defaulttrue]
390
+
391
+ ## specifying turns them on, regardless of default
392
+ opts = @p.parse %w(--defaultfalse --defaulttrue --defaultnone)
393
+ assert_equal true, opts[:defaultnone]
394
+ assert_equal true, opts[:defaultfalse]
395
+ assert_equal true, opts[:defaulttrue]
396
+
397
+ ## using --no- form turns them off, regardless of default
398
+ opts = @p.parse %w(--no-defaultfalse --no-defaulttrue --no-defaultnone)
399
+ assert_equal false, opts[:defaultnone]
400
+ assert_equal false, opts[:defaultfalse]
401
+ assert_equal false, opts[:defaulttrue]
402
+ end
403
+
404
+ ## note: this behavior has changed in optimist 2.0!
405
+ def test_flag_parameters_for_inverted_flags
406
+ @p.opt :no_default_none, "desc"
407
+ @p.opt :no_default_false, "desc", :default => false
408
+ @p.opt :no_default_true, "desc", :default => true
409
+
410
+ ## default state
411
+ opts = @p.parse []
412
+ assert_equal false, opts[:no_default_none]
413
+ assert_equal false, opts[:no_default_false]
414
+ assert_equal true, opts[:no_default_true]
415
+
416
+ ## specifying turns them all on, regardless of default
417
+ opts = @p.parse %w(--no-default-false --no-default-true --no-default-none)
418
+ assert_equal true, opts[:no_default_none]
419
+ assert_equal true, opts[:no_default_false]
420
+ assert_equal true, opts[:no_default_true]
421
+
422
+ ## using dropped-no form turns them all off, regardless of default
423
+ opts = @p.parse %w(--default-false --default-true --default-none)
424
+ assert_equal false, opts[:no_default_none]
425
+ assert_equal false, opts[:no_default_false]
426
+ assert_equal false, opts[:no_default_true]
427
+
428
+ ## disallow double negatives for reasons of sanity preservation
429
+ assert_raises(CommandlineError) { @p.parse %w(--no-no-default-true) }
430
+ end
431
+
432
+ def test_short_options_combine
433
+ @p.opt :arg1, "desc", :short => "a"
434
+ @p.opt :arg2, "desc", :short => "b"
435
+ @p.opt :arg3, "desc", :short => "c", :type => :int
436
+
437
+ opts = @p.parse %w(-a -b)
438
+ assert_equal true, opts[:arg1]
439
+ assert_equal true, opts[:arg2]
440
+ assert_nil opts[:arg3]
441
+
442
+ opts = @p.parse %w(-ab)
443
+ assert_equal true, opts[:arg1]
444
+ assert_equal true, opts[:arg2]
445
+ assert_nil opts[:arg3]
446
+
447
+ opts = @p.parse %w(-ac 4 -b)
448
+ assert_equal true, opts[:arg1]
449
+ assert_equal true, opts[:arg2]
450
+ assert_equal 4, opts[:arg3]
451
+
452
+ assert_raises(CommandlineError) { @p.parse %w(-cab 4) }
453
+ assert_raises(CommandlineError) { @p.parse %w(-cba 4) }
454
+ end
455
+
456
+ def test_doubledash_ends_option_processing
457
+ @p.opt :arg1, "desc", :short => "a", :default => 0
458
+ @p.opt :arg2, "desc", :short => "b", :default => 0
459
+ opts = @p.parse %w(-- -a 3 -b 2)
460
+ assert_equal opts[:arg1], 0
461
+ assert_equal opts[:arg2], 0
462
+ assert_equal %w(-a 3 -b 2), @p.leftovers
463
+ opts = @p.parse %w(-a 3 -- -b 2)
464
+ assert_equal opts[:arg1], 3
465
+ assert_equal opts[:arg2], 0
466
+ assert_equal %w(-b 2), @p.leftovers
467
+ opts = @p.parse %w(-a 3 -b 2 --)
468
+ assert_equal opts[:arg1], 3
469
+ assert_equal opts[:arg2], 2
470
+ assert_equal %w(), @p.leftovers
471
+ end
472
+
473
+ def test_wrap
474
+ assert_equal [""], @p.wrap("")
475
+ assert_equal ["a"], @p.wrap("a")
476
+ assert_equal ["one two", "three"], @p.wrap("one two three", :width => 8)
477
+ assert_equal ["one two three"], @p.wrap("one two three", :width => 80)
478
+ assert_equal ["one", "two", "three"], @p.wrap("one two three", :width => 3)
479
+ assert_equal ["onetwothree"], @p.wrap("onetwothree", :width => 3)
480
+ assert_equal [
481
+ "Test is an awesome program that does something very, very important.",
482
+ "",
483
+ "Usage:",
484
+ " test [options] <filenames>+",
485
+ "where [options] are:"], @p.wrap(<<EOM, :width => 100)
486
+ Test is an awesome program that does something very, very important.
487
+
488
+ Usage:
489
+ test [options] <filenames>+
490
+ where [options] are:
491
+ EOM
492
+ end
493
+
494
+ def test_multi_line_description
495
+ out = StringIO.new
496
+ @p.opt :arg, <<-EOM, :type => :int
497
+ This is an arg
498
+ with a multi-line description
499
+ EOM
500
+ @p.educate(out)
501
+ assert_equal <<-EOM, out.string
502
+ Options:
503
+ --arg=<i> This is an arg
504
+ with a multi-line description
505
+ EOM
506
+ end
507
+
508
+ def test_integer_formatting
509
+ @p.opt :arg, "desc", :type => :integer, :short => "i"
510
+ opts = @p.parse %w(-i 5)
511
+ assert_equal 5, opts[:arg]
512
+ end
513
+
514
+ def test_integer_formatting_default
515
+ @p.opt :arg, "desc", :type => :integer, :short => "i", :default => 3
516
+ opts = @p.parse %w(-i)
517
+ assert_equal 3, opts[:arg]
518
+ end
519
+
520
+ def test_floating_point_formatting
521
+ @p.opt :arg, "desc", :type => :float, :short => "f"
522
+ opts = @p.parse %w(-f 1)
523
+ assert_equal 1.0, opts[:arg]
524
+ opts = @p.parse %w(-f 1.0)
525
+ assert_equal 1.0, opts[:arg]
526
+ opts = @p.parse %w(-f 0.1)
527
+ assert_equal 0.1, opts[:arg]
528
+ opts = @p.parse %w(-f .1)
529
+ assert_equal 0.1, opts[:arg]
530
+ opts = @p.parse %w(-f .99999999999999999999)
531
+ assert_equal 1.0, opts[:arg]
532
+ opts = @p.parse %w(-f -1)
533
+ assert_equal(-1.0, opts[:arg])
534
+ opts = @p.parse %w(-f -1.0)
535
+ assert_equal(-1.0, opts[:arg])
536
+ opts = @p.parse %w(-f -0.1)
537
+ assert_equal(-0.1, opts[:arg])
538
+ opts = @p.parse %w(-f -.1)
539
+ assert_equal(-0.1, opts[:arg])
540
+ assert_raises(CommandlineError) { @p.parse %w(-f a) }
541
+ assert_raises(CommandlineError) { @p.parse %w(-f 1a) }
542
+ assert_raises(CommandlineError) { @p.parse %w(-f 1.a) }
543
+ assert_raises(CommandlineError) { @p.parse %w(-f a.1) }
544
+ assert_raises(CommandlineError) { @p.parse %w(-f 1.0.0) }
545
+ assert_raises(CommandlineError) { @p.parse %w(-f .) }
546
+ assert_raises(CommandlineError) { @p.parse %w(-f -.) }
547
+ end
548
+
549
+ def test_floating_point_formatting_default
550
+ @p.opt :arg, "desc", :type => :float, :short => "f", :default => 5.5
551
+ opts = @p.parse %w(-f)
552
+ assert_equal 5.5, opts[:arg]
553
+ end
554
+
555
+ def test_date_formatting
556
+ @p.opt :arg, "desc", :type => :date, :short => 'd'
557
+ opts = @p.parse(['-d', 'Jan 4, 2007'])
558
+ assert_equal Date.civil(2007, 1, 4), opts[:arg]
559
+ end
560
+
561
+ def test_chronic_date_formatting
562
+ # note: only works with chronic gem
563
+ require 'optimist_xl/chronic'
564
+ @p.opt :arg, "chronic", :type => :chronic_date, :short => 'd'
565
+ opts = @p.parse(['-d', 'today'])
566
+ assert_equal Date.today, opts[:arg]
567
+ rescue LoadError
568
+ end
569
+
570
+ def test_short_options_cant_be_numeric
571
+ assert_raises(ArgumentError) { @p.opt :arg, "desc", :short => "-1" }
572
+ @p.opt :a1b, "desc"
573
+ @p.opt :a2b, "desc"
574
+ assert @p.specs[:a2b].short.to_i == 0
575
+ end
576
+
577
+ def test_short_options_can_be_weird
578
+ @p.opt :arg1, "desc", :short => "#"
579
+ @p.opt :arg2, "desc", :short => "."
580
+ assert_raises(ArgumentError) { @p.opt :arg3, "desc", :short => "-" }
581
+ end
582
+
583
+ def test_options_cant_be_set_multiple_times_if_not_specified
584
+ @p.opt :arg, "desc", :short => "-x"
585
+ @p.parse %w(-x)
586
+ assert_raises(CommandlineError) { @p.parse %w(-x -x) }
587
+ assert_raises(CommandlineError) { @p.parse %w(-xx) }
588
+ end
589
+
590
+ def test_options_can_be_set_multiple_times_if_specified
591
+ @p.opt :arg, "desc", :short => "-x", :multi => true
592
+ @p.parse %w(-x)
593
+ @p.parse %w(-x -x)
594
+ @p.parse %w(-xx)
595
+ end
596
+
597
+ def test_short_options_with_multiple_options
598
+ @p.opt :xarg, "desc", :short => "-x", :type => String, :multi => true
599
+ opts = @p.parse %w(-x a -x b)
600
+ assert_equal %w(a b), opts[:xarg]
601
+ assert_equal [], @p.leftovers
602
+ end
603
+
604
+ def test_short_options_with_multiple_options_does_not_affect_flags_type
605
+ @p.opt :xarg, "desc", :short => "-x", :type => :flag, :multi => true
606
+
607
+ opts = @p.parse %w(-x a)
608
+ assert_equal true, opts[:xarg]
609
+ assert_equal %w(a), @p.leftovers
610
+
611
+ opts = @p.parse %w(-x a -x b)
612
+ assert_equal true, opts[:xarg]
613
+ assert_equal %w(a b), @p.leftovers
614
+
615
+ opts = @p.parse %w(-xx a -x b)
616
+ assert_equal true, opts[:xarg]
617
+ assert_equal %w(a b), @p.leftovers
618
+ end
619
+
620
+ def test_short_options_with_multiple_arguments
621
+ @p.opt :xarg, "desc", :type => :ints
622
+ opts = @p.parse %w(-x 3 4 0)
623
+ assert_equal [3, 4, 0], opts[:xarg]
624
+ assert_equal [], @p.leftovers
625
+
626
+ @p.opt :yarg, "desc", :type => :floats
627
+ opts = @p.parse %w(-y 3.14 4.21 0.66)
628
+ assert_equal [3.14, 4.21, 0.66], opts[:yarg]
629
+ assert_equal [], @p.leftovers
630
+
631
+ @p.opt :zarg, "desc", :type => :strings
632
+ opts = @p.parse %w(-z a b c)
633
+ assert_equal %w(a b c), opts[:zarg]
634
+ assert_equal [], @p.leftovers
635
+ end
636
+
637
+ def test_short_options_with_multiple_options_and_arguments
638
+ @p.opt :xarg, "desc", :type => :ints, :multi => true
639
+ opts = @p.parse %w(-x 3 4 5 -x 6 7)
640
+ assert_equal [[3, 4, 5], [6, 7]], opts[:xarg]
641
+ assert_equal [], @p.leftovers
642
+
643
+ @p.opt :yarg, "desc", :type => :floats, :multi => true
644
+ opts = @p.parse %w(-y 3.14 4.21 5.66 -y 6.99 7.01)
645
+ assert_equal [[3.14, 4.21, 5.66], [6.99, 7.01]], opts[:yarg]
646
+ assert_equal [], @p.leftovers
647
+
648
+ @p.opt :zarg, "desc", :type => :strings, :multi => true
649
+ opts = @p.parse %w(-z a b c -z d e)
650
+ assert_equal [%w(a b c), %w(d e)], opts[:zarg]
651
+ assert_equal [], @p.leftovers
652
+ end
653
+
654
+ def test_combined_short_options_with_multiple_arguments
655
+ @p.opt :arg1, "desc", :short => "a"
656
+ @p.opt :arg2, "desc", :short => "b"
657
+ @p.opt :arg3, "desc", :short => "c", :type => :ints
658
+ @p.opt :arg4, "desc", :short => "d", :type => :floats
659
+
660
+ opts = @p.parse %w(-abc 4 6 9)
661
+ assert_equal true, opts[:arg1]
662
+ assert_equal true, opts[:arg2]
663
+ assert_equal [4, 6, 9], opts[:arg3]
664
+
665
+ opts = @p.parse %w(-ac 4 6 9 -bd 3.14 2.41)
666
+ assert_equal true, opts[:arg1]
667
+ assert_equal true, opts[:arg2]
668
+ assert_equal [4, 6, 9], opts[:arg3]
669
+ assert_equal [3.14, 2.41], opts[:arg4]
670
+
671
+ assert_raises(CommandlineError) { opts = @p.parse %w(-abcd 3.14 2.41) }
672
+ end
673
+
674
+ def test_long_options_with_multiple_options
675
+ @p.opt :xarg, "desc", :type => String, :multi => true
676
+ opts = @p.parse %w(--xarg=a --xarg=b)
677
+ assert_equal %w(a b), opts[:xarg]
678
+ assert_equal [], @p.leftovers
679
+ opts = @p.parse %w(--xarg a --xarg b)
680
+ assert_equal %w(a b), opts[:xarg]
681
+ assert_equal [], @p.leftovers
682
+ end
683
+
684
+ def test_long_options_with_multiple_arguments
685
+ @p.opt :xarg, "desc", :type => :ints
686
+ opts = @p.parse %w(--xarg 3 2 5)
687
+ assert_equal [3, 2, 5], opts[:xarg]
688
+ assert_equal [], @p.leftovers
689
+ opts = @p.parse %w(--xarg=3)
690
+ assert_equal [3], opts[:xarg]
691
+ assert_equal [], @p.leftovers
692
+
693
+ @p.opt :yarg, "desc", :type => :floats
694
+ opts = @p.parse %w(--yarg 3.14 2.41 5.66)
695
+ assert_equal [3.14, 2.41, 5.66], opts[:yarg]
696
+ assert_equal [], @p.leftovers
697
+ opts = @p.parse %w(--yarg=3.14)
698
+ assert_equal [3.14], opts[:yarg]
699
+ assert_equal [], @p.leftovers
700
+
701
+ @p.opt :zarg, "desc", :type => :strings
702
+ opts = @p.parse %w(--zarg a b c)
703
+ assert_equal %w(a b c), opts[:zarg]
704
+ assert_equal [], @p.leftovers
705
+ opts = @p.parse %w(--zarg=a)
706
+ assert_equal %w(a), opts[:zarg]
707
+ assert_equal [], @p.leftovers
708
+ end
709
+
710
+ def test_long_options_with_multiple_options_and_arguments
711
+ @p.opt :xarg, "desc", :type => :ints, :multi => true
712
+ opts = @p.parse %w(--xarg 3 2 5 --xarg 2 1)
713
+ assert_equal [[3, 2, 5], [2, 1]], opts[:xarg]
714
+ assert_equal [], @p.leftovers
715
+ opts = @p.parse %w(--xarg=3 --xarg=2)
716
+ assert_equal [[3], [2]], opts[:xarg]
717
+ assert_equal [], @p.leftovers
718
+
719
+ @p.opt :yarg, "desc", :type => :floats, :multi => true
720
+ opts = @p.parse %w(--yarg 3.14 2.72 5 --yarg 2.41 1.41)
721
+ assert_equal [[3.14, 2.72, 5], [2.41, 1.41]], opts[:yarg]
722
+ assert_equal [], @p.leftovers
723
+ opts = @p.parse %w(--yarg=3.14 --yarg=2.41)
724
+ assert_equal [[3.14], [2.41]], opts[:yarg]
725
+ assert_equal [], @p.leftovers
726
+
727
+ @p.opt :zarg, "desc", :type => :strings, :multi => true
728
+ opts = @p.parse %w(--zarg a b c --zarg d e)
729
+ assert_equal [%w(a b c), %w(d e)], opts[:zarg]
730
+ assert_equal [], @p.leftovers
731
+ opts = @p.parse %w(--zarg=a --zarg=d)
732
+ assert_equal [%w(a), %w(d)], opts[:zarg]
733
+ assert_equal [], @p.leftovers
734
+ end
735
+
736
+ def test_long_options_also_take_equals
737
+ @p.opt :arg, "desc", :long => "arg", :type => String, :default => "hello"
738
+ opts = @p.parse %w()
739
+ assert_equal "hello", opts[:arg]
740
+ opts = @p.parse %w(--arg goat)
741
+ assert_equal "goat", opts[:arg]
742
+ opts = @p.parse %w(--arg=goat)
743
+ assert_equal "goat", opts[:arg]
744
+ ## actually, this next one is valid. empty string for --arg, and goat as a
745
+ ## leftover.
746
+ ## assert_raises(CommandlineError) { opts = @p.parse %w(--arg= goat) }
747
+ end
748
+
749
+ def test_auto_generated_long_names_convert_underscores_to_hyphens
750
+ @p.opt :hello_there
751
+ assert_equal "hello-there", @p.specs[:hello_there].long
752
+ end
753
+
754
+ def test_arguments_passed_through_block
755
+ @goat = 3
756
+ boat = 4
757
+ Parser.new(@goat) do |goat|
758
+ boat = goat
759
+ end
760
+ assert_equal @goat, boat
761
+ end
762
+
763
+ ## test-only access reader method so that we dont have to
764
+ ## expose settings in the public API.
765
+ class OptimistXL::Parser
766
+ def get_settings_for_testing ; return @settings ;end
767
+ end
768
+
769
+ def test_two_arguments_passed_through_block
770
+ newp = Parser.new(:abcd => 123, :efgh => "other" ) do |i|
771
+ end
772
+ assert_equal newp.get_settings_for_testing[:abcd], 123
773
+ assert_equal newp.get_settings_for_testing[:efgh], "other"
774
+ end
775
+
776
+
777
+ def test_version_and_help_override_errors
778
+ @p.opt :asdf, "desc", :type => String
779
+ @p.version "version"
780
+ @p.parse %w(--asdf goat)
781
+ assert_raises(CommandlineError) { @p.parse %w(--asdf) }
782
+ assert_raises(HelpNeeded) { @p.parse %w(--asdf --help) }
783
+ assert_raises(HelpNeeded) { @p.parse %w(--asdf -h) }
784
+ assert_raises(VersionNeeded) { @p.parse %w(--asdf --version) }
785
+ end
786
+
787
+ def test_conflicts
788
+ @p.opt :one
789
+ assert_raises(ArgumentError) { @p.conflicts :one, :two }
790
+ @p.opt :two
791
+ @p.conflicts :one, :two
792
+ @p.parse %w(--one)
793
+ @p.parse %w(--two)
794
+ assert_raises(CommandlineError) { @p.parse %w(--one --two) }
795
+
796
+ @p.opt :hello
797
+ @p.opt :yellow
798
+ @p.opt :mellow
799
+ @p.opt :jello
800
+ @p.conflicts :hello, :yellow, :mellow, :jello
801
+ assert_raises(CommandlineError) { @p.parse %w(--hello --yellow --mellow --jello) }
802
+ assert_raises(CommandlineError) { @p.parse %w(--hello --mellow --jello) }
803
+ assert_raises(CommandlineError) { @p.parse %w(--hello --jello) }
804
+
805
+ @p.parse %w(--hello)
806
+ @p.parse %w(--jello)
807
+ @p.parse %w(--yellow)
808
+ @p.parse %w(--mellow)
809
+
810
+ @p.parse %w(--mellow --one)
811
+ @p.parse %w(--mellow --two)
812
+
813
+ assert_raises(CommandlineError) { @p.parse %w(--mellow --two --jello) }
814
+ assert_raises(CommandlineError) { @p.parse %w(--one --mellow --two --jello) }
815
+ end
816
+
817
+ def test_conflict_error_messages
818
+ @p.opt :one
819
+ @p.opt "two"
820
+ @p.conflicts :one, "two"
821
+
822
+ assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--one --two) }
823
+ end
824
+
825
+ def test_depends
826
+ @p.opt :one
827
+ assert_raises(ArgumentError) { @p.depends :one, :two }
828
+ @p.opt :two
829
+ @p.depends :one, :two
830
+ @p.parse %w(--one --two)
831
+ assert_raises(CommandlineError) { @p.parse %w(--one) }
832
+ assert_raises(CommandlineError) { @p.parse %w(--two) }
833
+
834
+ @p.opt :hello
835
+ @p.opt :yellow
836
+ @p.opt :mellow
837
+ @p.opt :jello
838
+ @p.depends :hello, :yellow, :mellow, :jello
839
+ @p.parse %w(--hello --yellow --mellow --jello)
840
+ assert_raises(CommandlineError) { @p.parse %w(--hello --mellow --jello) }
841
+ assert_raises(CommandlineError) { @p.parse %w(--hello --jello) }
842
+
843
+ assert_raises(CommandlineError) { @p.parse %w(--hello) }
844
+ assert_raises(CommandlineError) { @p.parse %w(--mellow) }
845
+
846
+ @p.parse %w(--hello --yellow --mellow --jello --one --two)
847
+ @p.parse %w(--hello --yellow --mellow --jello --one --two a b c)
848
+
849
+ assert_raises(CommandlineError) { @p.parse %w(--mellow --two --jello --one) }
850
+ end
851
+
852
+ def test_depend_error_messages
853
+ @p.opt :one
854
+ @p.opt "two"
855
+ @p.depends :one, "two"
856
+
857
+ @p.parse %w(--one --two)
858
+
859
+ assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--one) }
860
+ assert_raises(CommandlineError, /--one.*--two/) { @p.parse %w(--two) }
861
+ end
862
+
863
+ ## courtesy neill zero
864
+ def test_two_required_one_missing_accuses_correctly
865
+ @p.opt "arg1", "desc1", :required => true
866
+ @p.opt "arg2", "desc2", :required => true
867
+
868
+ assert_raises(CommandlineError, /arg2/) { @p.parse(%w(--arg1)) }
869
+ assert_raises(CommandlineError, /arg1/) { @p.parse(%w(--arg2)) }
870
+ @p.parse(%w(--arg1 --arg2))
871
+ end
872
+
873
+ def test_stopwords_mixed
874
+ @p.opt "arg1", :default => false
875
+ @p.opt "arg2", :default => false
876
+ @p.stop_on %w(happy sad)
877
+
878
+ opts = @p.parse %w(--arg1 happy --arg2)
879
+ assert_equal true, opts["arg1"]
880
+ assert_equal false, opts["arg2"]
881
+
882
+ ## restart parsing
883
+ @p.leftovers.shift
884
+ opts = @p.parse @p.leftovers
885
+ assert_equal false, opts["arg1"]
886
+ assert_equal true, opts["arg2"]
887
+ end
888
+
889
+ def test_stopwords_no_stopwords
890
+ @p.opt "arg1", :default => false
891
+ @p.opt "arg2", :default => false
892
+ @p.stop_on %w(happy sad)
893
+
894
+ opts = @p.parse %w(--arg1 --arg2)
895
+ assert_equal true, opts["arg1"]
896
+ assert_equal true, opts["arg2"]
897
+
898
+ ## restart parsing
899
+ @p.leftovers.shift
900
+ opts = @p.parse @p.leftovers
901
+ assert_equal false, opts["arg1"]
902
+ assert_equal false, opts["arg2"]
903
+ end
904
+
905
+ def test_stopwords_multiple_stopwords
906
+ @p.opt "arg1", :default => false
907
+ @p.opt "arg2", :default => false
908
+ @p.stop_on %w(happy sad)
909
+
910
+ opts = @p.parse %w(happy sad --arg1 --arg2)
911
+ assert_equal false, opts["arg1"]
912
+ assert_equal false, opts["arg2"]
913
+
914
+ ## restart parsing
915
+ @p.leftovers.shift
916
+ opts = @p.parse @p.leftovers
917
+ assert_equal false, opts["arg1"]
918
+ assert_equal false, opts["arg2"]
919
+
920
+ ## restart parsing again
921
+ @p.leftovers.shift
922
+ opts = @p.parse @p.leftovers
923
+ assert_equal true, opts["arg1"]
924
+ assert_equal true, opts["arg2"]
925
+ end
926
+
927
+ def test_stopwords_with_short_args
928
+ @p.opt :global_option, "This is a global option", :short => "-g"
929
+ @p.stop_on %w(sub-command-1 sub-command-2)
930
+
931
+ global_opts = @p.parse %w(-g sub-command-1 -c)
932
+ cmd = @p.leftovers.shift
933
+
934
+ @q = Parser.new
935
+ @q.opt :cmd_option, "This is an option only for the subcommand", :short => "-c"
936
+ cmd_opts = @q.parse @p.leftovers
937
+
938
+ assert_equal true, global_opts[:global_option]
939
+ assert_nil global_opts[:cmd_option]
940
+
941
+ assert_equal true, cmd_opts[:cmd_option]
942
+ assert_nil cmd_opts[:global_option]
943
+
944
+ assert_equal cmd, "sub-command-1"
945
+ assert_equal @q.leftovers, []
946
+ end
947
+
948
+ def test_unknown_subcommand
949
+ @p.opt :global_flag, "Global flag", :short => "-g", :type => :flag
950
+ @p.opt :global_param, "Global parameter", :short => "-p", :default => 5
951
+ @p.stop_on_unknown
952
+
953
+ expected_opts = { :global_flag => true, :help => false, :global_param => 5, :global_flag_given => true }
954
+ expected_leftovers = [ "my_subcommand", "-c" ]
955
+
956
+ assert_parses_correctly @p, %w(--global-flag my_subcommand -c), \
957
+ expected_opts, expected_leftovers
958
+ assert_parses_correctly @p, %w(-g my_subcommand -c), \
959
+ expected_opts, expected_leftovers
960
+
961
+ expected_opts = { :global_flag => false, :help => false, :global_param => 5, :global_param_given => true }
962
+ expected_leftovers = [ "my_subcommand", "-c" ]
963
+
964
+ assert_parses_correctly @p, %w(-p 5 my_subcommand -c), \
965
+ expected_opts, expected_leftovers
966
+ assert_parses_correctly @p, %w(--global-param 5 my_subcommand -c), \
967
+ expected_opts, expected_leftovers
968
+ end
969
+
970
+ def test_alternate_args
971
+ args = %w(-a -b -c)
972
+
973
+ opts = ::OptimistXL.options(args) do
974
+ opt :alpher, "Ralph Alpher", :short => "-a"
975
+ opt :bethe, "Hans Bethe", :short => "-b"
976
+ opt :gamow, "George Gamow", :short => "-c"
977
+ end
978
+
979
+ physicists_with_humor = [:alpher, :bethe, :gamow]
980
+ physicists_with_humor.each do |physicist|
981
+ assert_equal true, opts[physicist]
982
+ end
983
+ end
984
+
985
+ def test_date_arg_type
986
+ temp = Date.new
987
+ @p.opt :arg, 'desc', :type => :date
988
+ @p.opt :arg2, 'desc', :type => Date
989
+ @p.opt :arg3, 'desc', :default => temp
990
+
991
+ opts = @p.parse []
992
+ assert_equal temp, opts[:arg3]
993
+
994
+ opts = @p.parse %w(--arg 2010/05/01)
995
+ assert_kind_of Date, opts[:arg]
996
+ assert_equal Date.new(2010, 5, 1), opts[:arg]
997
+
998
+ opts = @p.parse %w(--arg2 2010/9/13)
999
+ assert_kind_of Date, opts[:arg2]
1000
+ assert_equal Date.new(2010, 9, 13), opts[:arg2]
1001
+
1002
+ opts = @p.parse %w(--arg3)
1003
+ assert_equal temp, opts[:arg3]
1004
+ end
1005
+
1006
+ def test_chronic_date_arg_type
1007
+ require 'optimist_xl/chronic'
1008
+ temp = Date.new
1009
+ @p.opt :arg, 'desc', :type => :chronic_date
1010
+ @p.opt :arg2, 'desc', :type => Chronic::Date
1011
+ @p.opt :arg3, 'desc', :default => temp
1012
+
1013
+ opts = @p.parse []
1014
+ assert_equal temp, opts[:arg3]
1015
+
1016
+ opts = @p.parse %w(--arg 5/1/2010)
1017
+ assert_kind_of Date, opts[:arg]
1018
+ assert_equal Date.new(2010, 5, 1), opts[:arg]
1019
+
1020
+ opts = @p.parse %w(--arg2 5/1/2010)
1021
+ assert_kind_of Date, opts[:arg2]
1022
+ assert_equal Date.new(2010, 5, 1), opts[:arg2]
1023
+
1024
+ opts = @p.parse %w(--arg3)
1025
+ assert_equal temp, opts[:arg3]
1026
+ rescue LoadError
1027
+ end
1028
+
1029
+ def test_unknown_arg_class_type
1030
+ assert_raises ArgumentError do
1031
+ @p.opt :arg, 'desc', :type => Hash
1032
+ end
1033
+ end
1034
+
1035
+ def test_io_arg_type
1036
+ @p.opt :arg, "desc", :type => :io
1037
+ @p.opt :arg2, "desc", :type => IO
1038
+ @p.opt :arg3, "desc", :default => $stdout
1039
+
1040
+ opts = @p.parse []
1041
+ assert_equal $stdout, opts[:arg3]
1042
+
1043
+ opts = @p.parse %w(--arg /dev/null)
1044
+ assert_kind_of File, opts[:arg]
1045
+ assert_equal "/dev/null", opts[:arg].path
1046
+
1047
+ #TODO: move to mocks
1048
+ #opts = @p.parse %w(--arg2 http://google.com/)
1049
+ #assert_kind_of StringIO, opts[:arg2]
1050
+
1051
+ opts = @p.parse %w(--arg3 stdin)
1052
+ assert_equal $stdin, opts[:arg3]
1053
+
1054
+ assert_raises(CommandlineError) { opts = @p.parse %w(--arg /fdasfasef/fessafef/asdfasdfa/fesasf) }
1055
+ end
1056
+
1057
+ def test_openstruct_style_access
1058
+ @p.opt "arg1", "desc", :type => :int
1059
+ @p.opt :arg2, "desc", :type => :int
1060
+
1061
+ opts = @p.parse(%w(--arg1 3 --arg2 4))
1062
+
1063
+ opts.arg1
1064
+ opts.arg2
1065
+ assert_equal 3, opts.arg1
1066
+ assert_equal 4, opts.arg2
1067
+ end
1068
+
1069
+ def test_multi_args_autobox_defaults
1070
+ @p.opt :arg1, "desc", :default => "hello", :multi => true
1071
+ @p.opt :arg2, "desc", :default => ["hello"], :multi => true
1072
+
1073
+ opts = @p.parse []
1074
+ assert_equal ["hello"], opts[:arg1]
1075
+ assert_equal ["hello"], opts[:arg2]
1076
+
1077
+ opts = @p.parse %w(--arg1 hello)
1078
+ assert_equal ["hello"], opts[:arg1]
1079
+ assert_equal ["hello"], opts[:arg2]
1080
+
1081
+ opts = @p.parse %w(--arg1 hello --arg1 there)
1082
+ assert_equal ["hello", "there"], opts[:arg1]
1083
+ end
1084
+
1085
+ def test_ambigious_multi_plus_array_default_resolved_as_specified_by_documentation
1086
+ @p.opt :arg1, "desc", :default => ["potato"], :multi => true
1087
+ @p.opt :arg2, "desc", :default => ["potato"], :multi => true, :type => :strings
1088
+ @p.opt :arg3, "desc", :default => ["potato"]
1089
+ @p.opt :arg4, "desc", :default => ["potato", "rhubarb"], :short => :none, :multi => true
1090
+
1091
+ ## arg1 should be multi-occurring but not multi-valued
1092
+ opts = @p.parse %w(--arg1 one two)
1093
+ assert_equal ["one"], opts[:arg1]
1094
+ assert_equal ["two"], @p.leftovers
1095
+
1096
+ opts = @p.parse %w(--arg1 one --arg1 two)
1097
+ assert_equal ["one", "two"], opts[:arg1]
1098
+ assert_equal [], @p.leftovers
1099
+
1100
+ ## arg2 should be multi-valued and multi-occurring
1101
+ opts = @p.parse %w(--arg2 one two)
1102
+ assert_equal [["one", "two"]], opts[:arg2]
1103
+ assert_equal [], @p.leftovers
1104
+
1105
+ ## arg3 should be multi-valued but not multi-occurring
1106
+ opts = @p.parse %w(--arg3 one two)
1107
+ assert_equal ["one", "two"], opts[:arg3]
1108
+ assert_equal [], @p.leftovers
1109
+
1110
+ ## arg4 should be multi-valued but not multi-occurring
1111
+ opts = @p.parse %w()
1112
+ assert_equal ["potato", "rhubarb"], opts[:arg4]
1113
+ end
1114
+
1115
+ def test_given_keys
1116
+ @p.opt :arg1
1117
+ @p.opt :arg2
1118
+
1119
+ opts = @p.parse %w(--arg1)
1120
+ assert opts[:arg1_given]
1121
+ assert !opts[:arg2_given]
1122
+
1123
+ opts = @p.parse %w(--arg2)
1124
+ assert !opts[:arg1_given]
1125
+ assert opts[:arg2_given]
1126
+
1127
+ opts = @p.parse []
1128
+ assert !opts[:arg1_given]
1129
+ assert !opts[:arg2_given]
1130
+
1131
+ opts = @p.parse %w(--arg1 --arg2)
1132
+ assert opts[:arg1_given]
1133
+ assert opts[:arg2_given]
1134
+ end
1135
+
1136
+ def test_default_shorts_assigned_only_after_user_shorts
1137
+ @p.opt :aab, "aaa" # should be assigned to -b
1138
+ @p.opt :ccd, "bbb" # should be assigned to -d
1139
+ @p.opt :user1, "user1", :short => 'a'
1140
+ @p.opt :user2, "user2", :short => 'c'
1141
+
1142
+ opts = @p.parse %w(-a -b)
1143
+ assert opts[:user1]
1144
+ assert !opts[:user2]
1145
+ assert opts[:aab]
1146
+ assert !opts[:ccd]
1147
+
1148
+ opts = @p.parse %w(-c -d)
1149
+ assert !opts[:user1]
1150
+ assert opts[:user2]
1151
+ assert !opts[:aab]
1152
+ assert opts[:ccd]
1153
+ end
1154
+
1155
+ def test_short_opts_not_implicitly_created
1156
+ newp = Parser.new(:explicit_short_opts => true)
1157
+ newp.opt :user1, "user1"
1158
+ newp.opt :bag, "bag", :short => 'b'
1159
+ assert_raises(CommandlineError) do
1160
+ newp.parse %w(-u)
1161
+ end
1162
+ opts = newp.parse %w(--user1)
1163
+ assert opts[:user1]
1164
+ opts = newp.parse %w(-b)
1165
+ assert opts[:bag]
1166
+ end
1167
+
1168
+ def test_inexact_match
1169
+ newp = Parser.new()
1170
+ newp.opt :liberation, "liberate something", :type => :int
1171
+ newp.opt :evaluate, "evaluate something", :type => :string
1172
+ opts = newp.parse %w(--lib 5 --ev bar)
1173
+ assert_equal 5, opts[:liberation]
1174
+ assert_equal 'bar', opts[:evaluate]
1175
+ assert_nil opts[:eval]
1176
+ end
1177
+
1178
+ def test_exact_match
1179
+ newp = Parser.new(exact_match: true)
1180
+ newp.opt :liberation, "liberate something", :type => :int
1181
+ newp.opt :evaluate, "evaluate something", :type => :string
1182
+ assert_raises(CommandlineError, /unknown argument '--lib'/) do
1183
+ newp.parse %w(--lib 5)
1184
+ end
1185
+ assert_raises_errmatch(CommandlineError, /unknown argument '--ev'/) do
1186
+ newp.parse %w(--ev bar)
1187
+ end
1188
+ end
1189
+
1190
+ def test_inexact_collision
1191
+ newp = Parser.new()
1192
+ newp.opt :bookname, "name of a book", :type => :string
1193
+ newp.opt :bookcost, "cost of the book", :type => :string
1194
+ opts = newp.parse %w(--bookn hairy_potsworth --bookc 10)
1195
+ assert_equal 'hairy_potsworth', opts[:bookname]
1196
+ assert_equal '10', opts[:bookcost]
1197
+ assert_raises(CommandlineError) do
1198
+ newp.parse %w(--book 5) # ambiguous
1199
+ end
1200
+ ## partial match causes 'specified multiple times' error
1201
+ assert_raises(CommandlineError, /specified multiple times/) do
1202
+ newp.parse %w(--bookc 17 --bookcost 22)
1203
+ end
1204
+ end
1205
+
1206
+ def test_inexact_collision_with_exact
1207
+ newp = Parser.new(:inexact_match => true)
1208
+ newp.opt :book, "name of a book", :type => :string, :default => "ABC"
1209
+ newp.opt :bookcost, "cost of the book", :type => :int, :default => 5
1210
+ opts = newp.parse %w(--book warthog --bookc 3)
1211
+ assert_equal 'warthog', opts[:book]
1212
+ assert_equal 3, opts[:bookcost]
1213
+
1214
+ end
1215
+
1216
+ def test_accepts_arguments_with_spaces
1217
+ @p.opt :arg1, "arg", :type => String
1218
+ @p.opt :arg2, "arg2", :type => String
1219
+
1220
+ opts = @p.parse ["--arg1", "hello there", "--arg2=hello there"]
1221
+ assert_equal "hello there", opts[:arg1]
1222
+ assert_equal "hello there", opts[:arg2]
1223
+ assert_equal 0, @p.leftovers.size
1224
+ end
1225
+
1226
+ def test_multi_args_default_to_empty_array
1227
+ @p.opt :arg1, "arg", :multi => true
1228
+ opts = @p.parse []
1229
+ assert_equal [], opts[:arg1]
1230
+ end
1231
+
1232
+ def test_simple_interface_handles_help
1233
+ assert_stdout(/Options:/) do
1234
+ assert_raises(SystemExit) do
1235
+ ::OptimistXL::options(%w(-h)) do
1236
+ opt :potato
1237
+ end
1238
+ end
1239
+ end
1240
+
1241
+ # ensure regular status is returned
1242
+
1243
+ assert_stdout do
1244
+ begin
1245
+ ::OptimistXL::options(%w(-h)) do
1246
+ opt :potato
1247
+ end
1248
+ rescue SystemExit => e
1249
+ assert_equal 0, e.status
1250
+ end
1251
+ end
1252
+ end
1253
+
1254
+ def test_simple_interface_handles_version
1255
+ assert_stdout(/1.2/) do
1256
+ assert_raises(SystemExit) do
1257
+ ::OptimistXL::options(%w(-v)) do
1258
+ version "1.2"
1259
+ opt :potato
1260
+ end
1261
+ end
1262
+ end
1263
+ end
1264
+
1265
+ def test_simple_interface_handles_regular_usage
1266
+ opts = ::OptimistXL::options(%w(--potato)) do
1267
+ opt :potato
1268
+ end
1269
+ assert opts[:potato]
1270
+ end
1271
+
1272
+ def test_simple_interface_handles_die
1273
+ assert_stderr do
1274
+ ::OptimistXL::options(%w(--potato)) do
1275
+ opt :potato
1276
+ end
1277
+ assert_raises(SystemExit) { ::OptimistXL::die :potato, "is invalid" }
1278
+ end
1279
+ end
1280
+
1281
+ def test_simple_interface_handles_die_without_message
1282
+ assert_stderr(/Error:/) do
1283
+ ::OptimistXL::options(%w(--potato)) do
1284
+ opt :potato
1285
+ end
1286
+ assert_raises(SystemExit) { ::OptimistXL::die :potato }
1287
+ end
1288
+ end
1289
+
1290
+ def test_invalid_option_with_simple_interface
1291
+ assert_stderr do
1292
+ assert_raises(SystemExit) do
1293
+ ::OptimistXL.options(%w(--potato))
1294
+ end
1295
+ end
1296
+
1297
+ assert_stderr do
1298
+ begin
1299
+ ::OptimistXL.options(%w(--potato))
1300
+ rescue SystemExit => e
1301
+ assert_equal(-1, e.status)
1302
+ end
1303
+ end
1304
+ end
1305
+
1306
+ def test_supports_callback_inline
1307
+ assert_raises(RuntimeError, "good") do
1308
+ @p.opt :cb1 do |vals|
1309
+ raise "good"
1310
+ end
1311
+ @p.parse(%w(--cb1))
1312
+ end
1313
+ end
1314
+
1315
+ def test_supports_callback_param
1316
+ assert_raises(RuntimeError, "good") do
1317
+ @p.opt :cb1, "with callback", :callback => lambda { |vals| raise "good" }
1318
+ @p.parse(%w(--cb1))
1319
+ end
1320
+ end
1321
+
1322
+ def test_ignore_invalid_options
1323
+ @p.opt :arg1, "desc", :type => String
1324
+ @p.opt :b, "desc", :type => String
1325
+ @p.opt :c, "desc", :type => :flag
1326
+ @p.opt :d, "desc", :type => :flag
1327
+ @p.ignore_invalid_options = true
1328
+ opts = @p.parse %w{unknown -S param --arg1 potato -fb daisy --foo -ecg --bar baz -z}
1329
+ assert_equal "potato", opts[:arg1]
1330
+ assert_equal "daisy", opts[:b]
1331
+ assert opts[:c]
1332
+ refute opts[:d]
1333
+ assert_equal %w{unknown -S param -f --foo -eg --bar baz -z}, @p.leftovers
1334
+ end
1335
+
1336
+ def test_ignore_invalid_options_stop_on_unknown_long
1337
+ @p.opt :arg1, "desc", :type => String
1338
+ @p.ignore_invalid_options = true
1339
+ @p.stop_on_unknown
1340
+ opts = @p.parse %w{--unk --arg1 potato}
1341
+ refute opts[:arg1]
1342
+ assert_equal %w{--unk --arg1 potato}, @p.leftovers
1343
+ end
1344
+
1345
+ def test_ignore_invalid_options_stop_on_unknown_short
1346
+ @p.opt :arg1, "desc", :type => String
1347
+ @p.ignore_invalid_options = true
1348
+ @p.stop_on_unknown
1349
+ opts = @p.parse %w{-ua potato}
1350
+ refute opts[:arg1]
1351
+ assert_equal %w{-ua potato}, @p.leftovers
1352
+ end
1353
+
1354
+ def test_ignore_invalid_options_stop_on_unknown_partial_end_short
1355
+ @p.opt :arg1, "desc", :type => :flag
1356
+ @p.ignore_invalid_options = true
1357
+ @p.stop_on_unknown
1358
+ opts = @p.parse %w{-au potato}
1359
+ assert opts[:arg1]
1360
+ assert_equal %w{-u potato}, @p.leftovers
1361
+ end
1362
+
1363
+ def test_ignore_invalid_options_stop_on_unknown_partial_mid_short
1364
+ @p.opt :arg1, "desc", :type => :flag
1365
+ @p.ignore_invalid_options = true
1366
+ @p.stop_on_unknown
1367
+ opts = @p.parse %w{-abu potato}
1368
+ assert opts[:arg1]
1369
+ assert_equal %w{-bu potato}, @p.leftovers
1370
+ end
1371
+
1372
+ # Due to strangeness in how the cloaker works, there were
1373
+ # cases where OptimistXL.parse would work, but OptimistXL.options
1374
+ # did not, depending on arguments given to the function.
1375
+ # These serve to validate different args given to OptimistXL.options
1376
+ def test_options_takes_hashy_settings
1377
+ passargs_copy = []
1378
+ settings_copy = []
1379
+ ::OptimistXL.options(%w(--wig --pig), :fizz=>:buzz, :bear=>:cat) do |*passargs|
1380
+ opt :wig
1381
+ opt :pig
1382
+ passargs_copy = passargs.dup
1383
+ settings_copy = @settings
1384
+ end
1385
+ assert_equal [], passargs_copy
1386
+ assert_equal settings_copy[:fizz], :buzz
1387
+ assert_equal settings_copy[:bear], :cat
1388
+ end
1389
+
1390
+ def test_options_takes_some_other_data
1391
+ passargs_copy = []
1392
+ settings_copy = []
1393
+ ::OptimistXL.options(%w(--nose --close), 1, 2, 3) do |*passargs|
1394
+ opt :nose
1395
+ opt :close
1396
+ passargs_copy = passargs.dup
1397
+ settings_copy = @settings
1398
+ end
1399
+ assert_equal [1,2,3], passargs_copy
1400
+ assert_equal(::OptimistXL::Parser::DEFAULT_SETTINGS, settings_copy)
1401
+ end
1402
+ end
1403
+
1404
+ end