configurable 0.7.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,11 @@
1
+ module Configurable
2
+ module ConfigTypes
3
+ class FloatType < ObjectType
4
+ matches Float
5
+
6
+ def cast(input)
7
+ Float(input)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Configurable
2
+ module ConfigTypes
3
+ class IntegerType < ObjectType
4
+ matches Integer
5
+
6
+ def cast(input)
7
+ Integer(input)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ module Configurable
2
+ module ConfigTypes
3
+ class NestType < ObjectType
4
+ class << self
5
+ def init(&block)
6
+ define_method(:init, &block) if block
7
+ self
8
+ end
9
+ end
10
+ matches Hash
11
+
12
+ attr_reader :configurable
13
+
14
+ def initialize(attrs={})
15
+ @configurable = attrs[:configurable]
16
+
17
+ unless configurable.respond_to?(:config) && configurable.class.respond_to?(:configs)
18
+ raise ArgumentError, "invalid configurable: #{configurable.inspect}"
19
+ end
20
+
21
+ super
22
+ end
23
+
24
+ def init(input)
25
+ obj = configurable.dup
26
+ obj.config.merge!(input)
27
+ obj
28
+ end
29
+
30
+ def cast(input)
31
+ configurable.class.configs.import(input)
32
+ end
33
+
34
+ def uncast(value)
35
+ configurable.class.configs.export(value)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,58 @@
1
+ module Configurable
2
+ module ConfigTypes
3
+ class ObjectType
4
+ class << self
5
+ attr_reader :matchers
6
+
7
+ def inherited(base) # :nodoc:
8
+ unless base.instance_variable_defined?(:@matchers)
9
+ base.instance_variable_set(:@matchers, matchers.dup)
10
+ end
11
+ end
12
+
13
+ def subclass(*matchers, &caster)
14
+ subclass = Class.new(self)
15
+ subclass.matches(*matchers)
16
+ subclass.cast(&caster)
17
+ subclass
18
+ end
19
+
20
+ def cast(&block)
21
+ define_method(:cast, &block) if block
22
+ self
23
+ end
24
+
25
+ def uncast(&block)
26
+ define_method(:uncast, &block) if block
27
+ self
28
+ end
29
+
30
+ def errors(&block)
31
+ define_method(:errors, &block) if block
32
+ self
33
+ end
34
+
35
+ def matches(*matchers)
36
+ @matchers = matchers
37
+ self
38
+ end
39
+
40
+ def matches?(value)
41
+ matchers.any? {|matcher| matcher === value }
42
+ end
43
+ end
44
+ matches()
45
+
46
+ def initialize(attrs={})
47
+ end
48
+
49
+ def cast(input)
50
+ input
51
+ end
52
+
53
+ def uncast(value)
54
+ value
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,15 @@
1
+ module Configurable
2
+ module ConfigTypes
3
+ class StringType < ObjectType
4
+ matches String
5
+
6
+ def cast(input)
7
+ String(input)
8
+ end
9
+
10
+ def uncast(value)
11
+ value.to_s
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,91 @@
1
+ require 'configurable/config_classes'
2
+ require 'config_parser'
3
+
4
+ module Configurable
5
+
6
+ # A set of methods used to convert various inputs based on a hash of (key,
7
+ # Config) pairs. Extend the hash and then use the methods.
8
+ module Conversions
9
+ include ConfigTypes
10
+
11
+ # Initializes and returns a ConfigParser generated using the configs for
12
+ # self. Arguments given to parser are passed to the ConfigParser
13
+ # initializer.
14
+ def to_parser(*args, &block)
15
+ parser = ConfigParser.new(*args, &block)
16
+ traverse do |nesting, config|
17
+ next if config[:hidden] == true || nesting.any? {|nest| nest[:hidden] == true }
18
+
19
+ nest_keys = nesting.collect {|nest| nest.key }
20
+ long, short = nesting.collect {|nest| nest.name }.push(config.name).join(':'), nil
21
+ long, short = short, long if long.length == 1
22
+
23
+ guess_attrs = {
24
+ :long => long,
25
+ :short => short
26
+ }
27
+
28
+ config_attrs = {
29
+ :key => config.key,
30
+ :nest_keys => nest_keys,
31
+ :default => config.default,
32
+ :callback => lambda {|value| config.type.cast(value) }
33
+ }
34
+
35
+ attrs = guess_attrs.merge(config.metadata).merge(config_attrs)
36
+ parser.on(attrs)
37
+ end
38
+
39
+ parser.sort_opts!
40
+ parser
41
+ end
42
+
43
+ # Returns a hash of the default values for each config in self.
44
+ def to_default
45
+ default = {}
46
+ each_pair do |key, config|
47
+ default[key] = config.default
48
+ end
49
+ default
50
+ end
51
+
52
+ def import(source, target={})
53
+ each_value do |config|
54
+ name = config.name
55
+
56
+ if source.has_key?(name)
57
+ target[config.key] = config.cast(source[name])
58
+ end
59
+ end
60
+
61
+ target
62
+ end
63
+
64
+ def export(source, target={})
65
+ each_value do |config|
66
+ key = config.key
67
+
68
+ if source.has_key?(key)
69
+ target[config.name] = config.uncast(source[key])
70
+ end
71
+ end
72
+
73
+ target
74
+ end
75
+
76
+ # Yields each config in configs to the block with nesting, after appened
77
+ # self to nesting.
78
+ def traverse(nesting=[], &block)
79
+ each_value do |config|
80
+ if config.type.kind_of?(NestType)
81
+ nesting.push config
82
+ configs = config.type.configurable.class.configs
83
+ configs.traverse(nesting, &block)
84
+ nesting.pop
85
+ else
86
+ yield(nesting, config)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,4 +1,3 @@
1
- require 'lazydoc'
2
1
  require 'configurable/class_methods'
