2022-08-17 22:56:45 -06:00
|
|
|
package infoerr
|
2022-08-09 00:25:45 -06:00
|
|
|
|
2022-08-09 18:12:33 -06:00
|
|
|
import "os"
|
2022-08-09 00:25:45 -06:00
|
|
|
import "fmt"
|
2022-08-29 23:11:10 -06:00
|
|
|
import "git.tebibyte.media/arf/arf/file"
|
2022-08-09 00:25:45 -06:00
|
|
|
|
|
|
|
type ErrorKind int
|
|
|
|
|
|
|
|
const (
|
|
|
|
ErrorKindError ErrorKind = iota
|
|
|
|
ErrorKindWarn
|
|
|
|
)
|
|
|
|
|
|
|
|
type Error struct {
|
2022-08-17 22:51:19 -06:00
|
|
|
file.Location
|
2022-08-09 00:25:45 -06:00
|
|
|
message string
|
|
|
|
kind ErrorKind
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewError creates a new error at the specified location.
|
|
|
|
func NewError (
|
2022-08-17 22:51:19 -06:00
|
|
|
location file.Location,
|
2022-08-09 00:25:45 -06:00
|
|
|
message string,
|
|
|
|
kind ErrorKind,
|
|
|
|
) (
|
2022-08-12 12:51:38 -06:00
|
|
|
err Error,
|
2022-08-09 00:25:45 -06:00
|
|
|
) {
|
2022-10-12 10:39:00 -06:00
|
|
|
if location.File() == nil {
|
|
|
|
panic("cannot create new Error in a blank file")
|
|
|
|
}
|
|
|
|
|
2022-08-12 12:51:38 -06:00
|
|
|
return Error {
|
2022-08-09 00:25:45 -06:00
|
|
|
Location: location,
|
|
|
|
message: message,
|
|
|
|
kind: kind,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error returns a formatted error message as a string.
|
|
|
|
func (err Error) Error () (formattedMessage string) {
|
|
|
|
switch err.kind {
|
|
|
|
case ErrorKindError:
|
2022-08-11 12:15:57 -06:00
|
|
|
formattedMessage += "\033[31mERR\033[0m"
|
2022-08-09 00:25:45 -06:00
|
|
|
case ErrorKindWarn:
|
2022-08-11 12:15:57 -06:00
|
|
|
formattedMessage += "\033[33m!!!\033[0m"
|
2022-08-09 00:25:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// print information about the location of the mistake
|
2022-08-17 22:51:19 -06:00
|
|
|
if err.Width() > 0 {
|
2022-08-09 00:25:45 -06:00
|
|
|
formattedMessage += fmt.Sprint (
|
2022-08-17 22:51:19 -06:00
|
|
|
" \033[34m", err.Row() + 1,
|
|
|
|
":", err.Column() + 1)
|
2022-08-09 00:25:45 -06:00
|
|
|
}
|
2022-08-11 12:15:57 -06:00
|
|
|
formattedMessage +=
|
|
|
|
" \033[90min\033[0m " +
|
2022-08-17 22:51:19 -06:00
|
|
|
err.File().Path() + "\n"
|
2022-08-09 00:25:45 -06:00
|
|
|
|
2022-08-17 22:51:19 -06:00
|
|
|
if err.Width() > 0 {
|
2022-08-09 00:25:45 -06:00
|
|
|
// print erroneous line
|
2022-08-17 22:51:19 -06:00
|
|
|
line := err.File().GetLine(err.Row())
|
|
|
|
formattedMessage += line + "\n"
|
2022-08-09 00:25:45 -06:00
|
|
|
|
2022-08-15 12:30:54 -06:00
|
|
|
// position error marker
|
|
|
|
var index int
|
2022-08-17 22:51:19 -06:00
|
|
|
for index = 0; index < err.Column(); index ++ {
|
2022-08-15 12:30:54 -06:00
|
|
|
if line[index] == '\t' {
|
|
|
|
formattedMessage += "\t"
|
|
|
|
} else {
|
|
|
|
formattedMessage += " "
|
|
|
|
}
|
2022-08-09 00:25:45 -06:00
|
|
|
}
|
2022-08-15 12:30:54 -06:00
|
|
|
|
|
|
|
// print an arrow with a tail spanning the width of the mistake
|
2022-08-18 00:04:49 -06:00
|
|
|
for index < err.Column() + err.Width() - 1 {
|
2022-08-15 12:30:54 -06:00
|
|
|
if line[index] == '\t' {
|
|
|
|
formattedMessage += "--------"
|
|
|
|
} else {
|
|
|
|
formattedMessage += "-"
|
|
|
|
}
|
|
|
|
index ++
|
2022-08-09 00:25:45 -06:00
|
|
|
}
|
2022-08-15 12:30:54 -06:00
|
|
|
|
2022-08-10 12:08:04 -06:00
|
|
|
formattedMessage += "^\n"
|
2022-08-09 00:25:45 -06:00
|
|
|
}
|
2022-08-10 12:08:04 -06:00
|
|
|
formattedMessage += err.message + "\n"
|
2022-08-09 00:25:45 -06:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2022-08-09 18:12:33 -06:00
|
|
|
|
|
|
|
// Print formats the error and prints it to stderr.
|
|
|
|
func (err Error) Print () {
|
|
|
|
os.Stderr.Write([]byte(err.Error()))
|
|
|
|
}
|
2022-08-17 22:39:08 -06:00
|
|
|
|
|
|
|
// Message returns the error's message string
|
|
|
|
func (err Error) Message () (message string) {
|
|
|
|
return err.message
|
|
|
|
}
|
|
|
|
|
|
|
|
// Kind returns what kind of error the error is.
|
|
|
|
func (err Error) Kind () (kind ErrorKind) {
|
|
|
|
return err.kind
|
|
|
|
}
|