color.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package ui
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. // Color represents a color.
  8. type Color interface {
  9. fgSGR() string
  10. bgSGR() string
  11. String() string
  12. }
  13. // Builtin ANSI colors.
  14. var (
  15. Black Color = ansiColor(0)
  16. Red Color = ansiColor(1)
  17. Green Color = ansiColor(2)
  18. Yellow Color = ansiColor(3)
  19. Blue Color = ansiColor(4)
  20. Magenta Color = ansiColor(5)
  21. Cyan Color = ansiColor(6)
  22. White Color = ansiColor(7)
  23. Default Color = ansiColor(9)
  24. BrightBlack Color = ansiBrightColor(0)
  25. BrightRed Color = ansiBrightColor(1)
  26. BrightGreen Color = ansiBrightColor(2)
  27. BrightYellow Color = ansiBrightColor(3)
  28. BrightBlue Color = ansiBrightColor(4)
  29. BrightMagenta Color = ansiBrightColor(5)
  30. BrightCyan Color = ansiBrightColor(6)
  31. BrightWhite Color = ansiBrightColor(7)
  32. )
  33. // XTerm256Color returns a color from the xterm 256-color palette.
  34. func XTerm256Color(i uint8) Color { return xterm256Color(i) }
  35. // TrueColor returns a 24-bit true color.
  36. func TrueColor(r, g, b uint8) Color { return trueColor{r, g, b} }
  37. var colorNames = []string{
  38. "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "unknown", "default",
  39. }
  40. var colorByName = map[string]Color{
  41. "black": Black,
  42. "red": Red,
  43. "green": Green,
  44. "yellow": Yellow,
  45. "blue": Blue,
  46. "magenta": Magenta,
  47. "cyan": Cyan,
  48. "white": White,
  49. "default": Default,
  50. "bright-black": BrightBlack,
  51. "bright-red": BrightRed,
  52. "bright-green": BrightGreen,
  53. "bright-yellow": BrightYellow,
  54. "bright-blue": BrightBlue,
  55. "bright-magenta": BrightMagenta,
  56. "bright-cyan": BrightCyan,
  57. "bright-white": BrightWhite,
  58. }
  59. type ansiColor uint8
  60. func (c ansiColor) fgSGR() string { return strconv.Itoa(30 + int(c)) }
  61. func (c ansiColor) bgSGR() string { return strconv.Itoa(40 + int(c)) }
  62. func (c ansiColor) String() string { return colorNames[c] }
  63. type ansiBrightColor uint8
  64. func (c ansiBrightColor) fgSGR() string { return strconv.Itoa(90 + int(c)) }
  65. func (c ansiBrightColor) bgSGR() string { return strconv.Itoa(100 + int(c)) }
  66. func (c ansiBrightColor) String() string { return "bright-" + colorNames[c] }
  67. type xterm256Color uint8
  68. func (c xterm256Color) fgSGR() string { return "38;5;" + strconv.Itoa(int(c)) }
  69. func (c xterm256Color) bgSGR() string { return "48;5;" + strconv.Itoa(int(c)) }
  70. func (c xterm256Color) String() string { return "color" + strconv.Itoa(int(c)) }
  71. type trueColor struct{ R, G, B uint8 }
  72. func (c trueColor) fgSGR() string { return "38;2;" + c.rgbSGR() }
  73. func (c trueColor) bgSGR() string { return "48;2;" + c.rgbSGR() }
  74. func (c trueColor) String() string {
  75. return fmt.Sprintf("#%02x%02x%02x", c.R, c.G, c.B)
  76. }
  77. func (c trueColor) rgbSGR() string {
  78. return fmt.Sprintf("%d;%d;%d", c.R, c.G, c.B)
  79. }
  80. func parseColor(name string) Color {
  81. if color, ok := colorByName[name]; ok {
  82. return color
  83. }
  84. if strings.HasPrefix(name, "color") {
  85. i, err := strconv.Atoi(name[5:])
  86. if err == nil && 0 <= i && i < 256 {
  87. return XTerm256Color(uint8(i))
  88. }
  89. } else if strings.HasPrefix(name, "#") && len(name) == 7 {
  90. r, rErr := strconv.ParseUint(name[1:3], 16, 8)
  91. g, gErr := strconv.ParseUint(name[3:5], 16, 8)
  92. b, bErr := strconv.ParseUint(name[5:7], 16, 8)
  93. if rErr == nil && gErr == nil && bErr == nil {
  94. return TrueColor(uint8(r), uint8(g), uint8(b))
  95. }
  96. }
  97. return nil
  98. }