lib/scss_lint/cli.rb in scss-lint-0.12.1 vs lib/scss_lint/cli.rb in scss-lint-0.13.0
- old
+ new
@@ -3,37 +3,70 @@
module SCSSLint
# Responsible for parsing command-line options and executing the appropriate
# application logic based on the options specified.
class CLI
- attr_accessor :options
+ attr_reader :config, :options
+ # Subset of semantic exit codes conforming to `sysexits` documentation.
+ EXIT_CODES = {
+ ok: 0,
+ usage: 64, # Command line usage error
+ data: 65, # User input was incorrect (i.e. contains lints)
+ no_input: 66, # Input file did not exist or was not readable
+ software: 70, # Internal software error
+ config: 78, # Configuration error
+ }
+
def initialize(args = [])
@args = args
@options = {}
+ @config = Config.default
end
def parse_arguments
- parser = OptionParser.new do |opts|
+ begin
+ options_parser.parse!(@args)
+
+ # Take the rest of the arguments as files/directories
+ @options[:files] = @args
+ rescue OptionParser::InvalidOption => ex
+ print_help options_parser.help, ex
+ end
+
+ begin
+ setup_configuration
+ rescue NoSuchLinter => ex
+ puts ex.message
+ halt :config
+ end
+ end
+
+ def options_parser
+ @options_parser ||= OptionParser.new do |opts|
opts.banner = "Usage: #{opts.program_name} [options] [scss-files]"
opts.separator ''
opts.separator 'Common options:'
+ opts.on('-c', '--config file', 'Specify configuration file', String) do |file|
+ @options[:config_file] = file
+ end
+
opts.on('-e', '--exclude file,...', Array,
'List of file names to exclude') do |files|
- options[:excluded_files] = files
+ @options[:excluded_files] = files
end
opts.on('-i', '--include-linter linter,...', Array,
'Specify which linters you want to run') do |linters|
- options[:included_linters] = linters
+ @options[:included_linters] = linters
end
opts.on('-x', '--exclude-linter linter,...', Array,
"Specify which linters you don't want to run") do |linters|
- options[:excluded_linters] = linters
+ @options[:excluded_linters] = linters
end
opts.on_tail('--show-linters', 'Shows available linters') do
print_linters
end
@@ -45,49 +78,80 @@
opts.on_tail('-v', '--version', 'Show version') do
print_version opts.program_name, VERSION
end
opts.on('--xml', 'Output the results in XML format') do
- options[:reporter] = SCSSLint::Reporter::XMLReporter
+ @options[:reporter] = SCSSLint::Reporter::XMLReporter
end
end
-
- begin
- parser.parse!(@args)
-
- # Take the rest of the arguments as files/directories
- options[:files] = @args
- rescue OptionParser::InvalidOption => ex
- print_help parser.help, ex
- end
end
def run
- runner = Runner.new(options)
- runner.run(find_files)
+ runner = Runner.new(@config)
+ runner.run(files_to_lint)
report_lints(runner.lints)
- halt(1) if runner.lints?
- rescue NoFilesError, NoSuchLinter, Errno::ENOENT => ex
+ halt :data if runner.lints.any?
+ rescue NoFilesError, Errno::ENOENT => ex
puts ex.message
- halt(-1)
+ halt :no_input
+ rescue NoSuchLinter => ex
+ puts ex.message
+ halt :usage
rescue => ex
puts ex.message
puts ex.backtrace
puts 'Report this bug at '.yellow + BUG_REPORT_URL.cyan
- halt(-1)
+ halt :software
end
private
- def find_files
- excluded_files = options.fetch(:excluded_files, [])
+ def setup_configuration
+ if @options[:config_file]
+ @config = Config.load(@options[:config_file])
+ @config.preferred = true
+ end
- extract_files_from(options[:files]).reject do |file|
- excluded_files.include?(file)
+ merge_command_line_flags_with_config(@config)
+ end
+
+ def merge_command_line_flags_with_config(config)
+ if @options[:excluded_files]
+ @options[:excluded_files].each do |file|
+ config.exclude_file(file)
+ end
end
+
+ if @options[:included_linters]
+ config.disable_all_linters
+ LinterRegistry.extract_linters_from(@options[:included_linters]).each do |linter|
+ config.enable_linter(linter)
+ end
+ end
+
+ if @options[:excluded_linters]
+ LinterRegistry.extract_linters_from(@options[:excluded_linters]).each do |linter|
+ config.disable_linter(linter)
+ end
+ end
+
+ config
end
+ def files_to_lint
+ extract_files_from(@options[:files]).reject do |file|
+ config =
+ if !@config.preferred && (config_for_file = Config.for_file(file))
+ merge_command_line_flags_with_config(config_for_file.dup)
+ else
+ @config
+ end
+
+ config.excluded_file?(file)
+ end
+ end
+
def extract_files_from(list)
files = []
list.each do |file|
Find.find(file) do |f|
files << f if scssish_file?(f)
@@ -103,11 +167,12 @@
VALID_EXTENSIONS.include?(File.extname(file))
end
def report_lints(lints)
sorted_lints = lints.sort_by { |l| [l.filename, l.line] }
- reporter = options.fetch(:reporter, Reporter::DefaultReporter).new(sorted_lints)
+ reporter = @options.fetch(:reporter, Reporter::DefaultReporter)
+ .new(sorted_lints)
output = reporter.report_lints
print output if output
end
def print_linters
@@ -125,19 +190,19 @@
end
def print_help(help_message, err = nil)
puts err, '' if err
puts help_message
- halt
+ halt(err ? :usage : :ok)
end
def print_version(program_name, version)
puts "#{program_name} #{version}"
halt
end
# Used for ease-of testing
- def halt(exit_status = 0)
- exit exit_status
+ def halt(exit_status = :ok)
+ exit(EXIT_CODES[exit_status])
end
end
end