1// Package xtermcolor provides a palette for xterm colors, and conversion to that palette from anything implementing color.Color
2package xtermcolor
3
4import (
5	"errors"
6	"image/color"
7	"strconv"
8)
9
10// Colors lists Xterm color codes vs. RGBA; values taken from https://gist.github.com/jasonm23/2868981
11// color.Palette is really []color.Color and provides .Convert() and .Index()
12var Colors = color.Palette{
13	// Basic block
14	0:  color.RGBA{0x00, 0x00, 0x00, 0xff},
15	1:  color.RGBA{0x80, 0x00, 0x00, 0xff},
16	2:  color.RGBA{0x00, 0x80, 0x00, 0xff},
17	3:  color.RGBA{0x80, 0x80, 0x00, 0xff},
18	4:  color.RGBA{0x00, 0x00, 0x80, 0xff},
19	5:  color.RGBA{0x80, 0x00, 0x80, 0xff},
20	6:  color.RGBA{0x00, 0x80, 0x80, 0xff},
21	7:  color.RGBA{0xc0, 0xc0, 0xc0, 0xff},
22	8:  color.RGBA{0x80, 0x80, 0x80, 0xff},
23	9:  color.RGBA{0xff, 0x00, 0x00, 0xff},
24	10: color.RGBA{0x00, 0xff, 0x00, 0xff},
25	11: color.RGBA{0xff, 0xff, 0x00, 0xff},
26	12: color.RGBA{0x00, 0x00, 0xff, 0xff},
27	13: color.RGBA{0xff, 0x00, 0xff, 0xff},
28	14: color.RGBA{0x00, 0xff, 0xff, 0xff},
29	15: color.RGBA{0xff, 0xff, 0xff, 0xff},
30
31	// 6x6x6 cube block
32	16:  color.RGBA{0x00, 0x00, 0x00, 0xff},
33	17:  color.RGBA{0x00, 0x00, 0x5f, 0xff},
34	18:  color.RGBA{0x00, 0x00, 0x87, 0xff},
35	19:  color.RGBA{0x00, 0x00, 0xaf, 0xff},
36	20:  color.RGBA{0x00, 0x00, 0xd7, 0xff},
37	21:  color.RGBA{0x00, 0x00, 0xff, 0xff},
38	22:  color.RGBA{0x00, 0x5f, 0x00, 0xff},
39	23:  color.RGBA{0x00, 0x5f, 0x5f, 0xff},
40	24:  color.RGBA{0x00, 0x5f, 0x87, 0xff},
41	25:  color.RGBA{0x00, 0x5f, 0xaf, 0xff},
42	26:  color.RGBA{0x00, 0x5f, 0xd7, 0xff},
43	27:  color.RGBA{0x00, 0x5f, 0xff, 0xff},
44	28:  color.RGBA{0x00, 0x87, 0x00, 0xff},
45	29:  color.RGBA{0x00, 0x87, 0x5f, 0xff},
46	30:  color.RGBA{0x00, 0x87, 0x87, 0xff},
47	31:  color.RGBA{0x00, 0x87, 0xaf, 0xff},
48	32:  color.RGBA{0x00, 0x87, 0xd7, 0xff},
49	33:  color.RGBA{0x00, 0x87, 0xff, 0xff},
50	34:  color.RGBA{0x00, 0xaf, 0x00, 0xff},
51	35:  color.RGBA{0x00, 0xaf, 0x5f, 0xff},
52	36:  color.RGBA{0x00, 0xaf, 0x87, 0xff},
53	37:  color.RGBA{0x00, 0xaf, 0xaf, 0xff},
54	38:  color.RGBA{0x00, 0xaf, 0xd7, 0xff},
55	39:  color.RGBA{0x00, 0xaf, 0xff, 0xff},
56	40:  color.RGBA{0x00, 0xd7, 0x00, 0xff},
57	41:  color.RGBA{0x00, 0xd7, 0x5f, 0xff},
58	42:  color.RGBA{0x00, 0xd7, 0x87, 0xff},
59	43:  color.RGBA{0x00, 0xd7, 0xaf, 0xff},
60	44:  color.RGBA{0x00, 0xd7, 0xd7, 0xff},
61	45:  color.RGBA{0x00, 0xd7, 0xff, 0xff},
62	46:  color.RGBA{0x00, 0xff, 0x00, 0xff},
63	47:  color.RGBA{0x00, 0xff, 0x5f, 0xff},
64	48:  color.RGBA{0x00, 0xff, 0x87, 0xff},
65	49:  color.RGBA{0x00, 0xff, 0xaf, 0xff},
66	50:  color.RGBA{0x00, 0xff, 0xd7, 0xff},
67	51:  color.RGBA{0x00, 0xff, 0xff, 0xff},
68	82:  color.RGBA{0x5f, 0xff, 0x00, 0xff},
69	83:  color.RGBA{0x5f, 0xff, 0x5f, 0xff},
70	84:  color.RGBA{0x5f, 0xff, 0x87, 0xff},
71	85:  color.RGBA{0x5f, 0xff, 0xaf, 0xff},
72	86:  color.RGBA{0x5f, 0xff, 0xd7, 0xff},
73	87:  color.RGBA{0x5f, 0xff, 0xff, 0xff},
74	76:  color.RGBA{0x5f, 0xd7, 0x00, 0xff},
75	77:  color.RGBA{0x5f, 0xd7, 0x5f, 0xff},
76	78:  color.RGBA{0x5f, 0xd7, 0x87, 0xff},
77	79:  color.RGBA{0x5f, 0xd7, 0xaf, 0xff},
78	80:  color.RGBA{0x5f, 0xd7, 0xd7, 0xff},
79	81:  color.RGBA{0x5f, 0xd7, 0xff, 0xff},
80	70:  color.RGBA{0x5f, 0xaf, 0x00, 0xff},
81	71:  color.RGBA{0x5f, 0xaf, 0x5f, 0xff},
82	72:  color.RGBA{0x5f, 0xaf, 0x87, 0xff},
83	73:  color.RGBA{0x5f, 0xaf, 0xaf, 0xff},
84	74:  color.RGBA{0x5f, 0xaf, 0xd7, 0xff},
85	75:  color.RGBA{0x5f, 0xaf, 0xff, 0xff},
86	64:  color.RGBA{0x5f, 0x87, 0x00, 0xff},
87	65:  color.RGBA{0x5f, 0x87, 0x5f, 0xff},
88	66:  color.RGBA{0x5f, 0x87, 0x87, 0xff},
89	67:  color.RGBA{0x5f, 0x87, 0xaf, 0xff},
90	68:  color.RGBA{0x5f, 0x87, 0xd7, 0xff},
91	69:  color.RGBA{0x5f, 0x87, 0xff, 0xff},
92	58:  color.RGBA{0x5f, 0x5f, 0x00, 0xff},
93	59:  color.RGBA{0x5f, 0x5f, 0x5f, 0xff},
94	60:  color.RGBA{0x5f, 0x5f, 0x87, 0xff},
95	61:  color.RGBA{0x5f, 0x5f, 0xaf, 0xff},
96	62:  color.RGBA{0x5f, 0x5f, 0xd7, 0xff},
97	63:  color.RGBA{0x5f, 0x5f, 0xff, 0xff},
98	52:  color.RGBA{0x5f, 0x00, 0x00, 0xff},
99	53:  color.RGBA{0x5f, 0x00, 0x5f, 0xff},
100	54:  color.RGBA{0x5f, 0x00, 0x87, 0xff},
101	55:  color.RGBA{0x5f, 0x00, 0xaf, 0xff},
102	56:  color.RGBA{0x5f, 0x00, 0xd7, 0xff},
103	57:  color.RGBA{0x5f, 0x00, 0xff, 0xff},
104	93:  color.RGBA{0x87, 0x00, 0xff, 0xff},
105	92:  color.RGBA{0x87, 0x00, 0xd7, 0xff},
106	91:  color.RGBA{0x87, 0x00, 0xaf, 0xff},
107	90:  color.RGBA{0x87, 0x00, 0x87, 0xff},
108	89:  color.RGBA{0x87, 0x00, 0x5f, 0xff},
109	88:  color.RGBA{0x87, 0x00, 0x00, 0xff},
110	99:  color.RGBA{0x87, 0x5f, 0xff, 0xff},
111	98:  color.RGBA{0x87, 0x5f, 0xd7, 0xff},
112	97:  color.RGBA{0x87, 0x5f, 0xaf, 0xff},
113	96:  color.RGBA{0x87, 0x5f, 0x87, 0xff},
114	95:  color.RGBA{0x87, 0x5f, 0x5f, 0xff},
115	94:  color.RGBA{0x87, 0x5f, 0x00, 0xff},
116	105: color.RGBA{0x87, 0x87, 0xff, 0xff},
117	104: color.RGBA{0x87, 0x87, 0xd7, 0xff},
118	103: color.RGBA{0x87, 0x87, 0xaf, 0xff},
119	102: color.RGBA{0x87, 0x87, 0x87, 0xff},
120	101: color.RGBA{0x87, 0x87, 0x5f, 0xff},
121	100: color.RGBA{0x87, 0x87, 0x00, 0xff},
122	111: color.RGBA{0x87, 0xaf, 0xff, 0xff},
123	110: color.RGBA{0x87, 0xaf, 0xd7, 0xff},
124	109: color.RGBA{0x87, 0xaf, 0xaf, 0xff},
125	108: color.RGBA{0x87, 0xaf, 0x87, 0xff},
126	107: color.RGBA{0x87, 0xaf, 0x5f, 0xff},
127	106: color.RGBA{0x87, 0xaf, 0x00, 0xff},
128	117: color.RGBA{0x87, 0xd7, 0xff, 0xff},
129	116: color.RGBA{0x87, 0xd7, 0xd7, 0xff},
130	115: color.RGBA{0x87, 0xd7, 0xaf, 0xff},
131	114: color.RGBA{0x87, 0xd7, 0x87, 0xff},
132	113: color.RGBA{0x87, 0xd7, 0x5f, 0xff},
133	112: color.RGBA{0x87, 0xd7, 0x00, 0xff},
134	123: color.RGBA{0x87, 0xff, 0xff, 0xff},
135	122: color.RGBA{0x87, 0xff, 0xd7, 0xff},
136	121: color.RGBA{0x87, 0xff, 0xaf, 0xff},
137	120: color.RGBA{0x87, 0xff, 0x87, 0xff},
138	119: color.RGBA{0x87, 0xff, 0x5f, 0xff},
139	118: color.RGBA{0x87, 0xff, 0x00, 0xff},
140	159: color.RGBA{0xaf, 0xff, 0xff, 0xff},
141	158: color.RGBA{0xaf, 0xff, 0xd7, 0xff},
142	157: color.RGBA{0xaf, 0xff, 0xaf, 0xff},
143	156: color.RGBA{0xaf, 0xff, 0x87, 0xff},
144	155: color.RGBA{0xaf, 0xff, 0x5f, 0xff},
145	154: color.RGBA{0xaf, 0xff, 0x00, 0xff},
146	153: color.RGBA{0xaf, 0xd7, 0xff, 0xff},
147	152: color.RGBA{0xaf, 0xd7, 0xd7, 0xff},
148	151: color.RGBA{0xaf, 0xd7, 0xaf, 0xff},
149	150: color.RGBA{0xaf, 0xd7, 0x87, 0xff},
150	149: color.RGBA{0xaf, 0xd7, 0x5f, 0xff},
151	148: color.RGBA{0xaf, 0xd7, 0x00, 0xff},
152	147: color.RGBA{0xaf, 0xaf, 0xff, 0xff},
153	146: color.RGBA{0xaf, 0xaf, 0xd7, 0xff},
154	145: color.RGBA{0xaf, 0xaf, 0xaf, 0xff},
155	144: color.RGBA{0xaf, 0xaf, 0x87, 0xff},
156	143: color.RGBA{0xaf, 0xaf, 0x5f, 0xff},
157	142: color.RGBA{0xaf, 0xaf, 0x00, 0xff},
158	141: color.RGBA{0xaf, 0x87, 0xff, 0xff},
159	140: color.RGBA{0xaf, 0x87, 0xd7, 0xff},
160	139: color.RGBA{0xaf, 0x87, 0xaf, 0xff},
161	138: color.RGBA{0xaf, 0x87, 0x87, 0xff},
162	137: color.RGBA{0xaf, 0x87, 0x5f, 0xff},
163	136: color.RGBA{0xaf, 0x87, 0x00, 0xff},
164	135: color.RGBA{0xaf, 0x5f, 0xff, 0xff},
165	134: color.RGBA{0xaf, 0x5f, 0xd7, 0xff},
166	133: color.RGBA{0xaf, 0x5f, 0xaf, 0xff},
167	132: color.RGBA{0xaf, 0x5f, 0x87, 0xff},
168	131: color.RGBA{0xaf, 0x5f, 0x5f, 0xff},
169	130: color.RGBA{0xaf, 0x5f, 0x00, 0xff},
170	129: color.RGBA{0xaf, 0x00, 0xff, 0xff},
171	128: color.RGBA{0xaf, 0x00, 0xd7, 0xff},
172	127: color.RGBA{0xaf, 0x00, 0xaf, 0xff},
173	126: color.RGBA{0xaf, 0x00, 0x87, 0xff},
174	125: color.RGBA{0xaf, 0x00, 0x5f, 0xff},
175	124: color.RGBA{0xaf, 0x00, 0x00, 0xff},
176	160: color.RGBA{0xd7, 0x00, 0x00, 0xff},
177	161: color.RGBA{0xd7, 0x00, 0x5f, 0xff},
178	162: color.RGBA{0xd7, 0x00, 0x87, 0xff},
179	163: color.RGBA{0xd7, 0x00, 0xaf, 0xff},
180	164: color.RGBA{0xd7, 0x00, 0xd7, 0xff},
181	165: color.RGBA{0xd7, 0x00, 0xff, 0xff},
182	166: color.RGBA{0xd7, 0x5f, 0x00, 0xff},
183	167: color.RGBA{0xd7, 0x5f, 0x5f, 0xff},
184	168: color.RGBA{0xd7, 0x5f, 0x87, 0xff},
185	169: color.RGBA{0xd7, 0x5f, 0xaf, 0xff},
186	170: color.RGBA{0xd7, 0x5f, 0xd7, 0xff},
187	171: color.RGBA{0xd7, 0x5f, 0xff, 0xff},
188	172: color.RGBA{0xd7, 0x87, 0x00, 0xff},
189	173: color.RGBA{0xd7, 0x87, 0x5f, 0xff},
190	174: color.RGBA{0xd7, 0x87, 0x87, 0xff},
191	175: color.RGBA{0xd7, 0x87, 0xaf, 0xff},
192	176: color.RGBA{0xd7, 0x87, 0xd7, 0xff},
193	177: color.RGBA{0xd7, 0x87, 0xff, 0xff},
194	178: color.RGBA{0xdf, 0xaf, 0x00, 0xff},
195	179: color.RGBA{0xdf, 0xaf, 0x5f, 0xff},
196	180: color.RGBA{0xdf, 0xaf, 0x87, 0xff},
197	181: color.RGBA{0xdf, 0xaf, 0xaf, 0xff},
198	182: color.RGBA{0xdf, 0xaf, 0xdf, 0xff},
199	183: color.RGBA{0xdf, 0xaf, 0xff, 0xff},
200	184: color.RGBA{0xdf, 0xdf, 0x00, 0xff},
201	185: color.RGBA{0xdf, 0xdf, 0x5f, 0xff},
202	186: color.RGBA{0xdf, 0xdf, 0x87, 0xff},
203	187: color.RGBA{0xdf, 0xdf, 0xaf, 0xff},
204	188: color.RGBA{0xdf, 0xdf, 0xdf, 0xff},
205	189: color.RGBA{0xdf, 0xdf, 0xff, 0xff},
206	190: color.RGBA{0xdf, 0xff, 0x00, 0xff},
207	191: color.RGBA{0xdf, 0xff, 0x5f, 0xff},
208	192: color.RGBA{0xdf, 0xff, 0x87, 0xff},
209	193: color.RGBA{0xdf, 0xff, 0xaf, 0xff},
210	194: color.RGBA{0xdf, 0xff, 0xdf, 0xff},
211	195: color.RGBA{0xdf, 0xff, 0xff, 0xff},
212	226: color.RGBA{0xff, 0xff, 0x00, 0xff},
213	227: color.RGBA{0xff, 0xff, 0x5f, 0xff},
214	228: color.RGBA{0xff, 0xff, 0x87, 0xff},
215	229: color.RGBA{0xff, 0xff, 0xaf, 0xff},
216	230: color.RGBA{0xff, 0xff, 0xdf, 0xff},
217	231: color.RGBA{0xff, 0xff, 0xff, 0xff},
218	220: color.RGBA{0xff, 0xdf, 0x00, 0xff},
219	221: color.RGBA{0xff, 0xdf, 0x5f, 0xff},
220	222: color.RGBA{0xff, 0xdf, 0x87, 0xff},
221	223: color.RGBA{0xff, 0xdf, 0xaf, 0xff},
222	224: color.RGBA{0xff, 0xdf, 0xdf, 0xff},
223	225: color.RGBA{0xff, 0xdf, 0xff, 0xff},
224	214: color.RGBA{0xff, 0xaf, 0x00, 0xff},
225	215: color.RGBA{0xff, 0xaf, 0x5f, 0xff},
226	216: color.RGBA{0xff, 0xaf, 0x87, 0xff},
227	217: color.RGBA{0xff, 0xaf, 0xaf, 0xff},
228	218: color.RGBA{0xff, 0xaf, 0xdf, 0xff},
229	219: color.RGBA{0xff, 0xaf, 0xff, 0xff},
230	208: color.RGBA{0xff, 0x87, 0x00, 0xff},
231	209: color.RGBA{0xff, 0x87, 0x5f, 0xff},
232	210: color.RGBA{0xff, 0x87, 0x87, 0xff},
233	211: color.RGBA{0xff, 0x87, 0xaf, 0xff},
234	212: color.RGBA{0xff, 0x87, 0xdf, 0xff},
235	213: color.RGBA{0xff, 0x87, 0xff, 0xff},
236	202: color.RGBA{0xff, 0x5f, 0x00, 0xff},
237	203: color.RGBA{0xff, 0x5f, 0x5f, 0xff},
238	204: color.RGBA{0xff, 0x5f, 0x87, 0xff},
239	205: color.RGBA{0xff, 0x5f, 0xaf, 0xff},
240	206: color.RGBA{0xff, 0x5f, 0xdf, 0xff},
241	207: color.RGBA{0xff, 0x5f, 0xff, 0xff},
242	196: color.RGBA{0xff, 0x00, 0x00, 0xff},
243	197: color.RGBA{0xff, 0x00, 0x5f, 0xff},
244	198: color.RGBA{0xff, 0x00, 0x87, 0xff},
245	199: color.RGBA{0xff, 0x00, 0xaf, 0xff},
246	200: color.RGBA{0xff, 0x00, 0xdf, 0xff},
247	201: color.RGBA{0xff, 0x00, 0xff, 0xff},
248
249	// Grayscale block
250	232: color.RGBA{0x08, 0x08, 0x08, 0xff},
251	233: color.RGBA{0x12, 0x12, 0x12, 0xff},
252	234: color.RGBA{0x1c, 0x1c, 0x1c, 0xff},
253	235: color.RGBA{0x26, 0x26, 0x26, 0xff},
254	236: color.RGBA{0x30, 0x30, 0x30, 0xff},
255	237: color.RGBA{0x3a, 0x3a, 0x3a, 0xff},
256	238: color.RGBA{0x44, 0x44, 0x44, 0xff},
257	239: color.RGBA{0x4e, 0x4e, 0x4e, 0xff},
258	240: color.RGBA{0x58, 0x58, 0x58, 0xff},
259	241: color.RGBA{0x62, 0x62, 0x62, 0xff},
260	242: color.RGBA{0x6c, 0x6c, 0x6c, 0xff},
261	243: color.RGBA{0x76, 0x76, 0x76, 0xff},
262	255: color.RGBA{0xee, 0xee, 0xee, 0xff},
263	254: color.RGBA{0xe4, 0xe4, 0xe4, 0xff},
264	253: color.RGBA{0xda, 0xda, 0xda, 0xff},
265	252: color.RGBA{0xd0, 0xd0, 0xd0, 0xff},
266	251: color.RGBA{0xc6, 0xc6, 0xc6, 0xff},
267	250: color.RGBA{0xbc, 0xbc, 0xbc, 0xff},
268	249: color.RGBA{0xb2, 0xb2, 0xb2, 0xff},
269	248: color.RGBA{0xa8, 0xa8, 0xa8, 0xff},
270	247: color.RGBA{0x9e, 0x9e, 0x9e, 0xff},
271	246: color.RGBA{0x94, 0x94, 0x94, 0xff},
272	245: color.RGBA{0x8a, 0x8a, 0x8a, 0xff},
273	244: color.RGBA{0x80, 0x80, 0x80, 0xff},
274}
275
276var (
277	// ErrorEmptyHexStr is returned by FromHexStr when an empty hex string is provided
278	ErrorEmptyHexStr = errors.New("Empty hex string provided")
279
280	// ErrorHexParse is returned by FromHexStr when an invalid hex string is provided
281	ErrorHexParse = errors.New("Failed to parse string as hex; try something like #CC66FF")
282)
283
284// Convert a 32 bit color to a color.RGBA
285func intToRGBA(c uint32) color.RGBA {
286	r := uint8((c >> 24) & 0xff)
287	g := uint8((c >> 16) & 0xff)
288	b := uint8((c >> 8) & 0xff)
289	a := uint8(c & 0xff)
290	return color.RGBA{r, g, b, a}
291}
292
293// FromColor finds the closest xterm colour to a given color.Color
294func FromColor(target color.Color) uint8 {
295
296	return uint8(Colors.Index(target))
297}
298
299// FromInt finds the closest xterm color to a given 32 bit RGBA color (e.g. 0xff00ff00).
300func FromInt(target uint32) uint8 {
301	return FromColor(intToRGBA(target))
302}
303
304// FromHexStr finds the closest xterm color to a given 24 bit hex string, e.g. "#CC66FF" or "FEFEFE"
305// It's mostly useful if you're used to specifying colours as hex in CSS etc
306func FromHexStr(str string) (uint8, error) {
307	if len(str) == 0 {
308		return 0, ErrorEmptyHexStr
309	}
310
311	if str[0] == '#' {
312		str = str[1:]
313	}
314	v, err := strconv.ParseUint(str, 16, 24)
315	if err != nil {
316		return 0, ErrorHexParse
317	}
318	return FromInt(uint32((v << 8) + 0xFF)), nil
319}
320