configurable 0.7.0 → 1.0.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.
- data/Help/Command Line.rdoc +141 -0
- data/Help/Config Syntax.rdoc +229 -0
- data/Help/Config Types.rdoc +143 -0
- data/{History → History.rdoc} +9 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +144 -0
- data/lib/configurable.rb +7 -270
- data/lib/configurable/class_methods.rb +344 -367
- data/lib/configurable/config_classes.rb +3 -0
- data/lib/configurable/config_classes/list_config.rb +26 -0
- data/lib/configurable/config_classes/nest_config.rb +50 -0
- data/lib/configurable/config_classes/scalar_config.rb +91 -0
- data/lib/configurable/config_hash.rb +87 -112
- data/lib/configurable/config_types.rb +6 -0
- data/lib/configurable/config_types/boolean_type.rb +22 -0
- data/lib/configurable/config_types/float_type.rb +11 -0
- data/lib/configurable/config_types/integer_type.rb +11 -0
- data/lib/configurable/config_types/nest_type.rb +39 -0
- data/lib/configurable/config_types/object_type.rb +58 -0
- data/lib/configurable/config_types/string_type.rb +15 -0
- data/lib/configurable/conversions.rb +91 -0
- data/lib/configurable/module_methods.rb +0 -1
- data/lib/configurable/version.rb +1 -5
- metadata +73 -30
- data/README +0 -207
- data/lib/cdoc.rb +0 -413
- data/lib/cdoc/cdoc_html_generator.rb +0 -38
- data/lib/cdoc/cdoc_html_template.rb +0 -42
- data/lib/config_parser.rb +0 -563
- data/lib/config_parser/option.rb +0 -108
- data/lib/config_parser/switch.rb +0 -44
- data/lib/config_parser/utils.rb +0 -177
- data/lib/configurable/config.rb +0 -97
- data/lib/configurable/indifferent_access.rb +0 -35
- data/lib/configurable/nest_config.rb +0 -78
- data/lib/configurable/ordered_hash_patch.rb +0 -85
- data/lib/configurable/utils.rb +0 -186
- data/lib/configurable/validation.rb +0 -768
data/lib/config_parser/option.rb
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
require 'config_parser/utils'
|
2
|
-
|
3
|
-
class ConfigParser
|
4
|
-
|
5
|
-
# Represents an option registered with ConfigParser.
|
6
|
-
class Option
|
7
|
-
|
8
|
-
# A format string used by to_s
|
9
|
-
LINE_FORMAT = "%-36s %-43s"
|
10
|
-
|
11
|
-
# The short switch mapping to self
|
12
|
-
attr_reader :short
|
13
|
-
|
14
|
-
# The long switch mapping to self
|
15
|
-
attr_reader :long
|
16
|
-
|
17
|
-
# The argument name printed by to_s. If arg_name
|
18
|
-
# is nil, no value will be parsed for self.
|
19
|
-
attr_reader :arg_name
|
20
|
-
|
21
|
-
# The description printed by to_s
|
22
|
-
attr_reader :desc
|
23
|
-
|
24
|
-
# The block called when one of the switches mapping
|
25
|
-
# to self is parse; block will receive the parsed
|
26
|
-
# argument if arg_name is specified.
|
27
|
-
attr_reader :block
|
28
|
-
|
29
|
-
# Initializes a new Option using attribute values for :long, :short,
|
30
|
-
# :arg_name, and :desc. The long and short values are transformed
|
31
|
-
# using Utils.longify and Utils.shortify, meaning both bare strings
|
32
|
-
# (ex 'opt', 'o') and full switches ('--opt', '-o') are valid.
|
33
|
-
def initialize(attributes={}, &block)
|
34
|
-
@short = Utils.shortify(attributes[:short])
|
35
|
-
@long = Utils.longify(attributes[:long])
|
36
|
-
@arg_name = attributes[:arg_name]
|
37
|
-
@desc = attributes[:desc]
|
38
|
-
@block = block
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns an array of non-nil switches mapping to self (ie [long, short]).
|
42
|
-
def switches
|
43
|
-
[long, short].compact
|
44
|
-
end
|
45
|
-
|
46
|
-
# Parse determines how an option is actually parsed from an argv. Parse
|
47
|
-
# recieves the switch mapping to self for cases in which it affects the
|
48
|
-
# outcome (see Switch). By default parse has two modes of action:
|
49
|
-
#
|
50
|
-
# ==== Argument-style option (arg_name is specified)
|
51
|
-
#
|
52
|
-
# If arg_name is set, then parse passes value to the block. If no value
|
53
|
-
# is specified, the next argument in argv is used instead. An error
|
54
|
-
# is raised if no value can be found.
|
55
|
-
#
|
56
|
-
# ==== Flag-style option (no arg_name is specified)
|
57
|
-
#
|
58
|
-
# In this case, parse simply calls the block. If a non-nil value is
|
59
|
-
# specified, parse raises an error.
|
60
|
-
#
|
61
|
-
def parse(switch, value, argv)
|
62
|
-
if arg_name
|
63
|
-
unless value
|
64
|
-
raise "no value provided for: #{switch}" if argv.empty?
|
65
|
-
value = argv.shift
|
66
|
-
end
|
67
|
-
block ? block.call(value) : value
|
68
|
-
else
|
69
|
-
raise "value specified for flag: #{switch}" if value
|
70
|
-
block ? block.call : nil
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Formats self as a help string for use on the command line.
|
75
|
-
def to_s
|
76
|
-
lines = Lazydoc::Utils.wrap(desc.to_s, 43)
|
77
|
-
|
78
|
-
header = " #{short_str}#{long_str} #{arg_name}"
|
79
|
-
header = header.length > 36 ? header.ljust(80) : (LINE_FORMAT % [header, lines.shift])
|
80
|
-
|
81
|
-
if lines.empty?
|
82
|
-
header
|
83
|
-
else
|
84
|
-
lines.collect! {|line| LINE_FORMAT % [nil, line] }
|
85
|
-
"#{header}\n#{lines.join("\n")}"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
# helper returning short formatted for to_s
|
92
|
-
def short_str # :nodoc:
|
93
|
-
case
|
94
|
-
when short && long
|
95
|
-
"#{short}, "
|
96
|
-
when short
|
97
|
-
"#{short}"
|
98
|
-
else
|
99
|
-
' '
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# helper returning long formatted for to_s
|
104
|
-
def long_str # :nodoc:
|
105
|
-
long
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
data/lib/config_parser/switch.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
class ConfigParser
|
2
|
-
|
3
|
-
# Switch represents a special type of Option where both a positive
|
4
|
-
# (--switch) and negative (--no-switch) version of long should
|
5
|
-
# map to self. A short may be specified for Switch; it will always
|
6
|
-
# be treated like the positive switch.
|
7
|
-
class Switch < Option
|
8
|
-
|
9
|
-
# The negative long switch, determined from long.
|
10
|
-
attr_reader :negative_long
|
11
|
-
|
12
|
-
# Initializes a new Switch. Raises an error if an arg_name is
|
13
|
-
# specified for self (as switches are intended to be boolean
|
14
|
-
# in nature), or if no long option is specified.
|
15
|
-
def initialize(options={})
|
16
|
-
super
|
17
|
-
raise ArgumentError, "arg_name specified for switch: #{arg_name}" if arg_name
|
18
|
-
raise ArgumentError, "no long specified" unless long
|
19
|
-
@negative_long = Utils.prefix_long(long, 'no-')
|
20
|
-
end
|
21
|
-
|
22
|
-
# Returns an array of non-nil switches mapping to self (ie
|
23
|
-
# [long, negative_long, short]).
|
24
|
-
def switches
|
25
|
-
[long, negative_long, short].compact
|
26
|
-
end
|
27
|
-
|
28
|
-
# Calls the block with false if the negative long is specified,
|
29
|
-
# or calls the block with true in all other cases. Raises an
|
30
|
-
# error if a value is specified.
|
31
|
-
def parse(switch, value, argv)
|
32
|
-
raise "value specified for switch: #{switch}" if value
|
33
|
-
value = (switch == negative_long ? false : true)
|
34
|
-
block ? block.call(value) : value
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
# helper returning long formatted for to_s
|
40
|
-
def long_str # :nodoc:
|
41
|
-
long ? Utils.prefix_long(long, '[no-]') : ''
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/config_parser/utils.rb
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
class ConfigParser
|
2
|
-
|
3
|
-
# A medly of methods used throughout the ConfigParser classes.
|
4
|
-
module Utils
|
5
|
-
module_function
|
6
|
-
|
7
|
-
# The option break argument
|
8
|
-
OPTION_BREAK = "--"
|
9
|
-
|
10
|
-
# Matches a nested long option, with or without a value
|
11
|
-
# (ex: '--opt', '--nested:opt', '--opt=value'). After
|
12
|
-
# the match:
|
13
|
-
#
|
14
|
-
# $1:: the switch
|
15
|
-
# $2:: the value
|
16
|
-
#
|
17
|
-
LONG_OPTION = /^(--[A-z].*?)(?:=(.*))?$/
|
18
|
-
|
19
|
-
# Matches a nested short option, with or without a value
|
20
|
-
# (ex: '-o', '-n:o', '-o=value'). After the match:
|
21
|
-
#
|
22
|
-
# $1:: the switch
|
23
|
-
# $2:: the value
|
24
|
-
#
|
25
|
-
SHORT_OPTION = /^(-[A-z](?::[A-z])*)(?:=(.*))?$/
|
26
|
-
|
27
|
-
# Matches the alternate syntax for short options
|
28
|
-
# (ex: '-n:ovalue', '-ovalue'). After the match:
|
29
|
-
#
|
30
|
-
# $1:: the switch
|
31
|
-
# $2:: the value
|
32
|
-
#
|
33
|
-
ALT_SHORT_OPTION = /^(-[A-z](?::[A-z])*)(.+)$/
|
34
|
-
|
35
|
-
# Turns the input string into a short-format option. Raises
|
36
|
-
# an error if the option does not match SHORT_OPTION. Nils
|
37
|
-
# are returned directly.
|
38
|
-
#
|
39
|
-
# shortify("-o") # => '-o'
|
40
|
-
# shortify(:o) # => '-o'
|
41
|
-
#
|
42
|
-
def shortify(str)
|
43
|
-
return nil if str == nil
|
44
|
-
|
45
|
-
str = str.to_s
|
46
|
-
str = "-#{str}" unless str[0] == ?-
|
47
|
-
unless str =~ SHORT_OPTION && $2 == nil
|
48
|
-
raise ArgumentError, "invalid short option: #{str}"
|
49
|
-
end
|
50
|
-
str
|
51
|
-
end
|
52
|
-
|
53
|
-
# Turns the input string into a long-format option. Underscores
|
54
|
-
# are converted to hyphens. Raises an error if the option does
|
55
|
-
# not match LONG_OPTION. Nils are returned directly.
|
56
|
-
#
|
57
|
-
# longify("--opt") # => '--opt'
|
58
|
-
# longify(:opt) # => '--opt'
|
59
|
-
# longify(:opt_ion) # => '--opt-ion'
|
60
|
-
#
|
61
|
-
def longify(str)
|
62
|
-
return nil if str == nil
|
63
|
-
|
64
|
-
str = str.to_s
|
65
|
-
str = "--#{str}" unless str =~ /^--/
|
66
|
-
str.gsub!(/_/, '-')
|
67
|
-
unless str =~ LONG_OPTION && $2 == nil
|
68
|
-
raise ArgumentError, "invalid long option: #{str}"
|
69
|
-
end
|
70
|
-
str
|
71
|
-
end
|
72
|
-
|
73
|
-
# Adds a prefix onto the last nested segment of a long option.
|
74
|
-
#
|
75
|
-
# prefix_long("--opt", 'no-') # => '--no-opt'
|
76
|
-
# prefix_long("--nested:opt", 'no-') # => '--nested:no-opt'
|
77
|
-
#
|
78
|
-
def prefix_long(switch, prefix, split_char=':')
|
79
|
-
switch = switch[2,switch.length-2] if switch =~ /^--/
|
80
|
-
switch = switch.split(split_char)
|
81
|
-
switch[-1] = "#{prefix}#{switch[-1]}"
|
82
|
-
"--#{switch.join(':')}"
|
83
|
-
end
|
84
|
-
|
85
|
-
# Infers the default long using key and adds it to attributes. Returns
|
86
|
-
# attributes.
|
87
|
-
#
|
88
|
-
# infer_long(:key, {}) # => {:long => '--key'}
|
89
|
-
#
|
90
|
-
def infer_long(key, attributes)
|
91
|
-
unless attributes.has_key?(:long)
|
92
|
-
attributes[:long] = "--#{key}"
|
93
|
-
end
|
94
|
-
|
95
|
-
attributes
|
96
|
-
end
|
97
|
-
|
98
|
-
# Infers the default argname from attributes[:long] and sets it in
|
99
|
-
# attributes. Returns attributes.
|
100
|
-
#
|
101
|
-
# infer_arg_name(:key, {:long => '--opt'}) # => {:long => '--opt', :arg_name => 'OPT'}
|
102
|
-
# infer_arg_name(:key, {}) # => {:arg_name => 'KEY'}
|
103
|
-
#
|
104
|
-
def infer_arg_name(key, attributes)
|
105
|
-
if attributes.has_key?(:arg_name)
|
106
|
-
return attributes
|
107
|
-
end
|
108
|
-
|
109
|
-
if long = attributes[:long]
|
110
|
-
long.to_s =~ /^(?:--)?(.*)$/
|
111
|
-
attributes[:arg_name] = $1.upcase
|
112
|
-
else
|
113
|
-
attributes[:arg_name] = key.to_s.upcase
|
114
|
-
end
|
115
|
-
|
116
|
-
attributes
|
117
|
-
end
|
118
|
-
|
119
|
-
# Attributes:
|
120
|
-
#
|
121
|
-
# :long the long key ("--key")
|
122
|
-
# :arg_name the argument name ("KEY")
|
123
|
-
#
|
124
|
-
def setup_option(key, attributes={})
|
125
|
-
infer_long(key, attributes)
|
126
|
-
infer_arg_name(key, attributes)
|
127
|
-
|
128
|
-
lambda {|value| config[key] = value }
|
129
|
-
end
|
130
|
-
|
131
|
-
# Attributes:
|
132
|
-
#
|
133
|
-
# :long the long key ("--key")
|
134
|
-
#
|
135
|
-
def setup_flag(key, default=true, attributes={})
|
136
|
-
infer_long(key, attributes)
|
137
|
-
|
138
|
-
lambda {config[key] = !default }
|
139
|
-
end
|
140
|
-
|
141
|
-
# Attributes:
|
142
|
-
#
|
143
|
-
# :long the long key ("--[no-]key")
|
144
|
-
#
|
145
|
-
def setup_switch(key, default=true, attributes={})
|
146
|
-
infer_long(key, attributes)
|
147
|
-
|
148
|
-
if attributes[:long].to_s =~ /^(?:--)?(\[no-\])?(.*)$/
|
149
|
-
attributes[:long] = "--[no-]#{$2}" unless $1
|
150
|
-
end
|
151
|
-
|
152
|
-
lambda {|value| config[key] = value }
|
153
|
-
end
|
154
|
-
|
155
|
-
# Attributes:
|
156
|
-
#
|
157
|
-
# :long the long key ("--key")
|
158
|
-
# :arg_name the argument name ("KEY")
|
159
|
-
# :split the split character
|
160
|
-
#
|
161
|
-
def setup_list(key, attributes={})
|
162
|
-
infer_long(key, attributes)
|
163
|
-
infer_arg_name(key, attributes)
|
164
|
-
|
165
|
-
split = attributes[:split]
|
166
|
-
n = attributes[:n]
|
167
|
-
|
168
|
-
lambda do |value|
|
169
|
-
array = (config[key] ||= [])
|
170
|
-
array.concat(split ? value.split(split) : [value])
|
171
|
-
if n && array.length > n
|
172
|
-
raise "too many assignments: #{key.inspect}"
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
data/lib/configurable/config.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
module Configurable
|
2
|
-
|
3
|
-
# Configs are used by ConfigHash to determine how to delegate read/write
|
4
|
-
# operations to a receiver. Configs also track metadata related to their
|
5
|
-
# presentation in various contexts.
|
6
|
-
class Config
|
7
|
-
class << self
|
8
|
-
|
9
|
-
# Determines if the value is duplicable. Non-duplicable values
|
10
|
-
# include nil, true, false, Symbol, Numeric, Method, Module, and
|
11
|
-
# any object that does not respond to dup.
|
12
|
-
def duplicable_value?(value)
|
13
|
-
case value
|
14
|
-
when nil, true, false, Symbol, Numeric, Method, Module then false
|
15
|
-
else value.respond_to?(:dup)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# The reader method called on a receiver during get
|
21
|
-
attr_reader :reader
|
22
|
-
|
23
|
-
# The writer method called on a receiver during set
|
24
|
-
attr_reader :writer
|
25
|
-
|
26
|
-
# An hash of metadata for self, often used to indicate how a config is
|
27
|
-
# presented in different contexts (ex on the command line, in a web form,
|
28
|
-
# or a desktop app).
|
29
|
-
attr_reader :attributes
|
30
|
-
|
31
|
-
# Initializes a new Config.
|
32
|
-
def initialize(reader, writer="#{reader}=", default=nil, attributes={}, init=true, dup=nil)
|
33
|
-
self.reader = reader
|
34
|
-
self.writer = writer
|
35
|
-
@default = default
|
36
|
-
@attributes = attributes
|
37
|
-
@init = init
|
38
|
-
@dup = dup.nil? ? Config.duplicable_value?(default) : dup
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns the default value. If duplicate is specified and the default
|
42
|
-
# may be duplicated (see Config.duplicable_value?) then a duplicate
|
43
|
-
# of the default is returned.
|
44
|
-
def default(duplicate=true)
|
45
|
-
duplicate && @dup ? @default.dup : @default
|
46
|
-
end
|
47
|
-
|
48
|
-
# Returns the value for the specified attribute, or default if the
|
49
|
-
# attribute is unspecified.
|
50
|
-
def [](key, default=nil)
|
51
|
-
attributes.has_key?(key) ? attributes[key] : default
|
52
|
-
end
|
53
|
-
|
54
|
-
# Calls reader on the receiver and returns the result.
|
55
|
-
def get(receiver)
|
56
|
-
receiver.send(reader)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Calls writer on the receiver with the value.
|
60
|
-
def set(receiver, value)
|
61
|
-
receiver.send(writer, value)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Sets the default value on the receiver. Normally this method is only
|
65
|
-
# called during Configurable#initialize_config, and only then when init?
|
66
|
-
# returns true.
|
67
|
-
def init(receiver)
|
68
|
-
receiver.send(writer, default)
|
69
|
-
end
|
70
|
-
|
71
|
-
# Returns true or false as specified in new. True indicates that this
|
72
|
-
# delegate is allowed to initialize values on the receiver during
|
73
|
-
# Configurable#initialize_config.
|
74
|
-
def init?
|
75
|
-
@init
|
76
|
-
end
|
77
|
-
|
78
|
-
# Returns an inspection string.
|
79
|
-
def inspect
|
80
|
-
"#<#{self.class}:#{object_id} reader=#{reader} writer=#{writer} default=#{default.inspect} >"
|
81
|
-
end
|
82
|
-
|
83
|
-
protected
|
84
|
-
|
85
|
-
# Sets the reader for self, assuring the reader is not nil.
|
86
|
-
def reader=(value) # :nodoc:
|
87
|
-
raise ArgumentError, "reader may not be nil" if value.nil?
|
88
|
-
@reader = value.to_sym
|
89
|
-
end
|
90
|
-
|
91
|
-
# Sets the writer for self, assuring the writer is not nil.
|
92
|
-
def writer=(value) # :nodoc:
|
93
|
-
raise ArgumentError, "writer may not be nil" if value.nil?
|
94
|
-
@writer = value.to_sym
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Configurable
|
2
|
-
|
3
|
-
# Implements AGET and ASET methods that symbolize string keys, in effect
|
4
|
-
# producing indifferent access. IndifferentAccess is intended to extend
|
5
|
-
# a Hash.
|
6
|
-
#
|
7
|
-
# Note that the indifference produced by this module is very thin indeed.
|
8
|
-
# Strings may still be used as keys through store/fetch, and
|
9
|
-
# existing string keys are not changed in any way. Nonetheless,
|
10
|
-
# these methods are sufficient for Configurable and ConfigHash.
|
11
|
-
module IndifferentAccess
|
12
|
-
|
13
|
-
# Symbolizes string keys and calls super.
|
14
|
-
def [](key)
|
15
|
-
super(convert(key))
|
16
|
-
end
|
17
|
-
|
18
|
-
# Symbolizes string keys and calls super.
|
19
|
-
def []=(key, value)
|
20
|
-
super(convert(key), value)
|
21
|
-
end
|
22
|
-
|
23
|
-
# Ensures duplicates use indifferent access.
|
24
|
-
def dup
|
25
|
-
super().extend IndifferentAccess
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
# a helper to convert strings to symbols
|
31
|
-
def convert(key) # :nodoc:
|
32
|
-
key.kind_of?(String) ? key.to_sym : key
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|