(71 lines)
1 -- This file has code for converting errors to user-friendly format, with colors,2 -- line numbers, code excerpts, and so on.3 require "containers"4 Text = require 'text'5 C = require 'colors'7 box = (text)->8 max_line = 09 for line in text\gmatch("[^\n]+")10 max_line = math.max(max_line, #(line\gsub("\027%[[0-9;]*m","")))11 ret = ("\n"..text)\gsub "\n([^\n]*)", (line)->12 line_len = #(line\gsub("\027%[[0-9;]*m",""))13 return "\n#{line}#{(" ")\rep(max_line-line_len)} "..C('reset')14 return ret\sub(2,-1), max_line16 format_error = (err)->17 context = err.context or 218 err_line, err_linenum, err_linepos = err.source\line_info_at(err.start)19 -- TODO: better handle multi-line errors20 err_size = math.min((err.stop - err.start), (#err_line-err_linepos) + 1)21 nl_indicator = (err_linepos > #err_line) and " " or ""22 fmt_str = " %#{#tostring(err_linenum+context)}d|"24 pointer = (" ")\rep(err_linepos+#fmt_str\format(0)-1)..("^")\rep(err_size)25 --pointer = if err_size >= 226 -- (" ")\rep(err_linepos+#fmt_str\format(0)-1).."╚#{("═")\rep(err_size-2)}╝"27 --else28 -- (" ")\rep(err_linepos+#fmt_str\format(0)-1).."⬆"30 err_msg = C('bold red', err.title or "Error")..C('red', " at #{err.filename or '???'}:#{err_linenum},#{err_linepos}")31 err_msg ..= "\n" unless COLOR_ENABLED32 lines = err.source\lines!33 for i=err_linenum-context,err_linenum-134 if line = lines[i]35 err_msg ..= "\n"..C('dim', fmt_str\format(i))..line36 if err_line37 before = err_line\sub(1, err_linepos-1)38 during = err_line\sub(err_linepos,err_linepos+err_size-1)39 after = err_line\sub(err_linepos+err_size, -1)40 err_line = before..C('black on red', during..nl_indicator)..after41 err_msg ..= "\n"..C('dim', fmt_str\format(err_linenum))..err_line42 _, err_linenum_end, err_linepos_end = err.source\line_info_at(err.stop)43 err_linenum_end or= err_linenum44 if err_linenum_end == err_linenum45 err_msg ..= "\n#{pointer}"46 else47 for i=err_linenum+1,err_linenum_end48 if line = lines[i]49 if i == err_linenum_end50 during, after = line\sub(1,err_linepos_end-1), line\sub(err_linepos_end,-1)51 err_msg ..= "\n"..C('dim', fmt_str\format(i))..C('black on red', during)..after52 else53 err_msg ..= "\n"..C('dim', fmt_str\format(i))..C('black on red', line)54 if i > err_linenum+1 + 555 err_msg ..= "\n ...\n"56 break58 box_width = 7059 err_text = C('black on white', " "..err.error\wrapped_to(box_width, 16)\gsub("\n", "\n"..C('black on white').." "))60 if err.hint61 err_text ..= "\n"..C('italic black on white', (" Suggestion: #{err.hint}")\wrapped_to(box_width, 16)\gsub("\n", "\n"..C('italic black on white').." "))62 err_msg ..= "\n "..box(err_text)\gsub("\n", "\n ")63 err_msg ..= "\n" unless COLOR_ENABLED65 for i=err_linenum_end+1,err_linenum_end+context66 if line = lines[i]67 err_msg ..= "\n"..C('dim', fmt_str\format(i))..line68 err_msg ..= "\n" unless COLOR_ENABLED69 return err_msg71 return format_error