benry-cmdopt 1.0.0 → 2.0.0

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.
data/test/cmdopt_test.rb CHANGED
@@ -1,921 +1,1612 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require 'minitest/spec'
4
- require 'minitest/autorun'
5
- require 'minitest/ok'
3
+ require 'oktest'
6
4
 
7
5
  require 'benry/cmdopt'
8
6
 
9
7
 
10
- def new_sample_schema()
11
- sc = Benry::Cmdopt::Schema.new
12
- sc.add(:help , "-h, --help" , "show help message.")
13
- sc.add(:version, "--version" , "print version")
14
- sc.add(:file , "-f, --file=<FILE>" , "filename")
15
- sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
16
- sc.add(:mode , "-m, --mode=<MODE>" , "mode", enum: ['verbose', 'quiet'])
17
- sc.add(:libpath, "-I, --path=<PATH>" , "library path (multiple ok)") do |optdef, key, val|
18
- File.directory?(val) or raise "directory not exist."
19
- arr = optdef[key] || []
20
- arr << val
21
- arr
8
+ Oktest.scope do
9
+
10
+
11
+ def new_sample_schema()
12
+ sc = Benry::CmdOpt::Schema.new
13
+ sc.add(:help , "-h, --help" , "show help message.")
14
+ sc.add(:version, "--version" , "print version")
15
+ sc.add(:file , "-f, --file=<FILE>" , "filename")
16
+ sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
17
+ sc.add(:mode , "-m, --mode=<MODE>" , "mode", enum: ['verbose', 'quiet'])
18
+ sc.add(:libpath, "-I, --path=<PATH>" , "library path (multiple ok)") do |optdef, key, val|
19
+ File.directory?(val) or raise "Directory not exist."
20
+ arr = optdef[key] || []
21
+ arr << val
22
+ arr
23
+ end
24
+ sc
22
25
  end
23
- sc
24
- end
25
26
 
26
27
 
27
28
 
28
- class Benry::Cmdopt::Schema::Test < MiniTest::Test
29
+ topic Benry::CmdOpt::Schema do
29
30
 
30
31
 
31
- describe "#parse()" do
32
+ topic '#parse()' do
32
33
 
33
- before do
34
- @schema = Benry::Cmdopt::Schema.new
35
- end
34
+ before do
35
+ @schema = Benry::CmdOpt::Schema.new
36
+ end
36
37
 
37
- it "[!qw0ac] parses command option definition string." do
38
- sc = @schema
39
- tuple = sc.__send__(:parse_optdef, "-h, --help")
40
- ok {tuple} == ['h', 'help', nil, false]
41
- tuple = sc.__send__(:parse_optdef, "-h")
42
- ok {tuple} == ['h', nil, nil, false]
43
- tuple = sc.__send__(:parse_optdef, "--help")
44
- ok {tuple} == [nil, 'help', nil, false]
45
- end
38
+ spec "[!qw0ac] parses command option definition string." do
39
+ sc = @schema
40
+ tuple = sc.__send__(:parse_optdef, "-h, --help")
41
+ ok {tuple} == ['h', 'help', nil, nil]
42
+ tuple = sc.__send__(:parse_optdef, "-h")
43
+ ok {tuple} == ['h', nil, nil, nil]
44
+ tuple = sc.__send__(:parse_optdef, "--help")
45
+ ok {tuple} == [nil, 'help', nil, nil]
46
+ end
46
47
 
47
- it "[!ae733] parses command option definition which has a required param." do
48
- sc = @schema
49
- tuple = sc.__send__(:parse_optdef, "-f, --file=<FILE>")
50
- ok {tuple} == ['f', 'file', '<FILE>', false]
51
- tuple = sc.__send__(:parse_optdef, "-f <FILE>")
52
- ok {tuple} == ['f', nil, '<FILE>', false]
53
- tuple = sc.__send__(:parse_optdef, "--file=<FILE>")
54
- ok {tuple} == [nil, 'file', '<FILE>', false]
55
- end
48
+ spec "[!ae733] parses command option definition which has a required param." do
49
+ sc = @schema
50
+ tuple = sc.__send__(:parse_optdef, "-f, --file=<FILE>")
51
+ ok {tuple} == ['f', 'file', '<FILE>', true]
52
+ tuple = sc.__send__(:parse_optdef, "-f <FILE>")
53
+ ok {tuple} == ['f', nil, '<FILE>', true]
54
+ tuple = sc.__send__(:parse_optdef, "--file=<FILE>")
55
+ ok {tuple} == [nil, 'file', '<FILE>', true]
56
+ end
57
+
58
+ spec "[!4h05c] parses command option definition which has an optional param." do
59
+ sc = @schema
60
+ tuple = sc.__send__(:parse_optdef, "-i, --indent[=<WIDTH>]")
61
+ ok {tuple} == ['i', 'indent', '<WIDTH>', false]
62
+ tuple = sc.__send__(:parse_optdef, "-i[<WIDTH>]")
63
+ ok {tuple} == ['i', nil, '<WIDTH>', false]
64
+ tuple = sc.__send__(:parse_optdef, "--indent[=<WIDTH>]")
65
+ ok {tuple} == [nil, 'indent', '<WIDTH>', false]
66
+ end
67
+
68
+ spec "[!b7jo3] raises SchemaError when command option definition is invalid." do
69
+ sc = @schema
70
+ pr = proc {
71
+ tuple = sc.__send__(:parse_optdef, "-i, --indent <WIDTH>")
72
+ }
73
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
74
+ "-i, --indent <WIDTH>: Invalid option definition (use '=--indent' instead of ' --indent').")
75
+ end
56
76
 
57
- it "[!4h05c] parses command option definition which has an optional param." do
58
- sc = @schema
59
- tuple = sc.__send__(:parse_optdef, "-i, --indent[=<WIDTH>]")
60
- ok {tuple} == ['i', 'indent', '<WIDTH>', true]
61
- tuple = sc.__send__(:parse_optdef, "-i[<WIDTH>]")
62
- ok {tuple} == ['i', nil, '<WIDTH>', true]
63
- tuple = sc.__send__(:parse_optdef, "--indent[=<WIDTH>]")
64
- ok {tuple} == [nil, 'indent', '<WIDTH>', true]
65
77
  end
66
78
 
67
- it "[!b7jo3] raises SchemaError when command option definition is invalid." do
68
- sc = @schema
69
- pr = proc {
70
- tuple = sc.__send__(:parse_optdef, "-i, --indent <WIDTH>")
71
- }
72
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
73
- "-i, --indent <WIDTH>: invalid option definition (use '=--indent' instead of ' --indent').")
79
+
80
+ topic '#dup()' do
81
+
82
+ before do
83
+ @schema = Benry::CmdOpt::Schema.new
84
+ @schema.add(:help , "-h" , "print help")
85
+ end
86
+
87
+ spec "[!lxb0o] copies self object." do
88
+ this = @schema
89
+ other = @schema.dup()
90
+ #
91
+ this_items = this.instance_variable_get(:@items)
92
+ other_items = other.instance_variable_get(:@items)
93
+ ok {this_items} != nil
94
+ ok {other_items} != nil
95
+ ok {other_items} == this_items
96
+ ok {other_items.object_id} != this_items.object_id
97
+ #
98
+ this.add(:silent, "-s", "silent")
99
+ other.add(:quiet, "-q", "quiet")
100
+ ok {this.option_help()} == (" -h : print help\n" +
101
+ " -s : silent\n")
102
+ ok {other.option_help()} == (" -h : print help\n" +
103
+ " -q : quiet\n")
104
+ end
105
+
74
106
  end
75
107
 
76
- end
77
108
 
109
+ topic '#copy_from()' do
110
+
111
+ before do
112
+ @schema1 = Benry::CmdOpt::Schema.new
113
+ @schema1.add(:help, "-h" , "print help")
114
+ @schema2 = Benry::CmdOpt::Schema.new
115
+ @schema2.add(:version, "-v" , "print version")
116
+ @schema2.add(:debug , "-D" , "debug mode")
117
+ end
118
+
119
+ spec "[!6six3] copy schema items from others." do
120
+ @schema1.copy_from(@schema2)
121
+ tuples = @schema1.each.collect {|x| [x.key, x.optdef, x.desc] }
122
+ ok {tuples} == [
123
+ [:help , "-h", "print help"],
124
+ [:version, "-v", "print version"],
125
+ [:debug , "-D", "debug mode"],
126
+ ]
127
+ end
128
+
129
+ spec "[!vt88s] copy schema items except items specified by 'except:' kwarg." do
130
+ @schema1.copy_from(@schema2, except: [:debug])
131
+ tuples = @schema1.each.collect {|x| [x.key, x.optdef, x.desc] }
132
+ ok {tuples} == [
133
+ [:help, "-h", "print help"],
134
+ [:version, "-v", "print version"],
135
+ ]
136
+ end
78
137
 
79
- describe "#add()" do
80
-
81
- before do
82
- @schema = Benry::Cmdopt::Schema.new
83
- end
84
-
85
- it "[!7hi2d] takes command option definition string." do
86
- sc = @schema
87
- sc.add(:indent, "-i, --indent=<WIDTH>", "print help")
88
- items = sc.instance_eval { @items }
89
- ok {items.length} == 1
90
- ok {items[0]}.is_a?(Benry::Cmdopt::SchemaItem)
91
- ok {items[0].key} == :indent
92
- ok {items[0].short} == 'i'
93
- ok {items[0].long} == 'indent'
94
- ok {items[0].param} == '<WIDTH>'
95
- ok {items[0].optional} == false
96
- ok {items[0].type} == nil
97
- ok {items[0].pattern} == nil
98
- ok {items[0].enum} == nil
99
- ok {items[0].callback} == nil
100
- end
101
-
102
- it "[!p9924] option key is omittable only when long option specified." do
103
- sc = @schema
104
- sc.add(nil, "-m, --max-num=<N>", nil)
105
- items = sc.instance_eval { @items }
106
- ok {items[0].key} == :max_num
107
- end
108
-
109
- it "[!jtp7z] raises SchemaError when key is nil and no long option." do
110
- sc = @schema
111
- pr = proc { sc.add(nil, "-i <N>", nil) }
112
- msg = "add(nil, \"-i <N>\"): long option required when option key (1st arg) not specified."
113
- ok {pr}.raise?(Benry::Cmdopt::SchemaError, msg)
114
- end
115
-
116
- it "[!yht0v] keeps command option definitions." do
117
- sc = @schema
118
- sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width",
119
- type: Integer, pattern: /\A\d+\z/, enum: ['2', '4', '8']) {|v| v.to_i }
120
- items = sc.instance_eval { @items }
121
- ok {items.length} == 1
122
- ok {items[0]}.is_a?(Benry::Cmdopt::SchemaItem)
123
- ok {items[0].key} == :indent
124
- ok {items[0].short} == 'i'
125
- ok {items[0].long} == 'indent'
126
- ok {items[0].param} == '<WIDTH>'
127
- ok {items[0].optional} == true
128
- ok {items[0].type} == Integer
129
- ok {items[0].pattern} == /\A\d+\z/
130
- ok {items[0].enum} == ['2', '4', '8']
131
- ok {items[0].callback}.is_a?(Proc)
132
- ok {items[0].callback.arity} == 1
133
- end
134
-
135
- it "[!rhhji] raises SchemaError when key is not a Symbol." do
136
- sc = @schema
137
- pr = proc {
138
- sc.add("-i, --indent[=<WIDTH>]", "indent width", nil)
139
- }
140
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
141
- 'add("-i, --indent[=<WIDTH>]"): 1st arg should be a Symbol as an option key.')
142
- end
143
-
144
- it "[!vq6eq] raises SchemaError when help message is missing." do
145
- sc = @schema
146
- pr = proc {
147
- begin
148
- sc.add(:indent, "-i, --indent[=<WIDTH>]", type: Array) # Ruby 2
149
- rescue ArgumentError
150
- sc.add(:indent, "-i, --indent[=<WIDTH>]", {type: Array}) # Ruby 3
151
- end
152
- }
153
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
154
- 'add(:indent, "-i, --indent[=<WIDTH>]"): help message required as 3rd argument.')
155
- end
156
-
157
- it "[!7xmr5] raises SchemaError when type is not registered." do
158
- sc = @schema
159
- pr = proc {
160
- sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width", type: Array)
161
- }
162
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
163
- "Array: unregistered type.")
164
- end
165
-
166
- it "[!s2aaj] raises SchemaError when option has no params but type specified." do
167
- sc = @schema
168
- pr = proc {
169
- sc.add(:indent, "-i, --indent", "indent width", type: Integer)
170
- }
171
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
172
- "Integer: type specified in spite of option has no params.")
173
- end
174
-
175
- it "[!bi2fh] raises SchemaError when pattern is not a regexp." do
176
- sc = @schema
177
- pr = proc {
178
- sc.add(:indent, "-x, --indent[=<WIDTH>]", "indent width", pattern: '\A\d+\z')
179
- }
180
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
181
- '"\\\\A\\\\d+\\\\z": regexp expected.')
182
- end
183
-
184
- it "[!01fmt] raises SchmeaError when option has no params but pattern specified." do
185
- sc = @schema
186
- pr = proc {
187
- sc.add(:indent, "-i, --indent", "indent width", pattern: /\A\d+\z/)
188
- }
189
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
190
- '/\A\d+\z/: pattern specified in spite of option has no params.')
191
- end
192
-
193
- it "[!melyd] raises SchmeaError when enum is not a Array nor Set." do
194
- sc = @schema
195
- sc.add(:indent, "-i <N>", "indent width", enum: ["2", "4", "8"])
196
- sc.add(:indent, "-i <N>", "indent width", enum: Set.new(["2", "4", "8"]))
197
- pr = proc {
198
- sc.add(:indent, "-i <N>", "indent width", enum: "2,4,8")
199
- }
200
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
201
- '"2,4,8": array or set expected.')
202
- end
203
-
204
- it "[!xqed8] raises SchemaError when enum specified for no param option." do
205
- sc = @schema
206
- pr = proc {
207
- sc.add(:indent, "-i", "enable indent", enum: [2, 4, 8])
208
- }
209
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
210
- "[2, 4, 8]: enum specified in spite of option has no params.")
211
138
  end
