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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9308d0182f3f4a17d45f3b7a1f212a4f5f2112f4084d725b2de05271a908bb1d
4
- data.tar.gz: f9b8e9066b9857d2693382f03bcbeacdd040695287d426d8ef8c28cf242f1cd1
3
+ metadata.gz: cb625857a40a61b165810acf4ee25cb3c9db54ac6e2c9e14678206a1036817a5
4
+ data.tar.gz: a47a9b936e4d63ea088945498d9469af67855af74c39680ae909ef36a6292945
5
5
  SHA512:
6
- metadata.gz: e231075a8a9fdd99a0379390ebc1fae07c812f8229d1689e0b7f04b91d5c0c596122835dde000c3ba609681898c3048fa51d08232cd33d4b9df0bacbc22036c6
7
- data.tar.gz: bcabe45f475efd7c95e989c9f7f2c9b61c65396b6373cbb0a68427ce10798a942c4af3cfd8ae66a34928c710b2cac24388d8848a6a1271ca40d3e9458a217898
6
+ metadata.gz: 4a35732c27d59d58ab02e23e22b7b52750975a728988b3f78c0d26bdcf52cfaffb7caa8d1feb2e1928a3455220e44dca0673720072dc31f164a87c08b6ed637c
7
+ data.tar.gz: 8ad1c06cb5b9e5adeb84fc01c4c236162a894c3fbea1f9470dbc87d67bb315c8669f8c84036cc1e594ac22f7047d5bb10fa790e298b24624d26858cc2ff3e127
data/CHANGES.md CHANGED
@@ -2,10 +2,22 @@ CHANGES
2
2
  =======
3
3
 
4
4
 
5
+ Release 2.4.0 (2023-12-04)
6
+ --------------------------
7
+
8
+ * [enhance] `Schema.add()` supports `multiple: true` keyword arg which enables to specify option multiple times.
9
+
10
+
11
+ Release 2.3.0 (2023-11-26)
12
+ --------------------------
13
+
14
+ * [change] `Schema#add()` raises SchemaError if option key, short or long option duplicated.
15
+
16
+
5
17
  Release 2.2.0 (2023-10-28)
6
18
  --------------------------
7
19
 
8
- * [enhance] Define `SchemaItem#add_item()` which adds option item into the schema. This is for Benry-CmdApp framework.
20
+ * [enhance] Define `Schema#add_item()` which adds option item into the schema. This is for Benry-CmdApp framework.
9
21
  * [change] (EXPERIMENTAL) Make `desc`, `detail`, `hidden`, `important`, `tag` attrubtes of `SchemaItem` object to be writable. This is for Benry-CmdApp framework.
10
22
 
11
23
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Benry-CmdOpt
2
2
 
3
- ($Release: 2.2.0 $)
3
+ ($Release: 2.4.0 $)
4
4
 
5
5
 
6
6
 
