ansi.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package ansi
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. )
  8. const (
  9. black = iota
  10. red
  11. green
  12. yellow
  13. blue
  14. magenta
  15. cyan
  16. white
  17. defaultt = 9
  18. normalIntensityFG = 30
  19. highIntensityFG = 90
  20. normalIntensityBG = 40
  21. highIntensityBG = 100
  22. start = "\033["
  23. bold = "1;"
  24. blink = "5;"
  25. underline = "4;"
  26. inverse = "7;"
  27. strikethrough = "9;"
  28. // Reset is the ANSI reset escape sequence
  29. Reset = "\033[0m"
  30. // DefaultBG is the default background
  31. DefaultBG = "\033[49m"
  32. // DefaultFG is the default foreground
  33. DefaultFG = "\033[39m"
  34. )
  35. // Black FG
  36. var Black string
  37. // Red FG
  38. var Red string
  39. // Green FG
  40. var Green string
  41. // Yellow FG
  42. var Yellow string
  43. // Blue FG
  44. var Blue string
  45. // Magenta FG
  46. var Magenta string
  47. // Cyan FG
  48. var Cyan string
  49. // White FG
  50. var White string
  51. // LightBlack FG
  52. var LightBlack string
  53. // LightRed FG
  54. var LightRed string
  55. // LightGreen FG
  56. var LightGreen string
  57. // LightYellow FG
  58. var LightYellow string
  59. // LightBlue FG
  60. var LightBlue string
  61. // LightMagenta FG
  62. var LightMagenta string
  63. // LightCyan FG
  64. var LightCyan string
  65. // LightWhite FG
  66. var LightWhite string
  67. var (
  68. plain = false
  69. // Colors maps common color names to their ANSI color code.
  70. Colors = map[string]int{
  71. "black": black,
  72. "red": red,
  73. "green": green,
  74. "yellow": yellow,
  75. "blue": blue,
  76. "magenta": magenta,
  77. "cyan": cyan,
  78. "white": white,
  79. "default": defaultt,
  80. }
  81. )
  82. func init() {
  83. for i := 0; i < 256; i++ {
  84. Colors[strconv.Itoa(i)] = i
  85. }
  86. Black = ColorCode("black")
  87. Red = ColorCode("red")
  88. Green = ColorCode("green")
  89. Yellow = ColorCode("yellow")
  90. Blue = ColorCode("blue")
  91. Magenta = ColorCode("magenta")
  92. Cyan = ColorCode("cyan")
  93. White = ColorCode("white")
  94. LightBlack = ColorCode("black+h")
  95. LightRed = ColorCode("red+h")
  96. LightGreen = ColorCode("green+h")
  97. LightYellow = ColorCode("yellow+h")
  98. LightBlue = ColorCode("blue+h")
  99. LightMagenta = ColorCode("magenta+h")
  100. LightCyan = ColorCode("cyan+h")
  101. LightWhite = ColorCode("white+h")
  102. }
  103. // ColorCode returns the ANSI color color code for style.
  104. func ColorCode(style string) string {
  105. return colorCode(style).String()
  106. }
  107. // Gets the ANSI color code for a style.
  108. func colorCode(style string) *bytes.Buffer {
  109. buf := bytes.NewBufferString("")
  110. if plain || style == "" {
  111. return buf
  112. }
  113. if style == "reset" {
  114. buf.WriteString(Reset)
  115. return buf
  116. } else if style == "off" {
  117. return buf
  118. }
  119. foregroundBackground := strings.Split(style, ":")
  120. foreground := strings.Split(foregroundBackground[0], "+")
  121. fgKey := foreground[0]
  122. fg := Colors[fgKey]
  123. fgStyle := ""
  124. if len(foreground) > 1 {
  125. fgStyle = foreground[1]
  126. }
  127. bg, bgStyle := "", ""
  128. if len(foregroundBackground) > 1 {
  129. background := strings.Split(foregroundBackground[1], "+")
  130. bg = background[0]
  131. if len(background) > 1 {
  132. bgStyle = background[1]
  133. }
  134. }
  135. buf.WriteString(start)
  136. base := normalIntensityFG
  137. if len(fgStyle) > 0 {
  138. if strings.Contains(fgStyle, "b") {
  139. buf.WriteString(bold)
  140. }
  141. if strings.Contains(fgStyle, "B") {
  142. buf.WriteString(blink)
  143. }
  144. if strings.Contains(fgStyle, "u") {
  145. buf.WriteString(underline)
  146. }
  147. if strings.Contains(fgStyle, "i") {
  148. buf.WriteString(inverse)
  149. }
  150. if strings.Contains(fgStyle, "s") {
  151. buf.WriteString(strikethrough)
  152. }
  153. if strings.Contains(fgStyle, "h") {
  154. base = highIntensityFG
  155. }
  156. }
  157. // if 256-color
  158. n, err := strconv.Atoi(fgKey)
  159. if err == nil {
  160. fmt.Fprintf(buf, "38;5;%d;", n)
  161. } else {
  162. fmt.Fprintf(buf, "%d;", base+fg)
  163. }
  164. base = normalIntensityBG
  165. if len(bg) > 0 {
  166. if strings.Contains(bgStyle, "h") {
  167. base = highIntensityBG
  168. }
  169. // if 256-color
  170. n, err := strconv.Atoi(bg)
  171. if err == nil {
  172. fmt.Fprintf(buf, "48;5;%d;", n)
  173. } else {
  174. fmt.Fprintf(buf, "%d;", base+Colors[bg])
  175. }
  176. }
  177. // remove last ";"
  178. buf.Truncate(buf.Len() - 1)
  179. buf.WriteRune('m')
  180. return buf
  181. }
  182. // Color colors a string based on the ANSI color code for style.
  183. func Color(s, style string) string {
  184. if plain || len(style) < 1 {
  185. return s
  186. }
  187. buf := colorCode(style)
  188. buf.WriteString(s)
  189. buf.WriteString(Reset)
  190. return buf.String()
  191. }
  192. // ColorFunc creates a closure to avoid computation ANSI color code.
  193. func ColorFunc(style string) func(string) string {
  194. if style == "" {
  195. return func(s string) string {
  196. return s
  197. }
  198. }
  199. color := ColorCode(style)
  200. return func(s string) string {
  201. if plain || s == "" {
  202. return s
  203. }
  204. buf := bytes.NewBufferString(color)
  205. buf.WriteString(s)
  206. buf.WriteString(Reset)
  207. result := buf.String()
  208. return result
  209. }
  210. }
  211. // DisableColors disables ANSI color codes. The default is false (colors are on).
  212. func DisableColors(disable bool) {
  213. plain = disable
  214. if plain {
  215. Black = ""
  216. Red = ""
  217. Green = ""
  218. Yellow = ""
  219. Blue = ""
  220. Magenta = ""
  221. Cyan = ""
  222. White = ""
  223. LightBlack = ""
  224. LightRed = ""
  225. LightGreen = ""
  226. LightYellow = ""
  227. LightBlue = ""
  228. LightMagenta = ""
  229. LightCyan = ""
  230. LightWhite = ""
  231. } else {
  232. Black = ColorCode("black")
  233. Red = ColorCode("red")
  234. Green = ColorCode("green")
  235. Yellow = ColorCode("yellow")
  236. Blue = ColorCode("blue")
  237. Magenta = ColorCode("magenta")
  238. Cyan = ColorCode("cyan")
  239. White = ColorCode("white")
  240. LightBlack = ColorCode("black+h")
  241. LightRed = ColorCode("red+h")
  242. LightGreen = ColorCode("green+h")
  243. LightYellow = ColorCode("yellow+h")
  244. LightBlue = ColorCode("blue+h")
  245. LightMagenta = ColorCode("magenta+h")
  246. LightCyan = ColorCode("cyan+h")
  247. LightWhite = ColorCode("white+h")
  248. }
  249. }