212
139
 
213
- end
214
140
 
141
+ topic '#add()' do
142
+
143
+ before do
144
+ @schema = Benry::CmdOpt::Schema.new
145
+ end
146
+
147
+ spec "[!7hi2d] takes command option definition string." do
148
+ sc = @schema
149
+ sc.add(:indent, "-i, --indent=<WIDTH>", "print help")
150
+ items = sc.instance_eval { @items }
151
+ ok {items.length} == 1
152
+ ok {items[0]}.is_a?(Benry::CmdOpt::SchemaItem)
153
+ ok {items[0].key} == :indent
154
+ ok {items[0].short} == 'i'
155
+ ok {items[0].long} == 'indent'
156
+ ok {items[0].param} == '<WIDTH>'
157
+ ok {items[0].required?} == true
158
+ ok {items[0].type} == nil
159
+ ok {items[0].rexp} == nil
160
+ ok {items[0].enum} == nil
161
+ ok {items[0].callback} == nil
162
+ end
163
+
164
+ spec "[!p9924] option key is omittable only when long option specified." do
165
+ sc = @schema
166
+ sc.add(nil, "-m, --max-num=<N>", nil)
167
+ items = sc.instance_eval { @items }
168
+ ok {items[0].key} == :max_num
169
+ end
170
+
171
+ spec "[!jtp7z] raises SchemaError when key is nil and no long option." do
172
+ sc = @schema
173
+ pr = proc { sc.add(nil, "-i <N>", nil) }
174
+ msg = "add(nil, \"-i <N>\"): Long option required when option key (1st arg) not specified."
175
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError, msg)
176
+ end
177
+
178
+ spec "[!rpl98] when long option is 'foo-bar' then key name is ':foo_bar'." do
179
+ sc = @schema
180
+ sc.add(nil, "--foo-bar", nil)
181
+ items = sc.instance_eval { @items }
182
+ ok {items[0].key} == :foo_bar
183
+ end
184
+
185
+ spec "[!97sn0] raises SchemaError when ',' is missing between short and long options." do
186
+ sc = @schema
187
+ pr = proc { sc.add(:exec, '-x --exec=ARG', "exec") }
188
+ msg = "add(:exec, \"-x --exec=ARG\"): Missing ',' between short option and long options."
189
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError, msg)
190
+ end
191
+
192
+ spec "[!yht0v] keeps command option definitions." do
193
+ sc = @schema
194
+ sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width",
195
+ range: (1..2), value: 8, detail: "(description)", tag: :ab,
196
+ type: Integer, rexp: /\A\d+\z/, enum: [2, 4, 8]) {|v| v.to_i }
197
+ items = sc.instance_eval { @items }
198
+ ok {items.length} == 1
199
+ ok {items[0]}.is_a?(Benry::CmdOpt::SchemaItem)
200
+ ok {items[0].key} == :indent
201
+ ok {items[0].short} == 'i'
202
+ ok {items[0].long} == 'indent'
203
+ ok {items[0].param} == '<WIDTH>'
204
+ ok {items[0].required?} == false
205
+ ok {items[0].type} == Integer
206
+ ok {items[0].rexp} == /\A\d+\z/
207
+ ok {items[0].enum} == [2, 4, 8]
208
+ ok {items[0].range} == (1..2)
209
+ ok {items[0].detail} == "(description)"
210
+ ok {items[0].value} == 8
211
+ ok {items[0].tag} == :ab
212
+ ok {items[0].callback}.is_a?(Proc)
213
+ ok {items[0].callback.arity} == 1
214
+ end
215
+
216
+ spec "[!kuhf9] type, rexp, enum, and range are can be passed as positional args as well as keyword args." do
217
+ sc = @schema
218
+ sc.add(:key, "--optdef=xx", "desc", Integer, /\A\d+\z/, [2,4,8], (2..8))
219
+ item = sc.each.first
220
+ ok {item.type} == Integer
221
+ ok {item.rexp} == /\A\d+\z/
222
+ ok {item.enum} == [2,4,8]
223
+ ok {item.range} == (2..8)
224
+ end
225
+
226
+ spec "[!e3emy] raises error when positional arg is not one of class, regexp, array, nor range." do
227
+ sc = @schema
228
+ pr = proc { sc.add(:key, "--optdef=xx", "desc", "value") }
229
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
230
+ '"value": Expected one of class, regexp, array or range, but got String.')
231
+ end
232
+
233
+ spec "[!rhhji] raises SchemaError when key is not a Symbol." do
234
+ sc = @schema
235
+ pr = proc {
236
+ sc.add("-i, --indent[=<WIDTH>]", "indent width", nil)
237
+ }
238
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
239
+ 'add("-i, --indent[=<WIDTH>]", "indent width"): The first arg should be a Symbol as an option key.')
240
+ end
241
+
242
+ spec "[!vq6eq] raises SchemaError when help message is missing." do
243
+ sc = @schema
244
+ pr = proc {
245
+ begin
246
+ sc.add(:indent, "-i, --indent[=<WIDTH>]", type: Array) # Ruby 2
247
+ rescue ArgumentError
248
+ sc.add(:indent, "-i, --indent[=<WIDTH>]", {type: Array}) # Ruby 3
249
+ end
250
+ }
251
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
252
+ 'add(:indent, "-i, --indent[=<WIDTH>]"): Help message required as 3rd argument.')
253
+ end
215
254
 
216
- describe '#build_option_help()' do
217
255
 
218
- before do
219
- sc = Benry::Cmdopt::Schema.new
220
- sc.add(:help , "-h, --help" , "show help message.")
221
- sc.add(:version, " --version" , "print version")
222
- sc.add(:file , "-f, --file=<FILE>" , "filename")
223
- sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
224
- sc.add(:debug , "-d, --debug" , nil)
225
- @schema = sc
226
256
  end
227
257
 
228
- it "[!0aq0i] can take integer as width." do
229
- help = @schema.build_option_help(41)
230
- ok {help} == <<END
231
- -h, --help : show help message.
232
- --version : print version
233
- -f, --file=<FILE> : filename
234
- -i, --indent[=<WIDTH>] : enable indent
258
+
259
+ topic '#option_help()' do
260
+
261
+ before do
262
+ sc = Benry::CmdOpt::Schema.new
263
+ sc.add(:help , "-h, --help" , "show help message.")
264
+ sc.add(:version, " --version" , "print version")
265
+ sc.add(:file , "-f, --file=<FILE>" , "filename")
266
+ sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
267
+ sc.add(:debug , "-d, --debug" , nil)
268
+ @schema = sc
269
+ end
270
+
271
+ spec "[!0aq0i] can take integer as width." do
272
+ helpmsg = @schema.option_help(41)
273
+ ok {helpmsg} == <<END
274
+ -h, --help : show help message.
275
+ --version : print version
276
+ -f, --file=<FILE> : filename
277
+ -i, --indent[=<WIDTH>] : enable indent
235
278
  END
236
- s = help.each_line.first.split(':')[0]
237
- ok {s.length} == 41+2
238
- end
279
+ s = helpmsg.each_line.first.split(':')[0]
280
+ ok {s.length} == 41+3
281
+ end
239
282
 
240
- it "[!pcsah] can take format string." do
241
- help = @schema.build_option_help("%-42s: %s")
242
- ok {help} == <<END
283
+ spec "[!pcsah] can take format string." do
284
+ helpmsg = @schema.option_help("%-42s: %s")
285
+ ok {helpmsg} == <<END
243
286
  -h, --help : show help message.
244
287
  --version : print version
245
288
  -f, --file=<FILE> : filename
246
289
  -i, --indent[=<WIDTH>] : enable indent
247
290
  END
248
- s = help.each_line.first.split(':')[0]
249
- ok {s.length} == 42+0
250
- end
291
+ s = helpmsg.each_line.first.split(':')[0]
292
+ ok {s.length} == 42+0
293
+ end
251
294
 
252
- it "[!dndpd] detects option width automatically when nothing specified." do
253
- help = @schema.build_option_help()
254
- ok {help} == <<END
295
+ spec "[!dndpd] detects option width automatically when nothing specified." do
296
+ helpmsg = @schema.option_help()
297
+ ok {helpmsg} == <<END
255
298
  -h, --help : show help message.
256
299
  --version : print version
257
300
  -f, --file=<FILE> : filename
258
301
  -i, --indent[=<WIDTH>] : enable indent
259
302
  END
260
- s = help.each_line.to_a.last.split(':')[0]
261
- ok {s.length} == 25
262
- end
303
+ s = helpmsg.each_line.to_a.last.split(':')[0]
304
+ ok {s.length} == 25
305
+ end
263
306
 
264
- it "[!v7z4x] skips option help if help message is not specified." do
265
- help = @schema.build_option_help()
266
- ok {help} !~ /debug/
267
- end
307
+ spec "[!v7z4x] skips option help if help message is not specified." do
308
+ helpmsg = @schema.option_help()
309
+ ok {helpmsg} !~ /debug/
310
+ end
268
311
 
269
- it "[!to1th] includes all option help when `all` is true." do
270
- help = @schema.build_option_help(nil, all: true)
271
- ok {help} =~ /debug/
272
- ok {help} == <<END
312
+ spec "[!to1th] includes all option help when `all` is true." do
313
+ helpmsg = @schema.option_help(nil, all: true)
314
+ ok {helpmsg} =~ /debug/
315
+ ok {helpmsg} == <<END
273
316
  -h, --help : show help message.
