libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
styler.hpp
1 #pragma once
2 
3 #include "fly/concepts/concepts.hpp"
4 #include "fly/fly.hpp"
5 #include "fly/logger/detail/styler_proxy.hpp"
6 #include "fly/types/numeric/literals.hpp"
7 
8 #include <cstdint>
9 #include <memory>
10 #include <ostream>
11 #include <stack>
12 #include <utility>
13 
14 namespace fly::logger {
15 
22 enum class Style : std::uint8_t
23 {
24  Default,
25  Blink,
26  Bold,
27  Dim,
28  Italic,
29  Strike,
30  Underline,
31 };
32 
36 struct Color
37 {
50  {
51  Black,
52  Red,
53  Green,
54  Yellow,
55  Blue,
56  Magenta,
57  Cyan,
58  White,
59  };
60 
64  enum Plane
65  {
66  Foreground,
67  Background,
68  };
69 
76  explicit constexpr Color(std::uint8_t color, Plane plane = Foreground) noexcept :
77  m_color(color),
78  m_plane(plane)
79  {
80  }
81 
82  const std::uint8_t m_color;
83  const Plane m_plane;
84 };
85 
89 struct Cursor
90 {
94  enum Direction
95  {
96  Up,
97  Down,
98  Forward,
99  Backward,
100  };
101 
108  constexpr Cursor(Direction direction, std::uint8_t distance = 1) noexcept :
109  m_direction(direction),
110  m_distance(distance > 0 ? distance : 1)
111  {
112  }
113 
114  const Direction m_direction;
115  const std::uint8_t m_distance;
116 };
117 
121 template <typename T>
122 concept Modifier = fly::SameAsAny<T, Style, Color, Color::StandardColor, Cursor, Cursor::Direction>;
123 
159 class Styler
160 {
161 public:
171  template <Modifier ModifierType>
172  explicit Styler(ModifierType &&modifier) noexcept
173  {
174  set_modifier(modifier);
175  }
176 
192  template <Modifier ModifierType, Modifier... ModifierTypes>
193  Styler(ModifierType &&modifier, ModifierTypes &&...modifiers) noexcept :
194  Styler(std::forward<ModifierTypes>(modifiers)...)
195  {
196  set_modifier(modifier);
197  }
198 
209  friend detail::StylerProxy &operator<<(std::ostream &stream, const Styler &styler);
210 
211 private:
221  template <Modifier ModifierType>
222  void set_modifier(ModifierType &&modifier)
223  {
224  if constexpr (fly::SameAs<ModifierType, Style>)
225  {
226  m_styles.emplace(std::move(modifier));
227  }
228  else if constexpr (fly::SameAsAny<ModifierType, Color, Color::StandardColor>)
229  {
230  m_colors.emplace(std::move(modifier));
231  }
232  else if constexpr (fly::SameAsAny<ModifierType, Cursor, Cursor::Direction>)
233  {
234  m_cursors.emplace(std::move(modifier));
235  }
236  }
237 
238  // Store modifier instances in a stack because the variadic constructor processes parameters
239  // from right-to-left (due to the delegating constructor invocation).
240  std::stack<Style> m_styles;
241  std::stack<Color> m_colors;
242  std::stack<Cursor> m_cursors;
243 
244  std::unique_ptr<detail::StylerProxy> m_proxy;
245 };
246 
247 } // namespace fly::logger
248 
249 namespace fly {
250 inline namespace literals {
251  inline namespace styler_literals {
252 
261  template <char... Literals>
262  FLY_CONSTEVAL inline fly::logger::Color operator"" _c()
263  {
264  // Convert to std::uint8_t via numeric literal to ensure the provided color is valid.
265  const std::uint8_t validated_color = operator"" _u8<Literals...>();
266  return fly::logger::Color(validated_color);
267  }
268 
269  } // namespace styler_literals
270 } // namespace literals
271 } // namespace fly
Definition: styler.hpp:160
Styler(ModifierType &&modifier, ModifierTypes &&...modifiers) noexcept
Definition: styler.hpp:193
friend detail::StylerProxy & operator<<(std::ostream &stream, const Styler &styler)
Definition: styler.cpp:13
Styler(ModifierType &&modifier) noexcept
Definition: styler.hpp:172
Definition: styler_proxy.hpp:16
Definition: styler.hpp:37
Plane
Definition: styler.hpp:65
StandardColor
Definition: styler.hpp:50
constexpr Color(std::uint8_t color, Plane plane=Foreground) noexcept
Definition: styler.hpp:76
Definition: styler.hpp:90
Direction
Definition: styler.hpp:95
constexpr Cursor(Direction direction, std::uint8_t distance=1) noexcept
Definition: styler.hpp:108