style.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. package ansi
  2. import (
  3. "image/color"
  4. "strconv"
  5. "strings"
  6. )
  7. // ResetStyle is a SGR (Select Graphic Rendition) style sequence that resets
  8. // all attributes.
  9. // See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
  10. const ResetStyle = "\x1b[m"
  11. // Attr is a SGR (Select Graphic Rendition) style attribute.
  12. type Attr = int
  13. // Style represents an ANSI SGR (Select Graphic Rendition) style.
  14. type Style []string
  15. // String returns the ANSI SGR (Select Graphic Rendition) style sequence for
  16. // the given style.
  17. func (s Style) String() string {
  18. if len(s) == 0 {
  19. return ResetStyle
  20. }
  21. return "\x1b[" + strings.Join(s, ";") + "m"
  22. }
  23. // Styled returns a styled string with the given style applied.
  24. func (s Style) Styled(str string) string {
  25. if len(s) == 0 {
  26. return str
  27. }
  28. return s.String() + str + ResetStyle
  29. }
  30. // Reset appends the reset style attribute to the style.
  31. func (s Style) Reset() Style {
  32. return append(s, resetAttr)
  33. }
  34. // Bold appends the bold style attribute to the style.
  35. func (s Style) Bold() Style {
  36. return append(s, boldAttr)
  37. }
  38. // Faint appends the faint style attribute to the style.
  39. func (s Style) Faint() Style {
  40. return append(s, faintAttr)
  41. }
  42. // Italic appends the italic style attribute to the style.
  43. func (s Style) Italic() Style {
  44. return append(s, italicAttr)
  45. }
  46. // Underline appends the underline style attribute to the style.
  47. func (s Style) Underline() Style {
  48. return append(s, underlineAttr)
  49. }
  50. // UnderlineStyle appends the underline style attribute to the style.
  51. func (s Style) UnderlineStyle(u UnderlineStyle) Style {
  52. switch u {
  53. case NoUnderlineStyle:
  54. return s.NoUnderline()
  55. case SingleUnderlineStyle:
  56. return s.Underline()
  57. case DoubleUnderlineStyle:
  58. return append(s, doubleUnderlineStyle)
  59. case CurlyUnderlineStyle:
  60. return append(s, curlyUnderlineStyle)
  61. case DottedUnderlineStyle:
  62. return append(s, dottedUnderlineStyle)
  63. case DashedUnderlineStyle:
  64. return append(s, dashedUnderlineStyle)
  65. }
  66. return s
  67. }
  68. // DoubleUnderline appends the double underline style attribute to the style.
  69. // This is a convenience method for UnderlineStyle(DoubleUnderlineStyle).
  70. func (s Style) DoubleUnderline() Style {
  71. return s.UnderlineStyle(DoubleUnderlineStyle)
  72. }
  73. // CurlyUnderline appends the curly underline style attribute to the style.
  74. // This is a convenience method for UnderlineStyle(CurlyUnderlineStyle).
  75. func (s Style) CurlyUnderline() Style {
  76. return s.UnderlineStyle(CurlyUnderlineStyle)
  77. }
  78. // DottedUnderline appends the dotted underline style attribute to the style.
  79. // This is a convenience method for UnderlineStyle(DottedUnderlineStyle).
  80. func (s Style) DottedUnderline() Style {
  81. return s.UnderlineStyle(DottedUnderlineStyle)
  82. }
  83. // DashedUnderline appends the dashed underline style attribute to the style.
  84. // This is a convenience method for UnderlineStyle(DashedUnderlineStyle).
  85. func (s Style) DashedUnderline() Style {
  86. return s.UnderlineStyle(DashedUnderlineStyle)
  87. }
  88. // SlowBlink appends the slow blink style attribute to the style.
  89. func (s Style) SlowBlink() Style {
  90. return append(s, slowBlinkAttr)
  91. }
  92. // RapidBlink appends the rapid blink style attribute to the style.
  93. func (s Style) RapidBlink() Style {
  94. return append(s, rapidBlinkAttr)
  95. }
  96. // Reverse appends the reverse style attribute to the style.
  97. func (s Style) Reverse() Style {
  98. return append(s, reverseAttr)
  99. }
  100. // Conceal appends the conceal style attribute to the style.
  101. func (s Style) Conceal() Style {
  102. return append(s, concealAttr)
  103. }
  104. // Strikethrough appends the strikethrough style attribute to the style.
  105. func (s Style) Strikethrough() Style {
  106. return append(s, strikethroughAttr)
  107. }
  108. // NoBold appends the no bold style attribute to the style.
  109. func (s Style) NoBold() Style {
  110. return append(s, noBoldAttr)
  111. }
  112. // NormalIntensity appends the normal intensity style attribute to the style.
  113. func (s Style) NormalIntensity() Style {
  114. return append(s, normalIntensityAttr)
  115. }
  116. // NoItalic appends the no italic style attribute to the style.
  117. func (s Style) NoItalic() Style {
  118. return append(s, noItalicAttr)
  119. }
  120. // NoUnderline appends the no underline style attribute to the style.
  121. func (s Style) NoUnderline() Style {
  122. return append(s, noUnderlineAttr)
  123. }
  124. // NoBlink appends the no blink style attribute to the style.
  125. func (s Style) NoBlink() Style {
  126. return append(s, noBlinkAttr)
  127. }
  128. // NoReverse appends the no reverse style attribute to the style.
  129. func (s Style) NoReverse() Style {
  130. return append(s, noReverseAttr)
  131. }
  132. // NoConceal appends the no conceal style attribute to the style.
  133. func (s Style) NoConceal() Style {
  134. return append(s, noConcealAttr)
  135. }
  136. // NoStrikethrough appends the no strikethrough style attribute to the style.
  137. func (s Style) NoStrikethrough() Style {
  138. return append(s, noStrikethroughAttr)
  139. }
  140. // DefaultForegroundColor appends the default foreground color style attribute to the style.
  141. func (s Style) DefaultForegroundColor() Style {
  142. return append(s, defaultForegroundColorAttr)
  143. }
  144. // DefaultBackgroundColor appends the default background color style attribute to the style.
  145. func (s Style) DefaultBackgroundColor() Style {
  146. return append(s, defaultBackgroundColorAttr)
  147. }
  148. // DefaultUnderlineColor appends the default underline color style attribute to the style.
  149. func (s Style) DefaultUnderlineColor() Style {
  150. return append(s, defaultUnderlineColorAttr)
  151. }
  152. // ForegroundColor appends the foreground color style attribute to the style.
  153. func (s Style) ForegroundColor(c Color) Style {
  154. return append(s, foregroundColorString(c))
  155. }
  156. // BackgroundColor appends the background color style attribute to the style.
  157. func (s Style) BackgroundColor(c Color) Style {
  158. return append(s, backgroundColorString(c))
  159. }
  160. // UnderlineColor appends the underline color style attribute to the style.
  161. func (s Style) UnderlineColor(c Color) Style {
  162. return append(s, underlineColorString(c))
  163. }
  164. // UnderlineStyle represents an ANSI SGR (Select Graphic Rendition) underline
  165. // style.
  166. type UnderlineStyle = int
  167. const (
  168. doubleUnderlineStyle = "4:2"
  169. curlyUnderlineStyle = "4:3"
  170. dottedUnderlineStyle = "4:4"
  171. dashedUnderlineStyle = "4:5"
  172. )
  173. const (
  174. // NoUnderlineStyle is the default underline style.
  175. NoUnderlineStyle UnderlineStyle = iota
  176. // SingleUnderlineStyle is a single underline style.
  177. SingleUnderlineStyle
  178. // DoubleUnderlineStyle is a double underline style.
  179. DoubleUnderlineStyle
  180. // CurlyUnderlineStyle is a curly underline style.
  181. CurlyUnderlineStyle
  182. // DottedUnderlineStyle is a dotted underline style.
  183. DottedUnderlineStyle
  184. // DashedUnderlineStyle is a dashed underline style.
  185. DashedUnderlineStyle
  186. )
  187. // SGR (Select Graphic Rendition) style attributes.
  188. // See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
  189. const (
  190. ResetAttr Attr = 0
  191. BoldAttr Attr = 1
  192. FaintAttr Attr = 2
  193. ItalicAttr Attr = 3
  194. UnderlineAttr Attr = 4
  195. SlowBlinkAttr Attr = 5
  196. RapidBlinkAttr Attr = 6
  197. ReverseAttr Attr = 7
  198. ConcealAttr Attr = 8
  199. StrikethroughAttr Attr = 9
  200. NoBoldAttr Attr = 21 // Some terminals treat this as double underline.
  201. NormalIntensityAttr Attr = 22
  202. NoItalicAttr Attr = 23
  203. NoUnderlineAttr Attr = 24
  204. NoBlinkAttr Attr = 25
  205. NoReverseAttr Attr = 27
  206. NoConcealAttr Attr = 28
  207. NoStrikethroughAttr Attr = 29
  208. BlackForegroundColorAttr Attr = 30
  209. RedForegroundColorAttr Attr = 31
  210. GreenForegroundColorAttr Attr = 32
  211. YellowForegroundColorAttr Attr = 33
  212. BlueForegroundColorAttr Attr = 34
  213. MagentaForegroundColorAttr Attr = 35
  214. CyanForegroundColorAttr Attr = 36
  215. WhiteForegroundColorAttr Attr = 37
  216. ExtendedForegroundColorAttr Attr = 38
  217. DefaultForegroundColorAttr Attr = 39
  218. BlackBackgroundColorAttr Attr = 40
  219. RedBackgroundColorAttr Attr = 41
  220. GreenBackgroundColorAttr Attr = 42
  221. YellowBackgroundColorAttr Attr = 43
  222. BlueBackgroundColorAttr Attr = 44
  223. MagentaBackgroundColorAttr Attr = 45
  224. CyanBackgroundColorAttr Attr = 46
  225. WhiteBackgroundColorAttr Attr = 47
  226. ExtendedBackgroundColorAttr Attr = 48
  227. DefaultBackgroundColorAttr Attr = 49
  228. ExtendedUnderlineColorAttr Attr = 58
  229. DefaultUnderlineColorAttr Attr = 59
  230. BrightBlackForegroundColorAttr Attr = 90
  231. BrightRedForegroundColorAttr Attr = 91
  232. BrightGreenForegroundColorAttr Attr = 92
  233. BrightYellowForegroundColorAttr Attr = 93
  234. BrightBlueForegroundColorAttr Attr = 94
  235. BrightMagentaForegroundColorAttr Attr = 95
  236. BrightCyanForegroundColorAttr Attr = 96
  237. BrightWhiteForegroundColorAttr Attr = 97
  238. BrightBlackBackgroundColorAttr Attr = 100
  239. BrightRedBackgroundColorAttr Attr = 101
  240. BrightGreenBackgroundColorAttr Attr = 102
  241. BrightYellowBackgroundColorAttr Attr = 103
  242. BrightBlueBackgroundColorAttr Attr = 104
  243. BrightMagentaBackgroundColorAttr Attr = 105
  244. BrightCyanBackgroundColorAttr Attr = 106
  245. BrightWhiteBackgroundColorAttr Attr = 107
  246. RGBColorIntroducerAttr Attr = 2
  247. ExtendedColorIntroducerAttr Attr = 5
  248. )
  249. const (
  250. resetAttr = "0"
  251. boldAttr = "1"
  252. faintAttr = "2"
  253. italicAttr = "3"
  254. underlineAttr = "4"
  255. slowBlinkAttr = "5"
  256. rapidBlinkAttr = "6"
  257. reverseAttr = "7"
  258. concealAttr = "8"
  259. strikethroughAttr = "9"
  260. noBoldAttr = "21"
  261. normalIntensityAttr = "22"
  262. noItalicAttr = "23"
  263. noUnderlineAttr = "24"
  264. noBlinkAttr = "25"
  265. noReverseAttr = "27"
  266. noConcealAttr = "28"
  267. noStrikethroughAttr = "29"
  268. blackForegroundColorAttr = "30"
  269. redForegroundColorAttr = "31"
  270. greenForegroundColorAttr = "32"
  271. yellowForegroundColorAttr = "33"
  272. blueForegroundColorAttr = "34"
  273. magentaForegroundColorAttr = "35"
  274. cyanForegroundColorAttr = "36"
  275. whiteForegroundColorAttr = "37"
  276. extendedForegroundColorAttr = "38"
  277. defaultForegroundColorAttr = "39"
  278. blackBackgroundColorAttr = "40"
  279. redBackgroundColorAttr = "41"
  280. greenBackgroundColorAttr = "42"
  281. yellowBackgroundColorAttr = "43"
  282. blueBackgroundColorAttr = "44"
  283. magentaBackgroundColorAttr = "45"
  284. cyanBackgroundColorAttr = "46"
  285. whiteBackgroundColorAttr = "47"
  286. extendedBackgroundColorAttr = "48"
  287. defaultBackgroundColorAttr = "49"
  288. extendedUnderlineColorAttr = "58"
  289. defaultUnderlineColorAttr = "59"
  290. brightBlackForegroundColorAttr = "90"
  291. brightRedForegroundColorAttr = "91"
  292. brightGreenForegroundColorAttr = "92"
  293. brightYellowForegroundColorAttr = "93"
  294. brightBlueForegroundColorAttr = "94"
  295. brightMagentaForegroundColorAttr = "95"
  296. brightCyanForegroundColorAttr = "96"
  297. brightWhiteForegroundColorAttr = "97"
  298. brightBlackBackgroundColorAttr = "100"
  299. brightRedBackgroundColorAttr = "101"
  300. brightGreenBackgroundColorAttr = "102"
  301. brightYellowBackgroundColorAttr = "103"
  302. brightBlueBackgroundColorAttr = "104"
  303. brightMagentaBackgroundColorAttr = "105"
  304. brightCyanBackgroundColorAttr = "106"
  305. brightWhiteBackgroundColorAttr = "107"
  306. )
  307. // foregroundColorString returns the style SGR attribute for the given
  308. // foreground color.
  309. // See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
  310. func foregroundColorString(c Color) string {
  311. switch c := c.(type) {
  312. case BasicColor:
  313. // 3-bit or 4-bit ANSI foreground
  314. // "3<n>" or "9<n>" where n is the color number from 0 to 7
  315. switch c {
  316. case Black:
  317. return blackForegroundColorAttr
  318. case Red:
  319. return redForegroundColorAttr
  320. case Green:
  321. return greenForegroundColorAttr
  322. case Yellow:
  323. return yellowForegroundColorAttr
  324. case Blue:
  325. return blueForegroundColorAttr
  326. case Magenta:
  327. return magentaForegroundColorAttr
  328. case Cyan:
  329. return cyanForegroundColorAttr
  330. case White:
  331. return whiteForegroundColorAttr
  332. case BrightBlack:
  333. return brightBlackForegroundColorAttr
  334. case BrightRed:
  335. return brightRedForegroundColorAttr
  336. case BrightGreen:
  337. return brightGreenForegroundColorAttr
  338. case BrightYellow:
  339. return brightYellowForegroundColorAttr
  340. case BrightBlue:
  341. return brightBlueForegroundColorAttr
  342. case BrightMagenta:
  343. return brightMagentaForegroundColorAttr
  344. case BrightCyan:
  345. return brightCyanForegroundColorAttr
  346. case BrightWhite:
  347. return brightWhiteForegroundColorAttr
  348. }
  349. case ExtendedColor:
  350. // 256-color ANSI foreground
  351. // "38;5;<n>"
  352. return "38;5;" + strconv.FormatUint(uint64(c), 10)
  353. case TrueColor, color.Color:
  354. // 24-bit "true color" foreground
  355. // "38;2;<r>;<g>;<b>"
  356. r, g, b, _ := c.RGBA()
  357. return "38;2;" +
  358. strconv.FormatUint(uint64(shift(r)), 10) + ";" +
  359. strconv.FormatUint(uint64(shift(g)), 10) + ";" +
  360. strconv.FormatUint(uint64(shift(b)), 10)
  361. }
  362. return defaultForegroundColorAttr
  363. }
  364. // backgroundColorString returns the style SGR attribute for the given
  365. // background color.
  366. // See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
  367. func backgroundColorString(c Color) string {
  368. switch c := c.(type) {
  369. case BasicColor:
  370. // 3-bit or 4-bit ANSI foreground
  371. // "4<n>" or "10<n>" where n is the color number from 0 to 7
  372. switch c {
  373. case Black:
  374. return blackBackgroundColorAttr
  375. case Red:
  376. return redBackgroundColorAttr
  377. case Green:
  378. return greenBackgroundColorAttr
  379. case Yellow:
  380. return yellowBackgroundColorAttr
  381. case Blue:
  382. return blueBackgroundColorAttr
  383. case Magenta:
  384. return magentaBackgroundColorAttr
  385. case Cyan:
  386. return cyanBackgroundColorAttr
  387. case White:
  388. return whiteBackgroundColorAttr
  389. case BrightBlack:
  390. return brightBlackBackgroundColorAttr
  391. case BrightRed:
  392. return brightRedBackgroundColorAttr
  393. case BrightGreen:
  394. return brightGreenBackgroundColorAttr
  395. case BrightYellow:
  396. return brightYellowBackgroundColorAttr
  397. case BrightBlue:
  398. return brightBlueBackgroundColorAttr
  399. case BrightMagenta:
  400. return brightMagentaBackgroundColorAttr
  401. case BrightCyan:
  402. return brightCyanBackgroundColorAttr
  403. case BrightWhite:
  404. return brightWhiteBackgroundColorAttr
  405. }
  406. case ExtendedColor:
  407. // 256-color ANSI foreground
  408. // "48;5;<n>"
  409. return "48;5;" + strconv.FormatUint(uint64(c), 10)
  410. case TrueColor, color.Color:
  411. // 24-bit "true color" foreground
  412. // "38;2;<r>;<g>;<b>"
  413. r, g, b, _ := c.RGBA()
  414. return "48;2;" +
  415. strconv.FormatUint(uint64(shift(r)), 10) + ";" +
  416. strconv.FormatUint(uint64(shift(g)), 10) + ";" +
  417. strconv.FormatUint(uint64(shift(b)), 10)
  418. }
  419. return defaultBackgroundColorAttr
  420. }
  421. // underlineColorString returns the style SGR attribute for the given underline
  422. // color.
  423. // See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
  424. func underlineColorString(c Color) string {
  425. switch c := c.(type) {
  426. // NOTE: we can't use 3-bit and 4-bit ANSI color codes with underline
  427. // color, use 256-color instead.
  428. //
  429. // 256-color ANSI underline color
  430. // "58;5;<n>"
  431. case BasicColor:
  432. return "58;5;" + strconv.FormatUint(uint64(c), 10)
  433. case ExtendedColor:
  434. return "58;5;" + strconv.FormatUint(uint64(c), 10)
  435. case TrueColor, color.Color:
  436. // 24-bit "true color" foreground
  437. // "38;2;<r>;<g>;<b>"
  438. r, g, b, _ := c.RGBA()
  439. return "58;2;" +
  440. strconv.FormatUint(uint64(shift(r)), 10) + ";" +
  441. strconv.FormatUint(uint64(shift(g)), 10) + ";" +
  442. strconv.FormatUint(uint64(shift(b)), 10)
  443. }
  444. return defaultUnderlineColorAttr
  445. }