-
-
Notifications
You must be signed in to change notification settings - Fork 579
Expand file tree
/
Copy pathterminal.cpp
More file actions
159 lines (135 loc) · 4.45 KB
/
terminal.cpp
File metadata and controls
159 lines (135 loc) · 4.45 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#include <cstdlib> // for getenv
#include <string> // for string, allocator
#include "ftxui/screen/terminal.hpp"
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#else
#include <sys/ioctl.h> // for winsize, ioctl, TIOCGWINSZ
#include <unistd.h> // for STDOUT_FILENO
#endif
namespace ftxui {
namespace {
bool g_cached = false; // NOLINT
Terminal::Color g_cached_supported_color; // NOLINT
Dimensions& FallbackSize() {
#if defined(__EMSCRIPTEN__)
// This dimension was chosen arbitrarily to be able to display:
// https://arthursonzogni.com/FTXUI/examples
// This will have to be improved when someone has time to implement and need
// it.
constexpr int fallback_width = 140;
constexpr int fallback_height = 43;
#else
// The terminal size in VT100 was 80x24. It is still used nowadays by
// default in many terminal emulator. That's a good choice for a fallback
// value.
constexpr int fallback_width = 80;
constexpr int fallback_height = 24;
#endif
static Dimensions g_fallback_size{
fallback_width,
fallback_height,
};
return g_fallback_size;
}
bool Contains(const std::string& s, const char* key) {
return s.find(key) != std::string::npos;
}
// https://github.com/gabime/spdlog/blob/885b5473e291833b148eeac3b7ce227e582cd88b/include/spdlog/details/os-inl.h#L566
std::string getenv_safe(const char *field) {
#if defined(_MSC_VER)
#if defined(__cplusplus_winrt)
return std::string{}; // not supported under uwp
#else
size_t len = 0;
char buf[1024];
bool ok = ::getenv_s(&len, buf, sizeof(buf), field) == 0;
return ok ? buf : std::string{};
#endif
#else // revert to getenv
char *buf = ::getenv(field); // NOLINT(*-mt-unsafe)
return buf ? buf : std::string{};
#endif
}
Terminal::Color ComputeColorSupport() {
#if defined(__EMSCRIPTEN__)
return Terminal::Color::TrueColor;
#endif
std::string COLORTERM = getenv_safe("COLORTERM");
if (Contains(COLORTERM, "24bit") || Contains(COLORTERM, "truecolor")) {
return Terminal::Color::TrueColor;
}
std::string TERM = getenv_safe("TERM");
if (Contains(COLORTERM, "256") || Contains(TERM, "256")) {
return Terminal::Color::Palette256;
}
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminals do not properly declare themselve supporting true
// colors: https://github.com/microsoft/terminal/issues/1040
// As a fallback, assume microsoft terminal are the ones not setting those
// variables, and enable true colors.
if (TERM.empty() && COLORTERM.empty()) {
return Terminal::Color::TrueColor;
}
#endif
return Terminal::Color::Palette16;
}
} // namespace
namespace Terminal {
/// @brief Get the terminal size.
/// @return The terminal size.
/// @ingroup screen
Dimensions Size() {
#if defined(__EMSCRIPTEN__)
// This dimension was chosen arbitrarily to be able to display:
// https://arthursonzogni.com/FTXUI/examples
// This will have to be improved when someone has time to implement and need
// it.
return FallbackSize();
#elif defined(_WIN32)
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
return Dimensions{csbi.srWindow.Right - csbi.srWindow.Left + 1,
csbi.srWindow.Bottom - csbi.srWindow.Top + 1};
}
return FallbackSize();
#else
winsize w{};
const int status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); // NOLINT
// The ioctl return value result should be checked. Some operating systems
// don't support TIOCGWINSZ.
if (w.ws_col == 0 || w.ws_row == 0 || status < 0) {
return FallbackSize();
}
return Dimensions{w.ws_col, w.ws_row};
#endif
}
/// @brief Override terminal size in case auto-detection fails
/// @param fallbackSize Terminal dimensions to fallback to
void SetFallbackSize(const Dimensions& fallbackSize) {
FallbackSize() = fallbackSize;
}
/// @brief Get the color support of the terminal.
/// @ingroup screen
Color ColorSupport() {
if (!g_cached) {
g_cached = true;
g_cached_supported_color = ComputeColorSupport();
}
return g_cached_supported_color;
}
/// @brief Override terminal color support in case auto-detection fails
/// @ingroup dom
void SetColorSupport(Color color) {
g_cached = true;
g_cached_supported_color = color;
}
} // namespace Terminal
} // namespace ftxui