benry-cmdopt 2.2.0 → 2.4.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.
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