benry-cmdopt 1.1.0 → 2.0.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.
data/test/cmdopt_test.rb CHANGED
@@ -1,973 +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 "[!97sn0] raises SchemaError when ',' is missing between short and long options." do
117
- sc = @schema
118
- pr = proc { sc.add(:exec, '-x --exec=ARG', "exec") }
119
- msg = "add(:exec, \"-x --exec=ARG\"): missing ',' between short option and long options."
120
- ok {pr}.raise?(Benry::Cmdopt::SchemaError, msg)
121
- end
122
-
123
- it "[!yht0v] keeps command option definitions." do
124
- sc = @schema
125
- sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width",
126
- type: Integer, pattern: /\A\d+\z/, enum: ['2', '4', '8']) {|v| v.to_i }
127
- items = sc.instance_eval { @items }
128
- ok {items.length} == 1
129
- ok {items[0]}.is_a?(Benry::Cmdopt::SchemaItem)
130
- ok {items[0].key} == :indent
131
- ok {items[0].short} == 'i'
132
- ok {items[0].long} == 'indent'
133
- ok {items[0].param} == '<WIDTH>'
134
- ok {items[0].optional} == true
135
- ok {items[0].type} == Integer
136
- ok {items[0].pattern} == /\A\d+\z/
137
- ok {items[0].enum} == ['2', '4', '8']
138
- ok {items[0].callback}.is_a?(Proc)
139
- ok {items[0].callback.arity} == 1
140
- end
141
-
142
- it "[!rhhji] raises SchemaError when key is not a Symbol." do
143
- sc = @schema
144
- pr = proc {
145
- sc.add("-i, --indent[=<WIDTH>]", "indent width", nil)
146
- }
147
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
148
- 'add("-i, --indent[=<WIDTH>]"): 1st arg should be a Symbol as an option key.')
149
- end
150
-
151
- it "[!vq6eq] raises SchemaError when help message is missing." do
152
- sc = @schema
153
- pr = proc {
154
- begin
155
- sc.add(:indent, "-i, --indent[=<WIDTH>]", type: Array) # Ruby 2
156
- rescue ArgumentError
157
- sc.add(:indent, "-i, --indent[=<WIDTH>]", {type: Array}) # Ruby 3
158
- end
159
- }
160
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
161
- 'add(:indent, "-i, --indent[=<WIDTH>]"): help message required as 3rd argument.')
162
- end
163
-
164
- it "[!7xmr5] raises SchemaError when type is not registered." do
165
- sc = @schema
166
- pr = proc {
167
- sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width", type: Array)
168
- }
169
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
170
- "Array: unregistered type.")
171
- end
172
-
173
- it "[!s2aaj] raises SchemaError when option has no params but type specified." do
174
- sc = @schema
175
- pr = proc {
176
- sc.add(:indent, "-i, --indent", "indent width", type: Integer)
177
- }
178
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
179
- "Integer: type specified in spite of option has no params.")
180
- end
181
-
182
- it "[!bi2fh] raises SchemaError when pattern is not a regexp." do
183
- sc = @schema
184
- pr = proc {
185
- sc.add(:indent, "-x, --indent[=<WIDTH>]", "indent width", pattern: '\A\d+\z')
186
- }
187
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
188
- '"\\\\A\\\\d+\\\\z": regexp expected.')
189
- end
190
-
191
- it "[!01fmt] raises SchmeaError when option has no params but pattern specified." do
192
- sc = @schema
193
- pr = proc {
194
- sc.add(:indent, "-i, --indent", "indent width", pattern: /\A\d+\z/)
195
- }
196
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
197
- '/\A\d+\z/: pattern specified in spite of option has no params.')
198
- end
199
-
200
- it "[!melyd] raises SchmeaError when enum is not a Array nor Set." do
201
- sc = @schema
202
- sc.add(:indent, "-i <N>", "indent width", enum: ["2", "4", "8"])
203
- sc.add(:indent, "-i <N>", "indent width", enum: Set.new(["2", "4", "8"]))
204
- pr = proc {
205
- sc.add(:indent, "-i <N>", "indent width", enum: "2,4,8")
206
- }
207
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
208
- '"2,4,8": array or set expected.')
209
- end
210
-
211
- it "[!xqed8] raises SchemaError when enum specified for no param option." do
212
- sc = @schema
213
- pr = proc {
214
- sc.add(:indent, "-i", "enable indent", enum: [2, 4, 8])
215
- }
216
- ok {pr}.raise?(Benry::Cmdopt::SchemaError,
217
- "[2, 4, 8]: enum specified in spite of option has no params.")
218
138
  end
