11 "github.com/mattn/go-colorable"
12 "github.com/mattn/go-isatty"
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. This is a global option and affects all colors. For more control
19 // over each color block use the methods DisableColor() individually.
20 NoColor = os.Getenv("TERM") == "dumb" ||
21 (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
23 // Output defines the standard output of the print functions. By default
25 Output = colorable.NewColorableStdout()
27 // Error defines a color supporting writer for os.Stderr.
28 Error = colorable.NewColorableStderr()
30 // colorsCache is used to reduce the count of created Color objects and
31 // allows to reuse already created objects with required Attribute.
32 colorsCache = make(map[Attribute]*Color)
33 colorsCacheMu sync.Mutex // protects colorsCache
36 // Color defines a custom color object which is defined by SGR parameters.
42 // Attribute defines a single SGR Code
49 Reset Attribute = iota
61 // Foreground text colors
63 FgBlack Attribute = iota + 30
73 // Foreground Hi-Intensity text colors
75 FgHiBlack Attribute = iota + 90
85 // Background text colors
87 BgBlack Attribute = iota + 40
97 // Background Hi-Intensity text colors
99 BgHiBlack Attribute = iota + 100
109 // New returns a newly created color object.
110 func New(value ...Attribute) *Color {
111 c := &Color{params: make([]Attribute, 0)}
116 // Set sets the given parameters immediately. It will change the color of
117 // output with the given SGR parameters until color.Unset() is called.
118 func Set(p ...Attribute) *Color {
124 // Unset resets all escape attributes and clears the output. Usually should
125 // be called after Set().
131 fmt.Fprintf(Output, "%s[%dm", escape, Reset)
134 // Set sets the SGR sequence.
135 func (c *Color) Set() *Color {
136 if c.isNoColorSet() {
140 fmt.Fprintf(Output, c.format())
144 func (c *Color) unset() {
145 if c.isNoColorSet() {
152 func (c *Color) setWriter(w io.Writer) *Color {
153 if c.isNoColorSet() {
157 fmt.Fprintf(w, c.format())
161 func (c *Color) unsetWriter(w io.Writer) {
162 if c.isNoColorSet() {
170 fmt.Fprintf(w, "%s[%dm", escape, Reset)
173 // Add is used to chain SGR parameters. Use as many as parameters to combine
174 // and create custom color objects. Example: Add(color.FgRed, color.Underline).
175 func (c *Color) Add(value ...Attribute) *Color {
176 c.params = append(c.params, value...)
180 func (c *Color) prepend(value Attribute) {
181 c.params = append(c.params, 0)
182 copy(c.params[1:], c.params[0:])
186 // Fprint formats using the default formats for its operands and writes to w.
187 // Spaces are added between operands when neither is a string.
188 // It returns the number of bytes written and any write error encountered.
189 // On Windows, users should wrap w with colorable.NewColorable() if w is of
191 func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
193 defer c.unsetWriter(w)
195 return fmt.Fprint(w, a...)
198 // Print formats using the default formats for its operands and writes to
199 // standard output. Spaces are added between operands when neither is a
200 // string. It returns the number of bytes written and any write error
201 // encountered. This is the standard fmt.Print() method wrapped with the given
203 func (c *Color) Print(a ...interface{}) (n int, err error) {
207 return fmt.Fprint(Output, a...)
210 // Fprintf formats according to a format specifier and writes to w.
211 // It returns the number of bytes written and any write error encountered.
212 // On Windows, users should wrap w with colorable.NewColorable() if w is of
214 func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
216 defer c.unsetWriter(w)
218 return fmt.Fprintf(w, format, a...)
221 // Printf formats according to a format specifier and writes to standard output.
222 // It returns the number of bytes written and any write error encountered.
223 // This is the standard fmt.Printf() method wrapped with the given color.
224 func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
228 return fmt.Fprintf(Output, format, a...)
231 // Fprintln formats using the default formats for its operands and writes to w.
232 // Spaces are always added between operands and a newline is appended.
233 // On Windows, users should wrap w with colorable.NewColorable() if w is of
235 func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
237 defer c.unsetWriter(w)
239 return fmt.Fprintln(w, a...)
242 // Println formats using the default formats for its operands and writes to
243 // standard output. Spaces are always added between operands and a newline is
244 // appended. It returns the number of bytes written and any write error
245 // encountered. This is the standard fmt.Print() method wrapped with the given
247 func (c *Color) Println(a ...interface{}) (n int, err error) {
251 return fmt.Fprintln(Output, a...)
254 // Sprint is just like Print, but returns a string instead of printing it.
255 func (c *Color) Sprint(a ...interface{}) string {
256 return c.wrap(fmt.Sprint(a...))
259 // Sprintln is just like Println, but returns a string instead of printing it.
260 func (c *Color) Sprintln(a ...interface{}) string {
261 return c.wrap(fmt.Sprintln(a...))
264 // Sprintf is just like Printf, but returns a string instead of printing it.
265 func (c *Color) Sprintf(format string, a ...interface{}) string {
266 return c.wrap(fmt.Sprintf(format, a...))
269 // FprintFunc returns a new function that prints the passed arguments as
270 // colorized with color.Fprint().
271 func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
272 return func(w io.Writer, a ...interface{}) {
277 // PrintFunc returns a new function that prints the passed arguments as
278 // colorized with color.Print().
279 func (c *Color) PrintFunc() func(a ...interface{}) {
280 return func(a ...interface{}) {
285 // FprintfFunc returns a new function that prints the passed arguments as
286 // colorized with color.Fprintf().
287 func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
288 return func(w io.Writer, format string, a ...interface{}) {
289 c.Fprintf(w, format, a...)
293 // PrintfFunc returns a new function that prints the passed arguments as
294 // colorized with color.Printf().
295 func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
296 return func(format string, a ...interface{}) {
297 c.Printf(format, a...)
301 // FprintlnFunc returns a new function that prints the passed arguments as
302 // colorized with color.Fprintln().
303 func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
304 return func(w io.Writer, a ...interface{}) {
309 // PrintlnFunc returns a new function that prints the passed arguments as
310 // colorized with color.Println().
311 func (c *Color) PrintlnFunc() func(a ...interface{}) {
312 return func(a ...interface{}) {
317 // SprintFunc returns a new function that returns colorized strings for the
318 // given arguments with fmt.Sprint(). Useful to put into or mix into other
319 // string. Windows users should use this in conjunction with color.Output, example:
321 // put := New(FgYellow).SprintFunc()
322 // fmt.Fprintf(color.Output, "This is a %s", put("warning"))
323 func (c *Color) SprintFunc() func(a ...interface{}) string {
324 return func(a ...interface{}) string {
325 return c.wrap(fmt.Sprint(a...))
329 // SprintfFunc returns a new function that returns colorized strings for the
330 // given arguments with fmt.Sprintf(). Useful to put into or mix into other
331 // string. Windows users should use this in conjunction with color.Output.
332 func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
333 return func(format string, a ...interface{}) string {
334 return c.wrap(fmt.Sprintf(format, a...))
338 // SprintlnFunc returns a new function that returns colorized strings for the
339 // given arguments with fmt.Sprintln(). Useful to put into or mix into other
340 // string. Windows users should use this in conjunction with color.Output.
341 func (c *Color) SprintlnFunc() func(a ...interface{}) string {
342 return func(a ...interface{}) string {
343 return c.wrap(fmt.Sprintln(a...))
347 // sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m"
348 // an example output might be: "1;36" -> bold cyan
349 func (c *Color) sequence() string {
350 format := make([]string, len(c.params))
351 for i, v := range c.params {
352 format[i] = strconv.Itoa(int(v))
355 return strings.Join(format, ";")
358 // wrap wraps the s string with the colors attributes. The string is ready to
360 func (c *Color) wrap(s string) string {
361 if c.isNoColorSet() {
365 return c.format() + s + c.unformat()
368 func (c *Color) format() string {
369 return fmt.Sprintf("%s[%sm", escape, c.sequence())
372 func (c *Color) unformat() string {
373 return fmt.Sprintf("%s[%dm", escape, Reset)
376 // DisableColor disables the color output. Useful to not change any existing
377 // code and still being able to output. Can be used for flags like
378 // "--no-color". To enable back use EnableColor() method.
379 func (c *Color) DisableColor() {
380 c.noColor = boolPtr(true)
383 // EnableColor enables the color output. Use it in conjunction with
384 // DisableColor(). Otherwise this method has no side effects.
385 func (c *Color) EnableColor() {
386 c.noColor = boolPtr(false)
389 func (c *Color) isNoColorSet() bool {
390 // check first if we have user setted action
391 if c.noColor != nil {
395 // if not return the global option, which is disabled by default
399 // Equals returns a boolean value indicating whether two colors are equal.
400 func (c *Color) Equals(c2 *Color) bool {
401 if len(c.params) != len(c2.params) {
405 for _, attr := range c.params {
406 if !c2.attrExists(attr) {
414 func (c *Color) attrExists(a Attribute) bool {
415 for _, attr := range c.params {
424 func boolPtr(v bool) *bool {
428 func getCachedColor(p Attribute) *Color {
430 defer colorsCacheMu.Unlock()
432 c, ok := colorsCache[p]
441 func colorPrint(format string, p Attribute, a ...interface{}) {
442 c := getCachedColor(p)
444 if !strings.HasSuffix(format, "\n") {
451 c.Printf(format, a...)
455 func colorString(format string, p Attribute, a ...interface{}) string {
456 c := getCachedColor(p)
459 return c.SprintFunc()(format)
462 return c.SprintfFunc()(format, a...)
465 // Black is a convenient helper function to print with black foreground. A
466 // newline is appended to format by default.
467 func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }
469 // Red is a convenient helper function to print with red foreground. A
470 // newline is appended to format by default.
471 func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }
473 // Green is a convenient helper function to print with green foreground. A
474 // newline is appended to format by default.
475 func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }
477 // Yellow is a convenient helper function to print with yellow foreground.
478 // A newline is appended to format by default.
479 func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }
481 // Blue is a convenient helper function to print with blue foreground. A
482 // newline is appended to format by default.
483 func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }
485 // Magenta is a convenient helper function to print with magenta foreground.
486 // A newline is appended to format by default.
487 func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }
489 // Cyan is a convenient helper function to print with cyan foreground. A
490 // newline is appended to format by default.
491 func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }
493 // White is a convenient helper function to print with white foreground. A
494 // newline is appended to format by default.
495 func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }
497 // BlackString is a convenient helper function to return a string with black
499 func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }
501 // RedString is a convenient helper function to return a string with red
503 func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }
505 // GreenString is a convenient helper function to return a string with green
507 func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }
509 // YellowString is a convenient helper function to return a string with yellow
511 func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }
513 // BlueString is a convenient helper function to return a string with blue
515 func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }
517 // MagentaString is a convenient helper function to return a string with magenta
519 func MagentaString(format string, a ...interface{}) string {
520 return colorString(format, FgMagenta, a...)
523 // CyanString is a convenient helper function to return a string with cyan
525 func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }
527 // WhiteString is a convenient helper function to return a string with white
529 func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }
531 // HiBlack is a convenient helper function to print with hi-intensity black foreground. A
532 // newline is appended to format by default.
533 func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) }
535 // HiRed is a convenient helper function to print with hi-intensity red foreground. A
536 // newline is appended to format by default.
537 func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) }
539 // HiGreen is a convenient helper function to print with hi-intensity green foreground. A
540 // newline is appended to format by default.
541 func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) }
543 // HiYellow is a convenient helper function to print with hi-intensity yellow foreground.
544 // A newline is appended to format by default.
545 func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) }
547 // HiBlue is a convenient helper function to print with hi-intensity blue foreground. A
548 // newline is appended to format by default.
549 func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) }
551 // HiMagenta is a convenient helper function to print with hi-intensity magenta foreground.
552 // A newline is appended to format by default.
553 func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) }
555 // HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A
556 // newline is appended to format by default.
557 func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) }
559 // HiWhite is a convenient helper function to print with hi-intensity white foreground. A
560 // newline is appended to format by default.
561 func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) }
563 // HiBlackString is a convenient helper function to return a string with hi-intensity black
565 func HiBlackString(format string, a ...interface{}) string {
566 return colorString(format, FgHiBlack, a...)
569 // HiRedString is a convenient helper function to return a string with hi-intensity red
571 func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) }
573 // HiGreenString is a convenient helper function to return a string with hi-intensity green
575 func HiGreenString(format string, a ...interface{}) string {
576 return colorString(format, FgHiGreen, a...)
579 // HiYellowString is a convenient helper function to return a string with hi-intensity yellow
581 func HiYellowString(format string, a ...interface{}) string {
582 return colorString(format, FgHiYellow, a...)
585 // HiBlueString is a convenient helper function to return a string with hi-intensity blue
587 func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) }
589 // HiMagentaString is a convenient helper function to return a string with hi-intensity magenta
591 func HiMagentaString(format string, a ...interface{}) string {
592 return colorString(format, FgHiMagenta, a...)
595 // HiCyanString is a convenient helper function to return a string with hi-intensity cyan
597 func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) }
599 // HiWhiteString is a convenient helper function to return a string with hi-intensity white
601 func HiWhiteString(format string, a ...interface{}) string {
602 return colorString(format, FgHiWhite, a...)