benry-cmdopt 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51be94488014a32dabfc2f524a850fa657a11c4c1d9d9b92761d00e57e24969e
4
- data.tar.gz: d2078058fec806f194f0bfd1d5d6705a78430c7989d7eb9ddccadea2daa3311b
3
+ metadata.gz: e22704458cfcb32a806de14c4b4df853673de1309b964d4362e2cc9605f64fca
4
+ data.tar.gz: 78a52a4a0d1b5d261bea63c58b454b0b68810f10fb3795e347644f269715580f
5
5
  SHA512:
6
- metadata.gz: 41e0e1a914cb6022f31244d6770067bd38636f27c0ce9e30dbcd37a731bc8d3f485329e0c0b49ff3aa322250f6d475ee0c28032a1053132e0f8c2bf061b2aa7c
7
- data.tar.gz: e5e3922ccf2d06e9b56997cc07e7616dfa905fedb1974953f7bc9138d7b888cab6d5b5c8025000cd574b8b608ead71ef772571fa71486c5467294d20376bdb9e
6
+ metadata.gz: b79a27875901ee9aaa5ef6f8bee208e2b5d76ff69511a9b47d741df9350c724f1b3c9530a48c80cc2e1bd69ce5283f447c104da0c2587ec96628750ce141031f
7
+ data.tar.gz: e063f8ab5ab3d1054d96e1410b6b85d4517086d0c64772b1957951e6faada16e2e71d7333eb3388f981d545b1011db37a002fc7eb70cb7e637f5828165f1aef0
data/CHANGES.md CHANGED
@@ -3,6 +3,13 @@ CHANGES
3
3
  =======
4
4
 
5
5
 
6
+ Release 1.0.0 (2021-01-18)
7
+ --------------------------
8
+
9
+ * [change] rename 'build_option_help()' to 'option_help()'.
10
+ * [change] shorten option help width when no long options defined.
11
+
12
+
6
13
  Release 1.0.0 (2021-01-17)
7
14
  --------------------------
8
15
 
data/README.md CHANGED
@@ -1,23 +1,184 @@
1
1
  Benry::Cmdopt README
2
2
  ====================
3
3
 
4
- ($Release: 1.0.0 $)
4
+ ($Release: 1.1.0 $)
5
5
 
6
6
  Benry::Cmdopt is a command option parser library, like `optparse.rb`.
7
7
 
8
- Compared to `optparse.rb`:
9
-
10
- * Easy to use, easy to extend, easy to understand.
11
- * Not add `-h` nor `--help` automatically.
12
- * Not add `-v` nor `--version` automatically.
13
- * Not regard `-x` as short cut of `--xxx`.
14
- (`optparser.rb` regards `-x` as short cut of `--xxx` automatically.)
15
- * Provides very simple feature to build custom help message.
16
- * Separates command option schema class from parser class.
8
+ Compared to `optparse.rb`, Benry::Cmdopt is easy to use, easy to extend,
9
+ and easy to understahnd.
17
10
 
18
11
  (Benry::Cmdopt requires Ruby >= 2.3)
19
12
 
20
13
 
