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