lib/mutant/cli.rb in mutant-0.8.24 vs lib/mutant/cli.rb in mutant-0.9.0
- old
+ new
@@ -1,75 +1,103 @@
# frozen_string_literal: true
module Mutant
# Commandline parser / runner
class CLI
- include Adamantium::Flat, Equalizer.new(:config), Procto.call(:config)
+ include Concord.new(:world, :config)
- # Error failed when CLI argv is invalid
- Error = Class.new(RuntimeError)
+ private_class_method :new
+ OPTIONS =
+ %i[
+ add_environment_options
+ add_mutation_options
+ add_filter_options
+ add_debug_options
+ ].freeze
+
+ private_constant(*constants(false))
+
# Run cli with arguments
#
- # @param [Array<String>] arguments
+ # @param [World] world
+ # the outside world
#
+ # @param [Config] default_config
+ # the default config
+ #
+ # @param [Array<String>]
+ # the user provided arguments
+ #
# @return [Boolean]
- def self.run(arguments)
- Runner.call(Env::Bootstrap.call(call(arguments))).success?
- rescue Error => exception
- $stderr.puts(exception.message)
- false
+ #
+ # rubocop:disable Style/Semicolon
+ #
+ # ignore :reek:LongParameterList
+ def self.run(world, default_config, arguments)
+ License
+ .apply(world)
+ .apply { Config.load_config_file(world, default_config) }
+ .apply { |file_config| apply(world, file_config, arguments) }
+ .apply { |cli_config| Bootstrap.apply(world, cli_config) }
+ .apply(&Runner.method(:apply))
+ .from_right { |error| world.stderr.puts(error); return false }
+ .success?
end
+ # rubocop:enable Style/Semicolon
- # Initialize object
+ # Parse arguments into config
#
- # @param [Array<String>]
+ # @param [World] world
+ # @param [Config] config
+ # @param [Array<String>] arguments
#
- # @return [undefined]
- def initialize(arguments)
- @config = Config::DEFAULT
-
- parse(arguments)
+ # @return [Either<OptionParser::ParseError, Config>]
+ #
+ # ignore :reek:LongParameterList
+ def self.apply(world, config, arguments)
+ Either
+ .wrap_error(OptionParser::ParseError) { new(world, config).parse(arguments) }
+ .lmap(&:message)
end
- # Config parsed from CLI
- #
- # @return [Config]
- attr_reader :config
+ # Local opt out of option parser defaults
+ class OptionParser < ::OptionParser
+ # Kill defaults added by option parser that
+ # inference with ours under mutation testing.
+ define_method(:add_officious) {}
+ end # OptionParser
- private
-
# Parse the command-line options
#
# @param [Array<String>] arguments
# Command-line options and arguments to be parsed.
#
- # @fail [Error]
- # An error occurred while parsing the options.
- #
- # @return [undefined]
+ # @return [Config]
def parse(arguments)
opts = OptionParser.new do |builder|
builder.banner = 'usage: mutant [options] MATCH_EXPRESSION ...'
- %i[add_environment_options add_mutation_options add_filter_options add_debug_options].each do |name|
+ OPTIONS.each do |name|
__send__(name, builder)
end
end
- parse_match_expressions(opts.parse!(arguments))
- rescue OptionParser::ParseError => error
- raise(Error, error)
+ parse_match_expressions(opts.parse!(arguments.dup))
+
+ config
end
+ private
+
# Parse matchers
#
# @param [Array<String>] expressions
#
# @return [undefined]
def parse_match_expressions(expressions)
expressions.each do |expression|
- add_matcher(:match_expressions, config.expression_parser.(expression))
+ add_matcher(:match_expressions, config.expression_parser.apply(expression).from_right)
end
end
# Add environmental options
#
@@ -92,51 +120,38 @@
opts.on('-j', '--jobs NUMBER', 'Number of kill jobs. Defaults to number of processors.') do |number|
with(jobs: Integer(number))
end
end
- # Use integration
- #
- # @param [String] name
- #
- # @return [undefined]
- def setup_integration(name)
- with(integration: Integration.setup(config.kernel, name))
- rescue LoadError
- raise Error, "Could not load integration #{name.inspect} (you may want to try installing the gem mutant-#{name})"
- end
-
# Add mutation options
#
# @param [OptionParser] opts
#
# @return [undefined]
def add_mutation_options(opts)
opts.separator(nil)
opts.separator('Options:')
- opts.on('--use INTEGRATION', 'Use INTEGRATION to kill mutations', &method(:setup_integration))
+ opts.on('--use INTEGRATION', 'Use INTEGRATION to kill mutations') do |name|
+ with(integration: name)
+ end
end
# Add filter options
#
# @param [OptionParser] opts
#
# @return [undefined]
def add_filter_options(opts)
opts.on('--ignore-subject EXPRESSION', 'Ignore subjects that match EXPRESSION as prefix') do |pattern|
- add_matcher(:ignore_expressions, config.expression_parser.(pattern))
+ add_matcher(:ignore_expressions, config.expression_parser.apply(pattern).from_right)
end
opts.on('--since REVISION', 'Only select subjects touched since REVISION') do |revision|
add_matcher(
:subject_filters,
Repository::SubjectFilter.new(
- Repository::Diff.new(
- config: config,
- from: Repository::Diff::HEAD,
- to: revision
- )
+ Repository::Diff.new(to: revision, world: world)
)
)
end
end
@@ -148,16 +163,16 @@
def add_debug_options(opts)
opts.on('--fail-fast', 'Fail fast') do
with(fail_fast: true)
end
opts.on('--version', 'Print mutants version') do
- puts("mutant-#{VERSION}")
- config.kernel.exit
+ world.stdout.puts("mutant-#{VERSION}")
+ world.kernel.exit
end
opts.on_tail('-h', '--help', 'Show this message') do
- puts(opts.to_s)
- config.kernel.exit
+ world.stdout.puts(opts.to_s)
+ world.kernel.exit
end
end
# With configuration
#
@@ -191,8 +206,7 @@
#
# @return [undefined]
def add_matcher(attribute, value)
with(matcher: config.matcher.add(attribute, value))
end
-
end # CLI
end # Mutant