lib/ruby-conf.rb in ruby-conf-1.4.4 vs lib/ruby-conf.rb in ruby-conf-2.0.0

- old
+ new

@@ -1,144 +1,154 @@ # # -# @author Hollin Wilkins & Curtis Schofield -class RubyConf - @@configs = {} +# @author Hollin Wilkins & Curtis Schofield & Mason Bo-bay-son +module Magic + attr_accessor :__rc_chain + def __rc_gather() "#{to_s}#{__rc_chain.nil? ? "" : " #{__rc_chain.__rc_gather}"}" end +end +class RubyConf < Object + @@__rc_configs = {} + class Config - attr_reader :attributes + attr_reader :__rc_attributes, :__rc_parent, :__rc_name, :__rc_chains, :__rc_locked - def initialize - @attributes = {} + def __rc_root() __rc_parent ? __rc_parent.__rc_root : self end + + def initialize(name = nil, parent = nil, &block) + @__rc_locked, @__rc_attributes, @__rc_chains, @__rc_parent = false, {}, [], parent + @__rc_name = name.to_sym if name + instance_eval(&block) if block_given? + __rc_lock end - def [](name) - value = @attributes[name.to_sym] + def __rc_lock + @__rc_locked = true + @__rc_attributes.each_value { |value| value.__rc_lock if value.is_a?(Config) } + self + end - if value.is_a?(Proc) - value.call + def [](name, args = nil) + value = @__rc_attributes[name.to_sym] + value.is_a?(Proc) ? __rc_root.instance_exec(*args, &value) : value + end + + def __rc_copy(o) + if o.is_a?(Hash) + o.inject({}) { |copy, (key, val)| copy[key] = __rc_copy(val); copy } + elsif o.is_a?(Array) + o.inject([]) { |copy, i| copy << __rc_copy(i); copy } else - value + o end end - def []=(name,value) - @attributes[name.to_sym] = value - end + def to_a() [self] end - def inherit(name, parent) - self[name] = Config.new - self[name].attributes.merge! parent.attributes.clone + def []=(name, value) + @__rc_attributes[name.to_sym] = value end - def []=(name,value) - @attributes[name.to_sym] = value + def __rc_set_default(conf, key, value) + if conf.__rc_attributes.key?(key) + if value.is_a?(Config) + sub = conf.__rc_attributes[key] + value.__rc_attributes.each do |k, v| + __rc_set_default(sub, k, v) + end + end + else + conf.__rc_attributes[key] = value + end end def method_missing(name, *args, &block) + name = name.to_sym + options = args.last.is_a?(Hash) ? args.last : {} + if block_given? - _inherit(name, args) - _set_config_with_block(name,block) - return - end + if options.key?(:inherits) + self[name] = [*options[:inherits]].inject(Config.new(name, self, &block)) do |conf, inherited| + inherited = self[inherited.to_sym] unless inherited.is_a?(Config) + __rc_copy(inherited.__rc_attributes).each do |key, value| + __rc_set_default(conf, key, value) + end + conf + end + elsif self[name].is_a?(Config) + self[name].instance_eval(&block) + else + self[name] = Config.new(name, self, &block) + end - super if 0 == args.size && !@attributes.has_key?(name.to_sym) + while (chain = self[name].__rc_chains.pop) + self[name][chain] = chain.__rc_chain.nil? ? "" : chain.__rc_chain.__rc_gather + end - _set_or_get_attribute(name, args) - end - - def respond_to?(name) - if @attributes.has_key? name.to_sym - true - elsif @parent - @parent.respond_to?(name) else - super - end - end - private + super if @__rc_locked && args.size == 0 && !@__rc_attributes.key?(name) - def _set_or_get_attribute(name, args) - case(args.size) - when 0 - # config.something - # => 'value' - self[name] - when 1 - # config.something "value" - self[name] = args.first - else - # config.something "value", "value2" - self[name] = args + if !@__rc_attributes.key?(name) && (args.size == 0 || args.first.is_a?(Magic)) + str = name.to_s + str.extend(Magic) + if args.first.is_a?(Magic) + str.__rc_chain = args.first + @__rc_chains.delete_if { |a| a.equal? args.first } + end + @__rc_chains << str + return str + end + + if args.empty? + self[name] + else + args = args.size == 1 ? args.first : args + (@__rc_locked && __rc_attributes[name.to_sym].is_a?(Proc)) ? self[name, args] : self[name] = args + end + end - end - def _update_config_with_block(name,block) - self[name].instance_eval(&block) end - def _new_config_with_block(name, block) - self[name] = RubyConf.define(&block) + def respond_to?(name) + super || @__rc_attributes.key?(name) || @__rc_parent.respond_to?(name) end - def _set_config_with_block(name, block) - if self[name].is_a?(Config) - _update_config_with_block(name,block) - else - _new_config_with_block(name,block) + def __rc_build_string(depth = 0) + str = "" + str += "[#@__rc_name]\n" unless @__rc_parent + str += "\n" + @__rc_attributes.keys.map{|k| k.to_s }.sort.each do |key| + value = self[key] + str += " " * depth + str += "#{key}:" + str += value.is_a?(Config) ? value.__rc_build_string(depth+1) : " #{value}\n" + str += "\n" unless depth > 0 end + str end + def to_s() __rc_build_string end + def to_str() to_s end - def _inherit(name, args) - if args.size > 0 && args.first.is_a?(Hash) && args.first.has_key?(:inherits) - inherit name, args.first[:inherits] - end - end + def __rc_build_inspect() "#{"[#@__rc_name] " unless @__rc_parent}#{@__rc_attributes.keys.map {|k| k.to_s }.sort.map { |key| "#{key}: #{self[key].is_a?(Config) ? "{ #{self[key].__rc_build_inspect} }" : self[key].inspect}" }.join(", ")}" end + def inspect() __rc_build_inspect end end - # Define a configuration: - # - # RubyConf.define "monkey" , :as => 'MyBonobo' do - # has_legs true - # number_arms 2 - # number_legs 2 - # name 'Nancy Drew' - # age 34 - # number_of_bananas_eaten lambda { - # BanannaChomper.lookup("nancy.bananas").count - # } - # end - # - # - # @param [Symbol] namespace of the config - # @param [Hash] list of options. e.g. :as => ConstantName - def self.define(name = nil , options = {}, &block) - config = Config.new - config.instance_eval &block - @@configs[name.to_sym] = config unless name.nil? - if options.has_key? :as - Object.const_set(options[:as].to_s.to_sym, config) + def self.define(name = nil, options = {}, &block) + config = Config.new(name, &block) + @@__rc_configs[name.to_sym] = config unless name.nil? + + const = options.fetch(:as, name) + if const && const.to_s[/^[A-Z]/] + const = const.to_sym + Object.const_set(const, config) if !Object.const_defined?(const) || Object.const_get(const).is_a?(Config) end config end - def self.[](name) - @@configs[name.to_sym] - end + def self.[](name) @@__rc_configs[name.to_sym] end - def self.method_missing(name, *args, &block) - if @@configs.has_key? name.to_sym - @@configs[name.to_sym] - else - super - end - end + def self.method_missing(name, *args) @@__rc_configs[name.to_sym] end - def self.respond_to?(name) - if @@configs.has_key? name.to_sym - true - else - super - end - end + def self.respond_to?(name) @@__rc_configs.key?(name.to_sym) end end