lib/rake-commander/options/error.rb in rake-commander-0.1.4 vs lib/rake-commander/options/error.rb in rake-commander-0.2.0

- old
+ new

@@ -1,18 +1,83 @@ -require_relative 'error_rely' +require_relative 'error/base' +require_relative 'error/missing_argument' +require_relative 'error/invalid_argument' +require_relative 'error/invalid_option' +require_relative 'error/missing_option' +require_relative 'error/unknown_argument' +require_relative 'error/handling' + class RakeCommander module Options - class MissingOption < RakeCommander::Options::ErrorRely - def initialize(value) - super("missing required option: #{to_description(value)}") + module Error + class << self + def included(base) + super(base) + base.send :include, RakeCommander::Options::Error::Handling + base.extend ClassMethods + end end - end - class MissingArgument < RakeCommander::Options::ErrorRely - OPTION_REGEX = /missing (?:required|) argument: (?<option>.+)/i.freeze - end + module ClassMethods + # Re-open method to add all the error handling. + # @see RakeCommander::Options::Result + def parse_options(argv = ARGV, results: {}, leftovers: [], &block) + with_error_handling(argv, results, leftovers) do + super.tap do |_| + check_on_leftovers(leftovers) + check_required_presence(results) + end + rescue OptionParser::InvalidOption => e + eklass = RakeCommander::Options::Error::InvalidOption + raise eklass.new(e, from: self), nil, cause: nil + rescue OptionParser::MissingArgument => e + eklass = RakeCommander::Options::Error::MissingArgument + opt = error_option(e, eklass) + msg = e.message + msg = "missing required argument: #{opt.name_hyphen} (#{opt.short_hyphen})" if opt + raise eklass.new(from: self, option: opt), msg, cause: nil + rescue OptionParser::InvalidArgument => e + eklass = RakeCommander::Options::Error::InvalidArgument + opt = error_option(e, eklass) + raise eklass.new(e, from: self, option: opt), nil, cause: nil unless opt&.argument_required? + eklass = RakeCommander::Options::Error::MissingArgument + msg = "missing required argument in option: #{opt.name_hyphen} (#{opt.short_hyphen})" + raise eklass.new(from: self, option: opt), msg, cause: nil + end + end - class InvalidArgument < RakeCommander::Options::ErrorRely - OPTION_REGEX = /invalid argument: (?<option>.+)/i.freeze + protected + + # Helper to retrieve an existing `RakeCommander::Option` out of a + # `OptionParser` error. + # @param e [OptionParser:Error] containing the original error `message` + # @param eklass [RakeCommander::Options::Error:Base::Class] the error class to retrive the option key + # @return [RakeCommander::Option, NilClass] + def error_option(err, eklass) + return false unless option_sym = eklass.option_sym(err.message) + options_hash(with_implicit: true)[option_sym] + end + + private + + # It implements the logic defined by `error_on_leftovers`. + # @param leftovers [Array<String>] + # @param results [Hash] the parsed options + # @return [Hash] the results (same object) + def check_on_leftovers(leftovers) + return if leftovers.empty? + eklass = RakeCommander::Options::Error::UnknownArgument + raise eklass.new(leftovers, from: self) + end + + # It throws an exception if any of the required options + # is missing in results + def check_required_presence(results) + missing = options.select(&:required?).reject do |opt| + results.key?(opt.short) || results.key?(opt.name) + end + raise RakeCommander::Options::Error::MissingOption.new(missing, from: self) unless missing.empty? + end + end end end end