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.
Files changed (38) hide show
  1. data/Help/Command Line.rdoc +141 -0
  2. data/Help/Config Syntax.rdoc +229 -0
  3. data/Help/Config Types.rdoc +143 -0
  4. data/{History → History.rdoc} +9 -0
  5. data/MIT-LICENSE +1 -1
  6. data/README.rdoc +144 -0
  7. data/lib/configurable.rb +7 -270
  8. data/lib/configurable/class_methods.rb +344 -367
  9. data/lib/configurable/config_classes.rb +3 -0
  10. data/lib/configurable/config_classes/list_config.rb +26 -0
  11. data/lib/configurable/config_classes/nest_config.rb +50 -0
  12. data/lib/configurable/config_classes/scalar_config.rb +91 -0
  13. data/lib/configurable/config_hash.rb +87 -112
  14. data/lib/configurable/config_types.rb +6 -0
  15. data/lib/configurable/config_types/boolean_type.rb +22 -0
  16. data/lib/configurable/config_types/float_type.rb +11 -0
  17. data/lib/configurable/config_types/integer_type.rb +11 -0
  18. data/lib/configurable/config_types/nest_type.rb +39 -0
  19. data/lib/configurable/config_types/object_type.rb +58 -0
  20. data/lib/configurable/config_types/string_type.rb +15 -0
  21. data/lib/configurable/conversions.rb +91 -0
  22. data/lib/configurable/module_methods.rb +0 -1
  23. data/lib/configurable/version.rb +1 -5
  24. metadata +73 -30
  25. data/README +0 -207
  26. data/lib/cdoc.rb +0 -413
  27. data/lib/cdoc/cdoc_html_generator.rb +0 -38
  28. data/lib/cdoc/cdoc_html_template.rb +0 -42
  29. data/lib/config_parser.rb +0 -563
  30. data/lib/config_parser/option.rb +0 -108
  31. data/lib/config_parser/switch.rb +0 -44
  32. data/lib/config_parser/utils.rb +0 -177
  33. data/lib/configurable/config.rb +0 -97
  34. data/lib/configurable/indifferent_access.rb +0 -35
  35. data/lib/configurable/nest_config.rb +0 -78
  36. data/lib/configurable/ordered_hash_patch.rb +0 -85
  37. data/lib/configurable/utils.rb +0 -186
  38. data/lib/configurable/validation.rb +0 -768
@@ -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
@@ -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
@@ -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
@@ -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