// Copyright 2026 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "bytes" "fmt" "strings" ) // labelWidth leaves one space after the longest label. Increase this if labels // change and the tables get out of alignment. const labelWidth = 47 // section writes a section heading and the tasks that move the figures in it. // A tag long enough to push the heading past the line budget goes on its own // line rather than trailing off the screen. func section(w *bytes.Buffer, title, tasks string) { head := "## " + title if tag := taskTag(tasks); tag != "" { if len(head)+len(tag)+1 <= 88 { head += " " + tag } else { head += "\n " + strings.TrimSpace(tag) } } fmt.Fprintf(w, "\n\n%s\n\n", head) } // note writes a block of explanatory prose, followed by a blank line. func note(w *bytes.Buffer, text string) { fmt.Fprintf(w, "%s\n\n", text) } // frac writes a figure heading for 100%. func frac(w *bytes.Buffer, label string, r result, tasks string) { pct := " --" if r.d > 0 { pct = fmt.Sprintf("%3.0f%%", 100*float64(r.n)/float64(r.d)) } line(w, fmt.Sprintf("%-*s %5d / %-5d %s%s", labelWidth, label, r.n, r.d, pct, taskTag(tasks))) } // count writes a figure heading for zero. func count(w *bytes.Buffer, label string, n int, tasks string) { line(w, fmt.Sprintf("%-*s %5d %-9s%s", labelWidth, label, n, "-> 0", taskTag(tasks))) } // kv writes a bare number: context rather than a figure with a target. func kv(w *bytes.Buffer, label string, n int) { line(w, fmt.Sprintf("%-*s %5d", labelWidth, label, n)) } // sub writes a bare number indented under the figure it breaks down. func sub(w *bytes.Buffer, label string, n int) { line(w, fmt.Sprintf(" %-*s %5d", labelWidth-4, label, n)) } // countIndented writes a count heading for zero, indented under the figure it // breaks down. Used for per-field and per-file detail rows. func countIndented(w *bytes.Buffer, label string, n int, tasks string) { line(w, fmt.Sprintf(" %-*s %5d %-9s%s", labelWidth-4, label, n, "-> 0", taskTag(tasks))) } // emptyList writes a placeholder when a list has no rows, so that a heading // with nothing under it reads as an empty list rather than a truncated one. func emptyList(w *bytes.Buffer, n int) { if n == 0 { line(w, " (none)") } } const lineWrap = 78 // wrap writes lead followed by a list of words, breaking before the line // wrapping budget and aligning continuations under the first word. The lead // labels the list, so that an inventory nested under a table row says what it // is rather than leaving the reader to infer it from position. func wrap(w *bytes.Buffer, indent, lead string, words []string) { first, rest := indent+lead, indent+strings.Repeat(" ", len(lead)) cur := first for _, s := range words { if len(cur) > len(rest) && len(cur)+1+len(s) > lineWrap { line(w, cur) cur = rest } if len(cur) > len(rest) { cur += " " } cur += s } if len(cur) > len(rest) { line(w, cur) } } func line(w *bytes.Buffer, s string) { fmt.Fprintf(w, "%s\n", strings.TrimRight(s, " ")) } func taskTag(tasks string) string { if tasks == "" || tasks == "-" { return "" } return " [" + tasks + "]" }