module AdventureRL
class Settings
include Helpers::Error
attr_reader :content
# Initialize Settings with either a string representing
# a path to a YAML file, or a hash with your settings.
def initialize arg
if ([String, Pathname].include? arg.class)
@file = Pathname.new arg
validate_file_exists @file
@content = get_file_content(@file).keys_to_sym
elsif (arg.is_a? Hash)
@content = arg.keys_to_sym
elsif (arg.is_a? Settings)
@content = arg.get
end
end
# Returns the settings, following the structure of the passed keys.
# Similar to Hash#dig
def get *keys
current_content = @content
keys.each do |key|
key = key.to_sym if (key.is_a? String)
if (current_content.is_a?(Hash) && !current_content[key].nil?)
current_content = current_content[key]
else
current_content = nil
break
end
end
return current_content
end
# Merge self Settings content with other_settings Settings content or Hash.
# Can pass unlimited optional arguments as keys.
# If keys are given, then it will only merge the content
# from the keys keys for both Settings instances.
# Returns a new Settings object where the values of the keys keys
# are its settings content.
def merge other_settings, *keys
merged_settings = nil
if (other_settings.is_a? Settings)
merged_settings = Settings.new get(*keys).merge(other_settings.get(*keys))
elsif (other_settings.is_a? Hash)
merged_settings = Settings.new get(*keys).merge(other_settings)
else
error(
"Argument needs to be an instance of `AdventureRL::Settings' or a Hash",
"but got a `#{other_settings.class.name}'"
)
end
return merged_settings
end
def each
return get.each
end
private
def validate_file_exists file = @file
error_no_file file unless (file_exists? file)
end
def get_file_content file = @file
file = Pathname.new file unless (file.is_a? Pathname)
begin
return YAML.load_file(file.to_path) || {}
rescue
begin
return JSON.parse(file.read, symbolize_names: true)
rescue
error "Couldn't load settings file: '#{file.to_path}'", 'Is it a valid YAML or JSON file?'
end
end
end
end
end