274
317
  --version : print version
275
318
  -f, --file=<FILE> : filename
276
319
  -i, --indent[=<WIDTH>] : enable indent
277
320
  -d, --debug :
278
321
  END
279
- end
322
+ end
280
323
 
281
- it "[!848rm] supports multi-lines help message." do
282
- sc = Benry::Cmdopt::Schema.new
283
- sc.add(:mode, "-m, --mode=<MODE>", <<END)
284
- output mode
324
+ spec "[!848rm] supports multi-lines help message." do
325
+ sc = Benry::CmdOpt::Schema.new
326
+ sc.add(:mode, "-m, --mode=<MODE>", "output mode",
327
+ detail: <<"END")
285
328
  v, verbose: print many output
286
329
  q, quiet: print litte output
287
330
  c, compact: print summary output
288
331
  END
289
- actual = sc.build_option_help()
290
- expected = <<END
332
+ actual = sc.option_help()
333
+ expected = <<END
291
334
  -m, --mode=<MODE> : output mode
292
335
  v, verbose: print many output
293
336
  q, quiet: print litte output
294
337
  c, compact: print summary output
295
338
  END
296
- ok {actual} == expected
339
+ ok {actual} == expected
340
+ end
341
+
342
+ spec "[!a4qe4] option should not be hidden if description is empty string." do
343
+ sc = Benry::CmdOpt::Schema.new
344
+ sc.add(:debug , "-D", nil) # hidden
345
+ sc.add(:_trace, "-T", "trace") # hidden
346
+ sc.add(:what , "-W", "") # NOT hidden!
347
+ ok {sc.option_help()} == <<END
348
+ -W :
349
+ END
350
+ end
351
+
297
352
  end
298
353
 
299
- end
300
354
 
355
+ topic '#_default_format()' do
301
356
 
302
- describe '#_default_format()' do
357
+ before do
358
+ sc = Benry::CmdOpt::Schema.new
359
+ sc.add(:help , "-h, --help" , "show help message.")
360
+ sc.add(:version, " --version" , "print version")
361
+ sc.add(:file , "-f, --file=<FILE>" , "filename")
362
+ sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
363
+ sc.add(:debug , "-d, --debug" , nil)
364
+ @schema = sc
365
+ end
303
366
 
304
- before do
305
- sc = Benry::Cmdopt::Schema.new
306
- sc.add(:help , "-h, --help" , "show help message.")
307
- sc.add(:version, " --version" , "print version")
308
- sc.add(:file , "-f, --file=<FILE>" , "filename")
309
- sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
310
- sc.add(:debug , "-d, --debug" , nil)
311
- @schema = sc
312
- end
367
+ spec "[!kkh9t] returns format string." do
368
+ ret = @schema.__send__(:_default_format)
369
+ ok {ret} == " %-22s : %s"
370
+ end
313
371
 
314
- it "[!kkh9t] returns format string." do
315
- ret = @schema.__send__(:_default_format)
316
- ok {ret} == " %-22s : %s"
317
- end
372
+ spec "[!hr45y] detects preffered option width." do
373
+ ret = @schema.__send__(:_default_format, 10, 20)
374
+ ok {ret} == " %-20s : %s"
375
+ ret = @schema.__send__(:_default_format, 30, 40)
376
+ ok {ret} == " %-30s : %s"
377
+ ret = @schema.__send__(:_default_format, 10, 40)
378
+ ok {ret} == " %-22s : %s"
379
+ end
380
+
381
+ spec "[!bmr7d] changes min_with according to options." do
382
+ sc = Benry::CmdOpt::Schema.new
383
+ sc.add(:help , '-h', "help")
384
+ sc.add(:version, '-v', "version")
385
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-8s : %s"
386
+ #
387
+ sc.add(:file , '-f <FILE>', "filename")
388
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
389
+ #
390
+ sc.add(:force , '--force', "forcedly")
391
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
392
+ #
393
+ sc.add(:mode , '-m, --mode=<MODE>', "verbose/quiet")
394
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-20s : %s"
395
+ end
318
396
 
319
- it "[!hr45y] detects preffered option width." do
320
- ret = @schema.__send__(:_default_format, 10, 20)
321
- ok {ret} == " %-20s : %s"
322
- ret = @schema.__send__(:_default_format, 30, 40)
323
- ok {ret} == " %-30s : %s"
324
- ret = @schema.__send__(:_default_format, 10, 40)
325
- ok {ret} == " %-22s : %s"
326
397
  end
327
398
 
328
- end
329
399
 
400
+ topic '#_preferred_option_width()' do
330
401
 
331
- describe '#each_option_help()' do
402
+ spec "[!kl91t] shorten option help min width when only single options which take no arg." do
403
+ sc = Benry::CmdOpt::Schema.new
404
+ sc.add(:help , '-h', "help")
405
+ sc.add(:version, '-v', "version")
406
+ ok {sc.__send__(:_preferred_option_width)} == 8
407
+ end
408
+
409
+ spec "[!0koqb] widen option help min width when any option takes an arg." do
410
+ sc = Benry::CmdOpt::Schema.new
411
+ sc.add(:help , '-h', "help")
412
+ sc.add(:indent , '-i[<N>]', "indent")
413
+ ok {sc.__send__(:_preferred_option_width)} == 14
414
+ end
415
+
416
+ spec "[!kl91t] widen option help min width when long option exists." do
417
+ sc = Benry::CmdOpt::Schema.new
418
+ sc.add(:help , '-h', "help")
419
+ sc.add(:version, '-v, --version', "version")
420
+ ok {sc.__send__(:_preferred_option_width)} == 14
421
+ #
422
+ sc.add(:file, '--file=<FILE>', "filename")
423
+ ok {sc.__send__(:_preferred_option_width)} == 20
424
+ end
332
425
 
333
- before do
334
- sc = Benry::Cmdopt::Schema.new
335
- sc.add(:help, "-h, --help", "show help message")
336
- sc.add(:version, " --version", "print version")
337
- @schema = sc
338
426
  end
339
427
 
340
- it "[!4b911] yields each optin definition str and help message." do
341
- sc = @schema
342
- arr = []
343
- sc.each_option_help do |opt, help|
344
- arr << [opt, help]
428
+
429
+ topic '#to_s()' do
430
+
431
+ spec "[!rrapd] '#to_s' is an alias to '#option_help()'." do
432
+ schema = Benry::CmdOpt::Schema.new
433
+ schema.add(:help , "-h, --help" , "show help message")
434
+ schema.add(:version, " --version" , "print version")
435
+ ok {schema.to_s} == schema.option_help()
345
436
  end
346
- ok {arr} == [
347
- ["-h, --help", "show help message"],
348
- [" --version", "print version"],
349
- ]
437
+
350
438
  end
351
439
 
352
- it "[!zbxyv] returns self." do
353
- sc = @schema
354
- ret = sc.each_option_help { nil }
355
- ok {ret}.same? sc
440
+
441
+ topic '#each_option_and_desc()' do
442
+
443
+ before do
444
+ sc = Benry::CmdOpt::Schema.new
445
+ sc.add(:help, "-h, --help", "show help message")
446
+ sc.add(:version, " --version", "print version")
447
+ sc.add(:debug , "-d, --debug" , nil) # hidden
448
+ sc.add(:_DEBUG , "-D, --DEBUG" , "debug mode") # hidden
449
+ @schema = sc
450
+ end
451
+
452
+ spec "[!4b911] yields each optin definition str and help message." do
453
+ pairs = []
454
+ @schema.each_option_and_desc {|opt, desc| pairs << [opt, desc] }
455
+ ok {pairs} == [
456
+ ["-h, --help" , "show help message"], # not hiddden
457
+ [" --version" , "print version"], # not hidden
458
+ ]
459
+ end
460
+
461
+ spec "[!cl8zy] when 'all' flag is false, not yield hidden items." do
462
+ pairs = []
463
+ @schema.each_option_and_desc(all: false) {|opt, desc| pairs << [opt, desc] }
464
+ ok {pairs} == [
465
+ ["-h, --help" , "show help message"], # not hiddden
466
+ [" --version" , "print version"], # not hidden
467
+ ]
468
+ end
469
+
470
+ spec "[!tc4bk] when 'all' flag is true, yields even hidden items." do
471
+ pairs = []
472
+ @schema.each_option_and_desc(all: true) {|opt, desc| pairs << [opt, desc] }
473
+ ok {pairs} == [
474
+ ["-h, --help" , "show help message"], # not hiddden
475
+ [" --version" , "print version"], # not hidden
476
+ ["-d, --debug" , nil], # hidden
477
+ ["-D, --DEBUG" , "debug mode"], # hidden
478
+ ]
479
+ end
480
+
481
+ spec "[!03sux] returns enumerator object if block not given." do
482
+ ## when 'all: true'
483
+ xs = @schema.each_option_and_desc(all: true)
484
+ ok {xs}.is_a?(Enumerator)
485
+ ok {xs.collect {|x, _| x }} == ["-h, --help", " --version", "-d, --debug", "-D, --DEBUG"]
486
+ ## when 'all: false'
487
+ xs = @schema.each_option_and_desc(all: false)
488
+ ok {xs}.is_a?(Enumerator)
489
+ ok {xs.collect {|x, _| x }} == ["-h, --help", " --version"]
490
+ end
491
+
492
+ spec "[!zbxyv] returns self." do
493
+ ret = @schema.each_option_and_desc { nil }
494
+ ok {ret}.same? @schema
495
+ end
496
+
356
497
  end
357
498
 
358
- end
359
499
 
500
+ topic '#each()' do
360
501
 
361
- describe '#find_short_option()' do
502
+ before do
503
+ @schema = Benry::CmdOpt::Schema.new
504
+ @schema.add(:help , "-h, --help" , "help message")
505
+ @schema.add(:version, " --version", "print version")
506
+ end
507
+
508
+ spec "[!y4k1c] yields each option item." do
509
+ items = []
510
+ @schema.each {|x| items << x }
511
+ ok {items.length} == 2
512
+ ok {items[0]}.is_a?(Benry::CmdOpt::SchemaItem)
513
+ ok {items[1]}.is_a?(Benry::CmdOpt::SchemaItem)
514
+ ok {items[0].key} == :help
515
+ ok {items[1].key} == :version
516
+ keys = @schema.each.collect {|x| x.key }
517
+ ok {keys} == [:help, :version]
518
+ end
362
519
 
363
- before do
364
- @schema = new_sample_schema()
365
520
  end
366
521
 
367
- it "[!b4js1] returns option definition matched to short name." do
368
- x = @schema.find_short_option('h')
369
- ok {x.key} == :help
370
- x = @schema.find_short_option('f')
371
- ok {x.key} == :file
372
- x = @schema.find_short_option('i')
373
- ok {x.key} == :indent
522
+
523
+ topic '#empty?()' do
524
+
525
+ spec "[!um8am] returns false if any item exists, else returns true." do
526
+ schema = Benry::CmdOpt::Schema.new
527
+ ok {schema.empty?()} == true
528
+ schema.add(:help , "-h, --help" , "help message")
529
+ ok {schema.empty?()} == false
530
+ end
531
+
532
+ spec "[!icvm1] ignores hidden items if 'all: false' kwarg specified." do
533
+ schema = Benry::CmdOpt::Schema.new
534
+ schema.add(:debug , "-D", nil)
535
+ schema.add(:_trace, "-T", "trace")
536
+ ok {schema.empty?()} == false
537
+ ok {schema.empty?(all: true)} == false
538
+ ok {schema.empty?(all: false)} == true
539
+ end
540
+
374
541
  end
375
542
 
