class CLI::Mastermind::Configuration

Main configuration object. Walks up the file tree looking for masterplan files and loading them to build a the configuration used by the CLI.

These masterplan files are loaded starting from the current working directory and traversing up until a masterplan with a `at_project_root` directive or or the directory specified by a `project_root` directive is reached.

Configuration options set with `configure` are latched once set to something non-nil. This, along with the aforementioned load order of masterplan files, means that masterplan files closest to the source of your invokation will “beat” other masterplan files.

A global masterplan located at $HOME/.masterplan (or equivalent) is loaded last. You can use this to specify plans you want accessible everywhere or global configuration that should apply everywhere (unless overridden by more proximal masterplans).

Additionally, there is a directive (`see_other`) that allows for masterplan files outside of the lookup tree to be loaded.

See {DSL} for a full list of the commands provided by Mastermind and a sample masterplan file.

Constants

MASTER_PLAN

Path to the top-level masterplan

PLANFILE

Filename of masterplan files

Attributes

plan_files[R]

The set of planfiles to load

Public Class Methods

add_attribute(attribute) click to toggle source

Adds an arbitrary attribute given by attribute to the configuration class

@param attribute [String,Symbol] the attribute to define

@!macro [attach] add_attribute

@!attribute [rw] $1
# File lib/cli/mastermind/configuration.rb, line 44
def self.add_attribute(attribute)
  return if self.method_defined? attribute

  define_method "#{attribute}=" do |new_value=nil, &block|
    self.instance_variable_set("@#{attribute}", new_value.nil? ? block : new_value) if self.instance_variable_get("@#{attribute}").nil?
  end

  define_method attribute do
    value = self.instance_variable_get("@#{attribute}")
    return value unless value.respond_to?(:call)

    # Cache the value returned by the block so we're not doing potentially
    # expensive operations mutliple times.
    self.instance_variable_set("@#{attribute}", self.instance_eval(&value))
  end
end
new(base_path=nil) click to toggle source

@param base_path [String,nil] plans outside of the base path will be ignored

# File lib/cli/mastermind/configuration.rb, line 67
def initialize(base_path=nil)
  @base_path = base_path
  @loaded_masterplans = Set.new
  @plan_files = Set.new
  @ask_for_confirmation = true

  # If no alias exists for a particular value, return that value
  @aliases = Hash.new { |_,k| k }

  lookup_and_load_masterplans
  load_masterplan MASTER_PLAN
end

Public Instance Methods

add_plans(planfiles) click to toggle source

Adds a set of filenames for plans into the set of +@plan_files+.

Plans with paths outside the +@base_path+, if set, will be ignored.

@param planfiles [Array<String>] new planfiles to add to the set of planfiles @return [Void]

# File lib/cli/mastermind/configuration.rb, line 86
def add_plans(planfiles)
  allowed_plans = if @base_path.nil?
                    planfiles
                  else
                    planfiles.select { |file| file.start_with? @base_path }
                  end

  @plan_files.merge(allowed_plans)
end
ask?() click to toggle source

@return [Boolean] the user's ask_for_confirmation setting

# File lib/cli/mastermind/configuration.rb, line 127
def ask?
  @ask_for_confirmation
end
define_alias(alias_from, alias_to) click to toggle source

Defines a user alias

@param alias_from [String] the string to be replaced during expansion @param alias_to [String, Array<String>] the expanded argument @return [Void]

# File lib/cli/mastermind/configuration.rb, line 112
def define_alias(alias_from, alias_to)
  arguments = alias_to.split(' ') if alias_to.is_a? String

  @aliases[alias_from] = arguments unless @aliases.has_key? alias_from
end
load_masterplan(filename) click to toggle source

Loads a masterplan using the DSL, if it exists and hasn't been loaded already

@param filename [String] the path to the masterplan to load @return [Void]

# File lib/cli/mastermind/configuration.rb, line 100
def load_masterplan filename
  if File.exists? filename and !@loaded_masterplans.include? filename
    @loaded_masterplans << filename
    DSL.new(self, filename)
  end
end
map_alias(input) click to toggle source

Maps an input string to an alias.

@param input [String] the value to be replaced @return [String,Array<String>] the replacement alias or the input, if no replacement exists

# File lib/cli/mastermind/configuration.rb, line 122
def map_alias(input)
  @aliases[input]
end
skip_confirmation!() click to toggle source

Sets +@ask_for_confirmation+ to `false`.

@return [false]

# File lib/cli/mastermind/configuration.rb, line 134
def skip_confirmation!
  @ask_for_confirmation = false
end

Private Instance Methods

lookup_and_load_masterplans() click to toggle source

Walks up the file tree looking for masterplans.

@return [Void]

# File lib/cli/mastermind/configuration.rb, line 154
def lookup_and_load_masterplans
  load_masterplan File.join(Dir.pwd, PLANFILE)

  # Walk up the tree until we reach the project root, the home directory, or
  # the root directory
  unless [project_root, Dir.home, '/'].include? Dir.pwd
    Dir.chdir('..') { lookup_and_load_masterplans }
  end
end
method_missing(symbol, *args) click to toggle source

Override the default NoMethodError with a more useful MissingConfigurationError.

Since the configuration object is used directly by plans for configuration information, accessing non-existant configuration can lead to unhelpful NoMethodErrors. This replaces those errors with more helpful errors.

Calls superclass method
# File lib/cli/mastermind/configuration.rb, line 145
def method_missing(symbol, *args)
  super
rescue NoMethodError
  raise MissingConfigurationError, symbol
end