require 'yaml'
module Scide
# Complete scide configuration as an object graph.
class Config
# The file from which the configuration is normally loaded.
# This defaults to $HOME/.scide/config.yml.
DEFAULT_CONFIG_FILE = File.join File.expand_path('~'), '.scide', 'config.yml'
# The file from which this configuration will be loaded.
attr_accessor :file
# GNU Screen options. Accessible after calling #load!.
attr_reader :screen
# The global configuration. Accessible after calling #load!.
attr_reader :global
# The project definitions (windows, option overrides, etc). Accessible
# after calling #load!.
attr_reader :projects
# Returns an empty configuration.
#
# ==== Arguments
# * file - The file from which to load the configuration. If not
# given, this defaults to DEFAULT_CONFIG_FILE.
def initialize file = nil
@file = file.try(:to_s) || DEFAULT_CONFIG_FILE
end
# Loads this configuration. This will read from #file and parse the contents
# as YAML. Configuration elements can then be retrieved with #global,
# #projects and #screen.
#
# ==== Errors
# * config_not_found - #file does not exist.
# * config_not_readable - #file cannot be read by the user running scide.
# * malformed_config - #file contains malformed YAML.
# * invalid_config - #file contains invalid configuration (see README).
# * unexpected - #file could not be read.
def load!
Scide.fail :config_not_found, "ERROR: expected to find configuration at #{@file}" unless File.exists? @file
Scide.fail :config_not_readable, "ERROR: configuration #{@file} is not readable" unless File.readable? @file
begin
raw_config = File.open(@file, 'r').read
rescue StandardError => err
Scide.fail :unexpected, "ERROR: could not read configuration #{@file}"
end
begin
@config = YAML::load raw_config
rescue StandardError => err
Scide.fail :malformed_config, "ERROR: could not parse configuration #{@file}\n #{err}"
end
invalid_config 'configuration must be a hash' unless @config.kind_of? Hash
# laziness
@config = HashWithIndifferentAccess.new @config
invalid_config 'screen configuration must be a hash' unless @config[:screen].nil? or @config[:screen].kind_of?(Hash)
invalid_config 'projects configuration must be a hash' unless @config[:projects].nil? or @config[:projects].kind_of?(Hash)
begin
@screen = @config[:screen]
@global = Scide::Global.new @config[:global]
@projects = @config[:projects].inject(HashWithIndifferentAccess.new) do |memo,obj|
memo[obj[0]] = Scide::Project.new @global, obj[0], obj[1]; memo
end
rescue ArgumentError => err
invalid_config err
end
end
private
# Causes scide to fail with an invalid_config error (see Scide#fail).
# Builds a complete error message containing the full path to the
# configuration file and the given message.
def invalid_config msg
Scide.fail :invalid_config, "ERROR: configuration #{@file} is invalid.\n #{msg}"
end
end
end