SlHelpers
Color.h
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #pragma once
4 
5 #include <iostream>
6 #include <unistd.h>
7 
8 namespace SlHelpers {
18 class Color {
19 public:
21  enum C : unsigned {
22  BLACK = 30,
23  RED = 31,
24  GREEN = 32,
25  YELLOW = 33,
26  BLUE = 34,
27  MAGENTA = 35,
28  CYAN = 36,
29  WHITE = 37,
30  COL256 = 38,
31  DEFAULT = 39,
32  };
33 
35  enum Ctrl {
36  NoNL,
37  NL,
38  };
39 
44  explicit Color(enum C c = DEFAULT) noexcept : Color(std::cout, c) {}
45 
51  explicit Color(std::ostream &os, enum C c = DEFAULT) noexcept : m_NL(true), m_os(os) {
52  if (doColor(os))
53  m_os << seqBegin << c << 'm';
54  }
55 
62  Color(unsigned char r, unsigned char g, unsigned char b) noexcept
63  : Color(std::cout, r, g, b) {}
64 
72  Color(std::ostream &os, unsigned char r, unsigned char g, unsigned char b) noexcept
73  : m_NL(true), m_os(os) {
74  if (!doColor(os))
75  return;
76  m_os << seqBegin << COL256 << ";2;" <<
77  toUnsigned(r) << ';' <<
78  toUnsigned(g) << ';' <<
79  toUnsigned(b) << 'm';
80  }
81 
82  ~Color() {
83  if (doColor(m_os))
84  m_os << seqEnd;
85  if (m_NL)
86  m_os << '\n';
87  }
88 
93  static void forceColor(bool force) { m_forceColor = force; }
98  static void forceColorValue(bool value) { m_forceColorValue = value; }
99 
104  std::ostream &os() { return m_os; }
105 
110  void ctrl(Ctrl ctrl) {
111  switch (ctrl) {
112  case NL:
113  case NoNL:
114  m_NL = ctrl == NL;
115  break;
116  }
117  }
118 
119 private:
120  template<typename T>
121  static unsigned toUnsigned(const T &val) { return val; }
122  static unsigned outIndex(const std::ostream &os) {
123  if (os.rdbuf() == std::cout.rdbuf())
124  return 0U;
125  if (os.rdbuf() == std::cerr.rdbuf())
126  return 1U;
127  return 2U;
128  }
129  static bool doColor(const std::ostream &os) {
130  if (m_forceColor)
131  return m_forceColorValue;
132  auto idx = outIndex(os);
133  if (m_doColor[idx] < 0)
134  m_doColor[idx] = isatty(idx + 1);
135  return m_doColor[idx];
136  }
137 
138  friend void testColor();
139  inline static std::string_view seqBegin = "\033[01;";
140  inline static std::string_view seqEnd = "\033[0m";
141  inline static signed char m_doColor[] = { -1, -1, 1 };
142  inline static bool m_forceColor = false;
143  inline static bool m_forceColorValue = false;
144  bool m_NL;
145  std::ostream &m_os;
146 };
147 
148 inline Color &&operator<<(Color &&os, const Color::Ctrl &ctrl)
149 {
150  os.ctrl(ctrl);
151  return std::move(os);
152 }
153 
154 template<typename T>
155 Color &&operator<<(Color &&os, const T &x)
156 {
157  os.os() << x;
158  return std::move(os);
159 }
160 
161 }
std::ostream & os()
Return current output stream.
Definition: Color.h:104
Color(std::ostream &os, enum C c=DEFAULT) noexcept
New Color stream (into os) using color c.
Definition: Color.h:51
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:72
static void forceColorValue(bool value)
If forceColor(true) was called, use of colors is bound to value.
Definition: Color.h:98
C
Predefined colors.
Definition: Color.h:21
Color(unsigned char r, unsigned char g, unsigned char b) noexcept
New Color stream (stdout) using an RGB color.
Definition: Color.h:62
static void forceColor(bool force)
Force color value (see forceColorValue())
Definition: Color.h:93
Colorized output.
Definition: Color.h:18
Ctrl
Controls for Color.
Definition: Color.h:35
void ctrl(Ctrl ctrl)
Controls the stream behavior.
Definition: Color.h:110
Color(enum C c=DEFAULT) noexcept
New Color stream (stdout) using color c.
Definition: Color.h:44
Definition: Color.h:8