module Scide
# Scide configuration for one project.
class Project
# The project key in the projects configuration hash.
attr_reader :key
# The path where the project is located. See {#initialize}.
attr_reader :path
# Project-specific options. Can be used by commands. See {#initialize}.
attr_reader :options
# The GNU Screen windows of this project.
attr_reader :windows
# The name or index of the window that should be displayed by default for
# this project (defaults to the last window).
attr_reader :default_window
# Returns a project configuration.
#
# If not given in the project hash, {#path} is built by joining
# the global path and key.
#
# == Arguments
# * global - The global configuration.
# * key - The key identifying the project. This is the
# key in the projects hash.
# * contents - The project hash.
#
# == Project Options
#
# {#options} is built by merging the options given in the project
# hash with the global options.
#
# The following default options are added if not given:
# * name - Defaults to the project key.
# * path - The path where the project is located.
def initialize global, key, contents
raise ArgumentError, "project '#{key}' must be a hash" unless contents.kind_of? Hash
raise ArgumentError, "windows of project '#{key}' must be an array" unless contents[:windows].kind_of?(Array)
raise ArgumentError, "options of project '#{key}' must be a hash" unless contents[:options].nil? or contents[:options].kind_of?(Hash)
@key = key
# path defaults to project key
@path = contents[:path].try(:to_s) || key.to_s
unless path.match /^\//
# if not absolute
if global.path
# expand from global directory
@path = File.join global.path, @path
else
# or from home directory
@path = File.join File.expand_path('~'), @path
end
end
@options = global.options.dup
@options[:name] = key
@options[:path] = @path
@options.merge!(contents[:options] || {})
@windows = contents[:windows].collect{ |w| Scide::Window.new self, w }
# find default window if specified
@default_window = if contents[:default_window].kind_of? Fixnum
@windows[contents[:default_window]]
elsif contents[:default_window].kind_of?(String) or contents[:default_window].kind_of?(Symbol)
@windows.find{ |w| w.name == contents[:default_window].to_s }
elsif !contents[:default_window].nil?
raise ArgumentError, "default window of project '#{key}' should be an integer, string or symbol"
end
raise ArgumentError, "default window of project '#{key}' must be the name or index of one of its windows" if !contents[:default_window].nil? and @default_window.nil?
end
# Returns a representation of this project as a GNU Screen
# configuration fragment. Returns nil if this project has
# no configured windows.
def to_screen
return nil if @windows.blank?
String.new.tap do |s|
@windows.each_with_index do |w,i|
s << w.to_screen(i)
s << "\n" if i != (@windows.length - 1)
end
s << "\nselect #{@default_window.name}" if @default_window
end
end
end
end