219
139
 
220
- end
221
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
222
254
 
223
- describe '#option_help()' do
224
255
 
225
- before do
226
- sc = Benry::Cmdopt::Schema.new
227
- sc.add(:help , "-h, --help" , "show help message.")
228
- sc.add(:version, " --version" , "print version")
229
- sc.add(:file , "-f, --file=<FILE>" , "filename")
230
- sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
231
- sc.add(:debug , "-d, --debug" , nil)
232
- @schema = sc
233
256
  end
234
257
 
235
- it "[!0aq0i] can take integer as width." do
236
- help = @schema.option_help(41)
237
- ok {help} == <<END
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
238
274
  -h, --help : show help message.
239
275
  --version : print version
240
276
  -f, --file=<FILE> : filename
241
277
  -i, --indent[=<WIDTH>] : enable indent
242
278
  END
243
- s = help.each_line.first.split(':')[0]
244
- ok {s.length} == 41+3
245
- end
279
+ s = helpmsg.each_line.first.split(':')[0]
280
+ ok {s.length} == 41+3
281
+ end
246
282
 
247
- it "[!pcsah] can take format string." do
248
- help = @schema.option_help("%-42s: %s")
249
- ok {help} == <<END
283
+ spec "[!pcsah] can take format string." do
284
+ helpmsg = @schema.option_help("%-42s: %s")
285
+ ok {helpmsg} == <<END
250
286
  -h, --help : show help message.
251
287
  --version : print version
252
288
  -f, --file=<FILE> : filename
253
289
  -i, --indent[=<WIDTH>] : enable indent
254
290
  END
255
- s = help.each_line.first.split(':')[0]
256
- ok {s.length} == 42+0
257
- end
291
+ s = helpmsg.each_line.first.split(':')[0]
292
+ ok {s.length} == 42+0
293
+ end
258
294
 
259
- it "[!dndpd] detects option width automatically when nothing specified." do
260
- help = @schema.option_help()
261
- ok {help} == <<END
295
+ spec "[!dndpd] detects option width automatically when nothing specified." do
296
+ helpmsg = @schema.option_help()
297
+ ok {helpmsg} == <<END
262
298
  -h, --help : show help message.
263
299
  --version : print version
264
300
  -f, --file=<FILE> : filename
265
301
  -i, --indent[=<WIDTH>] : enable indent
266
302
  END
267
- s = help.each_line.to_a.last.split(':')[0]
268
- ok {s.length} == 25
269
- end
303
+ s = helpmsg.each_line.to_a.last.split(':')[0]
304
+ ok {s.length} == 25
305
+ end
270
306
 
271
- it "[!v7z4x] skips option help if help message is not specified." do
272
- help = @schema.option_help()
273
- ok {help} !~ /debug/
274
- 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
275
311
 
276
- it "[!to1th] includes all option help when `all` is true." do
277
- help = @schema.option_help(nil, all: true)
278
- ok {help} =~ /debug/
279
- 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
280
316
  -h, --help : show help message.
281
317
  --version : print version
282
318
  -f, --file=<FILE> : filename
283
319
  -i, --indent[=<WIDTH>] : enable indent
284
320
  -d, --debug :
285
321
  END
286
- end
322
+ end
287
323
 
288
- it "[!848rm] supports multi-lines help message." do
289
- sc = Benry::Cmdopt::Schema.new
290
- sc.add(:mode, "-m, --mode=<MODE>", <<END)
291
- 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")
292
328
  v, verbose: print many output
293
329
  q, quiet: print litte output
294
330
  c, compact: print summary output
295
331
  END
296
- actual = sc.option_help()
297
- expected = <<END
332
+ actual = sc.option_help()
333
+ expected = <<END
298
334
  -m, --mode=<MODE> : output mode
299
335
  v, verbose: print many output
300
336
  q, quiet: print litte output
301
337
  c, compact: print summary output
302
338
  END
303
- 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
+
304
352
  end
305
353
 
306
- end
307
354
 
355
+ topic '#_default_format()' do
308
356
 
