Class: ErrorToCommunicate::FormatTerminal::Code

Inherits:
Object
  • Object
show all
Defined in:
lib/error_to_communicate/format_terminal.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes) ⇒ Code

Returns a new instance of Code.



64
65
66
67
# File 'lib/error_to_communicate/format_terminal.rb', line 64

def initialize(attributes)
  self.theme = attributes.fetch :theme
  self.cwd   = attributes.fetch :cwd
end

Instance Attribute Details

#cwdObject

Returns the value of attribute cwd.



62
63
64
# File 'lib/error_to_communicate/format_terminal.rb', line 62

def cwd
  @cwd
end

#themeObject

Returns the value of attribute theme.



62
63
64
# File 'lib/error_to_communicate/format_terminal.rb', line 62

def theme
  @theme
end

Instance Method Details

#add_message_to(code, offset, message) ⇒ Object



150
151
152
153
154
# File 'lib/error_to_communicate/format_terminal.rb', line 150

def add_message_to(code, offset, message)
  lines = code.lines.to_a
  lines[offset].chomp! << " " << message << "\n"
  lines.join("")
end

#bound_num(attributes) ⇒ Object



122
123
124
125
126
# File 'lib/error_to_communicate/format_terminal.rb', line 122

def bound_num(attributes)
  num = attributes.fetch :num
  min = attributes.fetch :min
  num < min ? min : num
end

#call(attributes) ⇒ Object



69
70
71
72
73
74
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
105
106
107
108
109
110
111
112
113
114
# File 'lib/error_to_communicate/format_terminal.rb', line 69

def call(attributes)
  location       = attributes.fetch :location
  path           = location.path
  line_index     = location.linenum - 1
  highlight      = attributes.fetch :highlight, location.label
  end_index      = bound_num min: 0, num: line_index+attributes.fetch(:context).end
  start_index    = bound_num min: 0, num: line_index+attributes.fetch(:context).begin
  message        = attributes.fetch :message, ''
  message_offset = line_index - start_index
  if attributes.fetch(:mark, true)
    mark_linenum = location.linenum
  else
    mark_linenum = -1
  end

  # first line gives the path
  path_line = [
    theme.color_path("#{path_to_dir cwd, path}/"),
    theme.color_filename(path.basename),
    ":",
    theme.color_linenum(location.linenum),
  ].join("")

  # then display the code
  if path.exist?
    code = File.read(path).lines.to_a[start_index..end_index].join("")
    code = remove_indentation       code
    code = theme.syntax_highlight   code
    code = prefix_linenos_to        code, start_index.next, mark: mark_linenum
    code = add_message_to           code, message_offset, theme.screaming_red(message)
    code = theme.highlight_text     code, message_offset, highlight
  else
    code = "Can't find code\n"
  end

  # adjust for emphasization
  if attributes.fetch(:emphasis) == :path
    path_line = theme.underline      path_line
    code      = theme.indent         code, "      "
    code      = theme.desaturate     code
    code      = theme.highlight_text code, message_offset, highlight # b/c desaturate really strips color
  end

  # all together
  path_line << "\n" << code
end

#path_to_dir(from, to) ⇒ Object



116
117
118
119
120
# File 'lib/error_to_communicate/format_terminal.rb', line 116

def path_to_dir(from, to)
  to.expand_path.relative_path_from(from).dirname
rescue ArgumentError
  return to # eg rbx's core code
end

#prefix_linenos_to(code, start_linenum, options) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/error_to_communicate/format_terminal.rb', line 133

def prefix_linenos_to(code, start_linenum, options)
  line_to_mark  = options.fetch :mark
  lines         = code.lines.to_a
  max_linenum   = lines.length + start_linenum - 1 # 1 to translate to indexes
  linenum_width = max_linenum.to_s.length + 4     # 1 for the colon, 3 for the arrow/space
  lines.zip(start_linenum..max_linenum)
       .map { |line, num|
         if line_to_mark == num
           formatted_num = "-> #{num}:".ljust(linenum_width)
           formatted_num = theme.mark_linenum formatted_num
         else
           formatted_num = "   #{num}:".ljust(linenum_width)
         end
         theme.color_linenum(formatted_num) << " " << line
       }.join("")
end

#remove_indentation(code) ⇒ Object



128
129
130
131
# File 'lib/error_to_communicate/format_terminal.rb', line 128

def remove_indentation(code)
  indentation = code.scan(/^[ \r\t]*/).min_by(&:length)
  code.gsub(/^#{indentation}/, "")
end