Full Code of fatih/color for AI

main ca25f6e17f11 cached
10 files
50.4 KB
14.8k tokens
160 symbols
1 requests
Download .txt
Repository: fatih/color
Branch: main
Commit: ca25f6e17f11
Files: 10
Total size: 50.4 KB

Directory structure:
gitextract_m7hx93sk/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       └── go.yml
├── LICENSE.md
├── README.md
├── color.go
├── color_test.go
├── color_windows.go
├── doc.go
├── go.mod
└── go.sum

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "gomod"
    directory: "/" # Location of go.mod
    schedule:
      interval: "daily"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"


================================================
FILE: .github/workflows/go.yml
================================================
name: build
on:
  push:
    branches:
      - main
  pull_request:

jobs:
  test:
    name: Test & Build
    runs-on: ubuntu-latest
    steps:

    - name: Check out code into the Go module directory
      uses: actions/checkout@v6

    - name: Set up Go 
      uses: actions/setup-go@v6
      with:
        go-version-file: go.mod

    - name: Run go mod tidy
      run: |
        set -e
        go mod tidy
        output=$(git status -s)
        if [ -z "${output}" ]; then
         exit 0
        fi
        echo 'We wish to maintain a tidy state for go mod. Please run `go mod tidy` on your branch, commit and push again.'
        echo 'Running `go mod tidy` on this CI test yields with the following changes:'
        echo "$output"
        exit 1
      
    - name: Test
      run: go test -race ./...

    - name: Lint
      run: "go vet ./..."

    - name: Staticcheck
      uses: dominikh/staticcheck-action@v1.4.1
      with:
        version: "2025.1.1"
        install-go: false

    - name: Build
      run: go build ./...


================================================
FILE: LICENSE.md
================================================
The MIT License (MIT)

Copyright (c) 2013 Fatih Arslan

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/fatih/color)](https://pkg.go.dev/github.com/fatih/color)

Color lets you use colorized outputs in terms of [ANSI Escape
Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It
has support for Windows too! The API can be used in several ways, pick one that
suits you.

![Color](https://user-images.githubusercontent.com/438920/96832689-03b3e000-13f4-11eb-9803-46f4c4de3406.jpg)

## Install

```
go get github.com/fatih/color
```

## Examples

### Standard colors

```go
// Print with default helper functions
color.Cyan("Prints text in cyan.")

// A newline will be appended automatically
color.Blue("Prints %s in blue.", "text")

// These are using the default foreground colors
color.Red("We have red")
color.Magenta("And many others ..")

```

### RGB colors

If your terminal supports 24-bit colors, you can use RGB color codes.

```go
color.RGB(255, 128, 0).Println("foreground orange")
color.RGB(230, 42, 42).Println("foreground red")

color.BgRGB(255, 128, 0).Println("background orange")
color.BgRGB(230, 42, 42).Println("background red")
```

### Mix and reuse colors

```go
// Create a new color object
c := color.New(color.FgCyan).Add(color.Underline)
c.Println("Prints cyan text with an underline.")

// Or just add them to New()
d := color.New(color.FgCyan, color.Bold)
d.Printf("This prints bold cyan %s\n", "too!.")

// Mix up foreground and background colors, create new mixes!
red := color.New(color.FgRed)

boldRed := red.Add(color.Bold)
boldRed.Println("This will print text in bold red.")

whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with white background.")

// Mix with RGB color codes
color.RGB(255, 128, 0).AddBgRGB(0, 0, 0).Println("orange with black background")

color.BgRGB(255, 128, 0).AddRGB(255, 255, 255).Println("orange background with white foreground")
```

### Use your own output (io.Writer)

```go
// Use your own io.Writer output
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")

blue := color.New(color.FgBlue)
blue.Fprint(writer, "This will print text in blue.")
```

### Custom print functions (PrintFunc)

```go
// Create a custom print function for convenience
red := color.New(color.FgRed).PrintfFunc()
red("Warning")
red("Error: %s", err)

// Mix up multiple attributes
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("Don't forget this...")
```

### Custom fprint functions (FprintFunc)

```go
blue := color.New(color.FgBlue).FprintfFunc()
blue(myWriter, "important notice: %s", stars)

// Mix up with multiple attributes
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
success(myWriter, "Don't forget this...")
```

### Insert into noncolor strings (SprintFunc)

```go
// Create SprintXxx functions to mix strings with other non-colorized strings:
yellow := color.New(color.FgYellow).SprintFunc()
red := color.New(color.FgRed).SprintFunc()
fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error"))

info := color.New(color.FgWhite, color.BgGreen).SprintFunc()
fmt.Printf("This %s rocks!\n", info("package"))

// Use helper functions
fmt.Println("This", color.RedString("warning"), "should be not neglected.")
fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.")

// Windows supported too! Just don't forget to change the output to color.Output
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
```

### Plug into existing code

```go
// Use handy standard colors
color.Set(color.FgYellow)

fmt.Println("Existing text will now be in yellow")
fmt.Printf("This one %s\n", "too")

color.Unset() // Don't forget to unset

// You can mix up parameters
color.Set(color.FgMagenta, color.Bold)
defer color.Unset() // Use it in your function

fmt.Println("All text will now be bold magenta.")
```

### Disable/Enable color

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`).

The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment
variable is set to a non-empty string.

`Color` has support to disable/enable colors programmatically 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")

if *flagNoColor {
	color.NoColor = true // disables colorized output
}
```

It also has support for single color definitions (local). You can
disable/enable color output on the fly:

```go
c := color.New(color.FgCyan)
c.Println("Prints cyan text")

c.DisableColor()
c.Println("This is printed without any color")

c.EnableColor()
c.Println("This prints again cyan...")
```

## GitHub Actions

To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams. 


## Credits

* [Fatih Arslan](https://github.com/fatih)
* Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable)

## License

The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details


================================================
FILE: color.go
================================================
package color

import (
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"

	"github.com/mattn/go-colorable"
	"github.com/mattn/go-isatty"
)

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. 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 = noColorIsSet() || os.Getenv("TERM") == "dumb" || !stdoutIsTerminal()

	// Output defines the standard output of the print functions. By default,
	// stdOut() is used.
	Output = stdOut()

	// Error defines the standard error of the print functions. By default,
	// stdErr() is used.
	Error = stdErr()

	// colorsCache is used to reduce the count of created Color objects and
	// allows to reuse already created objects with required Attribute.
	colorsCache   = make(map[Attribute]*Color)
	colorsCacheMu sync.Mutex // protects colorsCache
)

// noColorIsSet returns true if the environment variable NO_COLOR is set to a non-empty string.
func noColorIsSet() bool {
	return os.Getenv("NO_COLOR") != ""
}

// stdoutIsTerminal returns true if os.Stdout is a terminal.
// Returns false if os.Stdout is nil (e.g., when running as a Windows service).
func stdoutIsTerminal() bool {
	if os.Stdout == nil {
		return false
	}
	return isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
}

// stdOut returns a writer for color output.
// Returns io.Discard if os.Stdout is nil (e.g., when running as a Windows service).
func stdOut() io.Writer {
	if os.Stdout == nil {
		return io.Discard
	}
	return colorable.NewColorableStdout()
}

// stdErr returns a writer for color error output.
// Returns io.Discard if os.Stderr is nil (e.g., when running as a Windows service).
func stdErr() io.Writer {
	if os.Stderr == nil {
		return io.Discard
	}
	return colorable.NewColorableStderr()
}

// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
	params  []Attribute
	noColor *bool
}

// Attribute defines a single SGR Code
type Attribute int

const escape = "\x1b"

// Base attributes
const (
	Reset Attribute = iota
	Bold
	Faint
	Italic
	Underline
	BlinkSlow
	BlinkRapid
	ReverseVideo
	Concealed
	CrossedOut
)

const (
	ResetBold Attribute = iota + 22
	ResetItalic
	ResetUnderline
	ResetBlinking
	_
	ResetReversed
	ResetConcealed
	ResetCrossedOut
)

var mapResetAttributes map[Attribute]Attribute = map[Attribute]Attribute{
	Bold:         ResetBold,
	Faint:        ResetBold,
	Italic:       ResetItalic,
	Underline:    ResetUnderline,
	BlinkSlow:    ResetBlinking,
	BlinkRapid:   ResetBlinking,
	ReverseVideo: ResetReversed,
	Concealed:    ResetConcealed,
	CrossedOut:   ResetCrossedOut,
}

// Foreground text colors
const (
	FgBlack Attribute = iota + 30
	FgRed
	FgGreen
	FgYellow
	FgBlue
	FgMagenta
	FgCyan
	FgWhite

	// used internally for 256 and 24-bit coloring
	foreground
)

// Foreground Hi-Intensity text colors
const (
	FgHiBlack Attribute = iota + 90
	FgHiRed
	FgHiGreen
	FgHiYellow
	FgHiBlue
	FgHiMagenta
	FgHiCyan
	FgHiWhite
)

// Background text colors
const (
	BgBlack Attribute = iota + 40
	BgRed
	BgGreen
	BgYellow
	BgBlue
	BgMagenta
	BgCyan
	BgWhite

	// used internally for 256 and 24-bit coloring
	background
)

// Background Hi-Intensity text colors
const (
	BgHiBlack Attribute = iota + 100
	BgHiRed
	BgHiGreen
	BgHiYellow
	BgHiBlue
	BgHiMagenta
	BgHiCyan
	BgHiWhite
)

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

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

	c.Add(value...)
	return c
}