376
- it "[!s4d1y] returns nil when nothing found." do
377
- ok {@schema.find_short_option('v')} == nil
543
+
544
+ topic '#get()' do
545
+
546
+ before do
547
+ @schema = Benry::CmdOpt::Schema.new
548
+ @schema.add(:help , "-h, --help" , "help message")
549
+ @schema.add(:version, " --version", "print version")
550
+ end
551
+
552
+ spec "[!3wjfp] finds option item object by key." do
553
+ item = @schema.get(:help)
554
+ ok {item.key} == :help
555
+ item = @schema.get(:version)
556
+ ok {item.key} == :version
557
+ end
558
+
559
+ spec "[!0spll] returns nil if key not found." do
560
+ ok {@schema.get(:debug)} == nil
561
+ end
562
+
378
563
  end
379
564
 
380
- end
381
565
 
566
+ topic '#delete()' do
567
+
568
+ before do
569
+ @schema = Benry::CmdOpt::Schema.new
570
+ @schema.add(:help , "-h, --help" , "help message")
571
+ @schema.add(:version, " --version", "print version")
572
+ end
573
+
574
+ spec "[!l86rb] deletes option item corresponding to key." do
575
+ keys = @schema.each.collect {|x| x.key }
576
+ ok {keys} == [:help, :version]
577
+ @schema.delete(:help)
578
+ keys = @schema.each.collect {|x| x.key }
579
+ ok {keys} == [:version]
580
+ end
382
581
 
383
- describe '#find_long_option()' do
582
+ spec "[!rq0aa] returns deleted item." do
583
+ item = @schema.delete(:version)
584
+ ok {item} != nil
585
+ ok {item.key} == :version
586
+ end
384
587
 
385
- before do
386
- @schema = new_sample_schema()
387
588
  end
388
589
 
389
- it "[!atmf9] returns option definition matched to long name." do
390
- x = @schema.find_long_option('help')
391
- ok {x.key} == :help
392
- x = @schema.find_long_option('file')
393
- ok {x.key} == :file
394
- x = @schema.find_long_option('indent')
395
- ok {x.key} == :indent
590
+
591
+ topic '#find_short_option()' do
592
+
593
+ before do
594
+ @schema = new_sample_schema()
595
+ end
596
+
597
+ spec "[!b4js1] returns option definition matched to short name." do
598
+ x = @schema.find_short_option('h')
599
+ ok {x.key} == :help
600
+ x = @schema.find_short_option('f')
601
+ ok {x.key} == :file
602
+ x = @schema.find_short_option('i')
603
+ ok {x.key} == :indent
604
+ end
605
+
606
+ spec "[!s4d1y] returns nil when nothing found." do
607
+ ok {@schema.find_short_option('v')} == nil
608
+ end
609
+
396
610
  end
397
611
 
398
- it "[!6haoo] returns nil when nothing found." do
399
- ok {@schema.find_long_option('lib')} == nil
612
+
613
+ topic '#find_long_option()' do
614
+
615
+ before do
616
+ @schema = new_sample_schema()
617
+ end
618
+
619
+ spec "[!atmf9] returns option definition matched to long name." do
620
+ x = @schema.find_long_option('help')
621
+ ok {x.key} == :help
622
+ x = @schema.find_long_option('file')
623
+ ok {x.key} == :file
624
+ x = @schema.find_long_option('indent')
625
+ ok {x.key} == :indent
626
+ end
627
+
628
+ spec "[!6haoo] returns nil when nothing found." do
629
+ ok {@schema.find_long_option('lib')} == nil
630
+ end
631
+
400
632
  end
401
633
 
634
+
402
635
  end
403
636
 
404
637
 
405
- end
406
638
 
639
+ topic Benry::CmdOpt::SchemaItem do
407
640
 
641
+ ITEMS = [
642
+ Benry::CmdOpt::SchemaItem.new(:help, "-h, --help", "help msg",
643
+ "h", "help", nil, nil),
644
+ Benry::CmdOpt::SchemaItem.new(:file, "-f, --file=<file>", "filename",
645
+ "f", "file", "<file>", true),
646
+ Benry::CmdOpt::SchemaItem.new(:indent, "-i, --indent[=<N>]", "indent width",
647
+ "i", "indent", "<N>", false),
648
+ ]
408
649
 
409
- class Benry::Cmdopt::SchemaItem::Test < MiniTest::Test
410
650
 
651
+ topic '#initialize()' do
411
652
 
412
- describe '#validate_and_convert()' do
653
+ before do
654
+ @schema = Benry::CmdOpt::Schema.new
655
+ end
413
656
 
414
- def new_item(key, optstr, short, long, param, help,
415
- optional: nil, type: nil, pattern: nil, enum: nil, &callback)
416
- return Benry::Cmdopt::SchemaItem.new(key, optstr, short, long, param, help,
417
- optional: optional, type: type, pattern: pattern, enum: enum, &callback)
418
- end
657
+ spec "[!nn4cp] freezes enum object." do
658
+ item = Benry::CmdOpt::SchemaItem.new(:foo, "--foo", "desc", nil, "foo", "<val>",
659
+ true, enum: ["x", "y", "z"])
660
+ ok {item.enum} == ["x", "y", "z"]
661
+ ok {item.enum}.frozen?
662
+ end
419
663
 
420
- it "[!h0s0o] raises RuntimeError when value not matched to pattern." do
421
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width", pattern: /\A\d+\z/)
422
- optdict = {}
423
- pr = proc { x.validate_and_convert("abc", optdict) }
424
- ok {pr}.raise?(RuntimeError, "pattern unmatched.")
425
- end
664
+ case_when "[!wy2iv] when 'type:' specified..." do
426
665
 
427
- it "[!5jrdf] raises RuntimeError when value not in enum." do
428
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width", enum: ['2', '4', '8'])
429
- optdict = {}
430
- pr = proc { x.validate_and_convert("10", optdict) }
431
- ok {pr}.raise?(RuntimeError, "expected one of 2/4/8.")
432
- end
666
+ spec "[!7xmr5] raises SchemaError when type is not registered." do
667
+ sc = @schema
668
+ pr = proc {
669
+ sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width", type: Array)
670
+ }
671
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
672
+ "Array: Unregistered type.")
673
+ end
433
674
 
434
- it "[!j4fuz] calls type-specific callback when type specified." do
435
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width", type: Integer)
436
- optdict = {}
437
- pr = proc { x.validate_and_convert("abc", optdict) }
438
- ok {pr}.raise?(RuntimeError, "integer expected.")
439
- end
675
+ spec "[!s2aaj] raises SchemaError when option has no params but type specified." do
676
+ sc = @schema
677
+ pr = proc {
678
+ sc.add(:indent, "-i, --indent", "indent width", type: Integer)
679
+ }
680
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
681
+ "Integer: Type specified in spite of option has no params.")
682
+ end
440
683
 
441
- it "[!jn9z3] calls callback when callback specified." do
442
- called = false
443
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width") {|va|
444
- called = true
445
- }
446
- optdict = {}
447
- x.validate_and_convert("abc", optdict)
448
- ok {called} == true
449
- end
684
+ spec "[!sz8x2] not raise error when no params but value specified." do
685
+ sc = @schema
686
+ pr = proc {
687
+ sc.add(:indent, "-i, --indent", "indent width", type: Integer, value: 0)
688
+ }
689
+ ok {pr}.NOT.raise?(Exception)
690
+ end
450
691
 
451
- it "[!iqalh] calls callback with different number of args according to arity." do
452
- args1 = nil
453
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil) {|val|
454
- args1 = val
455
- }
456
- optdict = {}
457
- x.validate_and_convert("123", optdict)
458
- ok {args1} == "123"
459
- #
460
- args2 = nil
461
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil) {|optdict, key, val|
462
- args2 = [optdict, key, val]
463
- }
464
- optdict = {}
465
- x.validate_and_convert("123", optdict)
466
- ok {args2} == [optdict, :indent, "123"]
467
- end
692
+ spec "[!70ogf] not raise error when no params but TrueClass specified." do
693
+ sc = @schema
694
+ pr = proc {
695
+ sc.add(:indent, "-i, --indent", "indent width", type: TrueClass)
696
+ }
697
+ ok {pr}.NOT.raise?(Exception)
698
+ end
468
699
 
469
- it "[!x066l] returns new value." do
470
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil, type: Integer)
471
- ok {x.validate_and_convert("123", {})} == 123
472
- #
473
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil, type: Integer) {|val|
474
- val * 2
475
- }
476
- ok {x.validate_and_convert("123", {})} == 246
477
- end
700
+ end
478
701
 
479
- end
702
+ case_when "[!6y8s2] when 'rexp:' specified..." do
480
703
 
481
- end
704
+ spec "[!bi2fh] raises SchemaError when pattern is not a regexp." do
705
+ sc = @schema
706
+ pr = proc {
707
+ sc.add(:indent, "-x, --indent[=<WIDTH>]", "indent width", rexp: '\A\d+\z')
708
+ }
709
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
710
+ '"\\\\A\\\\d+\\\\z": Regexp pattern expected.')
711
+ end
482
712
 
713
+ spec "[!01fmt] raises SchmeaError when option has no params but pattern specified." do
714
+ sc = @schema
715
+ pr = proc {
716
+ sc.add(:indent, "-i, --indent", "indent width", rexp: /\A\d+\z/)
717
+ }
718
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
719
+ '/\A\d+\z/: Regexp pattern specified in spite of option has no params.')
720
+ end
483
721
 
722
+ end
484
723
 
485
- class Benry::Cmdopt::Parser::Test < MiniTest::Test
724
+ case_when "[!5nrvq] when 'enum:' specified..." do
725
+
726
+ spec "[!melyd] raises SchemaError when enum is not an Array nor Set." do
727
+ sc = @schema
728
+ sc.add(:indent, "-i <N>", "indent width", enum: ["2", "4", "8"])
729
+ sc.add(:indent, "-i <N>", "indent width", enum: Set.new(["2", "4", "8"]))
730
+ pr = proc {
731
+ sc.add(:indent, "-i <N>", "indent width", enum: "2,4,8")
732
+ }
733
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
734
+ '"2,4,8": Array or set expected.')
735
+ end
486
736
 
737
+ spec "[!xqed8] raises SchemaError when enum specified for no param option." do
738
+ sc = @schema
739
+ pr = proc {
740
+ sc.add(:indent, "-i", "enable indent", enum: [2, 4, 8])
741
+ }
742
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
743
+ "[2, 4, 8]: Enum specified in spite of option has no params.")
744
+ end
487
745
 
488
- describe '#parse_options()' do
746
+ spec "[!zuthh] raises SchemaError when enum element value is not instance of type class." do
747
+ sc = @schema
748
+ pr = proc {
749
+ sc.add(:indent, "-i <N>", "enable indent", type: Integer, enum: ['2', '4', '8'])
750
+ }
751
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
752
+ '["2", "4", "8"]: Enum element value should be instance of Integer, but "2" is not.')
753
+ end
489
754
 
490
- before do
491
- @parser = Benry::Cmdopt::Parser.new(new_sample_schema())
492
- end
755
+ end
493
756
 
494
- it "[!3wmsy] returns command option values as a dict." do
495
- argv = ["-h", "--version"]
496
- d = @parser.parse(argv)
497
- ok {d} == {help: true, version: true}
498
- end
757
+ case_when "[!hk4nw] when 'range:' specified..." do
499
758
 
500
- it "[!uh7j8] parses long options." do
501
- argv = ["--help", "--file=foo.png", "--indent=10"]
502
- d = @parser.parse(argv)
503
- ok {d} == {help: true, file: "foo.png", indent: 10}
504
- end
759
+ spec "[!z20ky] raises SchemaError when range is not a Range object." do
760
+ pr = proc {
761
+ @schema.add(:indent, "-i <N>", "indent", type: Integer, range: [1,8])
762
+ }
763
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
764
+ "[1, 8]: Range object expected.")
765
+ end
505
766
 
