Skip to content

Commit cf45235

Browse files
authored
Merge pull request #137 from fatih/add-no-color-support
Add `NO_COLOR` support to disable color output
2 parents f4c4316 + f08ed43 commit cf45235

File tree

4 files changed

+73
-10
lines changed

4 files changed

+73
-10
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,14 @@ fmt.Println("All text will now be bold magenta.")
127127

128128
There might be a case where you want to explicitly disable/enable color output. the
129129
`go-isatty` package will automatically disable color output for non-tty output streams
130-
(for example if the output were piped directly to `less`)
130+
(for example if the output were piped directly to `less`).
131131

132-
`Color` has support to disable/enable colors both globally and for single color
133-
definitions. For example suppose you have a CLI app and a `--no-color` bool flag. You
134-
can easily disable the color output with:
132+
The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment
133+
variable is set (regardless of its value).
134+
135+
`Color` has support to disable/enable colors programatically both globally and
136+
for single color definitions. For example suppose you have a CLI app and a
137+
`--no-color` bool flag. You can easily disable the color output with:
135138

136139
```go
137140
var flagNoColor = flag.Bool("no-color", false, "Disable color output")

color.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ import (
1515
var (
1616
// NoColor defines if the output is colorized or not. It's dynamically set to
1717
// false or true based on the stdout's file descriptor referring to a terminal
18-
// or not. This is a global option and affects all colors. For more control
19-
// over each color block use the methods DisableColor() individually.
20-
NoColor = os.Getenv("TERM") == "dumb" ||
18+
// or not. It's also set to true if the NO_COLOR environment variable is
19+
// set (regardless of its value). This is a global option and affects all
20+
// colors. For more control over each color block use the methods
21+
// DisableColor() individually.
22+
NoColor = noColorExists() || os.Getenv("TERM") == "dumb" ||
2123
(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
2224

2325
// Output defines the standard output of the print functions. By default
@@ -33,6 +35,12 @@ var (
3335
colorsCacheMu sync.Mutex // protects colorsCache
3436
)
3537

38+
// noColorExists returns true if the environment variable NO_COLOR exists.
39+
func noColorExists() bool {
40+
_, exists := os.LookupEnv("NO_COLOR")
41+
return exists
42+
}
43+
3644
// Color defines a custom color object which is defined by SGR parameters.
3745
type Color struct {
3846
params []Attribute
@@ -108,7 +116,14 @@ const (
108116

109117
// New returns a newly created color object.
110118
func New(value ...Attribute) *Color {
111-
c := &Color{params: make([]Attribute, 0)}
119+
c := &Color{
120+
params: make([]Attribute, 0),
121+
}
122+
123+
if noColorExists() {
124+
c.noColor = boolPtr(true)
125+
}
126+
112127
c.Add(value...)
113128
return c
114129
}

color_test.go

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,52 @@ func TestNoColor(t *testing.T) {
142142

143143
// global check
144144
NoColor = true
145-
defer func() {
145+
t.Cleanup(func() {
146146
NoColor = false
147-
}()
147+
})
148+
149+
for _, c := range testColors {
150+
p := New(c.code)
151+
p.Print(c.text)
152+
153+
line, _ := rb.ReadString('\n')
154+
if line != c.text {
155+
t.Errorf("Expecting %s, got '%s'\n", c.text, line)
156+
}
157+
}
158+
}
159+
160+
func TestNoColor_Env(t *testing.T) {
161+
rb := new(bytes.Buffer)
162+
Output = rb
163+
164+
testColors := []struct {
165+
text string
166+
code Attribute
167+
}{
168+
{text: "black", code: FgBlack},
169+
{text: "red", code: FgRed},
170+
{text: "green", code: FgGreen},
171+
{text: "yellow", code: FgYellow},
172+
{text: "blue", code: FgBlue},
173+
{text: "magent", code: FgMagenta},
174+
{text: "cyan", code: FgCyan},
175+
{text: "white", code: FgWhite},
176+
{text: "hblack", code: FgHiBlack},
177+
{text: "hred", code: FgHiRed},
178+
{text: "hgreen", code: FgHiGreen},
179+
{text: "hyellow", code: FgHiYellow},
180+
{text: "hblue", code: FgHiBlue},
181+
{text: "hmagent", code: FgHiMagenta},
182+
{text: "hcyan", code: FgHiCyan},
183+
{text: "hwhite", code: FgHiWhite},
184+
}
185+
186+
os.Setenv("NO_COLOR", "")
187+
t.Cleanup(func() {
188+
os.Unsetenv("NO_COLOR")
189+
})
190+
148191
for _, c := range testColors {
149192
p := New(c.code)
150193
p.Print(c.text)

doc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ the color output with:
118118
color.NoColor = true // disables colorized output
119119
}
120120
121+
You can also disable the color by setting the NO_COLOR environment variable to any value.
122+
121123
It also has support for single color definitions (local). You can
122124
disable/enable color output on the fly:
123125

0 commit comments

Comments
 (0)