diff --git a/color.go b/color.go index b2795fed..1e0eb5a8 100644 --- a/color.go +++ b/color.go @@ -19,7 +19,8 @@ var ( // set (regardless of its value). This is a global option and affects all // colors. For more control over each color block use the methods // DisableColor() individually. - NoColor = noColorIsSet() || os.Getenv("TERM") == "dumb" || + // NOTE: NO_COLOR environment variable will only be checked at init. + NoColor = hasNoColorEnv() || os.Getenv("TERM") == "dumb" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) // Output defines the standard output of the print functions. By default, @@ -35,15 +36,15 @@ var ( colorsCacheMu sync.Mutex // protects colorsCache ) -// noColorIsSet returns true if the environment variable NO_COLOR is set to a non-empty string. -func noColorIsSet() bool { +// hasNoColorEnv returns true if the environment variable NO_COLOR is set to a non-empty string. +func hasNoColorEnv() bool { return os.Getenv("NO_COLOR") != "" } // Color defines a custom color object which is defined by SGR parameters. type Color struct { params []Attribute - noColor *bool + noColor bool } // Attribute defines a single SGR Code @@ -148,8 +149,10 @@ func New(value ...Attribute) *Color { params: make([]Attribute, 0), } - if noColorIsSet() { - c.noColor = boolPtr(true) + if NoColor { + c.noColor = true + } else { + c.noColor = false } c.Add(value...) @@ -200,7 +203,7 @@ func Unset() { // Set sets the SGR sequence. func (c *Color) Set() *Color { - if c.isNoColorSet() { + if c.noColor { return c } @@ -209,7 +212,7 @@ func (c *Color) Set() *Color { } func (c *Color) unset() { - if c.isNoColorSet() { + if c.noColor { return } @@ -220,7 +223,7 @@ func (c *Color) unset() { // a low-level function, and users should use the higher-level functions, such // as color.Fprint, color.Print, etc. func (c *Color) SetWriter(w io.Writer) *Color { - if c.isNoColorSet() { + if c.noColor { return c } @@ -231,7 +234,7 @@ func (c *Color) SetWriter(w io.Writer) *Color { // UnsetWriter resets all escape attributes and clears the output with the give // io.Writer. Usually should be called after SetWriter(). func (c *Color) UnsetWriter(w io.Writer) { - if c.isNoColorSet() { + if c.noColor { return } @@ -414,7 +417,7 @@ func (c *Color) sequence() string { // wrap wraps the s string with the colors attributes. The string is ready to // be printed. func (c *Color) wrap(s string) string { - if c.isNoColorSet() { + if c.noColor { return s } @@ -444,23 +447,13 @@ func (c *Color) unformat() string { // code and still being able to output. Can be used for flags like // "--no-color". To enable back use EnableColor() method. func (c *Color) DisableColor() { - c.noColor = boolPtr(true) + c.noColor = true } // EnableColor enables the color output. Use it in conjunction with // DisableColor(). Otherwise, this method has no side effects. func (c *Color) EnableColor() { - c.noColor = boolPtr(false) -} - -func (c *Color) isNoColorSet() bool { - // check first if we have user set action - if c.noColor != nil { - return *c.noColor - } - - // if not return the global option, which is disabled by default - return NoColor + c.noColor = false } // Equals returns a boolean value indicating whether two colors are equal. @@ -494,10 +487,6 @@ func (c *Color) attrExists(a Attribute) bool { return false } -func boolPtr(v bool) *bool { - return &v -} - func getCachedColor(p Attribute) *Color { colorsCacheMu.Lock() defer colorsCacheMu.Unlock() diff --git a/color_test.go b/color_test.go index 586039b4..6f2eed53 100644 --- a/color_test.go +++ b/color_test.go @@ -158,49 +158,7 @@ func TestNoColor(t *testing.T) { } } -func TestNoColor_Env(t *testing.T) { - rb := new(bytes.Buffer) - Output = rb - - testColors := []struct { - text string - code Attribute - }{ - {text: "black", code: FgBlack}, - {text: "red", code: FgRed}, - {text: "green", code: FgGreen}, - {text: "yellow", code: FgYellow}, - {text: "blue", code: FgBlue}, - {text: "magent", code: FgMagenta}, - {text: "cyan", code: FgCyan}, - {text: "white", code: FgWhite}, - {text: "hblack", code: FgHiBlack}, - {text: "hred", code: FgHiRed}, - {text: "hgreen", code: FgHiGreen}, - {text: "hyellow", code: FgHiYellow}, - {text: "hblue", code: FgHiBlue}, - {text: "hmagent", code: FgHiMagenta}, - {text: "hcyan", code: FgHiCyan}, - {text: "hwhite", code: FgHiWhite}, - } - - os.Setenv("NO_COLOR", "1") - t.Cleanup(func() { - os.Unsetenv("NO_COLOR") - }) - - for _, c := range testColors { - p := New(c.code) - p.Print(c.text) - - line, _ := rb.ReadString('\n') - if line != c.text { - t.Errorf("Expecting %s, got '%s'\n", c.text, line) - } - } -} - -func Test_noColorIsSet(t *testing.T) { +func Test_hasNoColorEnv(t *testing.T) { tests := []struct { name string act func() @@ -228,8 +186,8 @@ func Test_noColorIsSet(t *testing.T) { os.Unsetenv("NO_COLOR") }) tt.act() - if got := noColorIsSet(); got != tt.want { - t.Errorf("noColorIsSet() = %v, want %v", got, tt.want) + if got := hasNoColorEnv(); got != tt.want { + t.Errorf("hasNoColorEnv() = %v, want %v", got, tt.want) } }) }