// RGB returns a new foreground color in 24-bit RGB.
func RGB(r, g, b int) *Color {
	return New(foreground, 2, Attribute(r), Attribute(g), Attribute(b))
}

// BgRGB returns a new background color in 24-bit RGB.
func BgRGB(r, g, b int) *Color {
	return New(background, 2, Attribute(r), Attribute(g), Attribute(b))
}

// AddRGB is used to chain foreground RGB SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: .Add(34, 0, 12).Add(255, 128, 0).
func (c *Color) AddRGB(r, g, b int) *Color {
	c.params = append(c.params, foreground, 2, Attribute(r), Attribute(g), Attribute(b))
	return c
}

// AddRGB is used to chain background RGB SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: .Add(34, 0, 12).Add(255, 128, 0).
func (c *Color) AddBgRGB(r, g, b int) *Color {
	c.params = append(c.params, background, 2, Attribute(r), Attribute(g), Attribute(b))
	return c
}

// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...Attribute) *Color {
	c := New(p...)
	c.Set()
	return c
}

// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
	if NoColor {
		return
	}

	fmt.Fprintf(Output, "%s[%dm", escape, Reset)
}

// Set sets the SGR sequence.
func (c *Color) Set() *Color {
	if c.isNoColorSet() {
		return c
	}

	fmt.Fprint(Output, c.format())
	return c
}

func (c *Color) unset() {
	if c.isNoColorSet() {
		return
	}

	Unset()
}

// SetWriter is used to set the SGR sequence with the given io.Writer. This is
// 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 {
	_, _ = c.setWriter(w)
	return c
}

func (c *Color) setWriter(w io.Writer) (int, error) {
	if c.isNoColorSet() {
		return 0, nil
	}

	return fmt.Fprint(w, c.format())
}

// 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) {
	_, _ = c.unsetWriter(w)
}

func (c *Color) unsetWriter(w io.Writer) (int, error) {
	if c.isNoColorSet() {
		return 0, nil
	}

	return fmt.Fprintf(w, "%s[%dm", escape, Reset)
}

// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attribute) *Color {
	c.params = append(c.params, value...)
	return c
}

// Fprint formats using the default formats for its operands and writes to w.
// Spaces are added between operands when neither is a string.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
	n, err = c.setWriter(w)
	if err != nil {
		return n, err
	}

	nn, err := fmt.Fprint(w, a...)
	n += nn
	if err != nil {
		return
	}

	nn, err = c.unsetWriter(w)
	n += nn
	return n, err
}

// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
// string. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Print(a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprint(Output, a...)
}

// Fprintf formats according to a format specifier and writes to w.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
	n, err = c.setWriter(w)
	if err != nil {
		return n, err
	}

	nn, err := fmt.Fprintf(w, format, a...)
	n += nn
	if err != nil {
		return
	}

	nn, err = c.unsetWriter(w)
	n += nn
	return n, err
}

// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprintf(Output, format, a...)
}

// Fprintln formats using the default formats for its operands and writes to w.
// Spaces are always added between operands and a newline is appended.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
	return fmt.Fprintln(w, c.wrap(sprintln(a...)))
}

// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Println(a ...interface{}) (n int, err error) {
	return fmt.Fprintln(Output, c.wrap(sprintln(a...)))
}

// Sprint is just like Print, but returns a string instead of printing it.
func (c *Color) Sprint(a ...interface{}) string {
	return c.wrap(fmt.Sprint(a...))
}

// Sprintln is just like Println, but returns a string instead of printing it.
func (c *Color) Sprintln(a ...interface{}) string {
	return c.wrap(sprintln(a...)) + "\n"
}

// Sprintf is just like Printf, but returns a string instead of printing it.
func (c *Color) Sprintf(format string, a ...interface{}) string {
	return c.wrap(fmt.Sprintf(format, a...))
}

// FprintFunc returns a new function that prints the passed arguments as
// colorized with color.Fprint().
func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
	return func(w io.Writer, a ...interface{}) {
		c.Fprint(w, a...)
	}
}

// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
	return func(a ...interface{}) {
		c.Print(a...)
	}
}

// FprintfFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintf().
func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
	return func(w io.Writer, format string, a ...interface{}) {
		c.Fprintf(w, format, a...)
	}
}

// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
	return func(format string, a ...interface{}) {
		c.Printf(format, a...)
	}
}

// FprintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintln().
func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
	return func(w io.Writer, a ...interface{}) {
		c.Fprintln(w, a...)
	}
}

// PrintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Println().
func (c *Color) PrintlnFunc() func(a ...interface{}) {
	return func(a ...interface{}) {
		c.Println(a...)
	}
}

// SprintFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprint(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output, example:
//
//	put := New(FgYellow).SprintFunc()
//	fmt.Fprintf(color.Output, "This is a %s", put("warning"))
func (c *Color) SprintFunc() func(a ...interface{}) string {
	return func(a ...interface{}) string {
		return c.wrap(fmt.Sprint(a...))
	}
}

// SprintfFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
	return func(format string, a ...interface{}) string {
		return c.wrap(fmt.Sprintf(format, a...))
	}
}

// SprintlnFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
	return func(a ...interface{}) string {
		return c.wrap(sprintln(a...)) + "\n"
	}
}

// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m"
// an example output might be: "1;36" -> bold cyan
func (c *Color) sequence() string {
	format := make([]string, len(c.params))
	for i, v := range c.params {
		format[i] = strconv.Itoa(int(v))
	}

	return strings.Join(format, ";")
}

// 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() {
		return s
	}

	return c.format() + s + c.unformat()
}

func (c *Color) format() string {
	return fmt.Sprintf("%s[%sm", escape, c.sequence())
}

func (c *Color) unformat() string {
	//return fmt.Sprintf("%s[%dm", escape, Reset)
	//for each element in sequence let's use the specific reset escape, or the generic one if not found
	format := make([]string, len(c.params))
	for i, v := range c.params {
		format[i] = strconv.Itoa(int(Reset))
		ra, ok := mapResetAttributes[v]
		if ok {
			format[i] = strconv.Itoa(int(ra))
		}
	}

	return fmt.Sprintf("%s[%sm", escape, strings.Join(format, ";"))
}

// DisableColor disables the color output. Useful to not change any existing
// 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)
}

// 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
}

// Equals returns a boolean value indicating whether two colors are equal.
func (c *Color) Equals(c2 *Color) bool {
	if c == nil && c2 == nil {
		return true
	}
	if c == nil || c2 == nil {
		return false
	}

	if len(c.params) != len(c2.params) {
		return false
	}

	counts := make(map[Attribute]int, len(c.params))
	for _, attr := range c.params {
		counts[attr]++
	}

	for _, attr := range c2.params {
		if counts[attr] == 0 {
			return false
		}
		counts[attr]--
	}

	return true
}

func boolPtr(v bool) *bool {
	return &v
}

func getCachedColor(p Attribute) *Color {
	colorsCacheMu.Lock()
	defer colorsCacheMu.Unlock()

	c, ok := colorsCache[p]
	if !ok {
		c = New(p)
		colorsCache[p] = c
	}

	return c
}

func colorPrint(format string, p Attribute, a ...interface{}) {
	c := getCachedColor(p)

	if !strings.HasSuffix(format, "\n") {
		format += "\n"
	}

	if len(a) == 0 {
		c.Print(format)
	} else {
		c.Printf(format, a...)
	}
}

func colorString(format string, p Attribute, a ...interface{}) string {
	c := getCachedColor(p)

	if len(a) == 0 {
		return c.SprintFunc()(format)
	}

	return c.SprintfFunc()(format, a...)
}

// Black is a convenient helper function to print with black foreground. A
// newline is appended to format by default.
func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }

// Red is a convenient helper function to print with red foreground. A
// newline is appended to format by default.
func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }

// Green is a convenient helper function to print with green foreground. A
// newline is appended to format by default.
func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }

// Yellow is a convenient helper function to print with yellow foreground.
// A newline is appended to format by default.
func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }

// Blue is a convenient helper function to print with blue foreground. A
// newline is appended to format by default.
func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }

// Magenta is a convenient helper function to print with magenta foreground.
// A newline is appended to format by default.
func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }

// Cyan is a convenient helper function to print with cyan foreground. A
// newline is appended to format by default.
func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }

// White is a convenient helper function to print with white foreground. A
// newline is appended to format by default.
func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }

// BlackString is a convenient helper function to return a string with black
// foreground.
func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }

// RedString is a convenient helper function to return a string with red
// foreground.
func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }

// GreenString is a convenient helper function to return a string with green
// foreground.
func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }

// YellowString is a convenient helper function to return a string with yellow
// foreground.
func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }

// BlueString is a convenient helper function to return a string with blue
// foreground.
func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }

// MagentaString is a convenient helper function to return a string with magenta
// foreground.
func MagentaString(format string, a ...interface{}) string {
	return colorString(format, FgMagenta, a...)
}

// CyanString is a convenient helper function to return a string with cyan
// foreground.
func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }

// WhiteString is a convenient helper function to return a string with white
// foreground.
func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }

// HiBlack is a convenient helper function to print with hi-intensity black foreground. A
// newline is appended to format by default.
func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) }

// HiRed is a convenient helper function to print with hi-intensity red foreground. A
// newline is appended to format by default.
func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) }

// HiGreen is a convenient helper function to print with hi-intensity green foreground. A
// newline is appended to format by default.
func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) }

// HiYellow is a convenient helper function to print with hi-intensity yellow foreground.
// A newline is appended to format by default.
func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) }

// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A
// newline is appended to format by default.
func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) }

// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground.
// A newline is appended to format by default.
func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) }

// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A
// newline is appended to format by default.
func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) }

// HiWhite is a convenient helper function to print with hi-intensity white foreground. A
// newline is appended to format by default.
func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) }

// HiBlackString is a convenient helper function to return a string with hi-intensity black
// foreground.
func HiBlackString(format string, a ...interface{}) string {
	return colorString(format, FgHiBlack, a...)
}

// HiRedString is a convenient helper function to return a string with hi-intensity red
// foreground.
func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) }

// HiGreenString is a convenient helper function to return a string with hi-intensity green
// foreground.
func HiGreenString(format string, a ...interface{}) string {
	return colorString(format, FgHiGreen, a...)
}

// HiYellowString is a convenient helper function to return a string with hi-intensity yellow
// foreground.
func HiYellowString(format string, a ...interface{}) string {
	return colorString(format, FgHiYellow, a...)
}

// HiBlueString is a convenient helper function to return a string with hi-intensity blue
// foreground.
func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) }

// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta
// foreground.
func HiMagentaString(format string, a ...interface{}) string {
	return colorString(format, FgHiMagenta, a...)
}

// HiCyanString is a convenient helper function to return a string with hi-intensity cyan
// foreground.
func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) }

// HiWhiteString is a convenient helper function to return a string with hi-intensity white
// foreground.
func HiWhiteString(format string, a ...interface{}) string {
	return colorString(format, FgHiWhite, a...)
}

// sprintln is a helper function to format a string with fmt.Sprintln and trim the trailing newline.
func sprintln(a ...interface{}) string {
	return strings.TrimSuffix(fmt.Sprintln(a...), "\n")
}


================================================
FILE: color_test.go
================================================
package color

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"testing"

	"github.com/mattn/go-colorable"
)

// Testing colors is kinda different. First we test for given colors and their
// escaped formatted results. Next we create some visual tests to be tested.
// Each visual test includes the color name to be compared.
func TestColor(t *testing.T) {
	rb := new(bytes.Buffer)
	Output = rb

	NoColor = false

	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},
	}

	for _, c := range testColors {
		New(c.code).Print(c.text)

		line, _ := rb.ReadString('\n')
		scannedLine := fmt.Sprintf("%q", line)
		colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
		escapedForm := fmt.Sprintf("%q", colored)

		fmt.Printf("%s\t: %s\n", c.text, line)

		if scannedLine != escapedForm {
			t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
		}
	}

	for _, c := range testColors {
		line := New(c.code).Sprintf("%s", c.text)
		scannedLine := fmt.Sprintf("%q", line)
		colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
		escapedForm := fmt.Sprintf("%q", colored)

		fmt.Printf("%s\t: %s\n", c.text, line)

		if scannedLine != escapedForm {
			t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
		}
	}
}

func TestColorEquals(t *testing.T) {
	fgblack1 := New(FgBlack)
	fgblack2 := New(FgBlack)
	bgblack := New(BgBlack)
	fgbgblack := New(FgBlack, BgBlack)
	fgblackbgred := New(FgBlack, BgRed)
	fgred := New(FgRed)
	bgred := New(BgRed)

	if !fgblack1.Equals(fgblack2) {
		t.Error("Two black colors are not equal")
	}

	if fgblack1.Equals(bgblack) {
		t.Error("Fg and bg black colors are equal")
	}

	if fgblack1.Equals(fgbgblack) {
		t.Error("Fg black equals fg/bg black color")
	}

	if fgblack1.Equals(fgred) {
		t.Error("Fg black equals Fg red")
	}

	if fgblack1.Equals(bgred) {
		t.Error("Fg black equals Bg red")
	}

	if fgblack1.Equals(fgblackbgred) {
		t.Error("Fg black equals fg black bg red")
	}
}

func TestColorEquals_DuplicateAttributes(t *testing.T) {
	ordered := New(FgRed, Bold).Add(FgRed)
	reordered := New(Bold, FgRed).Add(FgRed)
	differentCounts := New(FgRed, Bold).Add(Bold)

	if !ordered.Equals(reordered) {
		t.Error("Colors with the same attributes in different orders are not equal")
	}

	if ordered.Equals(differentCounts) {
		t.Error("Colors with different duplicate attribute counts are equal")
	}
}