506
- it "[!nwnjc] parses short options." do
507
- argv = ["-h", "-f", "foo.png", "-i10"]
508
- d = @parser.parse(argv)
509
- ok {d} == {help: true, file: "foo.png", indent: 10}
510
- end
767
+ spec "[!gp025] raises SchemaError when range specified with `type: TrueClass`." do
768
+ pr = proc {
769
+ @schema.add(:indent, "-i <N>", "indent", type: TrueClass, range: 0..1)
770
+ }
771
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
772
+ "0..1: Range is not available with `type: TrueClass`.")
773
+ end
511
774
 
512
- it "[!y04um] skips rest options when '--' found in argv." do
513
- argv = ["-h", "--", "-f", "foo.png", "-i10"]
514
- d = @parser.parse(argv)
515
- ok {d} == {help: true}
516
- ok {argv} == ["-f", "foo.png", "-i10"]
517
- end
775
+ spec "[!7njd5] range beginning/end value should be expected type." do
776
+ pr = proc {
777
+ @schema.add(:indent, "-i <N>", "indent", range: (1..8))
778
+ }
779
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
780
+ "1..8: Range value should be String, but not.")
781
+ pr = proc {
782
+ @schema.add(:indent, "-i <N>", "indent", type: Date, range: (1..8))
783
+ }
784
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
785
+ "1..8: Range value should be Date, but not.")
786
+ end
787
+
788
+ spec "[!uymig] range object can be endless." do
789
+ begin
790
+ range1 = eval "(1..)" # Ruby >= 2.6
791
+ range2 = eval "(..3)" # Ruby >= 2.6
792
+ rescue SyntaxError
793
+ range1 = nil # Ruby < 2.6
794
+ range2 = nil # Ruby < 2.6
795
+ end
796
+ if range1
797
+ pr = proc {
798
+ @schema.add(:indent1, "-i <N>", "indent", type: Integer, range: range1)
799
+ @schema.add(:indent2, "-j <N>", "indent", type: Integer, range: range2)
800
+ }
801
+ pr.call
802
+ ok {pr}.NOT.raise?(Exception)
803
+ end
804
+ end
518
805
 
519
- it "[!qpuxh] handles only OptionError when block given." do
520
- errmsg = nil
521
- errcls = nil
522
- @parser.parse(["-ix"]) {|err|
523
- errmsg = err.message
524
- errcls = err.class
525
- }
526
- ok {errmsg} == "-ix: integer expected."
527
- ok {errcls} == Benry::Cmdopt::OptionError
528
- #
529
- sc = Benry::Cmdopt::Schema.new
530
- sc.add(:file, "--file=<FILE>", "file") do |val|
531
- File.open(val) {|f| f.read }
532
806
  end
533
- parser = Benry::Cmdopt::Parser.new(sc)
534
- pr = proc { parser.parse(["--file=/foo/bar/baz.png"]) }
535
- ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
536
- end
537
807
 
538
- it "[!dhpw1] returns nil when OptionError handled." do
539
- ret = @parser.parse(["-dx"]) {|err| 1 }
540
- ok {ret} == nil
541
- end
808
+ case_when "[!a0g52] when 'value:' specified..." do
542
809
 
543
- end
810
+ spec "[!435t6] raises SchemaError when 'value:' is specified on argument-required option." do
811
+ sc = @schema
812
+ pr = proc {
813
+ sc.add(:flag, "--flag=<on|off>", "flag", type: TrueClass, value: true)
814
+ }
815
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
816
+ "true: 'value:' is meaningless when option has required argument (hint: change to optional argument instead).")
817
+ end
544
818
 
819
+ spec "[!6vwqv] raises SchemaError when type is TrueClass but value is not true nor false." do
820
+ sc = @schema
821
+ pr = proc {
822
+ sc.add(:flag, "--flag[=<on|off>]", "flag", type: TrueClass, value: 0)
823
+ }
824
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
825
+ "0: Value should be true or false when `type: TrueClass` specified.")
826
+ end
545
827
 
546
- describe '#parse_long_option()' do
828
+ spec "[!c6i2o] raises SchemaError when value is not a kind of type." do
829
+ sc = @schema
830
+ pr = proc {
831
+ sc.add(:flag, "--flag[=<on|off>]", "flag", type: Integer, value: false)
832
+ }
833
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
834
+ "Type mismatched between `type: Integer` and `value: false`.")
835
+ end
547
836
 
548
- before do
549
- @parser = Benry::Cmdopt::Parser.new(new_sample_schema())
550
- end
837
+ spec "[!lnhp6] not raise error when type is not specified." do
838
+ sc = @schema
839
+ pr = proc {
840
+ sc.add(:flag, "--flag[=<on|off>]", "flag", value: false)
841
+ }
842
+ ok {pr}.NOT.raise?(Exception)
843
+ end
551
844
 
552
- it "[!3i994] raises OptionError when invalid long option format." do
553
- argv = ["--f/o/o"]
554
- pr = proc { @parser.parse(argv) }
555
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--f/o/o: invalid long option.")
556
- end
845
+ spec "[!6xb8o] value should be included in enum values." do
846
+ sc = @schema
847
+ pr = proc {
848
+ sc.add(:lang, "--lang[=<en|fr|it>]", "language", enum: ["en", "fr", "it"], value: "ja")
849
+ }
850
+ ok {pr}.raise?(Benry::CmdOpt::SchemaError,
851
+ "ja: Value should be included in enum values, but not.")
852
+ end
557
853
 
558
- it "[!er7h4] raises OptionError when unknown long option." do
559
- argv = ["--foo"]
560
- pr = proc { @parser.parse(argv) }
561
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--foo: unknown long option.")
562
- end
854
+ end
563
855
 
564
- it "[!2jd9w] raises OptionError when no arguments specified for arg required long option." do
565
- argv = ["--file"]
566
- pr = proc { @parser.parse(argv) }
567
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--file: argument required.")
568
856
  end
569
857
 
570
- it "[!qyq8n] raises optionError when an argument specified for no arg long option." do
571
- argv = ["--version=1.0.0"]
572
- pr = proc { @parser.parse(argv) }
573
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--version=1.0.0: unexpected argument.")
574
- end
575
858
 
576
- it "[!o596x] validates argument value." do
577
- argv = ["--indent=abc"]
578
- pr = proc { @parser.parse(argv) }
579
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--indent=abc: integer expected.")
580
- #
581
- argv = ["--path=/foo/bar"]
582
- pr = proc { @parser.parse(argv) }
583
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--path=/foo/bar: directory not exist.")
859
+ topic '#required?' do
860
+
861
+ spec "[!svxny] returns nil if option takes no arguments." do
862
+ item, _, _ = ITEMS
863
+ ok {item.required?} == nil
864
+ end
865
+
866
+ spec "[!togcx] returns true if argument is required." do
867
+ _, item, _ = ITEMS
868
+ ok {item.required?} == true
869
+ end
870
+
871
+ spec "[!uwbgc] returns false if argument is optional." do
872
+ _, _, item = ITEMS
873
+ ok {item.required?} == false
874
+ end
584
875
 
585
876
  end
586
877
 
587
- end
588
878
 
879
+ topic '#arg_requireness()' do
589
880
 
590
- describe '#parse_short_option()' do
881
+ spec "[!kmo28] returns :none if option takes no arguments." do
882
+ item, _, _ = ITEMS
883
+ ok {item.arg_requireness()} == :none
884
+ end
591
885
 
592
- before do
593
- @parser = Benry::Cmdopt::Parser.new(new_sample_schema())
594
- end
886
+ spec "[!s8gxl] returns :required if argument is required." do
887
+ _, item, _ = ITEMS
888
+ ok {item.arg_requireness()} == :required
889
+ end
595
890
 
596
- it "[!4eh49] raises OptionError when unknown short option specified." do
597
- argv = ["-hxf", "foo.png"]
598
- pr = proc { @parser.parse(argv) }
599
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-x: unknown option.")
600
- end
891
+ spec "[!owpba] returns :optional if argument is optional." do
892
+ _, _, item = ITEMS
893
+ ok {item.arg_requireness()} == :optional
894
+ end
601
895
 
602
- it "[!utdbf] raises OptionError when argument required but not specified." do
603
- argv = ["-hf"]
604
- pr = proc { @parser.parse(argv) }
605
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-f: argument required.")
606
896
  end
607
897
 
608
- it "[!f63hf] short option arg can be specified without space separator." do
609
- argv = ["-hfabc.png", "xx"]
610
- d = @parser.parse(argv)
611
- ok {d} == {help: true, file: "abc.png"}
612
- ok {argv} == ["xx"]
613
- end
614
898
 
615
- it "[!yjq6b] optional arg should be specified without space separator." do
616
- argv = ["-hi123", "xx"]
617
- d = @parser.parse(argv)
618
- ok {d} == {help: true, indent: 123}
619
- ok {argv} == ['xx']
620
- end
899
+ topic '#hidden?()' do
621
900
 
622
- it "[!wape4] otpional arg can be omit." do
623
- argv = ["-hi", "xx"]
624
- d = @parser.parse(argv)
625
- ok {d} == {help: true, indent: true}
626
- ok {argv} == ['xx']
627
- end
901
+ spec "[!h0uxs] returns true if desc is nil." do
902
+ desc = nil
903
+ item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", desc, "D", nil, nil, nil)
904
+ ok {item.hidden?} == true
905
+ end
906
+
907
+ spec "[!su00g] returns true if key starts with '_'." do
908
+ desc = "debug mode"
909
+ item = Benry::CmdOpt::SchemaItem.new(:_debug, "-D", desc, "D", nil, nil, nil)
910
+ ok {item.hidden?} == true
911
+ end
912
+
913
+ spec "[!28vzx] returns false if else." do
914
+ desc = "debug mode"
915
+ item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", desc, "D", nil, nil, nil)
916
+ ok {item.hidden?} == false
917
+ end
628
918
 
629
- it "[!yu0kc] validates short option argument." do
630
- argv = ["-iaaa"]
631
- pr = proc { @parser.parse(argv) }
632
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-iaaa: integer expected.")
633
- #
634
- argv = ["-I", "/foo/bar"]
635
- pr = proc { @parser.parse(argv) }
636
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-I /foo/bar: directory not exist.")
637
919
  end
638
920
 
639
- end
640
921
 
922
+ topic '#validate_and_convert()' do
923
+
924
+ def new_item(key, optstr, desc, short, long, param, required,
925
+ type: nil, rexp: nil, enum: nil, range: nil, value: nil, &callback)
926
+ return Benry::CmdOpt::SchemaItem.new(key, optstr, desc, short, long, param, required,
927
+ type: type, rexp: rexp, enum: enum, range: range, value: value, &callback)
928
+ end
929
+
930
+ spec "[!h0s0o] raises RuntimeError when value not matched to pattern." do
931
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, rexp: /\A\d+\z/)
932
+ optdict = {}
933
+ pr = proc { x.validate_and_convert("abc", optdict) }
934
+ ok {pr}.raise?(RuntimeError, "Pattern unmatched.")
935
+ end
936
+
937
+ spec "[!5jrdf] raises RuntimeError when value not in enum." do
938
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, enum: ['2', '4', '8'])
939
+ optdict = {}
940
+ pr = proc { x.validate_and_convert("10", optdict) }
941
+ ok {pr}.raise?(RuntimeError, "Expected one of 2/4/8.")
942
+ end
641
943
 
