Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NO_COLOR support to disable color output #137

Merged
merged 1 commit into from May 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions README.md
Expand Up @@ -127,11 +127,14 @@ fmt.Println("All text will now be bold magenta.")

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

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

`Color` has support to disable/enable colors programatically both globally and
for single color definitions. For example suppose you have a CLI app and a
`--no-color` bool flag. You can easily disable the color output with:

```go
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
Expand Down
23 changes: 19 additions & 4 deletions color.go
Expand Up @@ -15,9 +15,11 @@ import (
var (
// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. This is a global option and affects all colors. For more control
// over each color block use the methods DisableColor() individually.
NoColor = os.Getenv("TERM") == "dumb" ||
// or not. It's also set to true if the NO_COLOR environment variable is
// 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 = noColorExists() || 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
Expand All @@ -33,6 +35,12 @@ var (
colorsCacheMu sync.Mutex // protects colorsCache
)

// noColorExists returns true if the environment variable NO_COLOR exists.
func noColorExists() bool {
_, exists := os.LookupEnv("NO_COLOR")
return exists
}

// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
params []Attribute
Expand Down Expand Up @@ -108,7 +116,14 @@ const (

// New returns a newly created color object.
func New(value ...Attribute) *Color {
c := &Color{params: make([]Attribute, 0)}
c := &Color{
params: make([]Attribute, 0),
}

if noColorExists() {
c.noColor = boolPtr(true)
}

c.Add(value...)
return c
}
Expand Down
47 changes: 45 additions & 2 deletions color_test.go
Expand Up @@ -142,9 +142,52 @@ func TestNoColor(t *testing.T) {

// global check
NoColor = true
defer func() {
t.Cleanup(func() {
NoColor = false
}()
})

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 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", "")
t.Cleanup(func() {
os.Unsetenv("NO_COLOR")
})

for _, c := range testColors {
p := New(c.code)
p.Print(c.text)
Expand Down
2 changes: 2 additions & 0 deletions doc.go
Expand Up @@ -118,6 +118,8 @@ the color output with:
color.NoColor = true // disables colorized output
}
You can also disable the color by setting the NO_COLOR environment variable to any value.
It also has support for single color definitions (local). You can
disable/enable color output on the fly:
Expand Down