-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRawTerminal.mpp
More file actions
88 lines (74 loc) · 1.91 KB
/
RawTerminal.mpp
File metadata and controls
88 lines (74 loc) · 1.91 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
module;
#include <CppUtils/System/Windows.hpp>
#if defined(OS_LINUX) or defined(OS_MACOS)
# include <unistd.h>
# include <termios.h>
# include <poll.h>
#endif
export module CppUtils.Terminal.RawTerminal;
import std;
export namespace CppUtils::Terminal
{
#if defined(OS_LINUX) or defined(OS_MACOS)
class RawTerminal final
{
public:
inline RawTerminal()
{
if (tcgetattr(STDIN_FILENO, std::addressof(m_oldTerminalState)))
return;
m_initialized = true;
auto rawTerminal = m_oldTerminalState;
rawTerminal.c_lflag &= static_cast<tcflag_t>(~(ICANON | ECHO));
tcsetattr(STDIN_FILENO, TCSANOW, std::addressof(rawTerminal));
}
RawTerminal(const RawTerminal&) = delete;
RawTerminal(RawTerminal&& other) noexcept:
m_oldTerminalState{other.m_oldTerminalState},
m_initialized{std::exchange(other.m_initialized, false)}
{}
RawTerminal& operator=(const RawTerminal&) = delete;
RawTerminal& operator=(RawTerminal&& rhs) noexcept
{
if (this != std::addressof(rhs))
{
m_oldTerminalState = rhs.m_oldTerminalState;
m_initialized = std::exchange(rhs.m_initialized, false);
}
return *this;
}
inline ~RawTerminal()
{
if (m_initialized)
tcsetattr(STDIN_FILENO, TCSANOW, std::addressof(m_oldTerminalState));
}
[[nodiscard]] static inline auto isInputAvailable() -> bool
{
auto pfd = pollfd{STDIN_FILENO, POLLIN, 0};
return ::poll(std::addressof(pfd), 1, 0) > 0;
}
[[nodiscard]] inline auto readChar() const -> char
{
auto c = char{};
if (::read(STDIN_FILENO, std::addressof(c), 1) == 1)
return c;
return '\0';
}
[[nodiscard]] inline auto read(char sentinel) const -> std::string
{
using namespace std::literals;
auto string = ""s;
auto c = readChar();
while (c != '\0' and c != sentinel)
{
string += c;
c = readChar();
}
return string;
}
private:
termios m_oldTerminalState;
bool m_initialized = false;
};
#endif
}