14
+ Why not `optparse.rb`?
15
+ ======================
16
+
17
+ * Source code of `optparse.rb` is very large and complicated, because
18
+ `OptParse` class does everything about command option parsing.
19
+ It is hard to customize or extend `OptionParser` class.
20
+
21
+ On the other hand, `benry/cmdopt.rb` consists of several classes
22
+ (schema class, parser class, and facade class).
23
+ Therefore it is easy to understand and extend these classes.
24
+
25
+ File `optparse.rb` contains 1234 lines (without comments), while
26
+ `benry/cmdopt.rb` (v1.1.0) contains only 361 lines (without comments).
27
+
28
+ * `optparse.rb` regards `-x` as a short cut of `--xxx` automatically
29
+ even if you have not defined `-x` option.
30
+ That is, short options which are not defined can be available unexpectedly.
31
+ This feature is hard-coded in `OptionParser#parse_in_order()`
32
+ and hard to be disabled.
33
+
34
+ On the other hand, `benry/cmdopt.rb` doesn't behave this way.
35
+ `-x` option is available only when `-x` is defined.
36
+
37
+ * `optparse.rb` can handle both `--name=val` and `--name val` styles.
38
+ The later style is ambiguous; you may wonder whether `--name` takes
39
+ `val` as argument or `--name` takes no argument (and `val` is command
40
+ argument).
41
+
42
+ Therefore the `--name=val` style is better than the `--name val` style.
43
+
44
+ `optparse.rb` cannot disable `--name val` style.
45
+ `benry/cmdopt.rb` supports only `--name=val` style.
46
+
47
+ * `optparse.rb` enforces you to catch `OptionParser::ParseError` exception.
48
+ That is, you must know error class name.
49
+
50
+ `benry/cmdopt.rb` provides error handler without exception class name.
51
+ You don't need to know error class name on error handling.
52
+
53
+ ```ruby
54
+ ### optparse.rb
55
+ require 'optparse'
56
+ parser = OptionParser.new
57
+ parser.on('-f', '--file=<FILE>', "filename")
58
+ opts = {}
59
+ begin
60
+ parser.parse!(ARGV, into: opts)
61
+ rescue OptionParser::ParseError => ex # specify error class
62
+ $stderr.puts "ERROR: #{ex.message}"
63
+ exit 1
64
+ end
65
+
66
+ ### benry/cmdopt.rb
67
+ require 'benry/cmdopt'
68
+ cmdopt = Benry::Cmdopt.new
69
+ cmdopt.add(:file, '-f, --file=<FILE>', "filename")
70
+ opts = cmdopt.parse(ARGV) do |err| # error handling wihtout error class name
71
+ $stderr.puts "ERROR: #{err.message}"
72
+ exit 1
73
+ end
74
+ ```
75
+
76
+ * `optparse.rb` uses long option name as hash key automatically, but
77
+ it doesn't provide the way to specify hash key of short-only option.
78
+
79
+ `benry/cmdopt.rb` can specify hash key of short-only option.
80
+
81
+ ```ruby
82
+ ### optparse.rb
83
+ require 'optparse'
84
+ parser = OptionParser.new
85
+ parser.on('-v', '--verbose', "verbose mode") # short and long option
86
+ parser.on('-q', "quiet mode") # short-only option
87
+ #
88
+ opts = {}
89
+ parser.parse!(['-v'], into: opts) # short option
90
+ p opts #=> {:verbose=>true} # hash key is long option name
91
+ #
92
+ opts = {}
93
+ parser.parse!(['-q'], into: opts) # short option
94
+ p opts #=> {:q=>true} # hash key is short option name
95
+
96
+ ### benry/cmdopt.rb
97
+ require 'benry/cmdopt'
98
+ cmdopt = Benry::Cmdopt.new
99
+ cmdopt.add(:verbose, '-v, --verbose', "verbose mode") # short and long
100
+ cmdopt.add(:quiet , '-q' , "quiet mode") # short-only
101
+ #
102
+ opts = cmdopt.parse(['-v']) # short option
103
+ p opts #=> {:verbose=>true} # independent hash key of option name
104
+ #
105
+ opts = cmdopt.parse(['-q']) # short option
106
+ p opts #=> {:quiet=>true} # independent hash key of option name
107
+ ```
108
+
109
+ * `optparse.rb` adds `-h` and `--help` options automatically, and
110
+ terminates current process when `-v` or `--version` specified in terminal.
111
+ It is hard to remove these options.
112
+
113
+ On the other hand, `benry/cmdopt.rb` does not add these options.
114
+ benry/cmdopt.rb` does nothing extra.
115
+
116
+ ```ruby
117
+ require 'optparse'
118
+ parser = OptionParser.new
119
+ ## it is able to overwrite '-h' and/or '--help',
120
+ ## but how to remove or disable these options?
121
+ opts = {}
122
+ parser.on('-h <host>', "hostname") {|v| opts[:host] = v }
123
+ parser.parse(['--help']) # <== terminates current process!!
124
+ puts 'xxx' #<== not printed because current process alreay terminated
125
+ ```
126
+
127
+ * `optparse.rb` adds `-v` and `--version` options automatically, and
128
+ terminates current process when `-v` or `--version` specified in terminal.
129
+ It is hard to remove these options.
130
+
131
+ On the other hand, `benry/cmdopt.rb` does not add these options.
132
+ benry/cmdopt.rb` does nothing extra.
133
+
134
+ ```ruby
135
+ require 'optparse'
136
+ parser = OptionParser.new
137
+ ## it is able to overwrite '-v' and/or '--version',
138
+ ## but how to remove or disable these options?
139
+ opts = {}
140
+ parser.on('-v', "verbose mode") { opts[:verbose] = true }
141
+ parser.parse(['--version']) # <== terminates current process!!
142
+ puts 'xxx' #<== not printed because current process alreay terminated
143
+ ```
144
+
145
+ * `optparse.rb` generates help message automatically, but it doesn't
146
+ contain `-h`, `--help`, `-v`, nor `--version`.
147
+ These options are available but not shown in help message. Strange.
148
+
149
+ * `optparse.rb` generates help message with too wide option name
150
+ by default. You must specify proper width.
151
+
152
+ `benry/cmdopt.rb` calculates proper width automatically.
153
+ You don't need to specify proper width in many case.
154
+
155
+ ```ruby
156
+ ### optparse.rb
157
+ require 'optparse'
158
+ banner = "Usage: blabla <options>"
159
+ parser = OptionParser.new(banner) # or OptionParser.new(banner, 25)
160
+ parser.on('-f', '--file=<FILE>', "filename")
161
+ parser.on('-m <MODE>' , "verbose/quiet")
162
+ puts parser.help
163
+ ### output
164
+ # Usage: blabla <options>
165
+ # -f, --file=<FILE> filename
166
+ # -m <MODE> verbose/quiet
167
+
168
+ ### benry/cmdopt.rb
169
+ require 'benry/cmdopt'
170
+ cmdopt = Benry::Cmdopt.new()
171
+ cmdopt.add(:file, '-f, --file=<FILE>', "filename")
172
+ cmdopt.add(:mode, '-m <MODE>' , "verbose/quiet")
173
+ puts "Usage: blabla <options>"
174
+ puts cmdopt.option_help()
175
+ ### output (calculated proper width)
176
+ # Usage: blabla <options>
177
+ # -f, --file=<FILE> : filename
178
+ # -m <MODE> : verbose/quiet
179
+ ```
180
+
181
+
21
182
  Usage
