libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
ansistream.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <cstring>
14#include <promeki/namespace.h>
15#include <promeki/string.h>
16#include <promeki/util.h>
17#include <promeki/color.h>
18
19PROMEKI_NAMESPACE_BEGIN
20
21class IODevice;
22
30class AnsiStream {
31 public:
35 enum TextStyle {
36 Bold = 1,
37 Dim = 2,
38 Italic = 3,
39 Underlined = 4,
40 Blink = 5,
41 Inverted = 7,
42 Hidden = 8
43 };
44
59 enum AnsiColor : uint8_t {
60 // -- System colors (0-15) --
61 Black = 0,
62 Maroon = 1,
63 DarkRed = 1,
64 Green = 2,
65 DarkGreen = 2,
66 Olive = 3,
67 DarkYellow = 3,
68 Navy = 4,
69 DarkBlue = 4,
70 Purple = 5,
71 DarkMagenta = 5,
72 Teal = 6,
73 DarkCyan = 6,
74 Silver = 7,
75 LightGray = 7,
76 Grey = 8,
77 DarkGray = 8,
78 Red = 9,
79 Lime = 10,
80 Yellow = 11,
81 Blue = 12,
82 Fuchsia = 13,
83 Magenta = 13,
84 Aqua = 14,
85 Cyan = 14,
86 White = 15,
87
88 // -- Color cube (16-231) --
89 Grey0 = 16,
90 NavyBlue = 17,
91 DarkBlue_18 = 18,
92 Blue3_19 = 19,
93 Blue3_20 = 20,
94 Blue1 = 21,
95 DarkGreen_22 = 22,
96 DeepSkyBlue4_23 = 23,
97 DeepSkyBlue4_24 = 24,
98 DeepSkyBlue4_25 = 25,
99 DodgerBlue3 = 26,
100 DodgerBlue2 = 27,
101 Green4 = 28,
102 SpringGreen4 = 29,
103 Turquoise4 = 30,
104 DeepSkyBlue3_31 = 31,
105 DeepSkyBlue3_32 = 32,
106 DodgerBlue1 = 33,
107 Green3_34 = 34,
108 SpringGreen3_35 = 35,
109 DarkCyan_36 = 36,
110 LightSeaGreen = 37,
111 DeepSkyBlue2 = 38,
112 DeepSkyBlue1 = 39,
113 Green3_40 = 40,
114 SpringGreen3_41 = 41,
115 SpringGreen2_42 = 42,
116 Cyan3 = 43,
117 DarkTurquoise = 44,
118 Turquoise2 = 45,
119 Green1 = 46,
120 SpringGreen2_47 = 47,
121 SpringGreen1 = 48,
122 MediumSpringGreen = 49,
123 Cyan2 = 50,
124 Cyan1 = 51,
125 DarkRed_52 = 52,
126 DeepPink4_53 = 53,
127 Purple4_54 = 54,
128 Purple4_55 = 55,
129 Purple3 = 56,
130 BlueViolet = 57,
131 Orange4_58 = 58,
132 Grey37 = 59,
133 MediumPurple4 = 60,
134 SlateBlue3_61 = 61,
135 SlateBlue3_62 = 62,
136 RoyalBlue1 = 63,
137 Chartreuse4 = 64,
138 DarkSeaGreen4_65 = 65,
139 PaleTurquoise4 = 66,
140 SteelBlue = 67,
141 SteelBlue3 = 68,
142 CornflowerBlue = 69,
143 Chartreuse3_70 = 70,
144 DarkSeaGreen4_71 = 71,
145 CadetBlue_72 = 72,
146 CadetBlue_73 = 73,
147 SkyBlue3 = 74,
148 SteelBlue1_75 = 75,
149 Chartreuse3_76 = 76,
150 PaleGreen3_77 = 77,
151 SeaGreen3 = 78,
152 Aquamarine3 = 79,
153 MediumTurquoise = 80,
154 SteelBlue1_81 = 81,
155 Chartreuse2_82 = 82,
156 SeaGreen2 = 83,
157 SeaGreen1_84 = 84,
158 SeaGreen1_85 = 85,
159 Aquamarine1_86 = 86,
160 DarkSlateGray2 = 87,
161 DarkRed_88 = 88,
162 DeepPink4_89 = 89,
163 DarkMagenta_90 = 90,
164 DarkMagenta_91 = 91,
165 DarkViolet_92 = 92,
166 Purple_93 = 93,
167 Orange4_94 = 94,
168 LightPink4 = 95,
169 Plum4 = 96,
170 MediumPurple3_97 = 97,
171 MediumPurple3_98 = 98,
172 SlateBlue1 = 99,
173 Yellow4_100 = 100,
174 Wheat4 = 101,
175 Grey53 = 102,
176 LightSlateGrey = 103,
177 MediumPurple = 104,
178 LightSlateBlue = 105,
179 Yellow4_106 = 106,
180 DarkOliveGreen3_107 = 107,
181 DarkSeaGreen = 108,
182 LightSkyBlue3_109 = 109,
183 LightSkyBlue3_110 = 110,
184 SkyBlue2 = 111,
185 Chartreuse2_112 = 112,
186 DarkOliveGreen3_113 = 113,
187 PaleGreen3_114 = 114,
188 DarkSeaGreen3_115 = 115,
189 DarkSlateGray3 = 116,
190 SkyBlue1 = 117,
191 Chartreuse1 = 118,
192 LightGreen_119 = 119,
193 LightGreen_120 = 120,
194 PaleGreen1_121 = 121,
195 Aquamarine1_122 = 122,
196 DarkSlateGray1 = 123,
197 Red3_124 = 124,
198 DeepPink4_125 = 125,
199 MediumVioletRed = 126,
200 Magenta3_127 = 127,
201 DarkViolet_128 = 128,
202 Purple_129 = 129,
203 DarkOrange3_130 = 130,
204 IndianRed_131 = 131,
205 HotPink3_132 = 132,
206 MediumOrchid3 = 133,
207 MediumOrchid = 134,
208 MediumPurple2_135 = 135,
209 DarkGoldenrod = 136,
210 LightSalmon3_137 = 137,
211 RosyBrown = 138,
212 Grey63 = 139,
213 MediumPurple2_140 = 140,
214 MediumPurple1 = 141,
215 Gold3_142 = 142,
216 DarkKhaki = 143,
217 NavajoWhite3 = 144,
218 Grey69 = 145,
219 LightSteelBlue3 = 146,
220 LightSteelBlue = 147,
221 Yellow3_148 = 148,
222 DarkOliveGreen3_149 = 149,
223 DarkSeaGreen3_150 = 150,
224 DarkSeaGreen2_151 = 151,
225 LightCyan3 = 152,
226 LightSkyBlue1 = 153,
227 GreenYellow = 154,
228 DarkOliveGreen2 = 155,
229 PaleGreen1_156 = 156,
230 DarkSeaGreen2_157 = 157,
231 DarkSeaGreen1_158 = 158,
232 PaleTurquoise1 = 159,
233 Red3_160 = 160,
234 DeepPink3_161 = 161,
235 DeepPink3_162 = 162,
236 Magenta3_163 = 163,
237 Magenta3_164 = 164,
238 Magenta2_165 = 165,
239 DarkOrange3_166 = 166,
240 IndianRed_167 = 167,
241 HotPink3_168 = 168,
242 HotPink2 = 169,
243 Orchid = 170,
244 MediumOrchid1_171 = 171,
245 Orange3 = 172,
246 LightSalmon3_173 = 173,
247 LightPink3 = 174,
248 Pink3 = 175,
249 Plum3 = 176,
250 Violet = 177,
251 Gold3_178 = 178,
252 LightGoldenrod3 = 179,
253 Tan = 180,
254 MistyRose3 = 181,
255 Thistle3 = 182,
256 Plum2 = 183,
257 Yellow3_184 = 184,
258 Khaki3 = 185,
259 LightGoldenrod2_186 = 186,
260 LightYellow3 = 187,
261 Grey84 = 188,
262 LightSteelBlue1 = 189,
263 Yellow2 = 190,
264 DarkOliveGreen1_191 = 191,
265 DarkOliveGreen1_192 = 192,
266 DarkSeaGreen1_193 = 193,
267 Honeydew2 = 194,
268 LightCyan1 = 195,
269 Red1 = 196,
270 DeepPink2 = 197,
271 DeepPink1_198 = 198,
272 DeepPink1_199 = 199,
273 Magenta2_200 = 200,
274 Magenta1 = 201,
275 OrangeRed1 = 202,
276 IndianRed1_203 = 203,
277 IndianRed1_204 = 204,
278 HotPink_205 = 205,
279 HotPink_206 = 206,
280 MediumOrchid1_207 = 207,
281 DarkOrange = 208,
282 Salmon1 = 209,
283 LightCoral = 210,
284 PaleVioletRed1 = 211,
285 Orchid2 = 212,
286 Orchid1 = 213,
287 Orange1 = 214,
288 SandyBrown = 215,
289 LightSalmon1 = 216,
290 LightPink1 = 217,
291 Pink1 = 218,
292 Plum1 = 219,
293 Gold1 = 220,
294 LightGoldenrod2_221 = 221,
295 LightGoldenrod2_222 = 222,
296 NavajoWhite1 = 223,
297 MistyRose1 = 224,
298 Thistle1 = 225,
299 Yellow1 = 226,
300 LightGoldenrod1 = 227,
301 Khaki1 = 228,
302 Wheat1 = 229,
303 Cornsilk1 = 230,
304 Grey100 = 231,
305
306 // -- Grayscale ramp (232-255) --
307 Grey3 = 232,
308 Grey7 = 233,
309 Grey11 = 234,
310 Grey15 = 235,
311 Grey19 = 236,
312 Grey23 = 237,
313 Grey27 = 238,
314 Grey30 = 239,
315 Grey35 = 240,
316 Grey39 = 241,
317 Grey42 = 242,
318 Grey46 = 243,
319 Grey50 = 244,
320 Grey54 = 245,
321 Grey58 = 246,
322 Grey62 = 247,
323 Grey66 = 248,
324 Grey70 = 249,
325 Grey74 = 250,
326 Grey78 = 251,
327 Grey82 = 252,
328 Grey85 = 253,
329 Grey89 = 254,
330 Grey93 = 255
331 };
332
338 static Color ansiColor(int index);
339
345 static Color ansiColor(AnsiColor color) { return ansiColor(static_cast<int>(color)); }
346
359 static AnsiColor findClosestAnsiColor(const Color &color, int maxIndex = 255);
360
367 static bool stdoutWindowSize(int &rows, int &cols);
368
373 static bool stdoutSupportsANSI();
374
379 AnsiStream(IODevice *device) : _device(device), _enabled(true) {}
380
387 void setAnsiEnabled(bool val) {
388 _enabled = val;
389 return;
390 }
391
396 IODevice *device() const { return _device; }
397
403 AnsiStream &write(const String &text);
404
410 AnsiStream &write(const char *text);
411
417 AnsiStream &write(char ch);
418
424 AnsiStream &write(int val);
425
429 void flush();
430
432 AnsiStream &operator<<(const String &text) { return write(text); }
434 AnsiStream &operator<<(const char *text) { return write(text); }
436 AnsiStream &operator<<(char ch) { return write(ch); }
438 AnsiStream &operator<<(int val) { return write(val); }
439
450 AnsiStream &setForeground(AnsiColor color);
451
462 AnsiStream &setBackground(AnsiColor color);
463
470 AnsiStream &setForeground(const Color &color, int maxIndex = 255);
471
478 AnsiStream &setBackground(const Color &color, int maxIndex = 255);
479
485 AnsiStream &cursorUp(int n) {
486 if (!_enabled) return *this;
487 *this << "\033[" << n << "A";
488 return *this;
489 }
490
496 AnsiStream &cursorDown(int n) {
497 if (!_enabled) return *this;
498 *this << "\033[" << n << "B";
499 return *this;
500 }
501
507 AnsiStream &cursorRight(int n) {
508 if (!_enabled) return *this;
509 *this << "\033[" << n << "C";
510 return *this;
511 }
512
518 AnsiStream &cursorLeft(int n) {
519 if (!_enabled) return *this;
520 *this << "\033[" << n << "D";
521 return *this;
522 }
523
530 AnsiStream &setCursorPosition(int r, int c) {
531 if (!_enabled) return *this;
532 *this << "\033[" << r << ";" << c << "H";
533 return *this;
534 }
535
540 AnsiStream &clearScreen() {
541 if (!_enabled) return *this;
542 *this << "\033[2J";
543 return *this;
544 }
545
550 AnsiStream &moveToStartOfLine() {
551 if (!_enabled) return *this;
552 *this << "\033[0G";
553 return *this;
554 }
555
560 AnsiStream &moveToEndOfLine() {
561 if (!_enabled) return *this;
562 *this << "\033[999G";
563 return *this;
564 }
565
570 AnsiStream &clearLine() {
571 if (!_enabled) return *this;
572 *this << "\033[2K";
573 return *this;
574 }
575
580 AnsiStream &clearLineBeforeCursor() {
581 if (!_enabled) return *this;
582 *this << "\033[1K";
583 return *this;
584 }
585
590 AnsiStream &clearLineAfterCursor() {
591 if (!_enabled) return *this;
592 *this << "\033[0K";
593 return *this;
594 }
595
600 AnsiStream &reset() {
601 if (!_enabled) return *this;
602 *this << "\033[0m";
603 return *this;
604 }
605
610 AnsiStream &resetForeground() {
611 if (!_enabled) return *this;
612 *this << "\033[39m";
613 return *this;
614 }
615
620 AnsiStream &resetBackground() {
621 if (!_enabled) return *this;
622 *this << "\033[49m";
623 return *this;
624 }
625
630 AnsiStream &showCursor() {
631 if (!_enabled) return *this;
632 *this << "\033[?25h";
633 return *this;
634 }
635
640 AnsiStream &hideCursor() {
641 if (!_enabled) return *this;
642 *this << "\033[?25l";
643 return *this;
644 }
645
650 AnsiStream &saveCursorPosition() {
651 if (!_enabled) return *this;
652 *this << "\033[s";
653 return *this;
654 }
655
661 AnsiStream &restoreCursorPosition() {
662 if (!_enabled) return *this;
663 *this << "\033[u";
664 return *this;
665 }
666
673 AnsiStream &enableScrollingRegion(int startRow, int endRow) {
674 if (!_enabled) return *this;
675 *this << "\033[" << startRow << ";" << endRow << "r";
676 return *this;
677 }
678
684 AnsiStream &scrollUp(int n) {
685 if (!_enabled) return *this;
686 *this << "\033[" << n << "S";
687 return *this;
688 }
689
695 AnsiStream &scrollDown(int n) {
696 if (!_enabled) return *this;
697 *this << "\033[" << n << "T";
698 return *this;
699 }
700
706 AnsiStream &eraseCharacters(int n) {
707 if (!_enabled) return *this;
708 *this << "\033[" << n << "X";
709 return *this;
710 }
711
722 AnsiStream &setForeground256(uint8_t index) {
723 if (!_enabled) return *this;
724 *this << "\033[38;5;" << static_cast<int>(index) << "m";
725 return *this;
726 }
727
738 AnsiStream &setBackground256(uint8_t index) {
739 if (!_enabled) return *this;
740 *this << "\033[48;5;" << static_cast<int>(index) << "m";
741 return *this;
742 }
743
751 AnsiStream &setForegroundRGB(uint8_t r, uint8_t g, uint8_t b) {
752 if (!_enabled) return *this;
753 *this << "\033[38;2;" << static_cast<int>(r) << ";" << static_cast<int>(g) << ";"
754 << static_cast<int>(b) << "m";
755 return *this;
756 }
757
765 AnsiStream &setBackgroundRGB(uint8_t r, uint8_t g, uint8_t b) {
766 if (!_enabled) return *this;
767 *this << "\033[48;2;" << static_cast<int>(r) << ";" << static_cast<int>(g) << ";"
768 << static_cast<int>(b) << "m";
769 return *this;
770 }
771
777 AnsiStream &setStrikethrough(bool enable) {
778 if (!_enabled) return *this;
779 *this << "\033[" << (enable ? "9" : "29") << "m";
780 return *this;
781 }
782
787 AnsiStream &useAlternateScreenBuffer() {
788 if (!_enabled) return *this;
789 *this << "\033[?1049h";
790 return *this;
791 }
792
797 AnsiStream &useMainScreenBuffer() {
798 if (!_enabled) return *this;
799 *this << "\033[?1049l";
800 return *this;
801 }
802
810 bool getCursorPosition(IODevice *input, int &row, int &col);
811
812 private:
813 IODevice *_device;
814 bool _enabled;
815};
816
817PROMEKI_NAMESPACE_END
818
819#endif // PROMEKI_ENABLE_CORE