309
- 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
310
366
 
311
- before do
312
- sc = Benry::Cmdopt::Schema.new
313
- sc.add(:help , "-h, --help" , "show help message.")
314
- sc.add(:version, " --version" , "print version")
315
- sc.add(:file , "-f, --file=<FILE>" , "filename")
316
- sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
317
- sc.add(:debug , "-d, --debug" , nil)
318
- @schema = sc
319
- end
367
+ spec "[!kkh9t] returns format string." do
368
+ ret = @schema.__send__(:_default_format)
369
+ ok {ret} == " %-22s : %s"
370
+ end
320
371
 
321
- it "[!kkh9t] returns format string." do
322
- ret = @schema.__send__(:_default_format)
323
- ok {ret} == " %-22s : %s"
324
- 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
325
380
 
326
- it "[!hr45y] detects preffered option width." do
327
- ret = @schema.__send__(:_default_format, 10, 20)
328
- ok {ret} == " %-20s : %s"
329
- ret = @schema.__send__(:_default_format, 30, 40)
330
- ok {ret} == " %-30s : %s"
331
- ret = @schema.__send__(:_default_format, 10, 40)
332
- ok {ret} == " %-22s : %s"
333
- end
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
334
396
 
335
- it "[!bmr7d] changes min_with according to options." do
336
- sc = Benry::Cmdopt::Schema.new
337
- sc.add(:help , '-h', "help")
338
- sc.add(:version, '-v', "version")
339
- ok {sc.__send__(:_default_format, nil, 40)} == " %-8s : %s"
340
- #
341
- sc.add(:file , '-f <FILE>', "filename")
342
- ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
343
- #
344
- sc.add(:force , '--force', "forcedly")
345
- ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
346
- #
347
- sc.add(:mode , '-m, --mode=<MODE>', "verbose/quiet")
348
- ok {sc.__send__(:_default_format, nil, 40)} == " %-20s : %s"
349
397
  end
350
398
 
351
- end
352
399
 
400
+ topic '#_preferred_option_width()' do
353
401
 
354
- describe '#_preferred_option_width()' 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
355
408
 
356
- it "[!kl91t] shorten option help min width when only single options which take no arg." do
357
- sc = Benry::Cmdopt::Schema.new
358
- sc.add(:help , '-h', "help")
359
- sc.add(:version, '-v', "version")
360
- ok {sc.__send__(:_preferred_option_width)} == 8
361
- end
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
362
415
 
363
- it "[!0koqb] widen option help min width when any option takes an arg." do
364
- sc = Benry::Cmdopt::Schema.new
365
- sc.add(:help , '-h', "help")
366
- sc.add(:indent , '-i[<N>]', "indent")
367
- ok {sc.__send__(:_preferred_option_width)} == 14
368
- end
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
369
425
 
370
- it "[!kl91t] widen option help min width when long option exists." do
371
- sc = Benry::Cmdopt::Schema.new
372
- sc.add(:help , '-h', "help")
373
- sc.add(:version, '-v, --version', "version")
374
- ok {sc.__send__(:_preferred_option_width)} == 14
375
- #
376
- sc.add(:file, '--file=<FILE>', "filename")
377
- ok {sc.__send__(:_preferred_option_width)} == 20
378
426
  end
379
427
 
380
- end
381
428
 
429
+ topic '#to_s()' do
382
430
 
383
- describe '#each_option_help()' do
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()
436
+ end
384
437
 
385
- before do
386
- sc = Benry::Cmdopt::Schema.new
387
- sc.add(:help, "-h, --help", "show help message")
388
- sc.add(:version, " --version", "print version")
389
- @schema = sc
390
438
  end
391
439
 
392
- it "[!4b911] yields each optin definition str and help message." do
393
- sc = @schema
394
- arr = []
395
- sc.each_option_help do |opt, help|
396
- arr << [opt, help]
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
397
495
  end
398
- ok {arr} == [
399
- ["-h, --help", "show help message"],
400
- [" --version", "print version"],
401
- ]
402
- end
403
496
 
404
- it "[!zbxyv] returns self." do
405
- sc = @schema
406
- ret = sc.each_option_help { nil }
407
- ok {ret}.same? sc
408
497
  end
409
498
 
410
- end
411
499
 
500
+ topic '#each()' do
412
501
 
