rc 0.2.0 → 0.3.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.
@@ -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