func TestNoColor(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},
	}

	for _, c := range testColors {
		p := New(c.code)
		p.DisableColor()
		p.Print(c.text)

		line, _ := rb.ReadString('\n')
		if line != c.text {
			t.Errorf("Expecting %s, got '%s'\n", c.text, line)
		}
	}

	// global check
	NoColor = true
	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", "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) {
	tests := []struct {
		name string
		act  func()
		want bool
	}{
		{
			name: "default",
			act:  func() {},
			want: false,
		},
		{
			name: "NO_COLOR=1",
			act:  func() { os.Setenv("NO_COLOR", "1") },
			want: true,
		},
		{
			name: "NO_COLOR=",
			act:  func() { os.Setenv("NO_COLOR", "") },
			want: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Cleanup(func() {
				os.Unsetenv("NO_COLOR")
			})
			tt.act()
			if got := noColorIsSet(); got != tt.want {
				t.Errorf("noColorIsSet() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestStdoutIsTerminal_NilStdout(t *testing.T) {
	stdout := os.Stdout
	os.Stdout = nil
	t.Cleanup(func() {
		os.Stdout = stdout
	})

	if stdoutIsTerminal() {
		t.Fatal("stdoutIsTerminal() = true, want false")
	}
}

func TestStdOut_NilStdout(t *testing.T) {
	stdout := os.Stdout
	os.Stdout = nil
	t.Cleanup(func() {
		os.Stdout = stdout
	})

	if got := stdOut(); got != io.Discard {
		t.Fatalf("stdOut() = %v, want %v", got, io.Discard)
	}
}

func TestStdErr_NilStderr(t *testing.T) {
	stderr := os.Stderr
	os.Stderr = nil
	t.Cleanup(func() {
		os.Stderr = stderr
	})

	if got := stdErr(); got != io.Discard {
		t.Fatalf("stdErr() = %v, want %v", got, io.Discard)
	}
}

func TestColorVisual(t *testing.T) {
	// First Visual Test
	Output = colorable.NewColorableStdout()

	New(FgRed).Printf("red\t")
	New(BgRed).Print("         ")
	New(FgRed, Bold).Println(" red")

	New(FgGreen).Printf("green\t")
	New(BgGreen).Print("         ")
	New(FgGreen, Bold).Println(" green")

	New(FgYellow).Printf("yellow\t")
	New(BgYellow).Print("         ")
	New(FgYellow, Bold).Println(" yellow")

	New(FgBlue).Printf("blue\t")
	New(BgBlue).Print("         ")
	New(FgBlue, Bold).Println(" blue")

	New(FgMagenta).Printf("magenta\t")
	New(BgMagenta).Print("         ")
	New(FgMagenta, Bold).Println(" magenta")

	New(FgCyan).Printf("cyan\t")
	New(BgCyan).Print("         ")
	New(FgCyan, Bold).Println(" cyan")

	New(FgWhite).Printf("white\t")
	New(BgWhite).Print("         ")
	New(FgWhite, Bold).Println(" white")
	fmt.Println("")

	// Second Visual test
	Black("black")
	Red("red")
	Green("green")
	Yellow("yellow")
	Blue("blue")
	Magenta("magenta")
	Cyan("cyan")
	White("white")
	HiBlack("hblack")
	HiRed("hred")
	HiGreen("hgreen")
	HiYellow("hyellow")
	HiBlue("hblue")
	HiMagenta("hmagenta")
	HiCyan("hcyan")
	HiWhite("hwhite")

	// Third visual test
	fmt.Println()
	Set(FgBlue)
	fmt.Println("is this blue?")
	Unset()

	Set(FgMagenta)
	fmt.Println("and this magenta?")
	Unset()

	// Fourth Visual test
	fmt.Println()
	blue := New(FgBlue).PrintlnFunc()
	blue("blue text with custom print func")

	red := New(FgRed).PrintfFunc()
	red("red text with a printf func: %d\n", 123)

	put := New(FgYellow).SprintFunc()
	warn := New(FgRed).SprintFunc()

	fmt.Fprintf(Output, "this is a %s and this is %s.\n", put("warning"), warn("error"))

	info := New(FgWhite, BgGreen).SprintFunc()
	fmt.Fprintf(Output, "this %s rocks!\n", info("package"))

	notice := New(FgBlue).FprintFunc()
	notice(os.Stderr, "just a blue notice to stderr")

	// Fifth Visual Test
	fmt.Println()

	fmt.Fprintln(Output, BlackString("black"))
	fmt.Fprintln(Output, RedString("red"))
	fmt.Fprintln(Output, GreenString("green"))
	fmt.Fprintln(Output, YellowString("yellow"))
	fmt.Fprintln(Output, BlueString("blue"))
	fmt.Fprintln(Output, MagentaString("magenta"))
	fmt.Fprintln(Output, CyanString("cyan"))
	fmt.Fprintln(Output, WhiteString("white"))
	fmt.Fprintln(Output, HiBlackString("hblack"))
	fmt.Fprintln(Output, HiRedString("hred"))
	fmt.Fprintln(Output, HiGreenString("hgreen"))
	fmt.Fprintln(Output, HiYellowString("hyellow"))
	fmt.Fprintln(Output, HiBlueString("hblue"))
	fmt.Fprintln(Output, HiMagentaString("hmagenta"))
	fmt.Fprintln(Output, HiCyanString("hcyan"))
	fmt.Fprintln(Output, HiWhiteString("hwhite"))
}

func TestNoFormat(t *testing.T) {
	fmt.Printf("%s   %%s = ", BlackString("Black"))
	Black("%s")

	fmt.Printf("%s     %%s = ", RedString("Red"))
	Red("%s")

	fmt.Printf("%s   %%s = ", GreenString("Green"))
	Green("%s")

	fmt.Printf("%s  %%s = ", YellowString("Yellow"))
	Yellow("%s")

	fmt.Printf("%s    %%s = ", BlueString("Blue"))
	Blue("%s")

	fmt.Printf("%s %%s = ", MagentaString("Magenta"))
	Magenta("%s")

	fmt.Printf("%s    %%s = ", CyanString("Cyan"))
	Cyan("%s")

	fmt.Printf("%s   %%s = ", WhiteString("White"))
	White("%s")

	fmt.Printf("%s   %%s = ", HiBlackString("HiBlack"))
	HiBlack("%s")

	fmt.Printf("%s     %%s = ", HiRedString("HiRed"))
	HiRed("%s")

	fmt.Printf("%s   %%s = ", HiGreenString("HiGreen"))
	HiGreen("%s")

	fmt.Printf("%s  %%s = ", HiYellowString("HiYellow"))
	HiYellow("%s")

	fmt.Printf("%s    %%s = ", HiBlueString("HiBlue"))
	HiBlue("%s")

	fmt.Printf("%s %%s = ", HiMagentaString("HiMagenta"))
	HiMagenta("%s")

	fmt.Printf("%s    %%s = ", HiCyanString("HiCyan"))
	HiCyan("%s")

	fmt.Printf("%s   %%s = ", HiWhiteString("HiWhite"))
	HiWhite("%s")
}

func TestNoFormatString(t *testing.T) {
	tests := []struct {
		f      func(string, ...interface{}) string
		format string
		args   []interface{}
		want   string
	}{
		{BlackString, "%s", nil, "\x1b[30m%s\x1b[0m"},
		{RedString, "%s", nil, "\x1b[31m%s\x1b[0m"},
		{GreenString, "%s", nil, "\x1b[32m%s\x1b[0m"},
		{YellowString, "%s", nil, "\x1b[33m%s\x1b[0m"},
		{BlueString, "%s", nil, "\x1b[34m%s\x1b[0m"},
		{MagentaString, "%s", nil, "\x1b[35m%s\x1b[0m"},
		{CyanString, "%s", nil, "\x1b[36m%s\x1b[0m"},
		{WhiteString, "%s", nil, "\x1b[37m%s\x1b[0m"},
		{HiBlackString, "%s", nil, "\x1b[90m%s\x1b[0m"},
		{HiRedString, "%s", nil, "\x1b[91m%s\x1b[0m"},
		{HiGreenString, "%s", nil, "\x1b[92m%s\x1b[0m"},
		{HiYellowString, "%s", nil, "\x1b[93m%s\x1b[0m"},
		{HiBlueString, "%s", nil, "\x1b[94m%s\x1b[0m"},
		{HiMagentaString, "%s", nil, "\x1b[95m%s\x1b[0m"},
		{HiCyanString, "%s", nil, "\x1b[96m%s\x1b[0m"},
		{HiWhiteString, "%s", nil, "\x1b[97m%s\x1b[0m"},
	}

	for i, test := range tests {
		s := test.f(test.format, test.args...)

		if s != test.want {
			t.Errorf("[%d] want: %q, got: %q", i, test.want, s)
		}
	}
}

func TestColor_Println_Newline(t *testing.T) {
	rb := new(bytes.Buffer)
	Output = rb

	c := New(FgRed)
	c.Println("foo")

	got := readRaw(t, rb)
	want := "\x1b[31mfoo\x1b[0m\n"

	if want != got {
		t.Errorf("Println newline error\n\nwant: %q\n got: %q", want, got)
	}
}

func TestColor_Sprintln_Newline(t *testing.T) {
	c := New(FgRed)

	got := c.Sprintln("foo")
	want := "\x1b[31mfoo\x1b[0m\n"

	if want != got {
		t.Errorf("Println newline error\n\nwant: %q\n got: %q", want, got)
	}
}

func TestColor_Fprint(t *testing.T) {
	rb := new(strings.Builder)
	c := New(FgRed)

	n, err := c.Fprint(rb, "foo", "bar")
	if err != nil {
		t.Errorf("Fprint error: %v", err)
	}
	got := rb.String()
	want := "\x1b[31mfoobar\x1b[0m"

	if want != got {
		t.Errorf("Fprint error\n\nwant: %q\n got: %q", want, got)
	}
	if n != len(got) {
		t.Errorf("Fprint byte count does not match actual bytes written\n\nwant: %d\n got: %d", len(got), n)
	}
}

func TestColor_Fprintln(t *testing.T) {
	rb := new(strings.Builder)
	c := New(FgRed)

	n, err := c.Fprintln(rb, "foo", "bar")
	if err != nil {
		t.Errorf("Fprint error: %v", err)
	}
	got := rb.String()
	want := "\x1b[31mfoo bar\x1b[0m\n"

	if want != got {
		t.Errorf("Fprintln error\n\nwant: %q\n got: %q", want, got)
	}
	if n != len(got) {
		t.Errorf("Fprintln byte count does not match actual bytes written\n\nwant: %d\n got: %d", len(got), n)
	}
}

func TestColor_Fprintf(t *testing.T) {
	rb := new(strings.Builder)
	c := New(FgRed)

	n, err := c.Fprintf(rb, "%-7s %-7s %5d\n", "hello", "world", 123)
	if err != nil {
		t.Errorf("Fprint error: %v", err)
	}

	want := "\x1b[31mhello   world     123\n\x1b[0m"

	got := rb.String()
	if want != got {
		t.Errorf("Fprintf error\n\nwant: %q\n got: %q", want, got)
	}
	if n != len(got) {
		t.Errorf("Fprintf byte count does not match actual bytes written\n\nwant: %d\n got: %d", len(got), n)
	}
}

func TestColor_Fprintln_Newline(t *testing.T) {
	rb := new(bytes.Buffer)
	c := New(FgRed)
	c.Fprintln(rb, "foo")

	got := readRaw(t, rb)
	want := "\x1b[31mfoo\x1b[0m\n"

	if want != got {
		t.Errorf("Println newline error\n\nwant: %q\n got: %q", want, got)
	}
}

func readRaw(t *testing.T, r io.Reader) string {
	t.Helper()

	out, err := io.ReadAll(r)
	if err != nil {
		t.Fatal(err)
	}

	return string(out)
}

func TestIssue206_1(t *testing.T) {
	// visual test, go test -v .
	// to  see the string with escape codes, use go test -v . > c:\temp\test.txt
	underline := New(Underline).Sprint

	line := fmt.Sprintf("%s %s %s %s", "word1", underline("word2"), "word3", underline("word4"))

	line = CyanString(line)

	fmt.Println(line)

	result := fmt.Sprintf("%v", line)
	const expectedResult = "\x1b[36mword1 \x1b[4mword2\x1b[24m word3 \x1b[4mword4\x1b[24m\x1b[0m"

	if !bytes.Equal([]byte(result), []byte(expectedResult)) {
		t.Errorf("Expecting %v, got '%v'\n", expectedResult, result)
	}
}

func TestIssue206_2(t *testing.T) {
	underline := New(Underline).Sprint
	bold := New(Bold).Sprint

	line := fmt.Sprintf("%s %s", GreenString(underline("underlined regular green")), RedString(bold("bold red")))

	fmt.Println(line)

	result := fmt.Sprintf("%v", line)
	const expectedResult = "\x1b[32m\x1b[4munderlined regular green\x1b[24m\x1b[0m \x1b[31m\x1b[1mbold red\x1b[22m\x1b[0m"

	if !bytes.Equal([]byte(result), []byte(expectedResult)) {
		t.Errorf("Expecting %v, got '%v'\n", expectedResult, result)
	}
}

func TestIssue218(t *testing.T) {
	// Adds a newline to the end of the last string to make sure it isn't trimmed.
	params := []interface{}{"word1", "word2", "word3", "word4\n"}

	c := New(FgCyan)
	c.Println(params...)

	result := c.Sprintln(params...)
	fmt.Println(params...)
	fmt.Print(result)

	const expectedResult = "\x1b[36mword1 word2 word3 word4\n\x1b[0m\n"

	if !bytes.Equal([]byte(result), []byte(expectedResult)) {
		t.Errorf("Sprintln: Expecting %v (%v), got '%v (%v)'\n", expectedResult, []byte(expectedResult), result, []byte(result))
	}

	fn := c.SprintlnFunc()
	result = fn(params...)
	if !bytes.Equal([]byte(result), []byte(expectedResult)) {
		t.Errorf("SprintlnFunc: Expecting %v (%v), got '%v (%v)'\n", expectedResult, []byte(expectedResult), result, []byte(result))
	}

	var buf bytes.Buffer
	c.Fprintln(&buf, params...)
	result = buf.String()
	if !bytes.Equal([]byte(result), []byte(expectedResult)) {
		t.Errorf("Fprintln: Expecting %v (%v), got '%v (%v)'\n", expectedResult, []byte(expectedResult), result, []byte(result))
	}
}

func TestRGB(t *testing.T) {
	tests := []struct {
		r, g, b int
	}{
		{255, 128, 0}, // orange
		{230, 42, 42}, // red
	}

	for i, tt := range tests {
		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
			RGB(tt.r, tt.g, tt.b).Println("foreground")
			RGB(tt.r, tt.g, tt.b).AddBgRGB(0, 0, 0).Println("with background")
			BgRGB(tt.r, tt.g, tt.b).Println("background")
			BgRGB(tt.r, tt.g, tt.b).AddRGB(255, 255, 255).Println("with foreground")
		})
	}
}


================================================
FILE: color_windows.go
================================================
package color

import (
	"os"

	"golang.org/x/sys/windows"
)

func init() {
	// Opt-in for ansi color support for current process.
	// https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#output-sequences
	if os.Stdout == nil {
		return
	}
	var outMode uint32
	out := windows.Handle(os.Stdout.Fd())
	if err := windows.GetConsoleMode(out, &outMode); err != nil {
		return
	}
	outMode |= windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
	_ = windows.SetConsoleMode(out, outMode)
}


================================================
FILE: doc.go
================================================
/*
Package color is an ANSI color package to output colorized or SGR defined
output to the standard output. The API can be used in several way, pick one
that suits you.

Use simple and default helper functions with predefined foreground colors:

	color.Cyan("Prints text in cyan.")

	// a newline will be appended automatically
	color.Blue("Prints %s in blue.", "text")

	// More default foreground colors..
	color.Red("We have red")
	color.Yellow("Yellow color too!")
	color.Magenta("And many others ..")

	// Hi-intensity colors
	color.HiGreen("Bright green color.")
	color.HiBlack("Bright black means gray..")
	color.HiWhite("Shiny white color!")

However, there are times when custom color mixes are required. Below are some
examples to create custom color objects and use the print functions of each
separate color object.

	// Create a new color object
	c := color.New(color.FgCyan).Add(color.Underline)
	c.Println("Prints cyan text with an underline.")

	// Or just add them to New()
	d := color.New(color.FgCyan, color.Bold)
	d.Printf("This prints bold cyan %s\n", "too!.")


	// Mix up foreground and background colors, create new mixes!
	red := color.New(color.FgRed)

	boldRed := red.Add(color.Bold)
	boldRed.Println("This will print text in bold red.")

	whiteBackground := red.Add(color.BgWhite)
	whiteBackground.Println("Red text with White background.")

	// Use your own io.Writer output
	color.New(color.FgBlue).Fprintln(myWriter, "blue color!")

	blue := color.New(color.FgBlue)
	blue.Fprint(myWriter, "This will print text in blue.")

You can create PrintXxx functions to simplify even more:

	// Create a custom print function for convenient
	red := color.New(color.FgRed).PrintfFunc()
	red("warning")
	red("error: %s", err)

	// Mix up multiple attributes
	notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
	notice("don't forget this...")

You can also FprintXxx functions to pass your own io.Writer:

	blue := color.New(FgBlue).FprintfFunc()
	blue(myWriter, "important notice: %s", stars)

	// Mix up with multiple attributes
	success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
	success(myWriter, don't forget this...")

Or create SprintXxx functions to mix strings with other non-colorized strings:

	yellow := New(FgYellow).SprintFunc()
	red := New(FgRed).SprintFunc()

	fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error"))

	info := New(FgWhite, BgGreen).SprintFunc()
	fmt.Printf("this %s rocks!\n", info("package"))

Windows support is enabled by default. All Print functions work as intended.
However, only for color.SprintXXX functions, user should use fmt.FprintXXX and
set the output to color.Output:

	fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))

	info := New(FgWhite, BgGreen).SprintFunc()
	fmt.Fprintf(color.Output, "this %s rocks!\n", info("package"))

Using with existing code is possible. Just use the Set() method to set the
standard output to the given parameters. That way a rewrite of an existing
code is not required.

	// Use handy standard colors.
	color.Set(color.FgYellow)

	fmt.Println("Existing text will be now in Yellow")
	fmt.Printf("This one %s\n", "too")

	color.Unset() // don't forget to unset

	// You can mix up parameters
	color.Set(color.FgMagenta, color.Bold)
	defer color.Unset() // use it in your function

	fmt.Println("All text will be now bold magenta.")

There might be a case where you want to disable color output (for example to
pipe the standard output of your app to somewhere else). `Color` has support to
disable colors both globally and for single color definition. For example
suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
the color output with:

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

	if *flagNoColor {
		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:

	c := color.New(color.FgCyan)
	c.Println("Prints cyan text")

	c.DisableColor()
	c.Println("This is printed without any color")

	c.EnableColor()
	c.Println("This prints again cyan...")
*/
package color


================================================
FILE: go.mod
================================================
module github.com/fatih/color

go 1.25.0

require (
	github.com/mattn/go-colorable v0.1.14
	github.com/mattn/go-isatty v0.0.20
	golang.org/x/sys v0.42.0
)


================================================
FILE: go.sum
================================================
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
Download .txt
gitextract_m7hx93sk/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       └── go.yml
├── LICENSE.md
├── README.md
├── color.go
├── color_test.go
├── color_windows.go
├── doc.go
├── go.mod
└── go.sum
Download .txt
SYMBOL INDEX (160 symbols across 3 files)

FILE: color.go
  function noColorIsSet (line 39) | func noColorIsSet() bool {
  function stdoutIsTerminal (line 45) | func stdoutIsTerminal() bool {
  function stdOut (line 54) | func stdOut() io.Writer {
  function stdErr (line 63) | func stdErr() io.Writer {
  type Color (line 71) | type Color struct
    method AddRGB (line 198) | func (c *Color) AddRGB(r, g, b int) *Color {
    method AddBgRGB (line 205) | func (c *Color) AddBgRGB(r, g, b int) *Color {
    method Set (line 229) | func (c *Color) Set() *Color {
    method unset (line 238) | func (c *Color) unset() {
    method SetWriter (line 249) | func (c *Color) SetWriter(w io.Writer) *Color {
    method setWriter (line 254) | func (c *Color) setWriter(w io.Writer) (int, error) {
    method UnsetWriter (line 264) | func (c *Color) UnsetWriter(w io.Writer) {
    method unsetWriter (line 268) | func (c *Color) unsetWriter(w io.Writer) (int, error) {
    method Add (line 278) | func (c *Color) Add(value ...Attribute) *Color {
    method Fprint (line 288) | func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err erro...
    method Print (line 310) | func (c *Color) Print(a ...interface{}) (n int, err error) {
    method Fprintf (line 321) | func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) ...
    method Printf (line 341) | func (c *Color) Printf(format string, a ...interface{}) (n int, err er...
    method Fprintln (line 352) | func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err er...
    method Println (line 361) | func (c *Color) Println(a ...interface{}) (n int, err error) {
    method Sprint (line 366) | func (c *Color) Sprint(a ...interface{}) string {
    method Sprintln (line 371) | func (c *Color) Sprintln(a ...interface{}) string {
    method Sprintf (line 376) | func (c *Color) Sprintf(format string, a ...interface{}) string {
    method FprintFunc (line 382) | func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
    method PrintFunc (line 390) | func (c *Color) PrintFunc() func(a ...interface{}) {
    method FprintfFunc (line 398) | func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...in...
    method PrintfFunc (line 406) | func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
    method FprintlnFunc (line 414) | func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
    method PrintlnFunc (line 422) | func (c *Color) PrintlnFunc() func(a ...interface{}) {
    method SprintFunc (line 434) | func (c *Color) SprintFunc() func(a ...interface{}) string {
    method SprintfFunc (line 443) | func (c *Color) SprintfFunc() func(format string, a ...interface{}) st...
    method SprintlnFunc (line 452) | func (c *Color) SprintlnFunc() func(a ...interface{}) string {
    method sequence (line 460) | func (c *Color) sequence() string {
    method wrap (line 471) | func (c *Color) wrap(s string) string {
    method format (line 479) | func (c *Color) format() string {
    method unformat (line 483) | func (c *Color) unformat() string {
    method DisableColor (line 501) | func (c *Color) DisableColor() {
    method EnableColor (line 507) | func (c *Color) EnableColor() {
    method isNoColorSet (line 511) | func (c *Color) isNoColorSet() bool {
    method Equals (line 522) | func (c *Color) Equals(c2 *Color) bool {
  type Attribute (line 77) | type Attribute
  constant escape (line 79) | escape = "\x1b"
  constant Reset (line 83) | Reset Attribute = iota
  constant Bold (line 84) | Bold
  constant Faint (line 85) | Faint
  constant Italic (line 86) | Italic
  constant Underline (line 87) | Underline
  constant BlinkSlow (line 88) | BlinkSlow
  constant BlinkRapid (line 89) | BlinkRapid
  constant ReverseVideo (line 90) | ReverseVideo
  constant Concealed (line 91) | Concealed
  constant CrossedOut (line 92) | CrossedOut
  constant ResetBold (line 96) | ResetBold Attribute = iota + 22
  constant ResetItalic (line 97) | ResetItalic
  constant ResetUnderline (line 98) | ResetUnderline
  constant ResetBlinking (line 99) | ResetBlinking
  constant _ (line 100) | _
  constant ResetReversed (line 101) | ResetReversed
  constant ResetConcealed (line 102) | ResetConcealed
  constant ResetCrossedOut (line 103) | ResetCrossedOut
  constant FgBlack (line 120) | FgBlack Attribute = iota + 30
  constant FgRed (line 121) | FgRed
  constant FgGreen (line 122) | FgGreen
  constant FgYellow (line 123) | FgYellow
  constant FgBlue (line 124) | FgBlue
  constant FgMagenta (line 125) | FgMagenta
  constant FgCyan (line 126) | FgCyan
  constant FgWhite (line 127) | FgWhite
  constant foreground (line 130) | foreground
  constant FgHiBlack (line 135) | FgHiBlack Attribute = iota + 90
  constant FgHiRed (line 136) | FgHiRed
  constant FgHiGreen (line 137) | FgHiGreen
  constant FgHiYellow (line 138) | FgHiYellow
  constant FgHiBlue (line 139) | FgHiBlue
  constant FgHiMagenta (line 140) | FgHiMagenta
  constant FgHiCyan (line 141) | FgHiCyan
  constant FgHiWhite (line 142) | FgHiWhite
  constant BgBlack (line 147) | BgBlack Attribute = iota + 40
  constant BgRed (line 148) | BgRed
  constant BgGreen (line 149) | BgGreen
  constant BgYellow (line 150) | BgYellow
  constant BgBlue (line 151) | BgBlue
  constant BgMagenta (line 152) | BgMagenta
  constant BgCyan (line 153) | BgCyan
  constant BgWhite (line 154) | BgWhite
  constant background (line 157) | background
  constant BgHiBlack (line 162) | BgHiBlack Attribute = iota + 100
  constant BgHiRed (line 163) | BgHiRed
  constant BgHiGreen (line 164) | BgHiGreen
  constant BgHiYellow (line 165) | BgHiYellow
  constant BgHiBlue (line 166) | BgHiBlue
  constant BgHiMagenta (line 167) | BgHiMagenta
  constant BgHiCyan (line 168) | BgHiCyan
  constant BgHiWhite (line 169) | BgHiWhite
  function New (line 173) | func New(value ...Attribute) *Color {
  function RGB (line 187) | func RGB(r, g, b int) *Color {
  function BgRGB (line 192) | func BgRGB(r, g, b int) *Color {
  function Set (line 212) | func Set(p ...Attribute) *Color {
  function Unset (line 220) | func Unset() {
  function boolPtr (line 549) | func boolPtr(v bool) *bool {
  function getCachedColor (line 553) | func getCachedColor(p Attribute) *Color {
  function colorPrint (line 566) | func colorPrint(format string, p Attribute, a ...interface{}) {
  function colorString (line 580) | func colorString(format string, p Attribute, a ...interface{}) string {
  function Black (line 592) | func Black(format string, a ...interface{}) { colorPrint(format, FgBlack...
  function Red (line 596) | func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a....
  function Green (line 600) | func Green(format string, a ...interface{}) { colorPrint(format, FgGreen...
  function Yellow (line 604) | func Yellow(format string, a ...interface{}) { colorPrint(format, FgYell...
  function Blue (line 608) | func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, ...
  function Magenta (line 612) | func Magenta(format string, a ...interface{}) { colorPrint(format, FgMag...
  function Cyan (line 616) | func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, ...
  function White (line 620) | func White(format string, a ...interface{}) { colorPrint(format, FgWhite...
  function BlackString (line 624) | func BlackString(format string, a ...interface{}) string { return colorS...
  function RedString (line 628) | func RedString(format string, a ...interface{}) string { return colorStr...
  function GreenString (line 632) | func GreenString(format string, a ...interface{}) string { return colorS...
  function YellowString (line 636) | func YellowString(format string, a ...interface{}) string { return color...
  function BlueString (line 640) | func BlueString(format string, a ...interface{}) string { return colorSt...
  function MagentaString (line 644) | func MagentaString(format string, a ...interface{}) string {
  function CyanString (line 650) | func CyanString(format string, a ...interface{}) string { return colorSt...
  function WhiteString (line 654) | func WhiteString(format string, a ...interface{}) string { return colorS...
  function HiBlack (line 658) | func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiB...
  function HiRed (line 662) | func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed...
  function HiGreen (line 666) | func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiG...
  function HiYellow (line 670) | func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHi...
  function HiBlue (line 674) | func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBl...
  function HiMagenta (line 678) | func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgH...
  function HiCyan (line 682) | func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCy...
  function HiWhite (line 686) | func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiW...
  function HiBlackString (line 690) | func HiBlackString(format string, a ...interface{}) string {
  function HiRedString (line 696) | func HiRedString(format string, a ...interface{}) string { return colorS...
  function HiGreenString (line 700) | func HiGreenString(format string, a ...interface{}) string {
  function HiYellowString (line 706) | func HiYellowString(format string, a ...interface{}) string {
  function HiBlueString (line 712) | func HiBlueString(format string, a ...interface{}) string { return color...
  function HiMagentaString (line 716) | func HiMagentaString(format string, a ...interface{}) string {
  function HiCyanString (line 722) | func HiCyanString(format string, a ...interface{}) string { return color...
  function HiWhiteString (line 726) | func HiWhiteString(format string, a ...interface{}) string {
  function sprintln (line 731) | func sprintln(a ...interface{}) string {

FILE: color_test.go
  function TestColor (line 17) | func TestColor(t *testing.T) {
  function TestColorEquals (line 74) | func TestColorEquals(t *testing.T) {
  function TestColorEquals_DuplicateAttributes (line 108) | func TestColorEquals_DuplicateAttributes(t *testing.T) {
  function TestNoColor (line 122) | func TestNoColor(t *testing.T) {
  function TestNoColor_Env (line 176) | func TestNoColor_Env(t *testing.T) {
  function Test_noColorIsSet (line 218) | func Test_noColorIsSet(t *testing.T) {
  function TestStdoutIsTerminal_NilStdout (line 253) | func TestStdoutIsTerminal_NilStdout(t *testing.T) {
  function TestStdOut_NilStdout (line 265) | func TestStdOut_NilStdout(t *testing.T) {
  function TestStdErr_NilStderr (line 277) | func TestStdErr_NilStderr(t *testing.T) {
  function TestColorVisual (line 289) | func TestColorVisual(t *testing.T) {
  function TestNoFormat (line 390) | func TestNoFormat(t *testing.T) {
  function TestNoFormatString (line 440) | func TestNoFormatString(t *testing.T) {
  function TestColor_Println_Newline (line 474) | func TestColor_Println_Newline(t *testing.T) {
  function TestColor_Sprintln_Newline (line 489) | func TestColor_Sprintln_Newline(t *testing.T) {
  function TestColor_Fprint (line 500) | func TestColor_Fprint(t *testing.T) {
  function TestColor_Fprintln (line 519) | func TestColor_Fprintln(t *testing.T) {
  function TestColor_Fprintf (line 538) | func TestColor_Fprintf(t *testing.T) {
  function TestColor_Fprintln_Newline (line 558) | func TestColor_Fprintln_Newline(t *testing.T) {
  function readRaw (line 571) | func readRaw(t *testing.T, r io.Reader) string {
  function TestIssue206_1 (line 582) | func TestIssue206_1(t *testing.T) {
  function TestIssue206_2 (line 601) | func TestIssue206_2(t *testing.T) {
  function TestIssue218 (line 617) | func TestIssue218(t *testing.T) {
  function TestRGB (line 648) | func TestRGB(t *testing.T) {

FILE: color_windows.go
  function init (line 9) | func init() {
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (56K chars).
[
  {
    "path": ".github/dependabot.yml",
    "chars": 227,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"gomod\"\n    directory: \"/\" # Location of go.mod\n    schedule:\n      interval:"
  },
  {
    "path": ".github/workflows/go.yml",
    "chars": 1036,
    "preview": "name: build\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  test:\n    name: Test & Build\n    runs-on: ub"
  },
  {
    "path": "LICENSE.md",
    "chars": 1079,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Fatih Arslan\n\nPermission is hereby granted, free of charge, to any person obta"
  },
  {
    "path": "README.md",
    "chars": 5508,
    "preview": "# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGo"
  },
  {
    "path": "color.go",
    "chars": 22147,
    "preview": "package color\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/mattn/go-colorable\"\n\t\"github.com/"
  },
  {
    "path": "color_test.go",
    "chars": 16061,
    "preview": "package color\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/mattn/go-colorable\"\n)\n\n// Testin"
  },
  {
    "path": "color_windows.go",
    "chars": 539,
    "preview": "package color\n\nimport (\n\t\"os\"\n\n\t\"golang.org/x/sys/windows\"\n)\n\nfunc init() {\n\t// Opt-in for ansi color support for curren"
  },
  {
    "path": "doc.go",
    "chars": 4284,
    "preview": "/*\nPackage color is an ANSI color package to output colorized or SGR defined\noutput to the standard output. The API can "
  },
  {
    "path": "go.mod",
    "chars": 155,
    "preview": "module github.com/fatih/color\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/mattn/go-colorable v0.1.14\n\tgithub.com/mattn/go-isatty v"
  },
  {
    "path": "go.sum",
    "chars": 584,
    "preview": "github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=\ngithub.com/mattn/go-colorable v0.1"
  }
]

About this extraction

This page contains the full source code of the fatih/color GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (50.4 KB), approximately 14.8k tokens, and a symbol index with 160 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!