642
- describe '#new_options_dict()' do
944
+ spec "[!5falp] raise RuntimeError when value not in range." do
945
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
946
+ type: Integer, range: 2..8)
947
+ optdict = {}
948
+ pr = proc { x.validate_and_convert("1", optdict) }
949
+ ok {pr}.raise?(RuntimeError, "Too small (min: 2)")
950
+ pr = proc { x.validate_and_convert("9", optdict) }
951
+ ok {pr}.raise?(RuntimeError, "Too large (max: 8)")
952
+ ## when min==0
953
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
954
+ type: Integer, range: 0..8)
955
+ optdict = {}
956
+ pr = proc { x.validate_and_convert("-1", optdict) }
957
+ ok {pr}.raise?(RuntimeError, "Positive value (>= 0) expected.")
958
+ ## when min==1
959
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
960
+ type: Integer, range: 1..8)
961
+ optdict = {}
962
+ pr = proc { x.validate_and_convert("0", optdict) }
963
+ ok {pr}.raise?(RuntimeError, "Positive value (>= 1) expected.")
964
+ end
965
+
966
+ spec "[!a0rej] supports endless range." do
967
+ begin
968
+ range1 = eval "(2..)" # Ruby >= 2.6
969
+ range2 = eval "(..8)"
970
+ rescue SyntaxError
971
+ range1 = nil # Ruby < 2.6
972
+ range2 = nil
973
+ end
974
+ if range1
975
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
976
+ type: Integer, range: range1)
977
+ optdict = {}
978
+ pr = proc { x.validate_and_convert("1", optdict) }
979
+ ok {pr}.raise?(RuntimeError, "Too small (min: 2)")
980
+ pr = proc { x.validate_and_convert("9", optdict) }
981
+ ok {pr}.NOT.raise?(RuntimeError)
982
+ end
983
+ if range2
984
+ x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
985
+ type: Integer, range: range2)
986
+ optdict = {}
987
+ pr = proc { x.validate_and_convert("1", optdict) }
988
+ ok {pr}.NOT.raise?(RuntimeError)
989
+ pr = proc { x.validate_and_convert("9", optdict) }
990
+ ok {pr}.raise?(RuntimeError, "Too large (max: 8)")
991
+ end
992
+ end
993
+
994
+ spec "[!j4fuz] calls type-specific callback when type specified." do
995
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer)
996
+ optdict = {}
997
+ pr = proc { x.validate_and_convert("abc", optdict) }
998
+ ok {pr}.raise?(RuntimeError, "Integer expected.")
999
+ end
1000
+
1001
+ spec "[!jn9z3] calls callback when callback specified." do
1002
+ called = false
1003
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|va|
1004
+ called = true
1005
+ }
1006
+ optdict = {}
1007
+ x.validate_and_convert("abc", optdict)
1008
+ ok {called} == true
1009
+ end
1010
+
1011
+ spec "[!iqalh] calls callback with different number of args according to arity." do
1012
+ args1 = nil
1013
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|val|
1014
+ args1 = val
1015
+ }
1016
+ optdict = {}
1017
+ x.validate_and_convert("123", optdict)
1018
+ ok {args1} == "123"
1019
+ #
1020
+ args2 = nil
1021
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|optdict, key, val|
1022
+ args2 = [optdict, key, val]
1023
+ }
1024
+ optdict = {}
1025
+ x.validate_and_convert("123", optdict)
1026
+ ok {args2} == [optdict, :indent, "123"]
1027
+ end
1028
+
1029
+ spec "[!x066l] returns new value." do
1030
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer)
1031
+ ok {x.validate_and_convert("123", {})} == 123
1032
+ #
1033
+ x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer) {|val|
1034
+ val * 2
1035
+ }
1036
+ ok {x.validate_and_convert("123", {})} == 246
1037
+ end
1038
+
1039
+ spec "[!eafem] returns default value (if specified) instead of true value." do
1040
+ x1 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: nil)
1041
+ ok {x1.validate_and_convert(true, {})} == true
1042
+ x2 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: "blabla")
1043
+ ok {x2.validate_and_convert(true, {})} == "blabla"
1044
+ x3 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: false)
1045
+ ok {x3.validate_and_convert(true, {})} == false
1046
+ end
643
1047
 
644
- it "[!vm6h0] returns new hash object." do
645
- parser = Benry::Cmdopt::Parser.new(new_sample_schema())
646
- ret = parser.__send__(:new_options_dict)
647
- ok {ret}.is_a?(Hash)
648
- ok {ret} == {}
649
1048
  end
650
1049
 
651
1050
  end
652
1051
 
653
1052
 
654
- end
655
1053
 
1054
+ topic Benry::CmdOpt::Parser do
656
1055
 
657
1056
 
658
- class Benry::Cmdopt::Test < MiniTest::Test
1057
+ topic '#parse_options()' do
659
1058
 
1059
+ before do
1060
+ @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1061
+ end
660
1062
 
661
- describe 'PARAM_TYPES[Integer]' do
1063
+ spec "[!3wmsy] returns command option values as a dict." do
1064
+ argv = ["-h", "--version"]
1065
+ d = @parser.parse(argv)
1066
+ ok {d} == {help: true, version: true}
1067
+ end
662
1068
 
663
- before do
664
- sc = Benry::Cmdopt::Schema.new
665
- sc.add(:indent, "-i, --indent[=<N>]", "indent width", type: Integer)
666
- @parser = Benry::Cmdopt::Parser.new(sc)
667
- end
1069
+ spec "[!uh7j8] parses long options." do
1070
+ argv = ["--help", "--file=foo.png", "--indent=10"]
1071
+ d = @parser.parse(argv)
1072
+ ok {d} == {help: true, file: "foo.png", indent: 10}
1073
+ end
668
1074
 
669
- it "[!6t8cs] converts value into integer." do
670
- d = @parser.parse(['-i20'])
671
- ok {d[:indent]} == 20
672
- #
673
- d = @parser.parse(['--indent=12'])
674
- ok {d[:indent]} == 12
675
- end
1075
+ spec "[!nwnjc] parses short options." do
1076
+ argv = ["-h", "-f", "foo.png", "-i10"]
1077
+ d = @parser.parse(argv)
1078
+ ok {d} == {help: true, file: "foo.png", indent: 10}
1079
+ end
1080
+
1081
+ spec "[!5s5b6] treats '-' as an argument, not an option." do
1082
+ argv = ["-h", "-", "xxx", "yyy"]
1083
+ d = @parser.parse(argv)
1084
+ ok {d} == {help: true}
1085
+ ok {argv} == ["-", "xxx", "yyy"]
1086
+ end
1087
+
1088
+ spec "[!q8356] parses options even after arguments when `all: true`." do
1089
+ argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1090
+ d = @parser.parse(argv, all: true)
1091
+ ok {d} == {help: true, file: "foo.png", indent: 10}
1092
+ ok {argv} == ["arg1", "arg2", "arg3"]
1093
+ #
1094
+ argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1095
+ d = @parser.parse(argv)
1096
+ ok {d} == {help: true, file: "foo.png", indent: 10}
1097
+ ok {argv} == ["arg1", "arg2", "arg3"]
1098
+ end
1099
+
1100
+ spec "[!ryra3] doesn't parse options after arguments when `all: false`." do
1101
+ argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1102
+ d = @parser.parse(argv, all: false)
1103
+ ok {d} == {help: true}
1104
+ ok {argv} == ["arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1105
+ end
1106
+
1107
+ spec "[!y04um] skips rest options when '--' found in argv." do
1108
+ argv = ["-h", "--", "-f", "foo.png", "-i10"]
1109
+ d = @parser.parse(argv)
1110
+ ok {d} == {help: true}
1111
+ ok {argv} == ["-f", "foo.png", "-i10"]
1112
+ end
1113
+
1114
+ spec "[!qpuxh] handles only OptionError when block given." do
1115
+ errmsg = nil
1116
+ errcls = nil
1117
+ @parser.parse(["-ix"]) {|err|
1118
+ errmsg = err.message
1119
+ errcls = err.class
1120
+ }
1121
+ ok {errmsg} == "-ix: Integer expected."
1122
+ ok {errcls} == Benry::CmdOpt::OptionError
1123
+ #
1124
+ sc = Benry::CmdOpt::Schema.new
1125
+ sc.add(:file, "--file=<FILE>", "file") do |val|
1126
+ File.open(val) {|f| f.read }
1127
+ end
1128
+ parser = Benry::CmdOpt::Parser.new(sc)
1129
+ pr = proc { parser.parse(["--file=/foo/bar/baz.png"]) }
1130
+ ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
1131
+ end
1132
+
1133
+ spec "[!dhpw1] returns nil when OptionError handled." do
1134
+ ret = @parser.parse(["-dx"]) {|err| 1 }
1135
+ ok {ret} == nil
1136
+ end
676
1137
 
677
- it "[!nzwc9] raises error when failed to convert value into integer." do
678
- pr = proc { @parser.parse(['-i2.1']) }
679
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-i2.1: integer expected.")
680
- #
681
- pr = proc { @parser.parse(['--indent=2.2']) }
682
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--indent=2.2: integer expected.")
683
1138
  end
684
1139
 
685
- end
686
1140
 
1141
+ topic '#parse_long_option()' do
1142
+
1143
+ before do
1144
+ @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1145
+ end
1146
+
1147
+ spec "[!3i994] raises OptionError when invalid long option format." do
1148
+ argv = ["--f/o/o"]
1149
+ pr = proc { @parser.parse(argv) }
1150
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--f/o/o: Invalid long option.")
1151
+ end
1152
+
1153
+ spec "[!1ab42] invokes error handler method when unknown long option." do
1154
+ def @parser.handle_unknown_long_option(optstr, name, val)
1155
+ (@_called_ ||= []) << [optstr, name, val]
1156
+ end
1157
+ ret = @parser.parse(["--xx=XX", "--yy=YY", "--zz"])
1158
+ ok {ret} == {}
1159
+ ok {@parser.instance_variable_get('@_called_')} == [
1160
+ ["--xx=XX", "xx", "XX"],
1161
+ ["--yy=YY", "yy", "YY"],
1162
+ ["--zz" , "zz", nil],
1163
+ ]
1164
+ end
1165
+
1166
+ spec "[!er7h4] default behavior is to raise OptionError when unknown long option." do
1167
+ argv = ["--foo"]
1168
+ pr = proc { @parser.parse(argv) }
1169
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--foo: Unknown long option.")
1170
+ end
1171
+
1172
+ spec "[!2jd9w] raises OptionError when no arguments specified for arg required long option." do
1173
+ argv = ["--file"]
1174
+ pr = proc { @parser.parse(argv) }
1175
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--file: Argument required.")
1176
+ end
1177
+
1178
+ spec "[!qyq8n] raises optionError when an argument specified for no arg long option." do
1179
+ argv = ["--version=1.0.0"]
1180
+ pr = proc { @parser.parse(argv) }
1181
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--version=1.0.0: Unexpected argument.")
1182
+ end
687
1183
 
688
- describe 'PARAM_TYPES[Float]' do
1184
+ spec "[!o596x] validates argument value." do
1185
+ argv = ["--indent=abc"]
1186
+ pr = proc { @parser.parse(argv) }
1187
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--indent=abc: Integer expected.")
1188
+ #
1189
+ argv = ["--path=/foo/bar"]
1190
+ pr = proc { @parser.parse(argv) }
1191
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--path=/foo/bar: Directory not exist.")
1192
+
1193
+ end
689
1194
 
690
- before do
691
- sc = Benry::Cmdopt::Schema.new
692
- sc.add(:ratio, "-r, --ratio=<RATIO>", "ratio", type: Float)
693
- @parser = Benry::Cmdopt::Parser.new(sc)
694
1195
  end
695
1196
 
696
- it "[!gggy6] converts value into float." do
697
- d = @parser.parse(['-r', '1.25'])
698
- ok {d[:ratio]} == 1.25
699
- #
700
- d = @parser.parse(['--ratio=1.25'])
701
- ok {d[:ratio]} == 1.25
1197
+
1198
+ topic '#parse_short_option()' do
1199
+
1200
+ before do
1201
+ @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1202
+ end
1203
+
1204
+ spec "[!4eh49] raises OptionError when unknown short option specified." do
1205
+ argv = ["-hxf", "foo.png"]
1206
+ pr = proc { @parser.parse(argv) }
1207
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-x: Unknown option.")
1208
+ end
1209
+
1210
+ spec "[!utdbf] raises OptionError when argument required but not specified." do
1211
+ argv = ["-hf"]
1212
+ pr = proc { @parser.parse(argv) }
1213
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-f: Argument required.")
1214
+ end
1215
+
1216
+ spec "[!f63hf] short option arg can be specified without space separator." do
1217
+ argv = ["-hfabc.png", "xx"]
1218
+ d = @parser.parse(argv)
1219
+ ok {d} == {help: true, file: "abc.png"}
1220
+ ok {argv} == ["xx"]
1221
+ end
1222
+
1223
+ spec "[!yjq6b] optional arg should be specified without space separator." do
1224
+ argv = ["-hi123", "xx"]
1225
+ d = @parser.parse(argv)
1226
+ ok {d} == {help: true, indent: 123}
1227
+ ok {argv} == ['xx']
1228
+ end
1229
+
1230
+ spec "[!wape4] otpional arg can be omit." do
1231
+ argv = ["-hi", "xx"]
1232
+ d = @parser.parse(argv)
1233
+ ok {d} == {help: true, indent: true}
1234
+ ok {argv} == ['xx']
1235
+ end
1236
+
1237
+ spec "[!yu0kc] validates short option argument." do
1238
+ argv = ["-iaaa"]
1239
+ pr = proc { @parser.parse(argv) }
1240
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-iaaa: Integer expected.")
1241
+ #
1242
+ argv = ["-I", "/foo/bar"]
1243
+ pr = proc { @parser.parse(argv) }
1244
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-I /foo/bar: Directory not exist.")
1245
+ end
1246
+
702
1247
  end
703
1248
 
704
- it "[!t4elj] raises error when faield to convert value into float." do
705
- pr = proc { @parser.parse(['-r', 'abc']) }
706
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-r abc: float expected.")
707
- #
708
- pr = proc { @parser.parse(['--ratio=abc']) }
709
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--ratio=abc: float expected.")
1249
+
1250
+ topic '#new_options_dict()' do
1251
+
1252
+ spec "[!vm6h0] returns new hash object." do
1253
+ parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1254
+ ret = parser.__send__(:new_options_dict)
1255
+ ok {ret}.is_a?(Hash)
1256
+ ok {ret} == {}
1257
+ end
1258
+
710
1259
  end
711
1260
 
712
- end
713
1261
 
1262
+ topic '#handle_unknown_long_option()' do
1263
+
1264
+ spec "[!0q78a] raises OptionError." do
1265
+ parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1266
+ pr = proc {
1267
+ parser.__send__(:handle_unknown_long_option, "--xx=XX", "xx", "XX")
1268
+ }
1269
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--xx=XX: Unknown long option.")
1270
+ end
714
1271
 
715
- describe 'PARAM_TYPES[TrueClass]' do
716
-
717
- before do
718
- sc = Benry::Cmdopt::Schema.new
719
- sc.add(:border , "-b, --border[=<on|off>]", "enable border", type: TrueClass)
720
- @parser = Benry::Cmdopt::Parser.new(sc)
721
- end
722
-
723
- it "[!47kx4] converts 'true'/'on'/'yes' into true." do
724
- d = @parser.parse(["-btrue"])
725
- ok {d} == {border: true}
726
- d = @parser.parse(["-bon"])
727
- ok {d} == {border: true}
728
- d = @parser.parse(["-byes"])
729
- ok {d} == {border: true}
730
- #
731
- d = @parser.parse(["--border=true"])
732
- ok {d} == {border: true}
733
- d = @parser.parse(["--border=on"])
734
- ok {d} == {border: true}
735
- d = @parser.parse(["--border=yes"])
736
- ok {d} == {border: true}
737
- end
738
-
739
- it "[!3n810] converts 'false'/'off'/'no' into false." do
740
- d = @parser.parse(["-bfalse"])
741
- ok {d} == {border: false}
742
- d = @parser.parse(["-boff"])
743
- ok {d} == {border: false}
744
- d = @parser.parse(["-bno"])
745
- ok {d} == {border: false}
746
- #
747
- d = @parser.parse(["--border=false"])
748
- ok {d} == {border: false}
749
- d = @parser.parse(["--border=off"])
750
- ok {d} == {border: false}
751
- d = @parser.parse(["--border=no"])
752
- ok {d} == {border: false}
753
- end
754
-
755
- it "[!h8ayh] raises error when failed to convert value into true nor false." do
756
- pr = proc { @parser.parse(["-bt"]) }
757
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
758
- "-bt: boolean expected.")
759
- #
760
- pr = proc { @parser.parse(["--border=t"]) }
761
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
762
- "--border=t: boolean expected.")
763
1272
  end
