configurable 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +9 -0
- data/MIT-LICENSE +1 -1
- data/README +40 -142
- data/lib/cdoc.rb +413 -0
- data/lib/cdoc/cdoc_html_generator.rb +38 -0
- data/lib/cdoc/cdoc_html_template.rb +42 -0
- data/lib/config_parser.rb +302 -52
- data/lib/config_parser/option.rb +70 -21
- data/lib/config_parser/switch.rb +25 -10
- data/lib/config_parser/utils.rb +41 -27
- data/lib/configurable.rb +64 -40
- data/lib/configurable/class_methods.rb +245 -100
- data/lib/configurable/delegate.rb +18 -2
- data/lib/configurable/delegate_hash.rb +112 -69
- data/lib/configurable/indifferent_access.rb +21 -8
- data/lib/configurable/utils.rb +193 -0
- data/lib/configurable/validation.rb +112 -112
- metadata +16 -15
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rdoc/generators/html_generator'
|
2
|
+
|
3
|
+
# Defines a specialized generator so it can be called for using a --fmt option.
|
4
|
+
class CDocHTMLGenerator < Generators::HTMLGenerator # :nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
module Generators # :nodoc:
|
8
|
+
const_set(:RubyToken, RDoc::RubyToken)
|
9
|
+
|
10
|
+
class HtmlClass < ContextUser # :nodoc:
|
11
|
+
alias cdoc_original_value_hash value_hash
|
12
|
+
|
13
|
+
def value_hash
|
14
|
+
# split attributes into configurations and regular attributes
|
15
|
+
configurations, attributes = @context.attributes.partition do |attribute|
|
16
|
+
attribute.kind_of?(CDoc::ConfigAttr)
|
17
|
+
end
|
18
|
+
|
19
|
+
# set the context attributes to JUST the regular
|
20
|
+
# attributes and process as usual.
|
21
|
+
@context.attributes.clear.concat attributes
|
22
|
+
values = cdoc_original_value_hash
|
23
|
+
|
24
|
+
# set the context attributes to the configurations
|
25
|
+
# and echo the regular processing to produce a list
|
26
|
+
# of configurations
|
27
|
+
@context.attributes.clear.concat configurations
|
28
|
+
@context.sections.each_with_index do |section, i|
|
29
|
+
secdata = values["sections"][i]
|
30
|
+
|
31
|
+
al = build_attribute_list(section)
|
32
|
+
secdata["configurations"] = al unless al.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
values
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rdoc/generators/template/html/html'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Add a template for documenting configurations. Do so by inserting in the
|
5
|
+
# template into the content regions used to template html.
|
6
|
+
# (see 'rdoc/generators/html_generator' line 864)
|
7
|
+
#
|
8
|
+
[
|
9
|
+
RDoc::Page::BODY,
|
10
|
+
RDoc::Page::FILE_PAGE,
|
11
|
+
RDoc::Page::METHOD_LIST].each do |content|
|
12
|
+
|
13
|
+
# this substitution method duplicates the attribute template for configurations
|
14
|
+
# (see rdoc\generators\template\html line 523)
|
15
|
+
#
|
16
|
+
#IF:attributes
|
17
|
+
# <div id="attribute-list">
|
18
|
+
# <h3 class="section-bar">Attributes</h3>
|
19
|
+
#
|
20
|
+
# <div class="name-list">
|
21
|
+
# <table>
|
22
|
+
#START:attributes
|
23
|
+
# <tr class="top-aligned-row context-row">
|
24
|
+
# <td class="context-item-name">%name%</td>
|
25
|
+
#IF:rw
|
26
|
+
# <td class="context-item-value"> [%rw%] </td>
|
27
|
+
#ENDIF:rw
|
28
|
+
#IFNOT:rw
|
29
|
+
# <td class="context-item-value"> </td>
|
30
|
+
#ENDIF:rw
|
31
|
+
# <td class="context-item-desc">%a_desc%</td>
|
32
|
+
# </tr>
|
33
|
+
#END:attributes
|
34
|
+
# </table>
|
35
|
+
# </div>
|
36
|
+
# </div>
|
37
|
+
#ENDIF:attributes
|
38
|
+
#
|
39
|
+
content.gsub!(/IF:attributes.*?ENDIF:attributes/m) do |match|
|
40
|
+
match + "\n\n" + match.gsub(/attributes/, 'configurations').gsub(/Attributes/, 'Configurations')
|
41
|
+
end
|
42
|
+
end
|
data/lib/config_parser.rb
CHANGED
@@ -3,6 +3,114 @@ require 'config_parser/switch'
|
|
3
3
|
|
4
4
|
autoload(:Shellwords, 'shellwords')
|
5
5
|
|
6
|
+
# ConfigParser is the Configurable equivalent of
|
7
|
+
# {OptionParser}[http://www.ruby-doc.org/core/classes/OptionParser.html]
|
8
|
+
# and uses a similar, simplified (see below) syntax to declare options.
|
9
|
+
#
|
10
|
+
# opts = {}
|
11
|
+
# parser = ConfigParser.new do |psr|
|
12
|
+
# psr.on "-s", "--long LONG", "a standard option" do |value|
|
13
|
+
# opts[:long] = value
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# psr.on "--[no-]switch", "a switch" do |value|
|
17
|
+
# opts[:switch] = value
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# psr.on "--flag", "a flag" do
|
21
|
+
# # note: no value is parsed; the block
|
22
|
+
# # only executes if the flag is found
|
23
|
+
# opts[:flag] = true
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# parser.parse("a b --long arg --switch --flag c") # => ['a', 'b', 'c']
|
28
|
+
# opts # => {:long => 'arg', :switch => true, :flag => true}
|
29
|
+
#
|
30
|
+
# ConfigParser formalizes this pattern of setting values in a hash as they
|
31
|
+
# occur, and adds the ability to specify default values. The syntax is
|
32
|
+
# not quite as friendly as for ordinary options, but meshes well with
|
33
|
+
# Configurable classes:
|
34
|
+
#
|
35
|
+
# psr = ConfigParser.new
|
36
|
+
# psr.define(:key, 'default', :desc => 'a standard option')
|
37
|
+
#
|
38
|
+
# psr.parse('a b --key option c') # => ['a', 'b', 'c']
|
39
|
+
# psr.config # => {:key => 'option'}
|
40
|
+
#
|
41
|
+
# psr.parse('a b c') # => ['a', 'b', 'c']
|
42
|
+
# psr.config # => {:key => 'default'}
|
43
|
+
#
|
44
|
+
# And now directly from a Configurable class, the equivalent of the
|
45
|
+
# original example:
|
46
|
+
#
|
47
|
+
# class ConfigClass
|
48
|
+
# include Configurable
|
49
|
+
#
|
50
|
+
# config :long, 'default', :short => 's' # a standard option
|
51
|
+
# config :switch, false, &c.switch # a switch
|
52
|
+
# config :flag, false, &c.flag # a flag
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# psr = ConfigParser.new
|
56
|
+
# psr.add(ConfigClass.configurations)
|
57
|
+
#
|
58
|
+
# psr.parse("a b --long arg --switch --flag c") # => ['a', 'b', 'c']
|
59
|
+
# psr.config # => {:long => 'arg', :switch => true, :flag => true}
|
60
|
+
#
|
61
|
+
# psr.parse("a b --long=arg --no-switch c") # => ['a', 'b', 'c']
|
62
|
+
# psr.config # => {:long => 'arg', :switch => false, :flag => false}
|
63
|
+
#
|
64
|
+
# psr.parse("a b -sarg c") # => ['a', 'b', 'c']
|
65
|
+
# psr.config # => {:long => 'arg', :switch => false, :flag => false}
|
66
|
+
#
|
67
|
+
# As you might expect, config attributes are used by ConfigParser to
|
68
|
+
# correctly build a corresponding option. In configurations like :switch,
|
69
|
+
# the block implies the {:type => :switch} attribute and so the
|
70
|
+
# config is made into a switch-style option by ConfigParser.
|
71
|
+
#
|
72
|
+
# Use the to_s method to convert a ConfigParser into command line
|
73
|
+
# documentation:
|
74
|
+
#
|
75
|
+
# "\nconfigurations:\n#{psr.to_s}"
|
76
|
+
# # => %q{
|
77
|
+
# # configurations:
|
78
|
+
# # -s, --long LONG a standard option
|
79
|
+
# # --[no-]switch a switch
|
80
|
+
# # --flag a flag
|
81
|
+
# # }
|
82
|
+
#
|
83
|
+
# ==== Simplifications
|
84
|
+
#
|
85
|
+
# ConfigParser simplifies the OptionParser syntax for 'on'. ConfigParser does
|
86
|
+
# not support automatic conversion of values, gets rid of 'optional' arguments
|
87
|
+
# for options, and only supports a single description string. Hence:
|
88
|
+
#
|
89
|
+
# psr = ConfigParser.new
|
90
|
+
#
|
91
|
+
# # incorrect, raises error as this will look
|
92
|
+
# # like multiple descriptions are specified
|
93
|
+
# psr.on("--delay N",
|
94
|
+
# Float,
|
95
|
+
# "Delay N seconds before executing") # !> ArgumentError
|
96
|
+
#
|
97
|
+
# # correct
|
98
|
+
# psr.on("--delay N", "Delay N seconds before executing") do |value|
|
99
|
+
# value.to_f
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# # this ALWAYS requires the argument and raises
|
103
|
+
# # an error because multiple descriptions are
|
104
|
+
# # specified
|
105
|
+
# psr.on("-i", "--inplace [EXTENSION]",
|
106
|
+
# "Edit ARGV files in place",
|
107
|
+
# " (make backup if EXTENSION supplied)") # !> ArgumentError
|
108
|
+
#
|
109
|
+
# # correct
|
110
|
+
# psr.on("-i", "--inplace EXTENSION",
|
111
|
+
# "Edit ARGV files in place\n (make backup if EXTENSION supplied)")
|
112
|
+
#
|
113
|
+
#
|
6
114
|
class ConfigParser
|
7
115
|
class << self
|
8
116
|
# Splits and nests compound keys of a hash.
|
@@ -43,14 +151,18 @@ class ConfigParser
|
|
43
151
|
|
44
152
|
include Utils
|
45
153
|
|
46
|
-
# A hash of (switch, Option) pairs mapping
|
47
|
-
#
|
154
|
+
# A hash of (switch, Option) pairs mapping command line
|
155
|
+
# switches like '-s' or '--long' to the Option that
|
156
|
+
# handles them.
|
48
157
|
attr_reader :switches
|
49
158
|
|
159
|
+
# The most recent hash of configurations produced by parse.
|
50
160
|
attr_reader :config
|
51
161
|
|
162
|
+
# A hash of default configurations merged into parsed configs.
|
52
163
|
attr_reader :default_config
|
53
164
|
|
165
|
+
# Initializes a new ConfigParser and passes it to the block, if given.
|
54
166
|
def initialize
|
55
167
|
@options = []
|
56
168
|
@switches = {}
|
@@ -59,21 +171,27 @@ class ConfigParser
|
|
59
171
|
|
60
172
|
yield(self) if block_given?
|
61
173
|
end
|
174
|
+
|
175
|
+
# Returns the nested form of config (see ConfigParser.nest). Primarily
|
176
|
+
# useful when nested configurations have been added with add.
|
177
|
+
def nested_config
|
178
|
+
ConfigParser.nest(config)
|
179
|
+
end
|
62
180
|
|
63
|
-
# Returns an array of options registered with self.
|
181
|
+
# Returns an array of the options registered with self.
|
64
182
|
def options
|
65
183
|
@options.select do |opt|
|
66
184
|
opt.kind_of?(Option)
|
67
185
|
end
|
68
186
|
end
|
69
187
|
|
70
|
-
# Adds a separator string to self.
|
188
|
+
# Adds a separator string to self, used in to_s.
|
71
189
|
def separator(str)
|
72
190
|
@options << str
|
73
191
|
end
|
74
192
|
|
75
193
|
# Registers the option with self by adding opt to options and mapping
|
76
|
-
# the opt switches. Raises an error for conflicting
|
194
|
+
# the opt switches. Raises an error for conflicting switches.
|
77
195
|
def register(opt)
|
78
196
|
@options << opt unless @options.include?(opt)
|
79
197
|
|
@@ -87,36 +205,50 @@ class ConfigParser
|
|
87
205
|
|
88
206
|
opt
|
89
207
|
end
|
90
|
-
|
91
|
-
# Defines and registers a config with self.
|
92
|
-
def define(key, default_value=nil, options={})
|
93
|
-
# check for conflicts and register
|
94
|
-
if default_config.has_key?(key)
|
95
|
-
raise ArgumentError, "already set by a different option: #{key.inspect}"
|
96
|
-
end
|
97
|
-
default_config[key] = default_value
|
98
|
-
|
99
|
-
block = case options[:type]
|
100
|
-
when :switch then setup_switch(key, default_value, options)
|
101
|
-
when :flag then setup_flag(key, default_value, options)
|
102
|
-
when :list then setup_list(key, options)
|
103
|
-
when nil then setup_option(key, options)
|
104
|
-
when respond_to?("setup_#{options[:type]}")
|
105
|
-
send("setup_#{options[:type]}", key, default_value, options)
|
106
|
-
else
|
107
|
-
raise ArgumentError, "unsupported type: #{options[:type]}"
|
108
|
-
end
|
109
|
-
|
110
|
-
on(options, &block)
|
111
|
-
end
|
112
208
|
|
209
|
+
# Constructs an Option using args and registers it with self. Args may
|
210
|
+
# contain (in any order) a short switch, a long switch, and a description
|
211
|
+
# string. Either the short or long switch may signal that the option
|
212
|
+
# should take an argument by providing an argument name.
|
213
|
+
#
|
214
|
+
# psr = ConfigParser.new
|
215
|
+
#
|
216
|
+
# # this option takes an argument
|
217
|
+
# psr.on('-s', '--long ARG_NAME', 'description') do |value|
|
218
|
+
# # ...
|
219
|
+
# end
|
220
|
+
#
|
221
|
+
# # so does this one
|
222
|
+
# psr.on('-o ARG_NAME', 'description') do |value|
|
223
|
+
# # ...
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# # this option does not
|
227
|
+
# psr.on('-f', '--flag') do
|
228
|
+
# # ...
|
229
|
+
# end
|
230
|
+
#
|
231
|
+
# A switch-style option can be specified by prefixing the long switch with
|
232
|
+
# '--[no-]'. Switch options will pass true to the block for the positive
|
233
|
+
# form and false for the negative form.
|
234
|
+
#
|
235
|
+
# psr.on('--[no-]switch') do |value|
|
236
|
+
# # ...
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# Args may also contain a trailing hash defining all or part of the option:
|
240
|
+
#
|
241
|
+
# psr.on('-k', :long => '--key', :desc => 'description')
|
242
|
+
# # ...
|
243
|
+
# end
|
244
|
+
#
|
113
245
|
def on(*args, &block)
|
114
|
-
|
246
|
+
attributes = args.last.kind_of?(Hash) ? args.pop : {}
|
115
247
|
args.each do |arg|
|
116
248
|
# split switch arguments... descriptions
|
117
249
|
# still won't match as a switch even
|
118
250
|
# after a split
|
119
|
-
switch, arg_name = arg.split(' ', 2)
|
251
|
+
switch, arg_name = arg.kind_of?(String) ? arg.split(' ', 2) : arg
|
120
252
|
|
121
253
|
# determine the kind of argument specified
|
122
254
|
key = case switch
|
@@ -126,37 +258,158 @@ class ConfigParser
|
|
126
258
|
end
|
127
259
|
|
128
260
|
# check for conflicts
|
129
|
-
if
|
130
|
-
raise ArgumentError, "conflicting #{key} options: [#{
|
261
|
+
if attributes[key]
|
262
|
+
raise ArgumentError, "conflicting #{key} options: [#{attributes[key].inspect}, #{arg.inspect}]"
|
131
263
|
end
|
132
264
|
|
133
|
-
# set the option
|
265
|
+
# set the option attributes
|
134
266
|
case key
|
135
267
|
when :long, :short
|
136
|
-
|
137
|
-
|
268
|
+
attributes[key] = switch
|
269
|
+
attributes[:arg_name] = arg_name if arg_name
|
138
270
|
else
|
139
|
-
|
271
|
+
attributes[key] = arg
|
140
272
|
end
|
141
273
|
end
|
142
274
|
|
143
|
-
# check if
|
275
|
+
# check if a switch-style option is specified
|
144
276
|
klass = case
|
145
|
-
when
|
146
|
-
|
277
|
+
when attributes[:long].to_s =~ /^--\[no-\](.*)$/
|
278
|
+
attributes[:long] = "--#{$1}"
|
147
279
|
Switch
|
148
280
|
else
|
149
281
|
Option
|
150
282
|
end
|
151
283
|
|
152
284
|
# instantiate and register the new option
|
153
|
-
register klass.new(
|
285
|
+
register klass.new(attributes, &block)
|
286
|
+
end
|
287
|
+
|
288
|
+
# Defines and registers a config-style option with self. Define does not
|
289
|
+
# take a block; the default value will be added to config, and any parsed
|
290
|
+
# value will override the default. Normally the key will be turned into
|
291
|
+
# the long switch; specify an alternate long, a short, description, etc
|
292
|
+
# using attributes.
|
293
|
+
#
|
294
|
+
# psr = ConfigParser.new
|
295
|
+
# psr.define(:one, 'default')
|
296
|
+
# psr.define(:two, 'default', :long => '--long', :short => '-s')
|
297
|
+
#
|
298
|
+
# psr.parse("--one one --long two")
|
299
|
+
# psr.config # => {:one => 'one', :two => 'two'}
|
300
|
+
#
|
301
|
+
# Define support several types of configurations that define a special
|
302
|
+
# block to handle the values parsed from the command line. See the
|
303
|
+
# 'setup_<type>' methods in Utils. Any type with a corresponding setup
|
304
|
+
# method is valid:
|
305
|
+
#
|
306
|
+
# psr = ConfigParser.new
|
307
|
+
# psr.define(:flag, false, :type => :flag)
|
308
|
+
# psr.define(:switch, false, :type => :switch)
|
309
|
+
# psr.define(:list, [], :type => :list)
|
310
|
+
#
|
311
|
+
# psr.parse("--flag --switch --list one --list two --list three")
|
312
|
+
# psr.config # => {:flag => true, :switch => true, :list => ['one', 'two', 'three']}
|
313
|
+
#
|
314
|
+
# New, valid types may be added by implementing new setup_<type> methods
|
315
|
+
# following this pattern:
|
316
|
+
#
|
317
|
+
# module SpecialType
|
318
|
+
# def setup_special(key, default_value, attributes)
|
319
|
+
# # modify attributes if necessary
|
320
|
+
# attributes[:long] = "--#{key}"
|
321
|
+
# attributes[:arg_name] = 'ARG_NAME'
|
322
|
+
#
|
323
|
+
# # return a block handling the input
|
324
|
+
# lambda {|input| config[key] = input.reverse }
|
325
|
+
# end
|
326
|
+
# end
|
327
|
+
#
|
328
|
+
# psr = ConfigParser.new.extend SpecialType
|
329
|
+
# psr.define(:opt, false, :type => :special)
|
330
|
+
#
|
331
|
+
# psr.parse("--opt value")
|
332
|
+
# psr.config # => {:opt => 'eulav'}
|
333
|
+
#
|
334
|
+
# Define raises an error if key is already set by a different option.
|
335
|
+
def define(key, default_value=nil, attributes={})
|
336
|
+
# check for conflicts and register
|
337
|
+
if default_config.has_key?(key)
|
338
|
+
raise ArgumentError, "already set by a different option: #{key.inspect}"
|
339
|
+
end
|
340
|
+
default_config[key] = default_value
|
341
|
+
|
342
|
+
# ensure setup does not modifiy input attributes
|
343
|
+
attributes = attributes.dup
|
344
|
+
|
345
|
+
block = case attributes[:type]
|
346
|
+
when :switch then setup_switch(key, default_value, attributes)
|
347
|
+
when :flag then setup_flag(key, default_value, attributes)
|
348
|
+
when :list then setup_list(key, attributes)
|
349
|
+
when nil then setup_option(key, attributes)
|
350
|
+
else
|
351
|
+
if respond_to?("setup_#{attributes[:type]}")
|
352
|
+
send("setup_#{attributes[:type]}", key, default_value, attributes)
|
353
|
+
else
|
354
|
+
raise ArgumentError, "unsupported type: #{attributes[:type]}"
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
on(attributes, &block)
|
154
359
|
end
|
155
360
|
|
156
|
-
#
|
157
|
-
#
|
361
|
+
# Adds a hash of delegates (for example the configurations for a Configurable
|
362
|
+
# class) to self. Delegates will be sorted by their :declaration_order
|
363
|
+
# attribute, then added like:
|
364
|
+
#
|
365
|
+
# define(key, delegate.default, delegate.attributes)
|
366
|
+
#
|
367
|
+
# ==== Nesting
|
368
|
+
#
|
369
|
+
# When you nest Configurable classes, a special syntax is necessary to
|
370
|
+
# specify nested configurations in a flat format compatible with the
|
371
|
+
# command line. As such, nested delegates, ie delegates with a
|
372
|
+
# DelegateHash as a default value, are recursively added with their
|
373
|
+
# key as a prefix. For instance:
|
374
|
+
#
|
375
|
+
# delegate_hash = DelegateHash.new(:key => Delegate.new(:reader))
|
376
|
+
# delegates = {}
|
377
|
+
# delegates[:nest] = Delegate.new(:reader, :writer=, delegate_hash)
|
158
378
|
#
|
159
|
-
|
379
|
+
# psr = ConfigParser.new
|
380
|
+
# psr.add(delegates)
|
381
|
+
# psr.parse('--nest:key value')
|
382
|
+
#
|
383
|
+
# psr.config # => {'nest:key' => 'value'}
|
384
|
+
# psr.nested_config # => {'nest' => {'key' => 'value'}}
|
385
|
+
#
|
386
|
+
# Side note: The fact that all the keys end up as strings underscores
|
387
|
+
# the importance of having indifferent access for delegates. If you
|
388
|
+
# set use_indifferent_access(false), be prepared to symbolize nested
|
389
|
+
# keys as necessary.
|
390
|
+
#
|
391
|
+
def add(delegates, nesting=nil)
|
392
|
+
delegates.each_pair do |key, delegate|
|
393
|
+
key = nesting ? "#{nesting}:#{key}" : key
|
394
|
+
default = delegate.default(false)
|
395
|
+
|
396
|
+
if delegate.is_nest?
|
397
|
+
add(default.delegates, key)
|
398
|
+
else
|
399
|
+
define(key, default, delegate.attributes)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
# Parses options from argv in a non-destructive manner and returns an
|
405
|
+
# array of arguments remaining after options have been removed. If a
|
406
|
+
# string argv is provided, it will be splits into an array using
|
407
|
+
# Shellwords.
|
408
|
+
#
|
409
|
+
# A config may be provided to receive configurations; it will be set
|
410
|
+
# as self.config.
|
411
|
+
#
|
412
|
+
def parse(argv=ARGV, config={}, merge_default=true)
|
160
413
|
@config = config
|
161
414
|
argv = argv.kind_of?(String) ? Shellwords.shellwords(argv) : argv.dup
|
162
415
|
args = []
|
@@ -192,23 +445,20 @@ class ConfigParser
|
|
192
445
|
|
193
446
|
default_config.each_pair do |key, default|
|
194
447
|
config[key] = default unless config.has_key?(key)
|
195
|
-
end
|
448
|
+
end if merge_default
|
196
449
|
|
197
450
|
args
|
198
451
|
end
|
199
452
|
|
200
453
|
# Same as parse, but removes parsed args from argv.
|
201
|
-
def parse!(argv=ARGV, config={})
|
202
|
-
|
454
|
+
def parse!(argv=ARGV, config={}, merge_default=true)
|
455
|
+
result = parse(argv, config, merge_default)
|
456
|
+
argv.kind_of?(Array) ? argv.replace(result) : result
|
203
457
|
end
|
204
|
-
|
458
|
+
|
459
|
+
# Converts the options and separators in self into a help string suitable for
|
460
|
+
# display on the command line.
|
205
461
|
def to_s
|
206
|
-
comments = @options.collect do |option|
|
207
|
-
next unless option.respond_to?(:desc)
|
208
|
-
option.desc.kind_of?(Lazydoc::Comment) ? option.desc : nil
|
209
|
-
end.compact
|
210
|
-
Lazydoc.resolve_comments(comments)
|
211
|
-
|
212
462
|
@options.collect do |option|
|
213
463
|
option.to_s.rstrip
|
214
464
|
end.join("\n") + "\n"
|