v3.42.32: Add fatih/color for cross-platform terminal colors
- Windows-compatible colors via native console API - Color helper functions: Success(), Error(), Warning(), Info() - Text styling: Header(), Dim(), Bold(), Green(), Red(), Yellow(), Cyan() - Logger CleanFormatter uses fatih/color instead of raw ANSI - All progress indicators use colored [OK]/[FAIL] status - Automatic color detection for non-TTY environments
This commit is contained in:
118
internal/logger/colors.go
Normal file
118
internal/logger/colors.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
// CLI output helpers using fatih/color for cross-platform support
|
||||
|
||||
// Success prints a success message with green checkmark
|
||||
func Success(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
SuccessColor.Fprint(os.Stdout, "✓ ")
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
// Error prints an error message with red X
|
||||
func Error(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
ErrorColor.Fprint(os.Stderr, "✗ ")
|
||||
fmt.Fprintln(os.Stderr, msg)
|
||||
}
|
||||
|
||||
// Warning prints a warning message with yellow exclamation
|
||||
func Warning(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
WarnColor.Fprint(os.Stdout, "⚠ ")
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
// Info prints an info message with blue arrow
|
||||
func Info(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
InfoColor.Fprint(os.Stdout, "→ ")
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
// Header prints a bold header
|
||||
func Header(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
HighlightColor.Println(msg)
|
||||
}
|
||||
|
||||
// Dim prints dimmed/secondary text
|
||||
func Dim(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
DimColor.Println(msg)
|
||||
}
|
||||
|
||||
// Bold returns bold text
|
||||
func Bold(text string) string {
|
||||
return color.New(color.Bold).Sprint(text)
|
||||
}
|
||||
|
||||
// Green returns green text
|
||||
func Green(text string) string {
|
||||
return SuccessColor.Sprint(text)
|
||||
}
|
||||
|
||||
// Red returns red text
|
||||
func Red(text string) string {
|
||||
return ErrorColor.Sprint(text)
|
||||
}
|
||||
|
||||
// Yellow returns yellow text
|
||||
func Yellow(text string) string {
|
||||
return WarnColor.Sprint(text)
|
||||
}
|
||||
|
||||
// Cyan returns cyan text
|
||||
func Cyan(text string) string {
|
||||
return InfoColor.Sprint(text)
|
||||
}
|
||||
|
||||
// StatusLine prints a key-value status line
|
||||
func StatusLine(key, value string) {
|
||||
DimColor.Printf(" %s: ", key)
|
||||
fmt.Println(value)
|
||||
}
|
||||
|
||||
// ProgressStatus prints operation status with timing
|
||||
func ProgressStatus(operation string, status string, isSuccess bool) {
|
||||
if isSuccess {
|
||||
SuccessColor.Print("[OK] ")
|
||||
} else {
|
||||
ErrorColor.Print("[FAIL] ")
|
||||
}
|
||||
fmt.Printf("%s: %s\n", operation, status)
|
||||
}
|
||||
|
||||
// Table prints a simple formatted table row
|
||||
func TableRow(cols ...string) {
|
||||
for i, col := range cols {
|
||||
if i == 0 {
|
||||
InfoColor.Printf("%-20s", col)
|
||||
} else {
|
||||
fmt.Printf("%-15s", col)
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// DisableColors disables all color output (for non-TTY or --no-color flag)
|
||||
func DisableColors() {
|
||||
color.NoColor = true
|
||||
}
|
||||
|
||||
// EnableColors enables color output
|
||||
func EnableColors() {
|
||||
color.NoColor = false
|
||||
}
|
||||
|
||||
// IsColorEnabled returns whether colors are enabled
|
||||
func IsColorEnabled() bool {
|
||||
return !color.NoColor
|
||||
}
|
||||
@@ -7,9 +7,29 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Color printers for consistent output across the application
|
||||
var (
|
||||
// Status colors
|
||||
SuccessColor = color.New(color.FgGreen, color.Bold)
|
||||
ErrorColor = color.New(color.FgRed, color.Bold)
|
||||
WarnColor = color.New(color.FgYellow, color.Bold)
|
||||
InfoColor = color.New(color.FgCyan)
|
||||
DebugColor = color.New(color.FgWhite)
|
||||
|
||||
// Highlight colors
|
||||
HighlightColor = color.New(color.FgMagenta, color.Bold)
|
||||
DimColor = color.New(color.FgHiBlack)
|
||||
|
||||
// Data colors
|
||||
NumberColor = color.New(color.FgYellow)
|
||||
PathColor = color.New(color.FgBlue, color.Underline)
|
||||
TimeColor = color.New(color.FgCyan)
|
||||
)
|
||||
|
||||
// Logger defines the interface for logging
|
||||
type Logger interface {
|
||||
Debug(msg string, args ...any)
|
||||
@@ -226,34 +246,32 @@ type CleanFormatter struct{}
|
||||
func (f *CleanFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
timestamp := entry.Time.Format("2006-01-02T15:04:05")
|
||||
|
||||
// Color codes for different log levels
|
||||
var levelColor, levelText string
|
||||
// Get level color and text using fatih/color
|
||||
var levelPrinter *color.Color
|
||||
var levelText string
|
||||
switch entry.Level {
|
||||
case logrus.DebugLevel:
|
||||
levelColor = "\033[36m" // Cyan
|
||||
levelPrinter = DebugColor
|
||||
levelText = "DEBUG"
|
||||
case logrus.InfoLevel:
|
||||
levelColor = "\033[32m" // Green
|
||||
levelPrinter = SuccessColor
|
||||
levelText = "INFO "
|
||||
case logrus.WarnLevel:
|
||||
levelColor = "\033[33m" // Yellow
|
||||
levelPrinter = WarnColor
|
||||
levelText = "WARN "
|
||||
case logrus.ErrorLevel:
|
||||
levelColor = "\033[31m" // Red
|
||||
levelPrinter = ErrorColor
|
||||
levelText = "ERROR"
|
||||
default:
|
||||
levelColor = "\033[0m" // Reset
|
||||
levelPrinter = InfoColor
|
||||
levelText = "INFO "
|
||||
}
|
||||
resetColor := "\033[0m"
|
||||
|
||||
// Build the message with perfectly aligned columns
|
||||
var output strings.Builder
|
||||
|
||||
// Column 1: Level (with color, fixed width 5 chars)
|
||||
output.WriteString(levelColor)
|
||||
output.WriteString(levelText)
|
||||
output.WriteString(resetColor)
|
||||
output.WriteString(levelPrinter.Sprint(levelText))
|
||||
output.WriteString(" ")
|
||||
|
||||
// Column 2: Timestamp (fixed format)
|
||||
|
||||
Reference in New Issue
Block a user