pkg/iostreams/color.go (77 lines of code) (raw):
package iostreams
import (
"fmt"
"io"
"os"
"strings"
"github.com/mattn/go-colorable"
"github.com/mgutz/ansi"
)
var (
_isColorEnabled = true
checkedNoColor = false
)
type ColorPalette struct {
// Magenta outputs ANSI color if stdout is a tty
Magenta func(string) string
// Cyan outputs ANSI color if stdout is a tty
Cyan func(string) string
// Red outputs ANSI color if stdout is a tty
Red func(string) string
// Yellow outputs ANSI color if stdout is a tty
Yellow func(string) string
// Blue outputs ANSI color if stdout is a tty
Blue func(string) string
// Green outputs ANSI color if stdout is a tty
Green func(string) string
// Gray outputs ANSI color if stdout is a tty
Gray func(string) string
// Bold outputs ANSI color if stdout is a tty
Bold func(string) string
}
func (s *IOStreams) Color() *ColorPalette {
return &ColorPalette{
Magenta: makeColorFunc("magenta"),
Cyan: makeColorFunc("cyan"),
Red: makeColorFunc("red"),
Yellow: makeColorFunc("yellow"),
Blue: makeColorFunc("blue"),
Green: makeColorFunc("green"),
Gray: makeColorFunc("black+h"),
Bold: makeColorFunc("default+b"),
}
}
// NewColorable returns an output stream that handles ANSI color sequences on Windows
func NewColorable(out io.Writer) io.Writer {
if outFile, isFile := out.(*os.File); isFile {
return colorable.NewColorable(outFile)
}
return out
}
func makeColorFunc(color string) func(string) string {
isColorfulOutput := isColorEnabled() && isStdoutTerminal()
if isColorfulOutput && color == "black+h" && Is256ColorSupported() {
return func(t string) string {
return fmt.Sprintf("\x1b[%d;5;%dm%s\x1b[m", 38, 242, t)
}
}
cf := ansi.ColorFunc(color)
return func(arg string) string {
if isColorfulOutput {
return cf(arg)
}
return arg
}
}
func isColorEnabled() bool {
if !checkedNoColor {
_, _isColorEnabled = os.LookupEnv("NO_COLOR")
_isColorEnabled = !_isColorEnabled // Revert the value NO_COLOR disables color
if !_isColorEnabled {
_isColorEnabled = os.Getenv("COLOR_ENABLED") == "1" || os.Getenv("COLOR_ENABLED") == "true"
}
checkedNoColor = true
}
return _isColorEnabled
}
func Is256ColorSupported() bool {
term := os.Getenv("TERM")
colorterm := os.Getenv("COLORTERM")
return strings.Contains(term, "256") ||
strings.Contains(term, "24bit") ||
strings.Contains(term, "truecolor") ||
strings.Contains(colorterm, "256") ||
strings.Contains(colorterm, "24bit") ||
strings.Contains(colorterm, "truecolor")
}