benry-cmdopt 2.2.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/test/cmdopt_test.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'oktest'
4
5
 
@@ -8,1344 +9,6 @@ require 'benry/cmdopt'
8
9
  Oktest.scope do
9
10
 
10
11
 
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
25
- end
26
-
27
-
28
-
29
- topic Benry::CmdOpt::Schema do
30
-
31
-
32
- topic '#parse()' do
33
-
34
- before do
35
- @schema = Benry::CmdOpt::Schema.new
36
- end
37
-
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
47
-
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
76
-
77
- end
78
-
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
-
106
- end
107
-
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
137
-
138
- end
139
-
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
254
-
255
-
256
- end
257
-
258
-
259
- topic '#add_item()' do
260
-
261
- spec "[!a693h] adds option item into current schema." do
262
- item = Benry::CmdOpt::SchemaItem.new(:quiet, "-q", "quiet", "q", nil, nil, false)
263
- sc = Benry::CmdOpt::Schema.new
264
- sc.add_item(item)
265
- ok {sc.to_s} == <<"END"
266
- -q : quiet
267
- END
268
- end
269
-
270
- end
271
-
272
- topic '#option_help()' do
273
-
274
- before do
275
- sc = Benry::CmdOpt::Schema.new
276
- sc.add(:help , "-h, --help" , "show help message.")
277
- sc.add(:version, " --version" , "print version")
278
- sc.add(:file , "-f, --file=<FILE>" , "filename")
279
- sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
280
- sc.add(:debug , "-d, --debug" , nil)
281
- @schema = sc
282
- end
283
-
284
- spec "[!0aq0i] can take integer as width." do
285
- helpmsg = @schema.option_help(41)
286
- ok {helpmsg} == <<END
287
- -h, --help : show help message.
288
- --version : print version
289
- -f, --file=<FILE> : filename
290
- -i, --indent[=<WIDTH>] : enable indent
291
- END
292
- s = helpmsg.each_line.first.split(':')[0]
293
- ok {s.length} == 41+3
294
- end
295
-
296
- spec "[!pcsah] can take format string." do
297
- helpmsg = @schema.option_help("%-42s: %s")
298
- ok {helpmsg} == <<END
299
- -h, --help : show help message.
300
- --version : print version
301
- -f, --file=<FILE> : filename
302
- -i, --indent[=<WIDTH>] : enable indent
303
- END
304
- s = helpmsg.each_line.first.split(':')[0]
305
- ok {s.length} == 42+0
306
- end
307
-
308
- spec "[!dndpd] detects option width automatically when nothing specified." do
309
- helpmsg = @schema.option_help()
310
- ok {helpmsg} == <<END
311
- -h, --help : show help message.
312
- --version : print version
313
- -f, --file=<FILE> : filename
314
- -i, --indent[=<WIDTH>] : enable indent
315
- END
316
- s = helpmsg.each_line.to_a.last.split(':')[0]
317
- ok {s.length} == 25
318
- end
319
-
320
- spec "[!v7z4x] skips option help if help message is not specified." do
321
- helpmsg = @schema.option_help()
322
- ok {helpmsg} !~ /debug/
323
- end
324
-
325
- spec "[!to1th] includes all option help when `all` is true." do
326
- helpmsg = @schema.option_help(nil, all: true)
327
- ok {helpmsg} =~ /debug/
328
- ok {helpmsg} == <<END
329
- -h, --help : show help message.
330
- --version : print version
331
- -f, --file=<FILE> : filename
332
- -i, --indent[=<WIDTH>] : enable indent
333
- -d, --debug :
334
- END
335
- end
336
-
337
- spec "[!848rm] supports multi-lines help message." do
338
- sc = Benry::CmdOpt::Schema.new
339
- sc.add(:mode, "-m, --mode=<MODE>", "output mode",
340
- detail: <<"END")
341
- v, verbose: print many output
342
- q, quiet: print litte output
343
- c, compact: print summary output
344
- END
345
- actual = sc.option_help()
346
- expected = <<END
347
- -m, --mode=<MODE> : output mode
348
- v, verbose: print many output
349
- q, quiet: print litte output
350
- c, compact: print summary output
351
- END
352
- ok {actual} == expected
353
- end
354
-
355
- spec "[!a4qe4] option should not be hidden if description is empty string." do
356
- sc = Benry::CmdOpt::Schema.new
357
- sc.add(:debug , "-D", nil) # hidden
358
- sc.add(:trace, "-T", "trace", hidden: true) # hidden
359
- sc.add(:what , "-W", "") # NOT hidden!
360
- ok {sc.option_help()} == <<END
361
- -W :
362
- END
363
- end
364
-
365
- fixture :schema_with_importance do
366
- sc = Benry::CmdOpt::Schema.new
367
- sc.add(:help , "-h, --help" , "help message")
368
- sc.add(:trace , "-T, --trace", "trace" , important: true)
369
- sc.add(:debug , "-D, --debug", "debug mode" , important: false)
370
- sc.add(:quiet , "-q, --quiet", "quiet mode")
371
- sc
372
- end
373
-
374
- spec "[!jrwb6] decorates help message according to `important:` value of option." do
375
- |schema_with_importance|
376
- sc = schema_with_importance
377
- ok {sc.option_help()} == <<END
378
- -h, --help : help message
379
- \e[1m -T, --trace : trace\e[0m
380
- \e[2m -D, --debug : debug mode\e[0m
381
- -q, --quiet : quiet mode
382
- END
383
- end
384
-
385
- spec "[!9nlfb] not decorate help message when stdout is not a tty." do
386
- |schema_with_importance|
387
- sc = schema_with_importance
388
- output = nil
389
- capture_sio() {
390
- ok {$stdout}.NOT.tty?
391
- output = sc.option_help()
392
- }
393
- ok {output} == <<END
394
- -h, --help : help message
395
- -T, --trace : trace
396
- -D, --debug : debug mode
397
- -q, --quiet : quiet mode
398
- END
399
- end
400
-
401
- end
402
-
403
-
404
- topic '#_default_format()' do
405
-
406
- before do
407
- sc = Benry::CmdOpt::Schema.new
408
- sc.add(:help , "-h, --help" , "show help message.")
409
- sc.add(:version, " --version" , "print version")
410
- sc.add(:file , "-f, --file=<FILE>" , "filename")
411
- sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
412
- sc.add(:debug , "-d, --debug" , nil)
413
- @schema = sc
414
- end
415
-
416
- spec "[!kkh9t] returns format string." do
417
- ret = @schema.__send__(:_default_format)
418
- ok {ret} == " %-22s : %s"
419
- end
420
-
421
- spec "[!hr45y] detects preffered option width." do
422
- ret = @schema.__send__(:_default_format, 10, 20)
423
- ok {ret} == " %-20s : %s"
424
- ret = @schema.__send__(:_default_format, 30, 40)
425
- ok {ret} == " %-30s : %s"
426
- ret = @schema.__send__(:_default_format, 10, 40)
427
- ok {ret} == " %-22s : %s"
428
- end
429
-
430
- spec "[!bmr7d] changes min_with according to options." do
431
- sc = Benry::CmdOpt::Schema.new
432
- sc.add(:help , '-h', "help")
433
- sc.add(:version, '-v', "version")
434
- ok {sc.__send__(:_default_format, nil, 40)} == " %-8s : %s"
435
- #
436
- sc.add(:file , '-f <FILE>', "filename")
437
- ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
438
- #
439
- sc.add(:force , '--force', "forcedly")
440
- ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
441
- #
442
- sc.add(:mode , '-m, --mode=<MODE>', "verbose/quiet")
443
- ok {sc.__send__(:_default_format, nil, 40)} == " %-20s : %s"
444
- end
445
-
446
- end
447
-
448
-
449
- topic '#_preferred_option_width()' do
450
-
451
- spec "[!kl91t] shorten option help min width when only single options which take no arg." do
452
- sc = Benry::CmdOpt::Schema.new
453
- sc.add(:help , '-h', "help")
454
- sc.add(:version, '-v', "version")
455
- ok {sc.__send__(:_preferred_option_width)} == 8
456
- end
457
-
458
- spec "[!0koqb] widen option help min width when any option takes an arg." do
459
- sc = Benry::CmdOpt::Schema.new
460
- sc.add(:help , '-h', "help")
461
- sc.add(:indent , '-i[<N>]', "indent")
462
- ok {sc.__send__(:_preferred_option_width)} == 14
463
- end
464
-
465
- spec "[!kl91t] widen option help min width when long option exists." do
466
- sc = Benry::CmdOpt::Schema.new
467
- sc.add(:help , '-h', "help")
468
- sc.add(:version, '-v, --version', "version")
469
- ok {sc.__send__(:_preferred_option_width)} == 14
470
- #
471
- sc.add(:file, '--file=<FILE>', "filename")
472
- ok {sc.__send__(:_preferred_option_width)} == 20
473
- end
474
-
475
- end
476
-
477
-
478
- topic '#to_s()' do
479
-
480
- spec "[!rrapd] '#to_s' is an alias to '#option_help()'." do
481
- schema = Benry::CmdOpt::Schema.new
482
- schema.add(:help , "-h, --help" , "show help message")
483
- schema.add(:version, " --version" , "print version")
484
- ok {schema.to_s} == schema.option_help()
485
- end
486
-
487
- end
488
-
489
-
490
- topic '#each_option_and_desc()' do
491
-
492
- before do
493
- sc = Benry::CmdOpt::Schema.new
494
- sc.add(:help, "-h, --help", "show help message")
495
- sc.add(:version, " --version", "print version")
496
- sc.add(:debug , "-d, --debug" , nil) # hidden
497
- sc.add(:DEBUG , "-D, --DEBUG" , "debug mode", hidden: true) # hidden
498
- @schema = sc
499
- end
500
-
501
- spec "[!4b911] yields each optin definition str and help message." do
502
- pairs = []
503
- @schema.each_option_and_desc {|opt, desc| pairs << [opt, desc] }
504
- ok {pairs} == [
505
- ["-h, --help" , "show help message"], # not hiddden
506
- [" --version" , "print version"], # not hidden
507
- ]
508
- end
509
-
510
- spec "[!cl8zy] when 'all' flag is false, not yield hidden items." do
511
- pairs = []
512
- @schema.each_option_and_desc(all: false) {|opt, desc| pairs << [opt, desc] }
513
- ok {pairs} == [
514
- ["-h, --help" , "show help message"], # not hiddden
515
- [" --version" , "print version"], # not hidden
516
- ]
517
- end
518
-
519
- spec "[!tc4bk] when 'all' flag is true, yields even hidden items." do
520
- pairs = []
521
- @schema.each_option_and_desc(all: true) {|opt, desc| pairs << [opt, desc] }
522
- ok {pairs} == [
523
- ["-h, --help" , "show help message"], # not hiddden
524
- [" --version" , "print version"], # not hidden
525
- ["-d, --debug" , nil], # hidden
526
- ["-D, --DEBUG" , "debug mode"], # hidden
527
- ]
528
- end
529
-
530
- spec "[!03sux] returns enumerator object if block not given." do
531
- ## when 'all: true'
532
- xs = @schema.each_option_and_desc(all: true)
533
- ok {xs}.is_a?(Enumerator)
534
- ok {xs.collect {|x, _| x }} == ["-h, --help", " --version", "-d, --debug", "-D, --DEBUG"]
535
- ## when 'all: false'
536
- xs = @schema.each_option_and_desc(all: false)
537
- ok {xs}.is_a?(Enumerator)
538
- ok {xs.collect {|x, _| x }} == ["-h, --help", " --version"]
539
- end
540
-
541
- spec "[!zbxyv] returns self." do
542
- ret = @schema.each_option_and_desc { nil }
543
- ok {ret}.same? @schema
544
- end
545
-
546
- end
547
-
548
-
549
- topic '#each()' do
550
-
551
- before do
552
- @schema = Benry::CmdOpt::Schema.new
553
- @schema.add(:help , "-h, --help" , "help message")
554
- @schema.add(:version, " --version", "print version")
555
- end
556
-
557
- spec "[!y4k1c] yields each option item." do
558
- items = []
559
- @schema.each {|x| items << x }
560
- ok {items.length} == 2
561
- ok {items[0]}.is_a?(Benry::CmdOpt::SchemaItem)
562
- ok {items[1]}.is_a?(Benry::CmdOpt::SchemaItem)
563
- ok {items[0].key} == :help
564
- ok {items[1].key} == :version
565
- keys = @schema.each.collect {|x| x.key }
566
- ok {keys} == [:help, :version]
567
- end
568
-
569
- end
570
-
571
-
572
- topic '#empty?()' do
573
-
574
- spec "[!um8am] returns false if any item exists, else returns true." do
575
- schema = Benry::CmdOpt::Schema.new
576
- ok {schema.empty?()} == true
577
- schema.add(:help , "-h, --help" , "help message")
578
- ok {schema.empty?()} == false
579
- end
580
-
581
- spec "[!icvm1] ignores hidden items if 'all: false' kwarg specified." do
582
- schema = Benry::CmdOpt::Schema.new
583
- schema.add(:debug , "-D", nil)
584
- schema.add(:trace, "-T", "trace", hidden: true)
585
- ok {schema.empty?()} == false
586
- ok {schema.empty?(all: true)} == false
587
- ok {schema.empty?(all: false)} == true
588
- end
589
-
590
- end
591
-
592
-
593
- topic '#get()' do
594
-
595
- before do
596
- @schema = Benry::CmdOpt::Schema.new
597
- @schema.add(:help , "-h, --help" , "help message")
598
- @schema.add(:version, " --version", "print version")
599
- end
600
-
601
- spec "[!3wjfp] finds option item object by key." do
602
- item = @schema.get(:help)
603
- ok {item.key} == :help
604
- item = @schema.get(:version)
605
- ok {item.key} == :version
606
- end
607
-
608
- spec "[!0spll] returns nil if key not found." do
609
- ok {@schema.get(:debug)} == nil
610
- end
611
-
612
- end
613
-
614
-
615
- topic '#delete()' do
616
-
617
- before do
618
- @schema = Benry::CmdOpt::Schema.new
619
- @schema.add(:help , "-h, --help" , "help message")
620
- @schema.add(:version, " --version", "print version")
621
- end
622
-
623
- spec "[!l86rb] deletes option item corresponding to key." do
624
- keys = @schema.each.collect {|x| x.key }
625
- ok {keys} == [:help, :version]
626
- @schema.delete(:help)
627
- keys = @schema.each.collect {|x| x.key }
628
- ok {keys} == [:version]
629
- end
630
-
631
- spec "[!rq0aa] returns deleted item." do
632
- item = @schema.delete(:version)
633
- ok {item} != nil
634
- ok {item.key} == :version
635
- end
636
-
637
- end
638
-
639
-
640
- topic '#find_short_option()' do
641
-
642
- before do
643
- @schema = new_sample_schema()
644
- end
645
-
646
- spec "[!b4js1] returns option definition matched to short name." do
647
- x = @schema.find_short_option('h')
648
- ok {x.key} == :help
649
- x = @schema.find_short_option('f')
650
- ok {x.key} == :file
651
- x = @schema.find_short_option('i')
652
- ok {x.key} == :indent
653
- end
654
-
655
- spec "[!s4d1y] returns nil when nothing found." do
656
- ok {@schema.find_short_option('v')} == nil
657
- end
658
-
659
- end
660
-
661
-
662
- topic '#find_long_option()' do
663
-
664
- before do
665
- @schema = new_sample_schema()
666
- end
667
-
668
- spec "[!atmf9] returns option definition matched to long name." do
669
- x = @schema.find_long_option('help')
670
- ok {x.key} == :help
671
- x = @schema.find_long_option('file')
672
- ok {x.key} == :file
673
- x = @schema.find_long_option('indent')
674
- ok {x.key} == :indent
675
- end
676
-
677
- spec "[!6haoo] returns nil when nothing found." do
678
- ok {@schema.find_long_option('lib')} == nil
679
- end
680
-
681
- end
682
-
683
-
684
- end
685
-
686
-
687
-
688
- topic Benry::CmdOpt::SchemaItem do
689
-
690
- ITEMS = [
691
- Benry::CmdOpt::SchemaItem.new(:help, "-h, --help", "help msg",
692
- "h", "help", nil, nil),
693
- Benry::CmdOpt::SchemaItem.new(:file, "-f, --file=<file>", "filename",
694
- "f", "file", "<file>", true),
695
- Benry::CmdOpt::SchemaItem.new(:indent, "-i, --indent[=<N>]", "indent width",
696
- "i", "indent", "<N>", false),
697
- ]
698
-
699
-
700
- topic '#initialize()' do
701
-
702
- before do
703
- @schema = Benry::CmdOpt::Schema.new
704
- end
705
-
706
- spec "[!nn4cp] freezes enum object." do
707
- item = Benry::CmdOpt::SchemaItem.new(:foo, "--foo", "desc", nil, "foo", "<val>",
708
- true, enum: ["x", "y", "z"])
709
- ok {item.enum} == ["x", "y", "z"]
710
- ok {item.enum}.frozen?
711
- end
712
-
713
- case_when "[!wy2iv] when 'type:' specified..." do
714
-
715
- spec "[!7xmr5] raises SchemaError when type is not registered." do
716
- sc = @schema
717
- pr = proc {
718
- sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width", type: Array)
719
- }
720
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
721
- "Array: Unregistered type.")
722
- end
723
-
724
- spec "[!s2aaj] raises SchemaError when option has no params but type specified." do
725
- sc = @schema
726
- pr = proc {
727
- sc.add(:indent, "-i, --indent", "indent width", type: Integer)
728
- }
729
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
730
- "Integer: Type specified in spite of option has no params.")
731
- end
732
-
733
- spec "[!sz8x2] not raise error when no params but value specified." do
734
- sc = @schema
735
- pr = proc {
736
- sc.add(:indent, "-i, --indent", "indent width", type: Integer, value: 0)
737
- }
738
- ok {pr}.NOT.raise?(Exception)
739
- end
740
-
741
- spec "[!70ogf] not raise error when no params but TrueClass specified." do
742
- sc = @schema
743
- pr = proc {
744
- sc.add(:indent, "-i, --indent", "indent width", type: TrueClass)
745
- }
746
- ok {pr}.NOT.raise?(Exception)
747
- end
748
-
749
- end
750
-
751
- case_when "[!6y8s2] when 'rexp:' specified..." do
752
-
753
- spec "[!bi2fh] raises SchemaError when pattern is not a regexp." do
754
- sc = @schema
755
- pr = proc {
756
- sc.add(:indent, "-x, --indent[=<WIDTH>]", "indent width", rexp: '\A\d+\z')
757
- }
758
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
759
- '"\\\\A\\\\d+\\\\z": Regexp pattern expected.')
760
- end
761
-
762
- spec "[!01fmt] raises SchmeaError when option has no params but pattern specified." do
763
- sc = @schema
764
- pr = proc {
765
- sc.add(:indent, "-i, --indent", "indent width", rexp: /\A\d+\z/)
766
- }
767
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
768
- '/\A\d+\z/: Regexp pattern specified in spite of option has no params.')
769
- end
770
-
771
- end
772
-
773
- case_when "[!5nrvq] when 'enum:' specified..." do
774
-
775
- spec "[!melyd] raises SchemaError when enum is not an Array nor Set." do
776
- sc = @schema
777
- sc.add(:indent, "-i <N>", "indent width", enum: ["2", "4", "8"])
778
- sc.add(:indent, "-i <N>", "indent width", enum: Set.new(["2", "4", "8"]))
779
- pr = proc {
780
- sc.add(:indent, "-i <N>", "indent width", enum: "2,4,8")
781
- }
782
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
783
- '"2,4,8": Array or set expected.')
784
- end
785
-
786
- spec "[!xqed8] raises SchemaError when enum specified for no param option." do
787
- sc = @schema
788
- pr = proc {
789
- sc.add(:indent, "-i", "enable indent", enum: [2, 4, 8])
790
- }
791
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
792
- "[2, 4, 8]: Enum specified in spite of option has no params.")
793
- end
794
-
795
- spec "[!zuthh] raises SchemaError when enum element value is not instance of type class." do
796
- sc = @schema
797
- pr = proc {
798
- sc.add(:indent, "-i <N>", "enable indent", type: Integer, enum: ['2', '4', '8'])
799
- }
800
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
801
- '["2", "4", "8"]: Enum element value should be instance of Integer, but "2" is not.')
802
- end
803
-
804
- end
805
-
806
- case_when "[!hk4nw] when 'range:' specified..." do
807
-
808
- spec "[!z20ky] raises SchemaError when range is not a Range object." do
809
- pr = proc {
810
- @schema.add(:indent, "-i <N>", "indent", type: Integer, range: [1,8])
811
- }
812
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
813
- "[1, 8]: Range object expected.")
814
- end
815
-
816
- spec "[!gp025] raises SchemaError when range specified with `type: TrueClass`." do
817
- pr = proc {
818
- @schema.add(:indent, "-i <N>", "indent", type: TrueClass, range: 0..1)
819
- }
820
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
821
- "0..1: Range is not available with `type: TrueClass`.")
822
- end
823
-
824
- spec "[!7njd5] range beginning/end value should be expected type." do
825
- pr = proc {
826
- @schema.add(:indent, "-i <N>", "indent", range: (1..8))
827
- }
828
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
829
- "1..8: Range value should be String, but not.")
830
- pr = proc {
831
- @schema.add(:indent, "-i <N>", "indent", type: Date, range: (1..8))
832
- }
833
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
834
- "1..8: Range value should be Date, but not.")
835
- end
836
-
837
- spec "[!uymig] range object can be endless." do
838
- begin
839
- range1 = eval "(1..)" # Ruby >= 2.6
840
- range2 = eval "(..3)" # Ruby >= 2.6
841
- rescue SyntaxError
842
- range1 = nil # Ruby < 2.6
843
- range2 = nil # Ruby < 2.6
844
- end
845
- if range1
846
- pr = proc {
847
- @schema.add(:indent1, "-i <N>", "indent", type: Integer, range: range1)
848
- @schema.add(:indent2, "-j <N>", "indent", type: Integer, range: range2)
849
- }
850
- pr.call
851
- ok {pr}.NOT.raise?(Exception)
852
- end
853
- end
854
-
855
- end
856
-
857
- case_when "[!a0g52] when 'value:' specified..." do
858
-
859
- spec "[!435t6] raises SchemaError when 'value:' is specified on argument-required option." do
860
- sc = @schema
861
- pr = proc {
862
- sc.add(:flag, "--flag=<on|off>", "flag", type: TrueClass, value: true)
863
- }
864
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
865
- "true: 'value:' is meaningless when option has required argument (hint: change to optional argument instead).")
866
- end
867
-
868
- spec "[!6vwqv] raises SchemaError when type is TrueClass but value is not true nor false." do
869
- sc = @schema
870
- pr = proc {
871
- sc.add(:flag, "--flag[=<on|off>]", "flag", type: TrueClass, value: 0)
872
- }
873
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
874
- "0: Value should be true or false when `type: TrueClass` specified.")
875
- end
876
-
877
- spec "[!c6i2o] raises SchemaError when value is not a kind of type." do
878
- sc = @schema
879
- pr = proc {
880
- sc.add(:flag, "--flag[=<on|off>]", "flag", type: Integer, value: false)
881
- }
882
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
883
- "Type mismatched between `type: Integer` and `value: false`.")
884
- end
885
-
886
- spec "[!lnhp6] not raise error when type is not specified." do
887
- sc = @schema
888
- pr = proc {
889
- sc.add(:flag, "--flag[=<on|off>]", "flag", value: false)
890
- }
891
- ok {pr}.NOT.raise?(Exception)
892
- end
893
-
894
- spec "[!6xb8o] value should be included in enum values." do
895
- sc = @schema
896
- pr = proc {
897
- sc.add(:lang, "--lang[=<en|fr|it>]", "language", enum: ["en", "fr", "it"], value: "ja")
898
- }
899
- ok {pr}.raise?(Benry::CmdOpt::SchemaError,
900
- "ja: Value should be included in enum values, but not.")
901
- end
902
-
903
- end
904
-
905
- end
906
-
907
-
908
- topic '#required?' do
909
-
910
- spec "[!svxny] returns nil if option takes no arguments." do
911
- item, _, _ = ITEMS
912
- ok {item.required?} == nil
913
- end
914
-
915
- spec "[!togcx] returns true if argument is required." do
916
- _, item, _ = ITEMS
917
- ok {item.required?} == true
918
- end
919
-
920
- spec "[!uwbgc] returns false if argument is optional." do
921
- _, _, item = ITEMS
922
- ok {item.required?} == false
923
- end
924
-
925
- end
926
-
927
-
928
- topic '#arg_requireness()' do
929
-
930
- spec "[!kmo28] returns :none if option takes no arguments." do
931
- item, _, _ = ITEMS
932
- ok {item.arg_requireness()} == :none
933
- end
934
-
935
- spec "[!s8gxl] returns :required if argument is required." do
936
- _, item, _ = ITEMS
937
- ok {item.arg_requireness()} == :required
938
- end
939
-
940
- spec "[!owpba] returns :optional if argument is optional." do
941
- _, _, item = ITEMS
942
- ok {item.arg_requireness()} == :optional
943
- end
944
-
945
- end
946
-
947
-
948
- topic '#hidden?()' do
949
-
950
- spec "[!no6ov] returns true if @hidden is true." do
951
- item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, hidden: true)
952
- ok {item.hidden?} == true
953
- end
954
-
955
- spec "[!ej8ot] returns false if @hidden is false." do
956
- item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, hidden: false)
957
- ok {item.hidden?} == false
958
- end
959
-
960
- spec "[!h0uxs] returns true if desc is nil." do
961
- desc = nil
962
- item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", desc, "D", nil, nil, nil)
963
- ok {item.hidden?} == true
964
- end
965
-
966
- spec "[!28vzx] returns false if else." do
967
- desc = "debug mode"
968
- item = Benry::CmdOpt::SchemaItem.new(:debug, "-D", desc, "D", nil, nil, nil)
969
- ok {item.hidden?} == false
970
- end
971
-
972
- end
973
-
974
-
975
- topic '#important?()' do
976
-
977
- spec "[!ua8kt] returns true/false if `important:` kwarg passed to constructor." do
978
- item1 = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, important: true)
979
- ok {item1.important?} == true
980
- item2 = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil, important: false)
981
- ok {item2.important?} == false
982
- end
983
-
984
- spec "[!hz9sx] returns nil if `important:` kwarg not passed to constructor." do
985
- item3 = Benry::CmdOpt::SchemaItem.new(:debug, "-D", "debug mode", "D", nil, nil, nil)
986
- ok {item3.important?} == nil
987
- end
988
-
989
- end
990
-
991
-
992
- topic '#validate_and_convert()' do
993
-
994
- def new_item(key, optstr, desc, short, long, param, required,
995
- type: nil, rexp: nil, enum: nil, range: nil, value: nil, &callback)
996
- return Benry::CmdOpt::SchemaItem.new(key, optstr, desc, short, long, param, required,
997
- type: type, rexp: rexp, enum: enum, range: range, value: value, &callback)
998
- end
999
-
1000
- spec "[!h0s0o] raises RuntimeError when value not matched to pattern." do
1001
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, rexp: /\A\d+\z/)
1002
- optdict = {}
1003
- pr = proc { x.validate_and_convert("abc", optdict) }
1004
- ok {pr}.raise?(RuntimeError, "Pattern unmatched.")
1005
- end
1006
-
1007
- spec "[!5jrdf] raises RuntimeError when value not in enum." do
1008
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, enum: ['2', '4', '8'])
1009
- optdict = {}
1010
- pr = proc { x.validate_and_convert("10", optdict) }
1011
- ok {pr}.raise?(RuntimeError, "Expected one of 2/4/8.")
1012
- end
1013
-
1014
- spec "[!5falp] raise RuntimeError when value not in range." do
1015
- x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
1016
- type: Integer, range: 2..8)
1017
- optdict = {}
1018
- pr = proc { x.validate_and_convert("1", optdict) }
1019
- ok {pr}.raise?(RuntimeError, "Too small (min: 2)")
1020
- pr = proc { x.validate_and_convert("9", optdict) }
1021
- ok {pr}.raise?(RuntimeError, "Too large (max: 8)")
1022
- ## when min==0
1023
- x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
1024
- type: Integer, range: 0..8)
1025
- optdict = {}
1026
- pr = proc { x.validate_and_convert("-1", optdict) }
1027
- ok {pr}.raise?(RuntimeError, "Positive value (>= 0) expected.")
1028
- ## when min==1
1029
- x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
1030
- type: Integer, range: 1..8)
1031
- optdict = {}
1032
- pr = proc { x.validate_and_convert("0", optdict) }
1033
- ok {pr}.raise?(RuntimeError, "Positive value (>= 1) expected.")
1034
- end
1035
-
1036
- spec "[!a0rej] supports endless range." do
1037
- begin
1038
- range1 = eval "(2..)" # Ruby >= 2.6
1039
- range2 = eval "(..8)"
1040
- rescue SyntaxError
1041
- range1 = nil # Ruby < 2.6
1042
- range2 = nil
1043
- end
1044
- if range1
1045
- x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
1046
- type: Integer, range: range1)
1047
- optdict = {}
1048
- pr = proc { x.validate_and_convert("1", optdict) }
1049
- ok {pr}.raise?(RuntimeError, "Too small (min: 2)")
1050
- pr = proc { x.validate_and_convert("9", optdict) }
1051
- ok {pr}.NOT.raise?(RuntimeError)
1052
- end
1053
- if range2
1054
- x = new_item(:indent, "-i[=<N>]", "indent", "i", nil, "<N>", false,
1055
- type: Integer, range: range2)
1056
- optdict = {}
1057
- pr = proc { x.validate_and_convert("1", optdict) }
1058
- ok {pr}.NOT.raise?(RuntimeError)
1059
- pr = proc { x.validate_and_convert("9", optdict) }
1060
- ok {pr}.raise?(RuntimeError, "Too large (max: 8)")
1061
- end
1062
- end
1063
-
1064
- spec "[!j4fuz] calls type-specific callback when type specified." do
1065
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer)
1066
- optdict = {}
1067
- pr = proc { x.validate_and_convert("abc", optdict) }
1068
- ok {pr}.raise?(RuntimeError, "Integer expected.")
1069
- end
1070
-
1071
- spec "[!jn9z3] calls callback when callback specified." do
1072
- called = false
1073
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|va|
1074
- called = true
1075
- }
1076
- optdict = {}
1077
- x.validate_and_convert("abc", optdict)
1078
- ok {called} == true
1079
- end
1080
-
1081
- spec "[!iqalh] calls callback with different number of args according to arity." do
1082
- args1 = nil
1083
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|val|
1084
- args1 = val
1085
- }
1086
- optdict = {}
1087
- x.validate_and_convert("123", optdict)
1088
- ok {args1} == "123"
1089
- #
1090
- args2 = nil
1091
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false) {|optdict, key, val|
1092
- args2 = [optdict, key, val]
1093
- }
1094
- optdict = {}
1095
- x.validate_and_convert("123", optdict)
1096
- ok {args2} == [optdict, :indent, "123"]
1097
- end
1098
-
1099
- spec "[!x066l] returns new value." do
1100
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer)
1101
- ok {x.validate_and_convert("123", {})} == 123
1102
- #
1103
- x = new_item(:indent, "", "indent width", "i", "indent", "<WIDTH>", false, type: Integer) {|val|
1104
- val * 2
1105
- }
1106
- ok {x.validate_and_convert("123", {})} == 246
1107
- end
1108
-
1109
- spec "[!eafem] returns default value (if specified) instead of true value." do
1110
- x1 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: nil)
1111
- ok {x1.validate_and_convert(true, {})} == true
1112
- x2 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: "blabla")
1113
- ok {x2.validate_and_convert(true, {})} == "blabla"
1114
- x3 = new_item(:flag, "", "desc", "f", "flag", nil, false, value: false)
1115
- ok {x3.validate_and_convert(true, {})} == false
1116
- end
1117
-
1118
- end
1119
-
1120
- end
1121
-
1122
-
1123
-
1124
- topic Benry::CmdOpt::Parser do
1125
-
1126
-
1127
- topic '#parse_options()' do
1128
-
1129
- before do
1130
- @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1131
- end
1132
-
1133
- spec "[!3wmsy] returns command option values as a dict." do
1134
- argv = ["-h", "--version"]
1135
- d = @parser.parse(argv)
1136
- ok {d} == {help: true, version: true}
1137
- end
1138
-
1139
- spec "[!uh7j8] parses long options." do
1140
- argv = ["--help", "--file=foo.png", "--indent=10"]
1141
- d = @parser.parse(argv)
1142
- ok {d} == {help: true, file: "foo.png", indent: 10}
1143
- end
1144
-
1145
- spec "[!nwnjc] parses short options." do
1146
- argv = ["-h", "-f", "foo.png", "-i10"]
1147
- d = @parser.parse(argv)
1148
- ok {d} == {help: true, file: "foo.png", indent: 10}
1149
- end
1150
-
1151
- spec "[!5s5b6] treats '-' as an argument, not an option." do
1152
- argv = ["-h", "-", "xxx", "yyy"]
1153
- d = @parser.parse(argv)
1154
- ok {d} == {help: true}
1155
- ok {argv} == ["-", "xxx", "yyy"]
1156
- end
1157
-
1158
- spec "[!q8356] parses options even after arguments when `all: true`." do
1159
- argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1160
- d = @parser.parse(argv, all: true)
1161
- ok {d} == {help: true, file: "foo.png", indent: 10}
1162
- ok {argv} == ["arg1", "arg2", "arg3"]
1163
- #
1164
- argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1165
- d = @parser.parse(argv)
1166
- ok {d} == {help: true, file: "foo.png", indent: 10}
1167
- ok {argv} == ["arg1", "arg2", "arg3"]
1168
- end
1169
-
1170
- spec "[!ryra3] doesn't parse options after arguments when `all: false`." do
1171
- argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1172
- d = @parser.parse(argv, all: false)
1173
- ok {d} == {help: true}
1174
- ok {argv} == ["arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
1175
- end
1176
-
1177
- spec "[!y04um] skips rest options when '--' found in argv." do
1178
- argv = ["-h", "--", "-f", "foo.png", "-i10"]
1179
- d = @parser.parse(argv)
1180
- ok {d} == {help: true}
1181
- ok {argv} == ["-f", "foo.png", "-i10"]
1182
- end
1183
-
1184
- spec "[!qpuxh] handles only OptionError when block given." do
1185
- errmsg = nil
1186
- errcls = nil
1187
- @parser.parse(["-ix"]) {|err|
1188
- errmsg = err.message
1189
- errcls = err.class
1190
- }
1191
- ok {errmsg} == "-ix: Integer expected."
1192
- ok {errcls} == Benry::CmdOpt::OptionError
1193
- #
1194
- sc = Benry::CmdOpt::Schema.new
1195
- sc.add(:file, "--file=<FILE>", "file") do |val|
1196
- File.open(val) {|f| f.read }
1197
- end
1198
- parser = Benry::CmdOpt::Parser.new(sc)
1199
- pr = proc { parser.parse(["--file=/foo/bar/baz.png"]) }
1200
- ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
1201
- end
1202
-
1203
- spec "[!dhpw1] returns nil when OptionError handled." do
1204
- ret = @parser.parse(["-dx"]) {|err| 1 }
1205
- ok {ret} == nil
1206
- end
1207
-
1208
- end
1209
-
1210
-
1211
- topic '#parse_long_option()' do
1212
-
1213
- before do
1214
- @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1215
- end
1216
-
1217
- spec "[!3i994] raises OptionError when invalid long option format." do
1218
- argv = ["--f/o/o"]
1219
- pr = proc { @parser.parse(argv) }
1220
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "--f/o/o: Invalid long option.")
1221
- end
1222
-
1223
- spec "[!1ab42] invokes error handler method when unknown long option." do
1224
- def @parser.handle_unknown_long_option(optstr, name, val)
1225
- (@_called_ ||= []) << [optstr, name, val]
1226
- end
1227
- ret = @parser.parse(["--xx=XX", "--yy=YY", "--zz"])
1228
- ok {ret} == {}
1229
- ok {@parser.instance_variable_get('@_called_')} == [
1230
- ["--xx=XX", "xx", "XX"],
1231
- ["--yy=YY", "yy", "YY"],
1232
- ["--zz" , "zz", nil],
1233
- ]
1234
- end
1235
-
1236
- spec "[!er7h4] default behavior is to raise OptionError when unknown long option." do
1237
- argv = ["--foo"]
1238
- pr = proc { @parser.parse(argv) }
1239
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "--foo: Unknown long option.")
1240
- end
1241
-
1242
- spec "[!2jd9w] raises OptionError when no arguments specified for arg required long option." do
1243
- argv = ["--file"]
1244
- pr = proc { @parser.parse(argv) }
1245
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "--file: Argument required.")
1246
- end
1247
-
1248
- spec "[!qyq8n] raises optionError when an argument specified for no arg long option." do
1249
- argv = ["--version=1.0.0"]
1250
- pr = proc { @parser.parse(argv) }
1251
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "--version=1.0.0: Unexpected argument.")
1252
- end
1253
-
1254
- spec "[!o596x] validates argument value." do
1255
- argv = ["--indent=abc"]
1256
- pr = proc { @parser.parse(argv) }
1257
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "--indent=abc: Integer expected.")
1258
- #
1259
- argv = ["--path=/foo/bar"]
1260
- pr = proc { @parser.parse(argv) }
1261
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "--path=/foo/bar: Directory not exist.")
1262
-
1263
- end
1264
-
1265
- end
1266
-
1267
-
1268
- topic '#parse_short_option()' do
1269
-
1270
- before do
1271
- @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1272
- end
1273
-
1274
- spec "[!4eh49] raises OptionError when unknown short option specified." do
1275
- argv = ["-hxf", "foo.png"]
1276
- pr = proc { @parser.parse(argv) }
1277
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "-x: Unknown option.")
1278
- end
1279
-
1280
- spec "[!utdbf] raises OptionError when argument required but not specified." do
1281
- argv = ["-hf"]
1282
- pr = proc { @parser.parse(argv) }
1283
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "-f: Argument required.")
1284
- end
1285
-
1286
- spec "[!f63hf] short option arg can be specified without space separator." do
1287
- argv = ["-hfabc.png", "xx"]
1288
- d = @parser.parse(argv)
1289
- ok {d} == {help: true, file: "abc.png"}
1290
- ok {argv} == ["xx"]
1291
- end
1292
-
1293
- spec "[!yjq6b] optional arg should be specified without space separator." do
1294
- argv = ["-hi123", "xx"]
1295
- d = @parser.parse(argv)
1296
- ok {d} == {help: true, indent: 123}
1297
- ok {argv} == ['xx']
1298
- end
1299
-
1300
- spec "[!wape4] otpional arg can be omit." do
1301
- argv = ["-hi", "xx"]
1302
- d = @parser.parse(argv)
1303
- ok {d} == {help: true, indent: true}
1304
- ok {argv} == ['xx']
1305
- end
1306
-
1307
- spec "[!yu0kc] validates short option argument." do
1308
- argv = ["-iaaa"]
1309
- pr = proc { @parser.parse(argv) }
1310
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "-iaaa: Integer expected.")
1311
- #
1312
- argv = ["-I", "/foo/bar"]
1313
- pr = proc { @parser.parse(argv) }
1314
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "-I /foo/bar: Directory not exist.")
1315
- end
1316
-
1317
- end
1318
-
1319
-
1320
- topic '#new_options_dict()' do
1321
-
1322
- spec "[!vm6h0] returns new hash object." do
1323
- parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1324
- ret = parser.__send__(:new_options_dict)
1325
- ok {ret}.is_a?(Hash)
1326
- ok {ret} == {}
1327
- end
1328
-
1329
- end
1330
-
1331
-
1332
- topic '#handle_unknown_long_option()' do
1333
-
1334
- spec "[!0q78a] raises OptionError." do
1335
- parser = Benry::CmdOpt::Parser.new(new_sample_schema())
1336
- pr = proc {
1337
- parser.__send__(:handle_unknown_long_option, "--xx=XX", "xx", "XX")
1338
- }
1339
- ok {pr}.raise?(Benry::CmdOpt::OptionError, "--xx=XX: Unknown long option.")
1340
- end
1341
-
1342
- end
1343
-
1344
-
1345
- end
1346
-
1347
-
1348
-
1349
12
  topic Benry::CmdOpt do
