1 package termenv 2 3 import ( 4 "errors" 5 6 "github.com/mattn/go-isatty" 7 ) 8 9 var ( 10 // ErrStatusReport gets returned when the terminal can't be queried. 11 ErrStatusReport = errors.New("unable to retrieve status report") 12 ) 13 14 const ( 15 // Escape character 16 ESC = '\x1b' 17 // Bell 18 BEL = '\a' 19 // Control Sequence Introducer 20 CSI = string(ESC) + "[" 21 // Operating System Command 22 OSC = string(ESC) + "]" 23 // String Terminator 24 ST = string(ESC) + `\` 25 ) 26 27 func (o *Output) isTTY() bool { 28 if o.assumeTTY || o.unsafe { 29 return true 30 } 31 if len(o.environ.Getenv("CI")) > 0 { 32 return false 33 } 34 if o.TTY() == nil { 35 return false 36 } 37 38 return isatty.IsTerminal(o.TTY().Fd()) 39 } 40 41 // ColorProfile returns the supported color profile: 42 // Ascii, ANSI, ANSI256, or TrueColor. 43 func ColorProfile() Profile { 44 return output.ColorProfile() 45 } 46 47 // ForegroundColor returns the terminal's default foreground color. 48 func ForegroundColor() Color { 49 return output.ForegroundColor() 50 } 51 52 // BackgroundColor returns the terminal's default background color. 53 func BackgroundColor() Color { 54 return output.BackgroundColor() 55 } 56 57 // HasDarkBackground returns whether terminal uses a dark-ish background. 58 func HasDarkBackground() bool { 59 return output.HasDarkBackground() 60 } 61 62 // EnvNoColor returns true if the environment variables explicitly disable color output 63 // by setting NO_COLOR (https://no-color.org/) 64 // or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) 65 // If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE 66 // If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset. 67 func (o *Output) EnvNoColor() bool { 68 return o.environ.Getenv("NO_COLOR") != "" || (o.environ.Getenv("CLICOLOR") == "0" && !o.cliColorForced()) 69 } 70 71 // EnvNoColor returns true if the environment variables explicitly disable color output 72 // by setting NO_COLOR (https://no-color.org/) 73 // or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) 74 // If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE 75 // If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset. 76 func EnvNoColor() bool { 77 return output.EnvNoColor() 78 } 79 80 // EnvColorProfile returns the color profile based on environment variables set 81 // Supports NO_COLOR (https://no-color.org/) 82 // and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) 83 // If none of these environment variables are set, this behaves the same as ColorProfile() 84 // It will return the Ascii color profile if EnvNoColor() returns true 85 // If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0" 86 // then the ANSI color profile will be returned. 87 func EnvColorProfile() Profile { 88 return output.EnvColorProfile() 89 } 90 91 // EnvColorProfile returns the color profile based on environment variables set 92 // Supports NO_COLOR (https://no-color.org/) 93 // and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) 94 // If none of these environment variables are set, this behaves the same as ColorProfile() 95 // It will return the Ascii color profile if EnvNoColor() returns true 96 // If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0" 97 // then the ANSI color profile will be returned. 98 func (o *Output) EnvColorProfile() Profile { 99 if o.EnvNoColor() { 100 return Ascii 101 } 102 p := o.ColorProfile() 103 if o.cliColorForced() && p == Ascii { 104 return ANSI 105 } 106 return p 107 } 108 109 func (o *Output) cliColorForced() bool { 110 if forced := o.environ.Getenv("CLICOLOR_FORCE"); forced != "" { 111 return forced != "0" 112 } 113 return false 114 } 115