196 lines
No EOL
5.2 KiB
Ruby
196 lines
No EOL
5.2 KiB
Ruby
|
|
|
|
module Comfpile
|
|
class ContextTag
|
|
attr_reader :tag, :taglist
|
|
|
|
def self.form_context(tag)
|
|
@known_tags ||= {}
|
|
|
|
case tag
|
|
when Symbol
|
|
tag_instance = @known_tags[tag]
|
|
|
|
return tag_instance unless tag_instance.nil?
|
|
|
|
tag_instance = ContextTag.new(tag)
|
|
tag_instance = (@known_tags[tag_instance] ||= tag_instance)
|
|
|
|
@known_tags[tag] ||= tag_instance
|
|
@known_tags[tag_instance.tag] ||= tag_instance
|
|
end
|
|
end
|
|
|
|
def initialize(tag)
|
|
process_tag(tag)
|
|
end
|
|
|
|
private def process_tag(tag)
|
|
case tag
|
|
when Symbol, String
|
|
@taglist = tag.to_s.split('_').uniq.sort
|
|
when Array
|
|
@taglist = tag.map(&:to_s).uniq.sort
|
|
end
|
|
|
|
@tag = @taglist.join('_').to_sym
|
|
@taghash = {}
|
|
@taglist.each do |tag|
|
|
@taghash[tag] = true
|
|
end
|
|
end
|
|
|
|
def include?(*tags)
|
|
tags = tags - @tag_array
|
|
|
|
tags.empy?
|
|
end
|
|
alias include_all? include?
|
|
|
|
def include_any?(*tags)
|
|
tags = tags & @tag_array
|
|
|
|
tags.empty?
|
|
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 =~ /(?<key>[^=]+)=(?<value>[^=]+)/
|
|
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 |