1350
13
 
1351
14
 
@@ -1509,192 +172,4 @@ END
1509
172
  end
1510
173
 
1511
174
 
1512
-
1513
- topic Benry::CmdOpt::Facade do
1514
-
1515
-
1516
- topic '#add()' do
1517
-
1518
- spec "[!vmb3r] defines command option." do
1519
- cmdopt = Benry::CmdOpt.new()
1520
- cmdopt.add(:help, "-h, --help", "show help message", detail: "(text)", tag: :important)
1521
- items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
1522
- ok {items}.is_a?(Array)
1523
- ok {items.length} == 1
1524
- ok {items[0].key} == :help
1525
- ok {items[0].short} == 'h'
1526
- ok {items[0].long} == 'help'
1527
- ok {items[0].desc} == 'show help message'
1528
- ok {items[0].detail} == '(text)'
1529
- ok {items[0].tag} == :important
1530
- end
1531
-
1532
- spec "[!71cvg] type, rexp, enum, and range are can be passed as positional args as well as keyword args." do
1533
- cmdopt = Benry::CmdOpt.new()
1534
- cmdopt.add(:key, "--optdef[=xx]", "desc", Integer, /\A\d+\z/, [2,4,8], (2..8), value: 4)
1535
- items = cmdopt.instance_eval { @schema.instance_variable_get('@items') }
1536
- item = items.first
1537
- ok {item.type} == Integer
1538
- ok {item.rexp} == /\A\d+\z/
1539
- ok {item.enum} == [2,4,8]
1540
- ok {item.range} == (2..8)
1541
- ok {item.value} == 4
1542
- end
1543
-
1544
- spec "[!tu4k3] returns self." do
1545
- cmdopt = Benry::CmdOpt.new()
1546
- x = cmdopt.add(:version, "-v, --version", "version")
1547
- ok {x}.same?(cmdopt)
1548
- end
1549
-
1550
- end
1551
-
1552
-
1553
- topic '#option_help()' do
1554
-
1555
- before do
1556
- @cmdopt = Benry::CmdOpt.new
1557
- @cmdopt.add(:help , "-h, --help" , "show help message")
1558
- @cmdopt.add(:version, " --version" , "print version")
1559
- @cmdopt.add(:file , "-f, --file=<FILE>" , "filename")
1560
- end
1561
-
1562
- spec "[!dm4p8] returns option help message." do
1563
- helpmsg = @cmdopt.option_help()
1564
- ok {helpmsg} == <<END
1565
- -h, --help : show help message
1566
- --version : print version
1567
- -f, --file=<FILE> : filename
1568
- END
1569
- end
1570
-
1571
- end
1572
-
1573
-
1574
- topic '#to_s()' do
1575
-
1576
- spec "[!s61vo] '#to_s' is an alias to '#option_help()'." do
1577
- cmdopt = Benry::CmdOpt.new
1578
- cmdopt.add(:help , "-h, --help" , "show help message")
1579
- cmdopt.add(:version, " --version" , "print version")
1580
- ok {cmdopt.to_s} == cmdopt.option_help()
1581
- end
1582
-
1583
- end
1584
-
1585
-
1586
- topic '#each_option_and_desc()' do
1587
-
1588
- before do
1589
- @cmdopt = Benry::CmdOpt.new
1590
- @cmdopt.add(:help , "-h, --help" , "show help message")
1591
- @cmdopt.add(:version, " --version" , "print version")
1592
- @cmdopt.add(:debug , "-D" , nil) # hidden option
1593
- @cmdopt.add(:trace , "-T" , "trace", hidden: true) # hidden option
1594
- end
1595
-
1596
- spec "[!bw9qx] yields each option definition string and help message." do
1597
- pairs = []
1598
- @cmdopt.each_option_and_desc {|opt, desc| pairs << [opt, desc] }
1599
- ok {pairs} == [
1600
- ["-h, --help" , "show help message"],
1601
- [" --version", "print version"],
1602
- ]
1603
- end
1604
-
1605
- spec "[!kunfw] yields all items (including hidden items) if `all: true` specified." do
1606
- ## when 'all: true'
1607
- pairs = []
1608
- @cmdopt.each_option_and_desc(all: true) {|opt, desc| pairs << [opt, desc] }
1609
- ok {pairs} == [
1610
- ["-h, --help" , "show help message"],
1611
- [" --version", "print version"],
1612
- ["-D" , nil],
1613
- ["-T" , "trace"],
1614
- ]
1615
- ## when 'all: false'
1616
- pairs = []
1617
- @cmdopt.each_option_and_desc(all: false) {|opt, desc| pairs << [opt, desc] }
1618
- ok {pairs} == [
1619
- ["-h, --help" , "show help message"],
1620
- [" --version", "print version"],
1621
- ]
1622
- end
1623
-
1624
- spec "[!wght5] returns enumerator object if block not given." do
1625
- ## when 'all: true'
1626
- xs = @cmdopt.each_option_and_desc(all: true)
1627
- ok {xs}.is_a?(Enumerator)
1628
- ok {xs.collect {|x, _| x }} == ["-h, --help", " --version", "-D", "-T"]
1629
- ## when 'all: false'
1630
- xs = @cmdopt.each_option_and_desc(all: false)
1631
- ok {xs}.is_a?(Enumerator)
1632
- ok {xs.collect {|x, _| x }} == ["-h, --help", " --version"]
1633
- end
1634
-
1635
- end
1636
-
1637
-
1638
- topic '#parse()' do
1639
-
1640
- before do
1641
- @cmdopt = Benry::CmdOpt.new()
1642
- @cmdopt.add(:file, "-f, --file=<FILE>", "file") do |val|
1643
- File.open(val) {|f| f.read }
1644
- end
1645
- @cmdopt.add(:debug, "-d, --debug[=<LEVEL>]", "debug", type: Integer)
1646
- end
1647
-
1648
- spec "[!7gc2m] parses command options." do
1649
- args = ["-d", "x", "y"]
1650
- @cmdopt.parse(args)
1651
- ok {args} == ["x", "y"]
1652
- end
1653
-
1654
- spec "[!no4xu] returns option values as dict." do
1655
- args = ["-d", "x"]
1656
- ok {@cmdopt.parse(args)} == {:debug=>true}
1657
- end
1658
-
1659
- spec "[!areof] handles only OptionError when block given." do
1660
- errmsg = nil
1661
- errcls = nil
1662
- @cmdopt.parse(["-dx"]) {|err|
1663
- errmsg = err.message
1664
- errcls = err.class
1665
- }
1666
- ok {errmsg} == "-dx: Integer expected."
1667
- ok {errcls} == Benry::CmdOpt::OptionError
1668
- #
1669
- pr = proc do
1670
- @cmdopt.parse(["-f", "/foo/bar/baz.png"])
1671
- end
1672
- ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
1673
- end
1674
-
1675
- spec "[!peuva] returns nil when OptionError handled." do
1676
- ret = @cmdopt.parse(["-dx"]) {|err| 1 }
1677
- ok {ret} == nil
1678
- end
1679
-
1680
- spec "[!za9at] parses options only before args when `all: false`." do
1681
- argv = ["aaa", "-d3", "bbb"]
1682
- #
1683
- argv1 = argv.dup
1684
- opts1 = @cmdopt.parse(argv1)
1685
- ok {opts1} == {:debug=>3}
1686
- ok {argv1} == ["aaa", "bbb"]
1687
- #
1688
- argv2 = argv.dup
1689
- opts2 = @cmdopt.parse(argv2, all: false)
1690
- ok {opts2} == {}
1691
- ok {argv2} == ["aaa", "-d3", "bbb"]
1692
- end
1693
-
1694
- end
1695
-
1696
-
1697
- end
1698
-
1699
-
1700
175
  end