-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTextModifier.mpp
More file actions
110 lines (96 loc) · 3.41 KB
/
TextModifier.mpp
File metadata and controls
110 lines (96 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module;
#include <CppUtils/System/Windows.hpp>
export module CppUtils.Terminal.TextModifier;
import std;
import CppUtils.Terminal.BackgroundColor;
import CppUtils.Terminal.Utility;
import CppUtils.Terminal.TextColor;
import CppUtils.Terminal.TextStyle;
import CppUtils.Terminal.Handle;
export namespace CppUtils::Terminal
{
using namespace std::literals;
namespace Ansi::EscapeCode
{
[[maybe_unused]] inline constexpr auto Reset = "\x1B[0m"sv; // \x1B[39m\x1B[49m
[[maybe_unused]] inline constexpr auto EraseCurrentLine = "\x1B[2K\r"sv;
[[maybe_unused]] inline constexpr auto MoveCursorUp = "\x1B[1A"sv;
[[maybe_unused]] inline constexpr auto GetCursorPosition = "\x1B[6n"sv;
[[maybe_unused]] inline constexpr auto SetCursorPosition = "\x1B[{};{}H"sv;
[[maybe_unused]] inline constexpr auto SetTitle = "\x1B]0;{}\a"sv;
}
class TextModifier final
{
public:
TextModifier() = default;
inline explicit TextModifier(
std::FILE* file,
TextColor::TextColorEnum textColor = TextColor::TextColorEnum::Default,
BackgroundColor::BackgroundColorEnum backgroundColor = BackgroundColor::BackgroundColorEnum::Default,
[[maybe_unused]] std::optional<TextStyle::TextStyleEnum> textStyle = std::nullopt):
m_modify{true},
m_file{file}
{
#if defined(OS_WINDOWS)
m_attributes = getTextColor(m_file);
SetConsoleTextAttribute(getTerminalHandle(m_file), static_cast<std::uint16_t>((BackgroundColor::WindowsNative::getBackgroundColorCode(backgroundColor) << 4) + TextColor::WindowsNative::getTextColorCode(textColor)));
#elif defined(OS_LINUX) or defined(OS_MACOS)
auto text = TextColor::Ansi::getTextColorCode(textColor);
auto background = BackgroundColor::Ansi::getBackgroundColorCode(backgroundColor);
std::print(m_file, "{}{}", text, background);
if (textStyle)
std::print(m_file, "{}", TextStyle::getTextStyleCode(*textStyle));
#endif
}
TextModifier(TextModifier&& other) noexcept = default;
TextModifier& operator=(TextModifier&& other) noexcept = default;
inline ~TextModifier()
{
if (not m_modify)
return;
#if defined(OS_WINDOWS)
SetConsoleTextAttribute(getTerminalHandle(m_file), m_attributes);
#elif defined(OS_LINUX) or defined(OS_MACOS)
std::print(m_file, "{}", Ansi::EscapeCode::Reset);
#endif
}
#if defined(OS_WINDOWS)
[[nodiscard]] inline static auto getTextColor(std::FILE* file) -> std::uint16_t
{
CONSOLE_SCREEN_BUFFER_INFO info;
if (not GetConsoleScreenBufferInfo(getTerminalHandle(file), std::addressof(info)))
return 0;
return info.wAttributes;
}
[[nodiscard]] static inline auto getTextColor(std::ostream& stream) -> std::uint16_t
{
CONSOLE_SCREEN_BUFFER_INFO info;
if (not GetConsoleScreenBufferInfo(getTerminalHandle(stream), std::addressof(info)))
return 0;
return info.wAttributes;
}
#endif
static inline auto eraseCurrentLine(std::FILE* file) -> void
{
std::fwrite(
std::data(Ansi::EscapeCode::EraseCurrentLine),
sizeof(decltype(Ansi::EscapeCode::EraseCurrentLine)::value_type),
std::size(Ansi::EscapeCode::EraseCurrentLine),
file);
}
static inline auto moveCursorUp(std::FILE* file) -> void
{
std::fwrite(
std::data(Ansi::EscapeCode::MoveCursorUp),
sizeof(decltype(Ansi::EscapeCode::MoveCursorUp)::value_type),
std::size(Ansi::EscapeCode::MoveCursorUp),
file);
}
private:
bool m_modify = false;
std::FILE* m_file = nullptr;
#if defined(OS_WINDOWS)
std::uint16_t m_attributes;
#endif
};
}