Something went wrong. Try again.
background code checker for golang
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297package gust
import ( "fmt" "strconv" "strings" "time" "unicode/utf8"
"github.com/charmbracelet/lipgloss" "github.com/muesli/reflow/wordwrap")
func (m Model) View() string { var b strings.Builder
b.WriteString(m.viewStatus())
m.viewport.SetContent(m.viewBody()) b.WriteString(m.viewport.View())
b.WriteString("\n")
b.WriteString(m.viewHelp())
return b.String()}
func (m Model) viewBody() string { style := m.config.Styles sign := m.config.Signs
var b strings.Builder if m.config.Mode == "build" || m.end != nil && m.process.cmd.ProcessState.ExitCode() != 0 { b.WriteString(m.viewBuild()) } else { b.WriteString(m.viewRun()) }
for _, o := range m.extra { b.WriteString(style.Error.Render(sign.System)) b.WriteString(" ") b.WriteString(o) b.WriteString("\n") }
for _, e := range m.systemErrors { b.WriteString(style.Error.Render(sign.System)) b.WriteString(" ") b.WriteString(e.Error()) b.WriteString("\n") }
b.WriteString("\n") return b.String()}
func (m Model) viewBuild() string { var b strings.Builder maxLineLen := 1 maxColLen := 1 style := m.config.Styles sign := m.config.Signs
for _, msg := range m.messages { lineLen := len(msg.Location.Line) colLen := len(msg.Location.Column)
if lineLen > maxLineLen { maxLineLen = lineLen } if colLen > maxColLen { maxColLen = colLen } }
for _, msg := range m.messages { var mb strings.Builder if msg.Type == "error" { mb.WriteString(style.Error.Render(sign.Error)) mb.WriteString(" ") } else { mb.WriteString(style.Warning.Render(sign.Warning)) mb.WriteString(" ") }
if msg.Location.Line != "" { mb.WriteString(style.Line.Align(lipgloss.Right).Width(maxLineLen).Render(msg.Location.Line))
if msg.Location.Column != "" { mb.WriteString(":") mb.WriteString(style.Line.Align(lipgloss.Left).Width(maxColLen).Render(msg.Location.Column)) } } if msg.Location.File != "" { mb.WriteString(" ") mb.WriteString(style.File.Render(msg.Location.File)) mb.WriteString(" ") }
mb.WriteString(msg.Message)
b.WriteString(wordwrap.String(mb.String(), m.width))
// display context if !m.config.Summarized { b.WriteString("\n") start := msg.Context.Start() style := style.Context for offset, line := range msg.Context.Ordered() { nr := fmt.Sprintf("%d", start+offset) nrStyle := style.PassiveLineNr lineStyle := style.PassiveLine indent := sign.PassiveIndent active := false if msg.Location.Line == nr { active = true nrStyle = style.ActiveLineNr lineStyle = style.ActiveLine indent = sign.ActiveIndent } b.WriteString(nrStyle.Render(indent)) b.WriteString(nrStyle.Align(lipgloss.Right).Render(nr)) b.WriteString(" ")
simplifiedLine := strings.ReplaceAll(line, "\t", " ") b.WriteString(lineStyle.Render(simplifiedLine)) // makes this easier to reason about if active && msg.Location.Column != "" { col, _ := strconv.Atoi(msg.Location.Column) // special logic to handle tab characters in the target line tabCount := strings.Count(line[:col-1], "\t")
b.WriteString("\n") b.WriteString(style.PassiveLineNr.Render(sign.PassiveIndent))
leftPadding := col + // current column to place the pointer at 3*tabCount + // if the line has tabs, we convert to spaces and offset len(msg.Location.Line) + // we always print line-numbers, so offset by that too 1 // there is a single space between line-number and line content b.WriteString(style.ActiveLineNr.Width(leftPadding).Align(lipgloss.Right).Render("^")) } b.WriteString("\n") } }
b.WriteString("\n") }
return b.String()}
func (m Model) viewRun() string { var b strings.Builder
if m.config.Stream == "stderr" { b.WriteString(m.stderr()) } else { b.WriteString(m.stdout()) }
return b.String()}
func (m Model) viewStatus() string { var b strings.Builder
errorCount := 0 warningCount := 0 for _, msg := range m.messages { if msg.Type == "error" { errorCount++ } else if msg.Type == "warning" { warningCount++ } }
style := m.config.Styles sign := m.config.Signs
// write mode b.WriteString(style.Mode.Render(m.config.Mode))
// write status statusStyle := style.Success switch m.status.Kind { case Running, Initializing: statusStyle = style.Running case Error: statusStyle = style.Error } if len(m.messages) == 0 { b.WriteString(style.Separator.Render(sign.Separator)) b.WriteString(statusStyle.Render(m.status.View())) }
plural := func(s string, n int) string { if n == 1 { return s } else { return fmt.Sprintf("%ss", s) } }
// write message summary if errorCount != 0 { b.WriteString(style.Separator.Render(sign.Separator)) b.WriteString(style.Error.Render(fmt.Sprintf("%d %s", errorCount, plural("error", errorCount)))) } if warningCount != 0 { b.WriteString(style.Separator.Render(sign.Separator)) b.WriteString(style.Warning.Render(fmt.Sprintf("%d %s", warningCount, plural("warning", warningCount)))) }
b.WriteString(style.Separator.Render(sign.Separator))
if m.start != nil && m.end != nil { b.WriteString(style.Duration.Render(m.end.Sub(*m.start).String())) } else if m.start != nil && m.end == nil { b.WriteString(style.Duration.Render(time.Now().Sub(*m.start).String())) }
b.WriteString(" ") line := strings.Repeat(sign.HorizontalBar, max(0, (m.viewport.Width-lipgloss.Width(b.String()))/utf8.RuneCountInString(sign.HorizontalBar))) b.WriteString(style.Separator.Render(line))
b.WriteString("\n")
return b.String()}
func (m Model) viewHelp() string { if !m.config.Help { return "" }
var b strings.Builder style := m.config.Styles sign := m.config.Signs
b.WriteString("s ") if m.config.Summarized { b.WriteString(style.Separator.Render("show context")) } else { b.WriteString(style.Separator.Render("hide context")) } b.WriteString(style.Separator.Render(sign.Separator))
if m.config.Mode != "build" { b.WriteString("b ") b.WriteString(style.Separator.Render("build")) b.WriteString(style.Separator.Render(sign.Separator))
b.WriteString("o ") if m.config.Stream != "stdout" { b.WriteString(style.Separator.Render("stdout")) b.WriteString(style.Separator.Render(sign.Separator)) } if m.config.Stream != "stderr" { b.WriteString(style.Separator.Render("stderr")) b.WriteString(style.Separator.Render(sign.Separator)) } }
if m.config.Mode != "run" { b.WriteString("r ") b.WriteString(style.Separator.Render("run")) b.WriteString(style.Separator.Render(sign.Separator)) }
b.WriteString("q ") b.WriteString(style.Separator.Render("quit")) b.WriteString(style.Separator.Render(sign.Separator))
b.WriteString("h/? ") b.WriteString(style.Separator.Render("hide help")) b.WriteString(" ")
var rightStatus strings.Builder rightStatus.WriteString(" ") if m.config.Mode == "run" { if m.config.Stream == "stderr" { rightStatus.WriteString(style.Stderr.Render("stderr")) } else { rightStatus.WriteString(style.Stdout.Render("stdout")) } rightStatus.WriteString(style.Separator.Render(sign.Separator)) } rightStatus.WriteString(fmt.Sprintf("%3.f%%", m.viewport.ScrollPercent()*100))
right := rightStatus.String() line := strings.Repeat(sign.HorizontalBar, max(0, (m.viewport.Width-lipgloss.Width(b.String())-lipgloss.Width(right))/utf8.RuneCountInString(sign.HorizontalBar))) b.WriteString(style.Separator.Render(line)) b.WriteString(style.Duration.Render(right))
return lipgloss.NewStyle().Render(b.String())}