Skip to content

Commit

Permalink
Merge pull request #137 from fatih/add-no-color-support
Browse files Browse the repository at this point in the history
Add `NO_COLOR` support to disable color output
  • Loading branch information
fatih committed May 24, 2021
2 parents f4c4316 + f08ed43 commit cf45235
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 10 deletions.
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

0 comments on commit cf45235

Please sign in to comment.