3
2
 
4
3
  module Configurable
@@ -1,7 +1,3 @@
1
1
  module Configurable
2
- MAJOR = 0
3
- MINOR = 7
4
- TINY = 0
5
-
6
- VERSION="#{MAJOR}.#{MINOR}.#{TINY}"
2
+ VERSION = '1.0.0'
7
3
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configurable
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 23
5
+ prerelease:
5
6
  segments:
7
+ - 1
6
8
  - 0
7
- - 7
8
9
  - 0
9
- version: 0.7.0
10
+ version: 1.0.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Simon Chiang
@@ -14,63 +15,101 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-05-02 00:00:00 -06:00
18
+ date: 2011-07-12 00:00:00 -06:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: lazydoc
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
- - - ">="
27
+ - - ~>
26
28
  - !ruby/object:Gem::Version
29
+ hash: 15
27
30
  segments:
28
31
  - 1
29
32
  - 0
30
- - 0
31
- version: 1.0.0
33
+ version: "1.0"
32
34
  type: :runtime
33
35
  version_requirements: *id001
34
- description:
35
- email: simon.a.chiang@gmail.com
36
+ - !ruby/object:Gem::Dependency
37
+ name: config_parser
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ - 5
48
+ - 4
49
+ version: 0.5.4
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: bundler
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 15
61
+ segments:
62
+ - 1
63
+ - 0
64
+ version: "1.0"
65
+ type: :development
66
+ version_requirements: *id003
67
+ description: Configurable adds methods to declare class configurations. Configurations are inheritable, delegate to methods, and have hash-like access. Configurable constructs configs such that they easily map to config files, web forms, and the command line.
68
+ email:
69
+ - simon.a.chiang@gmail.com
36
70
  executables: []
37
71
 
38
72
  extensions: []
39
73
 
40
74
  extra_rdoc_files:
41
75
  - MIT-LICENSE
42
- - README
43
- - History
76
+ - README.rdoc
77
+ - History.rdoc
78
+ - Help/Command Line.rdoc
79
+ - Help/Config Syntax.rdoc
80
+ - Help/Config Types.rdoc
44
81
  files:
45
- - lib/cdoc.rb
46
- - lib/cdoc/cdoc_html_generator.rb
47
- - lib/cdoc/cdoc_html_template.rb
48
- - lib/config_parser.rb
49
- - lib/config_parser/option.rb
50
- - lib/config_parser/switch.rb
51
- - lib/config_parser/utils.rb
52
82
  - lib/configurable.rb
53
83
  - lib/configurable/class_methods.rb
54
- - lib/configurable/config.rb
84
+ - lib/configurable/config_classes.rb
85
+ - lib/configurable/config_classes/list_config.rb
86
+ - lib/configurable/config_classes/nest_config.rb
87
+ - lib/configurable/config_classes/scalar_config.rb
55
88
  - lib/configurable/config_hash.rb
56
- - lib/configurable/indifferent_access.rb
89
+ - lib/configurable/config_types.rb
90
+ - lib/configurable/config_types/boolean_type.rb
91
+ - lib/configurable/config_types/float_type.rb
92
+ - lib/configurable/config_types/integer_type.rb
93
+ - lib/configurable/config_types/nest_type.rb
94
+ - lib/configurable/config_types/object_type.rb
95
+ - lib/configurable/config_types/string_type.rb
96
+ - lib/configurable/conversions.rb
57
97
  - lib/configurable/module_methods.rb