413
- 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
414
519
 
415
- before do
416
- @schema = new_sample_schema()
417
520
  end
418
521
 
419
- it "[!b4js1] returns option definition matched to short name." do
420
- x = @schema.find_short_option('h')
421
- ok {x.key} == :help
422
- x = @schema.find_short_option('f')
423
- ok {x.key} == :file
424
- x = @schema.find_short_option('i')
425
- 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
+
426
541
  end
427
542
 
428
- it "[!s4d1y] returns nil when nothing found." do
429
- 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
+
430
563
  end
431
564
 
432
- end
433
565
 
566
+ topic '#delete()' do
434
567
 
435
- describe '#find_long_option()' do
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
581
+
582
+ spec "[!rq0aa] returns deleted item." do
583
+ item = @schema.delete(:version)
584
+ ok {item} != nil
585
+ ok {item.key} == :version
586
+ end
436
587
 
437
- before do
438
- @schema = new_sample_schema()
439
588
  end
440
589
 
441
- it "[!atmf9] returns option definition matched to long name." do
442
- x = @schema.find_long_option('help')
443
- ok {x.key} == :help
444
- x = @schema.find_long_option('file')
445
- ok {x.key} == :file
446
- x = @schema.find_long_option('indent')
447
- 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
+
448
610
  end
449
611
 
450
- it "[!6haoo] returns nil when nothing found." do
451
- 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
+
452
632
  end
453
633
 
634
+
454
635
  end
455
636
 
456
637
 
457
- end
458
638
 
639
+ topic Benry::CmdOpt::SchemaItem do
459
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
+ ]
460
649
 
461
- class Benry::Cmdopt::SchemaItem::Test < MiniTest::Test
462
650
 
651
+ topic '#initialize()' do
463
652
 
464
- describe '#validate_and_convert()' do
653
+ before do
654
+ @schema = Benry::CmdOpt::Schema.new
655
+ end
465
656
 
466
- def new_item(key, optstr, short, long, param, help,
467
- optional: nil, type: nil, pattern: nil, enum: nil, &callback)
468
- return Benry::Cmdopt::SchemaItem.new(key, optstr, short, long, param, help,
469
- optional: optional, type: type, pattern: pattern, enum: enum, &callback)
470
- 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
471
663
 
472
- it "[!h0s0o] raises RuntimeError when value not matched to pattern." do
473
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width", pattern: /\A\d+\z/)
474
- optdict = {}
475
- pr = proc { x.validate_and_convert("abc", optdict) }
476
- ok {pr}.raise?(RuntimeError, "pattern unmatched.")
477
- end
664
+ case_when "[!wy2iv] when 'type:' specified..." do
478
665
 
479
- it "[!5jrdf] raises RuntimeError when value not in enum." do
480
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width", enum: ['2', '4', '8'])
481
- optdict = {}
482
- pr = proc { x.validate_and_convert("10", optdict) }
483
- ok {pr}.raise?(RuntimeError, "expected one of 2/4/8.")
484
- 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
485
674
 
486
- it "[!j4fuz] calls type-specific callback when type specified." do
487
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width", type: Integer)
488
- optdict = {}
489
- pr = proc { x.validate_and_convert("abc", optdict) }
490
- ok {pr}.raise?(RuntimeError, "integer expected.")
491
- 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
492
683
 
493
- it "[!jn9z3] calls callback when callback specified." do
494
- called = false
495
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", "indent width") {|va|
496
- called = true
497
- }
498
- optdict = {}
499
- x.validate_and_convert("abc", optdict)
500
- ok {called} == true
501
- 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
502
691
 
503
- it "[!iqalh] calls callback with different number of args according to arity." do
504
- args1 = nil
505
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil) {|val|
506
- args1 = val
507
- }
508
- optdict = {}
509
- x.validate_and_convert("123", optdict)
510
- ok {args1} == "123"
511
- #
512
- args2 = nil
513
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil) {|optdict, key, val|
514
- args2 = [optdict, key, val]
515
- }
516
- optdict = {}
517
- x.validate_and_convert("123", optdict)
518
- ok {args2} == [optdict, :indent, "123"]
519
- 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
520
699
 
