github.com/jd-ly/cmd@v1.0.10/utils/error.go (about) 1 package utils 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 ) 8 9 // The error is a wrapper for the 10 type ( 11 SourceError struct { 12 SourceType string // The type of source that failed to build. 13 Title, Path, Description string // Description of the error, as presented to the user. 14 Line, Column int // Where the error was encountered. 15 SourceLines []string // The entire source file, split into lines. 16 Stack string // The raw stack trace string from debug.Stack(). 17 MetaError string // Error that occurred producing the error page. 18 Link string // A configurable link to wrap the error source in 19 } 20 SourceLine struct { 21 Source string 22 Line int 23 IsError bool 24 } 25 ) 26 // Return a new error object 27 func NewError(source, title, path, description string) *SourceError { 28 return &SourceError{ 29 SourceType:source, 30 Title:title, 31 Path:path, 32 Description:description, 33 } 34 } 35 36 // Creates a link based on the configuration setting "errors.link" 37 func (e *SourceError) SetLink(errorLink string) { 38 errorLink = strings.Replace(errorLink, "{{Path}}", e.Path, -1) 39 errorLink = strings.Replace(errorLink, "{{Line}}", strconv.Itoa(e.Line), -1) 40 41 e.Link = "<a href=" + errorLink + ">" + e.Path + ":" + strconv.Itoa(e.Line) + "</a>" 42 } 43 44 // Error method constructs a plaintext version of the error, taking 45 // account that fields are optionally set. Returns e.g. Compilation Error 46 // (in views/header.html:51): expected right delim in end; got "}" 47 func (e *SourceError) Error() string { 48 if e == nil { 49 panic("opps") 50 } 51 loc := "" 52 if e.Path != "" { 53 line := "" 54 if e.Line != 0 { 55 line = fmt.Sprintf(":%d", e.Line) 56 } 57 loc = fmt.Sprintf("(in %s%s)", e.Path, line) 58 } 59 header := loc 60 if e.Title != "" { 61 if loc != "" { 62 header = fmt.Sprintf("%s %s: ", e.Title, loc) 63 } else { 64 header = fmt.Sprintf("%s: ", e.Title) 65 } 66 } 67 return fmt.Sprintf("%s%s", header, e.Description) 68 } 69 70 // ContextSource method returns a snippet of the source around 71 // where the error occurred. 72 func (e *SourceError) ContextSource() []SourceLine { 73 if e.SourceLines == nil { 74 return nil 75 } 76 start := (e.Line - 1) - 5 77 if start < 0 { 78 start = 0 79 } 80 end := (e.Line - 1) + 5 81 if end > len(e.SourceLines) { 82 end = len(e.SourceLines) 83 } 84 85 lines := make([]SourceLine, end - start) 86 for i, src := range e.SourceLines[start:end] { 87 fileLine := start + i + 1 88 lines[i] = SourceLine{src, fileLine, fileLine == e.Line} 89 } 90 return lines 91 }