58
- - lib/configurable/nest_config.rb
59
- - lib/configurable/ordered_hash_patch.rb
60
- - lib/configurable/utils.rb
61
- - lib/configurable/validation.rb
62
98
  - lib/configurable/version.rb
63
99
  - MIT-LICENSE
64
- - README
65
- - History
100
+ - README.rdoc
101
+ - History.rdoc
102
+ - Help/Command Line.rdoc
103
+ - Help/Config Syntax.rdoc
104
+ - Help/Config Types.rdoc
66
105
  has_rdoc: true
67
- homepage: http://tap.rubyforge.org/configurable
106
+ homepage: http://github.com/thinkerbot/configurable
68
107
  licenses: []
69
108
 
70
109
  post_install_message:
71
110
  rdoc_options:
72
111
  - --main
73
- - README
112
+ - README.rdoc
74
113
  - -S
75
114
  - -N
76
115
  - --title
@@ -78,23 +117,27 @@ rdoc_options:
78
117
  require_paths:
79
118
  - lib
80
119
  required_ruby_version: !ruby/object:Gem::Requirement
120
+ none: false
81
121
  requirements:
82
122
  - - ">="
83
123
  - !ruby/object:Gem::Version
124
+ hash: 3
84
125
  segments:
85
126
  - 0
86
127
  version: "0"
87
128
  required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
88
130
  requirements:
89
131
  - - ">="
90
132
  - !ruby/object:Gem::Version
133
+ hash: 3
91
134
  segments:
92
135
  - 0
93
136
  version: "0"
94
137
  requirements: []
95
138
 
96
- rubyforge_project: tap
97
- rubygems_version: 1.3.6
139
+ rubyforge_project:
140
+ rubygems_version: 1.6.2
98
141
  signing_key:
99
142
  specification_version: 3
100
143
  summary: configurable