521
- it "[!x066l] returns new value." do
522
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil, type: Integer)
523
- ok {x.validate_and_convert("123", {})} == 123
524
- #
525
- x = new_item(:indent, "", "i", "indent", "<WIDTH>", nil, type: Integer) {|val|
526
- val * 2
527
- }
528
- ok {x.validate_and_convert("123", {})} == 246
529
- end
700
+ end
530
701
 
531
- end
702
+ case_when "[!6y8s2] when 'rexp:' specified..." do
532
703
 
533
- 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
534
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
535
721
 
722
+ end
536
723
 
537
- 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
538
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
539
745
 
540
- 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
541
754
 
542
- before do
543
- @parser = Benry::Cmdopt::Parser.new(new_sample_schema())
544
- end
755
+ end
545
756
 
546
- it "[!3wmsy] returns command option values as a dict." do
547
- argv = ["-h", "--version"]
548
- d = @parser.parse(argv)
549
- ok {d} == {help: true, version: true}
550
- end
757
+ case_when "[!hk4nw] when 'range:' specified..." do
551
758
 
552
- it "[!uh7j8] parses long options." do
553
- argv = ["--help", "--file=foo.png", "--indent=10"]
554
- d = @parser.parse(argv)
555
- ok {d} == {help: true, file: "foo.png", indent: 10}
556
- 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
557
766
 
558
- it "[!nwnjc] parses short options." do
559
- argv = ["-h", "-f", "foo.png", "-i10"]
560
- d = @parser.parse(argv)
561
- ok {d} == {help: true, file: "foo.png", indent: 10}
562
- 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
563
774
 
564
- it "[!y04um] skips rest options when '--' found in argv." do
565
- argv = ["-h", "--", "-f", "foo.png", "-i10"]
566
- d = @parser.parse(argv)
567
- ok {d} == {help: true}
568
- ok {argv} == ["-f", "foo.png", "-i10"]
569
- 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
570
805
 
571
- it "[!qpuxh] handles only OptionError when block given." do
572
- errmsg = nil
573
- errcls = nil
574
- @parser.parse(["-ix"]) {|err|
575
- errmsg = err.message
576
- errcls = err.class
577
- }
578
- ok {errmsg} == "-ix: integer expected."
579
- ok {errcls} == Benry::Cmdopt::OptionError
580
- #
581
- sc = Benry::Cmdopt::Schema.new
582
- sc.add(:file, "--file=<FILE>", "file") do |val|
583
- File.open(val) {|f| f.read }
584
806
  end
585
- parser = Benry::Cmdopt::Parser.new(sc)
586
- pr = proc { parser.parse(["--file=/foo/bar/baz.png"]) }
587
- ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
588
- end
589
807
 
590
- it "[!dhpw1] returns nil when OptionError handled." do
591
- ret = @parser.parse(["-dx"]) {|err| 1 }
592
- ok {ret} == nil
593
- end
808
+ case_when "[!a0g52] when 'value:' specified..." do
594
809
 
595
- 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
596
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
597
827
 
598
- 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
599
836
 
600
- before do
601
- @parser = Benry::Cmdopt::Parser.new(new_sample_schema())
602
- 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
603
844
 
604
- it "[!3i994] raises OptionError when invalid long option format." do
605
- argv = ["--f/o/o"]
606
- pr = proc { @parser.parse(argv) }
607
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--f/o/o: invalid long option.")
608
- 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
609
853
 
610
- it "[!er7h4] raises OptionError when unknown long option." do
611
- argv = ["--foo"]
612
- pr = proc { @parser.parse(argv) }
613
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--foo: unknown long option.")
614
- end
854
+ end
615
855
 
616
- it "[!2jd9w] raises OptionError when no arguments specified for arg required long option." do
617
- argv = ["--file"]
618
- pr = proc { @parser.parse(argv) }
619
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--file: argument required.")
620
856
  end
621
857
 
622
- it "[!qyq8n] raises optionError when an argument specified for no arg long option." do
623
- argv = ["--version=1.0.0"]
624
- pr = proc { @parser.parse(argv) }
625
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--version=1.0.0: unexpected argument.")
626
- end
627
858
 
628
- it "[!o596x] validates argument value." do
629
- argv = ["--indent=abc"]
630
- pr = proc { @parser.parse(argv) }
631
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--indent=abc: integer expected.")
632
- #
633
- argv = ["--path=/foo/bar"]
634
- pr = proc { @parser.parse(argv) }
635
- 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
636
875
 
