shard-ameba/src/ameba/formatter/util.cr

119 lines
3.2 KiB
Crystal

module Ameba::Formatter
module Util
extend self
def deansify(message : String?) : String?
message.try &.gsub(/\x1b[^m]*m/, "").presence
end
def trim(str, max_length = 120, ellipsis = " ...")
if (str.size - ellipsis.size) > max_length
str = str[0, max_length]
if str.size > ellipsis.size
str = str[0...-ellipsis.size] + ellipsis
end
end
str
end
def context(lines, lineno, context_lines = 3, remove_empty = true)
pre_context, post_context = %w[], %w[]
lines.each_with_index do |line, i|
case i + 1
when lineno - context_lines...lineno
pre_context << line
when lineno + 1..lineno + context_lines
post_context << line
end
end
if remove_empty
# remove empty lines at the beginning ...
while pre_context.first?.try(&.blank?)
pre_context.shift
end
# ... and the end
while post_context.last?.try(&.blank?)
post_context.pop
end
end
{pre_context, post_context}
end
def affected_code(issue : Issue, context_lines = 0, max_length = 120, ellipsis = " ...", prompt = "> ")
return unless location = issue.location
affected_code(issue.code, location, issue.end_location, context_lines, max_length, ellipsis, prompt)
end
def affected_code(code, location, end_location = nil, context_lines = 0, max_length = 120, ellipsis = " ...", prompt = "> ")
lines = code.split('\n') # must preserve trailing newline
lineno, column =
location.line_number, location.column_number
return unless affected_line = lines[lineno - 1]?.presence
if column < max_length
affected_line = trim(affected_line, max_length, ellipsis)
end
show_context = context_lines > 0
if show_context
pre_context, post_context =
context(lines, lineno, context_lines)
position = prompt.size + column
position -= 1
else
affected_line_size, affected_line =
affected_line.size, affected_line.lstrip
position = column - (affected_line_size - affected_line.size) + prompt.size
position -= 1
end
String.build do |str|
if show_context
pre_context.try &.each do |line|
line = trim(line, max_length, ellipsis)
str << prompt
str.puts(line.colorize(:dark_gray))
end
end
str << prompt
str.puts(affected_line.colorize(:white))
str << (" " * position)
str << "^".colorize(:yellow)
if end_location
end_lineno = end_location.line_number
end_column = end_location.column_number
if end_lineno == lineno && end_column > column
end_position = end_column - column
end_position -= 1
str << ("-" * end_position).colorize(:dark_gray)
str << "^".colorize(:yellow)
end
end
str.puts
if show_context
post_context.try &.each do |line|
line = trim(line, max_length, ellipsis)
str << prompt
str.puts(line.colorize(:dark_gray))
end
end
end
end
end
end