7#include <initializer_list>
14#define WIN32_LEAN_AND_MEAN
25#if defined(__sun) || defined(__illumos__)
26#include <sys/termios.h>
33bool g_color_support_detected =
false;
34Terminal::Quirks g_quirks = [] {
35 Terminal::Quirks quirks;
37 quirks.SetBlockCharacters(
false);
38 quirks.SetCursorHiding(
false);
39 quirks.SetComponentAscii(
true);
44Dimensions& FallbackSize() {
45#if defined(__EMSCRIPTEN__)
50 constexpr int fallback_width = 140;
51 constexpr int fallback_height = 43;
56 constexpr int fallback_width = 80;
57 constexpr int fallback_height = 24;
59 static Dimensions g_fallback_size{
63 return g_fallback_size;
66const char* Safe(
const char* c) {
67 return (c !=
nullptr) ? c :
"";
70bool Contains(std::string_view s, std::string_view key) {
74 const auto it = std::search(
75 s.begin(), s.end(), key.begin(), key.end(), [](
char a,
char b) {
76 return std::tolower(static_cast<unsigned char>(a)) ==
77 std::tolower(static_cast<unsigned char>(b));
82bool ContainsAny(std::string_view s,
83 std::initializer_list<std::string_view> keys) {
84 for (
const std::string_view key : keys) {
85 if (Contains(s, key)) {
93 static const std::vector<int> empty_capabilities;
95 Safe(std::getenv(
"TERM")),
96 Safe(std::getenv(
"COLORTERM")),
97 Safe(std::getenv(
"TERM_PROGRAM")),
98 "unknown",
"unknown", empty_capabilities);
106 bool block_characters =
true;
107 bool cursor_hiding =
true;
108 bool component_ascii =
false;
112Quirks::Quirks() : impl_(std::make_unique<Impl>()) {}
113Quirks::~Quirks() =
default;
114Quirks::Quirks(
const Quirks& other)
115 : impl_(std::make_unique<Impl>(*other.impl_)) {}
116Quirks& Quirks::operator=(
const Quirks& other) {
117 if (
this != &other) {
118 *impl_ = *other.impl_;
122Quirks::Quirks(Quirks&&) noexcept = default;
123Quirks& Quirks::operator=(Quirks&&) noexcept = default;
125bool Quirks::BlockCharacters()
const {
126 return impl_->block_characters;
128void Quirks::SetBlockCharacters(
bool v) {
129 impl_->block_characters = v;
132bool Quirks::CursorHiding()
const {
133 return impl_->cursor_hiding;
135void Quirks::SetCursorHiding(
bool v) {
136 impl_->cursor_hiding = v;
139bool Quirks::ComponentAscii()
const {
140 return impl_->component_ascii;
142void Quirks::SetComponentAscii(
bool v) {
143 impl_->component_ascii = v;
146Color Quirks::ColorSupport()
const {
147 return impl_->color_support;
149void Quirks::SetColorSupport(Color v) {
150 impl_->color_support = v;
153struct TerminalInfo::Impl {
155 std::string colorterm;
156 std::string term_program;
157 std::string terminal_name;
158 std::string terminal_emulator_name;
159 std::vector<int> capabilities;
162TerminalInfo::TerminalInfo() : impl_(std::make_unique<Impl>()) {}
163TerminalInfo::~TerminalInfo() =
default;
164TerminalInfo::TerminalInfo(TerminalInfo&&) noexcept = default;
165TerminalInfo& TerminalInfo::operator=(TerminalInfo&&) noexcept = default;
167void TerminalInfo::SetTerm(std::string_view term) {
170void TerminalInfo::SetColorterm(std::string_view colorterm) {
171 impl_->colorterm = colorterm;
173void TerminalInfo::SetTermProgram(std::string_view term_program) {
174 impl_->term_program = term_program;
176void TerminalInfo::SetTerminalName(std::string_view terminal_name) {
177 impl_->terminal_name = terminal_name;
179void TerminalInfo::SetTerminalEmulatorName(
180 std::string_view terminal_emulator_name) {
181 impl_->terminal_emulator_name = terminal_emulator_name;
183void TerminalInfo::SetCapabilities(std::vector<int> capabilities) {
184 impl_->capabilities = std::move(capabilities);
196 std::string_view colorterm,
197 std::string_view term_program,
198 std::string_view terminal_name,
199 std::string_view terminal_emulator_name,
200 const std::vector<int>& capabilities) {
203 info.SetColorterm(colorterm);
204 info.SetTermProgram(term_program);
205 info.SetTerminalName(terminal_name);
206 info.SetTerminalEmulatorName(terminal_emulator_name);
207 info.SetCapabilities(capabilities);
208 return info.ComputeColorSupport();
211Color TerminalInfo::ComputeColorSupport()
const {
213#if defined(__EMSCRIPTEN__)
214 return Terminal::Color::TrueColor;
218 if (ContainsAny(impl_->colorterm, {
"24bit",
"truecolor"})) {
219 return Terminal::Color::TrueColor;
221 if (ContainsAny(impl_->term,
222 {
"direct",
"truecolor",
"kitty",
"alacritty",
"foot"})) {
223 return Terminal::Color::TrueColor;
225 if (ContainsAny(impl_->colorterm, {
"256"}) ||
226 ContainsAny(impl_->term, {
"256",
"xterm",
"screen",
"tmux"})) {
227 return Terminal::Color::Palette256;
231 if (ContainsAny(impl_->term_program, {
239 return Terminal::Color::TrueColor;
241 if (Contains(impl_->term_program,
"iterm")) {
242 return Terminal::Color::Palette256;
246 if (impl_->terminal_emulator_name !=
"unknown") {
247 return Terminal::Color::TrueColor;
249 if (impl_->terminal_name ==
"xterm") {
250 return Terminal::Color::TrueColor;
252 for (
const int x : impl_->capabilities) {
258 return Terminal::Color::Palette256;
262 return Terminal::Color::Palette16;
269#if defined(__EMSCRIPTEN__)
274 return FallbackSize();
276 CONSOLE_SCREEN_BUFFER_INFO csbi;
278 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
279 return Dimensions{csbi.srWindow.Right - csbi.srWindow.Left + 1,
280 csbi.srWindow.Bottom - csbi.srWindow.Top + 1};
283 return FallbackSize();
286 const int status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
289 if (w.ws_col == 0 || w.ws_row == 0 || status < 0) {
290 return FallbackSize();
292 return Dimensions{w.ws_col, w.ws_row};
298void SetFallbackSize(
const Dimensions& fallbackSize) {
299 FallbackSize() = fallbackSize;
305 if (!g_color_support_detected) {
306 g_quirks.SetColorSupport(ComputeColorSupportInternal());
307 g_color_support_detected =
true;
309 return g_quirks.ColorSupport();
315 g_quirks.SetColorSupport(color);
316 g_color_support_detected =
true;
322 if (!g_color_support_detected) {
323 g_quirks.SetColorSupport(ComputeColorSupportInternal());
324 g_color_support_detected =
true;
331void SetQuirks(
const Quirks& quirks) {
333 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.