optimist_xl 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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