package color import ( "os" "strings" "sync" ) // ANSI color codes const ( resetCode = "\033[0m" redCode = "\033[31m" greenCode = "\033[32m" yellowCode = "\033[33m" blueCode = "\033[34m" purpleCode = "\033[35m" cyanCode = "\033[36m" whiteCode = "\033[37m" grayCode = "\033[90m" ) var ( useColors bool colorMu sync.RWMutex ) // Color function; makes a call to makeColorFunc with the associated color code var ( Reset = makeColorFunc(resetCode) Red = makeColorFunc(redCode) Green = makeColorFunc(greenCode) Yellow = makeColorFunc(yellowCode) Blue = makeColorFunc(blueCode) Purple = makeColorFunc(purpleCode) Cyan = makeColorFunc(cyanCode) White = makeColorFunc(whiteCode) Gray = makeColorFunc(grayCode) ) func init() { useColors = DetectShellColors() } func makeColorFunc(code string) func(string) string { return func(text string) string { colorMu.RLock() enabled := useColors colorMu.RUnlock() if enabled { return code + text + resetCode } return text } } // DetectShellColors checks if the current shell supports colors func DetectShellColors() bool { // Check NO_COLOR environment variable (standard) if os.Getenv("NO_COLOR") != "" { return false } // Check FORCE_COLOR environment variable if os.Getenv("FORCE_COLOR") != "" { return true } // Check if stdout is a terminal if !isTerminal(os.Stdout) { return false } // Check TERM environment variable term := os.Getenv("TERM") if term == "" || term == "dumb" { return false } // Common color-supporting terminals return strings.Contains(term, "color") || strings.Contains(term, "xterm") || strings.Contains(term, "screen") || strings.Contains(term, "tmux") || term == "linux" || isWindowsTerminal() } // SetColors enables or disables colors globally func SetColors(enabled bool) { colorMu.Lock() useColors = enabled colorMu.Unlock() } // ColorsEnabled returns current global color setting func ColorsEnabled() bool { colorMu.RLock() defer colorMu.RUnlock() return useColors }