lib/cliutils/prefs.rb in cliutils-2.0.3 vs lib/cliutils/prefs.rb in cliutils-2.1.0

- old
+ new

@@ -4,10 +4,11 @@ module CLIUtils # Engine to derive preferences from a YAML file, deliver # those to a user via a prompt, and collect the results. class Prefs include Messaging + # Stores the filepath (if it exists) to the prefs file. # @return [String] attr_reader :config_path # Stores a Configurator instance. @@ -16,22 +17,41 @@ # Stores answers to prompt questions. # @return [Array] attr_reader :prompts + class << self + # Stores any actions registered for all + # instances of Prefs. + # @return [Hash] + attr_accessor :registered_actions + + # Stores any behaviors registered for all + # instances of Prefs. + # @return [Hash] + attr_accessor :registered_behaviors + + # Stores any validators registered for all + # instances of Prefs. + # @return [Hash] + attr_accessor :registered_validators + end + + self.registered_actions = {} + self.registered_behaviors = {} + self.registered_validators = {} + # Reads prompt data from and stores it. # @param [<String, Hash, Array>] data Filepath to YAML, Hash, or Array # @param [Configurator] configurator Source of defailt values # @return [void] def initialize(data, configurator = nil) - @answers = [] - @configurator = configurator @prompts = [] - + @configurator = configurator case data when String - if File.exist?(data) + if File.file?(data) @config_path = data data = YAML.load_file(data).deep_symbolize_keys @prompts = _generate_prefs(data) else fail "Invalid configuration file: #{ data }" @@ -54,29 +74,81 @@ # answers from the user. Note that all questions w/o # prerequisites are examined first; once those are # complete, questions w/ prerequisites are examined. # @return [void] def ask + # First, deliver all the prompts that don't have + # any prerequisites. @prompts.reject { |p| p.prereqs }.each do |p| _deliver_prompt(p) end + # After the "non-prerequisite" prompts are delivered, + # deliver any that require prerequisites. @prompts.select { |p| p.prereqs }.each do |p| _deliver_prompt(p) if _prereqs_fulfilled?(p) end end + # Deregister an action based on the symbol it was + # stored under. + # @param [Symbol] symbol The symbol to remove + # @remove [void] + def self.deregister_action(symbol) + _deregister_asset(symbol, Pref::ASSET_TYPE_ACTION) + end + + # Deregister a behavior based on the symbol it was + # stored under. + # @param [Symbol] symbol The symbol to remove + # @remove [void] + def self.deregister_behavior(symbol) + _deregister_asset(symbol, Pref::ASSET_TYPE_BEHAVIOR) + end + + # Deregister a validator based on the symbol it was + # stored under. + # @param [Symbol] symbol The symbol to remove + # @remove [void] + def self.deregister_validator(symbol) + _deregister_asset(symbol, Pref::ASSET_TYPE_VALIDATOR) + end + + # Register an action. + # @param [String] path The filepath of the action + # @remove [void] + def self.register_action(path) + self._register_asset(path, Pref::ASSET_TYPE_ACTION) + end + + # Register a behavior. + # @param [String] path The filepath of the behavior + # @remove [void] + def self.register_behavior(path) + _register_asset(path, Pref::ASSET_TYPE_BEHAVIOR) + end + + # Register a validator. + # @param [String] path The filepath of the validator + # @remove [void] + def self.register_validator(path) + _register_asset(path, Pref::ASSET_TYPE_VALIDATOR) + end + private # Utility method for prompting the user to answer the # question (taking into account any options). # @param [Hash] p The prompt # @return [void] def _deliver_prompt(p) default = p.default unless @configurator.nil? section_sym = p.config_section.to_sym + + # If a Configurator has been included, replace relevant + # prompt defaults with those values from the Configurator. unless @configurator.data[section_sym].nil? config_val = @configurator.data[section_sym][p.config_key.to_sym] default = config_val unless config_val.nil? end end @@ -104,8 +176,57 @@ answer.answer == req[:config_value] end ret = false if a.nil? end ret + end + + # Utility function to deregister an asset. + # @param [Symbol] symbol The asset to remove + # @param [Fixnum] type A Pref asset type + # @return [void] + def self._deregister_asset(symbol, type) + case type + when Pref::ASSET_TYPE_ACTION + CLIUtils::Prefs.registered_actions.delete(symbol) + when Pref::ASSET_TYPE_BEHAVIOR + CLIUtils::Prefs.registered_behaviors.delete(symbol) + when Pref::ASSET_TYPE_VALIDATOR + CLIUtils::Prefs.registered_validators.delete(symbol) + end + end + + # Utility function to register an asset and associate + # it with the Prefs eigenclass. + # @param [String] path The filepath to the asset + # @param [Fixnum] type A Pref asset type + # @raise [StandardError] if the asset is unknown + # @return [void] + def self._register_asset(path, type) + if File.file?(path) + class_name = File.basename(path, '.*').camelize + case type + when Pref::ASSET_TYPE_ACTION + k = class_name.sub('Action', '').to_sym + unless CLIUtils::Prefs.registered_actions.key?(k) + h = { k => { class: class_name, path: path } } + CLIUtils::Prefs.registered_actions.merge!(h) + end + when Pref::ASSET_TYPE_BEHAVIOR + k = class_name.sub('Behavior', '').to_sym + unless CLIUtils::Prefs.registered_behaviors.key?(k) + h = { k => { class: class_name, path: path } } + CLIUtils::Prefs.registered_behaviors.merge!(h) + end + when Pref::ASSET_TYPE_VALIDATOR + k = class_name.sub('Validator', '').to_sym + unless CLIUtils::Prefs.registered_validators.key?(k) + h = { k => { class: class_name, path: path } } + CLIUtils::Prefs.registered_validators.merge!(h) + end + end + else + fail "Registration failed because of unknown filepath: #{ path }" + end end end end