class Configuration Version = '0.0.3' def Configuration.version() Version end Path = [ if defined? CONFIGURATION_PATH CONFIGURATION_PATH else ENV['CONFIGURATION_PATH'] end ].compact.flatten.join(File::PATH_SEPARATOR).split(File::PATH_SEPARATOR) Table = Hash.new Error = Class.new StandardError Import = Class.new Error module ClassMethods def for name, options = nil, &block name = name.to_s if Table.has_key?(name) if options or block configuration = Table[name] Table[name] = DSL.evaluate(configuration, options || {}, &block) else Table[name] end else if options or block Table[name] = new name, options || {}, &block else load name end end end def path *value return self.path = value.first unless value.empty? Path end def path= value Path.clear Path.replace [value].compact.flatten.join(File::PATH_SEPARATOR).split(File::PATH_SEPARATOR) end def load name name = name.to_s name = name + '.rb' unless name[%r/\.rb$/] key = name.sub %r/\.rb$/, '' load_path = $LOAD_PATH.dup begin $LOAD_PATH.replace(path + load_path) ::Kernel.load name ensure $LOAD_PATH.replace load_path end Table[key] end end send :extend, ClassMethods module InstanceMethods attr 'name' def initialize *argv, &block options = Hash === argv.last ? argv.pop : Hash.new @name = argv.shift DSL.evaluate(self, options, &block) end def method_missing m, *a, &b return(Pure[@__parent].send m, *a, &b) rescue super if @__parent super end end send :include, InstanceMethods class DSL instance_methods.each do |m| undef_method m unless m[%r/^__/] end Kernel.methods.each do |m| next if m[%r/^__/] module_eval <<-code def #{ m }(*a, &b) method_missing '#{ m }', *a, &b end code end def self.evaluate configuration, options = {}, &block dsl = new configuration Pure[dsl].instance_eval &block if block options.each{|key, value| Pure[dsl].send key, value} Pure[dsl].instance_eval{ @__configuration } end def initialize configuration, &block @__configuration = configuration @__singleton_class = class << @__configuration self end end def method_missing m, *a, &b if(a.empty? and b.nil?) return Pure[@__configuration].send(m, *a, &b) end if b raise ArgumentError unless a.empty? parent = @__configuration name = m.to_s configuration = if @__configuration.respond_to?(name) and Configuration === @__configuration.send(name) @__configuration.send name else Configuration.new name end Pure[configuration].instance_eval{ @__parent = parent } DSL.evaluate configuration, &b value = configuration end unless a.empty? value = a.size == 1 ? a.first : a end @__singleton_class.module_eval do define_method(m){ value } end end end class Pure Instance_Methods = Hash.new ::Object.instance_methods.each do |m| Instance_Methods[m.to_s] = ::Object.instance_method m undef_method m unless m[%r/^__/] end def method_missing m, *a, &b Instance_Methods[m.to_s].bind(@object).call(*a, &b) end def initialize object @object = object end def Pure.[] object new object end end end def Configuration(*a, &b) if a.empty? and b.nil? const_get :Configuration else Configuration.new(*a, &b) end end