color.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. BrightBlack Color = ansiBrightColor(0)
  24. BrightRed Color = ansiBrightColor(1)
  25. BrightGreen Color = ansiBrightColor(2)
  26. BrightYellow Color = ansiBrightColor(3)
  27. BrightBlue Color = ansiBrightColor(4)
  28. BrightMagenta Color = ansiBrightColor(5)
  29. BrightCyan Color = ansiBrightColor(6)
  30. BrightWhite Color = ansiBrightColor(7)
  31. )
  32. // XTerm256Color returns a color from the xterm 256-color palette.
  33. func XTerm256Color(i uint8) Color { return xterm256Color(i) }
  34. // TrueColor returns a 24-bit true color.
  35. func TrueColor(r, g, b uint8) Color { return trueColor{r, g, b} }
  36. var colorNames = []string{
  37. "black", "red", "green", "yellow",
  38. "blue", "magenta", "cyan", "white",
  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. "bright-black": BrightBlack,
  50. "bright-red": BrightRed,
  51. "bright-green": BrightGreen,
  52. "bright-yellow": BrightYellow,
  53. "bright-blue": BrightBlue,
  54. "bright-magenta": BrightMagenta,
  55. "bright-cyan": BrightCyan,
  56. "bright-white": BrightWhite,
  57. }
  58. type ansiColor uint8
  59. func (c ansiColor) fgSGR() string { return strconv.Itoa(30 + int(c)) }
  60. func (c ansiColor) bgSGR() string { return strconv.Itoa(40 + int(c)) }
  61. func (c ansiColor) String() string { return colorNames[c] }
  62. type ansiBrightColor uint8
  63. func (c ansiBrightColor) fgSGR() string { return strconv.Itoa(90 + int(c)) }
  64. func (c ansiBrightColor) bgSGR() string { return strconv.Itoa(100 + int(c)) }
  65. func (c ansiBrightColor) String() string { return "bright-" + colorNames[c] }
  66. type xterm256Color uint8
  67. func (c xterm256Color) fgSGR() string { return "38;5;" + strconv.Itoa(int(c)) }
  68. func (c xterm256Color) bgSGR() string { return "48;5;" + strconv.Itoa(int(c)) }
  69. func (c xterm256Color) String() string { return "color" + strconv.Itoa(int(c)) }
  70. type trueColor struct{ R, G, B uint8 }
  71. func (c trueColor) fgSGR() string { return "38;2;" + c.rgbSGR() }
  72. func (c trueColor) bgSGR() string { return "48;2;" + c.rgbSGR() }
  73. func (c trueColor) String() string {
  74. return fmt.Sprintf("#%02x%02x%02x", c.R, c.G, c.B)
  75. }
  76. func (c trueColor) rgbSGR() string {
  77. return fmt.Sprintf("%d;%d;%d", c.R, c.G, c.B)
  78. }
  79. func parseColor(name string) Color {
  80. if color, ok := colorByName[name]; ok {
  81. return color
  82. }
  83. if strings.HasPrefix(name, "color") {
  84. i, err := strconv.Atoi(name[5:])
  85. if err == nil && 0 <= i && i < 256 {
  86. return XTerm256Color(uint8(i))
  87. }
  88. } else if strings.HasPrefix(name, "#") && len(name) == 7 {
  89. r, rErr := strconv.ParseUint(name[1:3], 16, 8)
  90. g, gErr := strconv.ParseUint(name[3:5], 16, 8)
  91. b, bErr := strconv.ParseUint(name[5:7], 16, 8)
  92. if rErr == nil && gErr == nil && bErr == nil {
  93. return TrueColor(uint8(r), uint8(g), uint8(b))
  94. }
  95. }
  96. return nil
  97. }