feat(ui): add colored, structured CLI output
ci / vet, staticcheck, test, build (push) Successful in 3m15s
ci / vet, staticcheck, test, build (push) Successful in 3m15s
Replace flat "info:" / "warning:" stderr lines with: - logStep (·), logDone (✓), logWarn (!) prefix symbols - ANSI colors when stderr is a TTY; auto-disabled via NO_COLOR or TERM=dumb - Verbose mode uses ▸ section headers (configuration / branch / commits / version) - Config table source tags colored: dim=[default], bold=[config file], cyan=[env:], green=[flag:] - Commit table in verbose mode: type column colored by kind (cyan=feat, green=fix, red=breaking), ignored commits dimmed - New cmd/ui.go holds all color helpers (paint, logStep, logDone, logWarn, logSection, fmtSource); removes the vlog() helper Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
ansiReset = "\033[0m"
|
||||
ansiBold = "\033[1m"
|
||||
ansiDim = "\033[2m"
|
||||
ansiRed = "\033[31m"
|
||||
ansiGreen = "\033[32m"
|
||||
ansiYellow = "\033[33m"
|
||||
ansiCyan = "\033[36m"
|
||||
)
|
||||
|
||||
var useColor bool
|
||||
|
||||
func init() {
|
||||
fi, err := os.Stderr.Stat()
|
||||
tty := err == nil && (fi.Mode()&os.ModeCharDevice) != 0
|
||||
useColor = tty && os.Getenv("NO_COLOR") == "" && os.Getenv("TERM") != "dumb"
|
||||
}
|
||||
|
||||
func paint(code, s string) string {
|
||||
if !useColor {
|
||||
return s
|
||||
}
|
||||
return code + s + ansiReset
|
||||
}
|
||||
|
||||
// logStep writes a neutral progress line to stderr.
|
||||
func logStep(format string, args ...any) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
fmt.Fprintf(os.Stderr, " %s %s\n", paint(ansiDim, "·"), msg)
|
||||
}
|
||||
|
||||
// logDone writes a success completion line to stderr.
|
||||
func logDone(format string, args ...any) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
fmt.Fprintf(os.Stderr, " %s %s\n", paint(ansiGreen+ansiBold, "✓"), msg)
|
||||
}
|
||||
|
||||
// logWarn writes a warning line to stderr.
|
||||
func logWarn(format string, args ...any) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
fmt.Fprintf(os.Stderr, " %s %s\n", paint(ansiYellow, "!"), msg)
|
||||
}
|
||||
|
||||
// logSection writes a bold section header to stderr (used in verbose mode).
|
||||
func logSection(title string) {
|
||||
fmt.Fprintf(os.Stderr, "\n%s\n", paint(ansiBold, "▸ "+title))
|
||||
}
|
||||
|
||||
// fmtSource returns a colored "[source]" tag for a config key source.
|
||||
func fmtSource(src string) string {
|
||||
switch {
|
||||
case strings.HasPrefix(src, "env:"):
|
||||
return paint(ansiCyan, "["+src+"]")
|
||||
case strings.HasPrefix(src, "flag:"):
|
||||
return paint(ansiGreen, "["+src+"]")
|
||||
case src == "default":
|
||||
return paint(ansiDim, "[default]")
|
||||
default: // "config file"
|
||||
return paint(ansiBold, "["+src+"]")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user