benry-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +428 -0
- data/Rakefile +108 -0
- data/benry-cli.gemspec +30 -0
- data/lib/benry/cli.rb +595 -0
- data/test/cli_test.rb +1025 -0
- metadata +79 -0
data/test/cli_test.rb
ADDED
@@ -0,0 +1,1025 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'minitest/spec'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/ok'
|
6
|
+
|
7
|
+
require 'benry/cli'
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
class HelloAction < Benry::CLI::Action
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
class HelloSubAction < HelloAction
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
class GitAction < Benry::CLI::Action
|
20
|
+
|
21
|
+
self.prefix = 'git'
|
22
|
+
|
23
|
+
@action.('switch', 'switch git branch')
|
24
|
+
@option.('-v, --verbose', "verbose mode")
|
25
|
+
def do_git_switch(branch, verbose: false)
|
26
|
+
puts "git checkout #{branch}"
|
27
|
+
end
|
28
|
+
|
29
|
+
@action.('fork', 'create and switch to new branch')
|
30
|
+
@option.('-v, --verbose', "verbose mode")
|
31
|
+
def do_git_fork(branch, verbose: false)
|
32
|
+
puts "git checkout -b #{branch}"
|
33
|
+
end
|
34
|
+
|
35
|
+
@action.('join', 'merge branch with --no-ff')
|
36
|
+
def do_git_join(branch)
|
37
|
+
puts "git merge --no-ff #{branch}"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
describe Benry::CLI::OptionSchema do
|
45
|
+
|
46
|
+
|
47
|
+
describe '.parse()' do
|
48
|
+
|
49
|
+
def _arg_should_be_nothing(x)
|
50
|
+
ok {x.argname} == nil
|
51
|
+
ok {x.arg_required?} == false
|
52
|
+
ok {x.arg_optional?} == false
|
53
|
+
ok {x.arg_nothing?} == true
|
54
|
+
end
|
55
|
+
|
56
|
+
def _arg_should_be_required(x, argname)
|
57
|
+
ok {x.argname} == argname
|
58
|
+
ok {x.arg_required?} == true
|
59
|
+
ok {x.arg_optional?} == false
|
60
|
+
ok {x.arg_nothing?} == false
|
61
|
+
end
|
62
|
+
|
63
|
+
def _arg_should_be_optional(x, argname)
|
64
|
+
ok {x.argname} == argname
|
65
|
+
ok {x.arg_required?} == false
|
66
|
+
ok {x.arg_optional?} == true
|
67
|
+
ok {x.arg_nothing?} == false
|
68
|
+
end
|
69
|
+
|
70
|
+
it "[!fdh36] can parse '-v, --version' (short + long)." do
|
71
|
+
x = Benry::CLI::OptionSchema.parse("-v, --version", "print version")
|
72
|
+
ok {x.short} == "v"
|
73
|
+
ok {x.long} == "version"
|
74
|
+
ok {x.desc} == "print version"
|
75
|
+
_arg_should_be_nothing(x)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "[!jkmee] can parse '-v' (short)" do
|
79
|
+
x = Benry::CLI::OptionSchema.parse("-v", "print version")
|
80
|
+
ok {x.short} == "v"
|
81
|
+
ok {x.long} == nil
|
82
|
+
ok {x.desc} == "print version"
|
83
|
+
_arg_should_be_nothing(x)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "[!uc2en] can parse '--version' (long)." do
|
87
|
+
x = Benry::CLI::OptionSchema.parse("--version", "print version")
|
88
|
+
ok {x.short} == nil
|
89
|
+
ok {x.long} == "version"
|
90
|
+
ok {x.desc} == "print version"
|
91
|
+
_arg_should_be_nothing(x)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "[!sy157] can parse '-f, --file=FILE' (short + long + required-arg)." do
|
95
|
+
x = Benry::CLI::OptionSchema.parse("-f, --file=FILENAME", "config file")
|
96
|
+
ok {x.short} == "f"
|
97
|
+
ok {x.long} == "file"
|
98
|
+
ok {x.desc} == "config file"
|
99
|
+
_arg_should_be_required(x, "FILENAME")
|
100
|
+
end
|
101
|
+
|
102
|
+
it "[!wrjqa] can parse '-f FILE' (short + required-arg)." do
|
103
|
+
x = Benry::CLI::OptionSchema.parse("-f FILENAME", "config file")
|
104
|
+
ok {x.short} == "f"
|
105
|
+
ok {x.long} == nil
|
106
|
+
ok {x.desc} == "config file"
|
107
|
+
_arg_should_be_required(x, "FILENAME")
|
108
|
+
end
|
109
|
+
|
110
|
+
it "[!ip99s] can parse '--file=FILE' (long + required-arg)." do
|
111
|
+
x = Benry::CLI::OptionSchema.parse("--file=FILENAME", "config file")
|
112
|
+
ok {x.short} == nil
|
113
|
+
ok {x.long} == "file"
|
114
|
+
ok {x.desc} == "config file"
|
115
|
+
_arg_should_be_required(x, "FILENAME")
|
116
|
+
end
|
117
|
+
|
118
|
+
it "[!9pmv8] can parse '-i, --indent[=N]' (short + long + optional-arg)." do
|
119
|
+
x = Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "indent (default 2)")
|
120
|
+
ok {x.short} == "i"
|
121
|
+
ok {x.long} == "indent"
|
122
|
+
ok {x.desc} == "indent (default 2)"
|
123
|
+
_arg_should_be_optional(x, "N")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "[!ooo42] can parse '-i[N]' (short + optional-arg)." do
|
127
|
+
x = Benry::CLI::OptionSchema.parse("-i[N]", "indent (default 2)")
|
128
|
+
ok {x.short} == "i"
|
129
|
+
ok {x.long} == nil
|
130
|
+
ok {x.desc} == "indent (default 2)"
|
131
|
+
_arg_should_be_optional(x, "N")
|
132
|
+
end
|
133
|
+
|
134
|
+
it "[!o93c7] can parse '--indent[=N]' (long + optional-arg)." do
|
135
|
+
x = Benry::CLI::OptionSchema.parse("--indent[=N]", "indent (default 2)")
|
136
|
+
ok {x.short} == nil
|
137
|
+
ok {x.long} == "indent"
|
138
|
+
ok {x.desc} == "indent (default 2)"
|
139
|
+
_arg_should_be_optional(x, "N")
|
140
|
+
end
|
141
|
+
|
142
|
+
it "[!gzuhx] can parse string with extra spaces." do
|
143
|
+
x = Benry::CLI::OptionSchema.parse(" -v, --version ", "print version")
|
144
|
+
ok {x.short} == "v"
|
145
|
+
ok {x.long} == "version"
|
146
|
+
ok {x.argname} == nil
|
147
|
+
x = Benry::CLI::OptionSchema.parse(" -f, --file=FILENAME ", "config file")
|
148
|
+
ok {x.short} == "f"
|
149
|
+
ok {x.long} == "file"
|
150
|
+
ok {x.argname} == "FILENAME"
|
151
|
+
x = Benry::CLI::OptionSchema.parse(" -i, --indent[=N] ", "indent (default 2)")
|
152
|
+
ok {x.short} == "i"
|
153
|
+
ok {x.long} == "indent"
|
154
|
+
ok {x.argname} == "N"
|
155
|
+
end
|
156
|
+
|
157
|
+
it "[!cy1ux] regards canonical name of '-f NAME #file' as 'file'." do
|
158
|
+
x = Benry::CLI::OptionSchema.parse("-v #version", "print version")
|
159
|
+
ok {x.short} == "v"
|
160
|
+
ok {x.long} == nil
|
161
|
+
ok {x.name} == "version"
|
162
|
+
ok {x.argname} == nil
|
163
|
+
x = Benry::CLI::OptionSchema.parse("-f FILENAME #file", "config file")
|
164
|
+
ok {x.short} == "f"
|
165
|
+
ok {x.long} == nil
|
166
|
+
ok {x.name} == "file"
|
167
|
+
ok {x.argname} == "FILENAME"
|
168
|
+
x = Benry::CLI::OptionSchema.parse("-i[N] #indent", "indent (default 2)")
|
169
|
+
ok {x.short} == "i"
|
170
|
+
ok {x.long} == nil
|
171
|
+
ok {x.name} == "indent"
|
172
|
+
ok {x.argname} == "N"
|
173
|
+
end
|
174
|
+
|
175
|
+
it "[!6f4xx] uses long name or short name as option name when option name is not specfied." do
|
176
|
+
x = Benry::CLI::OptionSchema.parse("-v, --ver #version", "")
|
177
|
+
ok {x.name} == "version"
|
178
|
+
ok {x.short} == "v"
|
179
|
+
ok {x.long} == "ver"
|
180
|
+
x = Benry::CLI::OptionSchema.parse("-v #version", "")
|
181
|
+
ok {x.name} == "version"
|
182
|
+
ok {x.short} == "v"
|
183
|
+
ok {x.long} == nil
|
184
|
+
x = Benry::CLI::OptionSchema.parse("--ver #version", "")
|
185
|
+
ok {x.name} == "version"
|
186
|
+
ok {x.short} == nil
|
187
|
+
ok {x.long} == "ver"
|
188
|
+
#
|
189
|
+
x = Benry::CLI::OptionSchema.parse("-v, --ver", "")
|
190
|
+
ok {x.name} == "ver"
|
191
|
+
ok {x.short} == "v"
|
192
|
+
ok {x.long} == "ver"
|
193
|
+
x = Benry::CLI::OptionSchema.parse("-v", "")
|
194
|
+
ok {x.name} == "v"
|
195
|
+
ok {x.short} == "v"
|
196
|
+
ok {x.long} == nil
|
197
|
+
x = Benry::CLI::OptionSchema.parse("--ver", "")
|
198
|
+
ok {x.name} == "ver"
|
199
|
+
ok {x.short} == nil
|
200
|
+
ok {x.long} == "ver"
|
201
|
+
end
|
202
|
+
|
203
|
+
it "[!1769n] raises error when invalid format." do
|
204
|
+
pr = proc { Benry::CLI::OptionSchema.parse("-f, --file FILENAME", "config file") }
|
205
|
+
ok {pr}.raise?(Benry::CLI::OptionDefinitionError,
|
206
|
+
"'-f, --file FILENAME': failed to parse option definition.")
|
207
|
+
end
|
208
|
+
|
209
|
+
it "[!j2wgf] raises error when '-i [N]' specified." do
|
210
|
+
pr = proc { Benry::CLI::OptionSchema.parse("-i [N]", "indent (default 2)") }
|
211
|
+
ok {pr}.raise?(Benry::CLI::OptionDefinitionError,
|
212
|
+
"'-i [N]': failed to parse option definition due to extra space before '[' (should be '-i[N]').")
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
describe '#option_string()' do
|
219
|
+
|
220
|
+
it "[!pdaz3] builds option definition string." do
|
221
|
+
cls = Benry::CLI::OptionSchema
|
222
|
+
#
|
223
|
+
ok {cls.parse("-v, --version", "") .option_string} == "-v, --version"
|
224
|
+
ok {cls.parse("-v", "") .option_string} == "-v"
|
225
|
+
ok {cls.parse("--version", "") .option_string} == " --version"
|
226
|
+
#
|
227
|
+
ok {cls.parse("-f, --file=FILE1", "") .option_string} == "-f, --file=FILE1"
|
228
|
+
ok {cls.parse("-f FILE1", "") .option_string} == "-f FILE1"
|
229
|
+
ok {cls.parse("--file=FILE1", "") .option_string} == " --file=FILE1"
|
230
|
+
#
|
231
|
+
ok {cls.parse("-i, --indent[=N]", "") .option_string} == "-i, --indent[=N]"
|
232
|
+
ok {cls.parse("-i[=N]", "") .option_string} == "-i[=N]"
|
233
|
+
ok {cls.parse("--indent[=N]", "") .option_string} == " --indent[=N]"
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
describe Benry::CLI::OptionParser do
|
244
|
+
|
245
|
+
def _option_schemas
|
246
|
+
return [
|
247
|
+
Benry::CLI::OptionSchema.parse("-v, --version", "print version"),
|
248
|
+
Benry::CLI::OptionSchema.parse("-f, --file=FILE", "config file"),
|
249
|
+
Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "indent (default 2)"),
|
250
|
+
]
|
251
|
+
end
|
252
|
+
|
253
|
+
def _option_parser
|
254
|
+
arr = _option_schemas()
|
255
|
+
return Benry::CLI::OptionParser.new(arr)
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
describe '#initialize()' do
|
260
|
+
|
261
|
+
it "[!bflls] takes array of option schema." do
|
262
|
+
arr = _option_schemas()
|
263
|
+
parser = Benry::CLI::OptionParser.new(arr)
|
264
|
+
parser.instance_exec(self) do |_|
|
265
|
+
_.ok {@option_schemas}.is_a?(Array)
|
266
|
+
_.ok {@option_schemas.length} == 3
|
267
|
+
_.ok {@option_schemas[0].long} == "version"
|
268
|
+
_.ok {@option_schemas[1].long} == "file"
|
269
|
+
_.ok {@option_schemas[2].long} == "indent"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
describe '#otpion()' do
|
277
|
+
|
278
|
+
it "[!s59ly] accepts option definition string and description." do
|
279
|
+
parser = Benry::CLI::OptionParser.new
|
280
|
+
parser.option('-v, --verbose', "set verbose mode")
|
281
|
+
parser.option('-f, --file=NAME', "config file")
|
282
|
+
parser.option('-i, --indent[=n]', "indentation (default 2)") {|val| val.to_i }
|
283
|
+
args = ["-vffoo.txt", "-i2", "x", "y"]
|
284
|
+
options = parser.parse(args)
|
285
|
+
ok {options} == {"verbose"=>true, "file"=>"foo.txt", "indent"=>2}
|
286
|
+
ok {args} == ["x", "y"]
|
287
|
+
end
|
288
|
+
|
289
|
+
it "[!2gfnh] recognizes first argument as option name if it is a symbol." do
|
290
|
+
parser = Benry::CLI::OptionParser.new
|
291
|
+
parser.option(:verbose, '-v ', "set verbose mode")
|
292
|
+
parser.option(:file , '-f NAME', "config file")
|
293
|
+
parser.option(:indent , '-i[=n] ', "indentation (default 2)")
|
294
|
+
args = ["-vffoo.txt", "-i", "x", "y"]
|
295
|
+
options = parser.parse(args)
|
296
|
+
ok {options} == {"verbose"=>true, "file"=>"foo.txt", "indent"=>true}
|
297
|
+
ok {args} == ["x", "y"]
|
298
|
+
end
|
299
|
+
|
300
|
+
it "[!fv5g4] return self in order to chain method call." do
|
301
|
+
parser = Benry::CLI::OptionParser.new
|
302
|
+
ret = parser.option('-v, --verbose', "set verbose mode")
|
303
|
+
ok {ret}.same?(parser)
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
|
309
|
+
describe '#each_option_string()' do
|
310
|
+
|
311
|
+
it "[!luro4] yields each option string and description." do
|
312
|
+
parser = Benry::CLI::OptionParser.new(_option_schemas())
|
313
|
+
#
|
314
|
+
arr = []
|
315
|
+
parser.each_option_string do |optstr, desc|
|
316
|
+
arr << [optstr, desc]
|
317
|
+
end
|
318
|
+
ok {arr} == [
|
319
|
+
['-v, --version' , "print version"],
|
320
|
+
['-f, --file=FILE' , "config file"],
|
321
|
+
['-i, --indent[=N]' , "indent (default 2)"],
|
322
|
+
]
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
|
328
|
+
describe '#each_option_schema()' do
|
329
|
+
|
330
|
+
it "[!ycgdm] yields each option schema." do
|
331
|
+
parser = Benry::CLI::OptionParser.new(_option_schemas())
|
332
|
+
#
|
333
|
+
arr = []
|
334
|
+
parser.each_option_schema do |schema|
|
335
|
+
arr << [schema.option_string, schema.desc]
|
336
|
+
end
|
337
|
+
ok {arr} == [
|
338
|
+
['-v, --version' , "print version"],
|
339
|
+
['-f, --file=FILE' , "config file"],
|
340
|
+
['-i, --indent[=N]' , "indent (default 2)"],
|
341
|
+
]
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
346
|
+
|
347
|
+
describe '#parse()' do
|
348
|
+
|
349
|
+
it "[!5jfhv] returns command-line options as hash object." do
|
350
|
+
p = _option_parser()
|
351
|
+
args = "-vffile.txt foo bar".split()
|
352
|
+
ok {p.parse(args)} == {"version"=>true, "file"=>"file.txt"}
|
353
|
+
args = "--file=foo.txt --version --indent=2".split()
|
354
|
+
ok {p.parse(args)} == {"version"=>true, "file"=>"foo.txt", "indent"=>"2"}
|
355
|
+
end
|
356
|
+
|
357
|
+
it "[!06iq3] removes command-line options from args." do
|
358
|
+
p = _option_parser()
|
359
|
+
args = "-vffile.txt foo bar".split()
|
360
|
+
p.parse(args)
|
361
|
+
ok {args} == ["foo", "bar"]
|
362
|
+
args = "--file=foo.txt --version --indent=2 1 2".split()
|
363
|
+
p.parse(args)
|
364
|
+
ok {args} == ["1", "2"]
|
365
|
+
end
|
366
|
+
|
367
|
+
it "[!j2fda] stops command-line parsing when '-' found in args." do
|
368
|
+
p = _option_parser()
|
369
|
+
args = "-v - -f file.txt foo bar".split()
|
370
|
+
options = p.parse(args)
|
371
|
+
ok {options} == {'version'=>true}
|
372
|
+
ok {args} == ["-", "-f", "file.txt", "foo", "bar"]
|
373
|
+
end
|
374
|
+
|
375
|
+
it "[!w5dpy] can parse long options." do
|
376
|
+
p = _option_parser()
|
377
|
+
args = "--version".split()
|
378
|
+
ok {p.parse(args)} == {"version"=>true}
|
379
|
+
args = "--file=foo.txt".split()
|
380
|
+
ok {p.parse(args)} == {"file"=>"foo.txt"}
|
381
|
+
args = "--indent".split()
|
382
|
+
ok {p.parse(args)} == {"indent"=>true}
|
383
|
+
args = "--indent=99".split()
|
384
|
+
ok {p.parse(args)} == {"indent"=>"99"}
|
385
|
+
end
|
386
|
+
|
387
|
+
it "[!mov8e] can parse short options." do
|
388
|
+
p = _option_parser()
|
389
|
+
args = "-v".split()
|
390
|
+
ok {p.parse(args)} == {"version"=>true}
|
391
|
+
args = "-f foo.txt".split()
|
392
|
+
ok {p.parse(args)} == {"file"=>"foo.txt"}
|
393
|
+
args = "-i foo bar".split()
|
394
|
+
ok {p.parse(args)} == {"indent"=>true}
|
395
|
+
args = "-i99 foo bar".split()
|
396
|
+
ok {p.parse(args)} == {"indent"=>"99"}
|
397
|
+
end
|
398
|
+
|
399
|
+
it "[!31h46] stops parsing when '--' appears in args." do
|
400
|
+
p = _option_parser()
|
401
|
+
args = "-v -- -ffile.txt foo bar".split()
|
402
|
+
ok {p.parse(args)} == {"version"=>true}
|
403
|
+
ok {args} == ["-ffile.txt", "foo", "bar"]
|
404
|
+
end
|
405
|
+
|
406
|
+
it "[!w67gl] raises error when long option is unknown." do
|
407
|
+
p = _option_parser()
|
408
|
+
pr = proc { p.parse("-v --verbose".split()) }
|
409
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "--verbose: unknown option.")
|
410
|
+
pr = proc { p.parse("-v --quiet=yes".split()) }
|
411
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "--quiet: unknown option.")
|
412
|
+
end
|
413
|
+
|
414
|
+
it "[!kyd1j] raises error when required argument of long option is missing." do
|
415
|
+
p = _option_parser()
|
416
|
+
pr = proc { p.parse("-v --file".split()) }
|
417
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "--file: argument required.")
|
418
|
+
end
|
419
|
+
|
420
|
+
it "[!wuyrh] uses true as default value of optional argument of long option." do
|
421
|
+
p = _option_parser()
|
422
|
+
ok {p.parse("-v --indent".split())} == {"indent"=>true, "version"=>true}
|
423
|
+
end
|
424
|
+
|
425
|
+
it "[!91b2j] raises error when long option takes no argument but specified." do
|
426
|
+
p = _option_parser()
|
427
|
+
pr = proc { p.parse("-v --version=1.1".split()) }
|
428
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "--version=1.1: unexpected argument.")
|
429
|
+
end
|
430
|
+
|
431
|
+
it "[!9td8b] invokes callback with long option value if callback exists." do
|
432
|
+
p = _option_parser()
|
433
|
+
ok {p.parse(["--indent=99"])} == {"indent"=>"99"}
|
434
|
+
#
|
435
|
+
arr = [
|
436
|
+
Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "") {|value| value.to_i }
|
437
|
+
]
|
438
|
+
p2 = Benry::CLI::OptionParser.new(arr)
|
439
|
+
ok {p2.parse(["--indent=99"])} == {"indent"=>99}
|
440
|
+
end
|
441
|
+
|
442
|
+
it "[!1hak2] invokes callback with long option values as 2nd argument." do
|
443
|
+
arr = [
|
444
|
+
Benry::CLI::OptionSchema.parse("--include=path", "") {|val, values|
|
445
|
+
(values['include'] || []) << val
|
446
|
+
}
|
447
|
+
]
|
448
|
+
p = Benry::CLI::OptionParser.new(arr)
|
449
|
+
args = ["--include=/tmp", "--include=/var/tmp", "--include=/usr/tmp"]
|
450
|
+
ok {p.parse(args)} == {"include"=>["/tmp", "/var/tmp", "/usr/tmp"]}
|
451
|
+
end
|
452
|
+
|
453
|
+
it "[!nkqln] regards RuntimeError callback raised as long option error." do
|
454
|
+
arr = [
|
455
|
+
Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "") {|val|
|
456
|
+
val =~ /\A\d+\z/ or raise "positive integer expected."
|
457
|
+
val.to_i
|
458
|
+
}
|
459
|
+
]
|
460
|
+
p2 = Benry::CLI::OptionParser.new(arr)
|
461
|
+
pr = proc { p2.parse(["--indent=9.9"]) }
|
462
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "--indent=9.9: positive integer expected.")
|
463
|
+
end
|
464
|
+
|
465
|
+
it "[!wr58v] raises error when unknown short option specified." do
|
466
|
+
p = _option_parser()
|
467
|
+
pr = proc { p.parse("-vx".split()) }
|
468
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "-x: unknown option.")
|
469
|
+
end
|
470
|
+
|
471
|
+
it "[!jzdcr] raises error when requried argument of short option is missing." do
|
472
|
+
p = _option_parser()
|
473
|
+
pr = proc { p.parse("-vf".split()) }
|
474
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "-f: argument required.")
|
475
|
+
end
|
476
|
+
|
477
|
+
it "[!hnki9] uses true as default value of optional argument of short option." do
|
478
|
+
p = _option_parser()
|
479
|
+
ok {p.parse("-i".split())} == {"indent"=>true}
|
480
|
+
end
|
481
|
+
|
482
|
+
it "[!8gj65] uses true as value of short option which takes no argument." do
|
483
|
+
p = _option_parser()
|
484
|
+
ok {p.parse("-v".split())} == {"version"=>true}
|
485
|
+
end
|
486
|
+
|
487
|
+
it "[!l6gss] invokes callback with short option value if exists." do
|
488
|
+
p = _option_parser()
|
489
|
+
ok {p.parse(["-i99"])} == {"indent"=>"99"}
|
490
|
+
#
|
491
|
+
arr = [
|
492
|
+
Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "") {|value| value.to_i }
|
493
|
+
]
|
494
|
+
p2 = Benry::CLI::OptionParser.new(arr)
|
495
|
+
ok {p2.parse(["-i99"])} == {"indent"=>99}
|
496
|
+
end
|
497
|
+
|
498
|
+
it "[!g4pld] invokes callback with short option values as 2nd argument." do
|
499
|
+
arr = [
|
500
|
+
Benry::CLI::OptionSchema.parse("-I path #include", "") {|val, values|
|
501
|
+
(values['include'] || []) << val
|
502
|
+
}
|
503
|
+
]
|
504
|
+
p = Benry::CLI::OptionParser.new(arr)
|
505
|
+
args = ['-I', '/tmp', '-I', '/var/tmp', '-I/usr/tmp']
|
506
|
+
ok {p.parse(args)} == {'include'=>['/tmp', '/var/tmp', '/usr/tmp']}
|
507
|
+
end
|
508
|
+
|
509
|
+
it "[!d4mgr] regards RuntimeError callback raised as short option error." do
|
510
|
+
arr = [
|
511
|
+
Benry::CLI::OptionSchema.parse("-L, --level=N", "") {|val|
|
512
|
+
val =~ /\A\d+\z/ or raise "positive integer expected."
|
513
|
+
val.to_i
|
514
|
+
}
|
515
|
+
]
|
516
|
+
p1 = Benry::CLI::OptionParser.new(arr)
|
517
|
+
pr = proc { p1.parse(["-L9.9"]) }
|
518
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "-L 9.9: positive integer expected.")
|
519
|
+
#
|
520
|
+
arr = [
|
521
|
+
Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "") {|val|
|
522
|
+
val =~ /\A\d+\z/ or raise "positive integer expected."
|
523
|
+
val.to_i
|
524
|
+
}
|
525
|
+
]
|
526
|
+
p2 = Benry::CLI::OptionParser.new(arr)
|
527
|
+
pr = proc { p2.parse(["-i9.9"]) }
|
528
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "-i9.9: positive integer expected.")
|
529
|
+
end
|
530
|
+
|
531
|
+
end
|
532
|
+
|
533
|
+
|
534
|
+
end
|
535
|
+
|
536
|
+
|
537
|
+
|
538
|
+
describe Benry::CLI::Action do
|
539
|
+
|
540
|
+
|
541
|
+
describe '.inherited()' do
|
542
|
+
|
543
|
+
it "[!al5pr] provides @action and @option for subclass." do
|
544
|
+
HelloAction.instance_exec(self) do |_|
|
545
|
+
_.ok {@action} != nil
|
546
|
+
_.ok {@action}.is_a?(Proc)
|
547
|
+
_.ok {@option} != nil
|
548
|
+
_.ok {@option}.is_a?(Proc)
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
it "[!ymtsg] allows block argument to @option." do
|
553
|
+
cls = Class.new(Benry::CLI::Action) do
|
554
|
+
@action.(:hello, "print hello")
|
555
|
+
@option.('-L, --level=N', 'level') {|val| val.to_i }
|
556
|
+
def hello(level: 1)
|
557
|
+
"level=#{level.inspect}"
|
558
|
+
end
|
559
|
+
end
|
560
|
+
cls.instance_exec(self) do |_|
|
561
|
+
arr = @__mappings[0]
|
562
|
+
_.ok {arr[0]} == :hello
|
563
|
+
_.ok {arr[1]} == "print hello"
|
564
|
+
_.ok {arr[2][1].short} == 'L'
|
565
|
+
_.ok {arr[2][1].long} == 'level'
|
566
|
+
_.ok {arr[2][1].callback}.is_a?(Proc)
|
567
|
+
_.ok {arr[2][1].callback.call("123")} == 123
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
it "[!v76cf] can take symbol as kwarg name." do
|
572
|
+
cls = Class.new(Benry::CLI::Action) do
|
573
|
+
@action.(:hello, "print hello")
|
574
|
+
@option.(:level, '-L N', 'level number') {|val| val.to_i }
|
575
|
+
def hello(level: 1)
|
576
|
+
"level=#{level.inspect}"
|
577
|
+
end
|
578
|
+
end
|
579
|
+
cls.instance_exec(self) do |_|
|
580
|
+
arr = @__mappings[0]
|
581
|
+
_.ok {arr[0]} == :hello
|
582
|
+
_.ok {arr[1]} == "print hello"
|
583
|
+
_.ok {arr[2][1].name} == 'level'
|
584
|
+
_.ok {arr[2][1].short} == 'L'
|
585
|
+
_.ok {arr[2][1].long} == nil
|
586
|
+
_.ok {arr[2][1].callback}.is_a?(Proc)
|
587
|
+
_.ok {arr[2][1].callback.call("123")} == 123
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
it "[!di9na] raises error when @option.() called without @action.()." do
|
592
|
+
pr = proc do
|
593
|
+
Class.new(Benry::CLI::Action) do
|
594
|
+
@option.('-v, --verbose', "verbose mode")
|
595
|
+
def hello(verbose)
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
ok {pr}.raise?(Benry::CLI::OptionDefinitionError,
|
600
|
+
'@option.("-v, --verbose"): @action.() should be called prior to @option.().')
|
601
|
+
end
|
602
|
+
|
603
|
+
it "[!4otr6] registers subclass." do
|
604
|
+
ok {Benry::CLI::Action::SUBCLASSES}.include?(HelloAction)
|
605
|
+
ok {Benry::CLI::Action::SUBCLASSES}.include?(HelloSubAction)
|
606
|
+
end
|
607
|
+
|
608
|
+
end
|
609
|
+
|
610
|
+
|
611
|
+
describe '.method_added()' do
|
612
|
+
|
613
|
+
it "[!syzvc] registers action with method." do
|
614
|
+
cls = Class.new(Benry::CLI::Action) do
|
615
|
+
@action.("hello", "print hello message")
|
616
|
+
@option.('-n, --name=NAME', "user name")
|
617
|
+
def do_hello(name: "World")
|
618
|
+
puts "Hello, #{name}!"
|
619
|
+
end
|
620
|
+
end
|
621
|
+
cls.instance_exec(self) do |_|
|
622
|
+
_.ok {@__mappings} == [
|
623
|
+
[
|
624
|
+
'hello',
|
625
|
+
'print hello message',
|
626
|
+
[Benry::CLI::OptionSchema.new('help', 'h', 'help', nil, nil, 'print help message'),
|
627
|
+
Benry::CLI::OptionSchema.new('name', 'n', 'name', 'NAME', :required, 'user name')],
|
628
|
+
:do_hello,
|
629
|
+
],
|
630
|
+
]
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
634
|
+
it "[!m7y8p] clears current action definition." do
|
635
|
+
_ = self
|
636
|
+
cls = Class.new(Benry::CLI::Action) do
|
637
|
+
_.ok {@__defining} == nil
|
638
|
+
@action.("hello", "print hello message")
|
639
|
+
@option.('-n, --name=NAME', "user name")
|
640
|
+
_.ok {@__defining} != nil
|
641
|
+
def do_hello
|
642
|
+
end
|
643
|
+
_.ok {@__defining} == nil
|
644
|
+
end
|
645
|
+
end
|
646
|
+
|
647
|
+
end
|
648
|
+
|
649
|
+
|
650
|
+
end
|
651
|
+
|
652
|
+
|
653
|
+
|
654
|
+
describe Benry::CLI::ActionInfo do
|
655
|
+
|
656
|
+
|
657
|
+
describe '#help_message()' do
|
658
|
+
|
659
|
+
def _new_info()
|
660
|
+
schemas = [
|
661
|
+
Benry::CLI::OptionSchema.parse("-v, --verbose", "verbose mode"),
|
662
|
+
Benry::CLI::OptionSchema.parse("-f, --file=NAME", "file name"),
|
663
|
+
Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "indent (default 2)"),
|
664
|
+
]
|
665
|
+
cls = Class.new(Benry::CLI::Action) do
|
666
|
+
def do_git_switch(aa, bb, cc=nil, dd=nil, *args, verbose: false, file: nil, indent: 2)
|
667
|
+
end
|
668
|
+
end
|
669
|
+
return Benry::CLI::ActionInfo.new('git:switch', 'switch', 'switch git branch',
|
670
|
+
schemas, cls, :do_git_switch)
|
671
|
+
end
|
672
|
+
|
673
|
+
it "[!hjq5l] builds help message." do
|
674
|
+
expected = <<END
|
675
|
+
switch git branch
|
676
|
+
|
677
|
+
Usage:
|
678
|
+
script-name git:switch [<options>] <aa> <bb> [<cc>] [<dd>] [<args>...]
|
679
|
+
|
680
|
+
Options:
|
681
|
+
-v, --verbose : verbose mode
|
682
|
+
-f, --file=NAME : file name
|
683
|
+
-i, --indent[=N] : indent (default 2)
|
684
|
+
END
|
685
|
+
info = _new_info()
|
686
|
+
ok {info.help_message('script-name')} == expected
|
687
|
+
end
|
688
|
+
|
689
|
+
it "[!7qmnz] replaces '_' in arg names with '-'." do
|
690
|
+
schemas = []
|
691
|
+
cls = Class.new(Benry::CLI::Action) do
|
692
|
+
def do_something(tmp_file_name, tmp_file_dir='/tmp')
|
693
|
+
end
|
694
|
+
end
|
695
|
+
action_info = Benry::CLI::ActionInfo.new('my:hom', 'hom', 'do something',
|
696
|
+
schemas, cls, :do_something)
|
697
|
+
s = action_info.help_message("script")
|
698
|
+
ok {s} =~ "Usage:\n script my:hom [<options>] <tmp-file-name> [<tmp-file-dir>]"
|
699
|
+
end
|
700
|
+
|
701
|
+
it "[!s6p09] converts arg name 'file_or_dir' into 'file|dir'." do
|
702
|
+
schemas = []
|
703
|
+
cls = Class.new(Benry::CLI::Action) do
|
704
|
+
def do_something(file_or_directory, name_or_id=nil)
|
705
|
+
end
|
706
|
+
end
|
707
|
+
action_info = Benry::CLI::ActionInfo.new('my:hom', 'hom', 'do something',
|
708
|
+
schemas, cls, :do_something)
|
709
|
+
s = action_info.help_message("script")
|
710
|
+
ok {s} =~ "Usage:\n script my:hom [<options>] <file|directory> [<name|id>]"
|
711
|
+
end
|
712
|
+
|
713
|
+
it "[!6m50d] don't show non-described options." do
|
714
|
+
schemas = [
|
715
|
+
Benry::CLI::OptionSchema.parse("-v, --verbose", "verbose mode"),
|
716
|
+
Benry::CLI::OptionSchema.parse("-f, --file=NAME", nil), # hidden option
|
717
|
+
Benry::CLI::OptionSchema.parse("-i, --indent[=N]", "indent (default 2)"),
|
718
|
+
]
|
719
|
+
cls = Class.new(Benry::CLI::Action) do
|
720
|
+
def do_something(verbose: false, file: nil, indent: nil)
|
721
|
+
end
|
722
|
+
end
|
723
|
+
action_info = Benry::CLI::ActionInfo.new('foo', 'foo', 'Do something',
|
724
|
+
schemas, cls, :do_something)
|
725
|
+
s = action_info.help_message("script")
|
726
|
+
ok {s} == <<END
|
727
|
+
Do something
|
728
|
+
|
729
|
+
Usage:
|
730
|
+
script foo [<options>]
|
731
|
+
|
732
|
+
Options:
|
733
|
+
-v, --verbose : verbose mode
|
734
|
+
-i, --indent[=N] : indent (default 2)
|
735
|
+
END
|
736
|
+
ok {s}.NOT =~ /--file/
|
737
|
+
end
|
738
|
+
|
739
|
+
end
|
740
|
+
|
741
|
+
|
742
|
+
end
|
743
|
+
|
744
|
+
|
745
|
+
describe Benry::CLI::Application do
|
746
|
+
|
747
|
+
|
748
|
+
describe '.inherited()' do
|
749
|
+
|
750
|
+
it "[!b09pv] provides @global_option in subclass." do
|
751
|
+
cls = Class.new(Benry::CLI::Application)
|
752
|
+
cls.instance_exec(self) do |_|
|
753
|
+
_.ok {@global_option} != nil
|
754
|
+
_.ok {@global_option}.is_a?(Proc)
|
755
|
+
end
|
756
|
+
end
|
757
|
+
|
758
|
+
it "[!8swia] global option '-h' and '--help' are enabled by default." do
|
759
|
+
cls = Class.new(Benry::CLI::Application)
|
760
|
+
cls.instance_exec(self) do |_|
|
761
|
+
_.ok {@_global_option_schemas[0].short} == 'h'
|
762
|
+
_.ok {@_global_option_schemas[0].long} == 'help'
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
it "[!vh08n] global option '--version' is enabled by defaut." do
|
767
|
+
cls = Class.new(Benry::CLI::Application)
|
768
|
+
cls.instance_exec(self) do |_|
|
769
|
+
_.ok {@_global_option_schemas[1].short} == nil
|
770
|
+
_.ok {@_global_option_schemas[1].long} == 'version'
|
771
|
+
end
|
772
|
+
end
|
773
|
+
|
774
|
+
end
|
775
|
+
|
776
|
+
|
777
|
+
describe '#accept()' do
|
778
|
+
|
779
|
+
it "[!ue26k] builds action dictionary." do
|
780
|
+
app = Benry::CLI::Application.new
|
781
|
+
d = app.__send__(:accept, [GitAction])
|
782
|
+
ok {d}.is_a?(Hash)
|
783
|
+
ok {d.keys().sort} == ['git:fork', 'git:join', 'git:switch']
|
784
|
+
ok {d['git:fork']} == Benry::CLI::ActionInfo.new(
|
785
|
+
'git:fork', 'fork', 'create and switch to new branch',
|
786
|
+
[Benry::CLI::OptionSchema.parse('-h, --help', 'print help message'),
|
787
|
+
Benry::CLI::OptionSchema.parse('-v, --verbose', 'verbose mode')],
|
788
|
+
GitAction, :do_git_fork
|
789
|
+
)
|
790
|
+
ok {d['git:switch']} == Benry::CLI::ActionInfo.new(
|
791
|
+
'git:switch', 'switch', 'switch git branch',
|
792
|
+
[Benry::CLI::OptionSchema.parse('-h, --help', 'print help message'),
|
793
|
+
Benry::CLI::OptionSchema.parse('-v, --verbose', 'verbose mode')],
|
794
|
+
GitAction, :do_git_switch
|
795
|
+
)
|
796
|
+
end
|
797
|
+
|
798
|
+
it "[!x6rh1] registers action name replacing '_' with '-'." do
|
799
|
+
cls = Class.new(Benry::CLI::Action) do
|
800
|
+
@action.(:bla_bla_bla, "bla bla bla")
|
801
|
+
def do_xx()
|
802
|
+
return "OK"
|
803
|
+
end
|
804
|
+
end
|
805
|
+
app = Benry::CLI::Application.new
|
806
|
+
d = app.__send__(:accept, [cls])
|
807
|
+
ok {d}.is_a?(Hash)
|
808
|
+
ok {d.keys().sort} == ['bla-bla-bla']
|
809
|
+
#
|
810
|
+
app = Benry::CLI::Application.new(nil, action_classes: [cls])
|
811
|
+
output1 = app.run('--help')
|
812
|
+
ok {output1} =~ /Actions:\n bla-bla-bla +: bla bla bla\n/
|
813
|
+
output2 = app.run('bla-bla-bla')
|
814
|
+
ok {output2} == "OK"
|
815
|
+
end
|
816
|
+
|
817
|
+
end
|
818
|
+
|
819
|
+
|
820
|
+
describe '#run()' do
|
821
|
+
|
822
|
+
def _argtest_action_class
|
823
|
+
return Class.new(Benry::CLI::Action) do
|
824
|
+
@action.(:hello1, "hello1")
|
825
|
+
@option.('-f, --file=NAME', 'filename')
|
826
|
+
@option.('-i, --indent[=N]', 'indent (default 2)')
|
827
|
+
def do_hello1(aa, bb, cc=nil, dd=nil, file: nil, indent: 2)
|
828
|
+
return ("aa=#{aa.inspect}, bb=#{bb.inspect}, cc=#{cc.inspect}, dd=#{dd.inspect}"+\
|
829
|
+
", file=#{file.inspect}, indent=#{indent.inspect}")
|
830
|
+
end
|
831
|
+
#
|
832
|
+
@action.(:hello2, "hello2")
|
833
|
+
@option.('-f, --file=NAME', 'filename')
|
834
|
+
@option.('-i, --indent[=N]', 'indent (default 2)')
|
835
|
+
def do_hello2(aa, bb, cc=nil, dd=nil, *args, file: nil, indent: 2)
|
836
|
+
return ("aa=#{aa.inspect}, bb=#{bb.inspect}, cc=#{cc.inspect}, dd=#{dd.inspect}"+\
|
837
|
+
", args=#{args.inspect}, file=#{file.inspect}, indent=#{indent.inspect}")
|
838
|
+
end
|
839
|
+
#
|
840
|
+
@action.(:hello3, "hello3")
|
841
|
+
@option.('-L, --debug-log-level=N', 'log level')
|
842
|
+
def do_hello3(debug_log_level: 1)
|
843
|
+
return "debug_log_level=#{debug_log_level.inspect}"
|
844
|
+
end
|
845
|
+
end
|
846
|
+
end
|
847
|
+
|
848
|
+
it "[!b8isy] returns help message when global option '-h' or '--help' is specified." do
|
849
|
+
expected = <<END
|
850
|
+
Usage:
|
851
|
+
cli_test.rb [<options>] <action> [<args>...]
|
852
|
+
|
853
|
+
Options:
|
854
|
+
-h, --help : print help message
|
855
|
+
--version : print version
|
856
|
+
|
857
|
+
Actions:
|
858
|
+
git:fork : create and switch to new branch
|
859
|
+
git:join : merge branch with --no-ff
|
860
|
+
git:switch : switch git branch
|
861
|
+
|
862
|
+
(Run `cli_test.rb help <action>' to show help message of each action.)
|
863
|
+
END
|
864
|
+
app = Benry::CLI::Application.new(action_classes: [GitAction])
|
865
|
+
output = app.run('--help')
|
866
|
+
ok {output} == expected
|
867
|
+
output = app.run('-h')
|
868
|
+
ok {output} == expected
|
869
|
+
end
|
870
|
+
|
871
|
+
it "[!4irzw] returns version string when global option '--version' is specified." do
|
872
|
+
app = Benry::CLI::Application.new(action_classes: [GitAction])
|
873
|
+
output = app.run('--version')
|
874
|
+
ok {output} == "0.0"
|
875
|
+
#
|
876
|
+
app = Benry::CLI::Application.new(version: '1.2.3', action_classes: [GitAction])
|
877
|
+
output = app.run('--version')
|
878
|
+
ok {output} == "1.2.3"
|
879
|
+
end
|
880
|
+
|
881
|
+
it "[!p5pr6] returns global help message when action is 'help'." do
|
882
|
+
expected = <<END
|
883
|
+
Usage:
|
884
|
+
cli_test.rb [<options>] <action> [<args>...]
|
885
|
+
|
886
|
+
Options:
|
887
|
+
-h, --help : print help message
|
888
|
+
--version : print version
|
889
|
+
|
890
|
+
Actions:
|
891
|
+
git:fork : create and switch to new branch
|
892
|
+
git:join : merge branch with --no-ff
|
893
|
+
git:switch : switch git branch
|
894
|
+
|
895
|
+
(Run `cli_test.rb help <action>' to show help message of each action.)
|
896
|
+
END
|
897
|
+
app = Benry::CLI::Application.new(action_classes: [GitAction])
|
898
|
+
output = app.run('help')
|
899
|
+
ok {output} == expected
|
900
|
+
end
|
901
|
+
|
902
|
+
it "[!3hyvi] returns help message of action when action is 'help' with action name." do
|
903
|
+
expected = <<END
|
904
|
+
create and switch to new branch
|
905
|
+
|
906
|
+
Usage:
|
907
|
+
cli_test.rb git:fork [<options>] <branch>
|
908
|
+
|
909
|
+
Options:
|
910
|
+
-h, --help : print help message
|
911
|
+
-v, --verbose : verbose mode
|
912
|
+
END
|
913
|
+
app = Benry::CLI::Application.new(action_classes: [GitAction])
|
914
|
+
output = app.run('help', 'git:fork')
|
915
|
+
ok {output} == expected
|
916
|
+
end
|
917
|
+
|
918
|
+
it "[!mb92l] raises error when action name is unknown." do
|
919
|
+
app = Benry::CLI::Application.new(action_classes: [GitAction])
|
920
|
+
pr = proc { app.run('fork') }
|
921
|
+
ok {pr}.raise?(Benry::CLI::OptionError, "fork: unknown action.")
|
922
|
+
end
|
923
|
+
|
924
|
+
it "[!13m3q] returns help message if '-h' or '--help' specified to action." do
|
925
|
+
expected = <<END
|
926
|
+
create and switch to new branch
|
927
|
+
|
928
|
+
Usage:
|
929
|
+
cli_test.rb git:fork [<options>] <branch>
|
930
|
+
|
931
|
+
Options:
|
932
|
+
-h, --help : print help message
|
933
|
+
-v, --verbose : verbose mode
|
934
|
+
END
|
935
|
+
app = Benry::CLI::Application.new(action_classes: [GitAction])
|
936
|
+
output = app.run('git:fork', '--help')
|
937
|
+
ok {output} == expected
|
938
|
+
end
|
939
|
+
|
940
|
+
it "[!yhry7] raises error when required argument is missing." do
|
941
|
+
cls = _argtest_action_class()
|
942
|
+
app = Benry::CLI::Application.new(action_classes: [cls])
|
943
|
+
pr = proc { app.run('hello1') }
|
944
|
+
ok {pr}.raise?(Benry::CLI::OptionError,
|
945
|
+
"too few arguments (at least 2 args expected).\n" +\
|
946
|
+
"(run `cli_test.rb help hello1' for details.)")
|
947
|
+
pr = proc { app.run('hello1', "x") }
|
948
|
+
ok {pr}.raise?(Benry::CLI::OptionError,
|
949
|
+
"too few arguments (at least 2 args expected).\n" +\
|
950
|
+
"(run `cli_test.rb help hello1' for details.)")
|
951
|
+
pr = proc { app.run('hello1', "x", "y") }
|
952
|
+
ok {pr}.NOT.raise?(Exception)
|
953
|
+
end
|
954
|
+
|
955
|
+
it "[!h5522] raises error when too much arguments specified." do
|
956
|
+
cls = _argtest_action_class()
|
957
|
+
app = Benry::CLI::Application.new(action_classes: [cls])
|
958
|
+
pr = proc { app.run('hello1', "x1", "x2", "x3", "x4", "x5") }
|
959
|
+
ok {pr}.raise?(Benry::CLI::OptionError,
|
960
|
+
"too many arguments (at most 4 args expected).\n" +\
|
961
|
+
"(run `cli_test.rb help hello1' for details.)")
|
962
|
+
end
|
963
|
+
|
964
|
+
it "[!hq8b0] not raise error when many argument specified but method has *args." do
|
965
|
+
cls = _argtest_action_class()
|
966
|
+
app = Benry::CLI::Application.new(action_classes: [cls])
|
967
|
+
pr = proc { app.run('hello2', "x1", "x2", "x3", "x4", "x5", "x6") }
|
968
|
+
ok {pr}.NOT.raise?(Exception)
|
969
|
+
end
|
970
|
+
|
971
|
+
it "[!qwd9x] passes command arguments and options as method arguments and options." do
|
972
|
+
cls = _argtest_action_class()
|
973
|
+
app = Benry::CLI::Application.new(action_classes: [cls])
|
974
|
+
#
|
975
|
+
output = app.run('hello1', "-ffoo.txt", "x1", "x2")
|
976
|
+
ok {output} == 'aa="x1", bb="x2", cc=nil, dd=nil, file="foo.txt", indent=2'
|
977
|
+
output = app.run('hello1', "-i", "x1", "x2", "x3")
|
978
|
+
ok {output} == 'aa="x1", bb="x2", cc="x3", dd=nil, file=nil, indent=true'
|
979
|
+
#
|
980
|
+
output = app.run('hello2', "-ffoo.txt", "x1", "x2", "x3", "x4", "x5", "x6")
|
981
|
+
ok {output} == 'aa="x1", bb="x2", cc="x3", dd="x4", args=["x5", "x6"], file="foo.txt", indent=2'
|
982
|
+
end
|
983
|
+
|
984
|
+
it "[!rph9y] converts 'foo-bar' option name into :foo_bar keyword." do
|
985
|
+
cls = _argtest_action_class()
|
986
|
+
app = Benry::CLI::Application.new(action_classes: [cls])
|
987
|
+
pr = proc { app.run('hello3', "-L30") }
|
988
|
+
ok {pr}.NOT.raise?(Exception)
|
989
|
+
output = pr.call()
|
990
|
+
ok {output} == 'debug_log_level="30"'
|
991
|
+
end
|
992
|
+
|
993
|
+
end
|
994
|
+
|
995
|
+
|
996
|
+
describe '#help_message()' do
|
997
|
+
|
998
|
+
it "[!1zpv4] adds command desc if it is specified at initializer." do
|
999
|
+
app = Benry::CLI::Application.new("my git wrapper", action_classes: [GitAction])
|
1000
|
+
s = app.help_message('mygit')
|
1001
|
+
ok {s} =~ /\Amy git wrapper\n\nUsage:/
|
1002
|
+
#
|
1003
|
+
app = Benry::CLI::Application.new(action_classes: [GitAction])
|
1004
|
+
s = app.help_message('mygit')
|
1005
|
+
ok {s} =~ /\AUsage:/
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
it "[!m3mry] skips action name when description is not provided." do
|
1009
|
+
cls = Class.new(Benry::CLI::Action) do
|
1010
|
+
@action.(:test1, nil)
|
1011
|
+
def do_test1; end
|
1012
|
+
@action.(:test2, "")
|
1013
|
+
def do_test2; end
|
1014
|
+
end
|
1015
|
+
app = Benry::CLI::Application.new(action_classes: [cls])
|
1016
|
+
s = app.help_message('script')
|
1017
|
+
ok {s} !~ /test1/
|
1018
|
+
ok {s} =~ /test2/
|
1019
|
+
ok {s} =~ /^Actions:\n test2 +: +\n/
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
|
1025
|
+
end
|