764
1273
 
1274
+
765
1275
  end
766
1276
 
767
1277
 
768
- describe 'PARAM_TYPES[Date]' do
769
1278
 
770
- before do
771
- require 'date'
772
- sc = Benry::Cmdopt::Schema.new
773
- sc.add(:date, "-d, --date=<YYYY-MM-DD>]", "date", type: Date)
774
- @parser = Benry::Cmdopt::Parser.new(sc)
775
- end
1279
+ topic Benry::CmdOpt do
776
1280
 
777
- it "[!sru5j] converts 'YYYY-MM-DD' into date object." do
778
- d = @parser.parse(['-d', '2000-01-01'])
779
- ok {d[:date]} == Date.new(2000, 1, 1)
780
- #
781
- d = @parser.parse(['--date=2000-1-2'])
782
- ok {d[:date]} == Date.new(2000, 1, 2)
783
- end
784
1281
 
785
- it "[!h9q9y] raises error when failed to convert into date object." do
786
- pr = proc { @parser.parse(['-d', '2000/01/01']) }
787
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
788
- "-d 2000/01/01: invalid date format (ex: '2000-01-01')")
789
- #
790
- pr = proc { @parser.parse(['--date=01-01-2000']) }
791
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
792
- "--date=01-01-2000: invalid date format (ex: '2000-01-01')")
1282
+ topic 'PARAM_TYPES[Integer]' do
1283
+
1284
+ before do
1285
+ sc = Benry::CmdOpt::Schema.new
1286
+ sc.add(:indent, "-i, --indent[=<N>]", "indent width", type: Integer)
1287
+ @parser = Benry::CmdOpt::Parser.new(sc)
1288
+ end
1289
+
1290
+ spec "[!6t8cs] converts value into integer." do
1291
+ d = @parser.parse(['-i20'])
1292
+ ok {d[:indent]} == 20
1293
+ #
1294
+ d = @parser.parse(['--indent=12'])
1295
+ ok {d[:indent]} == 12
1296
+ end
1297
+
1298
+ spec "[!nzwc9] raises error when failed to convert value into integer." do
1299
+ pr = proc { @parser.parse(['-i2.1']) }
1300
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-i2.1: Integer expected.")
1301
+ #
1302
+ pr = proc { @parser.parse(['--indent=2.2']) }
1303
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--indent=2.2: Integer expected.")
1304
+ end
1305
+
793
1306
  end
794
1307
 
795
- it "[!i4ui8] raises error when specified date not exist." do
796
- pr = proc { @parser.parse(['-d', '2001-02-29']) }
797
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
798
- "-d 2001-02-29: date not exist.")
799
- #
800
- pr = proc { @parser.parse(['--date=2001-02-29']) }
801
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
802
- "--date=2001-02-29: date not exist.")
1308
+
1309
+ topic 'PARAM_TYPES[Float]' do
1310
+
1311
+ before do
1312
+ sc = Benry::CmdOpt::Schema.new
1313
+ sc.add(:ratio, "-r, --ratio=<RATIO>", "ratio", type: Float)
1314
+ @parser = Benry::CmdOpt::Parser.new(sc)
1315
+ end
1316
+
1317
+ spec "[!gggy6] converts value into float." do
1318
+ d = @parser.parse(['-r', '1.25'])
1319
+ ok {d[:ratio]} == 1.25
1320
+ #
1321
+ d = @parser.parse(['--ratio=1.25'])
1322
+ ok {d[:ratio]} == 1.25
1323
+ end
1324
+
1325
+ spec "[!t4elj] raises error when faield to convert value into float." do
1326
+ pr = proc { @parser.parse(['-r', 'abc']) }
1327
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-r abc: Float expected.")
1328
+ #
1329
+ pr = proc { @parser.parse(['--ratio=abc']) }
1330
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--ratio=abc: Float expected.")
1331
+ end
1332
+
803
1333
  end
804
1334
 
805
- end
806
1335
 
1336
+ topic 'PARAM_TYPES[TrueClass]' do
1337
+
1338
+ before do
1339
+ sc = Benry::CmdOpt::Schema.new
1340
+ sc.add(:border , "-b, --border[=<on|off>]", "enable border", type: TrueClass)
1341
+ @parser = Benry::CmdOpt::Parser.new(sc)
1342
+ end
1343
+
1344
+ spec "[!47kx4] converts 'true'/'on'/'yes' into true." do
1345
+ d = @parser.parse(["-btrue"])
1346
+ ok {d} == {border: true}
1347
+ d = @parser.parse(["-bon"])
1348
+ ok {d} == {border: true}
1349
+ d = @parser.parse(["-byes"])
1350
+ ok {d} == {border: true}
1351
+ #
1352
+ d = @parser.parse(["--border=true"])
1353
+ ok {d} == {border: true}
1354
+ d = @parser.parse(["--border=on"])
1355
+ ok {d} == {border: true}
1356
+ d = @parser.parse(["--border=yes"])
1357
+ ok {d} == {border: true}
1358
+ end
1359
+
1360
+ spec "[!3n810] converts 'false'/'off'/'no' into false." do
1361
+ d = @parser.parse(["-bfalse"])
1362
+ ok {d} == {border: false}
1363
+ d = @parser.parse(["-boff"])
1364
+ ok {d} == {border: false}
1365
+ d = @parser.parse(["-bno"])
1366
+ ok {d} == {border: false}
1367
+ #
1368
+ d = @parser.parse(["--border=false"])
1369
+ ok {d} == {border: false}
1370
+ d = @parser.parse(["--border=off"])
1371
+ ok {d} == {border: false}
1372
+ d = @parser.parse(["--border=no"])
1373
+ ok {d} == {border: false}
1374
+ end
807
1375
 
808
- describe '.new()' do
1376
+ spec "[!h8ayh] raises error when failed to convert value into true nor false." do
1377
+ pr = proc { @parser.parse(["-bt"]) }
1378
+ ok {pr}.raise?(Benry::CmdOpt::OptionError,
1379
+ "-bt: Boolean expected.")
1380
+ #
1381
+ pr = proc { @parser.parse(["--border=t"]) }
1382
+ ok {pr}.raise?(Benry::CmdOpt::OptionError,
1383
+ "--border=t: Boolean expected.")
1384
+ end
809
1385
 
810
- it "[!7kkqv] creates Facade object." do
811
- obj = Benry::Cmdopt.new
812
- ok {obj}.is_a?(Benry::Cmdopt::Facade)
813
1386
  end
814
1387
 
815
- end
816
1388
 
1389
+ topic 'PARAM_TYPES[Date]' do
817
1390
 
818
- end
1391
+ before do
1392
+ require 'date'
1393
+ sc = Benry::CmdOpt::Schema.new
1394
+ sc.add(:date, "-d, --date=<YYYY-MM-DD>]", "date", type: Date)
1395
+ @parser = Benry::CmdOpt::Parser.new(sc)
1396
+ end
1397
+
1398
+ spec "[!sru5j] converts 'YYYY-MM-DD' into date object." do
1399
+ d = @parser.parse(['-d', '2000-01-01'])
1400
+ ok {d[:date]} == Date.new(2000, 1, 1)
1401
+ #
1402
+ d = @parser.parse(['--date=2000-1-2'])
1403
+ ok {d[:date]} == Date.new(2000, 1, 2)
1404
+ end
819
1405
 
