aboutsummaryrefslogtreecommitdiff
path: root/pretty_errors.moon
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-09-12 15:31:59 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-09-12 15:32:04 -0700
commitea310306d73e0bc6542f7133825549ae4471b06a (patch)
treefcc2a5a868fe09fb599d8261f66dad96ac69bb0b /pretty_errors.moon
parent9e10c8bf006f42e90a011b8f9284e3ffa52a5859 (diff)
Initial working version.
Diffstat (limited to 'pretty_errors.moon')
-rw-r--r--pretty_errors.moon46
1 files changed, 46 insertions, 0 deletions
diff --git a/pretty_errors.moon b/pretty_errors.moon
new file mode 100644
index 0000000..3adada5
--- /dev/null
+++ b/pretty_errors.moon
@@ -0,0 +1,46 @@
+-- This file has code for converting errors to user-friendly format, with colors,
+-- line numbers, code excerpts, and so on.
+require "containers"
+string2 = require 'string2'
+
+box = (text)->
+ max_line = 0
+ for line in text\gmatch("[^\n]+")
+ max_line = math.max(max_line, #(line\gsub("\027%[[0-9;]*m","")))
+ ret = ("\n"..text)\gsub "\n([^\n]*)", (line)->
+ line_len = #(line\gsub("\027%[[0-9;]*m",""))
+ return "\n#{line}#{(" ")\rep(max_line-line_len)} \027[0m"
+ return ret\sub(2,-1), max_line
+
+format_error = (err)->
+ context = err.context or 2
+ err_line, err_linenum, err_linepos = string2.line_at(err.source, err.start)
+ -- TODO: better handle multi-line errors
+ err_size = math.min((err.stop - err.start), (#err_line-err_linepos) + 1)
+ nl_indicator = (err_linepos > #err_line) and " " or ""
+ fmt_str = " %#{#tostring(err_linenum+context)}d|"
+ pointer = if err_size >= 2
+ (" ")\rep(err_linepos+#fmt_str\format(0)-1).."╚#{("═")\rep(err_size-2)}╝"
+ else
+ (" ")\rep(err_linepos+#fmt_str\format(0)-1).."⬆"
+ err_msg = "\027[33;41;1mParse error at #{err.filename}:#{err_linenum}\027[0m"
+ for i=err_linenum-context,err_linenum-1
+ if line = string2.line(err.source, i)
+ err_msg ..= "\n\027[2m#{fmt_str\format(i)}\027[0m#{line}\027[0m"
+ if err_line
+ box_width = 60
+ before = err_line\sub(1, err_linepos-1)
+ during = err_line\sub(err_linepos,err_linepos+err_size-1)
+ after = err_line\sub(err_linepos+err_size, -1)
+ err_line = "\027[0m#{before}\027[41;30m#{during}#{nl_indicator}\027[0m#{after}"
+ err_msg ..= "\n\027[2m#{fmt_str\format(err_linenum)}#{err_line}\027[0m\n#{pointer}"
+ err_text = "\027[47;31;1m#{(" "..err.error)\wrap_to_1(box_width)\gsub("\n", "\n\027[47;31;1m ")}"
+ if err.hint
+ err_text ..= "\n\027[47;30m#{(" Suggestion: #{err.hint}")\wrap_to_1(box_width)\gsub("\n", "\n\027[47;30m ")}"
+ err_msg ..= "\n\027[33;1m "..box(err_text)\gsub("\n", "\n ")
+ for i=err_linenum+1,err_linenum+context
+ if line = string2.line(err.source, i)
+ err_msg ..= "\n\027[2m#{fmt_str\format(i)}\027[0m#{line}\027[0m"
+ return err_msg
+
+return format_error