config_parser 0.5.4 → 0.5.5

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.
@@ -1,3 +1,12 @@
1
+ == 0.5.5 / 2011-07-18
2
+
3
+ * [issue #3] added options to to_s to allow changes to the option/desc columns
4
+ widths
5
+ * [issue #4] made parser check for option_break such that breaks on non-option
6
+ args is possible
7
+ * [issue #5] single-character keys now default to a short rather than long
8
+ option
9
+
1
10
  == 0.5.4 / 2011-07-11
2
11
 
3
12
  Misc cleanup to the README and project structure. Also:
@@ -20,10 +20,10 @@ Define options and their default values using +add+:
20
20
  parser.add :switch, true # true makes a --[no-]switch
21
21
  parser.add :flag, false # false as a default makes a --flag
22
22
  parser.add :list, [] # an array makes a list-style option
23
-
23
+
24
24
  parser.parse 'a b --flag --list x --list y,z c'
25
25
  # => ['a', 'b', 'c']
26
-
26
+
27
27
  parser.config
28
28
  # => {
29
29
  # :option => 'default',
@@ -64,19 +64,19 @@ to the option (although by default it does). As you may expect a block can be
64
64
  given to process values before they are set as configs.
65
65
 
66
66
  parser = ConfigParser.new
67
-
67
+
68
68
  # use args to define the option
69
69
  parser.add(:x, nil, '-o', '--one')
70
-
70
+
71
71
  # use an options hash to define the option
72
72
  parser.add(:y, nil, :short => 't', :long => 'two')
73
-
73
+
74
74
  # use a block to process the values
75
75
  parser.add(:z, nil, :long => 'three') {|value| value.upcase }
76
-
76
+
77
77
  parser.parse('a b --one uno --two dos --three tres c')
78
78
  # => ['a', 'b', 'c']
79
-
79
+
80
80
  parser.config
81
81
  # => {:x => 'uno', :y => 'dos', :z => 'TRES'}
82
82
 
@@ -86,6 +86,16 @@ ConfigParser is available as a gem[http://rubygems.org/gems/config_parser].
86
86
 
87
87
  % gem install config_parser
88
88
 
89
+ == Development
90
+
91
+ To get started, checkout the code from GitHub[http://github.com/thinkerbot/config_parser] and run the tests:
92
+
93
+ git clone git://github.com/thinkerbot/config_parser.git
94
+ cd config_parser
95
+ rake test
96
+
97
+ Please report any issues {here}[http://github.com/thinkerbot/config_parser/issues].
98
+
89
99
  == Info
90
100
 
91
101
  Developer:: {Simon Chiang}[http://github.com/thinkerbot]
@@ -8,27 +8,27 @@ autoload(:Shellwords, 'shellwords')
8
8
  # additionally supports option declaration using an attributes hash.
9
9
  class ConfigParser
10
10
  include Utils
11
-
11
+
12
12
  # Returns an array of the options registered with self, in the order in
13
13
  # which they were added. Separators are also stored in the registry.
14
14
  attr_reader :registry
15
-
15
+
16
16
  # A hash of (flag, Option) pairs mapping command line flags like '-s' or
17
17
  # '--long' to the Option that handles them.
18
18
  attr_reader :options
19
-
19
+
20
20
  # The hash receiving parsed configs.
21
21
  attr_accessor :config
22
-
22
+
23
23
  # The argument to stop processing options.
24
24
  attr_accessor :option_break
25
-
25
+
26
26
  # Set to true to preserve the option break.
27
27
  attr_accessor :preserve_option_break
28
-
28
+
29
29
  # Set to true to assign config defaults on parse.
30
30
  attr_accessor :assign_defaults
31
-
31
+
32
32
  # Initializes a new ConfigParser and passes it to the block, if given.
33
33
  def initialize(config={}, opts={})
34
34
  opts = {
@@ -36,27 +36,27 @@ class ConfigParser
36
36
  :preserve_option_break => false,
37
37
  :assign_defaults => true
38
38
  }.merge(opts)
39
-
39
+
40
40
  @registry = []
41
41
  @options = {}
42
42
  @config = config
43
43
  @option_break = opts[:option_break]
44
44
  @preserve_option_break = opts[:preserve_option_break]
45
45
  @assign_defaults = opts[:assign_defaults]
46
-
46
+
47
47
  yield(self) if block_given?
48
48
  end
49
-
49
+
50
50
  # Returns the config value for key.
51
51
  def [](key)
52
52
  config[key]
53
53
  end
54
-
54
+
55
55
  # Sets the config value for key.
56
56
  def []=(key, value)
57
57
  config[key] = value
58
58
  end
59
-
59
+
60
60
  # Adds a separator string to self, used in to_s.
61
61
  def separator(str)
62
62
  @registry << str
@@ -70,29 +70,29 @@ class ConfigParser
70
70
  # no error is raised. Note that this may remove multiple options.
71
71
  def register(option, override=false)
72
72
  return nil if option.nil?
73
-
73
+
74
74
  if override
75
75
  existing = option.flags.collect {|flag| @options.delete(flag) }
76
76
  @registry -= existing
77
77
  end
78
-
78
+
79
79
  unless @registry.include?(option)
80
80
  @registry << option
81
81
  end
82
-
82
+
83
83
  option.flags.each do |flag|
84
84
  current = @options[flag]
85
-
85
+
86
86
  if current && current != option
87
87
  raise ArgumentError, "already mapped to a different option: #{flag}"
88
88
  end
89
-
89
+
90
90
  @options[flag] = option
91
91
  end
92
-
92
+
93
93
  option
94
94
  end
95
-
95
+
96
96
  # Unregisters the option by removing it from the registry and options.
97
97
  # Returns option.
98
98
  def unregister(option)
@@ -100,16 +100,16 @@ class ConfigParser
100
100
  @options.delete_if {|key, value| option == value }
101
101
  option
102
102
  end
103
-
103
+
104
104
  # Sorts options in the registry as specified by the block. Groups of
105
105
  # options as delimited by separators are sorted independently. If no block
106
106
  # is given, options are sorted by their long and short keys.
107
107
  def sort_opts!(&block)
108
108
  block ||= lambda {|option| (option.long || option.short).to_s.sub(/^-+/, '') }
109
-
109
+
110
110
  splits = []
111
111
  current = []
112
-
112
+
113
113
  options = self.options.values.uniq
114
114
  registry.each do |option|
115
115
  if options.include?(option)
@@ -120,14 +120,14 @@ class ConfigParser
120
120
  current = []
121
121
  end
122
122
  end
123
-
123
+
124
124
  splits << current
125
125
  @registry = splits.collect {|split| split.kind_of?(Array) ? split.sort_by(&block) : split }
126
126
  @registry.flatten!
127
-
127
+
128
128
  self
129
129
  end
130
-
130
+
131
131
  # Constructs an Option using args and registers it with self. The args may
132
132
  # contain (in any order) a short switch, a long switch, and a description
133
133
  # string. A callback may be provided as a block to process values for the
@@ -183,12 +183,12 @@ class ConfigParser
183
183
  def on(*args, &block)
184
184
  register new_option(args, &block)
185
185
  end
186
-
186
+
187
187
  # Same as on, but overrides options with overlapping flags.
188
188
  def on!(*args, &block)
189
189
  register new_option(args, &block), true
190
190
  end
191
-
191
+
192
192
  # An alternate syntax for on, where the key and default attributes are set
193
193
  # by the first two args. Like on, add can define option attributes using a
194
194
  # series of args or with a trailing hash.
@@ -204,7 +204,7 @@ class ConfigParser
204
204
  args << attrs
205
205
  on(*args, &block)
206
206
  end
207
-
207
+
208
208
  # Removes options by key. Any options with the specified key are removed.
209
209
  # Returns the removed options.
210
210
  def rm(key)
@@ -216,7 +216,7 @@ class ConfigParser
216
216
  end
217
217
  end.compact
218
218
  end
219
-
219
+
220
220
  # Parses options from argv in a non-destructive manner. Parsing stops if an
221
221
  # argument matching option_break is reached. If preserve_option_break is
222
222
  # specified then the option break is preserved in the remaining arguments.
@@ -228,90 +228,91 @@ class ConfigParser
228
228
  argv = argv.dup unless argv.kind_of?(String)
229
229
  parse!(argv, &block)
230
230
  end
231
-
231
+
232
232
  # Same as parse, but removes parsed args from argv.
233
233
  def parse!(argv=ARGV)
234
234
  argv = Shellwords.shellwords(argv) if argv.kind_of?(String)
235
-
235
+
236
236
  registry.each do |option|
237
237
  if assign_defaults && option.respond_to?(:assign_default)
238
238
  option.assign_default(config)
239
239
  end
240
240
  end
241
-
241
+
242
242
  args = []
243
243
  while !argv.empty?
244
244
  arg = argv.shift
245
-
246
- # determine if the arg is an option
247
- unless option?(arg)
248
- args << arg
249
- next
250
- end
251
-
245
+
252
246
  # add the remaining args and break
253
247
  # for the option break
254
248
  if option_break === arg
255
249
  argv.unshift(arg) if preserve_option_break
256
250
  break
257
251
  end
258
-
252
+
253
+ # determine if the arg is an option
254
+ unless option?(arg)
255
+ args << arg
256
+ next
257
+ end
258
+
259
259
  flag, value = arg, nil
260
-
260
+
261
261
  # try the flag directly
262
262
  unless option = @options[flag]
263
-
263
+
264
264
  # then try --opt=value syntax
265
265
  flag, value = flag.split('=', 2)
266
-
266
+
267
267
  # then try -ovalue syntax
268
268
  if value.nil? && flag[1] != ?-
269
269
  flag, value = flag[0, 2], flag[2, flag.length - 2]
270
270
  end
271
-
271
+
272
272
  unless option = @options[flag]
273
273
  raise "unknown option: #{flag}"
274
274
  end
275
275
  end
276
-
276
+
277
277
  option.parse(flag, value, argv, config)
278
278
  end
279
-
279
+
280
280
  args.concat(argv)
281
281
  argv.replace(args)
282
-
282
+
283
283
  block_given? ? yield(argv, config) : argv
284
284
  end
285
-
285
+
286
286
  # Resets each option and clears the config (if specified). Returns self.
287
287
  def reset(options={})
288
288
  options = {
289
289
  :clear => true
290
290
  }.merge(options)
291
-
291
+
292
292
  registry.each do |option|
293
293
  if option.respond_to?(:reset)
294
294
  option.reset
295
295
  end
296
296
  end
297
-
297
+
298
298
  config.clear if options[:clear]
299
299
  self
300
300
  end
301
-
301
+
302
302
  # Converts the options and separators in self into a help string suitable
303
303
  # for display on the command line.
304
- def to_s
304
+ def to_s(opts={})
305
305
  @registry.collect do |option|
306
- option.to_s.rstrip
306
+ str = option.kind_of?(Flag) ? option.to_s(opts) : option.to_s
307
+ str.rstrip
307
308
  end.join("\n") + "\n"
308
309
  end
309
-
310
+
310
311
  protected
311
-
312
+
312
313
  def option_class(attrs) # :nodoc:
313
314
  type = attrs[:option_type] || guess_option_type(attrs)
314
-
315
+
315
316
  case type
316
317
  when :option then Option
317
318
  when :flag then Flag
@@ -321,16 +322,16 @@ class ConfigParser
321
322
  else raise "unknown option type: #{type}"
322
323
  end
323
324
  end
324
-
325
+
325
326
  # helper to parse an option from an argv. new_option is used
326
327
  # by on and on! to generate options
327
328
  def new_option(argv, &block) # :nodoc:
328
329
  attrs = argv.last.kind_of?(Hash) ? argv.pop : {}
329
330
  attrs = parse_attrs(argv).merge(attrs)
330
-
331
+
331
332
  attrs[:hint] ||= guess_hint(attrs)
332
333
  attrs[:callback] = block if block
333
-
334
+
334
335
  option_class(attrs).new(attrs)
335
336
  end
336
337
  end
@@ -1,59 +1,59 @@
1
1
  require 'config_parser/utils'
2
2
 
3
3
  class ConfigParser
4
-
4
+
5
5
  # Represents a boolean flag-style option. Flag handles the parsing of
6
6
  # specific flags, and provides hooks for processing the various types of
7
7
  # options (Switch, Option, List).
8
8
  class Flag
9
9
  include Utils
10
-
10
+
11
11
  # The config key.
12
12
  attr_reader :key
13
-
13
+
14
14
  # The config nesting keys.
15
15
  attr_reader :nest_keys
16
-
16
+
17
17
  # The default value.
18
18
  attr_reader :default
19
-
19
+
20
20
  # The short flag mapping to self.
21
21
  attr_reader :short
22
-
22
+
23
23
  # The long flag mapping to self.
24
24
  attr_reader :long
25
-
25
+
26
26
  # The description printed by to_s.
27
27
  attr_reader :desc
28
-
28
+
29
29
  # A hint printed by to_s, after desc.
30
30
  attr_reader :hint
31
-
31
+
32
32
  # A callback for processing values (must respond to call, or be nil).
33
33
  attr_reader :callback
34
-
34
+
35
35
  # A tracking flag set to true when assign is called. Useful when assign
36
36
  # works differently for the first assignment than later assignments. See
37
37
  # reset.
38
38
  attr_reader :assigned
39
-
39
+
40
40
  def initialize(attrs={})
41
41
  @key = attrs[:key]
42
42
  @nest_keys = attrs[:nest_keys]
43
43
  @default = attrs[:default]
44
- @short = shortify(attrs[:short])
44
+ @short = shortify(attrs.has_key?(:short) ? attrs[:short] : default_short)
45
45
  @long = longify(attrs.has_key?(:long) ? attrs[:long] : default_long)
46
46
  @desc = attrs[:desc]
47
47
  @hint = attrs[:hint]
48
48
  @callback = attrs[:callback]
49
49
  reset
50
50
  end
51
-
51
+
52
52
  # Returns an array of flags mapping to self (ie [long, short]).
53
53
  def flags
54
54
  [long, short].compact
55
55
  end
56
-
56
+
57
57
  # Parse handles the parsing of flags, which happens in three steps:
58
58
  #
59
59
  # * determine the value (occurs in parse)
@@ -95,17 +95,17 @@ class ConfigParser
95
95
  raise "value specified for #{flag}: #{value.inspect}"
96
96
  end
97
97
  end
98
-
98
+
99
99
  value = (default.nil? ? true : !default)
100
100
  assign(config, process(value))
101
101
  end
102
-
102
+
103
103
  # Process the value by calling the callback, if specified, with the value
104
104
  # and returns the result. Returns value if no callback is specified.
105
105
  def process(value)
106
106
  callback ? callback.call(value) : value
107
107
  end
108
-
108
+
109
109
  # Assigns the default value into config and resets the assigned flag to
110
110
  # false, such that the next assign behaves as if self has not put a value
111
111
  # into config. Returns config.
@@ -114,7 +114,7 @@ class ConfigParser
114
114
  reset
115
115
  config
116
116
  end
117
-
117
+
118
118
  # Assign the value to the config hash, if key is set, and flips assigned
119
119
  # to true. Returns config.
120
120
  def assign(config, value)
@@ -122,51 +122,58 @@ class ConfigParser
122
122
  nest_config = nest(config)
123
123
  nest_config[key] = value
124
124
  end
125
-
125
+
126
126
  @assigned = true
127
127
  config
128
128
  end
129
-
129
+
130
130
  # Returns the nested config hash for config, as specified by nest_keys.
131
131
  def nest(config)
132
132
  nest_keys.each do |key|
133
133
  config = (config[key] ||= {})
134
134
  end if nest_keys
135
-
135
+
136
136
  config
137
137
  end
138
-
138
+
139
139
  # Resets assigned to false.
140
140
  def reset
141
141
  @assigned = false
142
142
  end
143
-
144
- # Formats self as a help string for use on the command line.
145
- def to_s
146
- lines = wrap(desc_str, 43)
147
-
143
+
144
+ # Formats self as a help string for use on the command line (deprecated
145
+ # for that use, see format instead).
146
+ def to_s(opts={})
147
+ width = opts[:width] || 80
148
+ head_size = opts[:head_size] || (width * 0.45).to_i
149
+ desc_size = width - head_size - 1
150
+
151
+ format = "%-#{head_size}s %-#{desc_size}s"
152
+
153
+ lines = wrap(desc_str, desc_size)
154
+
148
155
  header = header_str
149
- header = header.length > 36 ? header.ljust(80) : (LINE_FORMAT % [header, lines.shift])
150
-
156
+ header = header.length > head_size ? header.ljust(width) : (format % [header, lines.shift])
157
+
151
158
  if lines.empty?
152
159
  header
153
160
  else
154
- lines.collect! {|line| LINE_FORMAT % [nil, line] }
161
+ lines.collect! {|line| format % [nil, line] }
155
162
  "#{header}\n#{lines.join("\n")}"
156
163
  end
157
164
  end
158
-
165
+
159
166
  # Returns an inspect string.
160
167
  def inspect
161
168
  "#<#{self.class}:#{object_id} key=#{key.inspect} default=#{default.inspect} long=#{long.inspect} short=#{short.inspect}>"
162
169
  end
163
-
170
+
164
171
  private
165
-
172
+
166
173
  def header_str # :nodoc:
167
174
  " #{short_str}#{long_str}"
168
175
  end
169
-
176
+
170
177
  def short_str # :nodoc:
171
178
  case
172
179
  when short && long then "#{short}, "
@@ -174,11 +181,11 @@ class ConfigParser
174
181
  else ' '
175
182
  end
176
183
  end
177
-
184
+
178
185
  def long_str # :nodoc:
179
186
  long
180
187
  end
181
-
188
+
182
189
  def desc_str # :nodoc:
183
190
  case
184
191
  when hint.nil? && desc.nil?
@@ -189,9 +196,14 @@ class ConfigParser
189
196
  "#{desc} (#{hint})".strip
190
197
  end
191
198
  end
192
-
199
+
193
200
  def default_long # :nodoc:
201
+ return nil if default_short
194
202
  nest_keys ? (nest_keys + [key]).join(':') : key
195
203
  end
204
+
205
+ def default_short # :nodoc:
206
+ key.to_s.length == 1 && nest_keys.nil? ? key : nil
207
+ end
196
208
  end
197
209
  end
@@ -1,46 +1,46 @@
1
1
  require 'config_parser/option'
2
2
 
3
3
  class ConfigParser
4
-
4
+
5
5
  # List represents a special type of Option where multiple values may be
6
6
  # assigned to the same key.
7
7
  class List < Option
8
-
8
+
9
9
  # The delimiter on which to split single values into multiple values; use
10
10
  # nil to prevent splitting.
11
11
  attr_reader :delimiter
12
-
12
+
13
13
  def initialize(attrs={})
14
14
  super
15
-
15
+
16
16
  @delimiter = attrs.has_key?(:delimiter) ? attrs[:delimiter] : DELIMITER
17
17
  @default = split(@default)
18
18
  end
19
-
19
+
20
20
  # Splits the value into multiple values, and then process as usual.
21
21
  def process(value)
22
22
  split(value).collect {|val| super(val) }
23
23
  end
24
-
24
+
25
25
  # Assigns the values to config. Multiple calls to assign will concatenate
26
26
  # (ie when assigned is true) new values onto the existing values. As
27
27
  # usual, no values are assigned if key is not set. Returns config.
28
28
  def assign(config, values)
29
29
  if key
30
30
  nest_config = nest(config)
31
-
31
+
32
32
  unless assigned
33
33
  nest_config[key] = []
34
34
  end
35
-
35
+
36
36
  array = (nest_config[key] ||= [])
37
37
  array.concat(values)
38
38
  end
39
-
39
+
40
40
  @assigned = true
41
41
  config
42
42
  end
43
-
43
+
44
44
  # Splits string values along the delimiter, if specified. Returns array
45
45
  # values directly, and an empty array for nil. All other values are
46
46
  # arrayified like [obj].
@@ -52,9 +52,9 @@ class ConfigParser
52
52
  else [obj]
53
53
  end
54
54
  end
55
-
55
+
56
56
  private
57
-
57
+
58
58
  def header_str # :nodoc:
59
59
  " #{short_str}#{long_str} #{arg_name}..."
60
60
  end
@@ -1,28 +1,28 @@
1
1
  require 'config_parser/switch'
2
2
 
3
3
  class ConfigParser
4
-
4
+
5
5
  # An Option represents a Flag that takes a value.
6
6
  class Option < Flag
7
-
7
+
8
8
  # The default argument name
9
9
  DEFAULT_ARGNAME = 'VALUE'
10
-
10
+
11
11
  # Matches optional argnames
12
12
  OPTIONAL = /\A\[.*\]\z/
13
-
13
+
14
14
  # The argument name printed by to_s.
15
15
  attr_reader :arg_name
16
-
16
+
17
17
  # Set to true to make the argument optional.
18
18
  attr_reader :optional
19
-
19
+
20
20
  def initialize(attrs={})
21
21
  super
22
22
  @arg_name = attrs[:arg_name] || (key ? key.to_s.upcase : DEFAULT_ARGNAME)
23
23
  @optional = (attrs.has_key?(:optional) ? attrs[:optional] : (arg_name =~ OPTIONAL ? true : false))
24
24
  end
25
-
25
+
26
26
  # Parse the flag and value. If no value is provided and a value is
27
27
  # required, then a value is shifted off of argv. The value is then
28
28
  # processed and assigned into config.
@@ -36,12 +36,12 @@ class ConfigParser
36
36
  end
37
37
  end
38
38
  end
39
-
39
+
40
40
  assign(config, process(value))
41
41
  end
42
-
42
+
43
43
  private
44
-
44
+
45
45
  def header_str # :nodoc:
46
46
  " #{short_str}#{long_str} #{arg_name}"
47
47
  end
@@ -1,43 +1,43 @@
1
1
  require 'config_parser/flag'
2
2
 
3
3
  class ConfigParser
4
-
4
+
5
5
  # Switch represents a special type of Option where both positive (--flag)
6
6
  # and negative (--no-flag) flags map to self.
7
7
  class Switch < Flag
8
-
8
+
9
9
  # The negative mapping prefix, defaults to 'no'
10
10
  attr_reader :prefix
11
-
11
+
12
12
  # The negative long flag, determined from long and prefix.
13
13
  attr_reader :negative_long
14
-
14
+
15
15
  def initialize(attrs={})
16
16
  attrs[:default] = true unless attrs.has_key?(:default)
17
17
  super
18
-
18
+
19
19
  raise ArgumentError, "no long specified" unless long
20
20
  @prefix = attrs[:prefix] || 'no'
21
21
  @negative_long = prefix_long(long, "#{prefix}-")
22
22
  end
23
-
23
+
24
24
  # Returns an array of flags mapping to self (ie [long, negative_long, short]).
25
25
  def flags
26
26
  [long, negative_long, short].compact
27
27
  end
28
-
28
+
29
29
  # Assigns default into config for positive flags and !default for negative
30
30
  # flags. The boolean value is then processed and assigned into config.
31
31
  # Raises an error if a value is provided (switches take none).
32
32
  def parse(flag, value=nil, argv=[], config={})
33
33
  raise "value specified for #{flag}: #{value.inspect}" if value
34
-
34
+
35
35
  value = (flag == negative_long ? !default : default)
36
36
  assign(config, process(value))
37
37
  end
38
38
 
39
39
  private
40
-
40
+
41
41
  def long_str # :nodoc:
42
42
  prefix_long(long, "[#{prefix}-]")
43
43
  end
@@ -1,24 +1,21 @@
1
1
  class ConfigParser
2
-
2
+
3
3
  # A medly of methods used throughout the ConfigParser classes.
4
4
  module Utils
5
5
  module_function
6
-
7
- # A format string used by to_s
8
- LINE_FORMAT = "%-36s %-43s"
9
-
6
+
10
7
  # The default option break
11
8
  OPTION_BREAK = "--"
12
-
9
+
13
10
  # Matches an option (long or short)
14
11
  OPTION = /\A-./
15
-
12
+
16
13
  # Matches a long flag
17
14
  LONG_FLAG = /\A--.+\z/
18
15
 
19
16
  # Matches a short flag
20
17
  SHORT_FLAG = /\A-.\z/
21
-
18
+
22
19
  # Matches a switch option (ex: '--[no-]opt', '--nest:[no-]opt'). After the
23
20
  # match:
24
21
  #
@@ -27,17 +24,17 @@ class ConfigParser
27
24
  # $3:: the long flag name ('opt')
28
25
  #
29
26
  SWITCH = /\A--(.*?)\[(.*?)-\](.+)\z/
30
-
27
+
31
28
  # Matches a nest option (ex: '--nest:opt'). After the match:
32
29
  #
33
30
  # $1:: the nesting prefix ('nest')
34
31
  # $2:: the long option ('long')
35
32
  #
36
33
  NEST = /\A--(.*):(.+)\z/
37
-
34
+
38
35
  # The default split character for multiple values
39
36
  DELIMITER = ','
40
-
37
+
41
38
  # Turns the input into a short flag by prefixing '-' (as needed). Raises
42
39
  # an error if the input doesn't result in a short flag. Nils are
43
40
  # returned directly.
@@ -47,14 +44,14 @@ class ConfigParser
47
44
  #
48
45
  def shortify(str)
49
46
  return nil if str.nil?
50
-
47
+
51
48
  str = str.to_s
52
49
  str = "-#{str}" unless option?(str)
53
-
50
+
54
51
  unless str =~ SHORT_FLAG
55
52
  raise ArgumentError, "invalid short flag: #{str}"
56
53
  end
57
-
54
+
58
55
  str
59
56
  end
60
57
 
@@ -67,17 +64,17 @@ class ConfigParser
67
64
  #
68
65
  def longify(str)
69
66
  return nil if str.nil?
70
-
67
+
71
68
  str = str.to_s
72
69
  str = "--#{str}" unless option?(str)
73
-
70
+
74
71
  unless str =~ LONG_FLAG
75
72
  raise ArgumentError, "invalid long flag: #{str}"
76
73
  end
77
-
74
+
78
75
  str
79
76
  end
80
-
77
+
81
78
  # Adds a prefix onto the last nested segment of a long option.
82
79
  #
83
80
  # prefix_long('--opt', 'no-') # => '--no-opt'
@@ -89,25 +86,25 @@ class ConfigParser
89
86
  switch[-1] = "#{prefix}#{switch[-1]}"
90
87
  "--#{switch.join(':')}"
91
88
  end
92
-
89
+
93
90
  # Returns true if the object is a string and matches OPTION.
94
91
  def option?(obj)
95
92
  obj.kind_of?(String) && obj =~ OPTION ? true : false
96
93
  end
97
-
94
+
98
95
  # Shifts and returns the first argument off of argv if it is an argument
99
96
  # (rather than an option) or returns the default value.
100
97
  def next_arg(argv)
101
98
  option?(argv.at(0)) ? nil : argv.shift
102
99
  end
103
-
100
+
104
101
  # A wrapping algorithm slightly modified from:
105
102
  # http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
106
103
  def wrap(line, cols=80, tabsize=2)
107
104
  line = line.gsub(/\t/, " " * tabsize) unless tabsize == nil
108
105
  line.gsub(/(.{1,#{cols}})( +|$\r?\n?)|(.{1,#{cols}})/, "\\1\\3\n").split(/\s*?\n/)
109
106
  end
110
-
107
+
111
108
  # Parses the argv into an attributes hash for initializing an option.
112
109
  # Heuristics are used to infer what an argument implies.
113
110
  #
@@ -129,7 +126,7 @@ class ConfigParser
129
126
  # arg_name with a switch) can be detected... others not so much.
130
127
  def parse_attrs(argv)
131
128
  attrs={}
132
-
129
+
133
130
  argv.each do |arg|
134
131
  unless option?(arg)
135
132
  attrs[:desc] = arg
@@ -137,7 +134,7 @@ class ConfigParser
137
134
  end
138
135
 
139
136
  flag, arg_name = arg.split(/\s+/, 2)
140
-
137
+
141
138
  if flag =~ NEST
142
139
  attrs[:nest_keys] = $1.split(':')
143
140
  end
@@ -150,7 +147,7 @@ class ConfigParser
150
147
  when SWITCH
151
148
  attrs[:long] = "--#{$1}#{$3}"
152
149
  attrs[:prefix] = $2
153
-
150
+
154
151
  if arg_name
155
152
  raise ArgumentError, "arg_name specified for switch: #{arg_name}"
156
153
  end
@@ -165,10 +162,10 @@ class ConfigParser
165
162
  raise ArgumentError.new("invalid flag: #{arg.inspect}")
166
163
  end
167
164
  end
168
-
165
+
169
166
  attrs
170
167
  end
171
-
168
+
172
169
  # Guesses an option type based on the attrs.
173
170
  #
174
171
  # if... then...
@@ -190,12 +187,12 @@ class ConfigParser
190
187
  :flag
191
188
  end
192
189
  end
193
-
190
+
194
191
  # Guesses :list if the arg_name has a comma, or nil.
195
192
  def guess_option_type_by_arg_name(arg_name)
196
193
  arg_name.to_s.include?(',') ? :list : nil
197
194
  end
198
-
195
+
199
196
  # Guesses an option type based on a value.
200
197
  #
201
198
  # if... then...
@@ -213,10 +210,10 @@ class ConfigParser
213
210
  else :option
214
211
  end
215
212
  end
216
-
213
+
217
214
  def guess_hint(attrs)
218
215
  default = attrs[:default]
219
-
216
+
220
217
  case default
221
218
  when true, false, nil
222
219
  nil
@@ -1,7 +1,7 @@
1
1
  class ConfigParser
2
2
  MAJOR = 0
3
3
  MINOR = 5
4
- TINY = 4
4
+ TINY = 5
5
5
 
6
6
  VERSION = "#{MAJOR}.#{MINOR}.#{TINY}"
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: config_parser
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 4
10
- version: 0.5.4
9
+ - 5
10
+ version: 0.5.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Simon Chiang
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-11 00:00:00 -06:00
18
+ date: 2011-07-18 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency