7#include <initializer_list>
14#define WIN32_LEAN_AND_MEAN
30bool g_color_support_detected =
false;
31Terminal::Quirks g_quirks = [] {
32 Terminal::Quirks quirks;
34 quirks.SetBlockCharacters(
false);
35 quirks.SetCursorHiding(
false);
36 quirks.SetComponentAscii(
true);
41Dimensions& FallbackSize() {
42#if defined(__EMSCRIPTEN__)
47 constexpr int fallback_width = 140;
48 constexpr int fallback_height = 43;
53 constexpr int fallback_width = 80;
54 constexpr int fallback_height = 24;
56 static Dimensions g_fallback_size{
60 return g_fallback_size;
63const char* Safe(
const char* c) {
64 return (c !=
nullptr) ? c :
"";
67bool Contains(std::string_view s, std::string_view key) {
71 const auto it = std::search(
72 s.begin(), s.end(), key.begin(), key.end(), [](
char a,
char b) {
73 return std::tolower(static_cast<unsigned char>(a)) ==
74 std::tolower(static_cast<unsigned char>(b));
79bool ContainsAny(std::string_view s,
80 std::initializer_list<std::string_view> keys) {
81 for (
const std::string_view key : keys) {
82 if (Contains(s, key)) {
90 static const std::vector<int> empty_capabilities;
92 Safe(std::getenv(
"TERM")),
93 Safe(std::getenv(
"COLORTERM")),
94 Safe(std::getenv(
"TERM_PROGRAM")),
95 "unknown",
"unknown", empty_capabilities);
103 bool block_characters =
true;
104 bool cursor_hiding =
true;
105 bool component_ascii =
false;
109Quirks::Quirks() : impl_(std::make_unique<Impl>()) {}
110Quirks::~Quirks() =
default;
111Quirks::Quirks(
const Quirks& other) : impl_(std::make_unique<Impl>(*other.impl_)) {}
112Quirks& Quirks::operator=(
const Quirks& other) {
113 if (
this != &other) {
114 *impl_ = *other.impl_;
118Quirks::Quirks(Quirks&&) noexcept = default;
119Quirks& Quirks::operator=(Quirks&&) noexcept = default;
121bool Quirks::BlockCharacters()
const {
122 return impl_->block_characters;
124void Quirks::SetBlockCharacters(
bool v) {
125 impl_->block_characters = v;
128bool Quirks::CursorHiding()
const {
129 return impl_->cursor_hiding;
131void Quirks::SetCursorHiding(
bool v) {
132 impl_->cursor_hiding = v;
135bool Quirks::ComponentAscii()
const {
136 return impl_->component_ascii;
138void Quirks::SetComponentAscii(
bool v) {
139 impl_->component_ascii = v;
142Color Quirks::ColorSupport()
const {
143 return impl_->color_support;
145void Quirks::SetColorSupport(Color v) {
146 impl_->color_support = v;
149struct TerminalInfo::Impl {
151 std::string colorterm;
152 std::string term_program;
153 std::string terminal_name;
154 std::string terminal_emulator_name;
155 std::vector<int> capabilities;
158TerminalInfo::TerminalInfo() : impl_(std::make_unique<Impl>()) {}
159TerminalInfo::~TerminalInfo() =
default;
160TerminalInfo::TerminalInfo(TerminalInfo&&) noexcept = default;
161TerminalInfo& TerminalInfo::operator=(TerminalInfo&&) noexcept = default;
163void TerminalInfo::SetTerm(std::string_view term) {
166void TerminalInfo::SetColorterm(std::string_view colorterm) {
167 impl_->colorterm = colorterm;
169void TerminalInfo::SetTermProgram(std::string_view term_program) {
170 impl_->term_program = term_program;
172void TerminalInfo::SetTerminalName(std::string_view terminal_name) {
173 impl_->terminal_name = terminal_name;
175void TerminalInfo::SetTerminalEmulatorName(
176 std::string_view terminal_emulator_name) {
177 impl_->terminal_emulator_name = terminal_emulator_name;
179void TerminalInfo::SetCapabilities(std::vector<int> capabilities) {
180 impl_->capabilities = std::move(capabilities);
192 std::string_view colorterm,
193 std::string_view term_program,
194 std::string_view terminal_name,
195 std::string_view terminal_emulator_name,
196 const std::vector<int>& capabilities) {
199 info.SetColorterm(colorterm);
200 info.SetTermProgram(term_program);
201 info.SetTerminalName(terminal_name);
202 info.SetTerminalEmulatorName(terminal_emulator_name);
203 info.SetCapabilities(capabilities);
204 return info.ComputeColorSupport();
207Color TerminalInfo::ComputeColorSupport()
const {
209#if defined(__EMSCRIPTEN__)
210 return Terminal::Color::TrueColor;
214 if (ContainsAny(impl_->colorterm, {
"24bit",
"truecolor"})) {
215 return Terminal::Color::TrueColor;
217 if (ContainsAny(impl_->term,
218 {
"direct",
"truecolor",
"kitty",
"alacritty",
"foot"})) {
219 return Terminal::Color::TrueColor;
221 if (ContainsAny(impl_->colorterm, {
"256"}) ||
222 ContainsAny(impl_->term, {
"256",
"xterm",
"screen",
"tmux"})) {
223 return Terminal::Color::Palette256;
227 if (ContainsAny(impl_->term_program, {
235 return Terminal::Color::TrueColor;
237 if (Contains(impl_->term_program,
"iterm")) {
238 return Terminal::Color::Palette256;
242 if (impl_->terminal_emulator_name !=
"unknown") {
243 return Terminal::Color::TrueColor;
245 if (impl_->terminal_name ==
"xterm") {
246 return Terminal::Color::TrueColor;
248 for (
const int x : impl_->capabilities) {
254 return Terminal::Color::Palette256;
258 return Terminal::Color::Palette16;
265#if defined(__EMSCRIPTEN__)
270 return FallbackSize();
272 CONSOLE_SCREEN_BUFFER_INFO csbi;
274 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
275 return Dimensions{csbi.srWindow.Right - csbi.srWindow.Left + 1,
276 csbi.srWindow.Bottom - csbi.srWindow.Top + 1};
279 return FallbackSize();
282 const int status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
285 if (w.ws_col == 0 || w.ws_row == 0 || status < 0) {
286 return FallbackSize();
288 return Dimensions{w.ws_col, w.ws_row};
294void SetFallbackSize(
const Dimensions& fallbackSize) {
295 FallbackSize() = fallbackSize;
301 if (!g_color_support_detected) {
302 g_quirks.SetColorSupport(ComputeColorSupportInternal());
303 g_color_support_detected =
true;
305 return g_quirks.ColorSupport();
311 g_quirks.SetColorSupport(color);
312 g_color_support_detected =
true;
318 if (!g_color_support_detected) {
319 g_quirks.SetColorSupport(ComputeColorSupportInternal());
320 g_color_support_detected =
true;
327void SetQuirks(
const Quirks& quirks) {
329 g_color_support_detected =
true;
Color
Color is an enumeration that represents the color support of the terminal.
The FTXUI ftxui::Terminal:: namespace.
Color ComputeColorSupport(std::string_view term, std::string_view colorterm, std::string_view term_program, std::string_view terminal_name, std::string_view terminal_emulator_name, const std::vector< int > &capabilities)
Compute the color support based on environment variables and terminal identification.
The FTXUI ftxui:: namespace.