22
183
  =====
23
184
 
@@ -30,8 +191,8 @@ require 'benry/cmdopt'
30
191
 
31
192
  ## define
32
193
  cmdopt = Benry::Cmdopt.new
33
- cmdopt.add(:help , "-h, --help" , "print help message")
34
- cmdopt.add(:version, " --version", "print version")
194
+ cmdopt.add(:help , '-h, --help' , "print help message")
195
+ cmdopt.add(:version, ' --version', "print version")
35
196
 
36
197
  ## parse with error handling
37
198
  options = cmdopt.parse(ARGV) do |err|
@@ -46,7 +207,7 @@ if options[:help]
46
207
  puts "Usage: foobar [<options>] [<args>...]"
47
208
  puts ""
48
209
  puts "Options:"
49
- puts cmdopt.build_option_help()
210
+ puts cmdopt.option_help()
50
211
  ## or
51
212
  #format = " %-20s : %s"
52
213
  #cmdopt.each_option_help {|opt, help| puts format % [opt, help] }
@@ -59,29 +220,32 @@ Command option parameter
59
220
 
60
221
  ```ruby
61
222
  ## required parameter
62
- cmdopt.add(:file, "-f, --file=<FILE>", "filename")
63
- cmdopt.add(:file, " --file=<FILE>", "filename")
64
- cmdopt.add(:file, "-f <FILE>" , "filename")
223
+ cmdopt.add(:file, '-f, --file=<FILE>', "filename")
224
+ cmdopt.add(:file, ' --file=<FILE>', "filename")
225
+ cmdopt.add(:file, '-f <FILE>' , "filename")
65
226
 
66
227
  ## optional parameter
67
- cmdopt.add(:file, "-f, --file[=<FILE>]", "filename")
68
- cmdopt.add(:file, " --file[=<FILE>]", "filename")
69
- cmdopt.add(:file, "-f[<FILE>]" , "filename")
228
+ cmdopt.add(:file, '-f, --file[=<FILE>]', "filename")
229
+ cmdopt.add(:file, ' --file[=<FILE>]', "filename")
230
+ cmdopt.add(:file, '-f[<FILE>]' , "filename")
70
231
  ```