637
876
  end
638
877
 
639
- end
640
878
 
879
+ topic '#arg_requireness()' do
641
880
 
642
- 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
643
885
 
644
- before do
645
- @parser = Benry::Cmdopt::Parser.new(new_sample_schema())
646
- end
886
+ spec "[!s8gxl] returns :required if argument is required." do
887
+ _, item, _ = ITEMS
888
+ ok {item.arg_requireness()} == :required
889
+ end
647
890
 
648
- it "[!4eh49] raises OptionError when unknown short option specified." do
649
- argv = ["-hxf", "foo.png"]
650
- pr = proc { @parser.parse(argv) }
651
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-x: unknown option.")
652
- end
891
+ spec "[!owpba] returns :optional if argument is optional." do
892
+ _, _, item = ITEMS
893
+ ok {item.arg_requireness()} == :optional
894
+ end
653
895
 
654
- it "[!utdbf] raises OptionError when argument required but not specified." do
655
- argv = ["-hf"]
656
- pr = proc { @parser.parse(argv) }
657
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-f: argument required.")
658
896
  end
659
897
 
660
- it "[!f63hf] short option arg can be specified without space separator." do
661
- argv = ["-hfabc.png", "xx"]
662
- d = @parser.parse(argv)
663
- ok {d} == {help: true, file: "abc.png"}
664
- ok {argv} == ["xx"]
665
- end
666
898
 
667
- it "[!yjq6b] optional arg should be specified without space separator." do
668
- argv = ["-hi123", "xx"]
669
- d = @parser.parse(argv)
670
- ok {d} == {help: true, indent: 123}
671
- ok {argv} == ['xx']
672
- end
899
+ topic '#hidden?()' do
673
900
 
674
- it "[!wape4] otpional arg can be omit." do
675
- argv = ["-hi", "xx"]
676
- d = @parser.parse(argv)
677
- ok {d} == {help: true, indent: true}
678
- ok {argv} == ['xx']
679
- 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
680
918
 
681
- it "[!yu0kc] validates short option argument." do
682
- argv = ["-iaaa"]
683
- pr = proc { @parser.parse(argv) }
684
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-iaaa: integer expected.")
685
- #
686
- argv = ["-I", "/foo/bar"]
687
- pr = proc { @parser.parse(argv) }
688
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-I /foo/bar: directory not exist.")
689
919
  end
690
920
 
691
- end
692
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
943
+
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
693
1028
 
694
- describe '#new_options_dict()' do
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
695
1047
 
696
- it "[!vm6h0] returns new hash object." do
697
- parser = Benry::Cmdopt::Parser.new(new_sample_schema())
698
- ret = parser.__send__(:new_options_dict)
699
- ok {ret}.is_a?(Hash)
700
- ok {ret} == {}
701
1048
  end
702
1049
 
703
1050
  end
704
1051
 
705
1052
 
706
- end
707
1053
 
1054
+ topic Benry::CmdOpt::Parser do
708
1055
 
709
1056
 
710
- class Benry::Cmdopt::Test < MiniTest::Test
1057
+ topic '#parse_options()' do
711
1058
 
1059
+ before do
1060
+ @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1061
+ end
712
1062
 
713
- 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
714
1068
 
715
- before do
716
- sc = Benry::Cmdopt::Schema.new
717
- sc.add(:indent, "-i, --indent[=<N>]", "indent width", type: Integer)
718
- @parser = Benry::Cmdopt::Parser.new(sc)
719
- 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
720
1074
 
721
- it "[!6t8cs] converts value into integer." do
722
- d = @parser.parse(['-i20'])
723
- ok {d[:indent]} == 20
724
- #
725
- d = @parser.parse(['--indent=12'])
726
- ok {d[:indent]} == 12
727
- 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
728
1137
 
729
- it "[!nzwc9] raises error when failed to convert value into integer." do
730
- pr = proc { @parser.parse(['-i2.1']) }
731
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-i2.1: integer expected.")
732
- #
733
- pr = proc { @parser.parse(['--indent=2.2']) }
734
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "--indent=2.2: integer expected.")
735
1138
  end
736
1139
 
737
- end
738
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
739
1183
 
740
- 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
741
1194
 
