comfpile-old/lib/comfpile/context.rb
2023-08-12 20:39:22 +02:00

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