Class: CovLoupe::Formatters::SourceFormatter
- Inherits:
-
Object
- Object
- CovLoupe::Formatters::SourceFormatter
- Defined in:
- lib/cov_loupe/formatters/source_formatter.rb
Overview
Formats source code with inline coverage markers for CLI output.
Supports two display modes:
- :full → show all lines with coverage markers
- :uncovered → show only uncovered lines with N lines of context around each
Covered and uncovered lines are marked in the output, with optional ANSI color coding. The context value controls how many surrounding lines are shown in :uncovered mode.
Instance Attribute Summary collapse
-
#color_enabled ⇒ Object
readonly
Returns the value of attribute color_enabled.
-
#output_chars ⇒ Object
readonly
Returns the value of attribute output_chars.
Instance Method Summary collapse
- #build_source_payload(model, path, mode: nil, context: 2) ⇒ Object
- #build_source_rows(src_lines, cov_lines, mode:, context: 2) ⇒ Object
- #format_detailed_rows(rows) ⇒ Object
- #format_source_for(model, path, mode: nil, context: 2) ⇒ Object
- #format_source_rows(rows) ⇒ Object
-
#initialize(color_enabled: true, output_chars: :default) ⇒ SourceFormatter
constructor
A new instance of SourceFormatter.
Constructor Details
#initialize(color_enabled: true, output_chars: :default) ⇒ SourceFormatter
Returns a new instance of SourceFormatter.
17 18 19 20 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 17 def initialize(color_enabled: true, output_chars: :default) @color_enabled = color_enabled @output_chars = output_chars end |
Instance Attribute Details
#color_enabled ⇒ Object (readonly)
Returns the value of attribute color_enabled.
117 118 119 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 117 def color_enabled @color_enabled end |
#output_chars ⇒ Object (readonly)
Returns the value of attribute output_chars.
117 118 119 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 117 def output_chars @output_chars end |
Instance Method Details
#build_source_payload(model, path, mode: nil, context: 2) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 44 def build_source_payload(model, path, mode: nil, context: 2) raw = fetch_raw(model, path) return nil unless raw abs = raw['file'] lines_cov = raw['lines'] src = File.file?(abs) ? File.readlines(abs, chomp: true) : nil return nil unless src build_source_rows(src, lines_cov, mode: mode, context: context) end |
#build_source_rows(src_lines, cov_lines, mode:, context: 2) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 56 def build_source_rows(src_lines, cov_lines, mode:, context: 2) # Normalize inputs defensively to avoid type errors in formatting coverage_lines = cov_lines || [] context_line_count = begin context.to_i rescue 2 end raise ArgumentError, 'Context lines cannot be negative' if context_line_count.negative? n = src_lines.length include_line = Array.new(n, mode == :full) if mode == :uncovered include_line = mark_uncovered_lines_with_context(coverage_lines, context_line_count, n) end build_row_data(src_lines, coverage_lines, include_line) end |
#format_detailed_rows(rows) ⇒ Object
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 106 def format_detailed_rows(rows) # Simple aligned columns: line, hits, covered out = [] out << format('%6s %6s %7s', 'Line', 'Hits', 'Covered') out << format('%6s %6s %7s', '-----', '----', '-------') rows.each do |r| out << format('%6d %6d %5s', r['line'], r['hits'], r['covered'] ? 'yes' : 'no') end out.join("\n") end |
#format_source_for(model, path, mode: nil, context: 2) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 22 def format_source_for(model, path, mode: nil, context: 2) raw = fetch_raw(model, path) return '[source not available]' unless raw abs = raw['file'] lines_cov = raw['lines'] src = File.file?(abs) ? File.readlines(abs, chomp: true) : nil return '[source not available]' unless src begin rows = build_source_rows(src, lines_cov, mode: mode, context: context) format_source_rows(rows) rescue ArgumentError raise rescue => e # If any unexpected formatting/indexing error occurs, avoid crashing the CLI CovLoupe.logger.safe_log( "SourceFormatter#format_source_for error for path '#{abs}': #{e.class} - #{e.}") '[source not available]' end end |
#format_source_rows(rows) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/cov_loupe/formatters/source_formatter.rb', line 75 def format_source_rows(rows) # Use ASCII-safe markers when output_chars is :ascii check_mark = OutputChars.ascii_mode?(@output_chars) ? '+' : "\u2713" miss_mark = 'X' marker = ->(covered, _hits) do case covered when true then colorize(check_mark, :green) when false then colorize(miss_mark, :red) else colorize(' ', :dim) end end hyphen_line = format('%6s-%2s-+-%s', '------', '--', '-' * 60) lines = [ '', hyphen_line, format('%6s %2s | %s', 'Line', ' ', 'Source'), hyphen_line, ] rows.each do |r| m = marker.call(r['covered'], r['hits']) # Convert source code to ASCII when in ASCII mode code = OutputChars.convert(r['code'], @output_chars) lines << format('%6d %2s | %s', r['line'], m, code) end lines.join("\n") end |