Skip to content

Commit

Permalink
Merge pull request #159 from andersonkrs/add-custom-formatters
Browse files Browse the repository at this point in the history
Add --format option
  • Loading branch information
rafaelfranca authored Nov 9, 2020
2 parents 10eddda + dfa13b3 commit 6179ee2
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 34 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,35 @@ def autocorrect(_processed_source, offense)
end
```

## Output formats

You can change the output format of ERB Lint by specifying formatters with the `-f/--format` option.

### Multiline (default)

```sh
$ erblint
Linting 8 files with 12 linters...
Remove multiple trailing newline at the end of the file.
In file: app/views/users/show.html.erb:95
Remove newline before `%>` to match start of tag.
In file: app/views/subscriptions/index.html.erb:38

2 error(s) were found in ERB files
```

### Compact

```sh
erblint --format compact
Linting 8 files with 12 linters...
app/views/users/show.html.erb:95:0: Remove multiple trailing newline at the end of the file.
app/views/users/_graph.html.erb:27:37: Extra space detected where there should be no space
2 error(s) were found in ERB files
```

## License

This project is released under the [MIT license](LICENSE.txt).
7 changes: 7 additions & 0 deletions lib/erb_lint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@
require 'erb_lint/runner_config'
require 'erb_lint/runner'
require 'erb_lint/version'
require 'erb_lint/stats'
require 'erb_lint/reporter'

# Load linters
Dir[File.expand_path('erb_lint/linters/**/*.rb', File.dirname(__FILE__))].each do |file|
require file
end

# Load reporters
Dir[File.expand_path('erb_lint/reporters/**/*.rb', File.dirname(__FILE__))].each do |file|
require file
end
65 changes: 31 additions & 34 deletions lib/erb_lint/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ class CLI
class ExitWithFailure < RuntimeError; end
class ExitWithSuccess < RuntimeError; end

class Stats
attr_accessor :found, :corrected, :exceptions
def initialize
@found = 0
@corrected = 0
@exceptions = 0
end
end

def initialize
@options = {}
@config = nil
Expand All @@ -51,9 +42,12 @@ def run(args = ARGV)
failure!('no linter available with current configuration')
end

puts "Linting #{lint_files.size} files with "\
"#{enabled_linter_classes.size} #{'autocorrectable ' if autocorrect?}linters..."
puts
@options[:format] ||= :multiline
@stats.files = lint_files.size
@stats.linters = enabled_linter_classes.size

reporter = Reporter.create_reporter(@options[:format], @stats, autocorrect?)
reporter.preview

runner = ERBLint::Runner.new(file_loader, @config)

Expand All @@ -72,20 +66,7 @@ def run(args = ARGV)
end
end

if @stats.corrected > 0
corrected_found_diff = @stats.found - @stats.corrected
if corrected_found_diff > 0
warn(Rainbow(
"#{@stats.corrected} error(s) corrected and #{corrected_found_diff} error(s) remaining in ERB files"
).red)
else
puts Rainbow("#{@stats.corrected} error(s) corrected in ERB files").green
end
elsif @stats.found > 0
warn(Rainbow("#{@stats.found} error(s) were found in ERB files").red)
else
puts Rainbow("No errors were found in ERB files").green
end
reporter.show

@stats.found == 0 && @stats.exceptions == 0
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, ExitWithFailure => e
Expand Down Expand Up @@ -126,15 +107,12 @@ def run_with_corrections(runner, filename)
file_content = corrector.corrected_content
runner.clear_offenses
end
offenses_filename = relative_filename(filename)
offenses = runner.offenses || []

@stats.found += runner.offenses.size
runner.offenses.each do |offense|
puts <<~EOF
#{offense.message}#{Rainbow(' (not autocorrected)').red if autocorrect?}
In file: #{relative_filename(filename)}:#{offense.line_range.begin}
EOF
end
@stats.found += offenses.size
@stats.processed_files[offenses_filename] ||= []
@stats.processed_files[offenses_filename] |= offenses
end

def correct(processed_source, offenses)
Expand Down Expand Up @@ -258,6 +236,15 @@ def option_parser
end
end

opts.on("--format FORMAT", format_options_help) do |format|
unless Reporter.available_format?(format)
error_message = invalid_format_error_message(format)
failure!(error_message)
end

@options[:format] = format
end

opts.on("--lint-all", "Lint all files matching configured glob [default: #{DEFAULT_LINT_ALL_GLOB}]") do |config|
@options[:lint_all] = config
end
Expand Down Expand Up @@ -289,5 +276,15 @@ def option_parser
end
end
end

def format_options_help
"Report offenses in the given format: "\
"(#{Reporter.available_formats.join(', ')}) (default: multiline)"
end

def invalid_format_error_message(given_format)
formats = Reporter.available_formats.map { |format| " - #{format}\n" }
"#{given_format}: is not a valid format. Available formats:\n#{formats.join}"
end
end
end
8 changes: 8 additions & 0 deletions lib/erb_lint/offense.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,13 @@ def ==(other)
def line_range
Range.new(source_range.line, source_range.last_line)
end

def line_number
line_range.begin
end

def column
source_range.column
end
end
end
38 changes: 38 additions & 0 deletions lib/erb_lint/reporter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'active_support/core_ext/class'

module ERBLint
class Reporter
def self.create_reporter(format, *args)
reporter_klass = "#{ERBLint::Reporters}::#{format.to_s.camelize}Reporter".constantize
reporter_klass.new(*args)
end

def self.available_format?(format)
available_formats.include?(format.to_s)
end

def self.available_formats
descendants
.map(&:to_s)
.map(&:demodulize)
.map(&:underscore)
.map { |klass_name| klass_name.sub("_reporter", "") }
.sort
end

def initialize(stats, autocorrect)
@stats = stats
@autocorrect = autocorrect
end

def preview; end

def show; end

private

attr_reader :stats, :autocorrect
delegate :processed_files, to: :stats
end
end
60 changes: 60 additions & 0 deletions lib/erb_lint/reporters/compact_reporter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true

module ERBLint
module Reporters
class CompactReporter < Reporter
def preview
puts "Linting #{stats.files} files with "\
"#{stats.linters} #{'autocorrectable ' if autocorrect}linters..."
end

def show
processed_files.each do |filename, offenses|
offenses.each do |offense|
puts format_offense(filename, offense)
end
end

footer
summary
end

private

def format_offense(filename, offense)
[
"#{filename}:",
"#{offense.line_number}:",
"#{offense.column}: ",
offense.message.to_s,
].join
end

def footer; end

def summary
if stats.corrected > 0
report_corrected_offenses
elsif stats.found > 0
warn(Rainbow("#{stats.found} error(s) were found in ERB files").red)
else
puts Rainbow("No errors were found in ERB files").green
end
end

def report_corrected_offenses
corrected_found_diff = stats.found - stats.corrected

if corrected_found_diff > 0
message = Rainbow(
"#{stats.corrected} error(s) corrected and #{corrected_found_diff} error(s) remaining in ERB files"
).red

warn(message)
else
puts Rainbow("#{stats.corrected} error(s) corrected in ERB files").green
end
end
end
end
end
22 changes: 22 additions & 0 deletions lib/erb_lint/reporters/multiline_reporter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true
require_relative "compact_reporter"

module ERBLint
module Reporters
class MultilineReporter < CompactReporter
private

def format_offense(filename, offense)
<<~EOF
#{offense.message}#{Rainbow(' (not autocorrected)').red if autocorrect}
In file: #{filename}:#{offense.line_number}
EOF
end

def footer
puts
end
end
end
end
27 changes: 27 additions & 0 deletions lib/erb_lint/stats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true
module ERBLint
class Stats
attr_accessor :found,
:corrected,
:exceptions,
:linters,
:files,
:processed_files

def initialize(
found: 0,
corrected: 0,
exceptions: 0,
linters: 0,
files: 0,
processed_files: {}
)
@found = found
@corrected = corrected
@exceptions = exceptions
@linters = linters
@files = files
@processed_files = processed_files
end
end
end
Loading

0 comments on commit 6179ee2

Please sign in to comment.