1/* 2Package color is Command line color library. 3Support rich color rendering output, universal API method, compatible with Windows system 4 5Source code and other details for the project are available at GitHub: 6 7 https://github.com/gookit/color 8 9More usage please see README and tests. 10*/ 11package color 12 13import ( 14 "fmt" 15 "io" 16 "os" 17 "regexp" 18 19 "github.com/xo/terminfo" 20) 21 22// terminal color available level alias of the terminfo.ColorLevel* 23const ( 24 LevelNo = terminfo.ColorLevelNone // not support color. 25 Level16 = terminfo.ColorLevelBasic // 3/4 bit color supported 26 Level256 = terminfo.ColorLevelHundreds // 8 bit color supported 27 LevelRgb = terminfo.ColorLevelMillions // (24 bit)true color supported 28) 29 30// color render templates 31// ESC 操作的表示: 32// "\033"(Octal 8进制) = "\x1b"(Hexadecimal 16进制) = 27 (10进制) 33const ( 34 SettingTpl = "\x1b[%sm" 35 FullColorTpl = "\x1b[%sm%s\x1b[0m" 36) 37 38// ResetSet Close all properties. 39const ResetSet = "\x1b[0m" 40 41// CodeExpr regex to clear color codes eg "\033[1;36mText\x1b[0m" 42const CodeExpr = `\033\[[\d;?]+m` 43 44var ( 45 // Enable switch color render and display 46 // 47 // NOTICE: 48 // if ENV: NO_COLOR is not empty, will disable color render. 49 Enable = os.Getenv("NO_COLOR") == "" 50 // RenderTag render HTML tag on call color.Xprint, color.PrintX 51 RenderTag = true 52 // debug mode for development. 53 // 54 // set env: 55 // COLOR_DEBUG_MODE=on 56 // or: 57 // COLOR_DEBUG_MODE=on go run ./_examples/envcheck.go 58 debugMode = os.Getenv("COLOR_DEBUG_MODE") == "on" 59 // inner errors record on detect color level 60 innerErrs []error 61 // output the default io.Writer message print 62 output io.Writer = os.Stdout 63 // mark current env, It's like in `cmd.exe` 64 // if not in windows, it's always is False. 65 isLikeInCmd bool 66 // the color support level for current terminal 67 // needVTP - need enable VTP, only for windows OS 68 colorLevel, needVTP = detectTermColorLevel() 69 // match color codes 70 codeRegex = regexp.MustCompile(CodeExpr) 71 // mark current env is support color. 72 // Always: isLikeInCmd != supportColor 73 // supportColor = IsSupportColor() 74) 75 76// TermColorLevel value on current ENV 77func TermColorLevel() terminfo.ColorLevel { 78 return colorLevel 79} 80 81// SupportColor on the current ENV 82func SupportColor() bool { 83 return colorLevel > terminfo.ColorLevelNone 84} 85 86// Support16Color on the current ENV 87// func Support16Color() bool { 88// return colorLevel > terminfo.ColorLevelNone 89// } 90 91// Support256Color on the current ENV 92func Support256Color() bool { 93 return colorLevel > terminfo.ColorLevelBasic 94} 95 96// SupportTrueColor on the current ENV 97func SupportTrueColor() bool { 98 return colorLevel > terminfo.ColorLevelHundreds 99} 100 101/************************************************************* 102 * global settings 103 *************************************************************/ 104 105// Set set console color attributes 106func Set(colors ...Color) (int, error) { 107 code := Colors2code(colors...) 108 err := SetTerminal(code) 109 return 0, err 110} 111 112// Reset reset console color attributes 113func Reset() (int, error) { 114 err := ResetTerminal() 115 return 0, err 116} 117 118// Disable disable color output 119func Disable() bool { 120 oldVal := Enable 121 Enable = false 122 return oldVal 123} 124 125// NotRenderTag on call color.Xprint, color.PrintX 126func NotRenderTag() { 127 RenderTag = false 128} 129 130// SetOutput set default colored text output 131func SetOutput(w io.Writer) { 132 output = w 133} 134 135// ResetOutput reset output 136func ResetOutput() { 137 output = os.Stdout 138} 139 140// ResetOptions reset all package option setting 141func ResetOptions() { 142 RenderTag = true 143 Enable = true 144 output = os.Stdout 145} 146 147// ForceColor force open color render 148func ForceSetColorLevel(level terminfo.ColorLevel) terminfo.ColorLevel { 149 oldLevelVal := colorLevel 150 colorLevel = level 151 return oldLevelVal 152} 153 154// ForceColor force open color render 155func ForceColor() terminfo.ColorLevel { 156 return ForceOpenColor() 157} 158 159// ForceOpenColor force open color render 160func ForceOpenColor() terminfo.ColorLevel { 161 // TODO should set level to ? 162 return ForceSetColorLevel(terminfo.ColorLevelMillions) 163} 164 165// IsLikeInCmd check result 166// Deprecated 167func IsLikeInCmd() bool { 168 return isLikeInCmd 169} 170 171// InnerErrs info 172func InnerErrs() []error { 173 return innerErrs 174} 175 176/************************************************************* 177 * render color code 178 *************************************************************/ 179 180// RenderCode render message by color code. 181// Usage: 182// msg := RenderCode("3;32;45", "some", "message") 183func RenderCode(code string, args ...interface{}) string { 184 var message string 185 if ln := len(args); ln == 0 { 186 return "" 187 } 188 189 message = fmt.Sprint(args...) 190 if len(code) == 0 { 191 return message 192 } 193 194 // disabled OR not support color 195 if !Enable || !SupportColor() { 196 return ClearCode(message) 197 } 198 199 return fmt.Sprintf(FullColorTpl, code, message) 200} 201 202// RenderWithSpaces Render code with spaces. 203// If the number of args is > 1, a space will be added between the args 204func RenderWithSpaces(code string, args ...interface{}) string { 205 message := formatArgsForPrintln(args) 206 if len(code) == 0 { 207 return message 208 } 209 210 // disabled OR not support color 211 if !Enable || !SupportColor() { 212 return ClearCode(message) 213 } 214 215 return fmt.Sprintf(FullColorTpl, code, message) 216} 217 218// RenderString render a string with color code. 219// Usage: 220// msg := RenderString("3;32;45", "a message") 221func RenderString(code string, str string) string { 222 if len(code) == 0 || str == "" { 223 return str 224 } 225 226 // disabled OR not support color 227 if !Enable || !SupportColor() { 228 return ClearCode(str) 229 } 230 231 return fmt.Sprintf(FullColorTpl, code, str) 232} 233 234// ClearCode clear color codes. 235// eg: "\033[36;1mText\x1b[0m" -> "Text" 236func ClearCode(str string) string { 237 return codeRegex.ReplaceAllString(str, "") 238} 239