742
- before do
743
- sc = Benry::Cmdopt::Schema.new
744
- sc.add(:ratio, "-r, --ratio=<RATIO>", "ratio", type: Float)
745
- @parser = Benry::Cmdopt::Parser.new(sc)
746
1195
  end
747
1196
 
748
- it "[!gggy6] converts value into float." do
749
- d = @parser.parse(['-r', '1.25'])
750
- ok {d[:ratio]} == 1.25
751
- #
752
- d = @parser.parse(['--ratio=1.25'])
753
- 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
+
754
1247
  end
755
1248
 
756
- it "[!t4elj] raises error when faield to convert value into float." do
757
- pr = proc { @parser.parse(['-r', 'abc']) }
758
- ok {pr}.raise?(Benry::Cmdopt::OptionError, "-r abc: float expected.")
759
- #
760
- pr = proc { @parser.parse(['--ratio=abc']) }
761
- 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
+
762
1259
  end
763
1260
 
764
- end
765
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
766
1271
 
767
- describe 'PARAM_TYPES[TrueClass]' do
768
-
769
- before do
770
- sc = Benry::Cmdopt::Schema.new
771
- sc.add(:border , "-b, --border[=<on|off>]", "enable border", type: TrueClass)
772
- @parser = Benry::Cmdopt::Parser.new(sc)
773
- end
774
-
775
- it "[!47kx4] converts 'true'/'on'/'yes' into true." do
776
- d = @parser.parse(["-btrue"])
777
- ok {d} == {border: true}
778
- d = @parser.parse(["-bon"])
779
- ok {d} == {border: true}
780
- d = @parser.parse(["-byes"])
781
- ok {d} == {border: true}
782
- #
783
- d = @parser.parse(["--border=true"])
784
- ok {d} == {border: true}
785
- d = @parser.parse(["--border=on"])
786
- ok {d} == {border: true}
787
- d = @parser.parse(["--border=yes"])
788
- ok {d} == {border: true}
789
- end
790
-
791
- it "[!3n810] converts 'false'/'off'/'no' into false." do
792
- d = @parser.parse(["-bfalse"])
793
- ok {d} == {border: false}
794
- d = @parser.parse(["-boff"])
795
- ok {d} == {border: false}
796
- d = @parser.parse(["-bno"])
797
- ok {d} == {border: false}
798
- #
799
- d = @parser.parse(["--border=false"])
800
- ok {d} == {border: false}
801
- d = @parser.parse(["--border=off"])
802
- ok {d} == {border: false}
803
- d = @parser.parse(["--border=no"])
804
- ok {d} == {border: false}
805
- end
806
-
807
- it "[!h8ayh] raises error when failed to convert value into true nor false." do
808
- pr = proc { @parser.parse(["-bt"]) }
809
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
810
- "-bt: boolean expected.")
811
- #
812
- pr = proc { @parser.parse(["--border=t"]) }
813
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
814
- "--border=t: boolean expected.")
815
1272
  end
816
1273
 
1274
+
817
1275
  end
818
1276
 
819
1277
 
820
- describe 'PARAM_TYPES[Date]' do
821
1278
 
822
- before do
823
- require 'date'
824
- sc = Benry::Cmdopt::Schema.new
825
- sc.add(:date, "-d, --date=<YYYY-MM-DD>]", "date", type: Date)
826
- @parser = Benry::Cmdopt::Parser.new(sc)
827
- end
1279
+ topic Benry::CmdOpt do
828
1280
 
829
- it "[!sru5j] converts 'YYYY-MM-DD' into date object." do
830
- d = @parser.parse(['-d', '2000-01-01'])
831
- ok {d[:date]} == Date.new(2000, 1, 1)
832
- #
833
- d = @parser.parse(['--date=2000-1-2'])
834
- ok {d[:date]} == Date.new(2000, 1, 2)
835
- end
836
1281
 
837
- it "[!h9q9y] raises error when failed to convert into date object." do
838
- pr = proc { @parser.parse(['-d', '2000/01/01']) }
839
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
840
- "-d 2000/01/01: invalid date format (ex: '2000-01-01')")
841
- #
842
- pr = proc { @parser.parse(['--date=01-01-2000']) }
843
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
844
- "--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
+
845
1306
  end
846
1307
 
