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.



59
60
61
62
# File 'lib/error_to_communicate/format_terminal.rb', line 59

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

Instance Attribute Details

#cwdObject

Returns the value of attribute cwd.



57
58
59
# File 'lib/error_to_communicate/format_terminal.rb', line 57

def cwd
  @cwd
end

#themeObject

Returns the value of attribute theme.



57
58
59
# File 'lib/error_to_communicate/format_terminal.rb', line 57

def theme
  @theme
end

Instance Method Details

#add_message_to(code, offset, message) ⇒ Object



145
146
147
148
149
# File 'lib/error_to_communicate/format_terminal.rb', line 145

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

#bound_num(attributes) ⇒ Object



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

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

#call(attributes) ⇒ Object



64
65
66
67
68
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
# File 'lib/error_to_communicate/format_terminal.rb', line 64

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[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



111
112
113
114
115
# File 'lib/error_to_communicate/format_terminal.rb', line 111

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



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/error_to_communicate/format_terminal.rb', line 128

def prefix_linenos_to(code, start_linenum, options)
  line_to_mark  = options.fetch :mark
  lines         = code.lines
  max_linenum   = lines.count + 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



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

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