package utils import ( "fmt" "strconv" "strings" ) // The error is a wrapper for the type ( Error struct { SourceType string // The type of source that failed to build. Title, Path, Description string // Description of the error, as presented to the user. Line, Column int // Where the error was encountered. SourceLines []string // The entire source file, split into lines. Stack string // The raw stack trace string from debug.Stack(). MetaError string // Error that occurred producing the error page. Link string // A configurable link to wrap the error source in } SourceLine struct { Source string Line int IsError bool } ) // Creates a link based on the configuration setting "errors.link" func (e *Error) SetLink(errorLink string) { errorLink = strings.Replace(errorLink, "{{Path}}", e.Path, -1) errorLink = strings.Replace(errorLink, "{{Line}}", strconv.Itoa(e.Line), -1) e.Link = "" + e.Path + ":" + strconv.Itoa(e.Line) + "" } // Error method constructs a plaintext version of the error, taking // account that fields are optionally set. Returns e.g. Compilation Error // (in views/header.html:51): expected right delim in end; got "}" func (e *Error) Error() string { if e == nil { panic("opps") } loc := "" if e.Path != "" { line := "" if e.Line != 0 { line = fmt.Sprintf(":%d", e.Line) } loc = fmt.Sprintf("(in %s%s)", e.Path, line) } header := loc if e.Title != "" { if loc != "" { header = fmt.Sprintf("%s %s: ", e.Title, loc) } else { header = fmt.Sprintf("%s: ", e.Title) } } return fmt.Sprintf("%s%s", header, e.Description) } // ContextSource method returns a snippet of the source around // where the error occurred. func (e *Error) ContextSource() []SourceLine { if e.SourceLines == nil { return nil } start := (e.Line - 1) - 5 if start < 0 { start = 0 } end := (e.Line - 1) + 5 if end > len(e.SourceLines) { end = len(e.SourceLines) } lines := make([]SourceLine, end-start) for i, src := range e.SourceLines[start:end] { fileLine := start + i + 1 lines[i] = SourceLine{src, fileLine, fileLine == e.Line} } return lines }