847
- it "[!i4ui8] raises error when specified date not exist." do
848
- pr = proc { @parser.parse(['-d', '2001-02-29']) }
849
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
850
- "-d 2001-02-29: date not exist.")
851
- #
852
- pr = proc { @parser.parse(['--date=2001-02-29']) }
853
- ok {pr}.raise?(Benry::Cmdopt::OptionError,
854
- "--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
+
855
1333
  end
856
1334
 
857
- end
858
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
859
1375
 
860
- 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
861
1385
 
862
- it "[!7kkqv] creates Facade object." do
863
- obj = Benry::Cmdopt.new
864
- ok {obj}.is_a?(Benry::Cmdopt::Facade)
865
1386
  end
866
1387
 
867
- end
868
1388
 
1389
+ topic 'PARAM_TYPES[Date]' do
869
1390
 
870
- 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
871
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
872
1425
 
1426
+ end
873
1427
 
874
- class Benry::Cmdopt::Facade::Test < MiniTest::Test
875
1428
 
1429
+ topic '.new()' do
876
1430
 
877
- 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
878
1435
 
879
- it "[!vmb3r] defines command option." do
880
- cmdopt = Benry::Cmdopt.new()
881
- cmdopt.add(:help, "-h, --help", "show help message")
882
- items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
883
- ok {items}.is_a?(Array)
884
- ok {items.length} == 1
885
- ok {items[0].key} == :help
886
- ok {items[0].short} == 'h'
887
- ok {items[0].long} == 'help'
888
- ok {items[0].help} == 'show help message'
889
1436
  end
890
1437
 
1438
+
891
1439
  end
892
1440
 
893
1441
 
894
- describe '#option_help()' do
895
1442
 
896
- before do
897
- @cmdopt = Benry::Cmdopt.new
898
- @cmdopt.add(:help , "-h, --help" , "show help message")
899
- @cmdopt.add(:version, " --version" , "print version")
900
- @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
+
901
1474
  end
902
1475
 
903
- it "[!dm4p8] returns option help message." do
904
- help = @cmdopt.option_help()
905
- 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
906
1489
  -h, --help : show help message
907
1490
  --version : print version
908
1491
  -f, --file=<FILE> : filename
909
1492
  END
1493
+ end
1494
+
910
1495
  end
911
1496
 
912
- end
913
1497
 
1498
+ topic '#to_s()' do
914
1499
 
915
- 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
916
1506
 
917
- before do
918
- @cmdopt = Benry::Cmdopt.new
919
- @cmdopt.add(:help , "-h, --help" , "show help message")
920
- @cmdopt.add(:version, " --version" , "print version")
921
- @cmdopt.add(:file , "-f, --file=<FILE>" , "filename")
922
1507
  end
923
1508
 
924
- it "[!bw9qx] yields each option definition string and help message." do
925
- cmdopt = @cmdopt
926
- pairs = []
927
- cmdopt.each_option_help do |opt, help|
928
- 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"]
929
1557
  end
930
- ok {pairs} == [
931
- ["-h, --help", "show help message"],
932
- [" --version", "print version"],
933
- ["-f, --file=<FILE>", "filename"],
934
- ]
1558
+
935
1559
  end
936
1560
 
937
- end
938
1561
 
1562
+ topic '#parse()' do
939
1563
 
940
- 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
941
1571
 
942
- before do
943
- @cmdopt = Benry::Cmdopt.new()
944
- @cmdopt.add(:file, "-f, --file=<FILE>", "file") do |val|
945
- 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/)
946
1586
  end
947
- @cmdopt.add(:file, "-d, --debug[=<LEVEL>]", "debug", type: Integer)
948
- end
949
1587
 
950
- it "[!areof] handles only OptionError when block given." do
951
- errmsg = nil
952
- errcls = nil
953
- @cmdopt.parse(["-dx"]) {|err|
954
- errmsg = err.message
955
- errcls = err.class
956
- }
957
- ok {errmsg} == "-dx: integer expected."
958
- ok {errcls} == Benry::Cmdopt::OptionError
959
- #
960
- pr = proc do
961
- @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"]
962
1605
  end
963
- ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
964
- end
965
1606
 
966
- it "[!peuva] returns nil when OptionError handled." do
967
- ret = @cmdopt.parse(["-dx"]) {|err| 1 }
968
- ok {ret} == nil
969
1607
  end
970
1608
 
1609
+
971
1610
  end
972
1611
 
973
1612