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.
- checksums.yaml +4 -4
- data/CHANGES.md +35 -3
- data/MIT-LICENSE +21 -0
- data/README.md +447 -123
- data/Rakefile.rb +6 -87
- data/benry-cmdopt.gemspec +23 -21
- data/doc/benry-cmdopt.html +648 -0
- data/doc/css/style.css +168 -0
- data/lib/benry/cmdopt.rb +568 -439
- data/task/common-task.rb +139 -0
- data/task/package-task.rb +72 -0
- data/task/readme-task.rb +125 -0
- data/task/test-task.rb +81 -0
- data/test/cmdopt_test.rb +1361 -722
- metadata +22 -28
data/test/cmdopt_test.rb
CHANGED
@@ -1,973 +1,1612 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'minitest/autorun'
|
5
|
-
require 'minitest/ok'
|
3
|
+
require 'oktest'
|
6
4
|
|
7
5
|
require 'benry/cmdopt'
|
8
6
|
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
29
|
+
topic Benry::CmdOpt::Schema do
|
29
30
|
|
30
31
|
|
31
|
-
|
32
|
+
topic '#parse()' do
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
before do
|
35
|
+
@schema = Benry::CmdOpt::Schema.new
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
236
|
-
|
237
|
-
|
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
|
-
|
244
|
-
|
245
|
-
|
279
|
+
s = helpmsg.each_line.first.split(':')[0]
|
280
|
+
ok {s.length} == 41+3
|
281
|
+
end
|
246
282
|
|
247
|
-
|
248
|
-
|
249
|
-
|
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
|
-
|
256
|
-
|
257
|
-
|
291
|
+
s = helpmsg.each_line.first.split(':')[0]
|
292
|
+
ok {s.length} == 42+0
|
293
|
+
end
|
258
294
|
|
259
|
-
|
260
|
-
|
261
|
-
|
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
|
-
|
268
|
-
|
269
|
-
|
303
|
+
s = helpmsg.each_line.to_a.last.split(':')[0]
|
304
|
+
ok {s.length} == 25
|
305
|
+
end
|
270
306
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
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
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
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
|
-
|
322
|
+
end
|
287
323
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
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
|
-
|
297
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
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
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
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
|
-
|
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
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
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
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
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
|
-
|
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
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
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
|
-
|
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
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
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
|
-
|
429
|
-
|
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
|
-
|
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
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
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
|
-
|
451
|
-
|
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
|
-
|
653
|
+
before do
|
654
|
+
@schema = Benry::CmdOpt::Schema.new
|
655
|
+
end
|
465
656
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
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
|
-
|
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
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
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
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
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
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
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
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
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
|
-
|
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
|
-
|
702
|
+
case_when "[!6y8s2] when 'rexp:' specified..." do
|
532
703
|
|
533
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
543
|
-
@parser = Benry::Cmdopt::Parser.new(new_sample_schema())
|
544
|
-
end
|
755
|
+
end
|
545
756
|
|
546
|
-
|
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
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
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
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
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
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
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
|
-
|
591
|
-
ret = @parser.parse(["-dx"]) {|err| 1 }
|
592
|
-
ok {ret} == nil
|
593
|
-
end
|
808
|
+
case_when "[!a0g52] when 'value:' specified..." do
|
594
809
|
|
595
|
-
|
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
|
-
|
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
|
-
|
601
|
-
|
602
|
-
|
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
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
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
|
-
|
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
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
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
|
-
|
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
|
-
|
645
|
-
|
646
|
-
|
886
|
+
spec "[!s8gxl] returns :required if argument is required." do
|
887
|
+
_, item, _ = ITEMS
|
888
|
+
ok {item.arg_requireness()} == :required
|
889
|
+
end
|
647
890
|
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
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
|
-
|
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
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
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
|
-
|
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
|
-
|
1057
|
+
topic '#parse_options()' do
|
711
1058
|
|
1059
|
+
before do
|
1060
|
+
@parser = Benry::CmdOpt::Parser.new(new_sample_schema())
|
1061
|
+
end
|
712
1062
|
|
713
|
-
|
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
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
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
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
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
|
-
|
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
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
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
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
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
|
-
|
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
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
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
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
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
|
-
|
904
|
-
|
905
|
-
|
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
|
-
|
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
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
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
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
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
|
|