1406
+ spec "[!h9q9y] raises error when failed to convert into date object." do
1407
+ pr = proc { @parser.parse(['-d', '2000/01/01']) }
1408
+ ok {pr}.raise?(Benry::CmdOpt::OptionError,
1409
+ "-d 2000/01/01: Invalid date format (ex: '2000-01-01')")
1410
+ #
1411
+ pr = proc { @parser.parse(['--date=01-01-2000']) }
1412
+ ok {pr}.raise?(Benry::CmdOpt::OptionError,
1413
+ "--date=01-01-2000: Invalid date format (ex: '2000-01-01')")
1414
+ end
1415
+
1416
+ spec "[!i4ui8] raises error when specified date not exist." do
1417
+ pr = proc { @parser.parse(['-d', '2001-02-29']) }
1418
+ ok {pr}.raise?(Benry::CmdOpt::OptionError,
1419
+ "-d 2001-02-29: Date not exist.")
1420
+ #
1421
+ pr = proc { @parser.parse(['--date=2001-02-29']) }
1422
+ ok {pr}.raise?(Benry::CmdOpt::OptionError,
1423
+ "--date=2001-02-29: Date not exist.")
1424
+ end
820
1425
 
1426
+ end
821
1427
 
822
- class Benry::Cmdopt::Facade::Test < MiniTest::Test
823
1428
 
1429
+ topic '.new()' do
824
1430
 
825
- describe '#add()' do
1431
+ spec "[!7kkqv] creates Facade object." do
1432
+ obj = Benry::CmdOpt.new
1433
+ ok {obj}.is_a?(Benry::CmdOpt::Facade)
1434
+ end
826
1435
 
827
- it "[!vmb3r] defines command option." do
828
- cmdopt = Benry::Cmdopt.new()
829
- cmdopt.add(:help, "-h, --help", "show help message")
830
- items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
831
- ok {items}.is_a?(Array)
832
- ok {items.length} == 1
833
- ok {items[0].key} == :help
834
- ok {items[0].short} == 'h'
835
- ok {items[0].long} == 'help'
836
- ok {items[0].help} == 'show help message'
837
1436
  end
838
1437
 
1438
+
839
1439
  end
840
1440
 
841
1441
 
842
- describe '#build_option_help()' do
843
1442
 
844
- before do
845
- @cmdopt = Benry::Cmdopt.new
846
- @cmdopt.add(:help , "-h, --help" , "show help message")
847
- @cmdopt.add(:version, " --version" , "print version")
848
- @cmdopt.add(:file , "-f, --file=<FILE>" , "filename")
1443
+ topic Benry::CmdOpt::Facade do
1444
+
1445
+
1446
+ topic '#add()' do
1447
+
1448
+ spec "[!vmb3r] defines command option." do
1449
+ cmdopt = Benry::CmdOpt.new()
1450
+ cmdopt.add(:help, "-h, --help", "show help message", detail: "(text)", tag: :important)
1451
+ items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
1452
+ ok {items}.is_a?(Array)
1453
+ ok {items.length} == 1
1454
+ ok {items[0].key} == :help
1455
+ ok {items[0].short} == 'h'
1456
+ ok {items[0].long} == 'help'
1457
+ ok {items[0].desc} == 'show help message'
1458
+ ok {items[0].detail} == '(text)'
1459
+ ok {items[0].tag} == :important
1460
+ end
1461
+
1462
+ spec "[!71cvg] type, rexp, enum, and range are can be passed as positional args as well as keyword args." do
1463
+ cmdopt = Benry::CmdOpt.new()
1464
+ cmdopt.add(:key, "--optdef[=xx]", "desc", Integer, /\A\d+\z/, [2,4,8], (2..8), value: 4)
1465
+ items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
1466
+ item = items.first
1467
+ ok {item.type} == Integer
1468
+ ok {item.rexp} == /\A\d+\z/
1469
+ ok {item.enum} == [2,4,8]
1470
+ ok {item.range} == (2..8)
1471
+ ok {item.value} == 4
1472
+ end
1473
+
849
1474
  end
850
1475
 
851
- it "[!dm4p8] returns option help message." do
852
- help = @cmdopt.build_option_help()
853
- ok {help} == <<END
1476
+
1477
+ topic '#option_help()' do
1478
+
1479
+ before do
1480
+ @cmdopt = Benry::CmdOpt.new
1481
+ @cmdopt.add(:help , "-h, --help" , "show help message")
1482
+ @cmdopt.add(:version, " --version" , "print version")
1483
+ @cmdopt.add(:file , "-f, --file=<FILE>" , "filename")
1484
+ end
1485
+
1486
+ spec "[!dm4p8] returns option help message." do
1487
+ helpmsg = @cmdopt.option_help()
1488
+ ok {helpmsg} == <<END
854
1489
  -h, --help : show help message
855
1490
  --version : print version
856
1491
  -f, --file=<FILE> : filename
857
1492
  END
1493
+ end
1494
+
858
1495
  end
859
1496
 
860
- end
861
1497
 
1498
+ topic '#to_s()' do
862
1499
 
863
- describe '#each_option_help()' do
1500
+ spec "[!s61vo] '#to_s' is an alias to '#option_help()'." do
1501
+ cmdopt = Benry::CmdOpt.new
1502
+ cmdopt.add(:help , "-h, --help" , "show help message")
1503
+ cmdopt.add(:version, " --version" , "print version")
1504
+ ok {cmdopt.to_s} == cmdopt.option_help()
1505
+ end
864
1506
 
865
- before do
866
- @cmdopt = Benry::Cmdopt.new
867
- @cmdopt.add(:help , "-h, --help" , "show help message")
868
- @cmdopt.add(:version, " --version" , "print version")
869
- @cmdopt.add(:file , "-f, --file=<FILE>" , "filename")
870
1507
  end
871
1508
 
872
- it "[!bw9qx] yields each option definition string and help message." do
873
- cmdopt = @cmdopt
874
- pairs = []
875
- cmdopt.each_option_help do |opt, help|
876
- pairs << [opt, help]
1509
+
1510
+ topic '#each_option_and_desc()' do
1511
+
1512
+ before do
1513
+ @cmdopt = Benry::CmdOpt.new
1514
+ @cmdopt.add(:help , "-h, --help" , "show help message")
1515
+ @cmdopt.add(:version, " --version" , "print version")
1516
+ @cmdopt.add(:debug , "-D" , nil) # hidden option
1517
+ @cmdopt.add(:_trace , "-T" , "trace") # hidden option
1518
+ end
1519
+
1520
+ spec "[!bw9qx] yields each option definition string and help message." do
1521
+ pairs = []
1522
+ @cmdopt.each_option_and_desc {|opt, desc| pairs << [opt, desc] }
1523
+ ok {pairs} == [
1524
+ ["-h, --help" , "show help message"],
1525
+ [" --version", "print version"],
1526
+ ]
1527
+ end
1528
+
1529
+ spec "[!kunfw] yields all items (including hidden items) if `all: true` specified." do
1530
+ ## when 'all: true'
1531
+ pairs = []
1532
+ @cmdopt.each_option_and_desc(all: true) {|opt, desc| pairs << [opt, desc] }
1533
+ ok {pairs} == [
1534
+ ["-h, --help" , "show help message"],
1535
+ [" --version", "print version"],
1536
+ ["-D" , nil],
1537
+ ["-T" , "trace"],
1538
+ ]
1539
+ ## when 'all: false'
1540
+ pairs = []
1541
+ @cmdopt.each_option_and_desc(all: false) {|opt, desc| pairs << [opt, desc] }
1542
+ ok {pairs} == [
1543
+ ["-h, --help" , "show help message"],
1544
+ [" --version", "print version"],
1545
+ ]
1546
+ end
1547
+
1548
+ spec "[!wght5] returns enumerator object if block not given." do
1549
+ ## when 'all: true'
1550
+ xs = @cmdopt.each_option_and_desc(all: true)
1551
+ ok {xs}.is_a?(Enumerator)
1552
+ ok {xs.collect {|x, _| x }} == ["-h, --help", " --version", "-D", "-T"]
1553
+ ## when 'all: false'
1554
+ xs = @cmdopt.each_option_and_desc(all: false)
1555
+ ok {xs}.is_a?(Enumerator)
1556
+ ok {xs.collect {|x, _| x }} == ["-h, --help", " --version"]
877
1557
  end
878
- ok {pairs} == [
879
- ["-h, --help", "show help message"],
880
- [" --version", "print version"],
881
- ["-f, --file=<FILE>", "filename"],
882
- ]
1558
+
883
1559
  end
884
1560
 
885
- end
886
1561
 
1562
+ topic '#parse()' do
887
1563
 
888
- describe '#parse_options()' do
1564
+ before do
1565
+ @cmdopt = Benry::CmdOpt.new()
1566
+ @cmdopt.add(:file, "-f, --file=<FILE>", "file") do |val|
1567
+ File.open(val) {|f| f.read }
1568
+ end
1569
+ @cmdopt.add(:debug, "-d, --debug[=<LEVEL>]", "debug", type: Integer)
1570
+ end
889
1571
 
890
- before do
891
- @cmdopt = Benry::Cmdopt.new()
892
- @cmdopt.add(:file, "-f, --file=<FILE>", "file") do |val|
893
- File.open(val) {|f| f.read }
1572
+ spec "[!areof] handles only OptionError when block given." do
1573
+ errmsg = nil
1574
+ errcls = nil
1575
+ @cmdopt.parse(["-dx"]) {|err|
1576
+ errmsg = err.message
1577
+ errcls = err.class
1578
+ }
1579
+ ok {errmsg} == "-dx: Integer expected."
1580
+ ok {errcls} == Benry::CmdOpt::OptionError
1581
+ #
1582
+ pr = proc do
1583
+ @cmdopt.parse(["-f", "/foo/bar/baz.png"])
1584
+ end
1585
+ ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
894
1586
  end
895
- @cmdopt.add(:file, "-d, --debug[=<LEVEL>]", "debug", type: Integer)
896
- end
897
1587
 
898
- it "[!areof] handles only OptionError when block given." do
899
- errmsg = nil
900
- errcls = nil
901
- @cmdopt.parse(["-dx"]) {|err|
902
- errmsg = err.message
903
- errcls = err.class
904
- }
905
- ok {errmsg} == "-dx: integer expected."
906
- ok {errcls} == Benry::Cmdopt::OptionError
907
- #
908
- pr = proc do
909
- @cmdopt.parse(["-f", "/foo/bar/baz.png"])
1588
+ spec "[!peuva] returns nil when OptionError handled." do
1589
+ ret = @cmdopt.parse(["-dx"]) {|err| 1 }
1590
+ ok {ret} == nil
1591
+ end
1592
+
1593
+ spec "[!za9at] parses options only before args when `all: false`." do
1594
+ argv = ["aaa", "-d3", "bbb"]
1595
+ #
1596
+ argv1 = argv.dup
1597
+ opts1 = @cmdopt.parse(argv1)
1598
+ ok {opts1} == {:debug=>3}
1599
+ ok {argv1} == ["aaa", "bbb"]
1600
+ #
1601
+ argv2 = argv.dup
1602
+ opts2 = @cmdopt.parse(argv2, all: false)
1603
+ ok {opts2} == {}
1604
+ ok {argv2} == ["aaa", "-d3", "bbb"]
910
1605
  end
911
- ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
912
- end
913
1606
 
914
- it "[!peuva] returns nil when OptionError handled." do
915
- ret = @cmdopt.parse(["-dx"]) {|err| 1 }
916
- ok {ret} == nil
917
1607
  end
918
1608
 
1609
+
919
1610
  end
920
1611
 
921
1612