This repository has been archived on 2022-08-29. You can view files and clone it, but cannot push or open issues or pull requests.
arf/file/error.go

90 lines
1.7 KiB
Go

package file
import "os"
import "fmt"
type ErrorKind int
const (
ErrorKindError ErrorKind = iota
ErrorKindWarn
)
type Error struct {
Location
message string
kind ErrorKind
}
// NewError creates a new error at the specified location.
func NewError (
location Location,
message string,
kind ErrorKind,
) (
err Error,
) {
return Error {
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:
formattedMessage += "\033[31mERR\033[0m"
case ErrorKindWarn:
formattedMessage += "\033[33m!!!\033[0m"
}
// print information about the location of the mistake
if err.width > 0 {
formattedMessage += fmt.Sprint (
" \033[34m", err.Location.row + 1,
":", err.Location.column + 1)
}
formattedMessage +=
" \033[90min\033[0m " +
err.Location.file.path + "\n"
if err.width > 0 {
// print erroneous line
line := err.Location.file.lines[err.Location.row]
formattedMessage +=
err.Location.file.lines[err.Location.row] + "\n"
// position error marker
var index int
for index = 0; index < err.Location.column; index ++ {
if line[index] == '\t' {
formattedMessage += "\t"
} else {
formattedMessage += " "
}
}
// print an arrow with a tail spanning the width of the mistake
for err.width > 1 {
if line[index] == '\t' {
formattedMessage += "--------"
} else {
formattedMessage += "-"
}
index ++
}
formattedMessage += "^\n"
}
formattedMessage += err.message + "\n"
return
}
// Print formats the error and prints it to stderr.
func (err Error) Print () {
os.Stderr.Write([]byte(err.Error()))
}