color.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package door
  2. import (
  3. "bytes"
  4. "log"
  5. "strconv"
  6. "strings"
  7. )
  8. // Profiling:
  9. // go build -gcflags=-m=2 . 2>&1 | less
  10. // What leaks to heap?
  11. // Possibly make this so it is part of an ANSI package.
  12. // DRY - Reuse.
  13. // Convert an array of int to \x1b[1;2;3m for ANSI Color
  14. // output.
  15. // https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
  16. // https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit
  17. /*
  18. func Color(arg ...int) string {
  19. var result string = "\x1b["
  20. for i := range arg {
  21. result += fmt.Sprintf("%d;", arg[i])
  22. }
  23. result = result[:len(result)-1]
  24. result += "m"
  25. return result
  26. }
  27. */
  28. func Color(arg []int) []byte {
  29. var result *bytes.Buffer = &bytes.Buffer{}
  30. result.WriteString("\x1b[")
  31. for idx, i := range arg {
  32. if idx != 0 {
  33. result.WriteString(";")
  34. }
  35. result.WriteString(strconv.Itoa(i))
  36. }
  37. result.WriteString("m")
  38. return result.Bytes()
  39. }
  40. func ColorS(arg []int) string {
  41. var result strings.Builder
  42. result.WriteString("\x1b[")
  43. for idx, i := range arg {
  44. if idx != 0 {
  45. result.WriteString(";")
  46. }
  47. result.WriteString(strconv.Itoa(i))
  48. }
  49. result.WriteString("m")
  50. return result.String()
  51. }
  52. // BUG(bugz) INVERSE does not work.
  53. // Would I want to do something like:
  54. // BRIGHT YELLOW or ON BLUE, and have it just change the
  55. // color or the background? Right now, I require the full
  56. // color (FG & BG).
  57. // Convert a string like "BRIGHT WHITE ON BLUE" into the expected
  58. // ANSI Color codes. You can use just the first 3 letters.
  59. // Supports BRIGHT, BOLD, BLINK and ON (to set the background color).
  60. // BLACK, RED, GREEN, BROWN / YELLOW, BLUE, MAGENTA, CYAN, WHITE
  61. // https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
  62. // https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit
  63. func ColorText(color string) []byte {
  64. // split on spaces, uppercase, match first 3 letter
  65. var res [5]int
  66. var result []int = res[0:0]
  67. var bg bool
  68. result = append(result, 0)
  69. parts := strings.Fields(strings.ToUpper(color))
  70. for _, part := range parts {
  71. if len(part) > 3 {
  72. part = part[:3]
  73. }
  74. switch part {
  75. case "BLA":
  76. if bg {
  77. result = append(result, 40)
  78. } else {
  79. result = append(result, 30)
  80. }
  81. case "RED":
  82. if bg {
  83. result = append(result, 41)
  84. } else {
  85. result = append(result, 31)
  86. }
  87. case "GRE":
  88. if bg {
  89. result = append(result, 42)
  90. } else {
  91. result = append(result, 32)
  92. }
  93. case "BRO", "YEL":
  94. if bg {
  95. result = append(result, 43)
  96. } else {
  97. result = append(result, 33)
  98. }
  99. case "BLU":
  100. if bg {
  101. result = append(result, 44)
  102. } else {
  103. result = append(result, 34)
  104. }
  105. case "MAG":
  106. if bg {
  107. result = append(result, 45)
  108. } else {
  109. result = append(result, 35)
  110. }
  111. case "CYA":
  112. if bg {
  113. result = append(result, 46)
  114. } else {
  115. result = append(result, 36)
  116. }
  117. case "WHI":
  118. if bg {
  119. result = append(result, 47)
  120. } else {
  121. result = append(result, 37)
  122. }
  123. case "BOL", "BRI":
  124. result = append(result, 1)
  125. case "ON":
  126. bg = true
  127. case "BLI":
  128. result = append(result, 5)
  129. // Invert is't well supported in terminals
  130. // case "INV":
  131. // result = append(result, 7)
  132. default:
  133. log.Panicf("ColorText Unknown: [%s] in %s\n", part, color)
  134. }
  135. }
  136. return Color(result)
  137. }
  138. func ColorTextS(color string) string {
  139. // split on spaces, uppercase, match first 3 letter
  140. var res [5]int
  141. var result []int = res[0:0]
  142. var bg bool
  143. result = append(result, 0)
  144. parts := strings.Fields(strings.ToUpper(color))
  145. for _, part := range parts {
  146. if len(part) > 3 {
  147. part = part[:3]
  148. }
  149. switch part {
  150. case "BLA":
  151. if bg {
  152. result = append(result, 40)
  153. } else {
  154. result = append(result, 30)
  155. }
  156. case "RED":
  157. if bg {
  158. result = append(result, 41)
  159. } else {
  160. result = append(result, 31)
  161. }
  162. case "GRE":
  163. if bg {
  164. result = append(result, 42)
  165. } else {
  166. result = append(result, 32)
  167. }
  168. case "BRO", "YEL":
  169. if bg {
  170. result = append(result, 43)
  171. } else {
  172. result = append(result, 33)
  173. }
  174. case "BLU":
  175. if bg {
  176. result = append(result, 44)
  177. } else {
  178. result = append(result, 34)
  179. }
  180. case "MAG":
  181. if bg {
  182. result = append(result, 45)
  183. } else {
  184. result = append(result, 35)
  185. }
  186. case "CYA":
  187. if bg {
  188. result = append(result, 46)
  189. } else {
  190. result = append(result, 36)
  191. }
  192. case "WHI":
  193. if bg {
  194. result = append(result, 47)
  195. } else {
  196. result = append(result, 37)
  197. }
  198. case "BOL", "BRI":
  199. result = append(result, 1)
  200. case "ON":
  201. bg = true
  202. case "BLI":
  203. result = append(result, 5)
  204. // Invert is't well supported in terminals
  205. // case "INV":
  206. // result = append(result, 7)
  207. default:
  208. log.Panicf("ColorText Unknown: [%s] in %s\n", part, color)
  209. }
  210. }
  211. return ColorS(result)
  212. }