11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
19PROMEKI_NAMESPACE_BEGIN
59 enum AnsiColor : uint8_t {
104 DeepSkyBlue3_31 = 31,
105 DeepSkyBlue3_32 = 32,
108 SpringGreen3_35 = 35,
114 SpringGreen3_41 = 41,
115 SpringGreen2_42 = 42,
120 SpringGreen2_47 = 47,
122 MediumSpringGreen = 49,
138 DarkSeaGreen4_65 = 65,
144 DarkSeaGreen4_71 = 71,
153 MediumTurquoise = 80,
170 MediumPurple3_97 = 97,
171 MediumPurple3_98 = 98,
176 LightSlateGrey = 103,
178 LightSlateBlue = 105,
180 DarkOliveGreen3_107 = 107,
182 LightSkyBlue3_109 = 109,
183 LightSkyBlue3_110 = 110,
185 Chartreuse2_112 = 112,
186 DarkOliveGreen3_113 = 113,
187 PaleGreen3_114 = 114,
188 DarkSeaGreen3_115 = 115,
189 DarkSlateGray3 = 116,
192 LightGreen_119 = 119,
193 LightGreen_120 = 120,
194 PaleGreen1_121 = 121,
195 Aquamarine1_122 = 122,
196 DarkSlateGray1 = 123,
199 MediumVioletRed = 126,
201 DarkViolet_128 = 128,
203 DarkOrange3_130 = 130,
208 MediumPurple2_135 = 135,
210 LightSalmon3_137 = 137,
213 MediumPurple2_140 = 140,
219 LightSteelBlue3 = 146,
220 LightSteelBlue = 147,
222 DarkOliveGreen3_149 = 149,
223 DarkSeaGreen3_150 = 150,
224 DarkSeaGreen2_151 = 151,
228 DarkOliveGreen2 = 155,
229 PaleGreen1_156 = 156,
230 DarkSeaGreen2_157 = 157,
231 DarkSeaGreen1_158 = 158,
232 PaleTurquoise1 = 159,
239 DarkOrange3_166 = 166,
244 MediumOrchid1_171 = 171,
246 LightSalmon3_173 = 173,
252 LightGoldenrod3 = 179,
259 LightGoldenrod2_186 = 186,
262 LightSteelBlue1 = 189,
264 DarkOliveGreen1_191 = 191,
265 DarkOliveGreen1_192 = 192,
266 DarkSeaGreen1_193 = 193,
276 IndianRed1_203 = 203,
277 IndianRed1_204 = 204,
280 MediumOrchid1_207 = 207,
284 PaleVioletRed1 = 211,
294 LightGoldenrod2_221 = 221,
295 LightGoldenrod2_222 = 222,
300 LightGoldenrod1 = 227,
338 static Color ansiColor(
int index);
345 static Color ansiColor(AnsiColor color) {
return ansiColor(
static_cast<int>(color)); }
359 static AnsiColor findClosestAnsiColor(
const Color &color,
int maxIndex = 255);
367 static bool stdoutWindowSize(
int &rows,
int &cols);
373 static bool stdoutSupportsANSI();
379 AnsiStream(IODevice *device) : _device(device), _enabled(true) {}
387 void setAnsiEnabled(
bool val) {
396 IODevice *device()
const {
return _device; }
403 AnsiStream &write(
const String &text);
410 AnsiStream &write(
const char *text);
417 AnsiStream &write(
char ch);
424 AnsiStream &write(
int val);
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); }
450 AnsiStream &setForeground(AnsiColor color);
462 AnsiStream &setBackground(AnsiColor color);
470 AnsiStream &setForeground(
const Color &color,
int maxIndex = 255);
478 AnsiStream &setBackground(
const Color &color,
int maxIndex = 255);
485 AnsiStream &cursorUp(
int n) {
486 if (!_enabled)
return *
this;
487 *
this <<
"\033[" << n <<
"A";
496 AnsiStream &cursorDown(
int n) {
497 if (!_enabled)
return *
this;
498 *
this <<
"\033[" << n <<
"B";
507 AnsiStream &cursorRight(
int n) {
508 if (!_enabled)
return *
this;
509 *
this <<
"\033[" << n <<
"C";
518 AnsiStream &cursorLeft(
int n) {
519 if (!_enabled)
return *
this;
520 *
this <<
"\033[" << n <<
"D";
530 AnsiStream &setCursorPosition(
int r,
int c) {
531 if (!_enabled)
return *
this;
532 *
this <<
"\033[" << r <<
";" << c <<
"H";
540 AnsiStream &clearScreen() {
541 if (!_enabled)
return *
this;
550 AnsiStream &moveToStartOfLine() {
551 if (!_enabled)
return *
this;
560 AnsiStream &moveToEndOfLine() {
561 if (!_enabled)
return *
this;
562 *
this <<
"\033[999G";
570 AnsiStream &clearLine() {
571 if (!_enabled)
return *
this;
580 AnsiStream &clearLineBeforeCursor() {
581 if (!_enabled)
return *
this;
590 AnsiStream &clearLineAfterCursor() {
591 if (!_enabled)
return *
this;
600 AnsiStream &reset() {
601 if (!_enabled)
return *
this;
610 AnsiStream &resetForeground() {
611 if (!_enabled)
return *
this;
620 AnsiStream &resetBackground() {
621 if (!_enabled)
return *
this;
630 AnsiStream &showCursor() {
631 if (!_enabled)
return *
this;
632 *
this <<
"\033[?25h";
640 AnsiStream &hideCursor() {
641 if (!_enabled)
return *
this;
642 *
this <<
"\033[?25l";
650 AnsiStream &saveCursorPosition() {
651 if (!_enabled)
return *
this;
661 AnsiStream &restoreCursorPosition() {
662 if (!_enabled)
return *
this;
673 AnsiStream &enableScrollingRegion(
int startRow,
int endRow) {
674 if (!_enabled)
return *
this;
675 *
this <<
"\033[" << startRow <<
";" << endRow <<
"r";
684 AnsiStream &scrollUp(
int n) {
685 if (!_enabled)
return *
this;
686 *
this <<
"\033[" << n <<
"S";
695 AnsiStream &scrollDown(
int n) {
696 if (!_enabled)
return *
this;
697 *
this <<
"\033[" << n <<
"T";
706 AnsiStream &eraseCharacters(
int n) {
707 if (!_enabled)
return *
this;
708 *
this <<
"\033[" << n <<
"X";
722 AnsiStream &setForeground256(uint8_t index) {
723 if (!_enabled)
return *
this;
724 *
this <<
"\033[38;5;" <<
static_cast<int>(index) <<
"m";
738 AnsiStream &setBackground256(uint8_t index) {
739 if (!_enabled)
return *
this;
740 *
this <<
"\033[48;5;" <<
static_cast<int>(index) <<
"m";
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";
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";
777 AnsiStream &setStrikethrough(
bool enable) {
778 if (!_enabled)
return *
this;
779 *
this <<
"\033[" << (enable ?
"9" :
"29") <<
"m";
787 AnsiStream &useAlternateScreenBuffer() {
788 if (!_enabled)
return *
this;
789 *
this <<
"\033[?1049h";
797 AnsiStream &useMainScreenBuffer() {
798 if (!_enabled)
return *
this;
799 *
this <<
"\033[?1049l";
810 bool getCursorPosition(IODevice *input,
int &row,
int &col);