benry-cmdopt 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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