lib/distil/configurable.rb in distil-0.13.6 vs lib/distil/configurable.rb in distil-0.14.0.b

- old
+ new

@@ -1,168 +1,79 @@ -module Kernel - - def Boolean(string) - return true if string == true || string =~ /^true$/i - return false if string == false || string.nil? || string =~ /^false$/i - raise ArgumentError.new("invalid value for Boolean: \"#{string}\"") - end - -end - -class ValidationError < StandardError -end - - -class Configurable - attr_reader :options +module Distil - @@options= {} - - def get_option(name) - return nil if !@options.respond_to?(name) - value=@options[name] - value.respond_to?(:value_of) ? value.value_of(self) : value - end + class Configurable - def get_options(settings=nil, parent=nil) - keys= @@options.keys - values= @@options.map { |k,v| convert_type(v[:type], v[:value]) } - - s= @options ? @options : (@options=Struct.new(*keys).new(*values)) - return s if !settings - - setting_keys= settings.keys.map { |key| key.to_s } - - @@options.each { |key, value| - - intersect= value[:aliases] & setting_keys - next if !parent && intersect.empty? - - if (intersect.empty?) - s[key]= parent[key] - next - end + @@config_aliases={} + def self.alias_config_key(original, key_alias) + @@config_aliases[key_alias.to_s]= original.to_s + end - if (intersect.length>1) - raise ArgumentError, "Multiple variants for #{key.to_s} defined: #{intersect.join(", ")}" - end - - setting_key= intersect[0] - setting_value= settings[setting_key] - settings.delete(setting_key) + def key_for_alias(key_alias) + key_alias= key_alias.to_s.gsub("-", "_").gsub(" ", "_") + @@config_aliases[key_alias] || key_alias + end - # decide if any type conversions are needed... - setting_value= convert_type(value[:type], setting_value) - - if (value.has_key?(:valid_values) && !value[:valid_values].include?(setting_value)) - raise ValidationError, "Invalid value for '#{setting_key}': #{setting_value}" - end - - s[key]= setting_value + class ConfigDsl - } - - @extras.merge!(settings) - s - end - - # option name, [type], [default], [options] - def self.option(name, *rest) - - name_string= name.to_s - - info= { - :aliases=>[name_string, name_string.gsub('_', '-'), name_string.gsub('_', ' ')].uniq - } - - arg= rest.shift - - if (arg.is_a?(Class) || arg==URI) - info[:type]= arg - info[:value]= nil - arg= rest.shift - end - - if (!arg.nil? && !arg.is_a?(Hash)) - info[:value]= arg - info[:type]= arg.class if !info.has_key?(:type) - arg= rest.shift - end - - # handle named arguments - if (arg.is_a?(Hash)) - if arg.has_key?(:aliases) - info[:aliases].concat(arg[:aliases]).uniq! - arg.delete(:aliases) + def initialize(hash) + @hash= hash + @used= Set.new end - info.merge!(arg) - end - if @@options.has_key?(name) - orig= @@options[name] - if orig.has_key?(:type) && info.has_key?(:type) && info[:type]!=orig[:type] - raise ArgumentError, "Redefinition of option #{self}##{name} changes type" + def with_each(key) + case when @hash.include?(key.to_sym) + value= @hash[key.to_sym] + when @hash.include?(key.to_s) + value= @hash[key.to_s] + else + return + end + + value= value.split(",").map { |s| s.strip } if value.is_a?(String) + value.each { |v| yield v } + @used << key.to_s end - if orig.has_key?(:value) && !info[:value].nil? && info[:value]!=orig[:value] - raise ArgumentError, "Redefinition of option #{name} changes value" + + def with(key) + case when @hash.include?(key.to_sym) + yield @hash[key.to_sym] + when @hash.include?(key.to_s) + yield @hash[key.to_s] + else + return + end + @used << key.to_s end - orig[:type]||=info[:type] - orig[:value]||=info[:value] - orig[:aliases].concat(info[:aliases]).uniq! - else - @@options[name]= info + + def used?(key) + @used.include?(key.to_s) + end + end - self.send :define_method, name do - value=@options[name] - value.respond_to?(:value_of) ? value.value_of(self) : value + def configure_with(hash) + new_hash= {} + hash.each { |key, value| + new_hash[key_for_alias(key)]= value + } + + dsl= ConfigDsl.new(new_hash) + yield dsl if block_given? + + new_hash.each { |key, value| + next if dsl.used?(key.to_s) + + key= key_for_alias(key) + case + when self.respond_to?("#{key}=") + self.send "#{key}=", value + when self.respond_to?(key) && 0!=self.method(key).arity + self.send key, value + else + self.instance_variable_set("@#{key}", value) + end + } end - self.send :define_method, "#{name}=" do |value| - @options[name]= convert_type(@@options[name][:type], value) - end - - # self.send :protected, "#{name}=".to_s - end - - def initialize(options={}, parent=nil) - @extras= Hash.new - if (parent.is_a?(Configurable)) - parent_options= parent.options - end - get_options(options, parent_options) - end - private - - def convert_type(type, value) - case - when FalseClass==type || TrueClass==type - Boolean(value) - when Array==type - value.is_a?(String) ? value.split(/\s*,\s*/) : value - when Fixnum==type - value.to_i - when nil==type || NilClass==type - value - when String==type - value ? value.to_s : nil; - when value.nil? - value - when URI==type - URI.parse(value) - else - if type.respond_to?(:from_options) - type.from_options(value, self) - else - puts "type=#{type} value=#{value}" - type.new(value) - end - end - end - -end - -Dir.glob("#{File.dirname(__FILE__)}/configurable/*.rb") { |file| - require file -} +end \ No newline at end of file