71
232
 
233
+ Notice that `"--file <FILE>"` style is not supported.
234
+ Please use `"--file=<FILE>"` style.
235
+
72
236
 
73
237
  Argument varidation
74
238
  -------------------
75
239
 
76
240
  ```ruby
77
241
  ## type
78
- cmdopt.add(:indent , "-i <N>", "indent width", type: Integer)
242
+ cmdopt.add(:indent , '-i <N>', "indent width", type: Integer)
79
243
  ## pattern
80
- cmdopt.add(:indent , "-i <N>", "indent width", pattern: /\A\d+\z/)
244
+ cmdopt.add(:indent , '-i <N>', "indent width", pattern: /\A\d+\z/)
81
245
  ## enum
82
- cmdopt.add(:indent , "-i <N>", "indent width", enum: [2, 4, 8])
246
+ cmdopt.add(:indent , '-i <N>', "indent width", enum: [2, 4, 8])
83
247
  ## callback
84
- cmdopt.add(:indent , "-i <N>", "indent width") {|val|
248
+ cmdopt.add(:indent , '-i <N>', "indent width") {|val|
85
249
  val =~ /\A\d+\z/ or
86
250
  raise "integer expected." # raise without exception class.
87
251
  val.to_i # convert argument value.
@@ -102,7 +266,7 @@ Multiple parameters
102
266
  -------------------
103
267
 
104
268
  ```ruby
