class EcoRake module Options module Forwarding class Rule extend EcoRake::Base::MethodHelpers RULE_TYPES = [String, Symbol, Proc].freeze SYMBOL_TYPES = [:mirror].freeze attr_accessor :parent, :sym attr_reader :rule # @param rule [String, Proc] # - `Proc` -> [value, ] def initialize(sym, rule, parent: nil) msg = "Rule should be either of: #{RULE_TYPES.join(', ')}. Given: #{rule.class}" raise ArgumentError, msg unless RULE_TYPES.any? {|type| rule.is_a?(type)} msg = "Accepted Symbol rules are: :#{SYMBOL_TYPES.join(', :')}. Given :#{rule}" raise ArgumentError, msg if rule.is_a?(Symbol) && SYMBOL_TYPES.none? {|type| rule == type} @parent = parent @sym = sym @rule = rule end def active?(option_results) opt = option [opt&.name, opt&.short, sym].compact.any? {|k| option_results.key?(k)} end def results_value(option_results) opt = option value = nil value = option_results[opt.name] if opt && value.nil? value = option_results[opt.short] if opt && value.nil? value = option_results[sym] if value.nil? value end # @note # 1. Retrives value from parsed options results by using the option name, short or sym. # 2. It then applies the rule on it. # @param option_results [Hash] the parsed option results. # @return [NilClass, Value] the value that the rule returns, `nil` if rule inactive/not-applicable. def apply(option_results) return nil unless active?(option_results) opt = option return nil unless opt || rule != :mirror value = results_value(option_results) return rule if value && rule.is_a?(String) return nil if rule.is_a?(String) return opt.mirror(value) if rule == :mirror self.class.safe_call(rule, value, option_results, opt) end # Does a copy of this rule. # @return [EcoRake::Options::Forwarding::Rule] def dup(parent: nil) new_rule = rule.respond_to?(:deep_dup)? rule.deep_dup : rule.dup self.class.new(sym, new_rule, parent: parent) end alias_method :deep_dup, :dup def desc ref = (opt_ref = option_ref) ? opt_ref : "on #{sym} (no associated option)" "rule #{ref}" end # Reference of the associated option. def option_ref (opt = option) ? "on option '#{opt.name}' (#{opt.short})" : nil end # @return [EcoRake::Option] the option associated with `sym` name. def option parent&.send(:option, sym) end end end end end