data/README DELETED
@@ -1,207 +0,0 @@
1
- = Configurable[http://tap.rubyforge.org/configurable]
2
-
3
- Class configurations that map to the command line.
4
-
5
- == Description
6
-
7
- Configurable allows the declaration of class configurations. Configurations
8
- are inheritable, delegate to methods, and have hash-like access. Configurable
9
- maps configurations to the command line through ConfigParser and is used by
10
- the Tap[http://tap.rubyforge.org] framework.
11
-
12
- Check out these links for development and bug tracking.
13
-
14
- * Website[http://tap.rubyforge.org/configurable]
15
- * Github[http://github.com/bahuvrihi/configurable/tree/master]
16
- * {Google Group}[http://groups.google.com/group/ruby-on-tap]
17
-
18
- ==== Minimal Example
19
-
20
- Include Configurable and declare configurations using the config method.
21
- Configs now have accessors and initialize with the default value.
22
-
23
- class ConfigClass
24
- include Configurable
25
- config :key, 'default', :short => 'k' # a sample config
26
- end
27
-
28
- c = ConfigClass.new
29
- c.key # => 'default'
30
- c.key = 'new value'
31
- c.config[:key] # => 'new value'
32
-
33
- Use a ConfigParser to parse configurations from the command line. Non-class
34
- options may be defined with (mostly) the same syntax as {OptionParser}[http://www.ruby-doc.org/core/classes/OptionParser.html]:
35
-
36
- parser = ConfigParser.new
37
-
38
- # add class configurations
39
- parser.add(ConfigClass.configurations)
40
-
41
- # define an option a-la OptionParser
42
- parser.on '-s', '--long ARGUMENT', 'description' do |value|
43
- parser[:long] = value
44
- end
45
-
46
- parser.parse "one two --key value -s VALUE three"
47
- # => ['one', 'two', 'three']
48
-
49
- parser.config
50
- # => {
51
- # :key => 'value',
52
- # :long => 'VALUE'
53
- # }
54
-
55
- "\n" + parser.to_s
56
- # => %Q{
57
- # -k, --key KEY a sample config
58
- # -s, --long ARGUMENT description
59
- # }
60
-
61
- == Usage
62
-
63
- The config method is used to declare class configurations. A block may be
64
- provided to validate/transform inputs; many standard validations are available
65
- through the 'c' method (an alias for the
66
- {Validation}[link:classes/Configurable/Validation.html] module).
67
-
68
- class ConfigClass
69
- include Configurable
70
-
71
- # basic #
72
-
73
- config :key, 'default' # a simple config
74
- config :flag, false, &c.flag # a flag config
75
- config :switch, false, &c.switch # a --[no-]switch config
76
- config :num, 10, &c.integer # integer only
77
-
78
- # fancy #
79
-
80
- config :range, 1..10, &c.range # specifies a range
81
- config :select, 'a', &c.select('a','b') # value must be 'a' or 'b'
82
- config :list, [], &c.list # allows a list of entries
83
-
84
- # custom #
85
-
86
- config :upcase, 'default' do |value| # custom transformation
87
- value.upcase
88
- end
89
-
90
- config :alt, 'default', # alternative flags
91
- :short => 's',
92
- :long => 'long',
93
- :arg_name => 'CUSTOM'
94
-
95
- # Initializes a new instance, setting the overriding configs.
96
- def initialize(config={})
97
- initialize_config(config)
98
- end
99
- end
100
-
101
- ConfigParser uses the config declarations to parse configurations and to make
102
- a documented help string:
103
-
104
- parser = ConfigParser.new
105
- parser.add(ConfigClass.configurations)
106
-
107
- parser.parse "a b --key=value --flag --no-switch --num 8 c"
108
- # => ['a', 'b', 'c']
109
-
110
- parser.config
111
- # => {
112
- # :key => 'value',
113
- # :flag => true,
114
- # :switch => false,
115
- # :num => '8',
116
- # :range => 1..10,
117
- # :select => 'a',
118
- # :list => [],
119
- # :upcase => 'default',
120
- # :alt => 'default'
121
- # }
122
-
123
- "\n" + parser.to_s
124
- # => %Q{
125
- # --key KEY a simple config
126
- # --flag a flag config
127
- # --[no-]switch a --[no-]switch config
128
- # --num NUM integer only
129
- # --range RANGE specifies a range
130
- # --select SELECT value must be 'a' or 'b'
131
- # --list LIST allows a list of entries
132
- # --upcase UPCASE custom transformation
133
- # -s, --long CUSTOM alternative flags
134
- # }
135
-
136
- Configurable classes typically call initialize_config to set configurations
137
- during initialization. The validation/transformation blocks are called as
138
- configurations are set. Notice how the :num and :upcase configs are translated
139
- on the instance:
140
-
141
- c = ConfigClass.new(parser.config)
142
- c.config.to_hash
143
- # => {
144
- # :key => 'value',
145
- # :flag => true,
146
- # :switch => false,
147
- # :num => 8, # no longer a string
148
- # :range => 1..10,
149
- # :select => 'a',
150
- # :list => [],
151
- # :upcase => 'DEFAULT', # no longer downcase
152
- # :alt => 'default'
153
- # }
154
-
155
- Configurations automatically generate accessors (the blocks are basically
156
- writer methods), and may be accessed through the config object. Configurations
157
- are validated every time they are set, regardless of whether they are set
158
- through an accessor or config.
159
-
160
- c.upcase # => 'DEFAULT'
161
-
162
- c.config[:upcase] = 'neW valuE'
163
- c.upcase # => 'NEW VALUE'
164
-
165
- c.upcase = 'fiNal Value'
166
- c.config[:upcase] # => 'FINAL VALUE'
167
-
168
- c.select = 'b' # ok
169
- c.select = 'c' # !> ValidationError
170
- c.config[:select] = 'c' # !> ValidationError
171
-
172
- By default config treats string and symbol keys identically, making YAML an
173
- obvious choice for configuration files.
174
-
175
- yaml_str = %Q{
176
- key: a new value
177
- flag: false
178
- range: 1..100
179
- }
180
-
181
- c.reconfigure(YAML.load(yaml_str))
182
- c.config.to_hash
183
- # => {
184
- # :key => 'a new value',
185
- # :flag => false,
186
- # :switch => false,
187
- # :num => 8,
188
- # :range => 1..100,
189
- # :select => 'b',
190
- # :list => [],
191
- # :upcase => 'FINAL VALUE',
192
- # :alt => 'default'
193
- # }
194
-
195
- See the Configurable module for more details.
196
-
197
- == Installation
198
-
199
- Configurable is available as a gem on Gemcutter[http://gemcutter.org/gems/configurable].
200
-
201
- % gem install configurable
202
-
203
- == Info
204
-
205
- Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com]
206
- License:: {MIT-Style}[link:files/MIT-LICENSE.html]
207
-