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.
- data/History.rdoc +9 -0
- data/README.rdoc +17 -7
- data/lib/config_parser.rb +60 -59
- data/lib/config_parser/flag.rb +49 -37
- data/lib/config_parser/list.rb +12 -12
- data/lib/config_parser/option.rb +10 -10
- data/lib/config_parser/switch.rb +9 -9
- data/lib/config_parser/utils.rb +28 -31
- data/lib/config_parser/version.rb +1 -1
- metadata +4 -4
data/History.rdoc
CHANGED
@@ -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:
|
data/README.rdoc
CHANGED
@@ -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]
|
data/lib/config_parser.rb
CHANGED
@@ -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.
|
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
|
data/lib/config_parser/flag.rb
CHANGED
@@ -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
|
-
|
146
|
-
|
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 >
|
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|
|
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
|
data/lib/config_parser/list.rb
CHANGED
@@ -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
|
data/lib/config_parser/option.rb
CHANGED
@@ -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
|
data/lib/config_parser/switch.rb
CHANGED
@@ -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
|
data/lib/config_parser/utils.rb
CHANGED
@@ -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
|
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:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
-
-
|
10
|
-
version: 0.5.
|
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-
|
18
|
+
date: 2011-07-18 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|