rc 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ # Config Class
2
+
3
+ The Config class encapsulates a single config entry. Every Config instance has a `command`, `feature`,
4
+ and `profile` atribute, as well as a procedure.
5
+
6
+ config = RC::Config.new('foo', :profile=>'bar') do
7
+ 'example'
8
+ end
9
+
10
+ config.command #=> 'foo'
11
+ config.feature #=> 'foo'
12
+ config.profile #=> 'bar'
13
+ config.to_proc.call #=> 'example'
14
+
@@ -0,0 +1,51 @@
1
+ # Configuration
2
+
3
+ The Configuration class handle evaluation of a project configuration file.
4
+
5
+ rc = RC::Configuration.new
6
+
7
+ We can use the `#instance_eval` method to evaluate a configuration for our
8
+ demonstration.
9
+
10
+ rc.evaluate(<<-HERE)
11
+ config :sample1 do
12
+ "block code"
13
+ end
14
+ HERE
15
+
16
+ Evaluation of a configuration file, populate the Confection.config instance.
17
+
18
+ sample = rc.configurations.last
19
+ sample.command #=> 'sample1'
20
+ sample.profile #=> 'default'
21
+ sample.class #=> RC::Config
22
+
23
+ A profile can be used as a means fo defining multiple configurations
24
+ for a single tool. This can be done by setting the second argument to
25
+ a Symbol.
26
+
27
+ rc.evaluate(<<-HERE)
28
+ config :sample2, :profile=>'opt1' do
29
+ "block code"
30
+ end
31
+ HERE
32
+
33
+ sample = rc.configurations.last
34
+ sample.command #=> 'sample2'
35
+ sample.profile #=> 'opt1'
36
+
37
+ Or it can be done by using a `profile` block.
38
+
39
+ rc.evaluate(<<-HERE)
40
+ profile :opt1 do
41
+ config :sample2 do
42
+ "block code"
43
+ end
44
+ end
45
+ HERE
46
+
47
+ sample = rc.configurations.last
48
+ sample.command #=> 'sample2'
49
+ sample.profile #=> 'opt1'
50
+
51
+
@@ -0,0 +1,48 @@
1
+ # Importing
2
+
3
+ ## Configuration Importing
4
+
5
+ Configurations can be imported from another project using the `:from` option.
6
+
7
+ rc = RC::Configuration.new
8
+
9
+ rc.config :qed, :profile=>'example', :from=>'test'
10
+
11
+ rc.to_a.size.assert == 1
12
+
13
+ The configuration can also be imported from a different profile.
14
+
15
+ rc.config :qed, :profile=>:coverage, :from=>['test', :profile=>'simplecov']
16
+
17
+ rc.to_a.size.assert == 2
18
+
19
+ Although it will very rarely be of use, it may also be imported from another
20
+ feature or command too.
21
+
22
+ rc.config :example, :from=>['test', :command=>'sample']
23
+
24
+ Imported configurations can also be augmented via a block.
25
+
26
+ rc = RC::Configuration.new
27
+
28
+ rc.config :qed, :from=>['test', :profile=>'simplecov'] do
29
+ # additional code here
30
+ end
31
+
32
+ rc.to_a.size.assert == 2
33
+
34
+ Technically this last form just creates two configurations for the same
35
+ tool and profile, but the ultimate effect is the same.
36
+
37
+ ## Script Importing
38
+
39
+ Library files can be imported directly into configuration blocks via the
40
+ `#import` method.
41
+
42
+ rc.config :example do
43
+ import "fruitbasket/example.rb"
44
+ end
45
+
46
+ This looks up the file via the `finder` gem and then evals it in the context
47
+ of the config block.
48
+
@@ -0,0 +1,39 @@
1
+ # Interface
2
+
3
+ The main means of workin with RC's API are the RC class methods,
4
+ collectively called the Inteface.
5
+
6
+ Let's say we have a configuration file `.ruby` containing:
7
+
8
+ config :example do
9
+ "example config"
10
+ end
11
+
12
+ config :example, :profile=>:something do
13
+ "example config using profile"
14
+ end
15
+
16
+ To get the configuration of the current project --relative to the
17
+ current working directory, use the `configuration` method.
18
+
19
+ RC.configuration
20
+
21
+ The configuration properties of the current project can be
22
+ had via the `properties` method.
23
+
24
+ RC.properties
25
+
26
+ The profile names can be looked up for any given tool via the `profile_names`
27
+ method.
28
+
29
+ RC.profile_names(:example) #=> ['default', 'something']
30
+
31
+ The number of feature configurations in the current project can be
32
+ had via the `size` method.
33
+
34
+ RC.configuration.size #=> 1
35
+
36
+ A list of all configuration entries can be had by calling #to_a.
37
+
38
+ RC.configuration.to_a.size #=> 2
39
+
@@ -0,0 +1 @@
1
+ require 'ae'
@@ -0,0 +1,8 @@
1
+ require 'rc/api'
2
+
3
+ When 'configuration file `(((\S+)))` containing' do |slots, text|
4
+ RC.clear! #configurations.clear
5
+ fname = [slots].flatten.first # temporary transition to new QED
6
+ File.open(fname, 'w'){ |f| f << text }
7
+ end
8
+
@@ -0,0 +1,10 @@
1
+ # Setup the fixtures.
2
+
3
+ dir = File.dirname(__FILE__) + '/fixture'
4
+ Dir.entries(dir).each do |file|
5
+ next if file == '.' or file == '..'
6
+ path = File.join(dir, file)
7
+ next if File.directory?(path)
8
+ FileUtils.install(path, Dir.pwd)
9
+ end
10
+
@@ -0,0 +1,11 @@
1
+ # exmaple configuration file
2
+
3
+ config :example do
4
+ "example config"
5
+ end
6
+
7
+ config :example, :profile=>:data do |ex|
8
+ ex.name = 'Tommy'
9
+ ex.age = 42
10
+ end
11
+
@@ -0,0 +1,7 @@
1
+ # Usage: qed -r ./spec/cov
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ coverage_dir 'log/coverage'
5
+ #add_group "Label", "lib/qed/directory"
6
+ end
7
+
@@ -0,0 +1,8 @@
1
+ # This script is for use in the RUBYOPT, e.g. RUBYOPT="-rc".
2
+ #
3
+ # My apologies to the author of the `c` gem. If it helps,
4
+ # I think it would be better if the functionaility of the
5
+ # `c` gem were provided via other gems, e.g. the `github`
6
+ # gem.
7
+
8
+ require 'rc'
@@ -0,0 +1,10 @@
1
+ # RC - Runtime Configuration
2
+ # Copyright (c) 2011 Rubyworks
3
+
4
+ # Runtime Configuration for Ruby.
5
+ #
6
+ module RC
7
+ require 'rc/api'
8
+ autoconfigure
9
+ end
10
+
@@ -0,0 +1,4 @@
1
+ # This file is simply a shortcut to `interface.rb`.
2
+
3
+ require 'rc/interface'
4
+
@@ -0,0 +1,305 @@
1
+ module RC
2
+
3
+ # Config encapsulates a single configuration entry as defined in a project's
4
+ # ruby rc file. A config consists of a possible `command`, `feature`,
5
+ # `profile` and `onload` flag.
6
+ #
7
+ # If `command` or `feature` are nil, then the configuration applies to all
8
+ # commands and/or features.
9
+ #
10
+ # If profile is `nil` it automatically becomes `default`, which is the
11
+ # profile used when no profile is specified.
12
+ #
13
+ class Config
14
+
15
+ #
16
+ # Initialize Config instance. Config instances are per-configuration,
17
+ # which means they are associated with one and only one config entry.
18
+ #
19
+ # @param [#to_s] target
20
+ # The command or feature name. (optional)
21
+ #
22
+ # @param [Hash] properties
23
+ # Any additional properties associated with the config entry.
24
+ #
25
+ def initialize(*args, &block)
26
+ properties = (Hash === args.last ? args.pop : {})
27
+ target = args.first
28
+
29
+ @property = {:command=>nil, :feature=>nil, :profile=>'default'}
30
+
31
+ if target
32
+ @property[:command] = target.to_s
33
+ @property[:feature] = target.to_s
34
+ end
35
+
36
+ @block = block
37
+
38
+ properties.each do |k, v|
39
+ property(k,v)
40
+ end
41
+ end
42
+
43
+ #
44
+ # Get/set property.
45
+ #
46
+ def property(name, value=ArgumentError)
47
+ if value == ArgumentError
48
+ get(name)
49
+ else
50
+ set(name, value)
51
+ end
52
+ end
53
+
54
+ #
55
+ # The feature being configured.
56
+ #
57
+ def feature
58
+ @property[:feature]
59
+ end
60
+
61
+ #
62
+ # The name of command being configured.
63
+ #
64
+ def command
65
+ @property[:command]
66
+ end
67
+
68
+ # @todo Deprecate #tool alias?
69
+ alias :tool :command
70
+
71
+ #
72
+ # The name of the profile to which this configuration belongs.
73
+ #
74
+ def profile
75
+ @property[:profile]
76
+ end
77
+
78
+ #
79
+ # The library from which this configuration derives.
80
+ #
81
+ def from
82
+ @property[:from]
83
+ end
84
+
85
+ #
86
+ #
87
+ #
88
+ def onload?
89
+ @property[:onload]
90
+ end
91
+
92
+ #
93
+ # Most configurations are scripted. In those cases the
94
+ # `@block` attributes holds the Proc instance, otherwise
95
+ # it is `nil`.
96
+ #
97
+ attr :block
98
+
99
+ #
100
+ # IDEA: Presets would be processed first and not require the underlying feature.
101
+ #
102
+ #def preset?
103
+ # @property[:preset]
104
+ #end
105
+
106
+ #
107
+ # The arity of the configuration procedure.
108
+ #
109
+ # @return [Fixnum] number of arguments
110
+ #
111
+ def arity
112
+ @block ? @block.arity : 0
113
+ end
114
+
115
+ #
116
+ # Require the feature.
117
+ #
118
+ def require_feature
119
+ begin
120
+ require feature
121
+ rescue LoadError
122
+ #warn "No such feature -- `#{feature}'"
123
+ end
124
+ end
125
+
126
+ #
127
+ # Call the configuration procedure.
128
+ #
129
+ def call(*args)
130
+ block.call(*args) if block
131
+ end
132
+
133
+ #
134
+ # Returns underlying block.
135
+ #
136
+ def to_proc
137
+ block
138
+ end
139
+
140
+ ##
141
+ ## Convert block into a Hash.
142
+ ##
143
+ ## @return [Hash]
144
+ ##
145
+ #def to_h
146
+ # HashBuilder.new(&self).to_h
147
+ #end
148
+
149
+ #
150
+ # Copy the configuration with alterations.
151
+ #
152
+ # @param [Hash] alt
153
+ # Alternate values for configuration attributes.
154
+ #
155
+ # @return [Config] copied config
156
+ #
157
+ def copy(alt={})
158
+ tool = @property[:feature] || @property[:command]
159
+ copy = self.class.new(tool, @property.dup, &@block)
160
+ alt.each do |k,v|
161
+ copy.property(k, v)
162
+ end
163
+ copy
164
+ end
165
+
166
+ #
167
+ # Match config against tool and/or profile names.
168
+ #
169
+ # @return [Boolean]
170
+ #
171
+ def match?(*args)
172
+ props = Hash === args.last ? args.pop : {}
173
+
174
+ if target = args.shift
175
+ props[:command] = target.to_s
176
+ props[:feature] = target.to_s
177
+ end
178
+
179
+ if props[:profile]
180
+ props[:profile] = (props[:profile] || :default).to_s
181
+ end
182
+
183
+ props.each do |k,v|
184
+ pv = property(k)
185
+ return false unless (pv.nil? || pv == v)
186
+ end
187
+
188
+ return true
189
+ end
190
+
191
+ #
192
+ # Does the given `feature` match the config's feature?
193
+ #
194
+ # @return [Boolean]
195
+ #
196
+ def feature?(feature=RC.current_feature)
197
+ return true if self.feature.nil?
198
+ self.feature == feature.to_s
199
+ end
200
+
201
+ #
202
+ # Does the given `command` match the config's command?
203
+ #
204
+ # @return [Boolean]
205
+ #
206
+ def command?(command=RC.current_command)
207
+ return true if self.command.nil?
208
+ self.command == command.to_s
209
+ end
210
+ alias_method :tool, :command?
211
+
212
+ #
213
+ # Does the given `profile` match the config's profile?
214
+ #
215
+ # @return [Boolean]
216
+ #
217
+ def profile?(profile=RC.current_profile)
218
+ self.profile == (profile || 'default').to_s
219
+ end
220
+
221
+ #
222
+ # @todo The feature argument might not be needed.
223
+ #
224
+ #def configure(feature)
225
+ # return false if self.feature != feature
226
+ #
227
+ # if setup = RC.setup(feature)
228
+ # setup.call(self)
229
+ # else
230
+ # block.call if command?
231
+ # end
232
+ #end
233
+
234
+ ##
235
+ ## Ruby 1.9 defines #inspect as #to_s, ugh.
236
+ ##
237
+ #def inspect
238
+ # "#<#{self.class.name}:#{object_id} @tool=%s @profile=%s>" % [tool.inspect, profile.inspect]
239
+ #end
240
+
241
+ #
242
+ # Does the configuration apply?
243
+ #
244
+ # @return [Boolean]
245
+ #
246
+ def apply_to_command?
247
+ return false if onload?
248
+ return false unless command? if command
249
+ return false unless profile? if profile
250
+ return true
251
+ end
252
+ alias_method :apply_to_tool?, :apply_to_command?
253
+
254
+ def apply_to_feature?
255
+ return false unless onload?
256
+ return false unless command? if command
257
+ return false unless profile? if profile
258
+ return true
259
+ end
260
+
261
+ private
262
+
263
+ #
264
+ # Get property.
265
+ #
266
+ def get(name)
267
+ @property[name.to_sym]
268
+ end
269
+
270
+ #
271
+ # Set property.
272
+ #
273
+ def set(name, value)
274
+ case name.to_sym
275
+ when :command
276
+ self.command = value
277
+ when :tool # deprecate ?
278
+ self.command = value
279
+ when :feature
280
+ self.feature = value
281
+ when :profile
282
+ self.profile = value
283
+ else
284
+ @property[name.to_sym] = value
285
+ end
286
+ end
287
+
288
+ #
289
+ def command=(name)
290
+ @property[:command] = name ? name.to_s : nil
291
+ end
292
+
293
+ #
294
+ def feature=(path)
295
+ @property[:feature] = path ? path.to_s : nil
296
+ end
297
+
298
+ #
299
+ def profile=(name)
300
+ @property[:profile] = name ? name.to_s : 'default'
301
+ end
302
+
303
+ end
304
+
305
+ end