105
- cmdopt.add(:lib , "-I <NAME>", "library names") {|optdict, key, val|
269
+ cmdopt.add(:lib , '-I <NAME>', "library name") {|optdict, key, val|
106
270
  arr = optdict[key] || []
107
271
  arr << val
108
272
  arr
@@ -110,11 +274,29 @@ cmdopt.add(:lib , "-I <NAME>", "library names") {|optdict, key, val|
110
274
  ```
111
275
 
112
276
 
113
- Not support
114
- -----------
277
+ Hidden option
278
+ -------------
279
+
280
+ If help string of command otpion is nil, it will not included
281
+ in help message.
282
+
283
+ ```ruby
284
+ require 'benry/cmdopt'
285
+ cmdopt = Benry::Cmdopt.new
286
+ cmdopt.add(:verbose, '-v, --verbose', "verbose mode")
287
+ cmdopt.add(:debug , '-d[<LEVEL>]' , nil, type: Integer) # hidden
288
+ puts cmdopt.option_help()
289
+ ### output ('-d' is not included)
290
+ # -v, --verbose : verbose mode
291
+ ```
292
+
293
+
294
+ Not supported
295
+ -------------
115
296
 
116
297
  * default value
117
298
  * `--no-xxx` style option
299
+ * bash/zsh completion
118
300
 
119
301
 
120
302
  Internal classes
@@ -140,7 +322,7 @@ opts = parser.parse(argv) do |err|
140
322
  $stderr.puts "ERROR: #{err.message}"
141
323
  exit 1
142
324
  end
143
- p opts #=> [:help=>true, :indent=>2, :file=>"blabla.txt"]
325
+ p opts #=> {:help=>true, :indent=>2, :file=>"blabla.txt"}
144
326
  p argv #=> ["aaa", "bbb"]
145
327
  ```
146
328
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'benry-cmdopt'
5
- spec.version = '$Release: 1.0.0 $'.split()[1]
5
+ spec.version = '$Release: 1.1.0 $'.split()[1]
6
6
  spec.author = 'kwatch'
7
7
  spec.email = 'kwatch@gmail.com'
8
8
  spec.platform = Gem::Platform::RUBY
@@ -19,8 +19,8 @@ module Benry
19
19
  ## Usage:
20
20
  ## ## define
21
21
  ## cmdopt = Benry::Cmdopt.new
22
- ## cmdopt.add(:help , "-h, --help" , "print help message")
23
- ## cmdopt.add(:version, " --version", "print version")
22
+ ## cmdopt.add(:help , '-h, --help' , "print help message")
23
+ ## cmdopt.add(:version, ' --version', "print version")
24
24
  ## ## parse
25
25
  ## options = cmdopt.parse(ARGV) do |err|
26
26
  ## $stderr.puts "ERROR: #{err.message}"
@@ -33,7 +33,7 @@ module Benry
33
33
  ## puts "Usage: foobar [<options>] [<args>...]"
34
34
  ## puts ""
35
35
  ## puts "Options:"
36
- ## puts cmdopt.build_option_help()
36
+ ## puts cmdopt.option_help()
37
37
  ## ## or
38
38
  ## #format = " %-20s : %s"
39
39
  ## #cmdopt.each_option_help {|opt, help| puts format % [opt, help] }
@@ -41,23 +41,23 @@ module Benry
41
41
  ##
42
42
  ## Command option parameter:
43
43
  ## ## required
44
- ## cmdopt.add(:file, "-f, --file=<FILE>", "filename")
45
- ## cmdopt.add(:file, " --file=<FILE>", "filename")
46
- ## cmdopt.add(:file, "-f <FILE>" , "filename")
44
+ ## cmdopt.add(:file, '-f, --file=<FILE>', "filename")
45
+ ## cmdopt.add(:file, ' --file=<FILE>', "filename")
46
+ ## cmdopt.add(:file, '-f <FILE>' , "filename")
47
47
  ## ## optional
48
- ## cmdopt.add(:file, "-f, --file[=<FILE>]", "filename")
49
- ## cmdopt.add(:file, " --file[=<FILE>]", "filename")
50
- ## cmdopt.add(:file, "-f[<FILE>]" , "filename")
48
+ ## cmdopt.add(:file, '-f, --file[=<FILE>]', "filename")
49
+ ## cmdopt.add(:file, ' --file[=<FILE>]', "filename")
50
+ ## cmdopt.add(:file, '-f[<FILE>]' , "filename")
51
51
  ##
52
52
  ## Validation:
53
53
  ## ## type
54
- ## cmdopt.add(:indent , "-i <N>", "indent width", type: Integer)
54
+ ## cmdopt.add(:indent , '-i <N>', "indent width", type: Integer)
55
55
  ## ## pattern
56
- ## cmdopt.add(:indent , "-i <N>", "indent width", pattern: /\A\d+\z/)
56
+ ## cmdopt.add(:indent , '-i <N>', "indent width", pattern: /\A\d+\z/)
57
57
  ## ## enum
58
- ## cmdopt.add(:indent , "-i <N>", "indent width", enum: [2, 4, 8])
58
+ ## cmdopt.add(:indent , '-i <N>', "indent width", enum: [2, 4, 8])
59
59
  ## ## callback
60
- ## cmdopt.add(:indent , "-i <N>", "indent width") {|val|
60
+ ## cmdopt.add(:indent , '-i <N>', "indent width") {|val|
61
61
  ## val =~ /\A\d+\z/ or
62
62
  ## raise "integer expected." # raise without exception class.
63
63
  ## val.to_i # convert argument value.
@@ -70,20 +70,31 @@ module Benry
70
70
  ## * Date (`/\A\d\d\d\d-\d\d?-\d\d?\z/`)
71
71
  ##
72
72
  ## Multiple parameters:
73
- ## cmdopt.add(:lib , "-I <NAME>", "library names") {|optdict, key, val|
73
+ ## cmdopt.add(:lib , '-I <NAME>', "library name") {|optdict, key, val|
74
74
  ## arr = optdict[key] || []
75
75
  ## arr << val
76
76
  ## arr
77
77
  ## }
78
78
  ##
79
- ## Not support:
79
+ ## Hidden option:
80
+ ## ### if help string is nil, that option is removed from help message.
81
+ ## require 'benry/cmdopt'
82
+ ## cmdopt = Benry::Cmdopt.new
83
+ ## cmdopt.add(:verbose, '-v, --verbose', "verbose mode")
84
+ ## cmdopt.add(:debug , '-d[<LEVEL>]' , nil, type: Integer) # hidden
85
+ ## puts cmdopt.option_help()
86
+ ## ### output ('-d' doesn't appear because help string is nil)
87
+ ## # -v, --verbose : verbose mode
88
+ ##
89
+ ## Not supported:
80
90
  ## * default value
81
91
  ## * `--no-xxx` style option
92
+ ## * bash/zsh completion
82
93
  ##
83
94
  module Cmdopt
84
95
 
85
96
 
86
- VERSION = '$Release: 1.0.0 $'.split()[1]
97
+ VERSION = '$Release: 1.1.0 $'.split()[1]
87
98
 
88
99
 
89
100
  def self.new
@@ -105,9 +116,9 @@ module Benry
105
116
  self
106
117
  end
107
118
 
108
- def build_option_help(width_or_format=nil, all: false)
119
+ def option_help(width_or_format=nil, all: false)
109
120
  #; [!dm4p8] returns option help message.
110
- return @schema.build_option_help(width_or_format, all: all)
121
+ return @schema.option_help(width_or_format, all: all)
111
122
  end
112
123
 
113
124
  def each_option_help(&block)
@@ -148,6 +159,10 @@ module Benry
148
159
  key || long or
149
160
  raise error("add(#{key.inspect}, #{optdef.inspect}): long option required when option key (1st arg) not specified.")
150
161
  key ||= long.gsub(/-/, '_').intern
162
+ #; [!97sn0] raises SchemaError when ',' is missing between short and long options.
163
+ if long.nil? && param =~ /\A--/
164
+ raise error("add(#{key.inspect}, #{optdef.inspect}): missing ',' between short option and long options.")
165
+ end
151
166
  #; [!7xmr5] raises SchemaError when type is not registered.
152
167
  #; [!s2aaj] raises SchemaError when option has no params but type specified.
153
168
  if type
@@ -179,13 +194,13 @@ module Benry
179
194
  item
180
195
  end
181
196
 
182
- def build_option_help(width_or_format=nil, all: false)
197
+ def option_help(width_or_format=nil, all: false)
183
198
  #; [!0aq0i] can take integer as width.
184
199
  #; [!pcsah] can take format string.
185
200
  #; [!dndpd] detects option width automatically when nothing specified.
186
201
  case width_or_format
187
202
  when nil ; format = _default_format()
188
- when Integer; format = " %-#{width_or_format}s: %s"
203
+ when Integer; format = " %-#{width_or_format}s : %s"
189
204
  when String ; format = width_or_format
190
205
  else
191
206
  raise ArgumentError.new("#{width_or_format.inspect}: width (integer) or format (string) expected.")
@@ -214,19 +229,6 @@ module Benry
214
229
  return buf.join()
215
230
  end
216
231
 
217
- def _default_format(min_width=20, max_width=35)
218
- #; [!hr45y] detects preffered option width.
219
- w = 0
220
- each_option_help do |opt, help|
221
- w = opt.length if w < opt.length
222
- end
223
- w = min_width if w < min_width
224
- w = max_width if w > max_width
225
- #; [!kkh9t] returns format string.
226
- return " %-#{w}s : %s"
227
- end
228
- private :_default_format
229
-
230
232
  def each_option_help(&block)
231
233
  #; [!4b911] yields each optin definition str and help message.
232
234
  @items.each do |item|
@@ -274,30 +276,50 @@ module Benry
274
276
  return short, long, param1 || param2, !!param2
275
277
  end
276
278
 
279
+ def _default_format(min_width=nil, max_width=35)
280
+ #; [!bmr7d] changes min_with according to options.
281
+ min_width ||= _preferred_option_width()
282
+ #; [!hr45y] detects preffered option width.
283
+ w = 0
284
+ each_option_help do |opt, help|
285
+ w = opt.length if w < opt.length
286
+ end
287
+ w = min_width if w < min_width
288
+ w = max_width if w > max_width
289
+ #; [!kkh9t] returns format string.
290
+ return " %-#{w}s : %s"
291
+ end
292
+
293
+ def _preferred_option_width()
294
+ #; [!kl91t] shorten option help min width when only single options which take no arg.
295
+ #; [!0koqb] widen option help min width when any option takes an arg.
296
+ #; [!kl91t] widen option help min width when long option exists.
297
+ long_p = @items.any? {|x| x.help && x.long && x.param }
298
+ short_p = @items.all? {|x| x.help && !x.long && !x.param }
299
+ return short_p ? 8 : long_p ? 20 : 14
300
+ end
301
+
277
302
  end
278
303
 
279
304
 
280
305
  class SchemaItem # avoid Struct
281
306
 
282
307
  def initialize(key, optdef, short, long, param, help, optional: nil, type: nil, pattern: nil, enum: nil, &callback)
283
- @key = key
284
- @optdef = optdef
285
- @short = short
286
- @long = long
287
- @param = param
288
- @help = help
289
- @optional = optional
290
- @type = type
291
- @pattern = pattern
292
- @enum = enum
293
- @callback = callback
308
+ @key = key unless key.nil?
309
+ @optdef = optdef unless optdef.nil?
310
+ @short = short unless short.nil?
311
+ @long = long unless long.nil?
312
+ @param = param unless param.nil?
313
+ @help = help unless help.nil?
314
+ @optional = optional unless optional.nil?
315
+ @type = type unless type.nil?
316
+ @pattern = pattern unless pattern.nil?
317
+ @enum = enum unless enum.nil?
318
+ @callback = callback unless callback.nil?
294
319
  end
295
320
 
296
321
  attr_reader :key, :optdef, :short, :long, :param, :help, :optional, :type, :pattern, :enum, :callback
297
-
298
- def optional_param?
299
- @optional
300
- end
322
+ alias optional_param? optional
301
323
 
302
324
  def validate_and_convert(val, optdict)
303
325
  #; [!h0s0o] raises RuntimeError when value not matched to pattern.
@@ -113,6 +113,13 @@ class Benry::Cmdopt::Schema::Test < MiniTest::Test
113
113
  ok {pr}.raise?(Benry::Cmdopt::SchemaError, msg)
114
114
  end
115
115
 
116
+ it "[!97sn0] raises SchemaError when ',' is missing between short and long options." do
117
+ sc = @schema
118
+ pr = proc { sc.add(:exec, '-x --exec=ARG', "exec") }
119
+ msg = "add(:exec, \"-x --exec=ARG\"): missing ',' between short option and long options."
120
+ ok {pr}.raise?(Benry::Cmdopt::SchemaError, msg)
121
+ end
122
+
116
123
  it "[!yht0v] keeps command option definitions." do
117
124
  sc = @schema
118
125
  sc.add(:indent, "-i, --indent[=<WIDTH>]", "indent width",
@@ -213,7 +220,7 @@ class Benry::Cmdopt::Schema::Test < MiniTest::Test
213
220
  end
214
221
 
215
222
 
216
- describe '#build_option_help()' do
223
+ describe '#option_help()' do
217
224
 
218
225
  before do
219
226
  sc = Benry::Cmdopt::Schema.new
@@ -226,19 +233,19 @@ class Benry::Cmdopt::Schema::Test < MiniTest::Test
226
233
  end
227
234
 
228
235
  it "[!0aq0i] can take integer as width." do
229
- help = @schema.build_option_help(41)
236
+ help = @schema.option_help(41)
230
237
  ok {help} == <<END
231
- -h, --help : show help message.
232
- --version : print version
233
- -f, --file=<FILE> : filename
234
- -i, --indent[=<WIDTH>] : enable indent
238
+ -h, --help : show help message.
239
+ --version : print version
240
+ -f, --file=<FILE> : filename
241
+ -i, --indent[=<WIDTH>] : enable indent
235
242
  END
236
243
  s = help.each_line.first.split(':')[0]
237
- ok {s.length} == 41+2
244
+ ok {s.length} == 41+3
238
245
  end
239
246
 
240
247
  it "[!pcsah] can take format string." do
241
- help = @schema.build_option_help("%-42s: %s")
248
+ help = @schema.option_help("%-42s: %s")
242
249
  ok {help} == <<END
243
250
  -h, --help : show help message.
244
251
  --version : print version
@@ -250,7 +257,7 @@ END
250
257
  end
251
258
 
252
259
  it "[!dndpd] detects option width automatically when nothing specified." do
253
- help = @schema.build_option_help()
260
+ help = @schema.option_help()
254
261
  ok {help} == <<END
255
262
  -h, --help : show help message.
256
263
  --version : print version
@@ -262,12 +269,12 @@ END
262
269
  end
263
270
 
264
271
  it "[!v7z4x] skips option help if help message is not specified." do
265
- help = @schema.build_option_help()
272
+ help = @schema.option_help()
266
273
  ok {help} !~ /debug/
267
274
  end
268
275
 
269
276
  it "[!to1th] includes all option help when `all` is true." do
270
- help = @schema.build_option_help(nil, all: true)
277
+ help = @schema.option_help(nil, all: true)
271
278
  ok {help} =~ /debug/
272
279
  ok {help} == <<END
273
280
  -h, --help : show help message.
@@ -286,7 +293,7 @@ output mode
286
293
  q, quiet: print litte output
287
294
  c, compact: print summary output
288
295
  END
289
- actual = sc.build_option_help()
296
+ actual = sc.option_help()
290
297
  expected = <<END
291
298
  -m, --mode=<MODE> : output mode
292
299
  v, verbose: print many output
@@ -325,6 +332,51 @@ END
325
332
  ok {ret} == " %-22s : %s"
326
333
  end
327
334
 
335
+ it "[!bmr7d] changes min_with according to options." do
336
+ sc = Benry::Cmdopt::Schema.new
337
+ sc.add(:help , '-h', "help")
338
+ sc.add(:version, '-v', "version")
339
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-8s : %s"
340
+ #
341
+ sc.add(:file , '-f <FILE>', "filename")
342
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
343
+ #
344
+ sc.add(:force , '--force', "forcedly")
345
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-14s : %s"
346
+ #
347
+ sc.add(:mode , '-m, --mode=<MODE>', "verbose/quiet")
348
+ ok {sc.__send__(:_default_format, nil, 40)} == " %-20s : %s"
349
+ end
350
+
351
+ end
352
+
353
+
354
+ describe '#_preferred_option_width()' do
355
+
356
+ it "[!kl91t] shorten option help min width when only single options which take no arg." do
357
+ sc = Benry::Cmdopt::Schema.new
358
+ sc.add(:help , '-h', "help")
359
+ sc.add(:version, '-v', "version")
360
+ ok {sc.__send__(:_preferred_option_width)} == 8
361
+ end
362
+
363
+ it "[!0koqb] widen option help min width when any option takes an arg." do
364
+ sc = Benry::Cmdopt::Schema.new
365
+ sc.add(:help , '-h', "help")
366
+ sc.add(:indent , '-i[<N>]', "indent")
367
+ ok {sc.__send__(:_preferred_option_width)} == 14
368
+ end
369
+
370
+ it "[!kl91t] widen option help min width when long option exists." do
371
+ sc = Benry::Cmdopt::Schema.new
372
+ sc.add(:help , '-h', "help")
373
+ sc.add(:version, '-v, --version', "version")
374
+ ok {sc.__send__(:_preferred_option_width)} == 14
375
+ #
376
+ sc.add(:file, '--file=<FILE>', "filename")
377
+ ok {sc.__send__(:_preferred_option_width)} == 20
378
+ end
379
+
328
380
  end
329
381
 
330
382
 
@@ -839,7 +891,7 @@ class Benry::Cmdopt::Facade::Test < MiniTest::Test
839
891
  end
840
892
 
841
893
 
842
- describe '#build_option_help()' do
894
+ describe '#option_help()' do
843
895
 
844
896
  before do
845
897
  @cmdopt = Benry::Cmdopt.new
@@ -849,7 +901,7 @@ class Benry::Cmdopt::Facade::Test < MiniTest::Test
849
901
  end
850
902
 
851
903
  it "[!dm4p8] returns option help message." do
852
- help = @cmdopt.build_option_help()
904
+ help = @cmdopt.option_help()
853
905
  ok {help} == <<END
854
906
  -h, --help : show help message
855
907
  --version : print version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: benry-cmdopt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kwatch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-17 00:00:00.000000000 Z
11
+ date: 2021-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest