...

Source file src/github.com/fatih/color/color.go

Documentation: github.com/fatih/color

     1  package color
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strconv"
     8  	"strings"
     9  	"sync"
    10  
    11  	"github.com/mattn/go-colorable"
    12  	"github.com/mattn/go-isatty"
    13  )
    14  
    15  var (
    16  	// NoColor defines if the output is colorized or not. It's dynamically set to
    17  	// false or true based on the stdout's file descriptor referring to a terminal
    18  	// or not. It's also set to true if the NO_COLOR environment variable is
    19  	// set (regardless of its value). This is a global option and affects all
    20  	// colors. For more control over each color block use the methods
    21  	// DisableColor() individually.
    22  	NoColor = noColorIsSet() || os.Getenv("TERM") == "dumb" ||
    23  		(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
    24  
    25  	// Output defines the standard output of the print functions. By default,
    26  	// os.Stdout is used.
    27  	Output = colorable.NewColorableStdout()
    28  
    29  	// Error defines a color supporting writer for os.Stderr.
    30  	Error = colorable.NewColorableStderr()
    31  
    32  	// colorsCache is used to reduce the count of created Color objects and
    33  	// allows to reuse already created objects with required Attribute.
    34  	colorsCache   = make(map[Attribute]*Color)
    35  	colorsCacheMu sync.Mutex // protects colorsCache
    36  )
    37  
    38  // noColorIsSet returns true if the environment variable NO_COLOR is set to a non-empty string.
    39  func noColorIsSet() bool {
    40  	return os.Getenv("NO_COLOR") != ""
    41  }
    42  
    43  // Color defines a custom color object which is defined by SGR parameters.
    44  type Color struct {
    45  	params  []Attribute
    46  	noColor *bool
    47  }
    48  
    49  // Attribute defines a single SGR Code
    50  type Attribute int
    51  
    52  const escape = "\x1b"
    53  
    54  // Base attributes
    55  const (
    56  	Reset Attribute = iota
    57  	Bold
    58  	Faint
    59  	Italic
    60  	Underline
    61  	BlinkSlow
    62  	BlinkRapid
    63  	ReverseVideo
    64  	Concealed
    65  	CrossedOut
    66  )
    67  
    68  const (
    69  	ResetBold Attribute = iota + 22
    70  	ResetItalic
    71  	ResetUnderline
    72  	ResetBlinking
    73  	_
    74  	ResetReversed
    75  	ResetConcealed
    76  	ResetCrossedOut
    77  )
    78  
    79  var mapResetAttributes map[Attribute]Attribute = map[Attribute]Attribute{
    80  	Bold:         ResetBold,
    81  	Faint:        ResetBold,
    82  	Italic:       ResetItalic,
    83  	Underline:    ResetUnderline,
    84  	BlinkSlow:    ResetBlinking,
    85  	BlinkRapid:   ResetBlinking,
    86  	ReverseVideo: ResetReversed,
    87  	Concealed:    ResetConcealed,
    88  	CrossedOut:   ResetCrossedOut,
    89  }
    90  
    91  // Foreground text colors
    92  const (
    93  	FgBlack Attribute = iota + 30
    94  	FgRed
    95  	FgGreen
    96  	FgYellow
    97  	FgBlue
    98  	FgMagenta
    99  	FgCyan
   100  	FgWhite
   101  )
   102  
   103  // Foreground Hi-Intensity text colors
   104  const (
   105  	FgHiBlack Attribute = iota + 90
   106  	FgHiRed
   107  	FgHiGreen
   108  	FgHiYellow
   109  	FgHiBlue
   110  	FgHiMagenta
   111  	FgHiCyan
   112  	FgHiWhite
   113  )
   114  
   115  // Background text colors
   116  const (
   117  	BgBlack Attribute = iota + 40
   118  	BgRed
   119  	BgGreen
   120  	BgYellow
   121  	BgBlue
   122  	BgMagenta
   123  	BgCyan
   124  	BgWhite
   125  )
   126  
   127  // Background Hi-Intensity text colors
   128  const (
   129  	BgHiBlack Attribute = iota + 100
   130  	BgHiRed
   131  	BgHiGreen
   132  	BgHiYellow
   133  	BgHiBlue
   134  	BgHiMagenta
   135  	BgHiCyan
   136  	BgHiWhite
   137  )
   138  
   139  // New returns a newly created color object.
   140  func New(value ...Attribute) *Color {
   141  	c := &Color{
   142  		params: make([]Attribute, 0),
   143  	}
   144  
   145  	if noColorIsSet() {
   146  		c.noColor = boolPtr(true)
   147  	}
   148  
   149  	c.Add(value...)
   150  	return c
   151  }
   152  
   153  // Set sets the given parameters immediately. It will change the color of
   154  // output with the given SGR parameters until color.Unset() is called.
   155  func Set(p ...Attribute) *Color {
   156  	c := New(p...)
   157  	c.Set()
   158  	return c
   159  }
   160  
   161  // Unset resets all escape attributes and clears the output. Usually should
   162  // be called after Set().
   163  func Unset() {
   164  	if NoColor {
   165  		return
   166  	}
   167  
   168  	fmt.Fprintf(Output, "%s[%dm", escape, Reset)
   169  }
   170  
   171  // Set sets the SGR sequence.
   172  func (c *Color) Set() *Color {
   173  	if c.isNoColorSet() {
   174  		return c
   175  	}
   176  
   177  	fmt.Fprint(Output, c.format())
   178  	return c
   179  }
   180  
   181  func (c *Color) unset() {
   182  	if c.isNoColorSet() {
   183  		return
   184  	}
   185  
   186  	Unset()
   187  }
   188  
   189  // SetWriter is used to set the SGR sequence with the given io.Writer. This is
   190  // a low-level function, and users should use the higher-level functions, such
   191  // as color.Fprint, color.Print, etc.
   192  func (c *Color) SetWriter(w io.Writer) *Color {
   193  	if c.isNoColorSet() {
   194  		return c
   195  	}
   196  
   197  	fmt.Fprint(w, c.format())
   198  	return c
   199  }
   200  
   201  // UnsetWriter resets all escape attributes and clears the output with the give
   202  // io.Writer. Usually should be called after SetWriter().
   203  func (c *Color) UnsetWriter(w io.Writer) {
   204  	if c.isNoColorSet() {
   205  		return
   206  	}
   207  
   208  	if NoColor {
   209  		return
   210  	}
   211  
   212  	fmt.Fprintf(w, "%s[%dm", escape, Reset)
   213  }
   214  
   215  // Add is used to chain SGR parameters. Use as many as parameters to combine
   216  // and create custom color objects. Example: Add(color.FgRed, color.Underline).
   217  func (c *Color) Add(value ...Attribute) *Color {
   218  	c.params = append(c.params, value...)
   219  	return c
   220  }
   221  
   222  // Fprint formats using the default formats for its operands and writes to w.
   223  // Spaces are added between operands when neither is a string.
   224  // It returns the number of bytes written and any write error encountered.
   225  // On Windows, users should wrap w with colorable.NewColorable() if w is of
   226  // type *os.File.
   227  func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
   228  	c.SetWriter(w)
   229  	defer c.UnsetWriter(w)
   230  
   231  	return fmt.Fprint(w, a...)
   232  }
   233  
   234  // Print formats using the default formats for its operands and writes to
   235  // standard output. Spaces are added between operands when neither is a
   236  // string. It returns the number of bytes written and any write error
   237  // encountered. This is the standard fmt.Print() method wrapped with the given
   238  // color.
   239  func (c *Color) Print(a ...interface{}) (n int, err error) {
   240  	c.Set()
   241  	defer c.unset()
   242  
   243  	return fmt.Fprint(Output, a...)
   244  }
   245  
   246  // Fprintf formats according to a format specifier and writes to w.
   247  // It returns the number of bytes written and any write error encountered.
   248  // On Windows, users should wrap w with colorable.NewColorable() if w is of
   249  // type *os.File.
   250  func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
   251  	c.SetWriter(w)
   252  	defer c.UnsetWriter(w)
   253  
   254  	return fmt.Fprintf(w, format, a...)
   255  }
   256  
   257  // Printf formats according to a format specifier and writes to standard output.
   258  // It returns the number of bytes written and any write error encountered.
   259  // This is the standard fmt.Printf() method wrapped with the given color.
   260  func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
   261  	c.Set()
   262  	defer c.unset()
   263  
   264  	return fmt.Fprintf(Output, format, a...)
   265  }
   266  
   267  // Fprintln formats using the default formats for its operands and writes to w.
   268  // Spaces are always added between operands and a newline is appended.
   269  // On Windows, users should wrap w with colorable.NewColorable() if w is of
   270  // type *os.File.
   271  func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
   272  	return fmt.Fprintln(w, c.wrap(fmt.Sprint(a...)))
   273  }
   274  
   275  // Println formats using the default formats for its operands and writes to
   276  // standard output. Spaces are always added between operands and a newline is
   277  // appended. It returns the number of bytes written and any write error
   278  // encountered. This is the standard fmt.Print() method wrapped with the given
   279  // color.
   280  func (c *Color) Println(a ...interface{}) (n int, err error) {
   281  	return fmt.Fprintln(Output, c.wrap(fmt.Sprint(a...)))
   282  }
   283  
   284  // Sprint is just like Print, but returns a string instead of printing it.
   285  func (c *Color) Sprint(a ...interface{}) string {
   286  	return c.wrap(fmt.Sprint(a...))
   287  }
   288  
   289  // Sprintln is just like Println, but returns a string instead of printing it.
   290  func (c *Color) Sprintln(a ...interface{}) string {
   291  	return fmt.Sprintln(c.Sprint(a...))
   292  }
   293  
   294  // Sprintf is just like Printf, but returns a string instead of printing it.
   295  func (c *Color) Sprintf(format string, a ...interface{}) string {
   296  	return c.wrap(fmt.Sprintf(format, a...))
   297  }
   298  
   299  // FprintFunc returns a new function that prints the passed arguments as
   300  // colorized with color.Fprint().
   301  func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
   302  	return func(w io.Writer, a ...interface{}) {
   303  		c.Fprint(w, a...)
   304  	}
   305  }
   306  
   307  // PrintFunc returns a new function that prints the passed arguments as
   308  // colorized with color.Print().
   309  func (c *Color) PrintFunc() func(a ...interface{}) {
   310  	return func(a ...interface{}) {
   311  		c.Print(a...)
   312  	}
   313  }
   314  
   315  // FprintfFunc returns a new function that prints the passed arguments as
   316  // colorized with color.Fprintf().
   317  func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
   318  	return func(w io.Writer, format string, a ...interface{}) {
   319  		c.Fprintf(w, format, a...)
   320  	}
   321  }
   322  
   323  // PrintfFunc returns a new function that prints the passed arguments as
   324  // colorized with color.Printf().
   325  func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
   326  	return func(format string, a ...interface{}) {
   327  		c.Printf(format, a...)
   328  	}
   329  }
   330  
   331  // FprintlnFunc returns a new function that prints the passed arguments as
   332  // colorized with color.Fprintln().
   333  func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
   334  	return func(w io.Writer, a ...interface{}) {
   335  		c.Fprintln(w, a...)
   336  	}
   337  }
   338  
   339  // PrintlnFunc returns a new function that prints the passed arguments as
   340  // colorized with color.Println().
   341  func (c *Color) PrintlnFunc() func(a ...interface{}) {
   342  	return func(a ...interface{}) {
   343  		c.Println(a...)
   344  	}
   345  }
   346  
   347  // SprintFunc returns a new function that returns colorized strings for the
   348  // given arguments with fmt.Sprint(). Useful to put into or mix into other
   349  // string. Windows users should use this in conjunction with color.Output, example:
   350  //
   351  //	put := New(FgYellow).SprintFunc()
   352  //	fmt.Fprintf(color.Output, "This is a %s", put("warning"))
   353  func (c *Color) SprintFunc() func(a ...interface{}) string {
   354  	return func(a ...interface{}) string {
   355  		return c.wrap(fmt.Sprint(a...))
   356  	}
   357  }
   358  
   359  // SprintfFunc returns a new function that returns colorized strings for the
   360  // given arguments with fmt.Sprintf(). Useful to put into or mix into other
   361  // string. Windows users should use this in conjunction with color.Output.
   362  func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
   363  	return func(format string, a ...interface{}) string {
   364  		return c.wrap(fmt.Sprintf(format, a...))
   365  	}
   366  }
   367  
   368  // SprintlnFunc returns a new function that returns colorized strings for the
   369  // given arguments with fmt.Sprintln(). Useful to put into or mix into other
   370  // string. Windows users should use this in conjunction with color.Output.
   371  func (c *Color) SprintlnFunc() func(a ...interface{}) string {
   372  	return func(a ...interface{}) string {
   373  		return fmt.Sprintln(c.Sprint(a...))
   374  	}
   375  }
   376  
   377  // sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m"
   378  // an example output might be: "1;36" -> bold cyan
   379  func (c *Color) sequence() string {
   380  	format := make([]string, len(c.params))
   381  	for i, v := range c.params {
   382  		format[i] = strconv.Itoa(int(v))
   383  	}
   384  
   385  	return strings.Join(format, ";")
   386  }
   387  
   388  // wrap wraps the s string with the colors attributes. The string is ready to
   389  // be printed.
   390  func (c *Color) wrap(s string) string {
   391  	if c.isNoColorSet() {
   392  		return s
   393  	}
   394  
   395  	return c.format() + s + c.unformat()
   396  }
   397  
   398  func (c *Color) format() string {
   399  	return fmt.Sprintf("%s[%sm", escape, c.sequence())
   400  }
   401  
   402  func (c *Color) unformat() string {
   403  	//return fmt.Sprintf("%s[%dm", escape, Reset)
   404  	//for each element in sequence let's use the speficic reset escape, ou the generic one if not found
   405  	format := make([]string, len(c.params))
   406  	for i, v := range c.params {
   407  		format[i] = strconv.Itoa(int(Reset))
   408  		ra, ok := mapResetAttributes[v]
   409  		if ok {
   410  			format[i] = strconv.Itoa(int(ra))
   411  		}
   412  	}
   413  
   414  	return fmt.Sprintf("%s[%sm", escape, strings.Join(format, ";"))
   415  }
   416  
   417  // DisableColor disables the color output. Useful to not change any existing
   418  // code and still being able to output. Can be used for flags like
   419  // "--no-color". To enable back use EnableColor() method.
   420  func (c *Color) DisableColor() {
   421  	c.noColor = boolPtr(true)
   422  }
   423  
   424  // EnableColor enables the color output. Use it in conjunction with
   425  // DisableColor(). Otherwise, this method has no side effects.
   426  func (c *Color) EnableColor() {
   427  	c.noColor = boolPtr(false)
   428  }
   429  
   430  func (c *Color) isNoColorSet() bool {
   431  	// check first if we have user set action
   432  	if c.noColor != nil {
   433  		return *c.noColor
   434  	}
   435  
   436  	// if not return the global option, which is disabled by default
   437  	return NoColor
   438  }
   439  
   440  // Equals returns a boolean value indicating whether two colors are equal.
   441  func (c *Color) Equals(c2 *Color) bool {
   442  	if c == nil && c2 == nil {
   443  		return true
   444  	}
   445  	if c == nil || c2 == nil {
   446  		return false
   447  	}
   448  	if len(c.params) != len(c2.params) {
   449  		return false
   450  	}
   451  
   452  	for _, attr := range c.params {
   453  		if !c2.attrExists(attr) {
   454  			return false
   455  		}
   456  	}
   457  
   458  	return true
   459  }
   460  
   461  func (c *Color) attrExists(a Attribute) bool {
   462  	for _, attr := range c.params {
   463  		if attr == a {
   464  			return true
   465  		}
   466  	}
   467  
   468  	return false
   469  }
   470  
   471  func boolPtr(v bool) *bool {
   472  	return &v
   473  }
   474  
   475  func getCachedColor(p Attribute) *Color {
   476  	colorsCacheMu.Lock()
   477  	defer colorsCacheMu.Unlock()
   478  
   479  	c, ok := colorsCache[p]
   480  	if !ok {
   481  		c = New(p)
   482  		colorsCache[p] = c
   483  	}
   484  
   485  	return c
   486  }
   487  
   488  func colorPrint(format string, p Attribute, a ...interface{}) {
   489  	c := getCachedColor(p)
   490  
   491  	if !strings.HasSuffix(format, "\n") {
   492  		format += "\n"
   493  	}
   494  
   495  	if len(a) == 0 {
   496  		c.Print(format)
   497  	} else {
   498  		c.Printf(format, a...)
   499  	}
   500  }
   501  
   502  func colorString(format string, p Attribute, a ...interface{}) string {
   503  	c := getCachedColor(p)
   504  
   505  	if len(a) == 0 {
   506  		return c.SprintFunc()(format)
   507  	}
   508  
   509  	return c.SprintfFunc()(format, a...)
   510  }
   511  
   512  // Black is a convenient helper function to print with black foreground. A
   513  // newline is appended to format by default.
   514  func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }
   515  
   516  // Red is a convenient helper function to print with red foreground. A
   517  // newline is appended to format by default.
   518  func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }
   519  
   520  // Green is a convenient helper function to print with green foreground. A
   521  // newline is appended to format by default.
   522  func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }
   523  
   524  // Yellow is a convenient helper function to print with yellow foreground.
   525  // A newline is appended to format by default.
   526  func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }
   527  
   528  // Blue is a convenient helper function to print with blue foreground. A
   529  // newline is appended to format by default.
   530  func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }
   531  
   532  // Magenta is a convenient helper function to print with magenta foreground.
   533  // A newline is appended to format by default.
   534  func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }
   535  
   536  // Cyan is a convenient helper function to print with cyan foreground. A
   537  // newline is appended to format by default.
   538  func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }
   539  
   540  // White is a convenient helper function to print with white foreground. A
   541  // newline is appended to format by default.
   542  func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }
   543  
   544  // BlackString is a convenient helper function to return a string with black
   545  // foreground.
   546  func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }
   547  
   548  // RedString is a convenient helper function to return a string with red
   549  // foreground.
   550  func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }
   551  
   552  // GreenString is a convenient helper function to return a string with green
   553  // foreground.
   554  func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }
   555  
   556  // YellowString is a convenient helper function to return a string with yellow
   557  // foreground.
   558  func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }
   559  
   560  // BlueString is a convenient helper function to return a string with blue
   561  // foreground.
   562  func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }
   563  
   564  // MagentaString is a convenient helper function to return a string with magenta
   565  // foreground.
   566  func MagentaString(format string, a ...interface{}) string {
   567  	return colorString(format, FgMagenta, a...)
   568  }
   569  
   570  // CyanString is a convenient helper function to return a string with cyan
   571  // foreground.
   572  func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }
   573  
   574  // WhiteString is a convenient helper function to return a string with white
   575  // foreground.
   576  func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }
   577  
   578  // HiBlack is a convenient helper function to print with hi-intensity black foreground. A
   579  // newline is appended to format by default.
   580  func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) }
   581  
   582  // HiRed is a convenient helper function to print with hi-intensity red foreground. A
   583  // newline is appended to format by default.
   584  func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) }
   585  
   586  // HiGreen is a convenient helper function to print with hi-intensity green foreground. A
   587  // newline is appended to format by default.
   588  func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) }
   589  
   590  // HiYellow is a convenient helper function to print with hi-intensity yellow foreground.
   591  // A newline is appended to format by default.
   592  func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) }
   593  
   594  // HiBlue is a convenient helper function to print with hi-intensity blue foreground. A
   595  // newline is appended to format by default.
   596  func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) }
   597  
   598  // HiMagenta is a convenient helper function to print with hi-intensity magenta foreground.
   599  // A newline is appended to format by default.
   600  func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) }
   601  
   602  // HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A
   603  // newline is appended to format by default.
   604  func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) }
   605  
   606  // HiWhite is a convenient helper function to print with hi-intensity white foreground. A
   607  // newline is appended to format by default.
   608  func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) }
   609  
   610  // HiBlackString is a convenient helper function to return a string with hi-intensity black
   611  // foreground.
   612  func HiBlackString(format string, a ...interface{}) string {
   613  	return colorString(format, FgHiBlack, a...)
   614  }
   615  
   616  // HiRedString is a convenient helper function to return a string with hi-intensity red
   617  // foreground.
   618  func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) }
   619  
   620  // HiGreenString is a convenient helper function to return a string with hi-intensity green
   621  // foreground.
   622  func HiGreenString(format string, a ...interface{}) string {
   623  	return colorString(format, FgHiGreen, a...)
   624  }
   625  
   626  // HiYellowString is a convenient helper function to return a string with hi-intensity yellow
   627  // foreground.
   628  func HiYellowString(format string, a ...interface{}) string {
   629  	return colorString(format, FgHiYellow, a...)
   630  }
   631  
   632  // HiBlueString is a convenient helper function to return a string with hi-intensity blue
   633  // foreground.
   634  func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) }
   635  
   636  // HiMagentaString is a convenient helper function to return a string with hi-intensity magenta
   637  // foreground.
   638  func HiMagentaString(format string, a ...interface{}) string {
   639  	return colorString(format, FgHiMagenta, a...)
   640  }
   641  
   642  // HiCyanString is a convenient helper function to return a string with hi-intensity cyan
   643  // foreground.
   644  func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) }
   645  
   646  // HiWhiteString is a convenient helper function to return a string with hi-intensity white
   647  // foreground.
   648  func HiWhiteString(format string, a ...interface{}) string {
   649  	return colorString(format, FgHiWhite, a...)
   650  }
   651  

View as plain text