github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/pkg/iostreams/color.go (about)

     1  package iostreams
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/mgutz/ansi"
    10  )
    11  
    12  var (
    13  	magenta  = ansi.ColorFunc("magenta")
    14  	cyan     = ansi.ColorFunc("cyan")
    15  	red      = ansi.ColorFunc("red")
    16  	yellow   = ansi.ColorFunc("yellow")
    17  	blue     = ansi.ColorFunc("blue")
    18  	green    = ansi.ColorFunc("green")
    19  	gray     = ansi.ColorFunc("black+h")
    20  	bold     = ansi.ColorFunc("default+b")
    21  	cyanBold = ansi.ColorFunc("cyan+b")
    22  
    23  	gray256 = func(t string) string {
    24  		return fmt.Sprintf("\x1b[%d;5;%dm%s\x1b[m", 38, 242, t)
    25  	}
    26  )
    27  
    28  func EnvColorDisabled() bool {
    29  	return os.Getenv("NO_COLOR") != "" || os.Getenv("CLICOLOR") == "0"
    30  }
    31  
    32  func EnvColorForced() bool {
    33  	return os.Getenv("CLICOLOR_FORCE") != "" && os.Getenv("CLICOLOR_FORCE") != "0"
    34  }
    35  
    36  func Is256ColorSupported() bool {
    37  	return IsTrueColorSupported() ||
    38  		strings.Contains(os.Getenv("TERM"), "256") ||
    39  		strings.Contains(os.Getenv("COLORTERM"), "256")
    40  }
    41  
    42  func IsTrueColorSupported() bool {
    43  	term := os.Getenv("TERM")
    44  	colorterm := os.Getenv("COLORTERM")
    45  
    46  	return strings.Contains(term, "24bit") ||
    47  		strings.Contains(term, "truecolor") ||
    48  		strings.Contains(colorterm, "24bit") ||
    49  		strings.Contains(colorterm, "truecolor")
    50  }
    51  
    52  func NewColorScheme(enabled, is256enabled bool, trueColor bool) *ColorScheme {
    53  	return &ColorScheme{
    54  		enabled:      enabled,
    55  		is256enabled: is256enabled,
    56  		hasTrueColor: trueColor,
    57  	}
    58  }
    59  
    60  type ColorScheme struct {
    61  	enabled      bool
    62  	is256enabled bool
    63  	hasTrueColor bool
    64  }
    65  
    66  func (c *ColorScheme) Bold(t string) string {
    67  	if !c.enabled {
    68  		return t
    69  	}
    70  	return bold(t)
    71  }
    72  
    73  func (c *ColorScheme) Boldf(t string, args ...interface{}) string {
    74  	return c.Bold(fmt.Sprintf(t, args...))
    75  }
    76  
    77  func (c *ColorScheme) Red(t string) string {
    78  	if !c.enabled {
    79  		return t
    80  	}
    81  	return red(t)
    82  }
    83  
    84  func (c *ColorScheme) Redf(t string, args ...interface{}) string {
    85  	return c.Red(fmt.Sprintf(t, args...))
    86  }
    87  
    88  func (c *ColorScheme) Yellow(t string) string {
    89  	if !c.enabled {
    90  		return t
    91  	}
    92  	return yellow(t)
    93  }
    94  
    95  func (c *ColorScheme) Yellowf(t string, args ...interface{}) string {
    96  	return c.Yellow(fmt.Sprintf(t, args...))
    97  }
    98  
    99  func (c *ColorScheme) Green(t string) string {
   100  	if !c.enabled {
   101  		return t
   102  	}
   103  	return green(t)
   104  }
   105  
   106  func (c *ColorScheme) Greenf(t string, args ...interface{}) string {
   107  	return c.Green(fmt.Sprintf(t, args...))
   108  }
   109  
   110  func (c *ColorScheme) Gray(t string) string {
   111  	if !c.enabled {
   112  		return t
   113  	}
   114  	if c.is256enabled {
   115  		return gray256(t)
   116  	}
   117  	return gray(t)
   118  }
   119  
   120  func (c *ColorScheme) Grayf(t string, args ...interface{}) string {
   121  	return c.Gray(fmt.Sprintf(t, args...))
   122  }
   123  
   124  func (c *ColorScheme) Magenta(t string) string {
   125  	if !c.enabled {
   126  		return t
   127  	}
   128  	return magenta(t)
   129  }
   130  
   131  func (c *ColorScheme) Magentaf(t string, args ...interface{}) string {
   132  	return c.Magenta(fmt.Sprintf(t, args...))
   133  }
   134  
   135  func (c *ColorScheme) Cyan(t string) string {
   136  	if !c.enabled {
   137  		return t
   138  	}
   139  	return cyan(t)
   140  }
   141  
   142  func (c *ColorScheme) Cyanf(t string, args ...interface{}) string {
   143  	return c.Cyan(fmt.Sprintf(t, args...))
   144  }
   145  
   146  func (c *ColorScheme) CyanBold(t string) string {
   147  	if !c.enabled {
   148  		return t
   149  	}
   150  	return cyanBold(t)
   151  }
   152  
   153  func (c *ColorScheme) Blue(t string) string {
   154  	if !c.enabled {
   155  		return t
   156  	}
   157  	return blue(t)
   158  }
   159  
   160  func (c *ColorScheme) Bluef(t string, args ...interface{}) string {
   161  	return c.Blue(fmt.Sprintf(t, args...))
   162  }
   163  
   164  func (c *ColorScheme) SuccessIcon() string {
   165  	return c.SuccessIconWithColor(c.Green)
   166  }
   167  
   168  func (c *ColorScheme) SuccessIconWithColor(colo func(string) string) string {
   169  	return colo("✓")
   170  }
   171  
   172  func (c *ColorScheme) WarningIcon() string {
   173  	return c.Yellow("!")
   174  }
   175  
   176  func (c *ColorScheme) FailureIcon() string {
   177  	return c.FailureIconWithColor(c.Red)
   178  }
   179  
   180  func (c *ColorScheme) FailureIconWithColor(colo func(string) string) string {
   181  	return colo("X")
   182  }
   183  
   184  func (c *ColorScheme) ColorFromString(s string) func(string) string {
   185  	s = strings.ToLower(s)
   186  	var fn func(string) string
   187  	switch s {
   188  	case "bold":
   189  		fn = c.Bold
   190  	case "red":
   191  		fn = c.Red
   192  	case "yellow":
   193  		fn = c.Yellow
   194  	case "green":
   195  		fn = c.Green
   196  	case "gray":
   197  		fn = c.Gray
   198  	case "magenta":
   199  		fn = c.Magenta
   200  	case "cyan":
   201  		fn = c.Cyan
   202  	case "blue":
   203  		fn = c.Blue
   204  	default:
   205  		fn = func(s string) string {
   206  			return s
   207  		}
   208  	}
   209  
   210  	return fn
   211  }
   212  
   213  func (c *ColorScheme) HexToRGB(hex string, x string) string {
   214  	if !c.enabled || !c.hasTrueColor {
   215  		return x
   216  	}
   217  
   218  	r, _ := strconv.ParseInt(hex[0:2], 16, 64)
   219  	g, _ := strconv.ParseInt(hex[2:4], 16, 64)
   220  	b, _ := strconv.ParseInt(hex[4:6], 16, 64)
   221  	return fmt.Sprintf("\033[38;2;%d;%d;%dm%s\033[0m", r, g, b, x)
   222  }