color.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. package color
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. "github.com/mattn/go-colorable"
  8. "github.com/mattn/go-isatty"
  9. )
  10. type (
  11. inner func(interface{}, []string, *Color) string
  12. )
  13. // Color styles
  14. const (
  15. // Blk Black text style
  16. Blk = "30"
  17. // Rd red text style
  18. Rd = "31"
  19. // Grn green text style
  20. Grn = "32"
  21. // Yel yellow text style
  22. Yel = "33"
  23. // Blu blue text style
  24. Blu = "34"
  25. // Mgn magenta text style
  26. Mgn = "35"
  27. // Cyn cyan text style
  28. Cyn = "36"
  29. // Wht white text style
  30. Wht = "37"
  31. // Gry grey text style
  32. Gry = "90"
  33. // BlkBg black background style
  34. BlkBg = "40"
  35. // RdBg red background style
  36. RdBg = "41"
  37. // GrnBg green background style
  38. GrnBg = "42"
  39. // YelBg yellow background style
  40. YelBg = "43"
  41. // BluBg blue background style
  42. BluBg = "44"
  43. // MgnBg magenta background style
  44. MgnBg = "45"
  45. // CynBg cyan background style
  46. CynBg = "46"
  47. // WhtBg white background style
  48. WhtBg = "47"
  49. // R reset emphasis style
  50. R = "0"
  51. // B bold emphasis style
  52. B = "1"
  53. // D dim emphasis style
  54. D = "2"
  55. // I italic emphasis style
  56. I = "3"
  57. // U underline emphasis style
  58. U = "4"
  59. // In inverse emphasis style
  60. In = "7"
  61. // H hidden emphasis style
  62. H = "8"
  63. // S strikeout emphasis style
  64. S = "9"
  65. )
  66. var (
  67. black = outer(Blk)
  68. red = outer(Rd)
  69. green = outer(Grn)
  70. yellow = outer(Yel)
  71. blue = outer(Blu)
  72. magenta = outer(Mgn)
  73. cyan = outer(Cyn)
  74. white = outer(Wht)
  75. grey = outer(Gry)
  76. blackBg = outer(BlkBg)
  77. redBg = outer(RdBg)
  78. greenBg = outer(GrnBg)
  79. yellowBg = outer(YelBg)
  80. blueBg = outer(BluBg)
  81. magentaBg = outer(MgnBg)
  82. cyanBg = outer(CynBg)
  83. whiteBg = outer(WhtBg)
  84. reset = outer(R)
  85. bold = outer(B)
  86. dim = outer(D)
  87. italic = outer(I)
  88. underline = outer(U)
  89. inverse = outer(In)
  90. hidden = outer(H)
  91. strikeout = outer(S)
  92. global = New()
  93. )
  94. func outer(n string) inner {
  95. return func(msg interface{}, styles []string, c *Color) string {
  96. // TODO: Drop fmt to boost performance?
  97. if c.disabled {
  98. return fmt.Sprintf("%v", msg)
  99. }
  100. b := new(bytes.Buffer)
  101. b.WriteString("\x1b[")
  102. b.WriteString(n)
  103. for _, s := range styles {
  104. b.WriteString(";")
  105. b.WriteString(s)
  106. }
  107. b.WriteString("m")
  108. return fmt.Sprintf("%s%v\x1b[0m", b.String(), msg)
  109. }
  110. }
  111. type (
  112. Color struct {
  113. output io.Writer
  114. disabled bool
  115. }
  116. )
  117. // New creates a Color instance.
  118. func New() (c *Color) {
  119. c = new(Color)
  120. c.SetOutput(colorable.NewColorableStdout())
  121. return
  122. }
  123. // Output returns the output.
  124. func (c *Color) Output() io.Writer {
  125. return c.output
  126. }
  127. // SetOutput sets the output.
  128. func (c *Color) SetOutput(w io.Writer) {
  129. c.output = w
  130. if w, ok := w.(*os.File); !ok || !isatty.IsTerminal(w.Fd()) {
  131. c.disabled = true
  132. }
  133. }
  134. // Disable disables the colors and styles.
  135. func (c *Color) Disable() {
  136. c.disabled = true
  137. }
  138. // Enable enables the colors and styles.
  139. func (c *Color) Enable() {
  140. c.disabled = false
  141. }
  142. // Print is analogous to `fmt.Print` with termial detection.
  143. func (c *Color) Print(args ...interface{}) {
  144. fmt.Fprint(c.output, args...)
  145. }
  146. // Println is analogous to `fmt.Println` with termial detection.
  147. func (c *Color) Println(args ...interface{}) {
  148. fmt.Fprintln(c.output, args...)
  149. }
  150. // Printf is analogous to `fmt.Printf` with termial detection.
  151. func (c *Color) Printf(format string, args ...interface{}) {
  152. fmt.Fprintf(c.output, format, args...)
  153. }
  154. func (c *Color) Black(msg interface{}, styles ...string) string {
  155. return black(msg, styles, c)
  156. }
  157. func (c *Color) Red(msg interface{}, styles ...string) string {
  158. return red(msg, styles, c)
  159. }
  160. func (c *Color) Green(msg interface{}, styles ...string) string {
  161. return green(msg, styles, c)
  162. }
  163. func (c *Color) Yellow(msg interface{}, styles ...string) string {
  164. return yellow(msg, styles, c)
  165. }
  166. func (c *Color) Blue(msg interface{}, styles ...string) string {
  167. return blue(msg, styles, c)
  168. }
  169. func (c *Color) Magenta(msg interface{}, styles ...string) string {
  170. return magenta(msg, styles, c)
  171. }
  172. func (c *Color) Cyan(msg interface{}, styles ...string) string {
  173. return cyan(msg, styles, c)
  174. }
  175. func (c *Color) White(msg interface{}, styles ...string) string {
  176. return white(msg, styles, c)
  177. }
  178. func (c *Color) Grey(msg interface{}, styles ...string) string {
  179. return grey(msg, styles, c)
  180. }
  181. func (c *Color) BlackBg(msg interface{}, styles ...string) string {
  182. return blackBg(msg, styles, c)
  183. }
  184. func (c *Color) RedBg(msg interface{}, styles ...string) string {
  185. return redBg(msg, styles, c)
  186. }
  187. func (c *Color) GreenBg(msg interface{}, styles ...string) string {
  188. return greenBg(msg, styles, c)
  189. }
  190. func (c *Color) YellowBg(msg interface{}, styles ...string) string {
  191. return yellowBg(msg, styles, c)
  192. }
  193. func (c *Color) BlueBg(msg interface{}, styles ...string) string {
  194. return blueBg(msg, styles, c)
  195. }
  196. func (c *Color) MagentaBg(msg interface{}, styles ...string) string {
  197. return magentaBg(msg, styles, c)
  198. }
  199. func (c *Color) CyanBg(msg interface{}, styles ...string) string {
  200. return cyanBg(msg, styles, c)
  201. }
  202. func (c *Color) WhiteBg(msg interface{}, styles ...string) string {
  203. return whiteBg(msg, styles, c)
  204. }
  205. func (c *Color) Reset(msg interface{}, styles ...string) string {
  206. return reset(msg, styles, c)
  207. }
  208. func (c *Color) Bold(msg interface{}, styles ...string) string {
  209. return bold(msg, styles, c)
  210. }
  211. func (c *Color) Dim(msg interface{}, styles ...string) string {
  212. return dim(msg, styles, c)
  213. }
  214. func (c *Color) Italic(msg interface{}, styles ...string) string {
  215. return italic(msg, styles, c)
  216. }
  217. func (c *Color) Underline(msg interface{}, styles ...string) string {
  218. return underline(msg, styles, c)
  219. }
  220. func (c *Color) Inverse(msg interface{}, styles ...string) string {
  221. return inverse(msg, styles, c)
  222. }
  223. func (c *Color) Hidden(msg interface{}, styles ...string) string {
  224. return hidden(msg, styles, c)
  225. }
  226. func (c *Color) Strikeout(msg interface{}, styles ...string) string {
  227. return strikeout(msg, styles, c)
  228. }
  229. // Output returns the output.
  230. func Output() io.Writer {
  231. return global.output
  232. }
  233. // SetOutput sets the output.
  234. func SetOutput(w io.Writer) {
  235. global.SetOutput(w)
  236. }
  237. func Disable() {
  238. global.Disable()
  239. }
  240. func Enable() {
  241. global.Enable()
  242. }
  243. // Print is analogous to `fmt.Print` with termial detection.
  244. func Print(args ...interface{}) {
  245. global.Print(args...)
  246. }
  247. // Println is analogous to `fmt.Println` with termial detection.
  248. func Println(args ...interface{}) {
  249. global.Println(args...)
  250. }
  251. // Printf is analogous to `fmt.Printf` with termial detection.
  252. func Printf(format string, args ...interface{}) {
  253. global.Printf(format, args...)
  254. }
  255. func Black(msg interface{}, styles ...string) string {
  256. return global.Black(msg, styles...)
  257. }
  258. func Red(msg interface{}, styles ...string) string {
  259. return global.Red(msg, styles...)
  260. }
  261. func Green(msg interface{}, styles ...string) string {
  262. return global.Green(msg, styles...)
  263. }
  264. func Yellow(msg interface{}, styles ...string) string {
  265. return global.Yellow(msg, styles...)
  266. }
  267. func Blue(msg interface{}, styles ...string) string {
  268. return global.Blue(msg, styles...)
  269. }
  270. func Magenta(msg interface{}, styles ...string) string {
  271. return global.Magenta(msg, styles...)
  272. }
  273. func Cyan(msg interface{}, styles ...string) string {
  274. return global.Cyan(msg, styles...)
  275. }
  276. func White(msg interface{}, styles ...string) string {
  277. return global.White(msg, styles...)
  278. }
  279. func Grey(msg interface{}, styles ...string) string {
  280. return global.Grey(msg, styles...)
  281. }
  282. func BlackBg(msg interface{}, styles ...string) string {
  283. return global.BlackBg(msg, styles...)
  284. }
  285. func RedBg(msg interface{}, styles ...string) string {
  286. return global.RedBg(msg, styles...)
  287. }
  288. func GreenBg(msg interface{}, styles ...string) string {
  289. return global.GreenBg(msg, styles...)
  290. }
  291. func YellowBg(msg interface{}, styles ...string) string {
  292. return global.YellowBg(msg, styles...)
  293. }
  294. func BlueBg(msg interface{}, styles ...string) string {
  295. return global.BlueBg(msg, styles...)
  296. }
  297. func MagentaBg(msg interface{}, styles ...string) string {
  298. return global.MagentaBg(msg, styles...)
  299. }
  300. func CyanBg(msg interface{}, styles ...string) string {
  301. return global.CyanBg(msg, styles...)
  302. }
  303. func WhiteBg(msg interface{}, styles ...string) string {
  304. return global.WhiteBg(msg, styles...)
  305. }
  306. func Reset(msg interface{}, styles ...string) string {
  307. return global.Reset(msg, styles...)
  308. }
  309. func Bold(msg interface{}, styles ...string) string {
  310. return global.Bold(msg, styles...)
  311. }
  312. func Dim(msg interface{}, styles ...string) string {
  313. return global.Dim(msg, styles...)
  314. }
  315. func Italic(msg interface{}, styles ...string) string {
  316. return global.Italic(msg, styles...)
  317. }
  318. func Underline(msg interface{}, styles ...string) string {
  319. return global.Underline(msg, styles...)
  320. }
  321. func Inverse(msg interface{}, styles ...string) string {
  322. return global.Inverse(msg, styles...)
  323. }
  324. func Hidden(msg interface{}, styles ...string) string {
  325. return global.Hidden(msg, styles...)
  326. }
  327. func Strikeout(msg interface{}, styles ...string) string {
  328. return global.Strikeout(msg, styles...)
  329. }