@@ -41,6 +41,9 @@ Benry-CmdOpt requires Ruby >= 2.3.
41
41
  * [Important Options](#important-options)
42
42
  * [Not Supported](#not-supported)
43
43
  * [Internal Classes](#internal-classes)
44
+ * [FAQ](#faq)
45
+ * [Q: How to change or customize error messages?](#q-how-to-change-or-customize-error-messages)
46
+ * [Q: Is it possible to support `-vvv` style option?](#q-is-it-possible-to-support--vvv-style-option)
44
47
  * [License and Copyright](#license-and-copyright)
45
48
 
46
49
  <!-- /TOC -->
@@ -139,6 +142,23 @@ cmdopt = Benry::CmdOpt.new
139
142
  cmdopt.add(:number, "-n <N>", "number", type: Integer, enum: [1, 2, 3]) # very intuitive
140
143
  ```
141
144
 
145
+ * `optparse.rb` doesn't report error even when options are duplicated.
146
+ This specification makes debugging hard.
147
+
148
+ `benry/cmdopt.rb` reports error when options are duplicated.
149
+
150
+ ```ruby
151
+ require 'optparse'
152
+
153
+ options = {}
154
+ parser = OptionParser.new
155
+ parser.on('-v', '--version') { options[:version] = true }
156
+ parser.on('-v', '--verbose') { options[:verbose] = true } # !!!!
157
+ argv = ["-v"]
158
+ parser.parse!(argv)
159
+ p options #=> {:verbose=>true}, not {:version=>true}
160
+ ```
161
+
142
162
  * `optparse.rb` adds `-h` and `--help` options automatically, and
143
163
  terminates current process when `-h` or `--help` specified in command-line.
144
164
  It is hard to remove these options.
@@ -260,13 +280,13 @@ end
260
280
 
261
281
  In fact, file `optparse.rb` and `optparse/*.rb` (in Ruby 3.2)
262
282
  contains total 1298 lines (except comments and blanks), while
263
- `benry/cmdopt.rb` (v2.0.0) contains only 429 lines (except both, too).
283
+ `benry/cmdopt.rb` (v2.4.0) contains only 479 lines (except both, too).
264
284
 
265
285
 
266
286
 
267
287
  ## Install
268
288
 
269
- ```
289
+ ```console
270
290
  $ gem install benry-cmdopt
271
291
  ```
272
292
 
@@ -450,11 +470,24 @@ p options[:flag2] #=> false (!!!!!)
450
470
 
451
471
  ### Multiple Value Option
452
472
 
473
+ Release 2.4 or later supports `multiple: true` keyword arg.
474
+
475
+ ```ruby
476
+ require 'benry/cmdopt'
477
+ cmdopt = Benry::CmdOpt.new
478
+
479
+ cmdopt.add(:inc , '-I <path>', "include path", multiple: true) # !!!!
480
+ options = cmdopt.parse(["-I", "/foo", "-I", "/bar", "-I/baz"])
481
+ p options #=> {:inc=>["/foo", "/bar", "/baz"]}
482
+ ```
483
+
484
+ On older version:
485
+
453
486
  ```ruby
454
487
  require 'benry/cmdopt'
455
488
  cmdopt = Benry::CmdOpt.new
456
489
 
457
- cmdopt.add(:lib , '-I <NAME>', "library name") {|options, key, val|
490
+ cmdopt.add(:inc , '-I <path>', "include path") {|options, key, val|
458
491
  arr = options[key] || []
459
492
  arr << val
460
493
  arr
@@ -462,8 +495,8 @@ cmdopt.add(:lib , '-I <NAME>', "library name") {|options, key, val|
462
495
  #(options[key] || []) << val
463
496
  }
464
497
 
465
- options = cmdopt.parse(["-I", "foo", "-I", "bar", "-Ibaz"])
466
- p options #=> {:lib=>["foo", "bar", "baz"]}
498
+ options = cmdopt.parse(["-I", "/foo", "-I", "/bar", "-I/baz"])
499
+ p options #=> {:inc=>["/foo", "/bar", "/baz"]}
467
500
  ```
468
501
 
469
502
 
@@ -687,6 +720,34 @@ Use `cmdopt.is_a?(Benry::CmdOpt::Facade)` instead if necessary.
687
720
 
688
721
 
689
722
 
723
+ ## FAQ
724
+
725
+
726
+ ### Q: How to change or customize error messages?
727
+
728
+ A: Currently not supported. Maybe supported in the future.
729
+
730
+
731
+ ### Q: Is it possible to support `-vvv` style option?
732
+
733
+ A: Yes.
734
+
735
+ ```ruby
736
+ require 'benry/cmdopt'
737
+ cmdopt = Benry::CmdOpt.new
738
+
739
+ cmdopt.add(:verbose , '-v', "verbose level") {|opts, key, val|
740
+ opts[key] ||= 0
741
+ opts[key] += 1
742
+ }
743
+
744
+ p cmdopt.parse(["-v"]) #=> {:verbose=>1}
745
+ p cmdopt.parse(["-vv"]) #=> {:verbose=>2}
746
+ p cmdopt.parse(["-vvv"]) #=> {:verbose=>3}
747
+ ```
748
+
749
+
750
+
690
751
  ## License and Copyright
691
752
 
692
753
  $License: MIT License $
data/benry-cmdopt.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "benry-cmdopt"
5
- spec.version = "$Release: 2.2.0 $".split()[1]
5
+ spec.version = "$Release: 2.4.0 $".split()[1]
6
6
  spec.author = "kwatch"
7
7
  spec.email = "kwatch@gmail.com"
8
8
  spec.platform = Gem::Platform::RUBY
@@ -21,7 +21,7 @@
21
21
  <ul class="nav">
22
22
  </ul>
23
23
  </nav>
24
- <p>($Release: 2.2.0 $)</p>
24
+ <p>($Release: 2.4.0 $)</p>
25
25
  <section class="section" id="whats-this">
26
26
  <h2>What's This?</h2>
27
27
  <p>Benry-CmdOpt is a command option parser library, like <code>optparse.rb</code>
@@ -57,6 +57,11 @@ and easy to understahnd.</p>
57
57
  <li><a href="#not-supported">Not Supported</a></li>
58
58
  </ul></li>
59
59
  <li><a href="#internal-classes">Internal Classes</a></li>
60
+ <li><a href="#faq">FAQ</a>
61
+ <ul>
62
+ <li><a href="#q-how-to-change-or-customize-error-messages">Q: How to change or customize error messages?</a></li>
63
+ <li><a href="#q-is-it-possible-to-support--vvv-style-option">Q: Is it possible to support <code>-vvv</code> style option?</a></li>
64
+ </ul></li>
60
65
  <li><a href="#license-and-copyright">License and Copyright</a></li>
61
66
  </ul>
62
67
  </div>
@@ -155,6 +160,23 @@ cmdopt = Benry::CmdOpt.new
155
160
  cmdopt.add(:number, "-n &ltN&gt;", "number", type: Integer, <strong>enum: [1, 2, 3]</strong>) # very intuitive
156
161
  </pre>
157
162
  <ul>
163
+ <li><code>optparse.rb</code> doesn't report error even when options are duplicated.
164
+ This specification makes debugging hard.
165
+ <p></p>
166
+ <code>benry/cmdopt.rb</code> reports error when options are duplicated.</li>
167
+ </ul>
168
+ <pre class="language-ruby">
169
+ require 'optparse'
170
+
171
+ options = {}
172
+ parser = OptionParser.new
173
+ parser.on(<strong>'-v'</strong>, '--version') { options[:version] = true }
174
+ parser.on(<strong>'-v'</strong>, '--verbose') { options[:verbose] = true } # !!!!
175
+ argv = ["-v"]
176
+ parser.parse!(argv)
177
+ p options #=&gt; {:verbose=&gt;true}, not {:version=&gt;true}
178
+ </pre>
179
+ <ul>
158
180
  <li><code>optparse.rb</code> adds <code>-h</code> and <code>--help</code> options automatically, and
159
181
  terminates current process when <code>-h</code> or <code>--help</code> specified in command-line.
160
182
  It is hard to remove these options.
@@ -276,12 +298,12 @@ end
276
298
  <p></p>
277
299
  In fact, file <code>optparse.rb</code> and <code>optparse/*.rb</code> (in Ruby 3.2)
278
300
  contains total 1298 lines (except comments and blanks), while
279
- <code>benry/cmdopt.rb</code> (v2.0.0) contains only 429 lines (except both, too).</li>
301
+ <code>benry/cmdopt.rb</code> (v2.4.0) contains only 479 lines (except both, too).</li>
280
302
  </ul>
281
303
  </section>
282
304
  <section class="section" id="install">
283
305
  <h2>Install</h2>
284
- <pre>
306
+ <pre class="language-console">
285
307
  $ gem install benry-cmdopt
286
308
  </pre>
287
309
  </section>
@@ -443,11 +465,21 @@ p options[:flag2] #=&gt; <strong>false</strong> (!!!!!)
443
465
  </section>
444
466
  <section class="subsection" id="multiple-value-option">
445
467
  <h3>Multiple Value Option</h3>
468
+ <p>Release 2.4 or later supports <code>multiple: true</code> keyword arg.</p>
469
+ <pre class="language-ruby">
470
+ require 'benry/cmdopt'
471
+ cmdopt = Benry::CmdOpt.new
472
+
473
+ cmdopt.add(:inc , '-I &ltpath&gt;', "include path", <strong>multiple: true</strong>) # !!!!
474
+ options = cmdopt.parse(["-I", "/foo", "-I", "/bar", "-I/baz"])
475
+ p options #=&gt; <strong>{:inc=&gt;["/foo", "/bar", "/baz"]}</strong>
476
+ </pre>
477
+ <p>On older version:</p>
446
478
  <pre class="language-ruby">
447
479
  require 'benry/cmdopt'
448
480
  cmdopt = Benry::CmdOpt.new
449
481
 
450
- cmdopt.add(:lib , '-I &ltNAME&gt;', "library name") <strong>{|options, key, val|</strong>
482
+ cmdopt.add(:inc , '-I &ltpath&gt;', "include path") <strong>{|options, key, val|</strong>
451
483
  <strong>arr = options[key] || []</strong>
452
484
  <strong>arr &lt&lt val</strong>
453
485
  <strong>arr</strong>
@@ -455,8 +487,8 @@ cmdopt.add(:lib , '-I &ltNAME&gt;', "library name") <strong>{|options, key, val|
455
487
  #(options[key] || []) &lt&lt val
456
488
  <strong>}</strong>
457
489
 
458
- options = cmdopt.parse(["-I", "foo", "-I", "bar", "-Ibaz"])
459
- p options #=&gt; <strong>{:lib=&gt;["foo", "bar", "baz"]}</strong>
490
+ options = cmdopt.parse(["-I", "/foo", "-I", "/bar", "-I/baz"])
491
+ p options #=&gt; <strong>{:inc=&gt;["/foo", "/bar", "/baz"]}</strong>
460
492
  </pre>
461
493
  </section>
462
494
  <section class="subsection" id="hidden-option">
@@ -661,6 +693,30 @@ opts = <strong>cmdopt.parse</strong>(ARGV) # same as <strong>pars
661
693
  <p>Notice that <code>cmdopt.is_a?(Benry::CmdOpt)</code> results in false.
662
694
  Use <code>cmdopt.is_a?(Benry::CmdOpt::Facade)</code> instead if necessary.</p>
663
695
  </section>
696
+ <section class="section" id="faq">
697
+ <h2>FAQ</h2>
698
+ <section class="subsection" id="q-how-to-change-or-customize-error-messages">
699
+ <h3>Q: How to change or customize error messages?</h3>
700
+ <p>A: Currently not supported. Maybe supported in the future.</p>
701
+ </section>
702
+ <section class="subsection" id="q-is-it-possible-to-support--vvv-style-option">
703
+ <h3>Q: Is it possible to support <code>-vvv</code> style option?</h3>
704
+ <p>A: Yes.</p>
705
+ <pre class="language-ruby">
706
+ require 'benry/cmdopt'
707
+ cmdopt = Benry::CmdOpt.new
708
+
709
+ cmdopt.add(:verbose , '-v', "verbose level") {|opts, key, val|
710
+ opts[key] ||= 0
711
+ opts[key] += 1
712
+ }
713
+
714
+ p cmdopt.parse(["-v"]) #=&gt; {:verbose=&gt;1}
715
+ p cmdopt.parse(["-vv"]) #=&gt; {:verbose=&gt;2}
716
+ p cmdopt.parse(["-vvv"]) #=&gt; {:verbose=&gt;3}
717
+ </pre>
718
+ </section>
719
+ </section>
664
720
  <section class="section" id="license-and-copyright">
665
721
  <h2>License and Copyright</h2>
666
722
  <p>$License: MIT License $</p>
data/doc/css/style.css CHANGED
@@ -74,12 +74,12 @@ pre > strong {
74
74
  font-weight: bold;
75
75
  color: #900;
76
76
  }
77
- pre.language-terminal {
77
+ pre.language-terminal, pre.language-console {
78
78
  background: #333;
79
79
  color: #fff;
80
80
  border-color: #000;
81
81
  }
82
- pre.language-terminal > strong {
82
+ pre.language-terminal > strong, pre.language-console > strong {
83
83
  color: #f66;
84
84
  }
85
85
  code {
data/lib/benry/cmdopt.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  ###
5
- ### $Release: 2.2.0 $
5
+ ### $Release: 2.4.0 $
6
6
  ### $Copyright: copyright(c) 2021 kwatch@gmail.com $
7
7
  ### $License: MIT License $
8
8
  ###
@@ -23,7 +23,7 @@ end
23
23
  module Benry::CmdOpt
24
24
 
25
25
 
26
- VERSION = '$Release: 2.2.0 $'.split()[1]
26
+ VERSION = '$Release: 2.4.0 $'.split()[1]
27
27
 
28
28
 
29
29
  def self.new()
@@ -40,11 +40,12 @@ module Benry::CmdOpt
40
40
 
41
41
  attr_reader :schema
42
42
 
43
- def add(key, optdef, desc, *rest, type: nil, rexp: nil, pattern: nil, enum: nil, range: nil, value: nil, detail: nil, hidden: nil, important: nil, tag: nil, &callback)
43
+ def add(key, optdef, desc, *rest, type: nil, rexp: nil, pattern: nil, enum: nil, range: nil, value: nil, multiple: nil, detail: nil, hidden: nil, important: nil, tag: nil, &callback)
44
44
  rexp ||= pattern # for backward compatibility
45
45
  #; [!vmb3r] defines command option.
46
46
  #; [!71cvg] type, rexp, enum, and range are can be passed as positional args as well as keyword args.
47
- @schema.add(key, optdef, desc, *rest, type: type, rexp: rexp, enum: enum, range: range, value: value, detail: detail, hidden: hidden, important: important, tag: tag, &callback)
47
+ @schema.add(key, optdef, desc, *rest,
48
+ type: type, rexp: rexp, enum: enum, range: range, value: value, multiple: multiple, detail: detail, hidden: hidden, important: important, tag: tag, &callback)
48
49
  #; [!tu4k3] returns self.
49
50
  self
50
51
  end
@@ -103,7 +104,7 @@ module Benry::CmdOpt
103
104
  self
104
105
  end
105
106
 
106
- def add(key, optdef, desc, *rest, type: nil, rexp: nil, pattern: nil, enum: nil, range: nil, value: nil, detail: nil, hidden: nil, important: nil, tag: nil, &callback)
107
+ def add(key, optdef, desc, *rest, type: nil, rexp: nil, pattern: nil, enum: nil, range: nil, value: nil, multiple: nil, detail: nil, hidden: nil, important: nil, tag: nil, &callback)
107
108
  rexp ||= pattern # for backward compatibility
108
109
  #; [!kuhf9] type, rexp, enum, and range are can be passed as positional args as well as keyword args.
109
110
  rest.each do |x|
@@ -137,17 +138,38 @@ module Benry::CmdOpt
137
138
  end
138
139
  #; [!yht0v] keeps command option definitions.
139
140
  item = SchemaItem.new(key, optdef, desc, short, long, param, required,
140
- type: type, rexp: rexp, enum: enum, range: range, value: value, detail: detail, hidden: hidden, important: important, tag: tag, &callback)
141
- @items << item
141
+ type: type, rexp: rexp, enum: enum, range: range, value: value, multiple: multiple, detail: detail, hidden: hidden, important: important, tag: tag, &callback)
142
+ add_item(item)
142
143
  item
143
144
  end
144
145
 
145
146
  def add_item(item)
147
+ #; [!qyjp9] raises SchemaError if invalid item added.
148
+ errmsg = _validate_item(item)
149
+ errmsg == nil or
150
+ raise SchemaError.new(errmsg)
146
151
  #; [!a693h] adds option item into current schema.
147
152
  @items << item
148
153
  self
149
154
  end
150
155
 
156
+ def _validate_item(item)
157
+ key = item.key; short = item.short; long = item.long
158
+ for x in @items
159
+ #; [!ewl20] returns error message if option key duplicated.
160
+ key != x.key or
161
+ return "#{key}: Option key duplicated."
162
+ #; [!xg56v] returns error message if short option duplicated.
163
+ short == nil || short != x.short or
164
+ return "-#{short}: Short option duplicated (key: #{key} and #{x.key})."
165
+ #; [!izezi] returns error message if long option duplicated.
166
+ long == nil || long != x.long or
167
+ return "--#{long}: Long option duplicated (key: #{key} and #{x.key})."
168
+ end
169
+ return nil
170
+ end
171
+ private :_validate_item
172
+
151
173
  def option_help(width_or_format=nil, all: false)
152
174
  #; [!0aq0i] can take integer as width.
153
175
  #; [!pcsah] can take format string.
@@ -301,7 +323,7 @@ module Benry::CmdOpt
301
323
 
302
324
  class SchemaItem # avoid Struct
303
325
 
304
- def initialize(key, optdef, desc, short, long, param, required, type: nil, rexp: nil, pattern: nil, enum: nil, range: nil, detail: nil, value: nil, hidden: nil, important: nil, tag: nil, &callback)
326
+ def initialize(key, optdef, desc, short, long, param, required, type: nil, rexp: nil, pattern: nil, enum: nil, range: nil, value: nil, multiple: nil, detail: nil, hidden: nil, important: nil, tag: nil, &callback)
305
327
  rexp ||= pattern # for backward compatibility
306
328
  _init_validation(param, required, type, rexp, enum, range, value)
307
329
  @key = key unless nil == key
@@ -315,8 +337,9 @@ module Benry::CmdOpt
315
337
  @rexp = rexp unless nil == rexp
316
338
  @enum = enum unless nil == enum
317
339
  @range = range unless nil == range
318
- @detail = detail unless nil == detail
319
340
  @value = value unless nil == value
341
+ @multiple = multiple unless nil == multiple
342
+ @detail = detail unless nil == detail
320
343
  @hidden = hidden unless nil == hidden
321
344
  @important = important unless nil == important
322
345
  @tag = tag unless nil == tag
@@ -325,7 +348,7 @@ module Benry::CmdOpt
325
348
  @enum.freeze() if @enum
326
349
  end
327
350
 
328
- attr_reader :key, :optdef, :desc, :short, :long, :param, :type, :rexp, :enum, :range, :detail, :value, :tag, :callback
351
+ attr_reader :key, :optdef, :desc, :short, :long, :param, :type, :rexp, :enum, :range, :value, :detail, :tag, :callback
329
352
  attr_writer :desc, :detail, :hidden, :important, :tag # !!experimental!!
330
353
  alias pattern rexp # for backward compatibility
331
354
  alias help desc # for backward compatibility
@@ -346,6 +369,12 @@ module Benry::CmdOpt
346
369
  return :optional
347
370
  end
348
371
 
372
+ def multiple?()
373
+ #; [!1lj8v] returns true if @multiple is truthy.
374
+ #; [!cun23] returns false if @multiple is falthy.
375
+ return !! @multiple
376
+ end
377
+
349
378
  def hidden?()
350
379
  #; [!no6ov] returns true if @hidden is true.
351
380
  #; [!ej8ot] returns false if @hidden is false.
@@ -608,7 +637,8 @@ module Benry::CmdOpt
608
637
  rescue RuntimeError => ex
609
638
  raise _error("#{optstr}: #{ex.message}")
610
639
  end
611
- optdict[item.key] = val
640
+ #; [!1m87b] supports multiple option.
641
+ store_option_value(optdict, item, val)
612
642
  end
613
643
 
614
644
  def parse_short_options(optstr, optdict, &block)
@@ -648,7 +678,8 @@ module Benry::CmdOpt
648
678
  raise _error("-#{char}#{sp}#{val}: #{ex.message}")
649
679
  end
650
680
  end
651
- optdict[item.key] = val
681
+ #; [!187r2] supports multiple option.
682
+ store_option_value(optdict, item, val)
652
683
  end
653
684
  end
654
685
 
@@ -657,6 +688,16 @@ module Benry::CmdOpt
657
688
  return OPTIONS_CLASS.new
658
689
  end
659
690
 
691
+ def store_option_value(optdict, item, val)
692
+ #; [!my86j] stores multiple values if multiple option item.
693
+ if item.multiple?
694
+ (optdict[item.key] ||= []) << val
695
+ #; [!tm7xw] stores singile value if not multiple option item.
696
+ else
697
+ optdict[item.key] = val
698
+ end
699
+ end
700
+
660
701
  def handle_unknown_long_option(optstr, name, val)
661
702
  #; [!0q78a] raises OptionError.
662
703
  raise _error("#{optstr}: Unknown long option.")