SlHelpers
Loading...
Searching...
No Matches
Color.h
1// SPDX-License-Identifier: GPL-2.0-only
2
3#pragma once
4
5#include <iostream>
6#include <unistd.h>
7
8namespace SlHelpers {
18class Color {
19public:
21 enum C : unsigned {
22 BOLD = 1,
23 BLACK = 30,
24 RED = 31,
25 GREEN = 32,
26 YELLOW = 33,
27 BLUE = 34,
28 MAGENTA = 35,
29 CYAN = 36,
30 WHITE = 37,
31 COL256 = 38,
32 DEFAULT = 39,
33 };
34
36 enum Ctrl {
37 NoNL,
38 NL,
39 };
40
45 explicit Color(enum C c = DEFAULT) noexcept : Color(std::cout, c) {}
46
52 explicit Color(std::ostream &os, enum C c = DEFAULT) noexcept : m_NL(true), m_os(os) {
53 if (!doColor(os))
54 return;
55 auto origFlags = m_os.setf(std::ios::dec, std::ios::basefield);
56 m_os << seqBegin;
57 if (c != DEFAULT)
58 m_os << BOLD << ';';
59 m_os << c << 'm';
60 m_os.flags(origFlags);
61 }
62
69 Color(unsigned char r, unsigned char g, unsigned char b) noexcept
70 : Color(std::cout, r, g, b) {}
71
79 Color(std::ostream &os, unsigned char r, unsigned char g, unsigned char b) noexcept
80 : m_NL(true), m_os(os) {
81 if (!doColor(os))
82 return;
83 auto origFlags = m_os.setf(std::ios::dec, std::ios::basefield);
84 m_os << seqBegin << BOLD << ';' << COL256 << ";2;" <<
85 toUnsigned(r) << ';' <<
86 toUnsigned(g) << ';' <<
87 toUnsigned(b) << 'm';
88 m_os.flags(origFlags);
89 }
90
91 ~Color() {
92 if (doColor(m_os))
93 m_os << seqEnd;
94 if (m_NL)
95 m_os << '\n';
96 }
97
102 static void forceColor(bool force) { m_forceColor = force; }
107 static void forceColorValue(bool value) { m_forceColorValue = value; }
108
113 std::ostream &os() { return m_os; }
114
119 void ctrl(Ctrl ctrl) {
120 switch (ctrl) {
121 case NL:
122 case NoNL:
123 m_NL = ctrl == NL;
124 break;
125 }
126 }
127
128private:
129 template<typename T>
130 static unsigned toUnsigned(const T &val) { return val; }
131 static unsigned outIndex(const std::ostream &os) {
132 if (os.rdbuf() == std::cout.rdbuf())
133 return 0U;
134 if (os.rdbuf() == std::cerr.rdbuf())
135 return 1U;
136 return 2U;
137 }
138 static bool doColor(const std::ostream &os) {
139 if (m_forceColor)
140 return m_forceColorValue;
141 auto idx = outIndex(os);
142 if (m_doColor[idx] < 0)
143 m_doColor[idx] = isatty(idx + 1);
144 return m_doColor[idx];
145 }
146
147 friend void testColor();
148 inline static std::string_view seqBegin = "\033[";
149 inline static std::string_view seqEnd = "\033[0m";
150 inline static signed char m_doColor[] = { -1, -1, 1 };
151 inline static bool m_forceColor = false;
152 inline static bool m_forceColorValue = false;
153 bool m_NL;
154 std::ostream &m_os;
155};
156
157inline Color &&operator<<(Color &&os, const Color::Ctrl &ctrl)
158{
159 os.ctrl(ctrl);
160 return std::move(os);
161}
162
163template<typename T>
164Color &&operator<<(Color &&os, const T &x)
165{
166 os.os() << x;
167 return std::move(os);
168}
169
170}
Colorized output.
Definition Color.h:18
Color(std::ostream &os, enum C c=DEFAULT) noexcept
New Color stream (into os) using color c.
Definition Color.h:52
Color(enum C c=DEFAULT) noexcept
New Color stream (stdout) using color c.
Definition Color.h:45
Ctrl
Controls for Color.
Definition Color.h:36
static void forceColor(bool force)
Force color value (see forceColorValue()).
Definition Color.h:102
void ctrl(Ctrl ctrl)
Controls the stream behavior.
Definition Color.h:119
Color(unsigned char r, unsigned char g, unsigned char b) noexcept
New Color stream (stdout) using an RGB color.
Definition Color.h:69
static void forceColorValue(bool value)
If forceColor(true) was called, use of colors is bound to value.
Definition Color.h:107
C
Predefined colors.
Definition Color.h:21
std::ostream & os()
Return current output stream.
Definition Color.h:113
Color(std::ostream &os, unsigned char r, unsigned char g, unsigned char b) noexcept
New Color stream (into os) using an RGB color.
Definition Color.h:79