module Comfpile class ContextKey attr_reader :provider, :context_hash, :context_symbol def initialize(provider, ctx_hash, ctx_symbol) @provider = provider @context_hash = ctx_hash @context_symbol = ctx_symbol end def to_s "CTX[" + @context_symbol.to_s + "]" end end # # This class represents the configuration of a specific context. # It has two main jobs: # To provide functions to set up and merge configuration options # from the various tags given to it, and # to give reader options for the various config options. # # Most importantly, it contains mechanisms for safely setting up # configurations and flagging issues. # class ContextConfig attr_reader :context_tag attr_reader :config_options def initialize(context_tag, parent) @context_tag = context_tag @seeder_blocks = [] @config_options = nil end def add_seeder_block(priority, &block) @seeder_blocks << { priority: priority, block: block } end def resolve_key(key) if key.is_a? Array return key.map {|k| k.to_sym } elsif key.is_a? String return key.split('.').map {|k| k.to_sym } elsif key.is_a? Symbol return resolve_key(key.to_s) end end def [](key) @config_options&.dig(*resolve_key(key)) end def []=(key, value) key = resolve_key(key) current_hash = (@config_options ||= {}) key[0..-2].each do |key| current_hash = (current_hash[key] ||= {}) next if current_hash.is_a? Hash raise ArgumentError, "Attempted to set child-parameter of another parameter!" end return @provider.provide_context(new_keys) end def to_s "CTX[" + @context_symbol.to_s + "]" end alias inspect to_s end class ContextKeyProvider def initialize @known_context_keys = Hash.new end def symbol_to_keys(symbol) raise ArgumentError, 'Input symbol needs to be a Symbol!' unless symbol.is_a? Symbol out_keys = Hash.new symbol.to_s.split(';').each do |key| if key =~ /(?[^=]+)=(?[^=]+)/ out_keys[$~['key'].to_sym] = $~['value'].to_s else out_keys[key.to_sym] = true end end out_keys end def sanitize_keys(keys) out_keys = Hash.new keys.each do |key, value| if value.is_a? TrueClass out_keys[key.to_sym] = true elsif (not value.nil?) and (not value.is_a? FalseClass) out_keys[key.to_sym] = value.to_s end end out_keys end def keys_to_symbol(keys) raise ArgumentError, 'Keys needs to be a Hash!' unless keys.is_a? Hash keys.keys.sort.map do |key| value = keys[key] if value.is_a? TrueClass key.to_s elsif value.is_a? FalseClass nil else "#{key}=#{value}" end end.compact.join(';').to_sym end def provide_context(ctx) return ctx if ctx.is_a? ContextKey orig_ctx = ctx return @known_context_keys[ctx] if @known_context_keys.include? ctx ctx = symbol_to_keys(ctx) if ctx.is_a? Symbol ctx = sanitize_keys(ctx) ctx_symbol = keys_to_symbol(ctx) if @known_context_keys.include? ctx existing_ctx = @known_context_keys[ctx] @known_context_keys[orig_ctx] = existing_ctx return existing_ctx end new_ctx = ContextKey.new(self, ctx, ctx_symbol) @known_context_keys[ctx] = new_ctx @known_context_keys[ctx_symbol] = new_ctx end end end