text: 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. 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" ||
  		(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
  
  	// Output defines the standard output of the print functions. By default
  	// os.Stdout is used.
  	Output = colorable.NewColorableStdout()
  
  	// 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
  )
  
  // 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
  )
  
  // Foreground text colors
  const (
  	FgBlack Attribute = iota + 30
  	FgRed
  	FgGreen
  	FgYellow
  	FgBlue
  	FgMagenta
  	FgCyan
  	FgWhite
  )
  
  // 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
  )
  
  // 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)}
  	c.Add(value...)
  	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.Fprintf(Output, c.format())
  	return c
  }
  
  func (c *Color) unset() {
  	if c.isNoColorSet() {
  		return
  	}
  
  	Unset()
  }
  
  func (c *Color) setWriter(w io.Writer) *Color {
  	if c.isNoColorSet() {
  		return c
  	}
  
  	fmt.Fprintf(w, c.format())
  	return c
  }
  
  func (c *Color) unsetWriter(w io.Writer) {
  	if c.isNoColorSet() {
  		return
  	}
  
  	if NoColor {
  		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
  }
  
  func (c *Color) prepend(value Attribute) {
  	c.params = append(c.params, 0)
  	copy(c.params[1:], c.params[0:])
  	c.params[0] = value
  }
  
  // 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) {
  	c.setWriter(w)
  	defer c.unsetWriter(w)
  
  	return fmt.Fprint(w, a...)
  }
  
  // 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) {
  	c.setWriter(w)
  	defer c.unsetWriter(w)
  
  	return fmt.Fprintf(w, format, a...)
  }
  
  // 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) {
  	c.setWriter(w)
  	defer c.unsetWriter(w)
  
  	return fmt.Fprintln(w, 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) {
  	c.Set()
  	defer c.unset()
  
  	return fmt.Fprintln(Output, 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(fmt.Sprintln(a...))
  }
  
  // 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(fmt.Sprintln(a...))
  	}
  }
  
  // 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)
  }
  
  // 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 setted 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 len(c.params) != len(c2.params) {
  		return false
  	}
  
  	for _, attr := range c.params {
  		if !c2.attrExists(attr) {
  			return false
  		}
  	}
  
  	return true
  }
  
  func (c *Color) attrExists(a Attribute) bool {
  	for _, attr := range c.params {
  		if attr == a {
  			return true
  		}
  	}
  
  	return false
  }
  
  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...)
  }
  