package diag
import (
)
type Context struct {
Name string
Source string
Ranging
savedShowInfo *rangeShowInfo
}
func (, string, Ranger) *Context {
return &Context{, , .Range(), nil}
}
type rangeShowInfo struct {
Head string
Culprit string
Tail string
BeginLine int
EndLine int
}
var (
culpritLineBegin = "\033[1;4m"
culpritLineEnd = "\033[m"
culpritPlaceHolder = "^"
)
func ( *Context) () string {
return .Source[.From:.To]
}
func ( *Context) () *rangeShowInfo {
if .savedShowInfo != nil {
return .savedShowInfo
}
:= .Source[:.From]
:= .Source[.From:.To]
:= .Source[.To:]
:= lastLine()
:= strings.Count(, "\n") + 1
var string
if strings.HasSuffix(, "\n") {
= [:len()-1]
} else {
= firstLine()
}
:= + strings.Count(, "\n")
.savedShowInfo = &rangeShowInfo{, , , , }
return .savedShowInfo
}
func ( *Context) ( string) string {
if := .checkPosition(); != nil {
return .Error()
}
return (.Name + ", " + .lineRange() +
"\n" + + .relevantSource())
}
func ( *Context) ( string) string {
if := .checkPosition(); != nil {
return .Error()
}
:= .Name + ", " + .lineRange() + " "
:= strings.Repeat(" ", wcwidth.Of())
return + .relevantSource(+)
}
func ( *Context) () error {
if .From == -1 {
return fmt.Errorf("%s, unknown position", .Name)
} else if .From < 0 || .To > len(.Source) || .From > .To {
return fmt.Errorf("%s, invalid position %d-%d", .Name, .From, .To)
}
return nil
}
func ( *Context) () string {
:= .showInfo()
if .BeginLine == .EndLine {
return fmt.Sprintf("line %d:", .BeginLine)
}
return fmt.Sprintf("line %d-%d:", .BeginLine, .EndLine)
}
func ( *Context) ( string) string {
:= .showInfo()
var bytes.Buffer
.WriteString(.Head)
:= .Culprit
if == "" {
= culpritPlaceHolder
}
for , := range strings.Split(, "\n") {
if > 0 {
.WriteByte('\n')
.WriteString()
}
.WriteString(culpritLineBegin)
.WriteString()
.WriteString(culpritLineEnd)
}
.WriteString(.Tail)
return .String()
}
func ( string) string {
:= strings.IndexByte(, '\n')
if == -1 {
return
}
return [:]
}
func ( string) string {
return [strings.LastIndexByte(, '\n')+1:]
}